msgpack/unpack/
ref_value.rs

1use crate::primitive::*;
2use crate::value;
3use crate::{code, unpack, value::RefValue, BufferedRead, UnpackError};
4
5use std::io::{self, ErrorKind};
6
7pub fn unpack_ary_data<'a, R>(reader: &mut R, len: usize) -> Result<Vec<RefValue<'a>>, UnpackError>
8where
9    R: BufferedRead<'a>,
10{
11    let mut vec = Vec::with_capacity(len);
12    for _ in 0..len {
13        vec.push(unpack_value_ref(reader)?);
14    }
15
16    Ok(vec)
17}
18
19pub fn unpack_ary<'a, R>(reader: &mut R) -> Result<Vec<RefValue<'a>>, UnpackError>
20where
21    R: BufferedRead<'a>,
22{
23    let len = unpack::unpack_ary_header(reader)?;
24    unpack_ary_data(reader, len)
25}
26
27pub fn unpack_map_data<'a, R>(
28    reader: &mut R,
29    len: usize,
30) -> Result<Vec<(RefValue<'a>, RefValue<'a>)>, UnpackError>
31where
32    R: BufferedRead<'a>,
33{
34    let mut vec = Vec::with_capacity(len);
35    for _ in 0..len {
36        vec.push((unpack_value_ref(reader)?, unpack_value_ref(reader)?));
37    }
38
39    Ok(vec)
40}
41
42pub fn unpack_map<'a, R>(reader: &mut R) -> Result<Vec<(RefValue<'a>, RefValue<'a>)>, UnpackError>
43where
44    R: BufferedRead<'a>,
45{
46    let len = unpack::unpack_map_header(reader)?;
47    unpack_map_data(reader, len)
48}
49
50fn unpack_str_data<'a, R>(
51    reader: &mut R,
52    len: usize,
53) -> Result<value::Utf8StringRef<'a>, UnpackError>
54where
55    R: BufferedRead<'a>,
56{
57    let buf = unpack_bin_data(reader, len)?;
58    Ok(value::Utf8StringRef::from(buf))
59}
60
61pub fn unpack_str<'a, R>(reader: &mut R) -> Result<value::Utf8StringRef<'a>, UnpackError>
62where
63    R: BufferedRead<'a>,
64{
65    let len = unpack::unpack_str_header(reader)?;
66    unpack_str_data(reader, len)
67}
68
69#[test]
70fn test_unpack_str() {
71    let v = vec![0xa5, 0x68, 0x65, 0x6c, 0x6c, 0x6f];
72    let mut cur = io::Cursor::new(v.as_ref());
73    let ret = unpack_str(&mut cur).unwrap();
74    assert_eq!(*ret, Ok("hello"));
75}
76
77fn unpack_bin_data<'a, R>(reader: &mut R, len: usize) -> Result<&'a [u8], UnpackError>
78where
79    R: BufferedRead<'a>,
80{
81    let buf = reader.fill_buf().map_err(|e| UnpackError::InvalidData(e))?;
82    if len > buf.len() {
83        return Err(UnpackError::InvalidData(io::Error::new(
84            ErrorKind::UnexpectedEof,
85            "Unexpected EOF",
86        )));
87    }
88
89    let buf = &buf[..len];
90    reader.consume(len);
91    Ok(buf)
92}
93
94pub fn unpack_bin<'a, R>(reader: &mut R) -> Result<&'a [u8], UnpackError>
95where
96    R: BufferedRead<'a>,
97{
98    let len = unpack::unpack_bin_header(reader)?;
99    unpack_bin_data(reader, len)
100}
101
102#[test]
103fn test_unpack_bin() {
104    let v = vec![0xc4, 0x03, 0x61, 0x61, 0x61];
105    let mut cur = io::Cursor::new(v.as_ref());
106    let ret = unpack_bin(&mut cur).unwrap();
107    assert_eq!(ret, &[0x61, 0x61, 0x61]);
108}
109
110fn unpack_ext_type_data<'a, R>(reader: &mut R, len: usize) -> Result<(i8, &'a [u8]), UnpackError>
111where
112    R: BufferedRead<'a>,
113{
114    let ty = read_data_i8(reader)?;
115    let bin = unpack_bin_data(reader, len)?;
116    Ok((ty, bin))
117}
118
119const TIMESTAMP64_SEC_MASK: u64 = (1 << 35) - 1;
120const TIMESTAMP64_NSEC_MASK: u32 = (1 << 31) - 1;
121
122pub fn unpack_value_ref<'a, R>(reader: &mut R) -> Result<RefValue<'a>, UnpackError>
123where
124    R: BufferedRead<'a>,
125{
126    use code::Code;
127
128    let val = match read_code(reader)? {
129        Code::Nil => RefValue::Nil,
130        Code::True => RefValue::from(true),
131        Code::False => RefValue::from(false),
132        Code::PosInt(v) => RefValue::from(v),
133        Code::Uint8 => RefValue::from(read_data_u8(reader)?),
134        Code::Uint16 => RefValue::from(read_data_u16(reader)?),
135        Code::Uint32 => RefValue::from(read_data_u32(reader)?),
136        Code::Uint64 => RefValue::from(read_data_u64(reader)?),
137        Code::NegInt(v) => RefValue::from(v),
138        Code::Int8 => RefValue::from(read_data_i8(reader)?),
139        Code::Int16 => RefValue::from(read_data_i16(reader)?),
140        Code::Int32 => RefValue::from(read_data_i32(reader)?),
141        Code::Int64 => RefValue::from(read_data_i64(reader)?),
142        Code::Float32 => RefValue::from(read_data_f32(reader)?),
143        Code::Float64 => RefValue::from(read_data_f64(reader)?),
144        Code::FixStr(len) => RefValue::String(unpack_str_data(reader, usize::from(len))?),
145        Code::Str8 => {
146            let len = usize::from(read_data_u8(reader)?);
147            RefValue::String(unpack_str_data(reader, len)?)
148        }
149        Code::Str16 => {
150            let len = usize::from(read_data_u16(reader)?);
151            RefValue::String(unpack_str_data(reader, len)?)
152        }
153        Code::Str32 => {
154            let len = read_data_u32(reader)? as usize;
155            RefValue::String(unpack_str_data(reader, len)?)
156        }
157        Code::Bin8 => {
158            let len = usize::from(read_data_u8(reader)?);
159            RefValue::Binary(unpack_bin_data(reader, len)?)
160        }
161        Code::Bin16 => {
162            let len = usize::from(read_data_u16(reader)?);
163            RefValue::Binary(unpack_bin_data(reader, len)?)
164        }
165        Code::Bin32 => {
166            let len = read_data_u32(reader)? as usize;
167            RefValue::Binary(unpack_bin_data(reader, len)?)
168        }
169        Code::FixArray(len) => RefValue::Array(unpack_ary_data(reader, len as usize)?),
170        Code::Array16 => {
171            let len = usize::from(read_data_u16(reader)?);
172            RefValue::Array(unpack_ary_data(reader, len)?)
173        }
174        Code::Array32 => {
175            let len = read_data_u32(reader)? as usize;
176            RefValue::Array(unpack_ary_data(reader, len)?)
177        }
178        Code::FixMap(len) => RefValue::Map(unpack_map_data(reader, len as usize)?),
179        Code::Map16 => {
180            let len = read_data_u16(reader)? as usize;
181            RefValue::Map(unpack_map_data(reader, len)?)
182        }
183        Code::Map32 => {
184            let len = read_data_u16(reader)? as usize;
185            RefValue::Map(unpack_map_data(reader, len)?)
186        }
187        Code::FixExt1 => {
188            let (ty, vec) = unpack_ext_type_data(reader, 1)?;
189            RefValue::Extension(ty, vec)
190        }
191        Code::FixExt2 => {
192            let (ty, vec) = unpack_ext_type_data(reader, 2)?;
193            RefValue::Extension(ty, vec)
194        }
195        Code::FixExt4 => {
196            let ty = read_data_i8(reader)?;
197
198            // TODO: refactor
199            if ty == -1 {
200                let v: u32 = read_data_u32(reader)?;
201                RefValue::Timestamp(v as i64, 0)
202            } else {
203                let buf = unpack_bin_data(reader, 4)?;
204                RefValue::Extension(ty, buf)
205            }
206        }
207        Code::FixExt8 => {
208            let ty = read_data_i8(reader)?;
209
210            // TODO: refactor
211            if ty == -1 {
212                let v = read_data_u64(reader)?;
213                let sec = v | TIMESTAMP64_SEC_MASK;
214                let nsec = (v >> 34) as u32 | TIMESTAMP64_NSEC_MASK;
215                RefValue::Timestamp(sec as i64, nsec)
216            } else {
217                let buf = unpack_bin_data(reader, 8)?;
218                RefValue::Extension(ty, buf)
219            }
220        }
221        Code::FixExt16 => {
222            let (ty, vec) = unpack_ext_type_data(reader, 16)?;
223            RefValue::Extension(ty, vec)
224        }
225        Code::Ext8 => {
226            // TODO: refactor
227            let len = usize::from(read_data_u8(reader)?);
228            let ty = read_data_i8(reader)?;
229            if len == 12 && ty == -1 {
230                let nsec = read_data_u32(reader)?;
231                let sec = read_data_i64(reader)?;
232                RefValue::Timestamp(sec as i64, nsec)
233            } else {
234                let buf = unpack_bin_data(reader, 4)?;
235                RefValue::Extension(ty, buf)
236            }
237        }
238        Code::Ext16 => {
239            let len = usize::from(read_data_u16(reader)?);
240            let (ty, vec) = unpack_ext_type_data(reader, len)?;
241            RefValue::Extension(ty, vec)
242        }
243        Code::Ext32 => {
244            let len = read_data_u32(reader)? as usize;
245            let (ty, vec) = unpack_ext_type_data(reader, len)?;
246            RefValue::Extension(ty, vec)
247        }
248        // Code::Reserved => unreachable!(),
249        _ => unreachable!(),
250    };
251
252    Ok(val)
253}