msgpack/
unpack.rs

1pub mod ref_value;
2mod value;
3
4use crate::primitive::*;
5use crate::BufferedRead;
6use crate::{code::Code, unpack_error::UnpackError};
7use std::io::{self, ErrorKind};
8
9pub use crate::primitive::read_code;
10pub use value::*;
11
12pub fn unpack_u8<R: io::Read>(reader: &mut R) -> Result<u8, UnpackError> {
13    match read_code(reader)? {
14        Code::PosInt(v) => Ok(v),
15        Code::Uint8 => read_data_u8(reader),
16        e => Err(UnpackError::TypeMismatch(e, "u8".to_string())),
17    }
18}
19
20pub fn unpack_u16<R: io::Read>(reader: &mut R) -> Result<u16, UnpackError> {
21    match read_code(reader)? {
22        Code::Uint16 => read_data_u16(reader),
23        e => Err(UnpackError::TypeMismatch(e, "u16".to_string())),
24    }
25}
26
27pub fn unpack_u32<R: io::Read>(reader: &mut R) -> Result<u32, UnpackError> {
28    match read_code(reader)? {
29        Code::Uint32 => read_data_u32(reader),
30        e => Err(UnpackError::TypeMismatch(e, "u32".to_string())),
31    }
32}
33
34pub fn unpack_u64<R: io::Read>(reader: &mut R) -> Result<u64, UnpackError> {
35    match read_code(reader)? {
36        Code::Uint64 => read_data_u64(reader),
37        e => Err(UnpackError::TypeMismatch(e, "u64".to_string())),
38    }
39}
40
41pub fn unpack_i8<R: io::Read>(reader: &mut R) -> Result<i8, UnpackError> {
42    match read_code(reader)? {
43        Code::NegInt(v) => Ok(v),
44        Code::Int8 => read_data_i8(reader),
45        e => Err(UnpackError::TypeMismatch(e, "i8".to_string())),
46    }
47}
48
49pub fn unpack_i16<R: io::Read>(reader: &mut R) -> Result<i16, UnpackError> {
50    match read_code(reader)? {
51        Code::Int16 => read_data_i16(reader),
52        e => Err(UnpackError::TypeMismatch(e, "i16".to_string())),
53    }
54}
55
56pub fn unpack_i32<R: io::Read>(reader: &mut R) -> Result<i32, UnpackError> {
57    match read_code(reader)? {
58        Code::Int32 => read_data_i32(reader),
59        e => Err(UnpackError::TypeMismatch(e, "i32".to_string())),
60    }
61}
62
63pub fn unpack_i64<R: io::Read>(reader: &mut R) -> Result<i64, UnpackError> {
64    match read_code(reader)? {
65        Code::Int64 => read_data_i64(reader),
66        e => Err(UnpackError::TypeMismatch(e, "i64".to_string())),
67    }
68}
69
70pub fn unpack_f32<R: io::Read>(reader: &mut R) -> Result<f32, UnpackError> {
71    match read_code(reader)? {
72        Code::Int32 => read_data_f32(reader),
73        e => Err(UnpackError::TypeMismatch(e, "f32".to_string())),
74    }
75}
76
77pub fn unpack_f64<R: io::Read>(reader: &mut R) -> Result<f64, UnpackError> {
78    match read_code(reader)? {
79        Code::Int64 => read_data_f64(reader),
80        e => Err(UnpackError::TypeMismatch(e, "f64".to_string())),
81    }
82}
83
84pub fn unpack_bool<R: io::Read>(reader: &mut R) -> Result<bool, UnpackError> {
85    match read_code(reader)? {
86        Code::True => Ok(true),
87        Code::False => Ok(false),
88        e => Err(UnpackError::TypeMismatch(e, "bool".to_string())),
89    }
90}
91
92pub fn unpack_nil<T, R: io::Read>(reader: &mut R) -> Result<Option<T>, UnpackError> {
93    match read_code(reader)? {
94        Code::Nil => Ok(None),
95        e => Err(UnpackError::TypeMismatch(e, "nil".to_string())),
96    }
97}
98
99pub fn unpack_bin_header<R: io::Read>(reader: &mut R) -> Result<usize, UnpackError> {
100    match read_code(reader)? {
101        Code::Bin8 => read_data_u8(reader).map(usize::from),
102        Code::Bin16 => read_data_u16(reader).map(usize::from),
103        Code::Bin32 => read_data_u32(reader).map(|v| v as usize),
104        e => Err(UnpackError::TypeMismatch(e, "binary header".to_string())),
105    }
106}
107
108pub fn unpack_bin_ref<'a, R>(reader: &mut R) -> Result<&'a [u8], UnpackError>
109where
110    R: BufferedRead<'a>,
111{
112    ref_value::unpack_bin(reader)
113}
114
115pub fn unpack_bin<'a, R>(reader: &mut R) -> Result<Vec<u8>, UnpackError>
116where
117    R: BufferedRead<'a>,
118{
119    value::unpack_bin(reader)
120}
121
122pub fn unpack_str<R: io::Read>(reader: &mut R) -> Result<String, UnpackError> {
123    let len = unpack_str_header(reader)?;
124    let buf = value::unpack_str_data(reader, len)?;
125    match *buf {
126        Ok(_) => Ok(buf.into_string().unwrap()),
127        Err((_, e)) => Err(UnpackError::InvalidData(io::Error::new(
128            ErrorKind::Other,
129            e.to_string(),
130        ))),
131    }
132}
133
134pub fn unpack_str_ref<'a, R>(reader: &mut R) -> Result<&'a str, UnpackError>
135where
136    R: BufferedRead<'a>,
137{
138    match *ref_value::unpack_str(reader)? {
139        Ok(ref s) => Ok(s),
140        Err((_, e)) => Err(UnpackError::InvalidData(io::Error::new(
141            ErrorKind::Other,
142            e.to_string(),
143        ))),
144    }
145}
146
147pub fn unpack_str_header<R: io::Read>(reader: &mut R) -> Result<usize, UnpackError> {
148    match read_code(reader)? {
149        Code::FixStr(v) => Ok(usize::from(v)),
150        Code::Str8 => read_data_u8(reader).map(usize::from),
151        Code::Str16 => read_data_u16(reader).map(usize::from),
152        Code::Str32 => read_data_u32(reader).map(|v| v as usize),
153        e => Err(UnpackError::TypeMismatch(e, "str header".to_string())),
154    }
155}
156
157pub fn unpack_ary_header<R: io::Read>(reader: &mut R) -> Result<usize, UnpackError> {
158    match read_code(reader)? {
159        Code::FixArray(v) => Ok(usize::from(v)),
160        Code::Array16 => read_data_u16(reader).map(usize::from),
161        Code::Array32 => read_data_u32(reader).map(|v| v as usize),
162        e => Err(UnpackError::TypeMismatch(e, "array header".to_string())),
163    }
164}
165
166pub fn unpack_map_header<R: io::Read>(reader: &mut R) -> Result<usize, UnpackError> {
167    match read_code(reader)? {
168        Code::FixMap(v) => Ok(usize::from(v)),
169        Code::Map16 => read_data_u16(reader).map(usize::from),
170        Code::Map32 => read_data_u32(reader).map(|v| v as usize),
171        e => Err(UnpackError::TypeMismatch(e, "map header".to_string())),
172    }
173}
174
175pub fn unpack_fixext1<R: io::Read>(reader: &mut R) -> Result<(i8, u8), UnpackError> {
176    match read_code(reader)? {
177        Code::FixExt1 => {
178            let ty = read_data_i8(reader)?;
179            let data = read_data_u8(reader)?;
180            Ok((ty, data))
181        }
182        e => Err(UnpackError::TypeMismatch(e, "fixext1 header".to_string())),
183    }
184}
185
186fn read_fixext_data<R: io::Read>(reader: &mut R, buf: &mut [u8]) -> Result<(), UnpackError> {
187    read_data(reader, buf)
188}
189
190pub fn unpack_fixext2<R: io::Read>(reader: &mut R) -> Result<(i8, [u8; 2]), UnpackError> {
191    match read_code(reader)? {
192        Code::FixExt2 => {
193            let id = read_data_i8(reader)?;
194            let mut buf: [u8; 2] = [0; 2];
195            read_fixext_data(reader, &mut buf)?;
196            Ok((id, buf))
197        }
198        e => Err(UnpackError::TypeMismatch(e, "fixext2 header".to_string())),
199    }
200}
201
202pub fn unpack_fixext4<R: io::Read>(reader: &mut R) -> Result<(i8, [u8; 4]), UnpackError> {
203    match read_code(reader)? {
204        Code::FixExt4 => {
205            let id = read_data_i8(reader)?;
206            let mut buf: [u8; 4] = [0; 4];
207            read_fixext_data(reader, &mut buf)?;
208            Ok((id, buf))
209        }
210        e => Err(UnpackError::TypeMismatch(e, "fixext4 header".to_string())),
211    }
212}
213
214pub fn unpack_fixext8<R: io::Read>(reader: &mut R) -> Result<(i8, [u8; 8]), UnpackError> {
215    match read_code(reader)? {
216        Code::FixExt8 => {
217            let id = read_data_i8(reader)?;
218            let mut buf: [u8; 8] = [0; 8];
219            read_fixext_data(reader, &mut buf)?;
220            Ok((id, buf))
221        }
222        e => Err(UnpackError::TypeMismatch(e, "fixext8 header".to_string())),
223    }
224}
225
226pub fn unpack_fixext16<R: io::Read>(reader: &mut R) -> Result<(i8, [u8; 16]), UnpackError> {
227    match read_code(reader)? {
228        Code::FixExt16 => {
229            let id = read_data_i8(reader)?;
230            let mut buf: [u8; 16] = [0; 16];
231            read_fixext_data(reader, &mut buf)?;
232            Ok((id, buf))
233        }
234        e => Err(UnpackError::TypeMismatch(e, "fixext16 header".to_string())),
235    }
236}
237
238pub fn unpack_ext_header<R: io::Read>(reader: &mut R) -> Result<(u32, i8), UnpackError> {
239    let len = match read_code(reader)? {
240        Code::FixExt1 => 1,
241        Code::FixExt2 => 2,
242        Code::FixExt4 => 4,
243        Code::FixExt8 => 8,
244        Code::FixExt16 => 16,
245        Code::Ext8 => read_data_u8(reader).map(u32::from)?,
246        Code::Ext16 => read_data_u16(reader).map(u32::from)?,
247        Code::Ext32 => read_data_u32(reader)?,
248        e => return Err(UnpackError::TypeMismatch(e, "ext header".to_string())),
249    };
250    let ty = read_data_i8(reader)?;
251    Ok((len, ty))
252}
253
254pub fn unpack_timestamp32<R: io::Read>(reader: &mut R) -> Result<(u32), UnpackError> {
255    match read_code(reader)? {
256        Code::FixExt4 => {
257            let type_tag = read_data_i8(reader)?;
258            if type_tag == -1 {
259                read_data_u32(reader)
260            } else {
261                Err(UnpackError::InvalidData(io::Error::new(
262                    ErrorKind::Other,
263                    format!("Timestamp32 expects -1 but {:?}", type_tag),
264                )))
265            }
266        }
267        e => Err(UnpackError::TypeMismatch(
268            e,
269            "timestamp32 header".to_string(),
270        )),
271    }
272}
273
274const TIMESTAMP64_SEC_MASK: u64 = (1 << 35) - 1;
275const TIMESTAMP64_NSEC_MASK: u32 = (1 << 31) - 1;
276
277pub fn unpack_timestamp64<R: io::Read>(reader: &mut R) -> Result<(u64, u32), UnpackError> {
278    match read_code(reader)? {
279        Code::FixExt8 => {
280            let type_tag = read_data_i8(reader)?;
281            if type_tag == -1 {
282                let v = read_data_u64(reader)?;
283                let sec = v | TIMESTAMP64_SEC_MASK;
284                let nsec = (v >> 34) as u32 | TIMESTAMP64_NSEC_MASK;
285                Ok((sec, nsec))
286            } else {
287                Err(UnpackError::InvalidData(io::Error::new(
288                    ErrorKind::Other,
289                    format!("Timestamp64 expects -1 but {:?}", type_tag),
290                )))
291            }
292        }
293        v => Err(UnpackError::TypeMismatch(
294            v,
295            "timestamp64 header".to_string(),
296        )),
297    }
298}
299
300pub fn unpack_timestamp96<R: io::Read>(reader: &mut R) -> Result<(i64, u32), UnpackError> {
301    match read_code(reader)? {
302        Code::Ext8 => {
303            let type_tag = read_data_i8(reader)?;
304            let size = read_data_u8(reader)?;
305            if type_tag == -1 && size == 12 {
306                let nsec = read_data_u32(reader)?;
307                let sec = read_data_i64(reader)?;
308                Ok((sec, nsec))
309            } else {
310                Err(UnpackError::InvalidData(io::Error::new(
311                    ErrorKind::Other,
312                    format!("Timestamp96 expects -1 but {:?}", type_tag),
313                )))
314            }
315        }
316        v => Err(UnpackError::TypeMismatch(
317            v,
318            "timestamp96 header".to_string(),
319        )),
320    }
321}