1 #[cfg(feature = "alloc")] 2 use alloc::vec::Vec; 3 #[cfg(not(feature = "std"))] 4 use core::fmt; 5 #[cfg(feature = "std")] 6 use std::io; 7 8 use crate::error; 9 10 #[cfg(not(feature = "unsealed_read_write"))] 11 /// A sink for serialized CBOR. 12 /// 13 /// This trait is similar to the [`Write`]() trait in the standard library, 14 /// but has a smaller and more general API. 15 /// 16 /// Any object implementing `std::io::Write` 17 /// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements 18 /// this trait for the underlying object. 19 pub trait Write: private::Sealed { 20 /// The type of error returned when a write operation fails. 21 #[doc(hidden)] 22 type Error: Into<error::Error>; 23 24 /// Attempts to write an entire buffer into this write. 25 #[doc(hidden)] write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>26 fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>; 27 } 28 29 #[cfg(feature = "unsealed_read_write")] 30 /// A sink for serialized CBOR. 31 /// 32 /// This trait is similar to the [`Write`]() trait in the standard library, 33 /// but has a smaller and more general API. 34 /// 35 /// Any object implementing `std::io::Write` 36 /// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements 37 /// this trait for the underlying object. 38 /// 39 /// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound 40 /// to allow objects outside of this crate to implement this trait. 41 pub trait Write { 42 /// The type of error returned when a write operation fails. 43 type Error: Into<error::Error>; 44 45 /// Attempts to write an entire buffer into this write. write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>46 fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>; 47 } 48 49 #[cfg(not(feature = "unsealed_read_write"))] 50 mod private { 51 pub trait Sealed {} 52 } 53 54 impl<W> Write for &mut W 55 where 56 W: Write, 57 { 58 type Error = W::Error; 59 write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>60 fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { 61 (*self).write_all(buf) 62 } 63 } 64 65 #[cfg(not(feature = "unsealed_read_write"))] 66 impl<W> private::Sealed for &mut W where W: Write {} 67 68 #[cfg(feature = "std")] 69 /// A wrapper for types that implement 70 /// [`std::io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html) to implement the local 71 /// [`Write`](trait.Write.html) trait. 72 #[derive(Debug)] 73 pub struct IoWrite<W>(W); 74 75 #[cfg(feature = "std")] 76 impl<W: io::Write> IoWrite<W> { 77 /// Wraps an `io::Write` writer to make it compatible with [`Write`](trait.Write.html) new(w: W) -> IoWrite<W>78 pub fn new(w: W) -> IoWrite<W> { 79 IoWrite(w) 80 } 81 } 82 83 #[cfg(feature = "std")] 84 impl<W: io::Write> Write for IoWrite<W> { 85 type Error = io::Error; 86 write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>87 fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { 88 self.0.write_all(buf) 89 } 90 } 91 92 #[cfg(all(feature = "std", not(feature = "unsealed_read_write")))] 93 impl<W> private::Sealed for IoWrite<W> where W: io::Write {} 94 95 #[cfg(any(feature = "std", feature = "alloc"))] 96 impl Write for Vec<u8> { 97 type Error = error::Error; 98 write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>99 fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { 100 self.extend_from_slice(buf); 101 Ok(()) 102 } 103 } 104 105 #[cfg(all( 106 any(feature = "std", feature = "alloc"), 107 not(feature = "unsealed_read_write") 108 ))] 109 impl private::Sealed for Vec<u8> {} 110 111 #[cfg(not(feature = "std"))] 112 #[derive(Debug)] 113 pub struct FmtWrite<'a, W: Write>(&'a mut W); 114 115 #[cfg(not(feature = "std"))] 116 impl<'a, W: Write> FmtWrite<'a, W> { 117 /// Wraps an `fmt::Write` writer to make it compatible with [`Write`](trait.Write.html) new(w: &'a mut W) -> FmtWrite<'a, W>118 pub fn new(w: &'a mut W) -> FmtWrite<'a, W> { 119 FmtWrite(w) 120 } 121 } 122 123 #[cfg(not(feature = "std"))] 124 impl<'a, W: Write> fmt::Write for FmtWrite<'a, W> { write_str(&mut self, s: &str) -> fmt::Result125 fn write_str(&mut self, s: &str) -> fmt::Result { 126 self.0.write_all(s.as_bytes()).map_err(|_| fmt::Error) 127 } 128 } 129 130 #[cfg(all(not(feature = "std"), not(feature = "unsealed_read_write")))] 131 impl<'a, W> private::Sealed for FmtWrite<'a, W> where W: Write {} 132 133 /// Implements [`Write`](trait.Write.html) for mutable byte slices (`&mut [u8]`). 134 /// 135 /// Returns an error if the value to serialize is too large to fit in the slice. 136 #[derive(Debug)] 137 pub struct SliceWrite<'a> { 138 slice: &'a mut [u8], 139 index: usize, 140 } 141 142 impl<'a> SliceWrite<'a> { 143 /// Wraps a mutable slice so it can be used as a `Write`. new(slice: &'a mut [u8]) -> SliceWrite<'a>144 pub fn new(slice: &'a mut [u8]) -> SliceWrite<'a> { 145 SliceWrite { slice, index: 0 } 146 } 147 148 /// Returns the number of bytes written to the underlying slice. bytes_written(&self) -> usize149 pub fn bytes_written(&self) -> usize { 150 self.index 151 } 152 153 /// Returns the underlying slice. into_inner(self) -> &'a mut [u8]154 pub fn into_inner(self) -> &'a mut [u8] { 155 self.slice 156 } 157 } 158 159 impl<'a> Write for SliceWrite<'a> { 160 type Error = error::Error; 161 write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>162 fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { 163 if self.slice.len() - self.index < buf.len() { 164 // This buffer will not fit in our slice 165 return Err(error::Error::scratch_too_small(self.index as u64)); 166 } 167 let end = self.index + buf.len(); 168 self.slice[self.index..end].copy_from_slice(buf); 169 self.index = end; 170 Ok(()) 171 } 172 } 173 174 #[cfg(not(feature = "unsealed_read_write"))] 175 impl<'a> private::Sealed for SliceWrite<'a> {} 176