/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rmp-0.8.15/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 | Self(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) -> Self { |
63 | 0 | Self(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 | 0 | self.write_bytes(&val.to_be_bytes()).map_err(DataWriteError) |
123 | 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 |
124 | | )* |
125 | | }; |
126 | | } |
127 | | |
128 | | /// A type that `rmp` supports writing into. |
129 | | /// |
130 | | /// The methods of this trait should be considered an implementation detail (for now). |
131 | | /// It is currently sealed (can not be implemented by the user). |
132 | | /// |
133 | | /// Its primary implementations are [`std::io::Write`] and [`ByteBuf`]. |
134 | | pub trait RmpWrite: sealed::Sealed { |
135 | | type Error: RmpWriteErr; |
136 | | |
137 | | /// Write a single byte to this stream |
138 | | #[inline] |
139 | 0 | fn write_u8(&mut self, val: u8) -> Result<(), Self::Error> { |
140 | 0 | let buf = [val]; |
141 | 0 | self.write_bytes(&buf) |
142 | 0 | } |
143 | | |
144 | | /// Write a slice of bytes to the underlying stream |
145 | | /// |
146 | | /// This will either write all the bytes or return an error. |
147 | | /// See also [`std::io::Write::write_all`] |
148 | | fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error>; |
149 | | |
150 | | // Internal helper functions to map I/O error into the `DataWriteError` error. |
151 | | |
152 | | /// Write a single (signed) byte to this stream. |
153 | | #[inline] |
154 | | #[doc(hidden)] |
155 | 0 | fn write_data_u8(&mut self, val: u8) -> Result<(), DataWriteError<Self::Error>> { |
156 | 0 | self.write_u8(val).map_err(DataWriteError) |
157 | 0 | } |
158 | | /// Write a single (signed) byte to this stream. |
159 | | #[inline] |
160 | | #[doc(hidden)] |
161 | 0 | fn write_data_i8(&mut self, val: i8) -> Result<(), DataWriteError<Self::Error>> { |
162 | 0 | self.write_data_u8(val as u8) |
163 | 0 | } |
164 | | |
165 | | write_byteorder_utils!( |
166 | | write_data_u16 => u16, |
167 | | write_data_u32 => u32, |
168 | | write_data_u64 => u64, |
169 | | write_data_i16 => i16, |
170 | | write_data_i32 => i32, |
171 | | write_data_i64 => i64, |
172 | | write_data_f32 => f32, |
173 | | write_data_f64 => f64 |
174 | | ); |
175 | | } |
176 | | |
177 | | #[cfg(feature = "std")] |
178 | | impl<T: std::io::Write> RmpWrite for T { |
179 | | type Error = std::io::Error; |
180 | | |
181 | | #[inline] |
182 | 0 | fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> { |
183 | 0 | self.write_all(buf) |
184 | 0 | } |
185 | | } |
186 | | |
187 | | /// An error that can occur when attempting to write multi-byte MessagePack value. |
188 | | #[derive(Debug)] |
189 | | #[allow(deprecated)] // TODO: Needed for compatibility |
190 | | pub enum ValueWriteError<E: RmpWriteErr = Error> { |
191 | | /// I/O error while writing marker. |
192 | | InvalidMarkerWrite(E), |
193 | | /// I/O error while writing data. |
194 | | InvalidDataWrite(E), |
195 | | } |
196 | | |
197 | | impl<E: RmpWriteErr> From<MarkerWriteError<E>> for ValueWriteError<E> { |
198 | | #[cold] |
199 | 0 | fn from(err: MarkerWriteError<E>) -> Self { |
200 | 0 | match err { |
201 | 0 | MarkerWriteError(err) => Self::InvalidMarkerWrite(err), |
202 | | } |
203 | 0 | } |
204 | | } |
205 | | |
206 | | impl<E: RmpWriteErr> From<DataWriteError<E>> for ValueWriteError<E> { |
207 | | #[cold] |
208 | 0 | fn from(err: DataWriteError<E>) -> Self { |
209 | 0 | match err { |
210 | 0 | DataWriteError(err) => Self::InvalidDataWrite(err), |
211 | | } |
212 | 0 | } |
213 | | } |
214 | | |
215 | | #[cfg(feature = "std")] // Backwards compatbility ;) |
216 | | impl From<ValueWriteError<Self>> for std::io::Error { |
217 | | #[cold] |
218 | 0 | fn from(err: ValueWriteError<Self>) -> Self { |
219 | 0 | match err { |
220 | 0 | ValueWriteError::InvalidMarkerWrite(err) | |
221 | 0 | ValueWriteError::InvalidDataWrite(err) => err, |
222 | | } |
223 | 0 | } |
224 | | } |
225 | | |
226 | | #[cfg(feature = "std")] |
227 | | impl<E: RmpWriteErr> error::Error for ValueWriteError<E> { |
228 | | #[cold] |
229 | 0 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { |
230 | 0 | match *self { |
231 | 0 | Self::InvalidMarkerWrite(ref err) | |
232 | 0 | Self::InvalidDataWrite(ref err) => Some(err), |
233 | | } |
234 | 0 | } Unexecuted instantiation: <rmp::encode::ValueWriteError as core::error::Error>::source Unexecuted instantiation: <rmp::encode::ValueWriteError<_> as core::error::Error>::source |
235 | | } |
236 | | |
237 | | impl<E: RmpWriteErr> Display for ValueWriteError<E> { |
238 | | #[cold] |
239 | 0 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { |
240 | 0 | f.write_str("error while writing multi-byte MessagePack value") |
241 | 0 | } Unexecuted instantiation: <rmp::encode::ValueWriteError as core::fmt::Display>::fmt Unexecuted instantiation: <rmp::encode::ValueWriteError<_> as core::fmt::Display>::fmt |
242 | | } |
243 | | |
244 | | /// Encodes and attempts to write the most efficient array length implementation to the given write, |
245 | | /// returning the marker used. |
246 | | /// |
247 | | /// # Errors |
248 | | /// |
249 | | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the |
250 | | /// marker or the data. |
251 | 0 | pub fn write_array_len<W: RmpWrite>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError<W::Error>> { |
252 | 0 | let marker = if len < 16 { |
253 | 0 | Marker::FixArray(len as u8) |
254 | 0 | } else if u16::try_from(len).is_ok() { |
255 | 0 | Marker::Array16 |
256 | | } else { |
257 | 0 | Marker::Array32 |
258 | | }; |
259 | | |
260 | 0 | write_marker(wr, marker)?; |
261 | 0 | if marker == Marker::Array16 { |
262 | 0 | wr.write_data_u16(len as u16)?; |
263 | 0 | } else if marker == Marker::Array32 { |
264 | 0 | wr.write_data_u32(len)?; |
265 | 0 | } |
266 | 0 | Ok(marker) |
267 | 0 | } |
268 | | |
269 | | /// Encodes and attempts to write the most efficient map length implementation to the given write, |
270 | | /// returning the marker used. |
271 | | /// |
272 | | /// # Errors |
273 | | /// |
274 | | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the |
275 | | /// marker or the data. |
276 | 0 | pub fn write_map_len<W: RmpWrite>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError<W::Error>> { |
277 | 0 | let marker = if len < 16 { |
278 | 0 | Marker::FixMap(len as u8) |
279 | 0 | } else if u16::try_from(len).is_ok() { |
280 | 0 | Marker::Map16 |
281 | | } else { |
282 | 0 | Marker::Map32 |
283 | | }; |
284 | | |
285 | 0 | write_marker(wr, marker)?; |
286 | 0 | if marker == Marker::Map16 { |
287 | 0 | wr.write_data_u16(len as u16)?; |
288 | 0 | } else if marker == Marker::Map32 { |
289 | 0 | wr.write_data_u32(len)?; |
290 | 0 | } |
291 | 0 | Ok(marker) |
292 | 0 | } |
293 | | |
294 | | /// Encodes and attempts to write the most efficient ext metadata implementation to the given |
295 | | /// write, returning the marker used. |
296 | | /// |
297 | | /// # Errors |
298 | | /// |
299 | | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the |
300 | | /// marker or the data. |
301 | | /// |
302 | | /// # Panics |
303 | | /// |
304 | | /// Panics if `ty` is negative, because it is reserved for future MessagePack extension including |
305 | | /// 2-byte type information. |
306 | 0 | pub fn write_ext_meta<W: RmpWrite>(wr: &mut W, len: u32, ty: i8) -> Result<Marker, ValueWriteError<W::Error>> { |
307 | 0 | let marker = match len { |
308 | 0 | 1 => Marker::FixExt1, |
309 | 0 | 2 => Marker::FixExt2, |
310 | 0 | 4 => Marker::FixExt4, |
311 | 0 | 8 => Marker::FixExt8, |
312 | 0 | 16 => Marker::FixExt16, |
313 | 0 | 0..=255 => Marker::Ext8, |
314 | 0 | 256..=65535 => Marker::Ext16, |
315 | 0 | _ => Marker::Ext32, |
316 | | }; |
317 | 0 | write_marker(wr, marker)?; |
318 | | |
319 | 0 | if marker == Marker::Ext8 { |
320 | 0 | wr.write_data_u8(len as u8)?; |
321 | 0 | } else if marker == Marker::Ext16 { |
322 | 0 | wr.write_data_u16(len as u16)?; |
323 | 0 | } else if marker == Marker::Ext32 { |
324 | 0 | wr.write_data_u32(len)?; |
325 | 0 | } |
326 | | |
327 | 0 | wr.write_data_i8(ty)?; |
328 | | |
329 | 0 | Ok(marker) |
330 | 0 | } |