From 7ece2bfb91d57208888ac56a8a6ee0bcd86b0c2b Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Tue, 28 Mar 2023 22:21:53 -0500 Subject: [PATCH] doc: `encoding.md5`; added `io.stream_read_until_full` --- core/hash/md5.onyx | 35 +++++++++++++++++------------------ core/io/stream.onyx | 17 +++++++++++++++++ 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/core/hash/md5.onyx b/core/hash/md5.onyx index 635a57d0..ab4984e3 100644 --- a/core/hash/md5.onyx +++ b/core/hash/md5.onyx @@ -4,30 +4,31 @@ use core {io, memory, conv} use core.intrinsics.wasm {rotl_i32} -digest :: #match #local -> MD5_Digest {} +#doc "Produces an MD5 digest of a string or stream." +digest :: #match #local {} +#doc "Produces an MD5 digest of a string. This is guaranteed to succeed." #overload digest :: (x: str) -> MD5_Digest { - string_reader, string_stream := io.reader_from_string(x); - defer cfree(string_stream); - defer delete(&string_reader); - - return digest(&string_reader); + string_stream := io.buffer_stream_make(x, write_enabled=false); + return digest(&string_stream)?; } +#doc "Produces an MD5 digest of a stream. This is not guaranteed to succeed, as the stream may fail part way through." #overload -digest :: (r: &io.Reader) -> MD5_Digest { +digest :: (s: &io.Stream) -> ?MD5_Digest { dig := MD5_Digest.make(); remaining_bytes_to_digest := 0; bytes_to_digest: [64] u8; - while !r->is_empty() { - byte_count, err := r->read_bytes(bytes_to_digest); - - // Exit early to handle the tail case. - // This is subject to read_pending errors if the reader - // does not have enough bytes and returns read_pending. + while true { + err, byte_count := io.stream_read(s, bytes_to_digest); + + if err != .None && err != .EOF { + return .{}; + } + if byte_count < 64 { remaining_bytes_to_digest = byte_count; break; @@ -36,7 +37,7 @@ digest :: (r: &io.Reader) -> MD5_Digest { do_cycle(&dig, bytes_to_digest); } - dig->finish(bytes_to_digest[0..remaining_bytes_to_digest]); + dig->_finish(bytes_to_digest[0..remaining_bytes_to_digest]); return dig; } @@ -59,7 +60,7 @@ MD5_Digest :: struct { *self = MD5_Digest.make(); } - finish :: (self: &#Self, tail: [] u8) { + _finish :: (self: &#Self, tail: [] u8) { assert(tail.count < 64, "Tail too long"); bytes_to_digest: [64] u8; @@ -69,11 +70,9 @@ MD5_Digest :: struct { if tail.count >= 56 { do_cycle(self, bytes_to_digest, accumulate=false); memory.set(~~bytes_to_digest, 0, 64); - - } else { - self.bytes_digested += ~~tail.count; } + self.bytes_digested += ~~tail.count; *cast(&u64, &bytes_to_digest[56]) = self.bytes_digested * 8; do_cycle(self, bytes_to_digest, accumulate=false); diff --git a/core/io/stream.onyx b/core/io/stream.onyx index a4610191..f6de5cb5 100644 --- a/core/io/stream.onyx +++ b/core/io/stream.onyx @@ -75,6 +75,23 @@ stream_read_byte :: (use s: &Stream) -> (Error, u8) { return vtable.read_byte(s); } +stream_read_until_full :: (use s: &Stream, buffer: [] u8) -> (Error, u32) { + if vtable == null do return .NoVtable, 0; + if vtable.read == null_proc do return .NotImplemented, 0; + + bytes_read := 0; + while bytes_read < buffer.count { + err, r := vtable.read(s, buffer[bytes_read .. buffer.length]); + bytes_read += r; + + if err != .ReadPending && err != .ReadLater && err != .None { + return err, bytes_read; + } + } + + return .None, bytes_read; +} + stream_write :: (use s: &Stream, buffer: [] u8) -> (Error, u32) { if vtable == null do return .NoVtable, 0; if vtable.write == null_proc do return .NotImplemented, 0; -- 2.25.1