packed_encoder/decoder.rs
1extern crate byteorder;
2use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5/// `DecodedData` enum is used to wrap the decoded content into one of the supported data-type.
6/// Example: `DecodedData::Str("hello")`, contains the string `hello` decoded back from the encoded bytes.
7pub enum DecodedData {
8 /// Int8 data representation
9 Int8(i8),
10 /// Int16 data representation
11 Int16(i16),
12 /// Int32 data representation
13 Int32(i32),
14 /// Int64 data representation
15 Int64(i64),
16 /// Int128 data representation
17 Int128(i128),
18
19 /// Uint8 data representation
20 Uint8(u8),
21 /// Uint16 data representation
22 Uint16(u16),
23 /// Uint32 data representation
24 Uint32(u32),
25 /// Uint64 data representation
26 Uint64(u64),
27 /// Uint128 data representation
28 Uint128(u128),
29
30 /// Str data representation
31 Str(String),
32
33 /// Bytes data representation
34 Bytes(Vec<u8>),
35}
36
37#[derive(Debug, Clone)]
38/// `DecodeType` enum can be used to tell the decoder who a sequence of bytes at a given offset must be decoded back.
39/// Example: `DecodeType::Uint16` can be used to tell the decoder to interpret the next two bytes as `uint16`.
40pub enum DecodeType {
41 /// Int8 tells the decoder to decode next 1 byte as signed 8-bit integer
42 Int8,
43 /// Int16 tells the decoder to decode next 2 bytes as signed 16-bit integer
44 Int16,
45 /// Int32 tells the decoder to decode next 4 bytes as signed 32-bit integer
46 Int32,
47 /// Int64 tells the decoder to decode next 8 bytes as signed 64-bit integer
48 Int64,
49 /// Int128 tells the decoder to decode next 16 bytes as signed 128-bit integer
50 Int128,
51
52 /// Uint8 tells the decoder to decode next 1 byte as unsigned 8-bit integer
53 Uint8,
54 /// Uint16 tells the decoder to decode next 2 bytes as unsigned 16-bit integer
55 Uint16,
56 /// Uint32 tells the decoder to decode next 4 bytes as unsigned 32-bit integer
57 Uint32,
58 /// Uint64 tells the decoder to decode next 8 bytes as unsigned 64-bit integer
59 Uint64,
60 /// Uint128 tells the decoder to decode next 16 bytes as unsigned 128-bit integer
61 Uint128,
62
63 /// Str(usize) tells the decoded to decode next `x` bytes as a string
64 Str(usize),
65
66 /// Str(usize) tells the decoded to decode next `x` bytes as a byte-array
67 Bytes(usize),
68}
69
70#[derive(Debug, Clone)]
71/// `DecodeOrder` is used to specify how signed and unsigned integers encoded as bytes must be assumed w.r.t byte-order for decoding.
72/// Example `DecodeOrder::Little` assumes all the bytes to be decoded are in little endian byte order.
73pub enum DecodeOrder {
74 /// Big endian byte ordering
75 Big,
76 /// Little endian byte ordering
77 Little,
78}
79
80#[derive(Debug, Clone)]
81/// `DecodeError` wraps the error that occurred during during
82pub enum DecodeError {
83 /// InvalidData represents an error that happens when given sequency of bytes at given offset cannot be decoded into the required data-type.
84 /// Example `Err(DecodeErr::InvalidData(1))` says that the given bytes cannot be converted into the data-type specified at index 1.
85 InvalidData(usize),
86 /// IndexOutOfBounds occurs when offset > size of the byte array.
87 IndexOutOfBounds,
88}
89
90#[inline]
91fn decode_i16(mut array: &[u8], decode_order: DecodeOrder) -> Option<i16> {
92 match decode_order {
93 DecodeOrder::Big => array.read_i16::<BigEndian>(),
94 DecodeOrder::Little => array.read_i16::<LittleEndian>(),
95 }
96 .ok()
97}
98
99#[inline]
100fn decode_i32(mut array: &[u8], decode_order: DecodeOrder) -> Option<i32> {
101 match decode_order {
102 DecodeOrder::Big => array.read_i32::<BigEndian>(),
103 DecodeOrder::Little => array.read_i32::<LittleEndian>(),
104 }
105 .ok()
106}
107
108#[inline]
109fn decode_i64(mut array: &[u8], decode_order: DecodeOrder) -> Option<i64> {
110 match decode_order {
111 DecodeOrder::Big => array.read_i64::<BigEndian>(),
112 DecodeOrder::Little => array.read_i64::<LittleEndian>(),
113 }
114 .ok()
115}
116
117#[inline]
118fn decode_i128(mut array: &[u8], decode_order: DecodeOrder) -> Option<i128> {
119 match decode_order {
120 DecodeOrder::Big => array.read_i128::<BigEndian>(),
121 DecodeOrder::Little => array.read_i128::<LittleEndian>(),
122 }
123 .ok()
124}
125
126#[inline]
127fn decode_u16(mut array: &[u8], decode_order: DecodeOrder) -> Option<u16> {
128 match decode_order {
129 DecodeOrder::Big => array.read_u16::<BigEndian>(),
130 DecodeOrder::Little => array.read_u16::<LittleEndian>(),
131 }
132 .ok()
133}
134
135#[inline]
136fn decode_u32(mut array: &[u8], decode_order: DecodeOrder) -> Option<u32> {
137 match decode_order {
138 DecodeOrder::Big => array.read_u32::<BigEndian>(),
139 DecodeOrder::Little => array.read_u32::<LittleEndian>(),
140 }
141 .ok()
142}
143
144#[inline]
145fn decode_u64(mut array: &[u8], decode_order: DecodeOrder) -> Option<u64> {
146 match decode_order {
147 DecodeOrder::Big => array.read_u64::<BigEndian>(),
148 DecodeOrder::Little => array.read_u64::<LittleEndian>(),
149 }
150 .ok()
151}
152
153#[inline]
154fn decode_u128(mut array: &[u8], decode_order: DecodeOrder) -> Option<u128> {
155 match decode_order {
156 DecodeOrder::Big => array.read_u128::<BigEndian>(),
157 DecodeOrder::Little => array.read_u128::<LittleEndian>(),
158 }
159 .ok()
160}
161
162#[inline]
163fn decode_string(array: &[u8]) -> Option<String> {
164 String::from_utf8(array.to_vec()).ok()
165}
166
167#[allow(clippy::question_mark)]
168/// `decode_packed` function decoded a given byte-array into list of required values specified in `types` parameter.
169/// Returns the list of decoded values `Vec<DecodedData>` or `DecodeError`.
170///
171/// # Arguments
172///
173/// * `types`: List of required types to decode, example: `&[DecodeType::Int8, DecodeType::Str(10)]`
174/// * `buffer`: Immutable reference to the slice that contains bytes to be decoded
175/// * `decode_order`: the byte ordering to consider while decoding
176///
177/// # Examples
178/// ```rust
179/// extern crate packed_encoder;
180/// use packed_encoder::decoder;
181///
182/// fn main() {
183///
184/// // byte data to decode
185/// let bytes = vec![192, 24, 212, 73, 201, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 116, 104, 105, 115, 45, 105, 115, 45, 103, 111, 111, 100, 11, 230, 234, 49, 0, 0, 0, 0, 10, 255, 171, 18, 51];
186/// // required types to decode from the given byte array
187/// let required_types = &[
188/// decoder::DecodeType::Int128,
189/// decoder::DecodeType::Str(12),
190/// decoder::DecodeType::Uint64,
191/// decoder::DecodeType::Int8,
192/// decoder::DecodeType::Bytes(4),
193/// ];
194///
195/// // decode
196/// let result = decoder::decode_packed(required_types, &bytes, decoder::DecodeOrder::Little);
197/// assert_eq!(result.is_ok(), true);
198///
199/// // check values
200/// let decoded_data = result.unwrap();
201/// match &decoded_data[1] {
202/// decoder::DecodedData::Str(content) => {println!("decoded string at position 1: {}", content)},
203/// _ => {}
204/// }
205///
206/// }
207/// ```
208pub fn decode_packed(
209 types: &[DecodeType],
210 buffer: &[u8],
211 decode_order: DecodeOrder,
212) -> Result<Vec<DecodedData>, DecodeError> {
213 let mut decoded_data = vec![];
214 let mut last_read = 0;
215
216 for (idx, entry) in types.iter().enumerate() {
217 let (result, size_offset) = match entry {
218 DecodeType::Int8 => {
219 if buffer.len() < last_read + 1 {
220 (Err(DecodeError::IndexOutOfBounds), 1)
221 } else {
222 (Ok(DecodedData::Int8(buffer[last_read] as i8)), 1)
223 }
224 }
225
226 DecodeType::Int16 => {
227 if buffer.len() < last_read + 2 {
228 (Err(DecodeError::IndexOutOfBounds), 2)
229 } else {
230 let decoded_result =
231 decode_i16(&buffer[last_read..last_read + 2], decode_order.clone());
232 (
233 decoded_result.map_or_else(
234 || Err(DecodeError::InvalidData(idx)),
235 |decoded| Ok(DecodedData::Int16(decoded)),
236 ),
237 2,
238 )
239 }
240 }
241
242 DecodeType::Int32 => {
243 if buffer.len() < last_read + 4 {
244 (Err(DecodeError::IndexOutOfBounds), 4)
245 } else {
246 let decoded_result =
247 decode_i32(&buffer[last_read..last_read + 4], decode_order.clone());
248 (
249 decoded_result.map_or_else(
250 || Err(DecodeError::InvalidData(idx)),
251 |decoded| Ok(DecodedData::Int32(decoded)),
252 ),
253 4,
254 )
255 }
256 }
257
258 DecodeType::Int64 => {
259 if buffer.len() < last_read + 8 {
260 (Err(DecodeError::IndexOutOfBounds), 8)
261 } else {
262 let decoded_result =
263 decode_i64(&buffer[last_read..last_read + 8], decode_order.clone());
264 (
265 decoded_result.map_or_else(
266 || Err(DecodeError::InvalidData(idx)),
267 |decoded| Ok(DecodedData::Int64(decoded)),
268 ),
269 8,
270 )
271 }
272 }
273
274 DecodeType::Int128 => {
275 if buffer.len() < last_read + 16 {
276 (Err(DecodeError::IndexOutOfBounds), 16)
277 } else {
278 let decoded_result =
279 decode_i128(&buffer[last_read..last_read + 16], decode_order.clone());
280 (
281 decoded_result.map_or_else(
282 || Err(DecodeError::InvalidData(idx)),
283 |decoded| Ok(DecodedData::Int128(decoded)),
284 ),
285 16,
286 )
287 }
288 }
289
290 DecodeType::Uint8 => {
291 if buffer.len() < last_read + 1 {
292 (Err(DecodeError::IndexOutOfBounds), 1)
293 } else {
294 (Ok(DecodedData::Uint8(buffer[last_read])), 1)
295 }
296 }
297
298 DecodeType::Uint16 => {
299 if buffer.len() < last_read + 2 {
300 (Err(DecodeError::IndexOutOfBounds), 2)
301 } else {
302 let decoded_result =
303 decode_u16(&buffer[last_read..last_read + 2], decode_order.clone());
304 (
305 decoded_result.map_or_else(
306 || Err(DecodeError::InvalidData(idx)),
307 |decoded| Ok(DecodedData::Uint16(decoded)),
308 ),
309 2,
310 )
311 }
312 }
313
314 DecodeType::Uint32 => {
315 if buffer.len() < last_read + 4 {
316 (Err(DecodeError::IndexOutOfBounds), 4)
317 } else {
318 let decoded_result =
319 decode_u32(&buffer[last_read..last_read + 4], decode_order.clone());
320 (
321 decoded_result.map_or_else(
322 || Err(DecodeError::InvalidData(idx)),
323 |decoded| Ok(DecodedData::Uint32(decoded)),
324 ),
325 4,
326 )
327 }
328 }
329
330 DecodeType::Uint64 => {
331 if buffer.len() < last_read + 8 {
332 (Err(DecodeError::IndexOutOfBounds), 8)
333 } else {
334 let decoded_result =
335 decode_u64(&buffer[last_read..last_read + 8], decode_order.clone());
336 (
337 decoded_result.map_or_else(
338 || Err(DecodeError::InvalidData(idx)),
339 |decoded| Ok(DecodedData::Uint64(decoded)),
340 ),
341 8,
342 )
343 }
344 }
345
346 DecodeType::Uint128 => {
347 if buffer.len() < last_read + 16 {
348 (Err(DecodeError::IndexOutOfBounds), 16)
349 } else {
350 let decoded_result =
351 decode_u128(&buffer[last_read..last_read + 16], decode_order.clone());
352 (
353 decoded_result.map_or_else(
354 || Err(DecodeError::InvalidData(idx)),
355 |decoded| Ok(DecodedData::Uint128(decoded)),
356 ),
357 16,
358 )
359 }
360 }
361
362 DecodeType::Str(size) => {
363 if buffer.len() < last_read + *size {
364 (Err(DecodeError::IndexOutOfBounds), *size)
365 } else {
366 let decoded_result = decode_string(&buffer[last_read..last_read + *size]);
367 (
368 decoded_result.map_or_else(
369 || Err(DecodeError::InvalidData(idx)),
370 |decoded| Ok(DecodedData::Str(decoded)),
371 ),
372 *size,
373 )
374 }
375 }
376
377 DecodeType::Bytes(size) => {
378 if buffer.len() < last_read + *size {
379 (Err(DecodeError::IndexOutOfBounds), *size)
380 } else {
381 let vec_repr = buffer[last_read..last_read + *size].to_vec();
382 (Ok(DecodedData::Bytes(vec_repr)), *size)
383 }
384 }
385 };
386
387 if let Err(err) = result {
388 return Err(err);
389 }
390
391 last_read += size_offset;
392 decoded_data.push(result.unwrap());
393 }
394
395 Ok(decoded_data)
396}