1// This file is based on the Go implementation found here:
2// https://cs.opensource.google/go/go/+/refs/tags/go1.23.2:src/io/io.go
3// which has the copyright notice:
4// copyright 2009 The Go Authors. All rights reserved.
5// Use of this source code is governed by a BSD-style
6// license that can be found in the LICENSE file.
7
8/// Package io provides basic interfaces to I/O primitives.
9/// Its primary job is to wrap existing implementations of such primitives,
10/// such as those in package os, into shared public interfaces that
11/// abstract the functionality, plus some other related primitives.
12///
13/// Because these interfaces and primitives wrap lower-level operations with
14/// various implementations, unless otherwise informed clients should not
15/// assume they are safe for parallel execution.
16
17///|
18/// Seek whence values.
19pub(all) enum Whence {
20  /// seek relative to the origin of the file
21  
Whence

seek relative to the origin of the file

SeekStart
22 /// seek relative to the current offset 23
Whence

seek relative to the current offset

SeekCurrent
24 /// seek relative to the end 25
Whence

seek relative to the end

SeekEnd
26} 27 28///| 29/// An IOError can be tested with equality checks. 30pub(all) type! IOError
String
String
derive(
(IOError, &Logger) -> Unit

Trait for types that can be converted to String

Show
,
(IOError, IOError) -> Bool

Trait for types whose elements can test for equality

Eq
)
31 32///| 33/// err_short_write means that a write accepted fewer bytes than requested 34/// but failed to return an explicit error. 35pub let
IOError

err_short_write means that a write accepted fewer bytes than requested but failed to return an explicit error.

err_short_write
:
type! IOError String

An IOError can be tested with equality checks.

IOError
=
(String) -> IOError

An IOError can be tested with equality checks.

IOError
("short write")
36 37///| 38/// err_invalid_write means that a write returned an impossible count. 39pub let
IOError

err_invalid_write means that a write returned an impossible count.

err_invalid_write
:
type! IOError String

An IOError can be tested with equality checks.

IOError
=
(String) -> IOError

An IOError can be tested with equality checks.

IOError
("invalid write result")
40 41///| 42/// err_short_buffer means that a read required a longer buffer than was provided. 43pub let
IOError

err_short_buffer means that a read required a longer buffer than was provided.

err_short_buffer
:
type! IOError String

An IOError can be tested with equality checks.

IOError
=
(String) -> IOError

An IOError can be tested with equality checks.

IOError
("short buffer")
44 45///| 46/// eof is the error returned by Read when no more input is available. 47/// (Read must return eof itself, not an error wrapping eof, 48/// because callers will test for eof using ==.) 49/// Functions should return eof only to signal a graceful end of input. 50/// If the eof occurs unexpectedly in a structured data stream, 51/// the appropriate error is either [err_unexpected_eof] or some other error 52/// giving more detail. 53pub let
IOError

eof is the error returned by Read when no more input is available. (Read must return eof itself, not an error wrapping eof, because callers will test for eof using ==.) Functions should return eof only to signal a graceful end of input. If the eof occurs unexpectedly in a structured data stream, the appropriate error is either [err_unexpected_eof] or some other error giving more detail.

eof
:
type! IOError String

An IOError can be tested with equality checks.

IOError
=
(String) -> IOError

An IOError can be tested with equality checks.

IOError
("eof")
54 55///| 56/// err_unexpected_eof means that eof was encountered in the 57/// middle of reading a fixed-size block or data structure. 58pub let
IOError

err_unexpected_eof means that eof was encountered in the middle of reading a fixed-size block or data structure.

err_unexpected_eof
:
type! IOError String

An IOError can be tested with equality checks.

IOError
=
(String) -> IOError

An IOError can be tested with equality checks.

IOError
("unexpected eof")
59 60///| 61/// err_no_progress is returned by some clients of a [Reader] when 62/// many calls to Read have failed to return any data or error, 63/// usually the sign of a broken [Reader] implementation. 64pub let
IOError

err_no_progress is returned by some clients of a [Reader] when many calls to Read have failed to return any data or error, usually the sign of a broken [Reader] implementation.

err_no_progress
:
type! IOError String

An IOError can be tested with equality checks.

IOError
=
(String) -> IOError

An IOError can be tested with equality checks.

IOError
(
65 "multiple Read calls return no data or error", 66) 67 68///| 69/// Reader is the interface that wraps the basic Read method. 70/// 71/// Read reads up to len(p) bytes into p. It returns the number of bytes 72/// read (0 <= n <= len(p)) and any error encountered. Even if Read 73/// returns n < len(p), it may use all of p as scratch space during the call. 74/// If some data is available but not len(p) bytes, Read conventionally 75/// returns what is available instead of waiting for more. 76/// 77/// When Read encounters an error or end-of-file condition after 78/// successfully reading n > 0 bytes, it returns the number of 79/// bytes read. It may return the (non-None) error from the same call 80/// or return the error (and n == 0) from a subsequent call. 81/// An instance of this general case is that a Reader returning 82/// a non-zero number of bytes at the end of the input stream may 83/// return either err == eof or err == None. The next Read should 84/// return 0, eof. 85/// 86/// Callers should always process the n > 0 bytes returned before 87/// considering the error err. Doing so correctly handles I/O errors 88/// that happen after reading some bytes and also both of the 89/// allowed eof behaviors. 90/// 91/// If len(p) == 0, Read should always return n == 0. It may return a 92/// non-None error if some error condition is known, such as eof. 93/// 94/// Implementations of Read are discouraged from returning a 95/// zero byte count with a None error, except when len(p) == 0. 96/// Callers should treat a return of 0 and None as indicating that 97/// nothing happened; in particular it does not indicate eof. 98/// 99/// Implementations must not retain p. 100pub(open) trait
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
{
101
(Self, Slice[Byte]) -> (Int, IOError?)
read
(

type parameter Self

Self
,
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
]) -> (
Int
Int
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?)
102} 103 104///| 105/// Writer is the interface that wraps the basic Write method. 106/// 107/// Write writes len(p) bytes from p to the underlying data stream. 108/// It returns the number of bytes written from p (0 <= n <= len(p)) 109/// and any error encountered that caused the write to stop early. 110/// Write must return a non-None error if it returns n < len(p). 111/// Write must not modify the slice data, even temporarily. 112/// 113/// Implementations must not retain p. 114pub(open) trait
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
{
115
(Self, Slice[Byte]) -> (Int, IOError?)
write
(

type parameter Self

Self
,
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
]) -> (
Int
Int
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?)
116} 117 118///| 119/// Closer is the interface that wraps the basic Close method. 120/// 121/// The behavior of Close after the first call is undefined. 122/// Specific implementations may document their own behavior. 123pub(open) trait
trait Closer {
  close(Self) -> IOError?
}

Closer is the interface that wraps the basic Close method.

The behavior of Close after the first call is undefined. Specific implementations may document their own behavior.

Closer
{
124
(Self) -> IOError?
close
(

type parameter Self

Self
) ->
type! IOError String

An IOError can be tested with equality checks.

IOError
?
125} 126 127///| 128/// Seeker is the interface that wraps the basic Seek method. 129/// 130/// Seek sets the offset for the next Read or Write to offset, 131/// interpreted according to whence: 132/// [SeekStart] means relative to the start of the file, 133/// [SeekCurrent] means relative to the current offset, and 134/// [SeekEnd] means relative to the end 135/// (for example, offset = -2 specifies the penultimate byte of the file). 136/// Seek returns the new offset relative to the start of the 137/// file or an error, if any. 138/// 139/// Seeking to an offset before the start of the file is an error. 140/// Seeking to any positive offset may be allowed, but if the new offset exceeds 141/// the size of the underlying object the behavior of subsequent I/O operations 142/// is implementation-dependent. 143pub(open) trait
trait Seeker {
  seek(Self, Int64, Whence) -> (Int64, IOError?)
}

Seeker is the interface that wraps the basic Seek method.

Seek sets the offset for the next Read or Write to offset, interpreted according to whence: [SeekStart] means relative to the start of the file, [SeekCurrent] means relative to the current offset, and [SeekEnd] means relative to the end (for example, offset = -2 specifies the penultimate byte of the file). Seek returns the new offset relative to the start of the file or an error, if any.

Seeking to an offset before the start of the file is an error. Seeking to any positive offset may be allowed, but if the new offset exceeds the size of the underlying object the behavior of subsequent I/O operations is implementation-dependent.

Seeker
{
144
(Self, Int64, Whence) -> (Int64, IOError?)
seek
(

type parameter Self

Self
,
Int64
Int64
,
enum Whence {
  SeekStart
  SeekCurrent
  SeekEnd
}

Seek whence values.

Whence
) -> (
Int64
Int64
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?)
145} 146 147///| 148/// ReadWriter is the interface that groups the basic Read and Write methods. 149pub(open) trait
trait ReadWriter {
}

ReadWriter is the interface that groups the basic Read and Write methods.

ReadWriter
:
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
+
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
{}
150 151///| 152/// ReadCloser is the interface that groups the basic Read and Close methods. 153pub(open) trait
trait ReadCloser {
}

ReadCloser is the interface that groups the basic Read and Close methods.

ReadCloser
:
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
+
trait Closer {
  close(Self) -> IOError?
}

Closer is the interface that wraps the basic Close method.

The behavior of Close after the first call is undefined. Specific implementations may document their own behavior.

Closer
{}
154 155///| 156/// WriteCloser is the interface that groups the basic Write and Close methods. 157pub(open) trait
trait WriteCloser {
}

WriteCloser is the interface that groups the basic Write and Close methods.

WriteCloser
:
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
+
trait Closer {
  close(Self) -> IOError?
}

Closer is the interface that wraps the basic Close method.

The behavior of Close after the first call is undefined. Specific implementations may document their own behavior.

Closer
{}
158 159///| 160/// ReadWriteCloser is the interface that groups the basic Read, Write and Close methods. 161pub(open) trait
trait ReadWriteCloser {
}

ReadWriteCloser is the interface that groups the basic Read, Write and Close methods.

ReadWriteCloser
:
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
+
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
+
trait Closer {
  close(Self) -> IOError?
}

Closer is the interface that wraps the basic Close method.

The behavior of Close after the first call is undefined. Specific implementations may document their own behavior.

Closer
{}
162 163///| 164/// ReadSeeker is the interface that groups the basic Read and Seek methods. 165pub(open) trait
trait ReadSeeker {
}

ReadSeeker is the interface that groups the basic Read and Seek methods.

ReadSeeker
:
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
+
trait Seeker {
  seek(Self, Int64, Whence) -> (Int64, IOError?)
}

Seeker is the interface that wraps the basic Seek method.

Seek sets the offset for the next Read or Write to offset, interpreted according to whence: [SeekStart] means relative to the start of the file, [SeekCurrent] means relative to the current offset, and [SeekEnd] means relative to the end (for example, offset = -2 specifies the penultimate byte of the file). Seek returns the new offset relative to the start of the file or an error, if any.

Seeking to an offset before the start of the file is an error. Seeking to any positive offset may be allowed, but if the new offset exceeds the size of the underlying object the behavior of subsequent I/O operations is implementation-dependent.

Seeker
{}
166 167///| 168/// ReadSeekCloser is the interface that groups the basic Read, Seek and Close 169/// methods. 170pub(open) trait
trait ReadSeekCloser {
}

ReadSeekCloser is the interface that groups the basic Read, Seek and Close methods.

