1#![allow(dead_code)]
2#![doc = include_str!("../README.md")]
3
4use shapely_core::Partial;
5use std::convert::TryInto;
6
7mod errors;
8use errors::Error as DecodeError;
9
10mod constants;
11use constants::*;
12
13#[cfg(test)]
14mod tests;
15
16#[allow(clippy::needless_lifetimes)]
33pub fn from_msgpack(partial: &mut Partial, msgpack: &[u8]) -> Result<(), DecodeError> {
34 let mut decoder = Decoder::new(msgpack);
35
36 fn deserialize_value(decoder: &mut Decoder, partial: &mut Partial) -> Result<(), DecodeError> {
37 let shape_desc = partial.shape();
38 let shape = shape_desc.get();
39
40 match &shape.innards {
41 shapely_core::Innards::Scalar(scalar) => {
42 let slot = partial.scalar_slot().expect("Scalar slot");
43 match scalar {
44 shapely_core::Scalar::String => {
45 let value = decoder.decode_string()?;
46 slot.fill(value);
47 }
48 shapely_core::Scalar::U64 => {
49 let value = decoder.decode_u64()?;
50 slot.fill(value);
51 }
52 _ => {
53 println!("Unsupported scalar type: {:?}", scalar);
54 todo!()
55 }
56 }
57 }
58 shapely_core::Innards::Struct { .. } => {
59 let map_len = decoder.decode_map_len()?;
60
61 for _ in 0..map_len {
62 let key = decoder.decode_string()?;
63 let slot = partial
64 .slot_by_name(&key)
65 .map_err(|_| DecodeError::UnknownField(key))?;
66
67 let mut partial_field = Partial::alloc(slot.shape());
68 deserialize_value(decoder, &mut partial_field)?;
69 slot.fill_from_partial(partial_field);
70 }
71 }
72 _ => {
73 println!("Unsupported shape: {:?}", shape.innards);
74 todo!()
75 }
76 }
77
78 Ok(())
79 }
80
81 deserialize_value(&mut decoder, partial)
82}
83
84struct Decoder<'input> {
85 input: &'input [u8],
86 offset: usize,
87}
88
89impl<'input> Decoder<'input> {
90 fn new(input: &'input [u8]) -> Self {
91 Decoder { input, offset: 0 }
92 }
93
94 fn decode_u8(&mut self) -> Result<u8, DecodeError> {
97 if self.offset >= self.input.len() {
98 return Err(DecodeError::InsufficientData);
99 }
100 let value = self.input[self.offset];
101 self.offset += 1;
102 Ok(value)
103 }
104
105 fn decode_u16(&mut self) -> Result<u16, DecodeError> {
108 if self.offset + 2 > self.input.len() {
109 return Err(DecodeError::InsufficientData);
110 }
111 let value =
112 u16::from_be_bytes(self.input[self.offset..self.offset + 2].try_into().unwrap());
113 self.offset += 2;
114 Ok(value)
115 }
116
117 fn decode_u32(&mut self) -> Result<u32, DecodeError> {
120 if self.offset + 4 > self.input.len() {
121 return Err(DecodeError::InsufficientData);
122 }
123 let value =
124 u32::from_be_bytes(self.input[self.offset..self.offset + 4].try_into().unwrap());
125 self.offset += 4;
126 Ok(value)
127 }
128
129 fn decode_u64(&mut self) -> Result<u64, DecodeError> {
139 match self.decode_u8()? {
140 MSGPACK_UINT8 => Ok(self.decode_u8()? as u64),
141 MSGPACK_UINT16 => Ok(self.decode_u16()? as u64),
142 MSGPACK_UINT32 => Ok(self.decode_u32()? as u64),
143 MSGPACK_UINT64 => {
144 if self.offset + 8 > self.input.len() {
145 return Err(DecodeError::InsufficientData);
146 }
147 let value = u64::from_be_bytes(
148 self.input[self.offset..self.offset + 8].try_into().unwrap(),
149 );
150 self.offset += 8;
151 Ok(value)
152 }
153 prefix @ MSGPACK_POSFIXINT_MIN..=MSGPACK_POSFIXINT_MAX => Ok(prefix as u64),
154 _ => Err(DecodeError::UnexpectedType),
155 }
156 }
157
158 fn decode_string(&mut self) -> Result<String, DecodeError> {
167 let prefix = self.decode_u8()?;
168
169 let len = match prefix {
170 prefix @ MSGPACK_FIXSTR_MIN..=MSGPACK_FIXSTR_MAX => (prefix & 0x1f) as usize,
171 MSGPACK_STR8 => self.decode_u8()? as usize,
172 MSGPACK_STR16 => self.decode_u16()? as usize,
173 MSGPACK_STR32 => self.decode_u32()? as usize,
174 _ => return Err(DecodeError::UnexpectedType),
175 };
176
177 if self.offset + len > self.input.len() {
178 return Err(DecodeError::InsufficientData);
179 }
180
181 let value = String::from_utf8(self.input[self.offset..self.offset + len].to_vec())
182 .map_err(|_| DecodeError::InvalidData)?;
183 self.offset += len;
184 Ok(value)
185 }
186
187 fn decode_map_len(&mut self) -> Result<usize, DecodeError> {
195 let prefix = self.decode_u8()?;
196
197 match prefix {
198 prefix @ MSGPACK_FIXMAP_MIN..=MSGPACK_FIXMAP_MAX => Ok((prefix & 0x0f) as usize),
199 MSGPACK_MAP16 => Ok(self.decode_u16()? as usize),
200 MSGPACK_MAP32 => Ok(self.decode_u32()? as usize),
201 _ => Err(DecodeError::UnexpectedType),
202 }
203 }
204}