1 use std::io::Write;
2 
3 use crate::Marker;
4 use crate::encode::{write_pfix, write_u8, write_u16, write_u32, write_u64, Error, ValueWriteError};
5 use super::{write_data_i8, write_data_i16, write_data_i32, write_data_i64, write_marker};
6 
7 /// Encodes and attempts to write a negative small integer value as a negative fixnum into the
8 /// given write.
9 ///
10 /// According to the MessagePack specification, a negative fixed integer value is represented using
11 /// a single byte in `[0xe0; 0xff]` range inclusively, prepended with a special marker mask.
12 ///
13 /// The function is **strict** with the input arguments - it is the user's responsibility to check
14 /// if the value fits in the described range, otherwise it will panic.
15 ///
16 /// If you are not sure if the value fits in the given range use `write_sint` instead, which
17 /// automatically selects the most compact integer representation.
18 ///
19 /// # Errors
20 ///
21 /// This function will return `FixedValueWriteError` on any I/O error occurred while writing the
22 /// positive integer marker.
23 ///
24 /// # Panics
25 ///
26 /// Panics if `val` does not fit in `[-32; 0)` range.
write_nfix<W: Write>(wr: &mut W, val: i8) -> Result<(), Error>27 pub fn write_nfix<W: Write>(wr: &mut W, val: i8) -> Result<(), Error> {
28     assert!(-32 <= val && val < 0);
29     write_marker(wr, Marker::FixNeg(val))?;
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 /// ```
write_i8<W: Write>(wr: &mut W, val: i8) -> Result<(), ValueWriteError>61 pub fn write_i8<W: Write>(wr: &mut W, val: i8) -> Result<(), ValueWriteError> {
62     write_marker(wr, Marker::I8)?;
63     write_data_i8(wr, 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.
write_i16<W: Write>(wr: &mut W, val: i16) -> Result<(), ValueWriteError>82 pub fn write_i16<W: Write>(wr: &mut W, val: i16) -> Result<(), ValueWriteError> {
83     write_marker(wr, Marker::I16)?;
84     write_data_i16(wr, 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.
write_i32<W: Write>(wr: &mut W, val: i32) -> Result<(), ValueWriteError>103 pub fn write_i32<W: Write>(wr: &mut W, val: i32) -> Result<(), ValueWriteError> {
104     write_marker(wr, Marker::I32)?;
105     write_data_i32(wr, 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.
write_i64<W: Write>(wr: &mut W, val: i64) -> Result<(), ValueWriteError>124 pub fn write_i64<W: Write>(wr: &mut W, val: i64) -> Result<(), ValueWriteError> {
125     write_marker(wr, Marker::I64)?;
126     write_data_i64(wr, 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.
write_sint<W: Write>(wr: &mut W, val: i64) -> Result<Marker, ValueWriteError>147 pub fn write_sint<W: Write>(wr: &mut W, val: i64) -> Result<Marker, ValueWriteError> {
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 }
169