diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
commit | d1b2d29528b7794b41e66fc2136e395a02f8529b (patch) | |
tree | a4a17504b260206dec3cf55b2dca82929a348ac2 /vendor/ciborium-ll/src/enc.rs | |
parent | Releasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip |
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/ciborium-ll/src/enc.rs')
-rw-r--r-- | vendor/ciborium-ll/src/enc.rs | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/vendor/ciborium-ll/src/enc.rs b/vendor/ciborium-ll/src/enc.rs new file mode 100644 index 000000000..b8b8a20d6 --- /dev/null +++ b/vendor/ciborium-ll/src/enc.rs @@ -0,0 +1,127 @@ +use super::*; + +use ciborium_io::Write; + +/// An encoder for serializing CBOR items +/// +/// This structure wraps a writer and provides convenience functions for +/// writing `Header` objects to the wire. +pub struct Encoder<W: Write>(W); + +impl<W: Write> From<W> for Encoder<W> { + #[inline] + fn from(value: W) -> Self { + Self(value) + } +} + +impl<W: Write> Write for Encoder<W> { + type Error = W::Error; + + fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> { + self.0.write_all(data) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + self.0.flush() + } +} + +impl<W: Write> Encoder<W> { + /// Push a `Header` to the wire + #[inline] + pub fn push(&mut self, header: Header) -> Result<(), W::Error> { + let title = Title::from(header); + + let major = match title.0 { + Major::Positive => 0, + Major::Negative => 1, + Major::Bytes => 2, + Major::Text => 3, + Major::Array => 4, + Major::Map => 5, + Major::Tag => 6, + Major::Other => 7, + }; + + let minor = match title.1 { + Minor::This(x) => x, + Minor::Next1(..) => 24, + Minor::Next2(..) => 25, + Minor::Next4(..) => 26, + Minor::Next8(..) => 27, + Minor::More => 31, + }; + + self.0.write_all(&[major << 5 | minor])?; + self.0.write_all(title.1.as_ref()) + } + + /// Serialize a byte slice as CBOR + /// + /// Optionally, segment the output into `segment` size segments. Note that + /// if `segment == Some(0)` it will be silently upgraded to `Some(1)`. This + /// minimum value is highly inefficient and should not be relied upon. + #[inline] + pub fn bytes( + &mut self, + value: &[u8], + segment: impl Into<Option<usize>>, + ) -> Result<(), W::Error> { + let max = segment.into().unwrap_or(value.len()); + let max = core::cmp::max(max, 1); + + if max >= value.len() { + self.push(Header::Bytes(Some(value.len())))?; + self.write_all(value)?; + } else { + self.push(Header::Bytes(None))?; + + for chunk in value.chunks(max) { + self.push(Header::Bytes(Some(chunk.len())))?; + self.write_all(chunk)?; + } + + self.push(Header::Break)?; + } + + Ok(()) + } + + /// Serialize a string slice as CBOR + /// + /// Optionally, segment the output into `segment` size segments. Note that + /// since care is taken to ensure that each segment is itself a valid UTF-8 + /// string, if `segment` contains a value of less than 4, it will be + /// silently upgraded to 4. This minimum value is highly inefficient and + /// should not be relied upon. + #[inline] + pub fn text(&mut self, value: &str, segment: impl Into<Option<usize>>) -> Result<(), W::Error> { + let max = segment.into().unwrap_or(value.len()); + let max = core::cmp::max(max, 4); + + if max >= value.len() { + self.push(Header::Text(Some(value.len())))?; + self.write_all(value.as_bytes())?; + } else { + self.push(Header::Text(None))?; + + let mut bytes = value.as_bytes(); + while !bytes.is_empty() { + let mut len = core::cmp::min(bytes.len(), max); + while len > 0 && core::str::from_utf8(&bytes[..len]).is_err() { + len -= 1 + } + + let (prefix, suffix) = bytes.split_at(len); + self.push(Header::Text(Some(prefix.len())))?; + self.write_all(prefix)?; + bytes = suffix; + } + + self.push(Header::Break)?; + } + + Ok(()) + } +} |