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 Self(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) -> Self {
63 Self(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 self.write_bytes(&val.to_be_bytes()).map_err(DataWriteError)
123 }
124 )*
125 };
126}
127
128pub trait RmpWrite: sealed::Sealed {
135 type Error: RmpWriteErr;
136
137 #[inline]
139 fn write_u8(&mut self, val: u8) -> Result<(), Self::Error> {
140 let buf = [val];
141 self.write_bytes(&buf)
142 }
143
144 fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
149
150 #[inline]
154 #[doc(hidden)]
155 fn write_data_u8(&mut self, val: u8) -> Result<(), DataWriteError<Self::Error>> {
156 self.write_u8(val).map_err(DataWriteError)
157 }
158 #[inline]
160 #[doc(hidden)]
161 fn write_data_i8(&mut self, val: i8) -> Result<(), DataWriteError<Self::Error>> {
162 self.write_data_u8(val as u8)
163 }
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")]
178impl<T: std::io::Write> RmpWrite for T {
179 type Error = std::io::Error;
180
181 #[inline]
182 fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
183 self.write_all(buf)
184 }
185}
186
187#[derive(Debug)]
189#[allow(deprecated)] pub enum ValueWriteError<E: RmpWriteErr = Error> {
191 InvalidMarkerWrite(E),
193 InvalidDataWrite(E),
195}
196
197impl<E: RmpWriteErr> From<MarkerWriteError<E>> for ValueWriteError<E> {
198 #[cold]
199 fn from(err: MarkerWriteError<E>) -> Self {
200 match err {
201 MarkerWriteError(err) => Self::InvalidMarkerWrite(err),
202 }
203 }
204}
205
206impl<E: RmpWriteErr> From<DataWriteError<E>> for ValueWriteError<E> {
207 #[cold]
208 fn from(err: DataWriteError<E>) -> Self {
209 match err {
210 DataWriteError(err) => Self::InvalidDataWrite(err),
211 }
212 }
213}
214
215#[cfg(feature = "std")] impl From<ValueWriteError<Self>> for std::io::Error {
217 #[cold]
218 fn from(err: ValueWriteError<Self>) -> Self {
219 match err {
220 ValueWriteError::InvalidMarkerWrite(err) |
221 ValueWriteError::InvalidDataWrite(err) => err,
222 }
223 }
224}
225
226#[cfg(feature = "std")]
227impl<E: RmpWriteErr> error::Error for ValueWriteError<E> {
228 #[cold]
229 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
230 match *self {
231 Self::InvalidMarkerWrite(ref err) |
232 Self::InvalidDataWrite(ref err) => Some(err),
233 }
234 }
235}
236
237impl<E: RmpWriteErr> Display for ValueWriteError<E> {
238 #[cold]
239 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
240 f.write_str("error while writing multi-byte MessagePack value")
241 }
242}
243
244pub fn write_array_len<W: RmpWrite>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError<W::Error>> {
252 let marker = if len < 16 {
253 Marker::FixArray(len as u8)
254 } else if u16::try_from(len).is_ok() {
255 Marker::Array16
256 } else {
257 Marker::Array32
258 };
259
260 write_marker(wr, marker)?;
261 if marker == Marker::Array16 {
262 wr.write_data_u16(len as u16)?;
263 } else if marker == Marker::Array32 {
264 wr.write_data_u32(len)?;
265 }
266 Ok(marker)
267}
268
269pub fn write_map_len<W: RmpWrite>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError<W::Error>> {
277 let marker = if len < 16 {
278 Marker::FixMap(len as u8)
279 } else if u16::try_from(len).is_ok() {
280 Marker::Map16
281 } else {
282 Marker::Map32
283 };
284
285 write_marker(wr, marker)?;
286 if marker == Marker::Map16 {
287 wr.write_data_u16(len as u16)?;
288 } else if marker == Marker::Map32 {
289 wr.write_data_u32(len)?;
290 }
291 Ok(marker)
292}
293
294pub fn write_ext_meta<W: RmpWrite>(wr: &mut W, len: u32, ty: i8) -> Result<Marker, ValueWriteError<W::Error>> {
307 let marker = match len {
308 1 => Marker::FixExt1,
309 2 => Marker::FixExt2,
310 4 => Marker::FixExt4,
311 8 => Marker::FixExt8,
312 16 => Marker::FixExt16,
313 0..=255 => Marker::Ext8,
314 256..=65535 => Marker::Ext16,
315 _ => Marker::Ext32,
316 };
317 write_marker(wr, marker)?;
318
319 if marker == Marker::Ext8 {
320 wr.write_data_u8(len as u8)?;
321 } else if marker == Marker::Ext16 {
322 wr.write_data_u16(len as u16)?;
323 } else if marker == Marker::Ext32 {
324 wr.write_data_u32(len)?;
325 }
326
327 wr.write_data_i8(ty)?;
328
329 Ok(marker)
330}