ReadSeekCloser
:
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
+
trait Seeker {
  seek(Self, Int64, Whence) -> (Int64, IOError?)
}

Seeker is the interface that wraps the basic Seek method.

Seek sets the offset for the next Read or Write to offset, interpreted according to whence: [SeekStart] means relative to the start of the file, [SeekCurrent] means relative to the current offset, and [SeekEnd] means relative to the end (for example, offset = -2 specifies the penultimate byte of the file). Seek returns the new offset relative to the start of the file or an error, if any.

Seeking to an offset before the start of the file is an error. Seeking to any positive offset may be allowed, but if the new offset exceeds the size of the underlying object the behavior of subsequent I/O operations is implementation-dependent.

Seeker
+
trait Closer {
  close(Self) -> IOError?
}

Closer is the interface that wraps the basic Close method.

The behavior of Close after the first call is undefined. Specific implementations may document their own behavior.

Closer
{}
171 172///| 173/// WriteSeeker is the interface that groups the basic Write and Seek methods. 174pub(open) trait
trait WriteSeeker {
}

WriteSeeker is the interface that groups the basic Write and Seek methods.

WriteSeeker
:
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
+
trait Seeker {
  seek(Self, Int64, Whence) -> (Int64, IOError?)
}

Seeker is the interface that wraps the basic Seek method.

Seek sets the offset for the next Read or Write to offset, interpreted according to whence: [SeekStart] means relative to the start of the file, [SeekCurrent] means relative to the current offset, and [SeekEnd] means relative to the end (for example, offset = -2 specifies the penultimate byte of the file). Seek returns the new offset relative to the start of the file or an error, if any.

Seeking to an offset before the start of the file is an error. Seeking to any positive offset may be allowed, but if the new offset exceeds the size of the underlying object the behavior of subsequent I/O operations is implementation-dependent.

Seeker
{}
175 176///| 177/// ReadWriteSeeker is the interface that groups the basic Read, Write and Seek methods. 178pub(open) trait
trait ReadWriteSeeker {
}

ReadWriteSeeker is the interface that groups the basic Read, Write and Seek methods.

ReadWriteSeeker
:
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
+
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
+
trait Seeker {
  seek(Self, Int64, Whence) -> (Int64, IOError?)
}

Seeker is the interface that wraps the basic Seek method.

Seek sets the offset for the next Read or Write to offset, interpreted according to whence: [SeekStart] means relative to the start of the file, [SeekCurrent] means relative to the current offset, and [SeekEnd] means relative to the end (for example, offset = -2 specifies the penultimate byte of the file). Seek returns the new offset relative to the start of the file or an error, if any.

Seeking to an offset before the start of the file is an error. Seeking to any positive offset may be allowed, but if the new offset exceeds the size of the underlying object the behavior of subsequent I/O operations is implementation-dependent.

Seeker
{}
179 180///| 181/// ReaderFrom is the interface that wraps the read_from method. 182/// 183/// read_from reads data from r until eof or error. 184/// The return value n is the number of bytes read. 185/// Any error except eof encountered during the read is also returned. 186/// 187/// The [copy] function uses [ReaderFrom] if available. 188pub(open) trait
trait ReaderFrom {
  read_from(Self, &Reader) -> (Int64, IOError?)
}

ReaderFrom is the interface that wraps the read_from method.

read_from reads data from r until eof or error. The return value n is the number of bytes read. Any error except eof encountered during the read is also returned.

The [copy] function uses [ReaderFrom] if available.

ReaderFrom
{
189
(Self, &Reader) -> (Int64, IOError?)
read_from
(

type parameter Self

Self
, &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
) -> (
Int64
Int64
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?)
190} 191 192///| 193/// WriterTo is the interface that wraps the write_to method. 194/// 195/// write_to writes data to w until there's no more data to write or 196/// when an error occurs. The return value n is the number of bytes 197/// written. Any error encountered during the write is also returned. 198/// 199/// The copy function uses WriterTo if available. 200pub(open) trait
trait WriterTo {
  write_to(Self, &Writer) -> (Int64, IOError?)
}

WriterTo is the interface that wraps the write_to method.

write_to writes data to w until there's no more data to write or when an error occurs. The return value n is the number of bytes written. Any error encountered during the write is also returned.

The copy function uses WriterTo if available.

WriterTo
{
201
(Self, &Writer) -> (Int64, IOError?)
write_to
(

type parameter Self

Self
, &
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
) -> (
Int64
Int64
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?)
202} 203 204///| 205/// ReaderAt is the interface that wraps the basic read_at method. 206/// 207/// read_at reads len(p) bytes into p starting at offset off in the 208/// underlying input source. It returns the number of bytes 209/// read (0 <= n <= len(p)) and any error encountered. 210/// 211/// When read_at returns n < len(p), it returns a non-None error 212/// explaining why more bytes were not returned. In this respect, 213/// read_at is stricter than Read. 214/// 215/// Even if read_at returns n < len(p), it may use all of p as scratch 216/// space during the call. If some data is available but not len(p) bytes, 217/// read_at blocks until either all the data is available or an error occurs. 218/// In this respect read_at is different from Read. 219/// 220/// If the n = len(p) bytes returned by read_at are at the end of the 221/// input source, read_at may return either err == eof or err == None. 222/// 223/// If read_at is reading from an input source with a seek offset, 224/// read_at should not affect nor be affected by the underlying 225/// seek offset. 226/// 227/// Clients of read_at can execute parallel read_at calls on the 228/// same input source. 229/// 230/// Implementations must not retain p. 231pub(open) trait
trait ReaderAt {
  read_at(Self, Slice[Byte], Int64) -> (Int, IOError?)
}

ReaderAt is the interface that wraps the basic read_at method.

read_at reads len(p) bytes into p starting at offset off in the underlying input source. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered.

When read_at returns n < len(p), it returns a non-None error explaining why more bytes were not returned. In this respect, read_at is stricter than Read.

Even if read_at returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, read_at blocks until either all the data is available or an error occurs. In this respect read_at is different from Read.

If the n = len(p) bytes returned by read_at are at the end of the input source, read_at may return either err == eof or err == None.

If read_at is reading from an input source with a seek offset, read_at should not affect nor be affected by the underlying seek offset.

Clients of read_at can execute parallel read_at calls on the same input source.

Implementations must not retain p.

ReaderAt
{
232
(Self, Slice[Byte], Int64) -> (Int, IOError?)
read_at
(

type parameter Self

Self
,
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
],
Int64
Int64
) -> (
Int
Int
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?)
233} 234 235///| 236/// WriterAt is the interface that wraps the basic write_at method. 237/// 238/// write_at writes len(p) bytes from p to the underlying data stream 239/// at offset off. It returns the number of bytes written from p (0 <= n <= len(p)) 240/// and any error encountered that caused the write to stop early. 241/// write_at must return a non-None error if it returns n < len(p). 242/// 243/// If write_at is writing to a destination with a seek offset, 244/// write_at should not affect nor be affected by the underlying 245/// seek offset. 246/// 247/// Clients of write_at can execute parallel write_at calls on the same 248/// destination if the ranges do not overlap. 249/// 250/// Implementations must not retain p. 251pub(open) trait
trait WriterAt {
  write_at(Self, Slice[Byte], Int64) -> (Int, IOError?)
}

WriterAt is the interface that wraps the basic write_at method.

write_at writes len(p) bytes from p to the underlying data stream at offset off. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. write_at must return a non-None error if it returns n < len(p).

If write_at is writing to a destination with a seek offset, write_at should not affect nor be affected by the underlying seek offset.

Clients of write_at can execute parallel write_at calls on the same destination if the ranges do not overlap.

Implementations must not retain p.

WriterAt
{
252
(Self, Slice[Byte], Int64) -> (Int, IOError?)
write_at
(

type parameter Self

Self
,
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
],
Int64
Int64
) -> (
Int
Int
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?)
253} 254 255///| 256/// ByteReader is the interface that wraps the read_byte method. 257/// 258/// read_byte reads and returns the next byte from the input or 259/// any error encountered. If read_byte returns an error, no input 260/// byte was consumed, and the returned byte value is undefined. 261/// 262/// read_byte provides an efficient interface for byte-at-time 263/// processing. A [Reader] that does not implement ByteReader 264/// can be wrapped using bufio.NewReader to add this method. 265pub(open) trait
trait ByteReader {
  read_byte(Self) -> (Byte, IOError?)
}

ByteReader is the interface that wraps the read_byte method.

read_byte reads and returns the next byte from the input or any error encountered. If read_byte returns an error, no input byte was consumed, and the returned byte value is undefined.

read_byte provides an efficient interface for byte-at-time processing. A [Reader] that does not implement ByteReader can be wrapped using bufio.NewReader to add this method.

ByteReader
{
266
(Self) -> (Byte, IOError?)
read_byte
(

type parameter Self

Self
) -> (
Byte
Byte
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?)
267} 268 269///| 270/// ByteScanner is the interface that adds the unread_byte method to the 271/// basic read_byte method. 272/// 273/// unread_byte causes the next call to read_byte to return the last byte read. 274/// If the last operation was not a successful call to read_byte, unread_byte may 275/// return an error, unread the last byte read (or the byte prior to the 276/// last-unread byte), or (in implementations that support the [Seeker] interface) 277/// seek to one byte before the current offset. 278pub(open) trait
trait ByteScanner {
  unread_byte(Self) -> IOError?
}

ByteScanner is the interface that adds the unread_byte method to the basic read_byte method.

unread_byte causes the next call to read_byte to return the last byte read. If the last operation was not a successful call to read_byte, unread_byte may return an error, unread the last byte read (or the byte prior to the last-unread byte), or (in implementations that support the [Seeker] interface) seek to one byte before the current offset.

ByteScanner
:
trait ByteReader {
  read_byte(Self) -> (Byte, IOError?)
}

ByteReader is the interface that wraps the read_byte method.

read_byte reads and returns the next byte from the input or any error encountered. If read_byte returns an error, no input byte was consumed, and the returned byte value is undefined.

read_byte provides an efficient interface for byte-at-time processing. A [Reader] that does not implement ByteReader can be wrapped using bufio.NewReader to add this method.

ByteReader
{
279
(Self) -> IOError?
unread_byte
(

type parameter Self

Self
) ->
type! IOError String

An IOError can be tested with equality checks.

IOError
?
280} 281 282///| 283/// ByteWriter is the interface that wraps the write_byte method. 284pub(open) trait
trait ByteWriter {
  write_byte(Self, Byte) -> IOError?
}

ByteWriter is the interface that wraps the write_byte method.

ByteWriter
{
285
(Self, Byte) -> IOError?
write_byte
(

type parameter Self

Self
,
Byte
Byte
) ->
type! IOError String

An IOError can be tested with equality checks.

IOError
?
286} 287 288///| 289/// read_at_least reads from r into buf until it has read at least min bytes. 290/// It returns the number of bytes copied and an error if fewer bytes were read. 291/// The error is eof only if no bytes were read. 292/// If an eof happens after reading fewer than min bytes, 293/// read_at_least returns [err_unexpected_eof]. 294/// If min is greater than the length of buf, read_at_least returns [err_short_buffer]. 295/// On return, n >= min if and only if err == None. 296/// If r returns an error having read at least min bytes, the error is dropped. 297fn
(r : &Reader, buf : Slice[Byte], min : Int) -> (Int, IOError?)

