/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rmp-0.8.14/src/encode/mod.rs
Line | Count | Source |
1 | | //! Provides various functions and structs for MessagePack encoding. |
2 | | |
3 | | mod bin; |
4 | | mod dec; |
5 | | mod ext; |
6 | | mod map; |
7 | | mod sint; |
8 | | mod str; |
9 | | mod uint; |
10 | | mod vec; |
11 | | |
12 | | pub use self::bin::{write_bin, write_bin_len}; |
13 | | pub use self::dec::{write_f32, write_f64}; |
14 | | pub use self::sint::{write_i16, write_i32, write_i64, write_i8, write_nfix, write_sint}; |
15 | | pub use self::str::{write_str, write_str_len}; |
16 | | pub use self::uint::{write_pfix, write_u16, write_u32, write_u64, write_u8, write_uint, write_uint8}; |
17 | | |
18 | | use core::fmt::{self, Debug, Display, Formatter}; |
19 | | #[cfg(feature = "std")] |
20 | | use std::error; |
21 | | |
22 | | use crate::Marker; |
23 | | |
24 | | pub mod buffer; |
25 | | pub use buffer::ByteBuf; |
26 | | |
27 | | #[doc(inline)] |
28 | | #[allow(deprecated)] |
29 | | pub use crate::errors::Error; |
30 | | |
31 | | /// The error type for operations on the [`RmpWrite`] trait. |
32 | | /// |
33 | | /// For [`std::io::Write`], this is [`std::io::Error`] |
34 | | /// For [`ByteBuf`], this is [`core::convert::Infallible`] |
35 | | pub trait RmpWriteErr: Display + Debug + crate::errors::MaybeErrBound + 'static {} |
36 | | #[cfg(feature = "std")] |
37 | | impl RmpWriteErr for std::io::Error {} |
38 | | impl RmpWriteErr for core::convert::Infallible {} |
39 | | |
40 | | // An error returned from the `write_marker` and `write_fixval` functions. |
41 | | struct MarkerWriteError<E: RmpWriteErr>(E); |
42 | | |
43 | | impl<E: RmpWriteErr> From<E> for MarkerWriteError<E> { |
44 | | #[cold] |
45 | 0 | fn from(err: E) -> Self { |
46 | 0 | MarkerWriteError(err) |
47 | 0 | } |
48 | | } |
49 | | |
50 | | /// Attempts to write the given marker into the writer. |
51 | 0 | fn write_marker<W: RmpWrite>(wr: &mut W, marker: Marker) -> Result<(), MarkerWriteError<W::Error>> { |
52 | 0 | wr.write_u8(marker.to_u8()).map_err(MarkerWriteError) |
53 | 0 | } |
54 | | |
55 | | /// An error returned from primitive values write functions. |
56 | | #[doc(hidden)] |
57 | | pub struct DataWriteError<E: RmpWriteErr>(E); |
58 | | |
59 | | impl<E: RmpWriteErr> From<E> for DataWriteError<E> { |
60 | | #[cold] |
61 | | #[inline] |
62 | 0 | fn from(err: E) -> DataWriteError<E> { |
63 | 0 | DataWriteError(err) |
64 | 0 | } |
65 | | } |
66 | | |
67 | | /// Encodes and attempts to write a nil value into the given write. |
68 | | /// |
69 | | /// According to the MessagePack specification, a nil value is represented as a single `0xc0` byte. |
70 | | /// |
71 | | /// # Errors |
72 | | /// |
73 | | /// This function will return `Error` on any I/O error occurred while writing the nil marker. |
74 | | /// |
75 | | /// # Examples |
76 | | /// |
77 | | /// ``` |
78 | | /// let mut buf = Vec::new(); |
79 | | /// |
80 | | /// rmp::encode::write_nil(&mut buf).unwrap(); |
81 | | /// |
82 | | /// assert_eq!(vec![0xc0], buf); |
83 | | /// ``` |
84 | | #[inline] |
85 | 0 | pub fn write_nil<W: RmpWrite>(wr: &mut W) -> Result<(), W::Error> { |
86 | 0 | write_marker(wr, Marker::Null).map_err(|e| e.0) |
87 | 0 | } |
88 | | |
89 | | /// Encodes and attempts to write a bool value into the given write. |
90 | | /// |
91 | | /// According to the MessagePack specification, an encoded boolean value is represented as a single |
92 | | /// byte. |
93 | | /// |
94 | | /// # Errors |
95 | | /// |
96 | | /// Each call to this function may generate an I/O error indicating that the operation could not be |
97 | | /// completed. |
98 | | #[inline] |
99 | 0 | pub fn write_bool<W: RmpWrite>(wr: &mut W, val: bool) -> Result<(), W::Error> { |
100 | 0 | let marker = if val { Marker::True } else { Marker::False }; |
101 | | |
102 | 0 | write_marker(wr, marker).map_err(|e| e.0) |
103 | 0 | } |
104 | | |
105 | | mod sealed { |
106 | | pub trait Sealed {} |
107 | | #[cfg(feature = "std")] |
108 | | impl<T: ?Sized + std::io::Write> Sealed for T {} |
109 | | #[cfg(not(feature = "std"))] |
110 | | impl Sealed for &mut [u8] {} |
111 | | #[cfg(not(feature = "std"))] |
112 | | impl Sealed for alloc::vec::Vec<u8> {} |
113 | | impl Sealed for super::ByteBuf {} |
114 | | } |
115 | | |
116 | | macro_rules! write_byteorder_utils { |
117 | | ($($name:ident => $tp:ident),* $(,)?) => { |
118 | | $( |
119 | | #[inline] |
120 | | #[doc(hidden)] |
121 | 0 | fn $name(&mut self, val: $tp) -> Result<(), DataWriteError<Self::Error>> where Self: Sized { |
122 | | const SIZE: usize = core::mem::size_of::<$tp>(); |
123 | 0 | let mut buf: [u8; SIZE] = [0u8; SIZE]; |
124 | | paste::paste! { |
125 | 0 | <byteorder::BigEndian as byteorder::ByteOrder>::[<write_ $tp>](&mut buf, val); |
126 | | } |
127 | 0 | self.write_bytes(&buf).map_err(DataWriteError) |
128 | 0 | } Unexecuted instantiation: <_ as rmp::encode::RmpWrite>::write_data_f32 Unexecuted instantiation: <_ as rmp::encode::RmpWrite>::write_data_f64 Unexecuted instantiation: <_ as rmp::encode::RmpWrite>::write_data_i16 Unexecuted instantiation: <_ as rmp::encode::RmpWrite>::write_data_i32 Unexecuted instantiation: <_ as rmp::encode::RmpWrite>::write_data_i64 Unexecuted instantiation: <_ as rmp::encode::RmpWrite>::write_data_u16 Unexecuted instantiation: <_ as rmp::encode::RmpWrite>::write_data_u32 Unexecuted instantiation: <_ as rmp::encode::RmpWrite>::write_data_u64 |
129 | | )* |
130 | | }; |
131 | | } |
132 | | |
133 | | /// A type that `rmp` supports writing into. |
134 | | /// |
135 | | /// The methods of this trait should be considered an implementation detail (for now). |
136 | | /// It is currently sealed (can not be implemented by the user). |
137 | | /// |
138 | | /// See also [`std::io::Write`] and [`byteorder::WriteBytesExt`] |
139 | | /// |
140 | | /// Its primary implementations are [`std::io::Write`] and [`ByteBuf`]. |
141 | | pub trait RmpWrite: sealed::Sealed { |
142 | | type Error: RmpWriteErr; |
143 | | |
144 | | /// Write a single byte to this stream |
145 | | #[inline] |
146 | 0 | fn write_u8(&mut self, val: u8) -> Result<(), Self::Error> { |
147 | 0 | let buf = [val]; |
148 | 0 | self.write_bytes(&buf) |
149 | 0 | } |
150 | | |
151 | | /// Write a slice of bytes to the underlying stream |
152 | | /// |
153 | | /// This will either write all the bytes or return an error. |
154 | | /// See also [`std::io::Write::write_all`] |
155 | | fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error>; |
156 | | |
157 | | // Internal helper functions to map I/O error into the `DataWriteError` error. |
158 | | |
159 | | /// Write a single (signed) byte to this stream. |
160 | | #[inline] |
161 | | #[doc(hidden)] |
162 | 0 | fn write_data_u8(&mut self, val: u8) -> Result<(), DataWriteError<Self::Error>> { |
163 | 0 | self.write_u8(val).map_err(DataWriteError) |
164 | 0 | } |
165 | | /// Write a single (signed) byte to this stream. |
166 | | #[inline] |
167 | | #[doc(hidden)] |
168 | 0 | fn write_data_i8(&mut self, val: i8) -> Result<(), DataWriteError<Self::Error>> { |
169 | 0 | self.write_data_u8(val as u8) |
170 | 0 | } |
171 | | |
172 | | write_byteorder_utils!( |
173 | | write_data_u16 => u16, |
174 | | write_data_u32 => u32, |
175 | | write_data_u64 => u64, |
176 | | write_data_i16 => i16, |
177 | | write_data_i32 => i32, |
178 | | write_data_i64 => i64, |
179 | | write_data_f32 => f32, |
180 | | write_data_f64 => f64 |
181 | | ); |
182 | | } |
183 | | |
184 | | #[cfg(feature = "std")] |
185 | | impl<T: std::io::Write> RmpWrite for T { |
186 | | type Error = std::io::Error; |
187 | | |
188 | | #[inline] |
189 | 0 | fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> { |
190 | 0 | self.write_all(buf) |
191 | 0 | } |
192 | | } |
193 | | |
194 | | /// An error that can occur when attempting to write multi-byte MessagePack value. |
195 | | #[derive(Debug)] |
196 | | #[allow(deprecated)] // TODO: Needed for compatibility |
197 | | pub enum ValueWriteError<E: RmpWriteErr = Error> { |
198 | | /// I/O error while writing marker. |
199 | | InvalidMarkerWrite(E), |
200 | | /// I/O error while writing data. |
201 | | InvalidDataWrite(E), |
202 | | } |
203 | | |
204 | | impl<E: RmpWriteErr> From<MarkerWriteError<E>> for ValueWriteError<E> { |
205 | | #[cold] |
206 | 0 | fn from(err: MarkerWriteError<E>) -> Self { |
207 | 0 | match err { |
208 | 0 | MarkerWriteError(err) => ValueWriteError::InvalidMarkerWrite(err), |
209 | | } |
210 | 0 | } |
211 | | } |
212 | | |
213 | | impl<E: RmpWriteErr> From<DataWriteError<E>> for ValueWriteError<E> { |
214 | | #[cold] |
215 | 0 | fn from(err: DataWriteError<E>) -> Self { |
216 | 0 | match err { |
217 | 0 | DataWriteError(err) => ValueWriteError::InvalidDataWrite(err), |
218 | | } |
219 | 0 | } |
220 | | } |
221 | | |
222 | | #[cfg(feature = "std")] // Backwards compatbility ;) |
223 | | impl From<ValueWriteError<std::io::Error>> for std::io::Error { |
224 | | #[cold] |
225 | 0 | fn from(err: ValueWriteError<std::io::Error>) -> std::io::Error { |
226 | 0 | match err { |
227 | 0 | ValueWriteError::InvalidMarkerWrite(err) | |
228 | 0 | ValueWriteError::InvalidDataWrite(err) => err, |
229 | | } |
230 | 0 | } |
231 | | } |
232 | | |
233 | | #[cfg(feature = "std")] |
234 | | impl<E: RmpWriteErr> error::Error for ValueWriteError<E> { |
235 | | #[cold] |
236 | 0 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { |
237 | 0 | match *self { |
238 | 0 | ValueWriteError::InvalidMarkerWrite(ref err) | |
239 | 0 | ValueWriteError::InvalidDataWrite(ref err) => Some(err), |
240 | | } |
241 | 0 | } |
242 | | } |
243 | | |
244 | | impl<E: RmpWriteErr> Display for ValueWriteError<E> { |
245 | | #[cold] |
246 | 0 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { |
247 | 0 | f.write_str("error while writing multi-byte MessagePack value") |
248 | 0 | } |
249 | | } |
250 | | |
251 | | /// Encodes and attempts to write the most efficient array length implementation to the given write, |
252 | | /// returning the marker used. |
253 | | /// |
254 | | /// # Errors |
255 | | /// |
256 | | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the |
257 | | /// marker or the data. |
258 | 0 | pub fn write_array_len<W: RmpWrite>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError<W::Error>> { |
259 | 0 | let marker = if len < 16 { |
260 | 0 | Marker::FixArray(len as u8) |
261 | 0 | } else if len <= u16::MAX as u32 { |
262 | 0 | Marker::Array16 |
263 | | } else { |
264 | 0 | Marker::Array32 |
265 | | }; |
266 | | |
267 | 0 | write_marker(wr, marker)?; |
268 | 0 | if marker == Marker::Array16 { |
269 | 0 | wr.write_data_u16(len as u16)?; |
270 | 0 | } else if marker == Marker::Array32 { |
271 | 0 | wr.write_data_u32(len)?; |
272 | 0 | } |
273 | 0 | Ok(marker) |
274 | 0 | } |
275 | | |
276 | | /// Encodes and attempts to write the most efficient map length implementation to the given write, |
277 | | /// returning the marker used. |
278 | | /// |
279 | | /// # Errors |
280 | | /// |
281 | | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the |
282 | | /// marker or the data. |
283 | 0 | pub fn write_map_len<W: RmpWrite>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError<W::Error>> { |
284 | 0 | let marker = if len < 16 { |
285 | 0 | Marker::FixMap(len as u8) |
286 | 0 | } else if len <= u16::MAX as u32 { |
287 | 0 | Marker::Map16 |
288 | | } else { |
289 | 0 | Marker::Map32 |
290 | | }; |
291 | | |
292 | 0 | write_marker(wr, marker)?; |
293 | 0 | if marker == Marker::Map16 { |
294 | 0 | wr.write_data_u16(len as u16)?; |
295 | 0 | } else if marker == Marker::Map32 { |
296 | 0 | wr.write_data_u32(len)?; |
297 | 0 | } |
298 | 0 | Ok(marker) |
299 | 0 | } |
300 | | |
301 | | /// Encodes and attempts to write the most efficient ext metadata implementation to the given |
302 | | /// write, returning the marker used. |
303 | | /// |
304 | | /// # Errors |
305 | | /// |
306 | | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the |
307 | | /// marker or the data. |
308 | | /// |
309 | | /// # Panics |
310 | | /// |
311 | | /// Panics if `ty` is negative, because it is reserved for future MessagePack extension including |
312 | | /// 2-byte type information. |
313 | 0 | pub fn write_ext_meta<W: RmpWrite>(wr: &mut W, len: u32, ty: i8) -> Result<Marker, ValueWriteError<W::Error>> { |
314 | 0 | let marker = match len { |
315 | 0 | 1 => Marker::FixExt1, |
316 | 0 | 2 => Marker::FixExt2, |
317 | 0 | 4 => Marker::FixExt4, |
318 | 0 | 8 => Marker::FixExt8, |
319 | 0 | 16 => Marker::FixExt16, |
320 | 0 | 0..=255 => Marker::Ext8, |
321 | 0 | 256..=65535 => Marker::Ext16, |
322 | 0 | _ => Marker::Ext32, |
323 | | }; |
324 | 0 | write_marker(wr, marker)?; |
325 | | |
326 | 0 | if marker == Marker::Ext8 { |
327 | 0 | wr.write_data_u8(len as u8)?; |
328 | 0 | } else if marker == Marker::Ext16 { |
329 | 0 | wr.write_data_u16(len as u16)?; |
330 | 0 | } else if marker == Marker::Ext32 { |
331 | 0 | wr.write_data_u32(len)?; |
332 | 0 | } |
333 | | |
334 | 0 | wr.write_data_i8(ty)?; |
335 | | |
336 | 0 | Ok(marker) |
337 | 0 | } |