Source code

Revision control

Copy as Markdown

Other Tools

#[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> {}