diff --git a/external/gojo/builtins/__init__.mojo b/external/gojo/builtins/__init__.mojo index 300e09b..3d1e11a 100644 --- a/external/gojo/builtins/__init__.mojo +++ b/external/gojo/builtins/__init__.mojo @@ -1,6 +1,5 @@ from .bytes import Byte, index_byte, has_suffix, has_prefix, to_string from .list import equals -from .result import Result, WrappedError from .attributes import cap, copy from .errors import exit, panic diff --git a/external/gojo/builtins/errors.mojo b/external/gojo/builtins/errors.mojo index 6488453..1c1a7ba 100644 --- a/external/gojo/builtins/errors.mojo +++ b/external/gojo/builtins/errors.mojo @@ -1,8 +1,4 @@ -fn exit(code: Int): - """Exits the program with the given exit code via libc. - TODO: Using this in the meantime until Mojo has a built in way to panic/exit. - """ - var status = external_call["exit", Int, Int](code) +from sys import exit fn panic[T: Stringable](message: T, code: Int = 1): diff --git a/external/gojo/builtins/result.mojo b/external/gojo/builtins/result.mojo deleted file mode 100644 index 38db539..0000000 --- a/external/gojo/builtins/result.mojo +++ /dev/null @@ -1,51 +0,0 @@ -from collections.optional import Optional - - -@value -struct WrappedError(CollectionElement, Stringable): - """Wrapped Error struct is just to enable the use of optional Errors.""" - - var error: Error - - fn __init__(inout self, error: Error): - self.error = error - - fn __init__[T: Stringable](inout self, message: T): - self.error = Error(message) - - fn __str__(self) -> String: - return str(self.error) - - -alias ValuePredicateFn = fn[T: CollectionElement] (value: T) -> Bool -alias ErrorPredicateFn = fn (error: Error) -> Bool - - -@value -struct Result[T: CollectionElement](): - var value: T - var error: Optional[WrappedError] - - fn __init__( - inout self, - value: T, - error: Optional[WrappedError] = None, - ): - self.value = value - self.error = error - - fn has_error(self) -> Bool: - if self.error: - return True - return False - - fn has_error_and(self, f: ErrorPredicateFn) -> Bool: - if self.error: - return f(self.error.value().error) - return False - - fn get_error(self) -> Optional[WrappedError]: - return self.error - - fn unwrap_error(self) -> WrappedError: - return self.error.value().error diff --git a/external/gojo/bytes/buffer.mojo b/external/gojo/bytes/buffer.mojo index bf0de48..89582d3 100644 --- a/external/gojo/bytes/buffer.mojo +++ b/external/gojo/bytes/buffer.mojo @@ -1,4 +1,3 @@ -from collections.optional import Optional from ..io import ( Reader, Writer, @@ -10,7 +9,7 @@ from ..io import ( ReaderFrom, BUFFER_SIZE, ) -from ..builtins import cap, copy, Byte, Result, WrappedError, panic, index_byte +from ..builtins import cap, copy, Byte, panic, index_byte alias Rune = Int32 @@ -148,8 +147,7 @@ struct Buffer( fn try_grow_by_reslice(inout self, n: Int) -> (Int, Bool): """Inlineable version of grow for the fast-case where the internal buffer only needs to be resliced. - It returns the index where bytes should be written and whether it succeeded. - """ + It returns the index where bytes should be written and whether it succeeded.""" var buffer_already_used = len(self.buf) if n <= self.buf.capacity - buffer_already_used: @@ -218,7 +216,7 @@ struct Buffer( var m = self.grow(n) self.buf = self.buf[:m] - fn write(inout self, src: List[Byte]) -> Result[Int]: + fn write(inout self, src: List[Byte]) -> (Int, Error): """Appends the contents of p to the buffer, growing the buffer as needed. The return value n is the length of p; err is always nil. If the buffer becomes too large, write will panic with [ERR_TOO_LARGE]. @@ -237,9 +235,9 @@ struct Buffer( write_at = self.grow(len(src)) var bytes_written = copy(self.buf, src, write_at) - return Result(bytes_written, None) + return bytes_written, Error() - fn write_string(inout self, src: String) -> Result[Int]: + fn write_string(inout self, src: String) -> (Int, Error): """Appends the contents of s to the buffer, growing the buffer as needed. The return value n is the length of s; err is always nil. If the buffer becomes too large, write_string will panic with [ERR_TOO_LARGE]. @@ -259,7 +257,7 @@ struct Buffer( # var b = self.buf[m:] return self.write(src.as_bytes()) - fn read_from[R: Reader](inout self, inout reader: R) -> Result[Int64]: + fn read_from[R: Reader](inout self, inout reader: R) -> (Int64, Error): """Reads data from r until EOF and appends it to the buffer, growing the buffer as needed. The return value n is the number of bytes read. Any error except io.EOF encountered during the read is also returned. If the @@ -276,19 +274,20 @@ struct Buffer( while True: _ = self.grow(MIN_READ) - var result = reader.read(self.buf) - var bytes_read = result.value + var bytes_read: Int + var err: Error + bytes_read, err = reader.read(self.buf) if bytes_read < 0: panic(ERR_NEGATIVE_READ) total_bytes_read += bytes_read - if result.has_error(): - var error = result.get_error() - if String(error.value()) == io.EOF: - return Result(total_bytes_read, None) + var err_message = str(err) + if err_message != "": + if err_message == io.EOF: + return total_bytes_read, Error() - return Result(total_bytes_read, error) + return total_bytes_read, err fn grow_slice(self, inout b: List[Byte], n: Int) -> List[Byte]: """Grows b by n, preserving the original content of self. @@ -319,7 +318,7 @@ struct Buffer( # b._vector.reserve(c) return resized_buffer[: b.capacity] - fn write_to[W: Writer](inout self, inout writer: W) -> Result[Int64]: + fn write_to[W: Writer](inout self, inout writer: W) -> (Int64, Error): """Writes data to w until the buffer is drained or an error occurs. The return value n is the number of bytes written; it always fits into an Int, but it is int64 to match the io.WriterTo trait. Any error @@ -338,27 +337,28 @@ struct Buffer( if bytes_to_write > 0: # TODO: Replace usage of this intermeidate slice when normal slicing, once slice references work. var sl = self.buf[self.off : bytes_to_write] - var result = writer.write(sl) - var bytes_written = result.value + var bytes_written: Int + var err: Error + bytes_written, err = writer.write(sl) if bytes_written > bytes_to_write: panic("bytes.Buffer.write_to: invalid write count") self.off += bytes_written total_bytes_written = Int64(bytes_written) - if result.has_error(): - var error = result.get_error() - return Result(total_bytes_written, error) + var err_message = str(err) + if err_message != "": + return total_bytes_written, err # all bytes should have been written, by definition of write method in io.Writer if bytes_written != bytes_to_write: - return Result(total_bytes_written, WrappedError(ERR_SHORT_WRITE)) + return total_bytes_written, Error(ERR_SHORT_WRITE) # Buffer is now empty; reset. self.reset() - return Result(total_bytes_written, None) + return total_bytes_written, Error() - fn write_byte(inout self, byte: Byte) -> Result[Int]: + fn write_byte(inout self, byte: Byte) -> (Int, Error): """Appends the byte c to the buffer, growing the buffer as needed. The returned error is always nil, but is included to match [bufio.Writer]'s write_byte. If the buffer becomes too large, write_byte will panic with @@ -378,7 +378,7 @@ struct Buffer( write_at = self.grow(1) _ = copy(self.buf, List[Byte](byte), write_at) - return Result(write_at, None) + return write_at, Error() # fn write_rune(inout self, r: Rune) -> Int: # """Appends the UTF-8 encoding of Unicode code point r to the @@ -401,7 +401,7 @@ struct Buffer( # self.buf = utf8.AppendRune(self.buf[:write_at], r) # return len(self.buf) - write_at - fn read(inout self, inout dest: List[Byte]) -> Result[Int]: + fn read(inout self, inout dest: List[Byte]) -> (Int, Error): """Reads the next len(dest) bytes from the buffer or until the buffer is drained. The return value n is the number of bytes read. If the buffer has no data to return, err is io.EOF (unless len(dest) is zero); @@ -418,15 +418,15 @@ struct Buffer( # Buffer is empty, reset to recover space. self.reset() if dest.capacity == 0: - return Result(0, None) - return Result(0, WrappedError(io.EOF)) + return 0, Error() + return 0, Error(io.EOF) var bytes_read = copy(dest, self.buf[self.off : len(self.buf)]) self.off += bytes_read if bytes_read > 0: self.last_read = OP_READ - return Result(bytes_read, None) + return bytes_read, Error() fn next(inout self, number_of_bytes: Int) raises -> List[Byte]: """Returns a slice containing the next n bytes from the buffer, @@ -453,20 +453,20 @@ struct Buffer( return data - fn read_byte(inout self) -> Result[Byte]: + fn read_byte(inout self) -> (Byte, Error): """Reads and returns the next byte from the buffer. If no byte is available, it returns error io.EOF. """ if self.empty(): # Buffer is empty, reset to recover space. self.reset() - return Result(Byte(0), WrappedError(io.EOF)) + return Byte(0), Error(io.EOF) var byte = self.buf[self.off] self.off += 1 self.last_read = OP_READ - return byte + return byte, Error() # read_rune reads and returns the next UTF-8-encoded # Unicode code point from the buffer. @@ -508,22 +508,22 @@ struct Buffer( # var err_unread_byte = errors.New("buffer.Buffer: unread_byte: previous operation was not a successful read") - fn unread_byte(inout self) -> Optional[WrappedError]: + fn unread_byte(inout self) -> Error: """Unreads the last byte returned by the most recent successful read operation that read at least one byte. If a write has happened since the last read, if the last read returned an error, or if the read read zero bytes, unread_byte returns an error. """ if self.last_read == OP_INVALID: - return WrappedError("buffer.Buffer: unread_byte: previous operation was not a successful read") + return Error("buffer.Buffer: unread_byte: previous operation was not a successful read") self.last_read = OP_INVALID if self.off > 0: self.off -= 1 - return None + return Error() - fn read_bytes(inout self, delim: Byte) -> Result[List[Byte]]: + fn read_bytes(inout self, delim: Byte) -> (List[Byte], Error): """Reads until the first occurrence of delim in the input, returning a slice containing the data up to and including the delimiter. If read_bytes encounters an error before finding a delimiter, @@ -537,20 +537,19 @@ struct Buffer( Returns: A List[Byte] struct containing the data up to and including the delimiter. """ - var result = self.read_slice(delim) - var slice = result.value + var slice: List[Byte] + var err: Error + slice, err = self.read_slice(delim) # return a copy of slice. The buffer's backing array may # be overwritten by later calls. var line = List[Byte](capacity=BUFFER_SIZE) for i in range(len(slice)): line.append(slice[i]) - return line + return line, Error() - fn read_slice(inout self, delim: Byte) -> Result[List[Byte]]: + fn read_slice(inout self, delim: Byte) -> (List[Byte], Error): """Like read_bytes but returns a reference to internal buffer data. - TODO: not returning a reference yet. Also, this returns List[Byte] and Error in Go, - but we arent't returning Errors as values until Mojo tuple returns supports Memory Only types. Args: delim: The delimiter to read until. @@ -571,11 +570,11 @@ struct Buffer( self.last_read = OP_READ if at_eof: - return Result(line, WrappedError(io.EOF)) + return line, Error(io.EOF) - return Result(line, None) + return line, Error() - fn read_string(inout self, delim: Byte) -> Result[String]: + fn read_string(inout self, delim: Byte) -> (String, Error): """Reads until the first occurrence of delim in the input, returning a string containing the data up to and including the delimiter. If read_string encounters an error before finding a delimiter, @@ -589,8 +588,10 @@ struct Buffer( Returns: A string containing the data up to and including the delimiter. """ - var result = self.read_slice(delim) - return Result(String(result.value), result.get_error()) + var slice: List[Byte] + var err: Error + slice, err = self.read_slice(delim) + return String(slice), err fn new_buffer() -> Buffer: diff --git a/external/gojo/bytes/reader.mojo b/external/gojo/bytes/reader.mojo index 3af1d1e..9539672 100644 --- a/external/gojo/bytes/reader.mojo +++ b/external/gojo/bytes/reader.mojo @@ -1,5 +1,5 @@ from collections.optional import Optional -from ..builtins import cap, copy, Byte, Result, WrappedError, panic +from ..builtins import cap, copy, Byte, panic import ..io @@ -39,7 +39,7 @@ struct Reader( The result is unaffected by any method calls except [Reader.Reset].""" return len(self.buffer) - fn read(inout self, inout dest: List[Byte]) -> Result[Int]: + fn read(inout self, inout dest: List[Byte]) -> (Int, Error): """Reads from the internal buffer into the dest List[Byte] struct. Implements the [io.Reader] Interface. @@ -49,16 +49,16 @@ struct Reader( Returns: Int: The number of bytes read into dest.""" if self.index >= len(self.buffer): - return Result(0, WrappedError(io.EOF)) + return 0, Error(io.EOF) self.prev_rune = -1 var unread_bytes = self.buffer[int(self.index) : len(self.buffer)] var bytes_read = copy(dest, unread_bytes) self.index += bytes_read - return Result(bytes_read) + return bytes_read, Error() - fn read_at(self, inout dest: List[Byte], off: Int64) -> Result[Int]: + fn read_at(self, inout dest: List[Byte], off: Int64) -> (Int, Error): """Reads len(dest) bytes into dest beginning at byte offset off. Implements the [io.ReaderAt] Interface. @@ -71,39 +71,39 @@ struct Reader( """ # cannot modify state - see io.ReaderAt if off < 0: - return Result(0, WrappedError("bytes.Reader.read_at: negative offset")) + return 0, Error("bytes.Reader.read_at: negative offset") if off >= Int64(len(self.buffer)): - return Result(0, WrappedError(io.EOF)) + return 0, Error(io.EOF) var unread_bytes = self.buffer[int(off) : len(self.buffer)] var bytes_written = copy(dest, unread_bytes) if bytes_written < len(dest): - return Result(0, WrappedError(io.EOF)) + return 0, Error(io.EOF) - return bytes_written + return bytes_written, Error() - fn read_byte(inout self) -> Result[Byte]: + fn read_byte(inout self) -> (Byte, Error): """Reads and returns a single byte from the internal buffer. Implements the [io.ByteReader] Interface.""" self.prev_rune = -1 if self.index >= len(self.buffer): - return Result(Int8(0), WrappedError(io.EOF)) + return Int8(0), Error(io.EOF) var byte = self.buffer[int(self.index)] self.index += 1 - return byte + return byte, Error() - fn unread_byte(inout self) -> Optional[WrappedError]: + fn unread_byte(inout self) -> Error: """Unreads the last byte read by moving the read position back by one. Complements [Reader.read_byte] in implementing the [io.ByteScanner] Interface. """ if self.index <= 0: - return WrappedError("bytes.Reader.unread_byte: at beginning of slice") + return Error("bytes.Reader.unread_byte: at beginning of slice") self.prev_rune = -1 self.index -= 1 - return None + return Error() # # read_rune implements the [io.RuneReader] Interface. # fn read_rune(self) (ch rune, size Int, err error): @@ -132,7 +132,7 @@ struct Reader( # self.prev_rune = -1 # return nil - fn seek(inout self, offset: Int64, whence: Int) -> Result[Int64]: + fn seek(inout self, offset: Int64, whence: Int) -> (Int64, Error): """Moves the read position to the specified offset from the specified whence. Implements the [io.Seeker] Interface. @@ -153,15 +153,15 @@ struct Reader( elif whence == io.SEEK_END: position = len(self.buffer) + offset else: - return Result(Int64(0), WrappedError("bytes.Reader.seek: invalid whence")) + return Int64(0), Error("bytes.Reader.seek: invalid whence") if position < 0: - return Result(Int64(0), WrappedError("bytes.Reader.seek: negative position")) + return Int64(0), Error("bytes.Reader.seek: negative position") self.index = position - return Result(position, None) + return position, Error() - fn write_to[W: io.Writer](inout self, inout writer: W) -> Result[Int64]: + fn write_to[W: io.Writer](inout self, inout writer: W) -> (Int64, Error): """Writes data to w until the buffer is drained or an error occurs. implements the [io.WriterTo] Interface. @@ -170,19 +170,20 @@ struct Reader( """ self.prev_rune = -1 if self.index >= len(self.buffer): - return Result(Int64(0), None) + return Int64(0), Error() var bytes = self.buffer[int(self.index) : len(self.buffer)] - var result = writer.write(bytes) - var write_count = result.value + var write_count: Int + var err: Error + write_count, err = writer.write(bytes) if write_count > len(bytes): panic("bytes.Reader.write_to: invalid Write count") self.index += write_count if write_count != len(bytes): - return Result(Int64(write_count), WrappedError(io.ERR_SHORT_WRITE)) + return Int64(write_count), Error(io.ERR_SHORT_WRITE) - return Int64(write_count) + return Int64(write_count), Error() fn reset(inout self, buffer: List[Byte]): """Resets the [Reader.Reader] to be reading from b. diff --git a/external/gojo/io/io.mojo b/external/gojo/io/io.mojo index de19555..338da66 100644 --- a/external/gojo/io/io.mojo +++ b/external/gojo/io/io.mojo @@ -1,12 +1,12 @@ from collections.optional import Optional -from ..builtins import cap, copy, Byte, Result, WrappedError, panic +from ..builtins import cap, copy, Byte, Error, panic from .traits import ERR_UNEXPECTED_EOF alias BUFFER_SIZE = 4096 -fn write_string[W: Writer](inout writer: W, string: String) -> Result[Int]: +fn write_string[W: Writer](inout writer: W, string: String) -> (Int, Error): """Writes the contents of the string s to w, which accepts a slice of bytes. If w implements [StringWriter], [StringWriter.write_string] is invoked directly. Otherwise, [Writer.write] is called exactly once. @@ -21,7 +21,7 @@ fn write_string[W: Writer](inout writer: W, string: String) -> Result[Int]: return writer.write(string.as_bytes()) -fn write_string[W: StringWriter](inout writer: W, string: String) -> Result[Int]: +fn write_string[W: StringWriter](inout writer: W, string: String) -> (Int, Error): """Writes the contents of the string s to w, which accepts a slice of bytes. If w implements [StringWriter], [StringWriter.write_string] is invoked directly. Otherwise, [Writer.write] is called exactly once. @@ -35,7 +35,7 @@ fn write_string[W: StringWriter](inout writer: W, string: String) -> Result[Int] return writer.write_string(string) -fn read_at_least[R: Reader](inout reader: R, inout dest: List[Byte], min: Int) -> Result[Int]: +fn read_at_least[R: Reader](inout reader: R, inout dest: List[Byte], min: Int) -> (Int, Error): """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. @@ -52,26 +52,26 @@ fn read_at_least[R: Reader](inout reader: R, inout dest: List[Byte], min: Int) - Returns: The number of bytes read.""" - var error: Optional[WrappedError] = None + var error = Error() if len(dest) < min: - return Result(0, WrappedError(io.ERR_SHORT_BUFFER)) + return 0, Error(io.ERR_SHORT_BUFFER) var total_bytes_read: Int = 0 while total_bytes_read < min and not error: - var result = reader.read(dest) - var bytes_read = result.value - var error = result.get_error() + var bytes_read: Int + bytes_read, error = reader.read(dest) total_bytes_read += bytes_read if total_bytes_read >= min: - error = None - elif total_bytes_read > 0 and str(error.value()): - error = WrappedError(ERR_UNEXPECTED_EOF) + error = Error() - return Result(total_bytes_read, None) + elif total_bytes_read > 0 and str(error): + error = Error(ERR_UNEXPECTED_EOF) + return total_bytes_read, error -fn read_full[R: Reader](inout reader: R, inout dest: List[Byte]) -> Result[Int]: + +fn read_full[R: Reader](inout reader: R, inout dest: List[Byte]) -> (Int, Error): """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. @@ -407,7 +407,7 @@ fn read_full[R: Reader](inout reader: R, inout dest: List[Byte]) -> Result[Int]: # } -fn read_all[R: Reader](inout reader: R) -> Result[List[Byte]]: +fn read_all[R: Reader](inout reader: R) -> (List[Byte], Error): """Reads from r until an error or EOF and returns the data it read. A successful call returns err == nil, not err == EOF. Because ReadAll is defined to read from src until EOF, it does not treat an EOF from Read @@ -424,12 +424,13 @@ fn read_all[R: Reader](inout reader: R) -> Result[List[Byte]]: while True: var temp = List[Byte](capacity=BUFFER_SIZE) - var result = reader.read(temp) - var bytes_read = result.value - var err = result.get_error() - if err: - if str(err.value()) != EOF: - return Result(dest, err) + var bytes_read: Int + var err: Error + bytes_read, err = reader.read(temp) + var err_message = str(err) + if err_message != "": + if err_message != EOF: + return dest, err at_eof = True @@ -440,4 +441,4 @@ fn read_all[R: Reader](inout reader: R) -> Result[List[Byte]]: dest.extend(temp) if at_eof: - return Result(dest, err.value()) + return dest, err diff --git a/external/gojo/io/traits.mojo b/external/gojo/io/traits.mojo index 7b9f4d6..0fa248c 100644 --- a/external/gojo/io/traits.mojo +++ b/external/gojo/io/traits.mojo @@ -1,5 +1,5 @@ from collections.optional import Optional -from ..builtins import Byte, Result, WrappedError +from ..builtins import Byte, Error alias Rune = Int32 @@ -78,7 +78,7 @@ trait Reader(Movable): Implementations must not retain p.""" - fn read(inout self, inout dest: List[Byte]) -> Result[Int]: + fn read(inout self, inout dest: List[Byte]) -> (Int, Error): ... @@ -94,7 +94,7 @@ trait Writer(Movable): Implementations must not retain p. """ - fn write(inout self, src: List[Byte]) -> Result[Int]: + fn write(inout self, src: List[Byte]) -> (Int, Error): ... @@ -106,7 +106,7 @@ trait Closer(Movable): Specific implementations may document their own behavior. """ - fn close(inout self) raises: + fn close(inout self) -> Error: ... @@ -129,7 +129,7 @@ trait Seeker(Movable): is implementation-dependent. """ - fn seek(inout self, offset: Int64, whence: Int) -> Result[Int64]: + fn seek(inout self, offset: Int64, whence: Int) -> (Int64, Error): ... @@ -174,7 +174,7 @@ trait ReaderFrom: The [copy] function uses [ReaderFrom] if available.""" - fn read_from[R: Reader](inout self, inout reader: R) -> Result[Int64]: + fn read_from[R: Reader](inout self, inout reader: R) -> (Int64, Error): ... @@ -191,7 +191,7 @@ trait WriterTo: The copy function uses WriterTo if available.""" - fn write_to[W: Writer](inout self, inout writer: W) -> Result[Int64]: + fn write_to[W: Writer](inout self, inout writer: W) -> (Int64, Error): ... @@ -227,7 +227,7 @@ trait ReaderAt: Implementations must not retain p.""" - fn read_at(self, inout dest: List[Byte], off: Int64) -> Result[Int]: + fn read_at(self, inout dest: List[Byte], off: Int64) -> (Int, Error): ... @@ -248,7 +248,7 @@ trait WriterAt: Implementations must not retain p.""" - fn write_at(self, src: List[Byte], off: Int64) -> Result[Int]: + fn write_at(self, src: List[Byte], off: Int64) -> (Int, Error): ... @@ -263,7 +263,7 @@ trait ByteReader: processing. A [Reader] that does not implement ByteReader can be wrapped using bufio.NewReader to add this method.""" - fn read_byte(inout self) -> Result[Byte]: + fn read_byte(inout self) -> (Byte, Error): ... @@ -277,14 +277,14 @@ trait ByteScanner(ByteReader): last-unread byte), or (in implementations that support the [Seeker] trait) seek to one byte before the current offset.""" - fn unread_byte(inout self) -> Optional[WrappedError]: + fn unread_byte(inout self) -> Error: ... trait ByteWriter: """ByteWriter is the trait that wraps the write_byte method.""" - fn write_byte(inout self, byte: Byte) -> Result[Int]: + fn write_byte(inout self, byte: Byte) -> (Int, Error): ... @@ -316,5 +316,5 @@ trait RuneScanner(RuneReader): trait StringWriter: """StringWriter is the trait that wraps the WriteString method.""" - fn write_string(inout self, src: String) -> Result[Int]: + fn write_string(inout self, src: String) -> (Int, Error): ... diff --git a/external/gojo/strings/builder.mojo b/external/gojo/strings/builder.mojo index 520fd0c..e7a76ed 100644 --- a/external/gojo/strings/builder.mojo +++ b/external/gojo/strings/builder.mojo @@ -2,7 +2,7 @@ # Modified to use List[Int8] instead of List[String] import ..io -from ..builtins import Byte, Result, WrappedError +from ..builtins import Byte @value @@ -10,7 +10,7 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite """ A string builder class that allows for efficient string management and concatenation. This class is useful when you need to build a string by appending multiple strings - together. It is around 10x faster than using the `+` operator to concatenate + together. It is around 20x faster than using the `+` operator to concatenate strings because it avoids the overhead of creating and destroying many intermediate strings and performs memcopy operations. @@ -24,15 +24,15 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite from strings.builder import StringBuilder var sb = StringBuilder() - sb.append("mojo") - sb.append("jojo") + sb.write_string("mojo") + sb.write_string("jojo") print(sb) # mojojojo ``` """ var _vector: List[Byte] - fn __init__(inout self, size: Int = 4096): + fn __init__(inout self, *, size: Int = 4096): self._vector = List[Byte](capacity=size) fn __str__(self) -> String: @@ -70,7 +70,7 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite return copy - fn write(inout self, src: List[Byte]) -> Result[Int]: + fn write(inout self, src: List[Byte]) -> (Int, Error): """ Appends a byte array to the builder buffer. @@ -78,9 +78,9 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite src: The byte array to append. """ self._vector.extend(src) - return Result(len(src), None) + return len(src), Error() - fn write_byte(inout self, byte: Int8) -> Result[Int]: + fn write_byte(inout self, byte: Int8) -> (Int, Error): """ Appends a byte array to the builder buffer. @@ -88,9 +88,9 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite byte: The byte array to append. """ self._vector.append(byte) - return Result(1, None) + return 1, Error() - fn write_string(inout self, src: String) -> Result[Int]: + fn write_string(inout self, src: String) -> (Int, Error): """ Appends a string to the builder buffer. @@ -99,7 +99,7 @@ struct StringBuilder(Stringable, Sized, io.Writer, io.ByteWriter, io.StringWrite """ var string_buffer = src.as_bytes() self._vector.extend(string_buffer) - return Result(len(string_buffer), None) + return len(string_buffer), Error() fn __len__(self) -> Int: """ diff --git a/external/gojo/strings/reader.mojo b/external/gojo/strings/reader.mojo index cd12b6c..8d8af28 100644 --- a/external/gojo/strings/reader.mojo +++ b/external/gojo/strings/reader.mojo @@ -1,18 +1,9 @@ import ..io -from collections.optional import Optional -from ..builtins import Byte, copy, Result, panic, WrappedError +from ..builtins import Byte, copy, panic @value -struct Reader( - Sized, - io.Reader, - io.ReaderAt, - io.ByteReader, - io.ByteScanner, - io.Seeker, - io.WriterTo, -): +struct Reader(Sized, io.Reader, io.ReaderAt, io.ByteReader, io.ByteScanner, io.Seeker, io.WriterTo): """A Reader that implements the [io.Reader], [io.ReaderAt], [io.ByteReader], [io.ByteScanner], [io.Seeker], and [io.WriterTo] traits by reading from a string. The zero value for Reader operates like a Reader of an empty string. """ @@ -48,7 +39,7 @@ struct Reader( """ return Int64(len(self.string)) - fn read(inout self, inout dest: List[Byte]) -> Result[Int]: + fn read(inout self, inout dest: List[Byte]) -> (Int, Error): """Reads from the underlying string into the provided List[Byte] object. Implements the [io.Reader] trait. @@ -59,14 +50,14 @@ struct Reader( The number of bytes read into dest. """ if self.read_pos >= Int64(len(self.string)): - return Result(0, WrappedError(io.EOF)) + return 0, Error(io.EOF) self.prev_rune = -1 var bytes_written = copy(dest, self.string[int(self.read_pos) :].as_bytes()) self.read_pos += Int64(bytes_written) - return bytes_written + return bytes_written, Error() - fn read_at(self, inout dest: List[Byte], off: Int64) -> Result[Int]: + fn read_at(self, inout dest: List[Byte], off: Int64) -> (Int, Error): """Reads from the Reader into the dest List[Byte] starting at the offset off. It returns the number of bytes read into dest and an error if any. Implements the [io.ReaderAt] trait. @@ -80,19 +71,19 @@ struct Reader( """ # cannot modify state - see io.ReaderAt if off < 0: - return Result(0, WrappedError("strings.Reader.read_at: negative offset")) + return 0, Error("strings.Reader.read_at: negative offset") if off >= Int64(len(self.string)): - return Result(0, WrappedError(io.EOF)) + return 0, Error(io.EOF) - var error: Optional[WrappedError] = None + var error = Error() var copied_elements_count = copy(dest, self.string[int(off) :].as_bytes()) if copied_elements_count < len(dest): - error = WrappedError(io.EOF) + error = Error(io.EOF) - return copied_elements_count + return copied_elements_count, Error() - fn read_byte(inout self) -> Result[Byte]: + fn read_byte(inout self) -> (Byte, Error): """Reads the next byte from the underlying string. Implements the [io.ByteReader] trait. @@ -101,23 +92,23 @@ struct Reader( """ self.prev_rune = -1 if self.read_pos >= Int64(len(self.string)): - return Result(Byte(0), WrappedError(io.EOF)) + return Byte(0), Error(io.EOF) var b = self.string[int(self.read_pos)] self.read_pos += 1 - return Result(Byte(ord(b)), None) + return Byte(ord(b)), Error() - fn unread_byte(inout self) -> Optional[WrappedError]: + fn unread_byte(inout self) -> Error: """Unreads the last byte read. Only the most recent byte read can be unread. Implements the [io.ByteScanner] trait. """ if self.read_pos <= 0: - return WrappedError("strings.Reader.unread_byte: at beginning of string") + return Error("strings.Reader.unread_byte: at beginning of string") self.prev_rune = -1 self.read_pos -= 1 - return None + return Error() # # read_rune implements the [io.RuneReader] trait. # fn read_rune() (ch rune, size int, err error): @@ -146,7 +137,7 @@ struct Reader( # self.prev_rune = -1 # return nil - fn seek(inout self, offset: Int64, whence: Int) -> Result[Int64]: + fn seek(inout self, offset: Int64, whence: Int) -> (Int64, Error): """Seeks to a new position in the underlying string. The next read will start from that position. Implements the [io.Seeker] trait. @@ -167,15 +158,15 @@ struct Reader( elif whence == io.SEEK_END: position = Int64(len(self.string)) + offset else: - return Result(Int64(0), WrappedError("strings.Reader.seek: invalid whence")) + return Int64(0), Error("strings.Reader.seek: invalid whence") if position < 0: - return Result(Int64(0), WrappedError("strings.Reader.seek: negative position")) + return Int64(0), Error("strings.Reader.seek: negative position") self.read_pos = position - return position + return position, Error() - fn write_to[W: io.Writer](inout self, inout writer: W) -> Result[Int64]: + fn write_to[W: io.Writer](inout self, inout writer: W) -> (Int64, Error): """Writes the remaining portion of the underlying string to the provided writer. Implements the [io.WriterTo] trait. @@ -187,20 +178,20 @@ struct Reader( """ self.prev_rune = -1 if self.read_pos >= Int64(len(self.string)): - return Result(Int64(0), None) + return Int64(0), Error() var chunk_to_write = self.string[int(self.read_pos) :] - var result = io.write_string(writer, chunk_to_write) - var bytes_written = result.value + var bytes_written: Int + var err: Error + bytes_written, err = io.write_string(writer, chunk_to_write) if bytes_written > len(chunk_to_write): panic("strings.Reader.write_to: invalid write_string count") - var error: Optional[WrappedError] = None self.read_pos += Int64(bytes_written) - if bytes_written != len(chunk_to_write) and result.has_error(): - error = WrappedError(io.ERR_SHORT_WRITE) + if bytes_written != len(chunk_to_write) and not err: + err = Error(io.ERR_SHORT_WRITE) - return Result(Int64(bytes_written), error) + return Int64(bytes_written), err # TODO: How can I differentiate between the two write_to methods when the writer implements both traits? # fn write_to[W: io.StringWriter](inout self, inout writer: W) raises -> Int64: diff --git a/external/gojo/unicode/utf8/runes.mojo b/external/gojo/unicode/utf8/runes.mojo index af35b78..56da84b 100644 --- a/external/gojo/unicode/utf8/runes.mojo +++ b/external/gojo/unicode/utf8/runes.mojo @@ -1,3 +1,7 @@ +"""Almost all of the actual implementation in this module was written by @mzaks (https://github.com/mzaks)! +This would not be possible without his help. +""" + from ...builtins import Rune from algorithm.functional import vectorize from memory.unsafe import DTypePointer @@ -324,7 +328,7 @@ fn rune_count_in_string(s: String) -> Int: @parameter fn count[simd_width: Int](offset: Int): - result += ((p.load[width=simd_width](offset) >> 6) != 0b10).cast[DType.uint8]().reduce_add().to_int() + result += int(((p.load[width=simd_width](offset) >> 6) != 0b10).cast[DType.uint8]().reduce_add()) vectorize[count, simd_width_u8](string_byte_length) return result @@ -340,7 +344,7 @@ fn string_iterator(s: String, func: fn (String) -> None): var bytes = len(s) var p = s._as_ptr().bitcast[DType.uint8]() while bytes > 0: - var char_length = ((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())).to_int() + var char_length = int((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())) var sp = DTypePointer[DType.int8].alloc(char_length + 1) memcpy(sp, p.bitcast[DType.int8](), char_length) sp[char_length] = 0 diff --git a/external/string_dict/dict.mojo b/external/string_dict/dict.mojo index 41e404f..a3cafbc 100644 --- a/external/string_dict/dict.mojo +++ b/external/string_dict/dict.mojo @@ -5,9 +5,10 @@ from .string_eq import eq from .keys_container import KeysContainer from .ahasher import ahash + struct Dict[ V: CollectionElement, - hash: fn(String) -> UInt64 = ahash, + hash: fn (String) -> UInt64 = ahash, KeyCountType: DType = DType.uint32, KeyOffsetType: DType = DType.uint32, destructive: Bool = True, @@ -23,20 +24,20 @@ struct Dict[ fn __init__(inout self, capacity: Int = 16): constrained[ - KeyCountType == DType.uint8 or - KeyCountType == DType.uint16 or - KeyCountType == DType.uint32 or - KeyCountType == DType.uint64, - "KeyCountType needs to be an unsigned integer" + KeyCountType == DType.uint8 + or KeyCountType == DType.uint16 + or KeyCountType == DType.uint32 + or KeyCountType == DType.uint64, + "KeyCountType needs to be an unsigned integer", ]() self.count = 0 if capacity <= 8: self.capacity = 8 else: var icapacity = Int64(capacity) - self.capacity = capacity if ctpop(icapacity) == 1 else - 1 << (bit_length(icapacity)).to_int() + self.capacity = capacity if ctpop(icapacity) == 1 else 1 << int(bit_length(icapacity)) self.keys = KeysContainer[KeyOffsetType](capacity) + @parameter if caching_hashes: self.key_hashes = DTypePointer[KeyCountType].alloc(self.capacity) @@ -45,6 +46,7 @@ struct Dict[ self.values = List[V](capacity=capacity) self.key_map = DTypePointer[KeyCountType].alloc(self.capacity) memset_zero(self.key_map, self.capacity) + @parameter if destructive: self.deleted_mask = DTypePointer[DType.uint8].alloc(self.capacity >> 3) @@ -56,6 +58,7 @@ struct Dict[ self.count = existing.count self.capacity = existing.capacity self.keys = existing.keys + @parameter if caching_hashes: self.key_hashes = DTypePointer[KeyCountType].alloc(self.capacity) @@ -65,6 +68,7 @@ struct Dict[ self.values = existing.values self.key_map = DTypePointer[KeyCountType].alloc(self.capacity) memcpy(self.key_map, existing.key_map, self.capacity) + @parameter if destructive: self.deleted_mask = DTypePointer[DType.uint8].alloc(self.capacity >> 3) @@ -99,11 +103,12 @@ struct Dict[ var key_hash = hash(key).cast[KeyCountType]() var modulo_mask = self.capacity - 1 - var key_map_index = (key_hash & modulo_mask).to_int() + var key_map_index = int(key_hash & modulo_mask) while True: - var key_index = self.key_map.load(key_map_index).to_int() + var key_index = int(self.key_map.load(key_map_index)) if key_index == 0: self.keys.add(key) + @parameter if caching_hashes: self.key_hashes.store(key_map_index, key_hash) @@ -111,13 +116,14 @@ struct Dict[ self.count += 1 self.key_map.store(key_map_index, SIMD[KeyCountType, 1](self.keys.count)) return + @parameter if caching_hashes: var other_key_hash = self.key_hashes[key_map_index] if other_key_hash == key_hash: var other_key = self.keys[key_index - 1] if eq(other_key, key): - self.values[key_index - 1] = value # replace value + self.values[key_index - 1] = value # replace value if destructive: if self._is_deleted(key_index - 1): self.count += 1 @@ -126,7 +132,7 @@ struct Dict[ else: var other_key = self.keys[key_index - 1] if eq(other_key, key): - self.values[key_index - 1] = value # replace value + self.values[key_index - 1] = value # replace value if destructive: if self._is_deleted(key_index - 1): self.count += 1 @@ -167,6 +173,7 @@ struct Dict[ memset_zero(self.key_map, self.capacity) var key_hashes = self.key_hashes + @parameter if caching_hashes: key_hashes = DTypePointer[KeyCountType].alloc(self.capacity) @@ -184,23 +191,25 @@ struct Dict[ if old_key_map[i] == 0: continue var key_hash = SIMD[KeyCountType, 1](0) + @parameter if caching_hashes: key_hash = self.key_hashes[i] else: - key_hash = hash(self.keys[(old_key_map[i] - 1).to_int()]).cast[KeyCountType]() + key_hash = hash(self.keys[int(old_key_map[i] - 1)]).cast[KeyCountType]() - var key_map_index = (key_hash & modulo_mask).to_int() + var key_map_index = int(key_hash & modulo_mask) var searching = True while searching: - var key_index = self.key_map.load(key_map_index).to_int() + var key_index = int(self.key_map.load(key_map_index)) if key_index == 0: self.key_map.store(key_map_index, old_key_map[i]) searching = False else: key_map_index = (key_map_index + 1) & modulo_mask + @parameter if caching_hashes: key_hashes[key_map_index] = key_hash @@ -229,7 +238,7 @@ struct Dict[ var key_index = self._find_key_index(key) if key_index == 0: - return + return if not self._is_deleted(key_index - 1): self.count -= 1 self._deleted(key_index - 1) @@ -239,9 +248,9 @@ struct Dict[ var key_hash = hash(key).cast[KeyCountType]() var modulo_mask = self.capacity - 1 - var key_map_index = (key_hash & modulo_mask).to_int() + var key_map_index = int(key_hash & modulo_mask) while True: - var key_index = self.key_map.load(key_map_index).to_int() + var key_index = int(self.key_map.load(key_map_index)) if key_index == 0: return key_index @@ -267,6 +276,7 @@ struct Dict[ print(self.key_map.load(i), end=end) print("Keys:") self.keys.print_keys() + @parameter if caching_hashes: print("KeyHashes:") diff --git a/external/string_dict/keys_container.mojo b/external/string_dict/keys_container.mojo index c4054e0..f284bef 100644 --- a/external/string_dict/keys_container.mojo +++ b/external/string_dict/keys_container.mojo @@ -55,7 +55,7 @@ struct KeysContainer[KeyEndType: DType = DType.uint32](Sized): if needs_realocation: var keys = DTypePointer[DType.int8].alloc(self.allocated_bytes) - memcpy(keys, self.keys, prev_end.to_int()) + memcpy(keys, self.keys, int(prev_end)) self.keys.free() self.keys = keys @@ -76,8 +76,8 @@ struct KeysContainer[KeyEndType: DType = DType.uint32](Sized): fn get(self, index: Int) -> StringRef: if index < 0 or index >= self.count: return "" - var start = 0 if index == 0 else self.keys_end[index - 1].to_int() - var length = self.keys_end[index].to_int() - start + var start = 0 if index == 0 else int(self.keys_end[index - 1]) + var length = int(self.keys_end[index]) - start return StringRef(self.keys.offset(start), length) @always_inline diff --git a/external/weave/ansi/__init__.mojo b/external/weave/ansi/__init__.mojo index 3ed7edf..f383f67 100644 --- a/external/weave/ansi/__init__.mojo +++ b/external/weave/ansi/__init__.mojo @@ -1,2 +1,2 @@ from .ansi import printable_rune_width, is_terminator, Marker -from .writer import Writer +from .writer import Writer, new_default_writer diff --git a/external/weave/ansi/ansi.mojo b/external/weave/ansi/ansi.mojo index a6eb95c..d3eb9c3 100644 --- a/external/weave/ansi/ansi.mojo +++ b/external/weave/ansi/ansi.mojo @@ -22,7 +22,7 @@ fn printable_rune_width(s: String) -> Int: var bytes = len(s) var p = s._as_ptr().bitcast[DType.uint8]() while bytes > 0: - var char_length = ((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())).to_int() + var char_length = int((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())) var sp = DTypePointer[DType.int8].alloc(char_length + 1) memcpy(sp, p.bitcast[DType.int8](), char_length) sp[char_length] = 0 @@ -56,9 +56,9 @@ fn printable_rune_width(s: List[Byte]) -> Int: # Rune iterator for string var bytes = len(s) - var p = DTypePointer[DType.int8](s.data.value).bitcast[DType.uint8]() + var p = DTypePointer[DType.int8](s.data).bitcast[DType.uint8]() while bytes > 0: - var char_length = ((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())).to_int() + var char_length = int((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())) var sp = DTypePointer[DType.int8].alloc(char_length + 1) memcpy(sp, p.bitcast[DType.int8](), char_length) sp[char_length] = 0 diff --git a/external/weave/ansi/writer.mojo b/external/weave/ansi/writer.mojo index 3877ff4..556939c 100644 --- a/external/weave/ansi/writer.mojo +++ b/external/weave/ansi/writer.mojo @@ -1,6 +1,5 @@ from math.bit import ctlz from external.gojo.bytes import buffer -from external.gojo.builtins import Result from external.gojo.builtins.bytes import Byte, has_suffix from external.gojo.io import traits as io from .ansi import Marker, is_terminator @@ -23,13 +22,20 @@ struct Writer(io.Writer): self.seq_changed = False # self.rune_buf = List[Byte](capacity=4096) - # write is used to write content to the ANSI buffer. - fn write(inout self, src: List[Byte]) -> Result[Int]: + fn write(inout self, src: List[Byte]) -> (Int, Error): + """Write content to the ANSI buffer. + + Args: + src: The content to write. + + Returns: + The number of bytes written and optional error. + """ # Rune iterator var bytes = len(src) - var p = DTypePointer[DType.int8](src.data.value).bitcast[DType.uint8]() + var p = DTypePointer[DType.int8](src.data).bitcast[DType.uint8]() while bytes > 0: - var char_length = ((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())).to_int() + var char_length = int((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())) var sp = DTypePointer[DType.int8].alloc(char_length + 1) memcpy(sp, p.bitcast[DType.int8](), char_length) sp[char_length] = 0 @@ -56,20 +62,19 @@ struct Writer(io.Writer): _ = self.ansi_seq.write_to(self.forward) else: - var result = self.forward.write_string(char) + _ = self.forward.write_string(char) # move forward iterator bytes -= char_length p += char_length - # TODO: Should this be returning just len(src)? - return len(src) + return len(src), Error() fn write_byte(inout self, byte: Byte) -> Int: _ = self.forward.write_byte(byte) return 1 - # fn write_rune(inout self, rune: String) -> Result[Int]: + # fn write_rune(inout self, rune: String) -> (Int, Error): # return self.forward.write(self.runeBuf[:n]) fn last_sequence(self) -> String: diff --git a/external/weave/dedent.mojo b/external/weave/dedent.mojo index daee19b..549aa03 100644 --- a/external/weave/dedent.mojo +++ b/external/weave/dedent.mojo @@ -1,10 +1,18 @@ from external.gojo.bytes import buffer from external.gojo.builtins import Byte +from .ansi import printable_rune_width -# String automatically detects the maximum indentation shared by all lines and -# trims them accordingly. fn apply_dedent(owned s: String) -> String: + """Automatically detects the maximum indentation shared by all lines and + trims them accordingly. + + Args: + s: The string to dedent. + + Returns: + The dedented string. + """ var indent = min_indent(s) if indent == 0: return s @@ -18,11 +26,12 @@ fn min_indent(s: String) -> Int: var should_append = True var i: Int = 0 - while i < len(s): - if s[i] == "\t" or s[i] == " ": + var s_bytes = s.as_bytes() + while i < len(s_bytes): + if s_bytes[i] == ord("\t") or s_bytes[i] == ord(" "): if should_append: cur_indent += 1 - elif s[i] == "\n": + elif s_bytes[i] == ord("\n"): cur_indent = 0 should_append = True else: @@ -41,17 +50,18 @@ fn dedent(s: String, indent: Int) -> String: var buf = buffer.new_buffer() var i: Int = 0 - while i < len(s): - if s[i] == "\t" or s[i] == " ": + var s_bytes = s.as_bytes() + while i < len(s_bytes): + if s_bytes[i] == ord("\t") or s_bytes[i] == ord(" "): if omitted < indent: omitted += 1 else: - _ = buf.write_byte(ord(s[i])) - elif s[i] == "\n": + _ = buf.write_byte(s_bytes[i]) + elif s_bytes[i] == ord("\n"): omitted = 0 - _ = buf.write_byte(ord(s[i])) + _ = buf.write_byte(s_bytes[i]) else: - _ = buf.write_byte(ord(s[i])) + _ = buf.write_byte(s_bytes[i]) i += 1 diff --git a/external/weave/indent.mojo b/external/weave/indent.mojo index 69ed6a1..3729d87 100644 --- a/external/weave/indent.mojo +++ b/external/weave/indent.mojo @@ -1,6 +1,6 @@ from math.bit import ctlz from external.gojo.bytes import buffer -from external.gojo.builtins import Result, Byte +from external.gojo.builtins import Byte import external.gojo.io from .ansi import writer, is_terminator, Marker from .strings import repeat @@ -28,7 +28,7 @@ struct Writer(Stringable, io.Writer): fn __str__(self) -> String: return str(self.ansi_writer.forward) - fn write(inout self, src: List[Byte]) -> Result[Int]: + fn write(inout self, src: List[Byte]) -> (Int, Error): """Writes the given byte slice to the writer. Args: @@ -37,11 +37,12 @@ struct Writer(Stringable, io.Writer): Returns: The number of bytes written and optional error. """ + var err = Error() # Rune iterator var bytes = len(src) - var p = DTypePointer[DType.int8](src.data.value).bitcast[DType.uint8]() + var p = DTypePointer[DType.int8](src.data).bitcast[DType.uint8]() while bytes > 0: - var char_length = ((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())).to_int() + var char_length = int((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())) var sp = DTypePointer[DType.int8].alloc(char_length + 1) memcpy(sp, p.bitcast[DType.int8](), char_length) sp[char_length] = 0 @@ -59,9 +60,11 @@ struct Writer(Stringable, io.Writer): if not self.skip_indent: self.ansi_writer.reset_ansi() var indent = repeat(" ", int(self.indent)).as_bytes() - var result = self.ansi_writer.write(indent) - if result.error: - return result + + var bytes_written = 0 + bytes_written, err = self.ansi_writer.write(indent) + if err: + return bytes_written, err self.skip_indent = True self.ansi_writer.restore_ansi() @@ -70,15 +73,16 @@ struct Writer(Stringable, io.Writer): # end of current line self.skip_indent = False - var result = self.ansi_writer.write(char.as_bytes()) - if result.error: - return result + var bytes_written = 0 + bytes_written, err = self.ansi_writer.write(char.as_bytes()) + if err: + return bytes_written, err # Move iterator forward bytes -= char_length p += char_length - return len(src) + return len(src), err fn new_writer(indent: UInt8) -> Writer: diff --git a/external/weave/margin.mojo b/external/weave/margin.mojo index 31a6750..6eff7f1 100644 --- a/external/weave/margin.mojo +++ b/external/weave/margin.mojo @@ -1,5 +1,5 @@ from external.gojo.bytes import buffer -from external.gojo.builtins import Result, Byte +from external.gojo.builtins import Byte import external.gojo.io from .ansi import writer, is_terminator, Marker from .strings import repeat, strip @@ -28,7 +28,7 @@ struct Writer(Stringable, io.Writer): fn __str__(self) -> String: return str(self.buf) - fn write(inout self, src: List[Byte]) -> Result[Int]: + fn write(inout self, src: List[Byte]) -> (Int, Error): """Writes the given byte slice to the writer. Args: src: The byte slice to write. @@ -36,9 +36,11 @@ struct Writer(Stringable, io.Writer): Returns: The number of bytes written and optional error. """ - var result = self.iw.write(src) - if result.error: - return result + var bytes_written = 0 + var err = Error() + bytes_written, err = self.iw.write(src) + if err: + return bytes_written, err return self.pw.write(self.iw.bytes()) diff --git a/external/weave/padding.mojo b/external/weave/padding.mojo index 3259c7e..fce9f53 100644 --- a/external/weave/padding.mojo +++ b/external/weave/padding.mojo @@ -1,6 +1,6 @@ from math.bit import ctlz from external.gojo.bytes import buffer -from external.gojo.builtins import Result, Byte +from external.gojo.builtins import Byte import external.gojo.io from .ansi import writer, is_terminator, Marker, printable_rune_width from .strings import repeat, strip @@ -28,7 +28,7 @@ struct Writer(Stringable, io.Writer): self.cache = buffer.new_buffer() self.ansi_writer = writer.new_default_writer() - fn write(inout self, src: List[Byte]) -> Result[Int]: + fn write(inout self, src: List[Byte]) -> (Int, Error): """Pads content to the given printable cell width. Args: @@ -37,11 +37,12 @@ struct Writer(Stringable, io.Writer): Returns: The number of bytes written and optional error. """ + var err = Error() # Rune iterator var bytes = len(src) - var p = DTypePointer[DType.int8](src.data.value).bitcast[DType.uint8]() + var p = DTypePointer[DType.int8](src.data).bitcast[DType.uint8]() while bytes > 0: - var char_length = ((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())).to_int() + var char_length = int((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())) var sp = DTypePointer[DType.int8].alloc(char_length + 1) memcpy(sp, p.bitcast[DType.int8](), char_length) sp[char_length] = 0 @@ -62,15 +63,17 @@ struct Writer(Stringable, io.Writer): else: self.line_len += printable_rune_width(char) - var result = self.ansi_writer.write(char.as_bytes()) - if result.error: - return result + var bytes_written = 0 + + bytes_written, err = self.ansi_writer.write(char.as_bytes()) + if err: + return bytes_written, err # Move iterator forward bytes -= char_length p += char_length - return len(src) + return len(src), err fn pad(inout self): """Pads the current line with spaces to the given width.""" diff --git a/external/weave/truncate.mojo b/external/weave/truncate.mojo index 8664521..3edf202 100644 --- a/external/weave/truncate.mojo +++ b/external/weave/truncate.mojo @@ -1,6 +1,6 @@ from math.bit import ctlz from external.gojo.bytes import buffer -from external.gojo.builtins import Result, Byte +from external.gojo.builtins import Byte import external.gojo.io from .ansi import writer, is_terminator, Marker, printable_rune_width from .strings import repeat, strip @@ -21,7 +21,7 @@ struct Writer(Stringable, io.Writer): self.ansi_writer = writer.new_default_writer() - fn write(inout self, src: List[Int8]) -> Result[Int]: + fn write(inout self, src: List[Int8]) -> (Int, Error): """Truncates content at the given printable cell width, leaving any ANSI sequences intact. Args: @@ -39,9 +39,9 @@ struct Writer(Stringable, io.Writer): # Rune iterator var bytes = len(src) - var p = DTypePointer[DType.int8](src.data.value).bitcast[DType.uint8]() + var p = DTypePointer[DType.int8](src.data).bitcast[DType.uint8]() while bytes > 0: - var char_length = ((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())).to_int() + var char_length = int((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())) var sp = DTypePointer[DType.int8].alloc(char_length + 1) memcpy(sp, p.bitcast[DType.int8](), char_length) sp[char_length] = 0 @@ -69,7 +69,7 @@ struct Writer(Stringable, io.Writer): bytes -= char_length p += char_length - return len(src) + return len(src), Error() fn bytes(self) -> List[Byte]: """Returns the truncated result as a byte slice. diff --git a/external/weave/wordwrap.mojo b/external/weave/wordwrap.mojo index 4765bdc..e6b2813 100644 --- a/external/weave/wordwrap.mojo +++ b/external/weave/wordwrap.mojo @@ -1,6 +1,6 @@ from math.bit import ctlz from external.gojo.bytes import buffer -from external.gojo.builtins import Result, Byte +from external.gojo.builtins import Byte import external.gojo.io from .ansi import writer, is_terminator, Marker, printable_rune_width from .strings import repeat, strip @@ -68,7 +68,7 @@ struct WordWrap(Stringable, io.Writer): self.line_len = 0 self.space.reset() - fn write(inout self, src: List[Byte]) -> Result[Int]: + fn write(inout self, src: List[Byte]) -> (Int, Error): """Write more content to the word-wrap buffer. Args: @@ -90,9 +90,9 @@ struct WordWrap(Stringable, io.Writer): # Rune iterator var bytes = len(s) var s_bytes = s.as_bytes() # needs to be mutable, so we steal the data of the copy - var p = DTypePointer[DType.int8](s_bytes.steal_data().value).bitcast[DType.uint8]() + var p = DTypePointer[DType.int8](s_bytes.steal_data()).bitcast[DType.uint8]() while bytes > 0: - var char_length = ((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())).to_int() + var char_length = int((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())) var sp = DTypePointer[DType.int8].alloc(char_length + 1) memcpy(sp, p.bitcast[DType.int8](), char_length) sp[char_length] = 0 @@ -147,7 +147,7 @@ struct WordWrap(Stringable, io.Writer): bytes -= char_length p += char_length - return len(src) + return len(src), Error() fn close(inout self): """Finishes the word-wrap operation. Always call it before trying to retrieve the final result.""" diff --git a/external/weave/wrap.mojo b/external/weave/wrap.mojo index 7597a87..720e30a 100644 --- a/external/weave/wrap.mojo +++ b/external/weave/wrap.mojo @@ -1,6 +1,6 @@ from math.bit import ctlz from external.gojo.bytes import buffer -from external.gojo.builtins import Result, Byte +from external.gojo.builtins import Byte import external.gojo.io from .ansi import writer, is_terminator, Marker, printable_rune_width from .strings import repeat @@ -50,7 +50,7 @@ struct Wrap(Stringable, io.Writer): _ = self.buf.write_byte(ord(self.newline)) self.line_len = 0 - fn write(inout self, src: List[Byte]) -> Result[Int]: + fn write(inout self, src: List[Byte]) -> (Int, Error): """Writes the given byte slice to the buffer, wrapping lines as needed. Args: @@ -76,9 +76,9 @@ struct Wrap(Stringable, io.Writer): # Rune iterator var bytes = len(s) var s_bytes = s.as_bytes() # needs to be mutable, so we steal the data of the copy - var p = DTypePointer[DType.int8](s_bytes.steal_data().value).bitcast[DType.uint8]() + var p = DTypePointer[DType.int8](s_bytes.steal_data()).bitcast[DType.uint8]() while bytes > 0: - var char_length = ((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())).to_int() + var char_length = int((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())) var sp = DTypePointer[DType.int8].alloc(char_length + 1) memcpy(sp, p.bitcast[DType.int8](), char_length) sp[char_length] = 0 @@ -119,7 +119,7 @@ struct Wrap(Stringable, io.Writer): bytes -= char_length p += char_length - return len(src) + return len(src), Error() fn bytes(self) -> List[Byte]: """Returns the wrapped result as a byte slice. diff --git a/mog/whitespace.mojo b/mog/whitespace.mojo index 6c17bab..78c3624 100644 --- a/mog/whitespace.mojo +++ b/mog/whitespace.mojo @@ -1,5 +1,4 @@ from math.bit import ctlz -from memory.unsafe import Reference import external.mist import external.weave.ansi from external.gojo.strings import StringBuilder @@ -71,7 +70,7 @@ struct WhiteSpace: var bytes = len(self.chars) var p = self.chars._as_ptr().bitcast[DType.uint8]() while bytes > 0: - var char_length = ((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())).to_int() + var char_length = int((p.load() >> 7 == 0).cast[DType.uint8]() * 1 + ctlz(~p.load())) var sp = DTypePointer[DType.int8].alloc(char_length + 1) memcpy(sp, p.bitcast[DType.int8](), char_length) sp[char_length] = 0