| #[cfg(feature = "alloc")] |
| use alloc::vec::Vec; |
| #[cfg(not(feature = "std"))] |
| use core::fmt; |
| #[cfg(feature = "std")] |
| use std::io; |
| |
| use crate::error; |
| |
| #[cfg(not(feature = "unsealed_read_write"))] |
| /// A sink for serialized CBOR. |
| /// |
| /// This trait is similar to the [`Write`]() trait in the standard library, |
| /// but has a smaller and more general API. |
| /// |
| /// Any object implementing `std::io::Write` |
| /// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements |
| /// this trait for the underlying object. |
| pub trait Write: private::Sealed { |
| /// The type of error returned when a write operation fails. |
| #[doc(hidden)] |
| type Error: Into<error::Error>; |
| |
| /// Attempts to write an entire buffer into this write. |
| #[doc(hidden)] |
| fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>; |
| } |
| |
| #[cfg(feature = "unsealed_read_write")] |
| /// A sink for serialized CBOR. |
| /// |
| /// This trait is similar to the [`Write`]() trait in the standard library, |
| /// but has a smaller and more general API. |
| /// |
| /// Any object implementing `std::io::Write` |
| /// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements |
| /// this trait for the underlying object. |
| /// |
| /// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound |
| /// to allow objects outside of this crate to implement this trait. |
| pub trait Write { |
| /// The type of error returned when a write operation fails. |
| type Error: Into<error::Error>; |
| |
| /// Attempts to write an entire buffer into this write. |
| fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>; |
| } |
| |
| #[cfg(not(feature = "unsealed_read_write"))] |
| mod private { |
| pub trait Sealed {} |
| } |
| |
| impl<W> Write for &mut W |
| where |
| W: Write, |
| { |
| type Error = W::Error; |
| |
| fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { |
| (*self).write_all(buf) |
| } |
| } |
| |
| #[cfg(not(feature = "unsealed_read_write"))] |
| impl<W> private::Sealed for &mut W where W: Write {} |
| |
| #[cfg(feature = "std")] |
| /// A wrapper for types that implement |
| /// [`std::io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html) to implement the local |
| /// [`Write`](trait.Write.html) trait. |
| #[derive(Debug)] |
| pub struct IoWrite<W>(W); |
| |
| #[cfg(feature = "std")] |
| impl<W: io::Write> IoWrite<W> { |
| /// Wraps an `io::Write` writer to make it compatible with [`Write`](trait.Write.html) |
| pub fn new(w: W) -> IoWrite<W> { |
| IoWrite(w) |
| } |
| } |
| |
| #[cfg(feature = "std")] |
| impl<W: io::Write> Write for IoWrite<W> { |
| type Error = io::Error; |
| |
| fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { |
| self.0.write_all(buf) |
| } |
| } |
| |
| #[cfg(all(feature = "std", not(feature = "unsealed_read_write")))] |
| impl<W> private::Sealed for IoWrite<W> where W: io::Write {} |
| |
| #[cfg(any(feature = "std", feature = "alloc"))] |
| impl Write for Vec<u8> { |
| type Error = error::Error; |
| |
| fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { |
| self.extend_from_slice(buf); |
| Ok(()) |
| } |
| } |
| |
| #[cfg(all( |
| any(feature = "std", feature = "alloc"), |
| not(feature = "unsealed_read_write") |
| ))] |
| impl private::Sealed for Vec<u8> {} |
| |
| #[cfg(not(feature = "std"))] |
| #[derive(Debug)] |
| pub struct FmtWrite<'a, W: Write>(&'a mut W); |
| |
| #[cfg(not(feature = "std"))] |
| impl<'a, W: Write> FmtWrite<'a, W> { |
| /// Wraps an `fmt::Write` writer to make it compatible with [`Write`](trait.Write.html) |
| pub fn new(w: &'a mut W) -> FmtWrite<'a, W> { |
| FmtWrite(w) |
| } |
| } |
| |
| #[cfg(not(feature = "std"))] |
| impl<'a, W: Write> fmt::Write for FmtWrite<'a, W> { |
| fn write_str(&mut self, s: &str) -> fmt::Result { |
| self.0.write_all(s.as_bytes()).map_err(|_| fmt::Error) |
| } |
| } |
| |
| #[cfg(all(not(feature = "std"), not(feature = "unsealed_read_write")))] |
| impl<'a, W> private::Sealed for FmtWrite<'a, W> where W: Write {} |
| |
| /// Implements [`Write`](trait.Write.html) for mutable byte slices (`&mut [u8]`). |
| /// |
| /// Returns an error if the value to serialize is too large to fit in the slice. |
| #[derive(Debug)] |
| pub struct SliceWrite<'a> { |
| slice: &'a mut [u8], |
| index: usize, |
| } |
| |
| impl<'a> SliceWrite<'a> { |
| /// Wraps a mutable slice so it can be used as a `Write`. |
| pub fn new(slice: &'a mut [u8]) -> SliceWrite<'a> { |
| SliceWrite { slice, index: 0 } |
| } |
| |
| /// Returns the number of bytes written to the underlying slice. |
| pub fn bytes_written(&self) -> usize { |
| self.index |
| } |
| |
| /// Returns the underlying slice. |
| pub fn into_inner(self) -> &'a mut [u8] { |
| self.slice |
| } |
| } |
| |
| impl<'a> Write for SliceWrite<'a> { |
| type Error = error::Error; |
| |
| fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { |
| if self.slice.len() - self.index < buf.len() { |
| // This buffer will not fit in our slice |
| return Err(error::Error::scratch_too_small(self.index as u64)); |
| } |
| let end = self.index + buf.len(); |
| self.slice[self.index..end].copy_from_slice(buf); |
| self.index = end; |
| Ok(()) |
| } |
| } |
| |
| #[cfg(not(feature = "unsealed_read_write"))] |
| impl<'a> private::Sealed for SliceWrite<'a> {} |