rmp/encode/
mod.rs

1//! Provides various functions and structs for MessagePack encoding.
2
3mod sint;
4mod uint;
5mod dec;
6mod str;
7mod bin;
8mod vec;
9mod map;
10mod ext;
11
12pub use self::sint::{write_nfix, write_i8, write_i16, write_i32, write_i64, write_sint};
13pub use self::uint::{write_pfix, write_u8, write_u16, write_u32, write_u64, write_uint};
14pub use self::dec::{write_f32, write_f64};
15pub use self::str::{write_str_len, write_str};
16pub use self::bin::{write_bin_len, write_bin};
17
18use std::error;
19use std::fmt::{self, Display, Formatter};
20use std::io::Write;
21
22use byteorder::{self, WriteBytesExt};
23
24use Marker;
25
26/// The error type for I/O operations of the `Write` and associated traits.
27pub type Error = ::std::io::Error;
28
29// An error returned from the `write_marker` and `write_fixval` functions.
30struct MarkerWriteError(Error);
31
32impl From<Error> for MarkerWriteError {
33    fn from(err: Error) -> MarkerWriteError {
34        MarkerWriteError(err)
35    }
36}
37
38impl From<MarkerWriteError> for Error {
39    fn from(err: MarkerWriteError) -> Error {
40        match err {
41            MarkerWriteError(err) => err
42        }
43    }
44}
45
46/// Attempts to write the given marker into the writer.
47fn write_marker<W: Write>(wr: &mut W, marker: Marker) -> Result<(), MarkerWriteError> {
48    wr.write_u8(marker.to_u8()).map_err(MarkerWriteError)
49}
50
51/// An error returned from primitive values write functions.
52struct DataWriteError(Error);
53
54impl From<Error> for DataWriteError {
55    fn from(err: Error) -> DataWriteError {
56        DataWriteError(err)
57    }
58}
59
60impl From<DataWriteError> for Error {
61    fn from(err: DataWriteError) -> Error {
62        err.0
63    }
64}
65
66/// Encodes and attempts to write a nil value into the given write.
67///
68/// According to the MessagePack specification, a nil value is represented as a single `0xc0` byte.
69///
70/// # Errors
71///
72/// This function will return `Error` on any I/O error occurred while writing the nil marker.
73///
74/// # Examples
75///
76/// ```
77/// let mut buf = Vec::new();
78///
79/// rmp::encode::write_nil(&mut buf).unwrap();
80///
81/// assert_eq!(vec![0xc0], buf);
82/// ```
83pub fn write_nil<W: Write>(wr: &mut W) -> Result<(), Error> {
84    write_marker(wr, Marker::Null).map_err(From::from)
85}
86
87/// Encodes and attempts to write a bool value into the given write.
88///
89/// According to the MessagePack specification, an encoded boolean value is represented as a single
90/// byte.
91///
92/// # Errors
93///
94/// Each call to this function may generate an I/O error indicating that the operation could not be
95/// completed.
96pub fn write_bool<W: Write>(wr: &mut W, val: bool) -> Result<(), Error> {
97    let marker = if val {
98        Marker::True
99    } else {
100        Marker::False
101    };
102
103    write_marker(wr, marker).map_err(From::from)
104}
105
106fn write_data_u8<W: Write>(wr: &mut W, val: u8) -> Result<(), DataWriteError> {
107    wr.write_u8(val).map_err(DataWriteError)
108}
109
110fn write_data_u16<W: Write>(wr: &mut W, val: u16) -> Result<(), DataWriteError> {
111    wr.write_u16::<byteorder::BigEndian>(val).map_err(DataWriteError)
112}
113
114fn write_data_u32<W: Write>(wr: &mut W, val: u32) -> Result<(), DataWriteError> {
115    wr.write_u32::<byteorder::BigEndian>(val).map_err(DataWriteError)
116}
117
118fn write_data_u64<W: Write>(wr: &mut W, val: u64) -> Result<(), DataWriteError> {
119    wr.write_u64::<byteorder::BigEndian>(val).map_err(DataWriteError)
120}
121
122fn write_data_i8<W: Write>(wr: &mut W, val: i8) -> Result<(), DataWriteError> {
123    wr.write_i8(val).map_err(DataWriteError)
124}
125
126fn write_data_i16<W: Write>(wr: &mut W, val: i16) -> Result<(), DataWriteError> {
127    wr.write_i16::<byteorder::BigEndian>(val).map_err(DataWriteError)
128}
129
130fn write_data_i32<W: Write>(wr: &mut W, val: i32) -> Result<(), DataWriteError> {
131    wr.write_i32::<byteorder::BigEndian>(val).map_err(DataWriteError)
132}
133
134fn write_data_i64<W: Write>(wr: &mut W, val: i64) -> Result<(), DataWriteError> {
135    wr.write_i64::<byteorder::BigEndian>(val).map_err(DataWriteError)
136}
137
138fn write_data_f32<W: Write>(wr: &mut W, val: f32) -> Result<(), DataWriteError> {
139    wr.write_f32::<byteorder::BigEndian>(val).map_err(DataWriteError)
140}
141
142fn write_data_f64<W: Write>(wr: &mut W, val: f64) -> Result<(), DataWriteError> {
143    wr.write_f64::<byteorder::BigEndian>(val).map_err(DataWriteError)
144}
145
146/// An error that can occur when attempting to write multi-byte MessagePack value.
147#[derive(Debug)]
148pub enum ValueWriteError {
149    /// I/O error while writing marker.
150    InvalidMarkerWrite(Error),
151    /// I/O error while writing data.
152    InvalidDataWrite(Error),
153}
154
155impl From<MarkerWriteError> for ValueWriteError {
156    fn from(err: MarkerWriteError) -> ValueWriteError {
157        match err {
158            MarkerWriteError(err) => ValueWriteError::InvalidMarkerWrite(err),
159        }
160    }
161}
162
163impl From<DataWriteError> for ValueWriteError {
164    fn from(err: DataWriteError) -> ValueWriteError {
165        match err {
166            DataWriteError(err) => ValueWriteError::InvalidDataWrite(err),
167        }
168    }
169}
170
171impl From<ValueWriteError> for Error {
172    fn from(err: ValueWriteError) -> Error {
173        match err {
174            ValueWriteError::InvalidMarkerWrite(err) |
175            ValueWriteError::InvalidDataWrite(err) => err,
176        }
177    }
178}
179
180impl error::Error for ValueWriteError {
181    fn description(&self) -> &str {
182        "error while writing multi-byte MessagePack value"
183    }
184
185    fn cause(&self) -> Option<&error::Error> {
186        match *self {
187            ValueWriteError::InvalidMarkerWrite(ref err) |
188            ValueWriteError::InvalidDataWrite(ref err) => Some(err),
189        }
190    }
191}
192
193impl Display for ValueWriteError {
194    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
195        error::Error::description(self).fmt(f)
196    }
197}
198
199/// Encodes and attempts to write the most efficient array length implementation to the given write,
200/// returning the marker used.
201///
202/// # Errors
203///
204/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
205/// marker or the data.
206pub fn write_array_len<W: Write>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError> {
207    let marker = if len < 16 {
208        try!(write_marker(wr, Marker::FixArray(len as u8)));
209        Marker::FixArray(len as u8)
210    } else if len < 65536 {
211        try!(write_marker(wr, Marker::Array16));
212        try!(write_data_u16(wr, len as u16));
213        Marker::Array16
214    } else {
215        try!(write_marker(wr, Marker::Array32));
216        try!(write_data_u32(wr, len));
217        Marker::Array32
218    };
219
220    Ok(marker)
221}
222
223/// Encodes and attempts to write the most efficient map length implementation to the given write,
224/// returning the marker used.
225///
226/// # Errors
227///
228/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
229/// marker or the data.
230pub fn write_map_len<W: Write>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError> {
231    let marker = if len < 16 {
232        try!(write_marker(wr, Marker::FixMap(len as u8)));
233        Marker::FixMap(len as u8)
234    } else if len < 65536 {
235        try!(write_marker(wr, Marker::Map16));
236        try!(write_data_u16(wr, len as u16));
237        Marker::Map16
238    } else {
239        try!(write_marker(wr, Marker::Map32));
240        try!(write_data_u32(wr, len));
241        Marker::Map32
242    };
243
244    Ok(marker)
245}
246
247/// Encodes and attempts to write the most efficient ext metadata implementation to the given
248/// write, returning the marker used.
249///
250/// # Errors
251///
252/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
253/// marker or the data.
254///
255/// # Panics
256///
257/// Panics if `ty` is negative, because it is reserved for future MessagePack extension including
258/// 2-byte type information.
259pub fn write_ext_meta<W: Write>(wr: &mut W, len: u32, ty: i8) -> Result<Marker, ValueWriteError> {
260    assert!(ty >= 0);
261
262    let marker = match len {
263        1 => {
264            try!(write_marker(wr, Marker::FixExt1));
265            Marker::FixExt1
266        }
267        2 => {
268            try!(write_marker(wr, Marker::FixExt2));
269            Marker::FixExt2
270        }
271        4 => {
272            try!(write_marker(wr, Marker::FixExt4));
273            Marker::FixExt4
274        }
275        8 => {
276            try!(write_marker(wr, Marker::FixExt8));
277            Marker::FixExt8
278        }
279        16 => {
280            try!(write_marker(wr, Marker::FixExt16));
281            Marker::FixExt16
282        }
283        len if len < 256 => {
284            try!(write_marker(wr, Marker::Ext8));
285            try!(write_data_u8(wr, len as u8));
286            Marker::Ext8
287        }
288        len if len < 65536 => {
289            try!(write_marker(wr, Marker::Ext16));
290            try!(write_data_u16(wr, len as u16));
291            Marker::Ext16
292        }
293        len => {
294            try!(write_marker(wr, Marker::Ext32));
295            try!(write_data_u32(wr, len));
296            Marker::Ext32
297        }
298    };
299
300    try!(write_data_i8(wr, ty));
301
302    Ok(marker)
303}