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}