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}