messagepack_core/decode/
timestamp.rs

1use super::{Decode, Error, NbyteReader, Result};
2use crate::{
3    Format,
4    timestamp::{TIMESTAMP_EXTENSION_TYPE, Timestamp32, Timestamp64, Timestamp96},
5};
6
7impl<'a> Decode<'a> for Timestamp32 {
8    type Value = Timestamp32;
9    fn decode(buf: &'a [u8]) -> Result<(Self::Value, &'a [u8])> {
10        let (format, buf) = Format::decode(buf)?;
11        match format {
12            Format::FixExt4 => Self::decode_with_format(format, buf),
13            _ => Err(Error::UnexpectedFormat),
14        }
15    }
16    fn decode_with_format(format: crate::Format, buf: &'a [u8]) -> Result<(Self::Value, &'a [u8])> {
17        let (len, buf) = match format {
18            Format::FixExt4 => (4, buf),
19            _ => return Err(Error::UnexpectedFormat),
20        };
21        let (ext_type, buf) = buf.split_first().ok_or(Error::EofData)?;
22        let ext_type = (*ext_type) as i8;
23        if ext_type != TIMESTAMP_EXTENSION_TYPE {
24            return Err(Error::InvalidData);
25        }
26
27        let (data, rest) = buf.split_at_checked(len).ok_or(Error::EofData)?;
28        let timestamp = Self::from_buf(data.try_into().expect("expect 4 len"));
29        Ok((timestamp, rest))
30    }
31}
32
33impl<'a> Decode<'a> for Timestamp64 {
34    type Value = Timestamp64;
35    fn decode(buf: &'a [u8]) -> Result<(Self::Value, &'a [u8])> {
36        let (format, buf) = Format::decode(buf)?;
37        match format {
38            Format::FixExt8 => Self::decode_with_format(format, buf),
39            _ => Err(Error::UnexpectedFormat),
40        }
41    }
42    fn decode_with_format(format: crate::Format, buf: &'a [u8]) -> Result<(Self::Value, &'a [u8])> {
43        let (len, buf) = match format {
44            Format::FixExt8 => (8, buf),
45            _ => return Err(Error::UnexpectedFormat),
46        };
47        let (ext_type, buf) = buf.split_first().ok_or(Error::EofData)?;
48        let ext_type = (*ext_type) as i8;
49        if ext_type != TIMESTAMP_EXTENSION_TYPE {
50            return Err(Error::InvalidData);
51        }
52
53        let (data, rest) = buf.split_at_checked(len).ok_or(Error::EofData)?;
54        let timestamp = Self::from_buf(data.try_into().expect("expect 8 len"));
55        Ok((timestamp, rest))
56    }
57}
58
59impl<'a> Decode<'a> for Timestamp96 {
60    type Value = Timestamp96;
61    fn decode(buf: &'a [u8]) -> Result<(Self::Value, &'a [u8])> {
62        let (format, buf) = Format::decode(buf)?;
63        match format {
64            Format::Ext8 => Self::decode_with_format(format, buf),
65            _ => Err(Error::UnexpectedFormat),
66        }
67    }
68    fn decode_with_format(format: crate::Format, buf: &'a [u8]) -> Result<(Self::Value, &'a [u8])> {
69        let (len, buf) = match format {
70            Format::Ext8 => NbyteReader::<1>::read(buf)?,
71            _ => return Err(Error::UnexpectedFormat),
72        };
73        const TIMESTAMP96_DATA_LENGTH: usize = 12;
74        if len != TIMESTAMP96_DATA_LENGTH {
75            return Err(Error::InvalidData);
76        }
77
78        let (ext_type, buf) = buf.split_first().ok_or(Error::EofData)?;
79        let ext_type = (*ext_type) as i8;
80        if ext_type != TIMESTAMP_EXTENSION_TYPE {
81            return Err(Error::InvalidData);
82        }
83
84        let (data, rest) = buf.split_at_checked(len).ok_or(Error::EofData)?;
85        let timestamp = Self::from_buf(data.try_into().expect("expect 12 len"));
86        Ok((timestamp, rest))
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93    const TIMESTAMP_EXT_TYPE: u8 = 255; // -1
94
95    #[test]
96    fn decode_success_timestamp32() {
97        let secs: u32 = 1234567890;
98        let mut buf = vec![0xd6, TIMESTAMP_EXT_TYPE];
99        buf.extend_from_slice(&secs.to_be_bytes());
100
101        let (ts, rest) = Timestamp32::decode(&buf).unwrap();
102        assert_eq!(ts.seconds(), secs);
103        assert!(rest.is_empty());
104    }
105
106    #[test]
107    fn decode_failed_timestamp32_invalid_ext_type() {
108        let secs: u32 = 1;
109        let mut buf = vec![0xd6, 0]; // ext type != -1
110        buf.extend_from_slice(&secs.to_be_bytes());
111
112        let err = Timestamp32::decode(&buf).unwrap_err();
113        assert_eq!(err, Error::InvalidData);
114    }
115
116    #[test]
117    fn decode_failed_timestamp32_eof_data() {
118        let secs: u32 = 123;
119        let mut buf = vec![0xd6, TIMESTAMP_EXT_TYPE];
120        buf.extend_from_slice(&secs.to_be_bytes()[..3]); // 1 byte short
121
122        let err = Timestamp32::decode(&buf).unwrap_err();
123        assert_eq!(err, Error::EofData);
124    }
125
126    #[test]
127    fn decode_success_timestamp64() {
128        let secs: u64 = 1234567890;
129        let nanos: u32 = 789;
130
131        let data = ((nanos as u64) << 34) | secs;
132        let mut buf = vec![0xd7, TIMESTAMP_EXT_TYPE];
133        buf.extend_from_slice(&data.to_be_bytes());
134
135        let (ts, rest) = Timestamp64::decode(&buf).unwrap();
136        assert_eq!(ts.seconds(), secs);
137        assert_eq!(ts.nanos(), nanos);
138        assert!(rest.is_empty());
139    }
140
141    #[test]
142    fn decode_failed_timestamp64_unexpected_format() {
143        let mut buf = vec![0xd6, TIMESTAMP_EXT_TYPE]; // FixExt4, not FixExt8
144        buf.extend_from_slice(&0u64.to_be_bytes());
145
146        let err = Timestamp64::decode(&buf).unwrap_err();
147        assert_eq!(err, Error::UnexpectedFormat);
148    }
149
150    #[test]
151    fn decode_failed_timestamp64_invalid_ext_type() {
152        let mut buf = vec![0xd7, 0]; // ext type != -1
153        buf.extend_from_slice(&0u64.to_be_bytes());
154
155        let err = Timestamp64::decode(&buf).unwrap_err();
156        assert_eq!(err, Error::InvalidData);
157    }
158
159    #[test]
160    fn decode_failed_timestamp64_eof_data() {
161        let mut buf = vec![0xd7, TIMESTAMP_EXT_TYPE];
162        buf.extend_from_slice(&[0u8; 7]); // 1 byte short
163
164        let err = Timestamp64::decode(&buf).unwrap_err();
165        assert_eq!(err, Error::EofData);
166    }
167
168    #[test]
169    fn decode_success_timestamp96_positive() {
170        let secs: i64 = 123456;
171        let nanos: u32 = 789;
172
173        let mut buf = vec![0xc7, 12, TIMESTAMP_EXT_TYPE];
174        buf.extend_from_slice(&nanos.to_be_bytes());
175        buf.extend_from_slice(&secs.to_be_bytes());
176
177        let (ts, rest) = Timestamp96::decode(&buf).unwrap();
178        assert_eq!(ts.seconds(), secs);
179        assert_eq!(ts.nanos(), nanos);
180        assert!(rest.is_empty());
181    }
182
183    #[test]
184    fn decode_success_timestamp96_negative() {
185        let secs: i64 = -123;
186        let nanos: u32 = 42;
187
188        let mut buf = vec![0xc7, 12, TIMESTAMP_EXT_TYPE];
189        buf.extend_from_slice(&nanos.to_be_bytes());
190        buf.extend_from_slice(&secs.to_be_bytes());
191
192        let (ts, rest) = Timestamp96::decode(&buf).unwrap();
193        assert_eq!(ts.seconds(), secs);
194        assert_eq!(ts.nanos(), nanos);
195        assert!(rest.is_empty());
196    }
197
198    #[test]
199    fn decode_failed_timestamp96_unexpected_format() {
200        // FixExt8 header instead of Ext8
201        let mut buf = vec![0xd7, TIMESTAMP_EXT_TYPE];
202        buf.extend_from_slice(&[0u8; 8]);
203
204        let err = Timestamp96::decode(&buf).unwrap_err();
205        assert_eq!(err, Error::UnexpectedFormat);
206    }
207
208    #[test]
209    fn decode_failed_timestamp96_invalid_length() {
210        // Ext8 length != 12
211        let mut buf = vec![0xc7, 11, TIMESTAMP_EXT_TYPE];
212        buf.extend_from_slice(&[0u8; 11]);
213
214        let err = Timestamp96::decode(&buf).unwrap_err();
215        assert_eq!(err, Error::InvalidData);
216    }
217
218    #[test]
219    fn decode_failed_timestamp96_invalid_ext_type() {
220        let secs: i64 = 1;
221        let nanos: u32 = 2;
222
223        let mut buf = vec![0xc7, 12, 0]; // ext type != -1
224        buf.extend_from_slice(&nanos.to_be_bytes());
225        buf.extend_from_slice(&secs.to_be_bytes());
226
227        let err = Timestamp96::decode(&buf).unwrap_err();
228        assert_eq!(err, Error::InvalidData);
229    }
230
231    #[test]
232    fn decode_failed_timestamp96_eof_data() {
233        // length says 12 but provide 11
234        let mut buf = vec![0xc7, 12, TIMESTAMP_EXT_TYPE];
235        buf.extend_from_slice(&[0u8; 11]);
236
237        let err = Timestamp96::decode(&buf).unwrap_err();
238        assert_eq!(err, Error::EofData);
239    }
240}