Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,86 @@
|
||||
module cbor
|
||||
|
||||
import io
|
||||
|
||||
// Stream I/O wrappers over the standard `io.Reader` / `io.Writer`
|
||||
// interfaces. Use these for files, sockets, pipes — anywhere the
|
||||
// payload doesn't fit cleanly in a single `[]u8`.
|
||||
|
||||
// encode_to serialises `val` into an internal buffer, then writes the
|
||||
// bytes to `w` in a loop until everything is accepted. Errors on the
|
||||
// first I/O failure.
|
||||
pub fn encode_to[T](val T, mut w io.Writer, opts EncodeOpts) ! {
|
||||
bytes := encode[T](val, opts)!
|
||||
mut written := 0
|
||||
for written < bytes.len {
|
||||
n := w.write(bytes[written..])!
|
||||
if n == 0 {
|
||||
return error('cbor: writer stopped accepting bytes at ${written}/${bytes.len}')
|
||||
}
|
||||
written += n
|
||||
}
|
||||
}
|
||||
|
||||
// decode_from reads bytes from `r` until EOF (or until
|
||||
// `DecodeOpts.max_stream_bytes` is hit) and decodes a single top-level
|
||||
// value. For multi-value streams, use `Unpacker` directly on a
|
||||
// pre-buffered slice.
|
||||
//
|
||||
// Always set `max_stream_bytes` on untrusted readers — otherwise a peer
|
||||
// that never sends EOF blocks the call forever.
|
||||
pub fn decode_from[T](mut r io.Reader, opts DecodeOpts) !T {
|
||||
bounded := opts.max_stream_bytes > 0
|
||||
mut buf := []u8{cap: 4096}
|
||||
for {
|
||||
if bounded && buf.len >= opts.max_stream_bytes {
|
||||
return error('cbor: stream exceeded max_stream_bytes (${opts.max_stream_bytes})')
|
||||
}
|
||||
slot_len := if bounded {
|
||||
cap_left := opts.max_stream_bytes - buf.len
|
||||
if cap_left < 4096 {
|
||||
cap_left
|
||||
} else {
|
||||
4096
|
||||
}
|
||||
} else {
|
||||
4096
|
||||
}
|
||||
mut slot := []u8{len: slot_len}
|
||||
// Treat io.Eof as the legitimate end of the stream; any other
|
||||
// reader error must propagate so callers don't mistake a
|
||||
// transport failure for a successful (truncated) decode. The
|
||||
// unbounded branch used to delegate to `io.read_all`, which
|
||||
// also swallows non-EOF errors — same loop here keeps the
|
||||
// strict semantic regardless of whether `max_stream_bytes` is set.
|
||||
n := r.read(mut slot) or {
|
||||
if err is io.Eof {
|
||||
break
|
||||
}
|
||||
return err
|
||||
}
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
buf << slot[..n]
|
||||
}
|
||||
return decode[T](buf, opts)!
|
||||
}
|
||||
|
||||
// pack_to is the streaming sibling of `encode_to`, for users who built
|
||||
// their payload manually via the `Packer` API. Errors if any
|
||||
// indefinite-length container is still open — emitting half-closed
|
||||
// CBOR would produce a payload no decoder can parse.
|
||||
pub fn (mut p Packer) pack_to(mut w io.Writer) ! {
|
||||
if !p.is_complete() {
|
||||
return error('cbor: pack_to called with an open indefinite-length item — close it with pack_break first')
|
||||
}
|
||||
bytes := p.bytes()
|
||||
mut written := 0
|
||||
for written < bytes.len {
|
||||
n := w.write(bytes[written..])!
|
||||
if n == 0 {
|
||||
return error('cbor: writer stopped at ${written}/${bytes.len}')
|
||||
}
|
||||
written += n
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user