1#![no_std]
2use core::ops::Deref;
14
15pub const EXTENSION: i8 = -1;
17
18#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
20pub struct Buffer(BufferInner);
21#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
22enum BufferInner {
23 Four([u8; 4]),
24 Eight([u8; 8]),
25 Twelve([u8; 12]),
26}
27impl Deref for Buffer {
28 type Target = [u8];
29
30 fn deref(&self) -> &Self::Target {
31 match &self.0 {
32 BufferInner::Four(a) => a,
33 BufferInner::Eight(a) => a,
34 BufferInner::Twelve(a) => a,
35 }
36 }
37}
38impl AsRef<[u8]> for Buffer {
39 fn as_ref(&self) -> &[u8] {
40 self.deref()
41 }
42}
43
44#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
45pub struct Timestamp {
46 pub sec: i64,
47 pub nsec: u32,
48}
49
50pub fn pack(stamp: &Timestamp) -> Buffer {
52 let upper = stamp.sec >> 34;
53 if upper == 0 {
54 let data = (stamp.nsec as u64) << 34 | (stamp.sec as u64);
55 if data & 0xFFFF_FFFF_0000_0000 == 0 {
56 Buffer(BufferInner::Four((data as u32).to_be_bytes()))
57 } else {
58 Buffer(BufferInner::Eight(data.to_be_bytes()))
59 }
60 } else {
61 let mut ret = [0u8; 12];
62 let (ns, s) = ret.split_at_mut(4);
63 ns.copy_from_slice(&stamp.nsec.to_be_bytes());
64 s.copy_from_slice(&stamp.sec.to_be_bytes());
65 Buffer(BufferInner::Twelve(ret))
66 }
67}
68
69pub fn unpack(buf: &[u8]) -> Option<Timestamp> {
73 if let Ok(four) = buf.try_into() {
75 Some(Timestamp {
76 sec: u32::from_be_bytes(four) as _,
77 nsec: 0,
78 })
79 } else if let Ok(eight) = buf.try_into() {
80 let data = u64::from_be_bytes(eight);
81 Some(Timestamp {
82 sec: (data & 0x0000_0003_FFFF_FFFF) as _,
83 nsec: (data >> 34) as _,
84 })
85 } else if let Some((four, rest)) = buf.split_at_checked(4)
86 && let Ok(four) = four.try_into()
87 && let Ok(eight) = rest.try_into()
88 {
89 Some(Timestamp {
90 sec: i64::from_be_bytes(eight),
91 nsec: u32::from_be_bytes(four),
92 })
93 } else {
94 None
95 }
96}