read_at_least reads from r into buf until it has read at least min bytes. It returns the number of bytes copied and an error if fewer bytes were read. The error is eof only if no bytes were read. If an eof happens after reading fewer than min bytes, read_at_least returns [err_unexpected_eof]. If min is greater than the length of buf, read_at_least returns [err_short_buffer]. On return, n >= min if and only if err == None. If r returns an error having read at least min bytes, the error is dropped.

read_at_least
(
&Reader
r
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
,
Slice[Byte]
buf
:
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
],
Int
min
:
Int
Int
) -> (
Int
Int
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
298 let mut
Int
n
= 0
299 let mut
IOError?
err
=
IOError?
None
300 if
Slice[Byte]
buf
.
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
()
(self_ : Int, other : Int) -> Bool
<
Int
min
{
301 return (0,
(IOError) -> IOError?
Some
(
IOError

err_short_buffer means that a read required a longer buffer than was provided.

err_short_buffer
))
302 } 303 while
Int
n
(self_ : Int, other : Int) -> Bool
<
Int
min
(Bool, Bool) -> Bool
&&
IOError?
err
(self : IOError?, other : IOError?) -> Bool
==
IOError?
None
{
304 let
(Int, IOError?)
v
=
&Reader
r
.
(&Reader, Slice[Byte]) -> (Int, IOError?)
read
(
Slice[Byte]
buf
[
Int
n
:])
305
Int
n
(self : Int, other : Int) -> Int

Adds two 32-bit signed integers. Performs two's complement arithmetic, which means the operation will wrap around if the result exceeds the range of a 32-bit integer.

Parameters:

  • self : The first integer operand.
  • other : The second integer operand.

Returns a new integer that is the sum of the two operands. If the mathematical sum exceeds the range of a 32-bit integer (-2,147,483,648 to 2,147,483,647), the result wraps around according to two's complement rules.

Example:

test "Int::op_add" {
  inspect(42 + 1, content="43")
  inspect(2147483647 + 1, content="-2147483648") // Overflow wraps around to minimum value
}
+=
(Int, IOError?)
v
.
Int
0
306
IOError?
err
=
(Int, IOError?)
v
.
IOError?
1
307 } 308 if
Int
n
(self_ : Int, other : Int) -> Bool
>=
Int
min
{
309
IOError?
err
=
IOError?
None
310 } else if
Int
n
(self_ : Int, other : Int) -> Bool
>
0
(Bool, Bool) -> Bool
&&
IOError?
err
(self : IOError?, other : IOError?) -> Bool
==
(IOError) -> IOError?
Some
(
IOError

eof is the error returned by Read when no more input is available. (Read must return eof itself, not an error wrapping eof, because callers will test for eof using ==.) Functions should return eof only to signal a graceful end of input. If the eof occurs unexpectedly in a structured data stream, the appropriate error is either [err_unexpected_eof] or some other error giving more detail.

eof
) {
311
IOError?
err
=
(IOError) -> IOError?
Some
(
IOError

err_unexpected_eof means that eof was encountered in the middle of reading a fixed-size block or data structure.

err_unexpected_eof
)
312 } 313 (
Int
n
,
IOError?
err
)
314} 315 316///| 317/// read_full reads exactly len(buf) bytes from r into buf. 318/// It returns the number of bytes copied and an error if fewer bytes were read. 319/// The error is eof only if no bytes were read. 320/// If an eof happens after reading some but not all the bytes, 321/// read_full returns [err_unexpected_eof]. 322/// On return, n == len(buf) if and only if err == None. 323/// If r returns an error having read at least len(buf) bytes, the error is dropped. 324pub fn
(r : &Reader, buf : Slice[Byte]) -> (Int, IOError?)

read_full reads exactly len(buf) bytes from r into buf. It returns the number of bytes copied and an error if fewer bytes were read. The error is eof only if no bytes were read. If an eof happens after reading some but not all the bytes, read_full returns [err_unexpected_eof]. On return, n == len(buf) if and only if err == None. If r returns an error having read at least len(buf) bytes, the error is dropped.

read_full
(
&Reader
r
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
,
Slice[Byte]
buf
:
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
]) -> (
Int
Int
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
325
(r : &Reader, buf : Slice[Byte], min : Int) -> (Int, IOError?)

read_at_least reads from r into buf until it has read at least min bytes. It returns the number of bytes copied and an error if fewer bytes were read. The error is eof only if no bytes were read. If an eof happens after reading fewer than min bytes, read_at_least returns [err_unexpected_eof]. If min is greater than the length of buf, read_at_least returns [err_short_buffer]. On return, n >= min if and only if err == None. If r returns an error having read at least min bytes, the error is dropped.

read_at_least
(
&Reader
r
,
Slice[Byte]
buf
,
Slice[Byte]
buf
.
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
())
326} 327 328///| 329/// copy_n copies n bytes (or until an error) from src to dst. 330/// It returns the number of bytes copied and the earliest 331/// error encountered while copying. 332/// On return, written == n if and only if err == None. 333/// 334/// If dst implements [ReaderFrom], the copy is implemented using it. 335pub fn
(dst : &Writer, src : &Reader, n : Int64) -> (Int64, IOError?)

copy_n copies n bytes (or until an error) from src to dst. It returns the number of bytes copied and the earliest error encountered while copying. On return, written == n if and only if err == None.

If dst implements [ReaderFrom], the copy is implemented using it.

copy_n
(
&Writer
dst
: &
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
,
&Reader
src
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
,
Int64
n
:
Int64
Int64
) -> (
Int64
Int64
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
336 let
(Int64, IOError?)
v
=
(dst : &Writer, src : &Reader) -> (Int64, IOError?)

copy copies from src to dst until either eof is reached on src or an error occurs. It returns the number of bytes copied and the first error encountered while copying, if any.

A successful copy returns err == None, not err == eof. Because copy is defined to read from src until eof, it does not treat an eof from Read as an error to be reported.

If src implements [WriterTo], the copy is implemented by calling src.write_to(dst). Otherwise, if dst implements [ReaderFrom], the copy is implemented by calling dst.read_from(src).

copy
(
&Writer
dst
,
struct LimitedReader {
  r: &Reader
  mut n: Int64
}

A LimitedReader reads from R but limits the amount of data returned to just N bytes. Each call to Read updates N to reflect the new amount remaining. Read returns eof when N <= 0 or when the underlying R returns eof.

LimitedReader
::
(r : &Reader, n : Int64) -> LimitedReader

LimitedReader::new returns a Reader that reads from r but stops with eof after n bytes. The underlying implementation is a LimitedReader.

new
(
&Reader
src
,
Int64
n
))
337 let
Int64
written
=
(Int64, IOError?)
v
.
Int64
0
338 let mut
IOError?
err
=
(Int64, IOError?)
v
.
IOError?
1
339 if
Int64
written
(self : Int64, other : Int64) -> Bool

Tests if two 64-bit integers are equal.

Parameters:

  • self : The first 64-bit integer to compare.
  • other : The second 64-bit integer to compare.

Returns true if both integers are equal, false otherwise.

Example:

test "Int64::op_equal" {
  let a = 42L
  let b = 42L
  let c = -42L
  inspect(a == b, content="true")
  inspect(a == c, content="false")
}
==
Int64
n
{
340 return (
Int64
n
,
IOError?
None
)
341 } 342 if
Int64
written
(self_ : Int64, other : Int64) -> Bool
<
Int64
n
(Bool, Bool) -> Bool
&&
IOError?
err
(self : IOError?, other : IOError?) -> Bool
==
IOError?
None
{
343 // src stopped early; must have been eof. 344
IOError?
err
=
(IOError) -> IOError?
Some
(
IOError

eof is the error returned by Read when no more input is available. (Read must return eof itself, not an error wrapping eof, because callers will test for eof using ==.) Functions should return eof only to signal a graceful end of input. If the eof occurs unexpectedly in a structured data stream, the appropriate error is either [err_unexpected_eof] or some other error giving more detail.

eof
)
345 } 346 (
Int64
written
,
IOError?
err
)
347} 348 349///| 350/// copy copies from src to dst until either eof is reached 351/// on src or an error occurs. It returns the number of bytes 352/// copied and the first error encountered while copying, if any. 353/// 354/// A successful copy returns err == None, not err == eof. 355/// Because copy is defined to read from src until eof, it does 356/// not treat an eof from Read as an error to be reported. 357/// 358/// If src implements [WriterTo], 359/// the copy is implemented by calling src.write_to(dst). 360/// Otherwise, if dst implements [ReaderFrom], 361/// the copy is implemented by calling dst.read_from(src). 362pub fn
(dst : &Writer, src : &Reader) -> (Int64, IOError?)

copy copies from src to dst until either eof is reached on src or an error occurs. It returns the number of bytes copied and the first error encountered while copying, if any.

A successful copy returns err == None, not err == eof. Because copy is defined to read from src until eof, it does not treat an eof from Read as an error to be reported.

If src implements [WriterTo], the copy is implemented by calling src.write_to(dst). Otherwise, if dst implements [ReaderFrom], the copy is implemented by calling dst.read_from(src).

copy
(
&Writer
dst
: &
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
,
&Reader
src
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
) -> (
Int64
Int64
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
363 return
(dst : &Writer, src : &Reader, buf : Slice[Byte]?) -> (Int64, IOError?)

copy_buffer is identical to copy except that it stages through the provided buffer (if one is required) rather than allocating a temporary one. If buf is None, one is allocated; otherwise if it has zero length, copy_buffer panics.

If either src implements [WriterTo] or dst implements [ReaderFrom], buf will not be used to perform the copy.

copy_buffer
(
&Writer
dst
,
&Reader
src
,
Slice[Byte]?
None
)
364} 365 366///| 367/// copy_buffer is identical to copy except that it stages through the 368/// provided buffer (if one is required) rather than allocating a 369/// temporary one. If buf is None, one is allocated; otherwise if it has 370/// zero length, copy_buffer panics. 371/// 372/// If either src implements [WriterTo] or dst implements [ReaderFrom], 373/// buf will not be used to perform the copy. 374pub fn
(dst : &Writer, src : &Reader, buf : Slice[Byte]?) -> (Int64, IOError?)

copy_buffer is identical to copy except that it stages through the provided buffer (if one is required) rather than allocating a temporary one. If buf is None, one is allocated; otherwise if it has zero length, copy_buffer panics.

If either src implements [WriterTo] or dst implements [ReaderFrom], buf will not be used to perform the copy.

