rmp/encode/
mod.rs
1mod bin;
4mod dec;
5mod ext;
6mod map;
7mod sint;
8mod str;
9mod uint;
10mod vec;
11
12pub use self::bin::{write_bin, write_bin_len};
13pub use self::dec::{write_f32, write_f64};
14pub use self::sint::{write_i16, write_i32, write_i64, write_i8, write_nfix, write_sint};
15pub use self::str::{write_str, write_str_len};
16pub use self::uint::{write_pfix, write_u16, write_u32, write_u64, write_u8, write_uint, write_uint8};
17
18use core::fmt::{self, Debug, Display, Formatter};
19#[cfg(feature = "std")]
20use std::error;
21
22use crate::Marker;
23
24pub mod buffer;
25pub use buffer::ByteBuf;
26
27#[doc(inline)]
28#[allow(deprecated)]
29pub use crate::errors::Error;
30
31pub trait RmpWriteErr: Display + Debug + crate::errors::MaybeErrBound + 'static {}
36#[cfg(feature = "std")]
37impl RmpWriteErr for std::io::Error {}
38impl RmpWriteErr for core::convert::Infallible {}
39
40struct MarkerWriteError<E: RmpWriteErr>(E);
42
43impl<E: RmpWriteErr> From<E> for MarkerWriteError<E> {
44 #[cold]
45 fn from(err: E) -> Self {
46 MarkerWriteError(err)
47 }
48}
49
50fn write_marker<W: RmpWrite>(wr: &mut W, marker: Marker) -> Result<(), MarkerWriteError<W::Error>> {
52 wr.write_u8(marker.to_u8()).map_err(MarkerWriteError)
53}
54
55#[doc(hidden)]
57pub struct DataWriteError<E: RmpWriteErr>(E);
58
59impl<E: RmpWriteErr> From<E> for DataWriteError<E> {
60 #[cold]
61 #[inline]
62 fn from(err: E) -> DataWriteError<E> {
63 DataWriteError(err)
64 }
65}
66
67#[inline]
85pub fn write_nil<W: RmpWrite>(wr: &mut W) -> Result<(), W::Error> {
86 write_marker(wr, Marker::Null).map_err(|e| e.0)
87}
88
89#[inline]
99pub fn write_bool<W: RmpWrite>(wr: &mut W, val: bool) -> Result<(), W::Error> {
100 let marker = if val { Marker::True } else { Marker::False };
101
102 write_marker(wr, marker).map_err(|e| e.0)
103}
104
105mod 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
116macro_rules! write_byteorder_utils {
117 ($($name:ident => $tp:ident),* $(,)?) => {
118 $(
119 #[inline]
120 #[doc(hidden)]
121 fn $name(&mut self, val: $tp) -> Result<(), DataWriteError<Self::Error>> where Self: Sized {
122 const SIZE: usize = core::mem::size_of::<$tp>();
123 let mut buf: [u8; SIZE] = [0u8; SIZE];
124 paste::paste! {
125 <byteorder::BigEndian as byteorder::ByteOrder>::[<write_ $tp>](&mut buf, val);
126 }
127 self.write_bytes(&buf).map_err(DataWriteError)
128 }
129 )*
130 };
131}
132
133pub trait RmpWrite: sealed::Sealed {
142 type Error: RmpWriteErr;
143
144 #[inline]
146 fn write_u8(&mut self, val: u8) -> Result<(), Self::Error> {
147 let buf = [val];
148 self.write_bytes(&buf)
149 }
150
151 fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
156
157 #[inline]
161 #[doc(hidden)]
162 fn write_data_u8(&mut self, val: u8) -> Result<(), DataWriteError<Self::Error>> {
163 self.write_u8(val).map_err(DataWriteError)
164 }
165 #[inline]
167 #[doc(hidden)]
168 fn write_data_i8(&mut self, val: i8) -> Result<(), DataWriteError<Self::Error>> {
169 self.write_data_u8(val as u8)
170 }
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")]
185impl<T: std::io::Write> RmpWrite for T {
186 type Error = std::io::Error;
187
188 #[inline]
189 fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
190 self.write_all(buf)
191 }
192}
193
194#[derive(Debug)]
196#[allow(deprecated)] pub enum ValueWriteError<E: RmpWriteErr = Error> {
198 InvalidMarkerWrite(E),
200 InvalidDataWrite(E),
202}
203
204impl<E: RmpWriteErr> From<MarkerWriteError<E>> for ValueWriteError<E> {
205 #[cold]
206 fn from(err: MarkerWriteError<E>) -> Self {
207 match err {
208 MarkerWriteError(err) => ValueWriteError::InvalidMarkerWrite(err),
209 }
210 }
211}
212
213impl<E: RmpWriteErr> From<DataWriteError<E>> for ValueWriteError<E> {
214 #[cold]
215 fn from(err: DataWriteError<E>) -> Self {
216 match err {
217 DataWriteError(err) => ValueWriteError::InvalidDataWrite(err),
218 }
219 }
220}
221
222#[cfg(feature = "std")] impl From<ValueWriteError<std::io::Error>> for std::io::Error {
224 #[cold]
225 fn from(err: ValueWriteError<std::io::Error>) -> std::io::Error {
226 match err {
227 ValueWriteError::InvalidMarkerWrite(err) |
228 ValueWriteError::InvalidDataWrite(err) => err,
229 }
230 }
231}
232
233#[cfg(feature = "std")]
234impl<E: RmpWriteErr> error::Error for ValueWriteError<E> {
235 #[cold]
236 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
237 match *self {
238 ValueWriteError::InvalidMarkerWrite(ref err) |
239 ValueWriteError::InvalidDataWrite(ref err) => Some(err),
240 }
241 }
242}
243
244impl<E: RmpWriteErr> Display for ValueWriteError<E> {
245 #[cold]
246 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
247 f.write_str("error while writing multi-byte MessagePack value")
248 }
249}
250
251pub fn write_array_len<W: RmpWrite>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError<W::Error>> {
259 let marker = if len < 16 {
260 Marker::FixArray(len as u8)
261 } else if len <= u16::MAX as u32 {
262 Marker::Array16
263 } else {
264 Marker::Array32
265 };
266
267 write_marker(wr, marker)?;
268 if marker == Marker::Array16 {
269 wr.write_data_u16(len as u16)?;
270 } else if marker == Marker::Array32 {
271 wr.write_data_u32(len)?;
272 }
273 Ok(marker)
274}
275
276pub fn write_map_len<W: RmpWrite>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError<W::Error>> {
284 let marker = if len < 16 {
285 Marker::FixMap(len as u8)
286 } else if len <= u16::MAX as u32 {
287 Marker::Map16
288 } else {
289 Marker::Map32
290 };
291
292 write_marker(wr, marker)?;
293 if marker == Marker::Map16 {
294 wr.write_data_u16(len as u16)?;
295 } else if marker == Marker::Map32 {
296 wr.write_data_u32(len)?;
297 }
298 Ok(marker)
299}
300
301pub fn write_ext_meta<W: RmpWrite>(wr: &mut W, len: u32, ty: i8) -> Result<Marker, ValueWriteError<W::Error>> {
314 let marker = match len {
315 1 => Marker::FixExt1,
316 2 => Marker::FixExt2,
317 4 => Marker::FixExt4,
318 8 => Marker::FixExt8,
319 16 => Marker::FixExt16,
320 0..=255 => Marker::Ext8,
321 256..=65535 => Marker::Ext16,
322 _ => Marker::Ext32,
323 };
324 write_marker(wr, marker)?;
325
326 if marker == Marker::Ext8 {
327 wr.write_data_u8(len as u8)?;
328 } else if marker == Marker::Ext16 {
329 wr.write_data_u16(len as u16)?;
330 } else if marker == Marker::Ext32 {
331 wr.write_data_u32(len)?;
332 }
333
334 wr.write_data_i8(ty)?;
335
336 Ok(marker)
337}