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