fory_core/serializer/
datetime.rs1use crate::context::ReadContext;
19use crate::context::WriteContext;
20use crate::error::Error;
21use crate::resolver::TypeResolver;
22use crate::serializer::util::read_basic_type_info;
23use crate::serializer::ForyDefault;
24use crate::serializer::Serializer;
25use crate::type_id::TypeId;
26use crate::types::{Date, Duration, Timestamp};
27use std::mem;
28
29impl Serializer for Timestamp {
30 #[inline(always)]
31 fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
32 context.writer.write_i64(self.seconds());
33 context.writer.write_u32(self.subsec_nanos());
34 Ok(())
35 }
36
37 #[inline(always)]
38 fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
39 let seconds = context.reader.read_i64()?;
40 let nanos = context.reader.read_u32()?;
41 Timestamp::new(seconds, nanos)
42 }
43
44 #[inline(always)]
45 fn fory_reserved_space() -> usize {
46 mem::size_of::<i64>() + mem::size_of::<u32>()
47 }
48
49 #[inline(always)]
50 fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
51 Ok(TypeId::TIMESTAMP)
52 }
53
54 #[inline(always)]
55 fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
56 Ok(TypeId::TIMESTAMP)
57 }
58
59 #[inline(always)]
60 fn fory_static_type_id() -> TypeId {
61 TypeId::TIMESTAMP
62 }
63
64 #[inline(always)]
65 fn as_any(&self) -> &dyn std::any::Any {
66 self
67 }
68
69 #[inline(always)]
70 fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
71 context.writer.write_u8(TypeId::TIMESTAMP as u8);
72 Ok(())
73 }
74
75 #[inline(always)]
76 fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
77 read_basic_type_info::<Self>(context)
78 }
79}
80
81impl ForyDefault for Timestamp {
82 #[inline(always)]
83 fn fory_default() -> Self {
84 Timestamp::default()
85 }
86}
87
88impl Serializer for Date {
89 #[inline(always)]
90 fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
91 let days = self.epoch_days();
92 if context.is_xlang() {
93 context.writer.write_var_i64(days);
94 } else {
95 let native_days = i32::try_from(days).map_err(|_| {
96 Error::invalid_data(format!("date day count {} exceeds native i32 range", days))
97 })?;
98 context.writer.write_i32(native_days);
99 }
100 Ok(())
101 }
102
103 #[inline(always)]
104 fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
105 let days = if context.is_xlang() {
106 context.reader.read_var_i64()?
107 } else {
108 i64::from(context.reader.read_i32()?)
109 };
110 Ok(Date::from_epoch_days(days))
111 }
112
113 #[inline(always)]
114 fn fory_reserved_space() -> usize {
115 9
116 }
117
118 #[inline(always)]
119 fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
120 Ok(TypeId::DATE)
121 }
122
123 #[inline(always)]
124 fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
125 Ok(TypeId::DATE)
126 }
127
128 #[inline(always)]
129 fn fory_static_type_id() -> TypeId {
130 TypeId::DATE
131 }
132
133 #[inline(always)]
134 fn as_any(&self) -> &dyn std::any::Any {
135 self
136 }
137
138 #[inline(always)]
139 fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
140 context.writer.write_u8(TypeId::DATE as u8);
141 Ok(())
142 }
143
144 #[inline(always)]
145 fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
146 read_basic_type_info::<Self>(context)
147 }
148}
149
150impl ForyDefault for Date {
151 #[inline(always)]
152 fn fory_default() -> Self {
153 Date::default()
154 }
155}
156
157impl Serializer for Duration {
158 #[inline(always)]
159 fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
160 context.writer.write_var_i64(self.seconds());
161 context.writer.write_i32(self.subsec_nanos() as i32);
162 Ok(())
163 }
164
165 #[inline(always)]
166 fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
167 let seconds = context.reader.read_var_i64()?;
168 let nanos = context.reader.read_i32()?;
169 Duration::new(seconds, nanos)
170 }
171
172 #[inline(always)]
173 fn fory_reserved_space() -> usize {
174 9 + mem::size_of::<i32>()
175 }
176
177 #[inline(always)]
178 fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
179 Ok(TypeId::DURATION)
180 }
181
182 #[inline(always)]
183 fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
184 Ok(TypeId::DURATION)
185 }
186
187 #[inline(always)]
188 fn fory_static_type_id() -> TypeId {
189 TypeId::DURATION
190 }
191
192 #[inline(always)]
193 fn as_any(&self) -> &dyn std::any::Any {
194 self
195 }
196
197 #[inline(always)]
198 fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
199 context.writer.write_u8(TypeId::DURATION as u8);
200 Ok(())
201 }
202
203 #[inline(always)]
204 fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
205 read_basic_type_info::<Self>(context)
206 }
207}
208
209impl ForyDefault for Duration {
210 #[inline(always)]
211 fn fory_default() -> Self {
212 Duration::default()
213 }
214}
215
216#[cfg(feature = "chrono")]
217mod chrono_support {
218 use super::*;
219 use chrono::{Duration as ChronoDuration, NaiveDate, NaiveDateTime};
220
221 impl Serializer for NaiveDateTime {
222 #[inline(always)]
223 fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
224 Timestamp::from(*self).fory_write_data(context)
225 }
226
227 #[inline(always)]
228 fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
229 Timestamp::fory_read_data(context)?.try_into()
230 }
231
232 #[inline(always)]
233 fn fory_reserved_space() -> usize {
234 Timestamp::fory_reserved_space()
235 }
236
237 #[inline(always)]
238 fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
239 Ok(TypeId::TIMESTAMP)
240 }
241
242 #[inline(always)]
243 fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
244 Ok(TypeId::TIMESTAMP)
245 }
246
247 #[inline(always)]
248 fn fory_static_type_id() -> TypeId {
249 TypeId::TIMESTAMP
250 }
251
252 #[inline(always)]
253 fn as_any(&self) -> &dyn std::any::Any {
254 self
255 }
256
257 #[inline(always)]
258 fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
259 Timestamp::fory_write_type_info(context)
260 }
261
262 #[inline(always)]
263 fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
264 read_basic_type_info::<Self>(context)
265 }
266 }
267
268 impl ForyDefault for NaiveDateTime {
269 #[inline(always)]
270 fn fory_default() -> Self {
271 NaiveDateTime::default()
272 }
273 }
274
275 impl Serializer for NaiveDate {
276 #[inline(always)]
277 fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
278 Date::from(*self).fory_write_data(context)
279 }
280
281 #[inline(always)]
282 fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
283 Date::fory_read_data(context)?.try_into()
284 }
285
286 #[inline(always)]
287 fn fory_reserved_space() -> usize {
288 Date::fory_reserved_space()
289 }
290
291 #[inline(always)]
292 fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
293 Ok(TypeId::DATE)
294 }
295
296 #[inline(always)]
297 fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
298 Ok(TypeId::DATE)
299 }
300
301 #[inline(always)]
302 fn fory_static_type_id() -> TypeId {
303 TypeId::DATE
304 }
305
306 #[inline(always)]
307 fn as_any(&self) -> &dyn std::any::Any {
308 self
309 }
310
311 #[inline(always)]
312 fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
313 Date::fory_write_type_info(context)
314 }
315
316 #[inline(always)]
317 fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
318 read_basic_type_info::<Self>(context)
319 }
320 }
321
322 impl ForyDefault for NaiveDate {
323 #[inline(always)]
324 fn fory_default() -> Self {
325 NaiveDate::default()
326 }
327 }
328
329 impl Serializer for ChronoDuration {
330 #[inline(always)]
331 fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
332 Duration::try_from(*self)?.fory_write_data(context)
333 }
334
335 #[inline(always)]
336 fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
337 Duration::fory_read_data(context)?.try_into()
338 }
339
340 #[inline(always)]
341 fn fory_reserved_space() -> usize {
342 Duration::fory_reserved_space()
343 }
344
345 #[inline(always)]
346 fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
347 Ok(TypeId::DURATION)
348 }
349
350 #[inline(always)]
351 fn fory_type_id_dyn(&self, _: &TypeResolver) -> Result<TypeId, Error> {
352 Ok(TypeId::DURATION)
353 }
354
355 #[inline(always)]
356 fn fory_static_type_id() -> TypeId {
357 TypeId::DURATION
358 }
359
360 #[inline(always)]
361 fn as_any(&self) -> &dyn std::any::Any {
362 self
363 }
364
365 #[inline(always)]
366 fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
367 Duration::fory_write_type_info(context)
368 }
369
370 #[inline(always)]
371 fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
372 read_basic_type_info::<Self>(context)
373 }
374 }
375
376 impl ForyDefault for ChronoDuration {
377 #[inline(always)]
378 fn fory_default() -> Self {
379 ChronoDuration::zero()
380 }
381 }
382}
383
384#[cfg(test)]
385mod tests {
386 use super::*;
387 use crate::fory::Fory;
388
389 #[test]
390 fn test_temporal_carrier_serialization() {
391 let fory = Fory::builder().xlang(false).build();
392
393 let timestamps = [
394 Timestamp::UNIX_EPOCH,
395 Timestamp::new(1, 0).unwrap(),
396 Timestamp::new(-1, 999_999_999).unwrap(),
397 ];
398 for timestamp in timestamps {
399 let bytes = fory.serialize(×tamp).unwrap();
400 let deserialized: Timestamp = fory.deserialize(&bytes).unwrap();
401 assert_eq!(timestamp, deserialized);
402 }
403
404 let dates = [
405 Date::UNIX_EPOCH,
406 Date::from_epoch_days(-1),
407 Date::from_epoch_days(18_628),
408 ];
409 for date in dates {
410 let bytes = fory.serialize(&date).unwrap();
411 let deserialized: Date = fory.deserialize(&bytes).unwrap();
412 assert_eq!(date, deserialized);
413 }
414
415 let durations = [
416 Duration::ZERO,
417 Duration::new(1, 0).unwrap(),
418 Duration::new(0, -1).unwrap(),
419 Duration::new(-123, 456_789).unwrap(),
420 ];
421 for duration in durations {
422 let bytes = fory.serialize(&duration).unwrap();
423 let deserialized: Duration = fory.deserialize(&bytes).unwrap();
424 assert_eq!(duration, deserialized);
425 }
426 }
427
428 #[test]
429 fn test_duration_normalizes_negative_nanoseconds() {
430 assert_eq!(
431 Duration::new(0, -1).unwrap(),
432 Duration::from_normalized(-1, 999_999_999).unwrap()
433 );
434 }
435
436 #[cfg(feature = "chrono")]
437 #[test]
438 fn test_chrono_temporal_feature_serialization() {
439 use chrono::{DateTime, Duration as ChronoDuration, NaiveDate, NaiveDateTime};
440
441 let fory = Fory::builder().xlang(false).build();
442 let date = NaiveDate::from_ymd_opt(2024, 2, 3).unwrap();
443 let timestamp = DateTime::from_timestamp(100, 1).unwrap().naive_utc();
444 let duration = ChronoDuration::nanoseconds(-1);
445
446 let bytes = fory.serialize(&date).unwrap();
447 let deserialized: NaiveDate = fory.deserialize(&bytes).unwrap();
448 assert_eq!(date, deserialized);
449
450 let bytes = fory.serialize(×tamp).unwrap();
451 let deserialized: NaiveDateTime = fory.deserialize(&bytes).unwrap();
452 assert_eq!(timestamp, deserialized);
453
454 let bytes = fory.serialize(&duration).unwrap();
455 let deserialized: ChronoDuration = fory.deserialize(&bytes).unwrap();
456 assert_eq!(duration, deserialized);
457 }
458}