copy_buffer
(
375
&Writer
dst
: &
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
,
376
&Reader
src
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
,
377
Slice[Byte]?
buf
:
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
]?
378) -> (
Int64
Int64
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
379 if
Slice[Byte]?
buf
(x : Slice[Byte]?, y : Slice[Byte]?) -> Bool
!=
Slice[Byte]?
None
(Bool, Bool) -> Bool
&&
Slice[Byte]?
buf
.
(self : Slice[Byte]?) -> Slice[Byte]

Extract the value in Some.

If the value is None, it throws a panic.

unwrap
().
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
()
(self : Int, other : Int) -> Bool

Compares two integers for equality.

Parameters:

  • self : The first integer to compare.
  • other : The second integer to compare.

Returns true if both integers have the same value, false otherwise.

Example:

test "Int::op_equal" {
  inspect(42 == 42, content="true")
  inspect(42 == -42, content="false")
}
==
0 {
380 return (0,
(IOError) -> IOError?
Some
(
(String) -> IOError

An IOError can be tested with equality checks.

IOError
("empty buffer in copy_buffer")))
381 } 382 let mut
Slice[Byte]?
buf
=
Slice[Byte]?
buf
383 384 // TODO: 385 // // If the reader has a write_to method, use it to do the copy. 386 // // Avoids an allocation and a copy. 387 // if wt, ok := src.(WriterTo); ok { 388 // return wt.write_to(dst) 389 // } 390 // // Similarly, if the writer has a read_from method, use it to do the copy. 391 // if rf, ok := dst.(ReaderFrom); ok { 392 // return rf.read_from(src) 393 // } 394 395 // 396 if
Slice[Byte]?
buf
(self : Slice[Byte]?, other : Slice[Byte]?) -> Bool
==
Slice[Byte]?
None
{
397 let
Int
size
= 32
(self : Int, other : Int) -> Int

Multiplies two 32-bit integers. This is the implementation of the * operator for Int.

Parameters:

  • self : The first integer operand.
  • other : The second integer operand.

Returns the product of the two integers. If the result overflows the range of Int, it wraps around according to two's complement arithmetic.

Example:

test "Int::op_mul" {
  inspect(42 * 2, content="84")
  inspect(-10 * 3, content="-30")
  let max = 2147483647 // Int.max_value
  inspect(max * 2, content="-2") // Overflow wraps around
}
*
1024
398 // TODO: 399 // if l, ok := src.(*LimitedReader); ok && Int64(size) > l.N { 400 // if l.N < 1 { 401 // size = 1 402 // } else { 403 // size = int(l.N) 404 // } 405 // } 406
Slice[Byte]?
buf
=
(Slice[Byte]) -> Slice[Byte]?
Some
(
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
::
(buf : Array[Byte], start~ : Int = .., end? : Int) -> Slice[Byte]
new
(
type Array[T]

An Array is a collection of values that supports random access and can grow in size.

Array
::
(Int, Byte) -> Array[Byte]

Creates a new array with a specified length and initializes all elements with the given value.

Parameters:

  • length : The length of the array to create. Must be a non-negative integer.
  • initial_value : The value used to initialize all elements in the array.

Returns a new array of type Array[T] with length elements, where each element is initialized to initial_value.

Throws an error if length is negative.

Example:

test "Array::make" {
  let arr = Array::make(3, 42)
  inspect(arr, content="[42, 42, 42]")
}

test "panic Array::make/negative_length" {
  ignore(Array::make(-1, 0))
}

WARNING: A common pitfall is creating with the same initial value, for example:

test {
  let two_dimension_array = Array::make(10, Array::make(10, 0))
  two_dimension_array[0][5] = 10
  assert_eq(two_dimension_array[5][5], 10)
}

This is because all the cells reference to the same object (the Array[Int] in this case). One should use makei() instead which creates an object for each index.

make
(
Int
size
, b'\x00')))
407 } 408 let
Slice[Byte]
buf
=
Slice[Byte]?
buf
.
(self : Slice[Byte]?) -> Slice[Byte]

Extract the value in Some.

If the value is None, it throws a panic.

unwrap
()
409 410 // 411 let mut
Int64
written
= 0L
412 let mut
IOError?
err
=
IOError?
None
413 for { 414 let (
Int
nr
,
IOError?
er
) =
&Reader
src
.
(&Reader, Slice[Byte]) -> (Int, IOError?)
read
(
Slice[Byte]
buf
)
415 if
Int
nr
(self_ : Int, other : Int) -> Bool
>
0 {
416 let (
Int
nw
,
IOError?
ew
) =
&Writer
dst
.
(&Writer, Slice[Byte]) -> (Int, IOError?)
write
(
Slice[Byte]
buf
[:
Int
nr
])
417 let mut
Int
nw
=
Int
nw
418 let mut
IOError?
ew
=
IOError?
ew
419 if
Int
nw
(self_ : Int, other : Int) -> Bool
<
0
(Bool, Bool) -> Bool
||
Int
nr
(self_ : Int, other : Int) -> Bool
<
Int
nw
{
420
Int
nw
= 0
421 if
IOError?
ew
(self : IOError?, other : IOError?) -> Bool
==
IOError?
None
{
422
IOError?
ew
=
(IOError) -> IOError?
Some
(
IOError

err_invalid_write means that a write returned an impossible count.

err_invalid_write
)
423 } 424 } 425
Int64
written
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+=
Int
nw
.
(self : Int) -> Int64

Converts a 32-bit signed integer to a 64-bit signed integer. All 32-bit integers can be represented exactly in 64-bit integer format, so the conversion is lossless.

Parameters:

  • self : The 32-bit signed integer to be converted.

Returns a 64-bit signed integer that represents the same numerical value as the input.

Example:

test "Int::to_int64" {
  let n = 42
  inspect(n.to_int64(), content="42")
  let neg = -42
  inspect(neg.to_int64(), content="-42")
}
to_int64
()
426 if
IOError?
ew
(x : IOError?, y : IOError?) -> Bool
!=
IOError?
None
{
427
IOError?
err
=
IOError?
ew
428 break 429 } 430 if
Int
nr
(x : Int, y : Int) -> Bool
!=
Int
nw
{
431
IOError?
err
=
(IOError) -> IOError?
Some
(
IOError

err_short_write means that a write accepted fewer bytes than requested but failed to return an explicit error.

err_short_write
)
432 break 433 } 434 } 435 if
IOError?
er
(x : IOError?, y : IOError?) -> Bool
!=
IOError?
None
{
436 if
IOError?
er
(x : IOError?, y : IOError?) -> Bool
!=
(IOError) -> IOError?
Some
(
IOError

eof is the error returned by Read when no more input is available. (Read must return eof itself, not an error wrapping eof, because callers will test for eof using ==.) Functions should return eof only to signal a graceful end of input. If the eof occurs unexpectedly in a structured data stream, the appropriate error is either [err_unexpected_eof] or some other error giving more detail.

eof
) {
437
IOError?
err
=
IOError?
er
438 } 439 break 440 } 441 } 442 (
Int64
written
,
IOError?
err
)
443} 444 445///| 446/// LimitedReader::new returns a Reader that reads from r 447/// but stops with eof after n bytes. 448/// The underlying implementation is a LimitedReader. 449pub fn
struct LimitedReader {
  r: &Reader
  mut n: Int64
}

A LimitedReader reads from R but limits the amount of data returned to just N bytes. Each call to Read updates N to reflect the new amount remaining. Read returns eof when N <= 0 or when the underlying R returns eof.

LimitedReader
::
(r : &Reader, n : Int64) -> LimitedReader

LimitedReader::new returns a Reader that reads from r but stops with eof after n bytes. The underlying implementation is a LimitedReader.

new
(
&Reader
r
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
,
Int64
n
:
Int64
Int64
) ->
struct LimitedReader {
  r: &Reader
  mut n: Int64
}

A LimitedReader reads from R but limits the amount of data returned to just N bytes. Each call to Read updates N to reflect the new amount remaining. Read returns eof when N <= 0 or when the underlying R returns eof.

LimitedReader
{
450 {
&Reader
r
,
Int64
n
}
451} 452 453///| 454let
&Reader
_trait3
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
=
struct LimitedReader {
  r: &Reader
  mut n: Int64
}

A LimitedReader reads from R but limits the amount of data returned to just N bytes. Each call to Read updates N to reflect the new amount remaining. Read returns eof when N <= 0 or when the underlying R returns eof.

LimitedReader
::
(r : &Reader, n : Int64) -> LimitedReader

LimitedReader::new returns a Reader that reads from r but stops with eof after n bytes. The underlying implementation is a LimitedReader.

new
(
Discard

discard is a [Writer] on which all Write calls succeed without doing anything.

discard
, 0)
455 456///| 457/// A LimitedReader reads from R but limits the amount of 458/// data returned to just N bytes. Each call to Read 459/// updates N to reflect the new amount remaining. 460/// Read returns eof when N <= 0 or when the underlying R returns eof. 461struct LimitedReader { 462
&Reader
r
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
// underlying reader
463 mut
Int64
n
:
Int64
Int64
// max bytes remaining
464} 465 466///| 467pub impl
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
for
struct LimitedReader {
  r: &Reader
  mut n: Int64
}

A LimitedReader reads from R but limits the amount of data returned to just N bytes. Each call to Read updates N to reflect the new amount remaining. Read returns eof when N <= 0 or when the underlying R returns eof.

LimitedReader
with
(self : LimitedReader, p : Slice[Byte]) -> (Int, IOError?)
read
(
LimitedReader
self
,
Slice[Byte]
p
) {
468 if
LimitedReader
self
.
Int64
n
(self_ : Int64, other : Int64) -> Bool
<=
0 {
469 return (0,
(IOError) -> IOError?
Some
(
IOError

eof is the error returned by Read when no more input is available. (Read must return eof itself, not an error wrapping eof, because callers will test for eof using ==.) Functions should return eof only to signal a graceful end of input. If the eof occurs unexpectedly in a structured data stream, the appropriate error is either [err_unexpected_eof] or some other error giving more detail.

eof
))
470 } 471 let mut
Slice[Byte]
p
=
Slice[Byte]
p
472 if
Slice[Byte]
p
.
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
().
(self : Int) -> Int64

Converts a 32-bit signed integer to a 64-bit signed integer. All 32-bit integers can be represented exactly in 64-bit integer format, so the conversion is lossless.

Parameters:

  • self : The 32-bit signed integer to be converted.

Returns a 64-bit signed integer that represents the same numerical value as the input.

Example:

test "Int::to_int64" {
  let n = 42
  inspect(n.to_int64(), content="42")
  let neg = -42
  inspect(neg.to_int64(), content="-42")
}
to_int64
()
(self_ : Int64, other : Int64) -> Bool
>
LimitedReader
self
.
Int64
n
{
473
Slice[Byte]
p
=
Slice[Byte]
p
[:
LimitedReader
self
.
Int64
n
.
(self : Int64) -> Int

Converts a 64-bit signed integer to a 32-bit signed integer by truncating higher bits.

Parameters:

  • value : The 64-bit signed integer (Int64) to be converted.

Returns a 32-bit signed integer (Int). Note that values outside the range of 32-bit integers will be truncated, potentially leading to loss of information.

Example:

test "Int64::to_int" {
  let small = 42L
  let big = 2147483648L // 2^31
  inspect(small.to_int(), content="42")
  inspect(big.to_int(), content="-2147483648") // Truncated to Int.min_value
}
to_int
()]
474 } 475 let (
Int
n
,
IOError?
err
) =
LimitedReader
self
.
&Reader
r
.
(&Reader, Slice[Byte]) -> (Int, IOError?)
read
(
Slice[Byte]
p
)
476
LimitedReader
self
.
Int64
n
(self : Int64, other : Int64) -> Int64

Performs subtraction between two 64-bit integers.

Parameters:

  • self : The minuend (the number being subtracted from).
  • other : The subtrahend (the number to subtract).

Returns the difference between self and other as a 64-bit integer.

Example:

test "Int64::op_sub" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a - b, content="9223372036854775806")
  let c = -9223372036854775808L // Int64 minimum value
  let d = 1L
  inspect(c - d, content="9223372036854775807")
}
-=
Int
n
.
(self : Int) -> Int64

Converts a 32-bit signed integer to a 64-bit signed integer. All 32-bit integers can be represented exactly in 64-bit integer format, so the conversion is lossless.

Parameters:

  • self : The 32-bit signed integer to be converted.

Returns a 64-bit signed integer that represents the same numerical value as the input.

Example:

