messagepack_core/
timestamp.rs1use crate::extension::{ExtensionRef, FixedExtension};
4
5pub(crate) const TIMESTAMP_EXTENSION_TYPE: i8 = -1;
6
7pub enum TryFromTimeStampError {
9 InvalidType,
11 InvalidDataLength,
13}
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
18pub struct Timestamp32 {
19 secs: u32,
20}
21
22impl Timestamp32 {
23 pub fn new(seconds: u32) -> Self {
25 Self { secs: seconds }
26 }
27
28 pub fn seconds(&self) -> u32 {
30 self.secs
31 }
32
33 pub(crate) fn to_buf(self) -> [u8; 4] {
34 self.secs.to_be_bytes()
35 }
36
37 pub(crate) fn from_buf(buf: [u8; 4]) -> Self {
38 Self {
39 secs: u32::from_be_bytes(buf),
40 }
41 }
42}
43
44impl TryFrom<ExtensionRef<'_>> for Timestamp32 {
45 type Error = TryFromTimeStampError;
46
47 fn try_from(value: ExtensionRef<'_>) -> Result<Self, Self::Error> {
48 if value.r#type != TIMESTAMP_EXTENSION_TYPE {
49 return Err(TryFromTimeStampError::InvalidType);
50 }
51
52 let data = value.data;
53 let mut buf = [0u8; 4];
54 if data.len() != buf.len() {
55 return Err(TryFromTimeStampError::InvalidDataLength);
56 }
57
58 buf.copy_from_slice(data);
59 Ok(Self::from_buf(buf))
60 }
61}
62
63impl TryFrom<FixedExtension<4>> for Timestamp32 {
64 type Error = TryFromTimeStampError;
65
66 fn try_from(value: FixedExtension<4>) -> Result<Self, Self::Error> {
67 value.as_ref().try_into()
68 }
69}
70
71impl From<Timestamp32> for FixedExtension<4> {
72 fn from(value: Timestamp32) -> Self {
73 let buf = value.to_buf();
74 FixedExtension::new_fixed(TIMESTAMP_EXTENSION_TYPE, buf.len(), buf)
75 }
76}
77
78#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
81pub struct Timestamp64 {
82 data: [u8; 8],
83}
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
87pub struct Timestamp64Error {
88 pub seconds: u64,
90 pub nanos: u32,
92}
93
94impl Timestamp64 {
95 pub fn new(seconds: u64, nanos: u32) -> Result<Self, Timestamp64Error> {
97 const SECONDS_MAX_LIMIT: u64 = 1 << 34;
98
99 if seconds >= SECONDS_MAX_LIMIT {
100 return Err(Timestamp64Error { seconds, nanos });
101 }
102
103 const NANOS_MAX_LIMIT: u32 = 1 << 30;
104 if nanos >= NANOS_MAX_LIMIT {
105 return Err(Timestamp64Error { seconds, nanos });
106 }
107
108 let mut buf = [0u8; 8];
109 buf[..].copy_from_slice(&seconds.to_be_bytes());
110
111 let nano = (nanos << 2).to_be_bytes();
112 buf[..3].copy_from_slice(&nano[..3]);
113 buf[3] |= nano[3];
114
115 Ok(Self::from_buf(buf))
116 }
117
118 pub fn nanos(&self) -> u32 {
120 let mut buf = [0u8; 4];
121 buf.copy_from_slice(&self.data[..4]);
122 let nanosec = u32::from_be_bytes(buf);
123 nanosec >> 2
124 }
125
126 pub fn seconds(&self) -> u64 {
128 const MASK: u64 = (1 << 34) - 1;
130 let mut buf = [0u8; 8];
131 buf.copy_from_slice(&self.data[..]);
132 let seconds = u64::from_be_bytes(buf);
133
134 seconds & MASK
135 }
136
137 pub(crate) fn to_buf(self) -> [u8; 8] {
138 self.data
139 }
140
141 pub(crate) fn from_buf(buf: [u8; 8]) -> Self {
142 Self { data: buf }
143 }
144}
145
146impl TryFrom<ExtensionRef<'_>> for Timestamp64 {
147 type Error = TryFromTimeStampError;
148
149 fn try_from(value: ExtensionRef<'_>) -> Result<Self, Self::Error> {
150 if value.r#type != TIMESTAMP_EXTENSION_TYPE {
151 return Err(TryFromTimeStampError::InvalidType);
152 }
153
154 let data = value.data;
155 let mut buf = [0u8; 8];
156 if data.len() != buf.len() {
157 return Err(TryFromTimeStampError::InvalidDataLength);
158 }
159
160 buf.copy_from_slice(data);
161 Ok(Self::from_buf(buf))
162 }
163}
164
165impl TryFrom<FixedExtension<8>> for Timestamp64 {
166 type Error = TryFromTimeStampError;
167
168 fn try_from(value: FixedExtension<8>) -> Result<Self, Self::Error> {
169 value.as_ref().try_into()
170 }
171}
172
173impl From<Timestamp64> for FixedExtension<8> {
174 fn from(value: Timestamp64) -> Self {
175 let buf = value.to_buf();
176 FixedExtension::new_fixed(TIMESTAMP_EXTENSION_TYPE, buf.len(), buf)
177 }
178}
179
180#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
183pub struct Timestamp96 {
184 nanos: u32,
185 secs: i64,
186}
187
188impl Timestamp96 {
189 pub fn new(seconds: i64, nanoseconds: u32) -> Self {
191 Self {
192 nanos: nanoseconds,
193 secs: seconds,
194 }
195 }
196
197 pub fn nanos(&self) -> u32 {
199 self.nanos
200 }
201
202 pub fn seconds(&self) -> i64 {
204 self.secs
205 }
206
207 pub(crate) fn to_buf(self) -> [u8; 12] {
208 let mut buf = [0u8; 12];
209 buf[..4].copy_from_slice(&self.nanos.to_be_bytes());
210 buf[4..].copy_from_slice(&self.secs.to_be_bytes());
211
212 buf
213 }
214
215 pub(crate) fn from_buf(buf: [u8; 12]) -> Self {
216 let mut nano = [0u8; 4];
217 nano.copy_from_slice(&buf[..4]);
218
219 let mut second = [0u8; 8];
220 second.copy_from_slice(&buf[4..]);
221
222 Self {
223 nanos: u32::from_be_bytes(nano),
224 secs: i64::from_be_bytes(second),
225 }
226 }
227}
228
229impl TryFrom<ExtensionRef<'_>> for Timestamp96 {
230 type Error = TryFromTimeStampError;
231
232 fn try_from(value: ExtensionRef<'_>) -> Result<Self, Self::Error> {
233 if value.r#type != TIMESTAMP_EXTENSION_TYPE {
234 return Err(TryFromTimeStampError::InvalidType);
235 }
236
237 let data = value.data;
238 let mut buf = [0u8; 12];
239 if data.len() != buf.len() {
240 return Err(TryFromTimeStampError::InvalidDataLength);
241 }
242
243 buf.copy_from_slice(data);
244 Ok(Self::from_buf(buf))
245 }
246}
247
248impl TryFrom<FixedExtension<12>> for Timestamp96 {
249 type Error = TryFromTimeStampError;
250
251 fn try_from(value: FixedExtension<12>) -> Result<Self, Self::Error> {
252 value.as_ref().try_into()
253 }
254}
255
256impl From<Timestamp96> for FixedExtension<12> {
257 fn from(value: Timestamp96) -> Self {
258 let buf = value.to_buf();
259 FixedExtension::new_fixed(TIMESTAMP_EXTENSION_TYPE, buf.len(), buf)
260 }
261}