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