rmp/encode/uint.rs
1use std::io::Write;
2
3use Marker;
4use encode::{Error, ValueWriteError};
5use super::{write_data_u8, write_data_u16, write_data_u32, write_data_u64, write_marker};
6
7/// Encodes and attempts to write an unsigned small integer value as a positive fixint into the
8/// given write.
9///
10/// According to the MessagePack specification, a positive fixed integer value is represented using
11/// a single byte in `[0x00; 0x7f]` 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_uint` 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` is greater than 127.
27pub fn write_pfix<W: Write>(wr: &mut W, val: u8) -> Result<(), Error> {
28 assert!(val < 128);
29 try!(write_marker(wr, Marker::FixPos(val)));
30 Ok(())
31}
32
33/// Encodes and attempts to write an `u8` 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 positive fixnum.
39///
40/// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically
41/// selects the appropriate integer representation.
42///
43/// # Errors
44///
45/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
46/// marker or the data.
47///
48/// # Examples
49/// ```
50/// let mut buf = [0x00, 0x00];
51///
52/// rmp::encode::write_u8(&mut &mut buf[..], 146).ok().unwrap();
53/// assert_eq!([0xcc, 0x92], buf);
54///
55/// // Note, that 42 can be represented simply as `[0x2a]`, but the function emits 2-byte sequence.
56/// rmp::encode::write_u8(&mut &mut buf[..], 42).ok().unwrap();
57/// assert_eq!([0xcc, 0x2a], buf);
58/// ```
59pub fn write_u8<W: Write>(wr: &mut W, val: u8) -> Result<(), ValueWriteError> {
60 try!(write_marker(wr, Marker::U8));
61 try!(write_data_u8(wr, val));
62 Ok(())
63}
64
65/// Encodes and attempts to write an `u16` value strictly as a 3-byte sequence into the given write.
66///
67/// The first byte becomes the marker and the others will represent the data itself.
68///
69/// Note, that this function will encode the given value in 3-byte sequence no matter what, even if
70/// the value can be represented using single byte as a positive fixnum.
71///
72/// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically
73/// selects the appropriate integer representation.
74///
75/// # Errors
76///
77/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
78/// marker or the data.
79pub fn write_u16<W: Write>(wr: &mut W, val: u16) -> Result<(), ValueWriteError> {
80 try!(write_marker(wr, Marker::U16));
81 try!(write_data_u16(wr, val));
82 Ok(())
83}
84
85/// Encodes and attempts to write an `u32` value strictly as a 5-byte sequence into the given write.
86///
87/// The first byte becomes the marker and the others will represent the data itself.
88///
89/// Note, that this function will encode the given value in 5-byte sequence no matter what, even if
90/// the value can be represented using single byte as a positive fixnum.
91///
92/// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically
93/// selects the appropriate integer representation.
94///
95/// # Errors
96///
97/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
98/// marker or the data.
99pub fn write_u32<W: Write>(wr: &mut W, val: u32) -> Result<(), ValueWriteError> {
100 try!(write_marker(wr, Marker::U32));
101 try!(write_data_u32(wr, val));
102 Ok(())
103}
104
105/// Encodes and attempts to write an `u64` value strictly as a 9-byte sequence into the given write.
106///
107/// The first byte becomes the marker and the others will represent the data itself.
108///
109/// Note, that this function will encode the given value in 9-byte sequence no matter what, even if
110/// the value can be represented using single byte as a positive fixnum.
111///
112/// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically
113/// selects the appropriate integer representation.
114///
115/// # Errors
116///
117/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
118/// marker or the data.
119pub fn write_u64<W: Write>(wr: &mut W, val: u64) -> Result<(), ValueWriteError> {
120 try!(write_marker(wr, Marker::U64));
121 try!(write_data_u64(wr, val));
122 Ok(())
123}
124
125/// Encodes and attempts to write an `u64` value into the given write using the most efficient
126/// representation, returning the marker used.
127///
128/// This function obeys the MessagePack specification, which requires that the serializer SHOULD use
129/// the format which represents the data in the smallest number of bytes.
130///
131/// The first byte becomes the marker and the others (if present, up to 9) will represent the data
132/// itself.
133///
134/// # Errors
135///
136/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
137/// marker or the data.
138pub fn write_uint<W: Write>(wr: &mut W, val: u64) -> Result<Marker, ValueWriteError> {
139 if val < 128 {
140 write_pfix(wr, val as u8)
141 .and(Ok(Marker::FixPos(val as u8)))
142 .map_err(ValueWriteError::InvalidMarkerWrite)
143 } else if val < 256 {
144 write_u8(wr, val as u8).and(Ok(Marker::U8))
145 } else if val < 65536 {
146 write_u16(wr, val as u16).and(Ok(Marker::U16))
147 } else if val < 4294967296 {
148 write_u32(wr, val as u32).and(Ok(Marker::U32))
149 } else {
150 write_u64(wr, val).and(Ok(Marker::U64))
151 }
152}