test "Int::to_int64" {
  let n = 42
  inspect(n.to_int64(), content="42")
  let neg = -42
  inspect(neg.to_int64(), content="-42")
}
to_int64
()
477 (
Int
n
,
IOError?
err
)
478} 479 480///| 481/// SectionReader::new returns a [SectionReader] that reads from r 482/// starting at offset off and stops with eof after n bytes. 483pub fn
struct SectionReader {
  r: &ReaderAt
  base: Int64
  mut off: Int64
  limit: Int64
  n: Int64
}

SectionReader implements Read, Seek, and read_at on a section of an underlying [ReaderAt].

SectionReader
::
(r : &ReaderAt, off : Int64, n : Int64) -> SectionReader

SectionReader::new returns a [SectionReader] that reads from r starting at offset off and stops with eof after n bytes.

new
(
484
&ReaderAt
r
: &
trait ReaderAt {
  read_at(Self, Slice[Byte], Int64) -> (Int, IOError?)
}

ReaderAt is the interface that wraps the basic read_at method.

read_at reads len(p) bytes into p starting at offset off in the underlying input source. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered.

When read_at returns n < len(p), it returns a non-None error explaining why more bytes were not returned. In this respect, read_at is stricter than Read.

Even if read_at returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, read_at blocks until either all the data is available or an error occurs. In this respect read_at is different from Read.

If the n = len(p) bytes returned by read_at are at the end of the input source, read_at may return either err == eof or err == None.

If read_at is reading from an input source with a seek offset, read_at should not affect nor be affected by the underlying seek offset.

Clients of read_at can execute parallel read_at calls on the same input source.

Implementations must not retain p.

ReaderAt
,
485
Int64
off
:
Int64
Int64
,
486
Int64
n
:
Int64
Int64
487) ->
struct SectionReader {
  r: &ReaderAt
  base: Int64
  mut off: Int64
  limit: Int64
  n: Int64
}

SectionReader implements Read, Seek, and read_at on a section of an underlying [ReaderAt].

SectionReader
{
488 let mut
Int64
remaining
= 0L
489 if
Int64
off
(self_ : Int64, other : Int64) -> Bool
<=
Int64
@int64.max_value
(self : Int64, other : Int64) -> Int64

Performs subtraction between two 64-bit integers.

Parameters:

  • self : The minuend (the number being subtracted from).
  • other : The subtrahend (the number to subtract).

Returns the difference between self and other as a 64-bit integer.

Example:

test "Int64::op_sub" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a - b, content="9223372036854775806")
  let c = -9223372036854775808L // Int64 minimum value
  let d = 1L
  inspect(c - d, content="9223372036854775807")
}
-
Int64
n
{
490
Int64
remaining
=
Int64
n
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+
Int64
off
491 } else { 492 // Overflow, with no way to return error. 493 // Assume we can read up to an offset of 1<<63 - 1. 494
Int64
remaining
=
Int64
@int64.max_value
495 } 496 {
&ReaderAt
r
,
Int64
base
:
Int64
off
,
Int64
off
,
Int64
limit
:
Int64
remaining
,
Int64
n
}
497} 498 499///| 500/// SectionReader implements Read, Seek, and read_at on a section 501/// of an underlying [ReaderAt]. 502struct SectionReader { 503
&ReaderAt
r
: &
trait ReaderAt {
  read_at(Self, Slice[Byte], Int64) -> (Int, IOError?)
}

ReaderAt is the interface that wraps the basic read_at method.

read_at reads len(p) bytes into p starting at offset off in the underlying input source. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered.

When read_at returns n < len(p), it returns a non-None error explaining why more bytes were not returned. In this respect, read_at is stricter than Read.

Even if read_at returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, read_at blocks until either all the data is available or an error occurs. In this respect read_at is different from Read.

If the n = len(p) bytes returned by read_at are at the end of the input source, read_at may return either err == eof or err == None.

If read_at is reading from an input source with a seek offset, read_at should not affect nor be affected by the underlying seek offset.

Clients of read_at can execute parallel read_at calls on the same input source.

Implementations must not retain p.

ReaderAt
// constant after creation
504
Int64
base
:
Int64
Int64
// constant after creation
505 mut
Int64
off
:
Int64
Int64
506
Int64
limit
:
Int64
Int64
// constant after creation
507
Int64
n
:
Int64
Int64
// constant after creation
508} 509 510///| 511fn
struct SectionReader {
  r: &ReaderAt
  base: Int64
  mut off: Int64
  limit: Int64
  n: Int64
}

SectionReader implements Read, Seek, and read_at on a section of an underlying [ReaderAt].

SectionReader
::
(self : SectionReader, p : Slice[Byte]) -> (Int, IOError?)
read
(
512
SectionReader
self
:
struct SectionReader {
  r: &ReaderAt
  base: Int64
  mut off: Int64
  limit: Int64
  n: Int64
}

SectionReader implements Read, Seek, and read_at on a section of an underlying [ReaderAt].

SectionReader
,
513
Slice[Byte]
p
:
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
]
514) -> (
Int
Int
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
515 if
SectionReader
self
.
Int64
off
(self_ : Int64, other : Int64) -> Bool
>=
SectionReader
self
.
Int64
limit
{
516 return (0,
(IOError) -> IOError?
Some
(
IOError

eof is the error returned by Read when no more input is available. (Read must return eof itself, not an error wrapping eof, because callers will test for eof using ==.) Functions should return eof only to signal a graceful end of input. If the eof occurs unexpectedly in a structured data stream, the appropriate error is either [err_unexpected_eof] or some other error giving more detail.

eof
))
517 } 518 let
Int64
max
=
SectionReader
self
.
Int64
limit
(self : Int64, other : Int64) -> Int64

Performs subtraction between two 64-bit integers.

Parameters:

  • self : The minuend (the number being subtracted from).
  • other : The subtrahend (the number to subtract).

Returns the difference between self and other as a 64-bit integer.

Example:

test "Int64::op_sub" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a - b, content="9223372036854775806")
  let c = -9223372036854775808L // Int64 minimum value
  let d = 1L
  inspect(c - d, content="9223372036854775807")
}
-
SectionReader
self
.
Int64
off
519 let mut
Slice[Byte]
p
=
Slice[Byte]
p
520 if
Slice[Byte]
p
.
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
().
(self : Int) -> Int64

Converts a 32-bit signed integer to a 64-bit signed integer. All 32-bit integers can be represented exactly in 64-bit integer format, so the conversion is lossless.

Parameters:

  • self : The 32-bit signed integer to be converted.

Returns a 64-bit signed integer that represents the same numerical value as the input.

Example:

test "Int::to_int64" {
  let n = 42
  inspect(n.to_int64(), content="42")
  let neg = -42
  inspect(neg.to_int64(), content="-42")
}
to_int64
()
(self_ : Int64, other : Int64) -> Bool
>
Int64
max
{
521
Slice[Byte]
p
=
Slice[Byte]
p
[:
Int64
max
.
(self : Int64) -> Int

Converts a 64-bit signed integer to a 32-bit signed integer by truncating higher bits.

Parameters:

  • value : The 64-bit signed integer (Int64) to be converted.

Returns a 32-bit signed integer (Int). Note that values outside the range of 32-bit integers will be truncated, potentially leading to loss of information.

Example:

test "Int64::to_int" {
  let small = 42L
  let big = 2147483648L // 2^31
  inspect(small.to_int(), content="42")
  inspect(big.to_int(), content="-2147483648") // Truncated to Int.min_value
}
to_int
()]
522 } 523 let (
Int
n
,
IOError?
err
) =
SectionReader
self
.
&ReaderAt
r
.
(&ReaderAt, Slice[Byte], Int64) -> (Int, IOError?)
read_at
(
Slice[Byte]
p
,
SectionReader
self
.
Int64
off
)
524
SectionReader
self
.
Int64
off
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+=
Int
n
.
(self : Int) -> Int64

Converts a 32-bit signed integer to a 64-bit signed integer. All 32-bit integers can be represented exactly in 64-bit integer format, so the conversion is lossless.

Parameters:

  • self : The 32-bit signed integer to be converted.

Returns a 64-bit signed integer that represents the same numerical value as the input.

Example:

test "Int::to_int64" {
  let n = 42
  inspect(n.to_int64(), content="42")
  let neg = -42
  inspect(neg.to_int64(), content="-42")
}
to_int64
()
525 (
Int
n
,
IOError?
err
)
526} 527 528///| 529pub let
IOError
err_whence
:
type! IOError String

An IOError can be tested with equality checks.

IOError
=
(String) -> IOError

An IOError can be tested with equality checks.

IOError
("Seek: invalid whence")
530 531///| 532pub let
IOError
err_offset
:
type! IOError String

An IOError can be tested with equality checks.

IOError
=
(String) -> IOError

An IOError can be tested with equality checks.

IOError
("Seek: invalid offset")
533 534///| 535fn
(self : SectionReader, offset : Int64, whence : Whence) -> (Int64, IOError?)
seek
(
536
SectionReader
self
:
struct SectionReader {
  r: &ReaderAt
  base: Int64
  mut off: Int64
  limit: Int64
  n: Int64
}

SectionReader implements Read, Seek, and read_at on a section of an underlying [ReaderAt].

SectionReader
,
537
Int64
offset
:
Int64
Int64
,
538
Whence
whence
:
enum Whence {
  SeekStart
  SeekCurrent
  SeekEnd
}

Seek whence values.

Whence
539) -> (
Int64
Int64
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
540 let mut
Int64
offset
=
Int64
offset
541 match
Whence
whence
{
542
Whence

seek relative to the origin of the file

SeekStart
=>
Int64
offset
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+=
SectionReader
self
.
Int64
base
543
Whence

seek relative to the current offset

SeekCurrent
=>
Int64
offset
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+=
SectionReader
self
.
Int64
off
544
Whence

seek relative to the end

SeekEnd
=>
Int64
offset
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+=
SectionReader
self
.
Int64
limit
545 } 546 if
Int64
offset
(self_ : Int64, other : Int64) -> Bool
<
SectionReader
self
.
Int64
base
{
547 return (0,
(IOError) -> IOError?
Some
(
IOError
err_offset
))
548 } 549
SectionReader
self
.
Int64
off
=
Int64
offset
550 (
Int64
offset
(self : Int64, other : Int64) -> Int64

Performs subtraction between two 64-bit integers.

Parameters:

  • self : The minuend (the number being subtracted from).
  • other : The subtrahend (the number to subtract).

Returns the difference between self and other as a 64-bit integer.

Example:

test "Int64::op_sub" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a - b, content="9223372036854775806")
  let c = -9223372036854775808L // Int64 minimum value
  let d = 1L
  inspect(c - d, content="9223372036854775807")
}
-
SectionReader
self
.
Int64
base
,
IOError?
None
)
551} 552 553///| 554fn
(self : SectionReader, p : Slice[Byte], off : Int64) -> (Int, IOError?)
read_at
(
555
SectionReader
self
:
struct SectionReader {
  r: &ReaderAt
  base: Int64
  mut off: Int64
  limit: Int64
  n: Int64
}

SectionReader implements Read, Seek, and read_at on a section of an underlying [ReaderAt].

SectionReader
,
556
Slice[Byte]
p
:
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
],
557
Int64
off
:
Int64
Int64
558) -> (
Int
Int
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
559 let mut
Int64
off
=
Int64
off
560 if
Int64
off
(self_ : Int64, other : Int64) -> Bool
<
0
(Bool, Bool) -> Bool
||
Int64
off
(self_ : Int64, other : Int64) -> Bool
>=
SectionReader
self
.
(self : SectionReader) -> Int64

Size returns the size of the section in bytes.

size
() {
561 return (0,
(IOError) -> IOError?
Some
(
IOError

eof is the error returned by Read when no more input is available. (Read must return eof itself, not an error wrapping eof, because callers will test for eof using ==.) Functions should return eof only to signal a graceful end of input. If the eof occurs unexpectedly in a structured data stream, the appropriate error is either [err_unexpected_eof] or some other error giving more detail.

eof
))
562 } 563
Int64
off
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+=
SectionReader
self
.
Int64
base
564 let
Int64
max
=
SectionReader
self
.
Int64
limit
(self : Int64, other : Int64) -> Int64

Performs subtraction between two 64-bit integers.

Parameters:

  • self : The minuend (the number being subtracted from).
  • other : The subtrahend (the number to subtract).

Returns the difference between self and other as a 64-bit integer.

Example:

test "Int64::op_sub" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a - b, content="9223372036854775806")
  let c = -9223372036854775808L // Int64 minimum value
  let d = 1L
  inspect(c - d, content="9223372036854775807")
}
-
Int64
off
565 let mut
Slice[Byte]
p
=
Slice[Byte]
p
566 if
Slice[Byte]
p
.
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
().
(self : Int) -> Int64

