nt_time/serde_with/unix_time/nanoseconds.rs
1// SPDX-FileCopyrightText: 2024 Shun Sakai
2//
3// SPDX-License-Identifier: Apache-2.0 OR MIT
4
5//! Use [Unix time] in nanoseconds when serializing and deserializing a
6//! [`FileTime`].
7//!
8//! Use this module in combination with Serde's [`with`] attribute.
9//!
10//! # Examples
11//!
12//! ```
13//! use nt_time::{
14//! FileTime,
15//! serde::{Deserialize, Serialize},
16//! serde_with::unix_time,
17//! };
18//!
19//! #[derive(Deserialize, Serialize)]
20//! struct Time {
21//! #[serde(with = "unix_time::nanoseconds")]
22//! time: FileTime,
23//! }
24//!
25//! let ft = Time {
26//! time: FileTime::NT_TIME_EPOCH,
27//! };
28//! let json = serde_json::to_string(&ft).unwrap();
29//! assert_eq!(json, r#"{"time":-11644473600000000000}"#);
30//!
31//! let ft: Time = serde_json::from_str(&json).unwrap();
32//! assert_eq!(ft.time, FileTime::NT_TIME_EPOCH);
33//! ```
34//!
35//! [Unix time]: https://en.wikipedia.org/wiki/Unix_time
36//! [`with`]: https://serde.rs/field-attrs.html#with
37
38pub mod option;
39
40use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
41
42use crate::FileTime;
43
44#[allow(clippy::missing_errors_doc)]
45/// Serializes a [`FileTime`] into the given Serde serializer.
46///
47/// This serializes using [Unix time] in nanoseconds.
48///
49/// [Unix time]: https://en.wikipedia.org/wiki/Unix_time
50#[inline]
51pub fn serialize<S: Serializer>(ft: &FileTime, serializer: S) -> Result<S::Ok, S::Error> {
52 ft.to_unix_time_nanos().serialize(serializer)
53}
54
55#[allow(clippy::missing_errors_doc)]
56/// Deserializes a [`FileTime`] from the given Serde deserializer.
57///
58/// This deserializes from its [Unix time] in nanoseconds.
59///
60/// [Unix time]: https://en.wikipedia.org/wiki/Unix_time
61#[inline]
62pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<FileTime, D::Error> {
63 FileTime::from_unix_time_nanos(<_>::deserialize(deserializer)?).map_err(D::Error::custom)
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
71 struct Test {
72 #[serde(with = "crate::serde_with::unix_time::nanoseconds")]
73 time: FileTime,
74 }
75
76 #[test]
77 fn serialize_json() {
78 assert_eq!(
79 serde_json::to_string(&Test {
80 time: FileTime::NT_TIME_EPOCH
81 })
82 .unwrap(),
83 r#"{"time":-11644473600000000000}"#
84 );
85 assert_eq!(
86 serde_json::to_string(&Test {
87 time: FileTime::UNIX_EPOCH
88 })
89 .unwrap(),
90 r#"{"time":0}"#
91 );
92 assert_eq!(
93 serde_json::to_string(&Test {
94 time: FileTime::MAX
95 })
96 .unwrap(),
97 r#"{"time":1833029933770955161500}"#
98 );
99 }
100
101 #[test]
102 fn deserialize_json() {
103 assert_eq!(
104 serde_json::from_str::<Test>(r#"{"time":-11644473600000000000}"#).unwrap(),
105 Test {
106 time: FileTime::NT_TIME_EPOCH
107 }
108 );
109 assert_eq!(
110 serde_json::from_str::<Test>(r#"{"time":0}"#).unwrap(),
111 Test {
112 time: FileTime::UNIX_EPOCH
113 }
114 );
115 assert_eq!(
116 serde_json::from_str::<Test>(r#"{"time":1833029933770955161500}"#).unwrap(),
117 Test {
118 time: FileTime::MAX
119 }
120 );
121 }
122}