@@ -31,7 +31,7 @@ use std::error;
31
31
32
32
use num_traits:: cast:: FromPrimitive ;
33
33
34
- use crate :: Marker ;
34
+ use crate :: { Marker , Timestamp } ;
35
35
36
36
pub mod bytes;
37
37
pub use bytes:: Bytes ;
@@ -244,6 +244,79 @@ pub fn read_marker<R: RmpRead>(rd: &mut R) -> Result<Marker, MarkerReadError<R::
244
244
Ok ( Marker :: from_u8 ( rd. read_u8 ( ) ?) )
245
245
}
246
246
247
+ /// Attempts to read an Extension struct from the given reader and to decode it as a Timestamp value.
248
+ ///
249
+ /// According to the MessagePack specification, there are 3 types of Timestamp, 32, 64, and 96.
250
+ ///
251
+ /// # Errors
252
+ ///
253
+ /// This function will return `ValueReadError` on any I/O error while reading the Timestamp,
254
+ /// except the EINTR, which is handled internally.
255
+ ///
256
+ /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the
257
+ /// expected one, indicating you with the actual type.
258
+ ///
259
+ /// # Note
260
+ ///
261
+ /// This function will silently retry on every EINTR received from the underlying `Read` until
262
+ /// successful read.
263
+ ///
264
+ /// # Examples
265
+ ///
266
+ /// ```
267
+ /// use rmp::Timestamp;
268
+ ///
269
+ /// // FixExt4 with a type of -1 (0xff)
270
+ /// let mut buf1 = [0xd6, 0xff, 0x66, 0xc1, 0xde, 0x7c];
271
+ /// // FixExt8 with a type of -1 (0xff)
272
+ /// let mut buf2 = [0xd7, 0xff, 0xee, 0x6b, 0x27, 0xfc, 0x66, 0xc1, 0xde, 0x7c];
273
+ /// // Ext8 with a size of 12 (0x0c) and a type of -1 (0xff)
274
+ /// let mut buf3 = [0xc7, 0x0c, 0xff, 0x3b, 0x9a, 0xc9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x66, 0xc1, 0xde, 0x7c];
275
+ ///
276
+ /// let ts1_expected = Timestamp::from_32(0x66c1de7c);
277
+ /// let ts2_expected = Timestamp::from_64(0x66c1de7c, 0x3b9ac9ff).unwrap();
278
+ /// let ts3_expected = Timestamp::from_96(0x66c1de7c, 0x3b9ac9ff).unwrap();
279
+ ///
280
+ /// let ts1_result = rmp::decode::read_timestamp(&mut buf1.as_slice()).unwrap();
281
+ /// let ts2_result = rmp::decode::read_timestamp(&mut buf2.as_slice()).unwrap();
282
+ /// let ts3_result = rmp::decode::read_timestamp(&mut buf3.as_slice()).unwrap();
283
+ ///
284
+ /// assert_eq!(ts1_expected, ts1_result);
285
+ /// assert_eq!(ts2_expected, ts2_result);
286
+ /// assert_eq!(ts3_expected, ts3_result);
287
+ /// ```
288
+ pub fn read_timestamp < R : RmpRead > ( rd : & mut R ) -> Result < Timestamp , ValueReadError < R :: Error > > {
289
+ let marker = read_marker ( rd) ?;
290
+ let prefix = rd. read_data_i8 ( ) ?;
291
+ match ( marker, prefix) {
292
+ // timestamp 32
293
+ ( Marker :: FixExt4 , -1 ) => {
294
+ let secs = rd. read_data_u32 ( ) ?;
295
+ Ok ( Timestamp :: from_32 ( secs) )
296
+ } ,
297
+ // timestamp 64
298
+ ( Marker :: FixExt8 , -1 ) => {
299
+ let data = rd. read_data_u64 ( ) ?;
300
+ Timestamp :: from_combined_64 ( data)
301
+ . ok_or ( ValueReadError :: TypeMismatch ( Marker :: Reserved ) )
302
+ } ,
303
+ // timestamp 96
304
+ ( Marker :: Ext8 , 12 ) => {
305
+ let prefix = rd. read_data_i8 ( ) ?;
306
+ if prefix == -1 {
307
+ let nsecs = rd. read_data_u32 ( ) ?;
308
+ let secs = rd. read_data_i64 ( ) ?;
309
+ Timestamp :: from_96 ( secs, nsecs)
310
+ . ok_or ( ValueReadError :: TypeMismatch ( Marker :: Reserved ) )
311
+ } else {
312
+ Err ( ValueReadError :: TypeMismatch ( Marker :: Reserved ) )
313
+ }
314
+ } ,
315
+ ( Marker :: Ext8 | Marker :: FixExt4 | Marker :: FixExt8 , _) => Err ( ValueReadError :: TypeMismatch ( Marker :: Reserved ) ) ,
316
+ ( marker, _) => Err ( ValueReadError :: TypeMismatch ( marker) ) ,
317
+ }
318
+ }
319
+
247
320
/// Attempts to read a single byte from the given reader and to decode it as a nil value.
248
321
///
249
322
/// According to the MessagePack specification, a nil value is represented as a single `0xc0` byte.
0 commit comments