Converts a 32-bit signed integer to a 64-bit signed integer. All 32-bit integers can be represented exactly in 64-bit integer format, so the conversion is lossless.

Parameters:

  • self : The 32-bit signed integer to be converted.

Returns a 64-bit signed integer that represents the same numerical value as the input.

Example:

test "Int::to_int64" {
  let n = 42
  inspect(n.to_int64(), content="42")
  let neg = -42
  inspect(neg.to_int64(), content="-42")
}
to_int64
()
(self_ : Int64, other : Int64) -> Bool
>
Int64
max
{
567
Slice[Byte]
p
=
Slice[Byte]
p
[:
Int64
max
.
(self : Int64) -> Int

Converts a 64-bit signed integer to a 32-bit signed integer by truncating higher bits.

Parameters:

  • value : The 64-bit signed integer (Int64) to be converted.

Returns a 32-bit signed integer (Int). Note that values outside the range of 32-bit integers will be truncated, potentially leading to loss of information.

Example:

test "Int64::to_int" {
  let small = 42L
  let big = 2147483648L // 2^31
  inspect(small.to_int(), content="42")
  inspect(big.to_int(), content="-2147483648") // Truncated to Int.min_value
}
to_int
()]
568 let (
Int
n
,
IOError?
err
) =
SectionReader
self
.
&ReaderAt
r
.
(&ReaderAt, Slice[Byte], Int64) -> (Int, IOError?)
read_at
(
Slice[Byte]
p
,
Int64
off
)
569 let mut
IOError?
err
=
IOError?
err
570 if
IOError?
err
(self : IOError?, other : IOError?) -> Bool
==
IOError?
None
{
571
IOError?
err
=
(IOError) -> IOError?
Some
(
IOError

eof is the error returned by Read when no more input is available. (Read must return eof itself, not an error wrapping eof, because callers will test for eof using ==.) Functions should return eof only to signal a graceful end of input. If the eof occurs unexpectedly in a structured data stream, the appropriate error is either [err_unexpected_eof] or some other error giving more detail.

eof
)
572 } 573 return (
Int
n
,
IOError?
err
)
574 } 575
SectionReader
self
.
&ReaderAt
r
.
(&ReaderAt, Slice[Byte], Int64) -> (Int, IOError?)
read_at
(
Slice[Byte]
p
,
Int64
off
)
576} 577 578///| 579/// Size returns the size of the section in bytes. 580fn
(self : SectionReader) -> Int64

Size returns the size of the section in bytes.

size
(
SectionReader
self
:
struct SectionReader {
  r: &ReaderAt
  base: Int64
  mut off: Int64
  limit: Int64
  n: Int64
}

SectionReader implements Read, Seek, and read_at on a section of an underlying [ReaderAt].

SectionReader
) ->
Int64
Int64
{
581 return
SectionReader
self
.
Int64
limit
(self : Int64, other : Int64) -> Int64

Performs subtraction between two 64-bit integers.

Parameters:

  • self : The minuend (the number being subtracted from).
  • other : The subtrahend (the number to subtract).

Returns the difference between self and other as a 64-bit integer.

Example:

test "Int64::op_sub" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a - b, content="9223372036854775806")
  let c = -9223372036854775808L // Int64 minimum value
  let d = 1L
  inspect(c - d, content="9223372036854775807")
}
-
SectionReader
self
.
Int64
base
582} 583 584///| 585/// Outer returns the underlying [ReaderAt] and offsets for the section. 586/// 587/// The returned values are the same that were passed to [SectionReader::new] 588/// when the [SectionReader] was created. 589fn
(self : SectionReader) -> (&ReaderAt, Int64, Int64)

Outer returns the underlying [ReaderAt] and offsets for the section.

The returned values are the same that were passed to [SectionReader::new] when the [SectionReader] was created.

outer
(
SectionReader
self
:
struct SectionReader {
  r: &ReaderAt
  base: Int64
  mut off: Int64
  limit: Int64
  n: Int64
}

SectionReader implements Read, Seek, and read_at on a section of an underlying [ReaderAt].

SectionReader
) -> (&
trait ReaderAt {
  read_at(Self, Slice[Byte], Int64) -> (Int, IOError?)
}

ReaderAt is the interface that wraps the basic read_at method.

read_at reads len(p) bytes into p starting at offset off in the underlying input source. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered.

When read_at returns n < len(p), it returns a non-None error explaining why more bytes were not returned. In this respect, read_at is stricter than Read.

Even if read_at returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, read_at blocks until either all the data is available or an error occurs. In this respect read_at is different from Read.

If the n = len(p) bytes returned by read_at are at the end of the input source, read_at may return either err == eof or err == None.

If read_at is reading from an input source with a seek offset, read_at should not affect nor be affected by the underlying seek offset.

Clients of read_at can execute parallel read_at calls on the same input source.

Implementations must not retain p.

ReaderAt
,
Int64
Int64
,
Int64
Int64
) {
590 (
SectionReader
self
.
&ReaderAt
r
,
SectionReader
self
.
Int64
base
,
SectionReader
self
.
Int64
n
)
591} 592 593///| 594/// An OffsetWriter maps writes at offset base to offset base+off in the underlying writer. 595struct OffsetWriter { 596
&WriterAt
w
: &
trait WriterAt {
  write_at(Self, Slice[Byte], Int64) -> (Int, IOError?)
}

WriterAt is the interface that wraps the basic write_at method.

write_at writes len(p) bytes from p to the underlying data stream at offset off. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. write_at must return a non-None error if it returns n < len(p).

If write_at is writing to a destination with a seek offset, write_at should not affect nor be affected by the underlying seek offset.

Clients of write_at can execute parallel write_at calls on the same destination if the ranges do not overlap.

Implementations must not retain p.

WriterAt
597
Int64
base
:
Int64
Int64
// the original offset
598 mut
Int64
off
:
Int64
Int64
// the current offset
599} 600 601///| 602/// OffsetWriter::new returns an [OffsetWriter] that writes to w 603/// starting at offset off. 604pub fn
struct OffsetWriter {
  w: &WriterAt
  base: Int64
  mut off: Int64
}

An OffsetWriter maps writes at offset base to offset base+off in the underlying writer.

OffsetWriter
::
(w : &WriterAt, off : Int64) -> OffsetWriter

OffsetWriter::new returns an [OffsetWriter] that writes to w starting at offset off.

new
(
&WriterAt
w
: &
trait WriterAt {
  write_at(Self, Slice[Byte], Int64) -> (Int, IOError?)
}

WriterAt is the interface that wraps the basic write_at method.

write_at writes len(p) bytes from p to the underlying data stream at offset off. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. write_at must return a non-None error if it returns n < len(p).

If write_at is writing to a destination with a seek offset, write_at should not affect nor be affected by the underlying seek offset.

Clients of write_at can execute parallel write_at calls on the same destination if the ranges do not overlap.

Implementations must not retain p.

WriterAt
,
Int64
off
:
Int64
Int64
) ->
struct OffsetWriter {
  w: &WriterAt
  base: Int64
  mut off: Int64
}

An OffsetWriter maps writes at offset base to offset base+off in the underlying writer.

OffsetWriter
{
605 {
&WriterAt
w
,
Int64
base
:
Int64
off
,
Int64
off
}
606} 607 608///| 609fn
struct OffsetWriter {
  w: &WriterAt
  base: Int64
  mut off: Int64
}

An OffsetWriter maps writes at offset base to offset base+off in the underlying writer.

OffsetWriter
::
(self : OffsetWriter, p : Slice[Byte]) -> (Int, IOError?)
write
(
OffsetWriter
self
:
struct OffsetWriter {
  w: &WriterAt
  base: Int64
  mut off: Int64
}

An OffsetWriter maps writes at offset base to offset base+off in the underlying writer.

OffsetWriter
,
Slice[Byte]
p
:
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
]) -> (
Int
Int
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
610 let (
Int
n
,
IOError?
err
) =
OffsetWriter
self
.
&WriterAt
w
.
(&WriterAt, Slice[Byte], Int64) -> (Int, IOError?)
write_at
(
Slice[Byte]
p
,
OffsetWriter
self
.
Int64
off
)
611
OffsetWriter
self
.
Int64
off
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+=
Int
n
.
(self : Int) -> Int64

Converts a 32-bit signed integer to a 64-bit signed integer. All 32-bit integers can be represented exactly in 64-bit integer format, so the conversion is lossless.

Parameters:

  • self : The 32-bit signed integer to be converted.

Returns a 64-bit signed integer that represents the same numerical value as the input.

Example:

test "Int::to_int64" {
  let n = 42
  inspect(n.to_int64(), content="42")
  let neg = -42
  inspect(neg.to_int64(), content="-42")
}
to_int64
()
612 (
Int
n
,
IOError?
err
)
613} 614 615///| 616fn
(self : OffsetWriter, p : Slice[Byte], off : Int64) -> (Int, IOError?)
write_at
(
617
OffsetWriter
self
:
struct OffsetWriter {
  w: &WriterAt
  base: Int64
  mut off: Int64
}

An OffsetWriter maps writes at offset base to offset base+off in the underlying writer.

OffsetWriter
,
618
Slice[Byte]
p
:
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
],
619
Int64
off
:
Int64
Int64
620) -> (
Int
Int
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
621 if
Int64
off
(self_ : Int64, other : Int64) -> Bool
<
0 {
622 return (0,
(IOError) -> IOError?
Some
(
IOError
err_offset
))
623 } 624 let
Int64
off
=
Int64
off
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+
OffsetWriter
self
.
Int64
base
625
OffsetWriter
self
.
&WriterAt
w
.
(&WriterAt, Slice[Byte], Int64) -> (Int, IOError?)
write_at
(
Slice[Byte]
p
,
Int64
off
)
626} 627 628///| 629fn
struct OffsetWriter {
  w: &WriterAt
  base: Int64
  mut off: Int64
}

An OffsetWriter maps writes at offset base to offset base+off in the underlying writer.

