use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
use crate::FileTime;
#[expect(clippy::missing_errors_doc)]
pub fn serialize<S: Serializer>(ft: &Option<FileTime>, serializer: S) -> Result<S::Ok, S::Error> {
ft.map(FileTime::to_unix_time_nanos).serialize(serializer)
}
#[expect(clippy::missing_errors_doc)]
pub fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Option<FileTime>, D::Error> {
Option::deserialize(deserializer)?
.map(FileTime::from_unix_time_nanos)
.transpose()
.map_err(D::Error::custom)
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
struct Test {
#[serde(with = "crate::serde_with::unix_time::nanoseconds::option")]
time: Option<FileTime>,
}
#[test]
fn serialize_json() {
assert_eq!(
serde_json::to_string(&Test {
time: Some(FileTime::NT_TIME_EPOCH)
})
.unwrap(),
r#"{"time":-11644473600000000000}"#
);
assert_eq!(
serde_json::to_string(&Test {
time: Some(FileTime::UNIX_EPOCH)
})
.unwrap(),
r#"{"time":0}"#
);
assert_eq!(
serde_json::to_string(&Test {
time: Some(FileTime::MAX)
})
.unwrap(),
r#"{"time":1833029933770955161500}"#
);
assert_eq!(
serde_json::to_string(&Test { time: None }).unwrap(),
r#"{"time":null}"#
);
}
#[test]
fn deserialize_json() {
assert_eq!(
serde_json::from_str::<Test>(r#"{"time":-11644473600000000000}"#).unwrap(),
Test {
time: Some(FileTime::NT_TIME_EPOCH)
}
);
assert_eq!(
serde_json::from_str::<Test>(r#"{"time":0}"#).unwrap(),
Test {
time: Some(FileTime::UNIX_EPOCH)
}
);
assert_eq!(
serde_json::from_str::<Test>(r#"{"time":1833029933770955161500}"#).unwrap(),
Test {
time: Some(FileTime::MAX)
}
);
assert_eq!(
serde_json::from_str::<Test>(r#"{"time":null}"#).unwrap(),
Test { time: None }
);
}
}