rmp/encode/
sint.rs

1use super::{write_marker, RmpWrite};
2use crate::encode::{write_pfix, write_u16, write_u32, write_u64, write_u8, ValueWriteError};
3use crate::Marker;
4
5/// Encodes and attempts to write a negative small integer value as a negative fixnum into the
6/// given write.
7///
8/// According to the MessagePack specification, a negative fixed integer value is represented using
9/// a single byte in `[0xe0; 0xff]` range inclusively, prepended with a special marker mask.
10///
11/// The function is **strict** with the input arguments - it is the user's responsibility to check
12/// if the value fits in the described range, otherwise it will panic.
13///
14/// If you are not sure if the value fits in the given range use `write_sint` instead, which
15/// automatically selects the most compact integer representation.
16///
17/// # Errors
18///
19/// This function will return `FixedValueWriteError` on any I/O error occurred while writing the
20/// positive integer marker.
21///
22/// # Panics
23///
24/// Panics if `val` does not fit in `[-32; 0)` range.
25#[inline]
26#[track_caller]
27pub fn write_nfix<W: RmpWrite>(wr: &mut W, val: i8) -> Result<(), W::Error> {
28    assert!(-32 <= val && val < 0);
29    write_marker(wr, Marker::FixNeg(val)).map_err(|e| e.0)?;
30    Ok(())
31}
32
33/// Encodes and attempts to write an `i8` value as a 2-byte sequence into the given write.
34///
35/// The first byte becomes the marker and the second one will represent the data itself.
36///
37/// Note, that this function will encode the given value in 2-byte sequence no matter what, even if
38/// the value can be represented using single byte as a fixnum. Also note, that the first byte will
39/// always be the i8 marker (`0xd0`).
40///
41/// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically
42/// selects the appropriate integer representation.
43///
44/// # Errors
45///
46/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
47/// marker or the data.
48///
49/// # Examples
50///
51/// ```
52/// let mut buf = [0x00, 0x00];
53///
54/// rmp::encode::write_i8(&mut &mut buf[..], 42).ok().unwrap();
55/// assert_eq!([0xd0, 0x2a], buf);
56///
57/// // Note, that -18 can be represented simply as `[0xee]`, but the function emits 2-byte sequence.
58/// rmp::encode::write_i8(&mut &mut buf[..], -18).ok().unwrap();
59/// assert_eq!([0xd0, 0xee], buf);
60/// ```
61pub fn write_i8<W: RmpWrite>(wr: &mut W, val: i8) -> Result<(), ValueWriteError<W::Error>> {
62    write_marker(wr, Marker::I8)?;
63    wr.write_data_i8(val)?;
64    Ok(())
65}
66
67/// Encodes and attempts to write an `i16` value as a 3-byte sequence into the given write.
68///
69/// The first byte becomes the marker and the others will represent the data itself.
70///
71/// Note, that this function will encode the given value in 3-byte sequence no matter what, even if
72/// the value can be represented using single byte as a fixnum. Also note, that the first byte will
73/// always be the i16 marker (`0xd1`).
74///
75/// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically
76/// selects the appropriate integer representation.
77///
78/// # Errors
79///
80/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
81/// marker or the data.
82pub fn write_i16<W: RmpWrite>(wr: &mut W, val: i16) -> Result<(), ValueWriteError<W::Error>> {
83    write_marker(wr, Marker::I16)?;
84    wr.write_data_i16(val)?;
85    Ok(())
86}
87
88/// Encodes and attempts to write an `i32` value as a 5-byte sequence into the given write.
89///
90/// The first byte becomes the marker and the others will represent the data itself.
91///
92/// Note, that this function will encode the given value in 5-byte sequence no matter what, even if
93/// the value can be represented using single byte as a fixnum. Also note, that the first byte will
94/// always be the i32 marker (`0xd2`).
95///
96/// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically
97/// selects the appropriate integer representation.
98///
99/// # Errors
100///
101/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
102/// marker or the data.
103pub fn write_i32<W: RmpWrite>(wr: &mut W, val: i32) -> Result<(), ValueWriteError<W::Error>> {
104    write_marker(wr, Marker::I32)?;
105    wr.write_data_i32(val)?;
106    Ok(())
107}
108
109/// Encodes and attempts to write an `i64` value as a 9-byte sequence into the given write.
110///
111/// The first byte becomes the marker and the others will represent the data itself.
112///
113/// Note, that this function will encode the given value in 9-byte sequence no matter what, even if
114/// the value can be represented using single byte as a fixnum. Also note, that the first byte will
115/// always be the i16 marker (`0xd3`).
116///
117/// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically
118/// selects the appropriate integer representation.
119///
120/// # Errors
121///
122/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
123/// marker or the data.
124pub fn write_i64<W: RmpWrite>(wr: &mut W, val: i64) -> Result<(), ValueWriteError<W::Error>> {
125    write_marker(wr, Marker::I64)?;
126    wr.write_data_i64(val)?;
127    Ok(())
128}
129
130/// Encodes and attempts to write an `i64` value into the given write using the most efficient
131/// representation, returning the marker used.
132///
133/// This function obeys the MessagePack specification, which requires that the serializer SHOULD use
134/// the format which represents the data in the smallest number of bytes, with the exception of
135/// sized/unsized types.
136///
137/// Note, that the function will **always** use signed integer representation even if the value can
138/// be more efficiently represented using unsigned integer encoding.
139///
140/// The first byte becomes the marker and the others (if present, up to 9) will represent the data
141/// itself.
142///
143/// # Errors
144///
145/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
146/// marker or the data.
147pub fn write_sint<W: RmpWrite>(wr: &mut W, val: i64) -> Result<Marker, ValueWriteError<W::Error>> {
148    match val {
149        val if -32 <= val && val < 0 => {
150            write_nfix(wr, val as i8)
151                .and(Ok(Marker::FixNeg(val as i8)))
152                .map_err(ValueWriteError::InvalidMarkerWrite)
153        }
154        val if -128 <= val && val < -32 => write_i8(wr, val as i8).and(Ok(Marker::I8)),
155        val if -32768 <= val && val < -128 => write_i16(wr, val as i16).and(Ok(Marker::I16)),
156        val if -2147483648 <= val && val < -32768 => write_i32(wr, val as i32).and(Ok(Marker::I32)),
157        val if val < -2147483648 => write_i64(wr, val).and(Ok(Marker::I64)),
158        val if 0 <= val && val < 128 => {
159            write_pfix(wr, val as u8)
160                .and(Ok(Marker::FixPos(val as u8)))
161                .map_err(ValueWriteError::InvalidMarkerWrite)
162        }
163        val if val < 256 => write_u8(wr, val as u8).and(Ok(Marker::U8)),
164        val if val < 65536 => write_u16(wr, val as u16).and(Ok(Marker::U16)),
165        val if val < 4294967296 => write_u32(wr, val as u32).and(Ok(Marker::U32)),
166        val => write_u64(wr, val as u64).and(Ok(Marker::U64)),
167    }
168}