OffsetWriter
::
(self : OffsetWriter, offset : Int64, whence : Whence) -> (Int64, IOError?)
seek
(
630
OffsetWriter
self
:
struct OffsetWriter {
  w: &WriterAt
  base: Int64
  mut off: Int64
}

An OffsetWriter maps writes at offset base to offset base+off in the underlying writer.

OffsetWriter
,
631
Int64
offset
:
Int64
Int64
,
632
Whence
whence
:
enum Whence {
  SeekStart
  SeekCurrent
  SeekEnd
}

Seek whence values.

Whence
633) -> (
Int64
Int64
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
634 let mut
Int64
offset
=
Int64
offset
635 match
Whence
whence
{
636
Whence

seek relative to the origin of the file

SeekStart
=>
Int64
offset
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+=
OffsetWriter
self
.
Int64
base
637
Whence

seek relative to the current offset

SeekCurrent
=>
Int64
offset
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+=
OffsetWriter
self
.
Int64
off
638 _ => return (0,
(IOError) -> IOError?
Some
(
IOError
err_whence
))
639 } 640 if
Int64
offset
(self_ : Int64, other : Int64) -> Bool
<
OffsetWriter
self
.
Int64
base
{
641 return (0,
(IOError) -> IOError?
Some
(
IOError
err_offset
))
642 } 643
OffsetWriter
self
.
Int64
off
=
Int64
offset
644 (
Int64
offset
(self : Int64, other : Int64) -> Int64

Performs subtraction between two 64-bit integers.

Parameters:

  • self : The minuend (the number being subtracted from).
  • other : The subtrahend (the number to subtract).

Returns the difference between self and other as a 64-bit integer.

Example:

test "Int64::op_sub" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a - b, content="9223372036854775806")
  let c = -9223372036854775808L // Int64 minimum value
  let d = 1L
  inspect(c - d, content="9223372036854775807")
}
-
OffsetWriter
self
.
Int64
base
,
IOError?
None
)
645} 646 647///| 648/// TeeReader::new returns a [Reader] that writes to w what it reads from r. 649/// All reads from r performed through it are matched with 650/// corresponding writes to w. There is no internal buffering - 651/// the write must complete before the read completes. 652/// Any error encountered while writing is reported as a read error. 653pub fn
struct TeeReader {
  r: &Reader
  w: &Writer
}
TeeReader
::
(r : &Reader, w : &Writer) -> TeeReader

TeeReader::new returns a [Reader] that writes to w what it reads from r. All reads from r performed through it are matched with corresponding writes to w. There is no internal buffering - the write must complete before the read completes. Any error encountered while writing is reported as a read error.

new
(
&Reader
r
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
,
&Writer
w
: &
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
) ->
struct TeeReader {
  r: &Reader
  w: &Writer
}
TeeReader
{
654 {
&Reader
r
,
&Writer
w
}
655} 656 657///| 658struct TeeReader { 659
&Reader
r
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
660
&Writer
w
: &
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
661} 662 663///| 664let
&Reader
_trait
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
=
struct TeeReader {
  r: &Reader
  w: &Writer
}
TeeReader
::
(r : &Reader, w : &Writer) -> TeeReader

TeeReader::new returns a [Reader] that writes to w what it reads from r. All reads from r performed through it are matched with corresponding writes to w. There is no internal buffering - the write must complete before the read completes. Any error encountered while writing is reported as a read error.

new
(
Discard

discard is a [Writer] on which all Write calls succeed without doing anything.

discard
,
Discard

discard is a [Writer] on which all Write calls succeed without doing anything.

discard
)
665 666///| 667pub impl
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
for
struct TeeReader {
  r: &Reader
  w: &Writer
}
TeeReader
with
(self : TeeReader, p : Slice[Byte]) -> (Int, IOError?)
read
(
TeeReader
self
,
Slice[Byte]
p
) {
668 let (
Int
n
,
IOError?
err
) =
TeeReader
self
.
&Reader
r
.
(&Reader, Slice[Byte]) -> (Int, IOError?)
read
(
Slice[Byte]
p
)
669 if
Int
n
(self_ : Int, other : Int) -> Bool
>
0 {
670 let (
Int
n
,
IOError?
err
) =
TeeReader
self
.
&Writer
w
.
(&Writer, Slice[Byte]) -> (Int, IOError?)
write
(
Slice[Byte]
p
[:
Int
n
])
671 if
IOError?
err
(x : IOError?, y : IOError?) -> Bool
!=
IOError?
None
{
672 return (
Int
n
,
IOError?
err
)
673 } 674 } 675 (
Int
n
,
IOError?
err
)
676} 677 678///| 679/// discard is a [Writer] on which all Write calls succeed 680/// without doing anything. 681pub let
Discard

discard is a [Writer] on which all Write calls succeed without doing anything.

discard
:
struct Discard {
}
Discard
=
struct Discard {
}
Discard
::{ }
682 683///| 684/// `discard` satisfies the `Writer` trait. 685let
&Writer

discard satisfies the Writer trait.

_discardIsWriter
: &
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
=
Discard

discard is a [Writer] on which all Write calls succeed without doing anything.

discard
686 687///| 688/// `discard` satisfies the `Reader` trait. 689let
&Reader

discard satisfies the Reader trait.

_discardIsReader
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
=
Discard

discard is a [Writer] on which all Write calls succeed without doing anything.

discard
690 691///| 692struct Discard {} 693 694///| 695pub impl
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
for
struct Discard {
}
Discard
with
(_self : Discard, _b : Slice[Byte]) -> (Int, IOError?)
read
(
Discard
_self
,
Slice[Byte]
_b
) {
696 (0,
(IOError) -> IOError?
Some
(
IOError

eof is the error returned by Read when no more input is available. (Read must return eof itself, not an error wrapping eof, because callers will test for eof using ==.) Functions should return eof only to signal a graceful end of input. If the eof occurs unexpectedly in a structured data stream, the appropriate error is either [err_unexpected_eof] or some other error giving more detail.

eof
))
697} 698 699///| 700/// Discard implements ReaderFrom as an optimization so copy to 701/// io.Discard can avoid doing unnecessary work. 702/// let _ : &ReaderFrom = discard 703pub impl
trait Writer {
  write(Self, Slice[Byte]) -> (Int, IOError?)
}

Writer is the interface that wraps the basic Write method.

Write writes len(p) bytes from p to the underlying data stream. It returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered that caused the write to stop early. Write must return a non-None error if it returns n < len(p). Write must not modify the slice data, even temporarily.

Implementations must not retain p.

Writer
for
struct Discard {
}
Discard
with
(_self : Discard, p : Slice[Byte]) -> (Int, IOError?)

Discard implements ReaderFrom as an optimization so copy to io.Discard can avoid doing unnecessary work. let _ : &ReaderFrom = discard

write
(
Discard
_self
,
Slice[Byte]
p
) {
704 // possible compiler bug - this `pub` should not be needed here but buffer_test.mbt fails if missing. 705 (
Slice[Byte]
p
.
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
(),
IOError?
None
)
706} 707 708///| 709fn
struct Discard {
}
Discard
::
(_self : Discard, r : &Reader) -> (Int64, IOError?)
read_from
(
Discard
_self
:
struct Discard {
}
Discard
,
&Reader
r
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
) -> (
Int64
Int64
,
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
710 let
Slice[Byte]
buf
=
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
::
(buf : Array[Byte], start~ : Int = .., end? : Int) -> Slice[Byte]
new
(
type Array[T]

An Array is a collection of values that supports random access and can grow in size.

Array
::
(Int, Byte) -> Array[Byte]

Creates a new array with a specified length and initializes all elements with the given value.

Parameters:

  • length : The length of the array to create. Must be a non-negative integer.
  • initial_value : The value used to initialize all elements in the array.

Returns a new array of type Array[T] with length elements, where each element is initialized to initial_value.

Throws an error if length is negative.

Example:

test "Array::make" {
  let arr = Array::make(3, 42)
  inspect(arr, content="[42, 42, 42]")
}

test "panic Array::make/negative_length" {
  ignore(Array::make(-1, 0))
}

WARNING: A common pitfall is creating with the same initial value, for example:

test {
  let two_dimension_array = Array::make(10, Array::make(10, 0))
  two_dimension_array[0][5] = 10
  assert_eq(two_dimension_array[5][5], 10)
}

This is because all the cells reference to the same object (the Array[Int] in this case). One should use makei() instead which creates an object for each index.

make
(8192, b'\x00'))
711 let mut
Int64
n
= 0L
712 for { 713 let
(Int, IOError?)
v
=
&Reader
r
.
(&Reader, Slice[Byte]) -> (Int, IOError?)
read
(
Slice[Byte]
buf
)
714
Int64
n
(self : Int64, other : Int64) -> Int64

Adds two 64-bit integers together. Performs overflow checking and wrapping according to two's complement arithmetic.

Parameters:

  • self : The first 64-bit integer operand.
  • other : The second 64-bit integer operand to add to the first.

Returns a new 64-bit integer representing the sum of the two operands.

Example:

test "Int64::op_add" {
  let a = 9223372036854775807L // Int64 maximum value
  let b = 1L
  inspect(a + b, content="-9223372036854775808") // Wraps around to minimum value
  inspect(42L + -42L, content="0")
}
+=
(Int, IOError?)
v
.
Int
0
.
(self : Int) -> Int64

Converts a 32-bit signed integer to a 64-bit signed integer. All 32-bit integers can be represented exactly in 64-bit integer format, so the conversion is lossless.

Parameters:

  • self : The 32-bit signed integer to be converted.

Returns a 64-bit signed integer that represents the same numerical value as the input.

Example:

test "Int::to_int64" {
  let n = 42
  inspect(n.to_int64(), content="42")
  let neg = -42
  inspect(neg.to_int64(), content="-42")
}
to_int64
()
715 let
IOError?
err
=
(Int, IOError?)
v
.
IOError?
1
716 if
IOError?
err
(x : IOError?, y : IOError?) -> Bool
!=
IOError?
None
{
717 if
IOError?
err
(self : IOError?, other : IOError?) -> Bool
==
(IOError) -> IOError?
Some
(
IOError

eof is the error returned by Read when no more input is available. (Read must return eof itself, not an error wrapping eof, because callers will test for eof using ==.) Functions should return eof only to signal a graceful end of input. If the eof occurs unexpectedly in a structured data stream, the appropriate error is either [err_unexpected_eof] or some other error giving more detail.

eof
) {
718 return (
Int64
n
,
IOError?
None
)
719 } 720 return (
Int64
n
,
IOError?
err
)
721 } 722 } 723} 724 725///| 726/// NopCloser::new returns a [ReadCloser] with a no-op Close method wrapping 727/// the provided [Reader] r. 728/// If r implements [WriterTo], the returned [ReadCloser] will implement [WriterTo] 729/// by forwarding calls to r. 730pub fn
struct NopCloser {
  r: &Reader
}
NopCloser
::
(r : &Reader) -> NopCloser

NopCloser::new returns a [ReadCloser] with a no-op Close method wrapping the provided [Reader] r. If r implements [WriterTo], the returned [ReadCloser] will implement [WriterTo] by forwarding calls to r.

new
(
&Reader
r
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
) ->
struct NopCloser {
  r: &Reader
}
NopCloser
{
731 // TODO: 732 // let _, ok := r.(WriterTo) 733 // if ok { 734 // return NopCloserWriterTo{r} 735 // } 736 {
&Reader
r
, }
737} 738 739///| 740/// `NopCloser` satisfies the `ReadCloser` trait. 741let
&ReadCloser

NopCloser satisfies the ReadCloser trait.

_NopCloser
: &
trait ReadCloser {
}

ReadCloser is the interface that groups the basic Read and Close methods.

ReadCloser
=
struct NopCloser {
  r: &Reader
}
NopCloser
::
(r : &Reader) -> NopCloser

