messagepack_core/decode/
extension.rs

1use super::{Decode, Error, NbyteReader, Result};
2use crate::formats::Format;
3
4pub struct Extension<'a> {
5    pub r#type: i8,
6    pub data: &'a [u8],
7}
8
9pub struct ExtensionDecoder;
10
11impl<'a> Decode<'a> for ExtensionDecoder {
12    type Value = Extension<'a>;
13    fn decode(buf: &'a [u8]) -> Result<(Self::Value, &'a [u8])> {
14        let (format, buf) = Format::decode(buf)?;
15        match format {
16            Format::FixExt1
17            | Format::FixExt2
18            | Format::FixExt4
19            | Format::FixExt8
20            | Format::FixExt16
21            | Format::Ext8
22            | Format::Ext16
23            | Format::Ext32 => Self::decode_with_format(format, buf),
24            _ => Err(Error::UnexpectedFormat),
25        }
26    }
27    fn decode_with_format(format: Format, buf: &'a [u8]) -> Result<(Self::Value, &'a [u8])> {
28        let (ext_type, buf) = buf.split_first().ok_or(Error::EofData)?;
29        let (len, buf) = match format {
30            Format::FixExt1 => (1, buf),
31            Format::FixExt2 => (2, buf),
32            Format::FixExt4 => (4, buf),
33            Format::FixExt8 => (8, buf),
34            Format::FixExt16 => (16, buf),
35            Format::Ext8 => NbyteReader::<1>::read(buf)?,
36            Format::Ext16 => NbyteReader::<2>::read(buf)?,
37            Format::Ext32 => NbyteReader::<4>::read(buf)?,
38            _ => return Err(Error::UnexpectedFormat),
39        };
40        let (data, rest) = buf.split_at_checked(len).ok_or(Error::EofData)?;
41        let ext = Extension {
42            r#type: (*ext_type) as i8,
43            data,
44        };
45        Ok((ext, rest))
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    const TIMESTAMP32: &[u8] = &[
54        0xd6, // FixExt4
55        0xff, // Timestamp type = -1
56        // Feb 22 2022 22:22:22 GMT+0000
57        // Unix sec = 1645568542
58        0x62, 0x15, 0x62, 0x1e,
59    ];
60
61    #[test]
62    fn decode_fix_ext4() {
63        let (ext, rest) = ExtensionDecoder::decode(TIMESTAMP32).unwrap();
64
65        let expect_type = -1;
66        let expect_data = 1645568542;
67        assert_eq!(ext.r#type, expect_type);
68        let data_u32 = u32::from_be_bytes(ext.data.try_into().unwrap());
69        assert_eq!(data_u32, expect_data);
70        assert_eq!(rest.len(), 0);
71    }
72}