From 2aa4a82499d4becd2284cdb482213d541b8804dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 16:29:10 +0200 Subject: Adding upstream version 86.0.1. Signed-off-by: Daniel Baumann --- third_party/rust/bincode/src/de/read.rs | 201 ++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 third_party/rust/bincode/src/de/read.rs (limited to 'third_party/rust/bincode/src/de/read.rs') diff --git a/third_party/rust/bincode/src/de/read.rs b/third_party/rust/bincode/src/de/read.rs new file mode 100644 index 0000000000..ffc5ae2ac0 --- /dev/null +++ b/third_party/rust/bincode/src/de/read.rs @@ -0,0 +1,201 @@ +use error::Result; +use serde; +use std::{io, slice}; + +/// An optional Read trait for advanced Bincode usage. +/// +/// It is highly recommended to use bincode with `io::Read` or `&[u8]` before +/// implementing a custom `BincodeRead`. +pub trait BincodeRead<'storage>: io::Read { + /// Forwards reading `length` bytes of a string on to the serde reader. + fn forward_read_str(&mut self, length: usize, visitor: V) -> Result + where + V: serde::de::Visitor<'storage>; + + /// Return the first `length` bytes of the internal byte buffer. + fn get_byte_buffer(&mut self, length: usize) -> Result>; + + /// Forwards reading `length` bytes on to the serde reader. + fn forward_read_bytes(&mut self, length: usize, visitor: V) -> Result + where + V: serde::de::Visitor<'storage>; +} + +/// A BincodeRead implementation for byte slices +/// NOT A PART OF THE STABLE PUBLIC API +#[doc(hidden)] +pub struct SliceReader<'storage> { + slice: &'storage [u8], +} + +/// A BincodeRead implementation for io::Readers +/// NOT A PART OF THE STABLE PUBLIC API +#[doc(hidden)] +pub struct IoReader { + reader: R, + temp_buffer: Vec, +} + +impl<'storage> SliceReader<'storage> { + /// Constructs a slice reader + pub fn new(bytes: &'storage [u8]) -> SliceReader<'storage> { + SliceReader { slice: bytes } + } +} + +impl IoReader { + /// Constructs an IoReadReader + pub fn new(r: R) -> IoReader { + IoReader { + reader: r, + temp_buffer: vec![], + } + } +} + +impl<'storage> io::Read for SliceReader<'storage> { + #[inline(always)] + fn read(&mut self, out: &mut [u8]) -> io::Result { + (&mut self.slice).read(out) + } + #[inline(always)] + fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> { + (&mut self.slice).read_exact(out) + } +} + +impl io::Read for IoReader { + #[inline(always)] + fn read(&mut self, out: &mut [u8]) -> io::Result { + self.reader.read(out) + } + #[inline(always)] + fn read_exact(&mut self, out: &mut [u8]) -> io::Result<()> { + self.reader.read_exact(out) + } +} + +impl<'storage> SliceReader<'storage> { + #[inline(always)] + fn unexpected_eof() -> Box<::ErrorKind> { + return Box::new(::ErrorKind::Io(io::Error::new( + io::ErrorKind::UnexpectedEof, + "", + ))); + } +} + +impl<'storage> BincodeRead<'storage> for SliceReader<'storage> { + #[inline(always)] + fn forward_read_str(&mut self, length: usize, visitor: V) -> Result + where + V: serde::de::Visitor<'storage>, + { + use ErrorKind; + if length > self.slice.len() { + return Err(SliceReader::unexpected_eof()); + } + + let string = match ::std::str::from_utf8(&self.slice[..length]) { + Ok(s) => s, + Err(e) => return Err(ErrorKind::InvalidUtf8Encoding(e).into()), + }; + let r = visitor.visit_borrowed_str(string); + self.slice = &self.slice[length..]; + r + } + + #[inline(always)] + fn get_byte_buffer(&mut self, length: usize) -> Result> { + if length > self.slice.len() { + return Err(SliceReader::unexpected_eof()); + } + + let r = &self.slice[..length]; + self.slice = &self.slice[length..]; + Ok(r.to_vec()) + } + + #[inline(always)] + fn forward_read_bytes(&mut self, length: usize, visitor: V) -> Result + where + V: serde::de::Visitor<'storage>, + { + if length > self.slice.len() { + return Err(SliceReader::unexpected_eof()); + } + + let r = visitor.visit_borrowed_bytes(&self.slice[..length]); + self.slice = &self.slice[length..]; + r + } +} + +impl IoReader +where + R: io::Read, +{ + fn fill_buffer(&mut self, length: usize) -> Result<()> { + // We first reserve the space needed in our buffer. + let current_length = self.temp_buffer.len(); + if length > current_length { + self.temp_buffer.reserve_exact(length - current_length); + } + + // Then create a slice with the length as our desired length. This is + // safe as long as we only write (no reads) to this buffer, because + // `reserve_exact` above has allocated this space. + let buf = unsafe { + slice::from_raw_parts_mut(self.temp_buffer.as_mut_ptr(), length) + }; + + // This method is assumed to properly handle slices which include + // uninitialized bytes (as ours does). See discussion at the link below. + // https://github.com/servo/bincode/issues/260 + self.reader.read_exact(buf)?; + + // Only after `read_exact` successfully returns do we set the buffer + // length. By doing this after the call to `read_exact`, we can avoid + // exposing uninitialized memory in the case of `read_exact` returning + // an error. + unsafe { + self.temp_buffer.set_len(length); + } + + Ok(()) + } +} + +impl<'a, R> BincodeRead<'a> for IoReader +where + R: io::Read, +{ + fn forward_read_str(&mut self, length: usize, visitor: V) -> Result + where + V: serde::de::Visitor<'a>, + { + self.fill_buffer(length)?; + + let string = match ::std::str::from_utf8(&self.temp_buffer[..]) { + Ok(s) => s, + Err(e) => return Err(::ErrorKind::InvalidUtf8Encoding(e).into()), + }; + + let r = visitor.visit_str(string); + r + } + + fn get_byte_buffer(&mut self, length: usize) -> Result> { + self.fill_buffer(length)?; + Ok(::std::mem::replace(&mut self.temp_buffer, Vec::new())) + } + + fn forward_read_bytes(&mut self, length: usize, visitor: V) -> Result + where + V: serde::de::Visitor<'a>, + { + self.fill_buffer(length)?; + let r = visitor.visit_bytes(&self.temp_buffer[..]); + r + } +} -- cgit v1.2.3