NopCloser::new returns a [ReadCloser] with a no-op Close method wrapping the provided [Reader] r. If r implements [WriterTo], the returned [ReadCloser] will implement [WriterTo] by forwarding calls to r.

new
(
struct Buffer {
  mut b: Slice[Byte]
  mut off: Int
}
Buffer
::
(size_hint~ : Int = ..) -> Buffer

Buffer::new creates a new empty Buffer with an optional size hint. The size hint is used to preallocate memory for the buffer, which can improve performance when the size of the data to be written is known in advance.

new
())
742 743///| 744pub impl
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
for
struct NopCloser {
  r: &Reader
}
NopCloser
with
(self : NopCloser, b : Slice[Byte]) -> (Int, IOError?)
read
(
NopCloser
self
,
Slice[Byte]
b
) {
745
NopCloser
self
.
&Reader
r
.
(&Reader, Slice[Byte]) -> (Int, IOError?)
read
(
Slice[Byte]
b
)
746} 747 748///| 749struct NopCloser { 750
&Reader
r
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
751} 752 753///| 754pub impl
trait Closer {
  close(Self) -> IOError?
}

Closer is the interface that wraps the basic Close method.

The behavior of Close after the first call is undefined. Specific implementations may document their own behavior.

Closer
for
struct NopCloser {
  r: &Reader
}
NopCloser
with
(_self : NopCloser) -> IOError?
close
(
NopCloser
_self
) {
755
IOError?
None
756} 757 758// TODO: 759// ///| NopCloserWriterTo is for internal use only. Do not make public. 760// struct NopCloserWriterTo { 761// // TODO: r : &Reader 762// } 763// 764// ///| 765// fn NopCloserWriterTo::close(_self : NopCloserWriterTo) -> IOError? { 766// None 767// } 768 769// TODO: 770// fn write_to(self : NopCloserWriterTo, w : &Writer) -> (Int64, IOEerror?) { 771// // return c.Reader.(WriterTo).WriteTo(w) 772// self.r.write_to(w) 773// } 774 775///| 776/// read_all reads from r until an error or eof and returns the data it read. 777/// A successful call returns err == None, not err == eof. Because read_all is 778/// defined to read from src until eof, it does not treat an eof from Read 779/// as an error to be reported. 780pub fn
(r : &Reader) -> (Slice[Byte], IOError?)

read_all reads from r until an error or eof and returns the data it read. A successful call returns err == None, not err == eof. Because read_all is defined to read from src until eof, it does not treat an eof from Read as an error to be reported.

read_all
(
&Reader
r
: &
trait Reader {
  read(Self, Slice[Byte]) -> (Int, IOError?)
}

Reader is the interface that wraps the basic Read method.

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-None) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == eof or err == None. The next Read should return 0, eof.

Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed eof behaviors.

If len(p) == 0, Read should always return n == 0. It may return a non-None error if some error condition is known, such as eof.

Implementations of Read are discouraged from returning a zero byte count with a None error, except when len(p) == 0. Callers should treat a return of 0 and None as indicating that nothing happened; in particular it does not indicate eof.

Implementations must not retain p.

Reader
) -> (
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
[
Byte
Byte
],
type! IOError String

An IOError can be tested with equality checks.

IOError
?) {
781 let
Int
mb
= 1
(self : Int, other : Int) -> Int

Performs a left shift operation on a 32-bit integer. Shifts each bit in the integer to the left by the specified number of positions, filling the rightmost positions with zeros.

Parameters:

  • self : The integer value to be shifted.
  • shift : The number of positions to shift. Must be a non-negative value less than 32. Values outside this range will be masked with & 31.

Returns a new integer with bits shifted left by the specified number of positions. For each position shifted, the rightmost bit is filled with 0, and the leftmost bit is discarded.

Example:

test "Int::op_shl" {
  let x = 1
  inspect(x << 3, content="8") // Binary: 1 -> 1000
  let y = -4
  inspect(y << 2, content="-16") // Binary: 100 -> 10000
}
<<
20
782 let mut
Int
cap
= 512
783 let mut
Array[Byte]
arr
=
type Array[T]

An Array is a collection of values that supports random access and can grow in size.

Array
::
(Int, Byte) -> Array[Byte]

Creates a new array with a specified length and initializes all elements with the given value.

Parameters:

  • length : The length of the array to create. Must be a non-negative integer.
  • initial_value : The value used to initialize all elements in the array.

Returns a new array of type Array[T] with length elements, where each element is initialized to initial_value.

Throws an error if length is negative.

Example:

test "Array::make" {
  let arr = Array::make(3, 42)
  inspect(arr, content="[42, 42, 42]")
}

test "panic Array::make/negative_length" {
  ignore(Array::make(-1, 0))
}

WARNING: A common pitfall is creating with the same initial value, for example:

test {
  let two_dimension_array = Array::make(10, Array::make(10, 0))
  two_dimension_array[0][5] = 10
  assert_eq(two_dimension_array[5][5], 10)
}

This is because all the cells reference to the same object (the Array[Int] in this case). One should use makei() instead which creates an object for each index.

make
(
Int
cap
, b'\x00')
784 let mut
Slice[Byte]
b
=
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
::
(buf : Array[Byte], end~ : Int, start~ : Int = ..) -> Slice[Byte]
new
(
Array[Byte]
arr
,
Int
end
=0)
785 for { 786 let (
Int
n
,
IOError?
err
) =
&Reader
r
.
(&Reader, Slice[Byte]) -> (Int, IOError?)
read
(
Slice[Byte]
b
[
Slice[Byte]
b
.
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
():
Int
cap
])
787 let mut
IOError?
err
=
IOError?
err
788
Slice[Byte]
b
=
Slice[Byte]
b
[:
Slice[Byte]
b
.
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
()
(self : Int, other : Int) -> Int

Adds two 32-bit signed integers. Performs two's complement arithmetic, which means the operation will wrap around if the result exceeds the range of a 32-bit integer.

Parameters:

  • self : The first integer operand.
  • other : The second integer operand.

Returns a new integer that is the sum of the two operands. If the mathematical sum exceeds the range of a 32-bit integer (-2,147,483,648 to 2,147,483,647), the result wraps around according to two's complement rules.

Example:

test "Int::op_add" {
  inspect(42 + 1, content="43")
  inspect(2147483647 + 1, content="-2147483648") // Overflow wraps around to minimum value
}
+
Int
n
]
789 if
IOError?
err
(x : IOError?, y : IOError?) -> Bool
!=
IOError?
None
{
790 if
IOError?
err
(self : IOError?, other : IOError?) -> Bool
==
(IOError) -> IOError?
Some
(
IOError

eof is the error returned by Read when no more input is available. (Read must return eof itself, not an error wrapping eof, because callers will test for eof using ==.) Functions should return eof only to signal a graceful end of input. If the eof occurs unexpectedly in a structured data stream, the appropriate error is either [err_unexpected_eof] or some other error giving more detail.

eof
) {
791
IOError?
err
=
IOError?
None
792 } 793 return (
Slice[Byte]
b
,
IOError?
err
)
794 } 795 if
Slice[Byte]
b
.
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
()
(self : Int, other : Int) -> Bool

Compares two integers for equality.

Parameters:

  • self : The first integer to compare.
  • other : The second integer to compare.

Returns true if both integers have the same value, false otherwise.

Example:

test "Int::op_equal" {
  inspect(42 == 42, content="true")
  inspect(42 == -42, content="false")
}
==
Int
cap
{
796 if
Int
cap
(self_ : Int, other : Int) -> Bool
<
Int
mb
{
797 // naive doubling of memory up until 1<<20 798
Int
cap
(self : Int, other : Int) -> Int

Multiplies two 32-bit integers. This is the implementation of the * operator for Int.

Parameters:

  • self : The first integer operand.
  • other : The second integer operand.

Returns the product of the two integers. If the result overflows the range of Int, it wraps around according to two's complement arithmetic.

Example:

test "Int::op_mul" {
  inspect(42 * 2, content="84")
  inspect(-10 * 3, content="-30")
  let max = 2147483647 // Int.max_value
  inspect(max * 2, content="-2") // Overflow wraps around
}
*=
2
799 } else { 800 // thereafter, just add another 1<<20 801
Int
cap
(self : Int, other : Int) -> Int

Adds two 32-bit signed integers. Performs two's complement arithmetic, which means the operation will wrap around if the result exceeds the range of a 32-bit integer.

Parameters:

  • self : The first integer operand.
  • other : The second integer operand.

Returns a new integer that is the sum of the two operands. If the mathematical sum exceeds the range of a 32-bit integer (-2,147,483,648 to 2,147,483,647), the result wraps around according to two's complement rules.

Example:

test "Int::op_add" {
  inspect(42 + 1, content="43")
  inspect(2147483647 + 1, content="-2147483648") // Overflow wraps around to minimum value
}
+=
Int
mb
802 } 803 let
Array[Byte]
new_arr
=
type Array[T]

An Array is a collection of values that supports random access and can grow in size.

Array
::
(capacity~ : Int) -> Array[Byte]

Creates a new empty array with an optional initial capacity.

Parameters:

  • capacity : The initial capacity of the array. If 0 (default), creates an array with minimum capacity. Must be non-negative.

Returns a new empty array of type Array[T] with the specified initial capacity.

Example:

test "Array::new" {
  let arr : Array[Int] = Array::new(capacity=10)
  inspect(arr.length(), content="0")
  inspect(arr.capacity(), content="10")
}

test "Array::new/default" {
  let arr : Array[Int] = Array::new()
  inspect(arr.length(), content="0")
}
new
(
Int
capacity
=
Int
cap
)
804 // Array::unsafe_blit(new_arr, 0, arr, 0, b.length()) // Doesn't work on wasm, wasm-gc, native 805 for
Int
i
in
Int
0
..<
Slice[Byte]
b
.
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
() {
806
Array[Byte]
new_arr
.
(self : Array[Byte], value : Byte) -> Unit

Adds an element to the end of the array.

If the array is at capacity, it will be reallocated.

Example

let v = []
v.push(3)
push
(
Array[Byte]
arr
(Array[Byte], Int) -> Byte

Retrieves an element from the array at the specified index.

Parameters:

  • array : The array to get the element from.
  • index : The position in the array from which to retrieve the element.

Returns the element at the specified index.

Throws a panic if the index is negative or greater than or equal to the length of the array.

Example:

test "Array::op_get" {
  let arr = [1, 2, 3]
  inspect(arr[1], content="2")
}

test "panic Array::op_get/out_of_bounds" {
  let arr = [1, 2, 3]
  ignore(arr[3]) // Index out of bounds
}
[
i])
807 } 808
Array[Byte]
arr
=
Array[Byte]
new_arr
809
Slice[Byte]
b
=
struct Slice[T] {
  buf: Array[T]
  start: Int
  len: Int
}

A Slice is a slice of an Array.

A separate Slice type was needed because of this issue: https://github.com/moonbitlang/core/issues/1063

This struct is based on MoonBit's "ArrayView" implementation here: https://github.com/moonbitlang/core/blob/main/builtin/arrayview.mbt which has the following copyright:

Copyright 2024 International Digital Economy Academy

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Slice
::
(buf : Array[Byte], start~ : Int = .., end? : Int) -> Slice[Byte]
new
(
Array[Byte]
arr
)[:
Slice[Byte]
b
.
(self : Slice[Byte]) -> Int

length returns the length of the slice.

length
()]
810 } 811 } 812} 813