#[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; /// 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; /// 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 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 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); #[cfg(feature = "std")] impl IoWrite { /// Wraps an `io::Write` writer to make it compatible with [`Write`](trait.Write.html) pub fn new(w: W) -> IoWrite { IoWrite(w) } } #[cfg(feature = "std")] impl Write for IoWrite { 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 private::Sealed for IoWrite where W: io::Write {} #[cfg(any(feature = "std", feature = "alloc"))] impl Write for Vec { 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 {} #[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> {}