Skip to main content

ferrex_model/
rkyv_wrappers.rs

1#[cfg(feature = "rkyv")]
2use rkyv::{
3    Archive, Archived, Deserialize, Place, Serialize,
4    rancor::Fallible,
5    with::{ArchiveWith, DeserializeWith, SerializeWith},
6};
7use std::path::PathBuf;
8
9use crate::chrono::{DateTime, Utc};
10
11// Wrapper for PathBuf
12#[derive(Debug, Clone, Copy, Default)]
13pub struct PathBufWrapper;
14
15impl ArchiveWith<PathBuf> for PathBufWrapper {
16    type Archived = Archived<String>;
17    type Resolver = <String as Archive>::Resolver;
18
19    fn resolve_with(
20        field: &PathBuf,
21        resolver: Self::Resolver,
22        out: Place<Self::Archived>,
23    ) {
24        let path_str = field.to_string_lossy().to_string();
25        path_str.resolve(resolver, out);
26    }
27}
28
29impl<S: Fallible + ?Sized> SerializeWith<PathBuf, S> for PathBufWrapper
30where
31    String: Serialize<S>,
32{
33    fn serialize_with(
34        field: &PathBuf,
35        serializer: &mut S,
36    ) -> Result<Self::Resolver, S::Error> {
37        let path_str = field.to_string_lossy().to_string();
38        path_str.serialize(serializer)
39    }
40}
41
42impl<D: Fallible + ?Sized> DeserializeWith<Archived<String>, PathBuf, D>
43    for PathBufWrapper
44where
45    Archived<String>: Deserialize<String, D>,
46{
47    fn deserialize_with(
48        field: &Archived<String>,
49        deserializer: &mut D,
50    ) -> Result<PathBuf, D::Error> {
51        let path_str: String = field.deserialize(deserializer)?;
52        Ok(PathBuf::from(path_str))
53    }
54}
55
56// Wrapper for DateTime<Utc>
57#[derive(Debug, Clone, Copy, Default)]
58pub struct DateTimeWrapper;
59
60impl ArchiveWith<DateTime<Utc>> for DateTimeWrapper {
61    type Archived = Archived<i64>; // Use Archived<i64> instead of raw i64
62    type Resolver = <i64 as Archive>::Resolver;
63
64    fn resolve_with(
65        field: &DateTime<Utc>,
66        resolver: Self::Resolver,
67        out: Place<Self::Archived>,
68    ) {
69        let timestamp = field.timestamp();
70        timestamp.resolve(resolver, out);
71    }
72}
73
74impl<S: Fallible + ?Sized> SerializeWith<DateTime<Utc>, S> for DateTimeWrapper
75where
76    i64: Serialize<S>,
77{
78    fn serialize_with(
79        field: &DateTime<Utc>,
80        serializer: &mut S,
81    ) -> Result<Self::Resolver, <S as Fallible>::Error> {
82        let timestamp = field.timestamp();
83        timestamp.serialize(serializer)
84    }
85}
86
87impl<D: Fallible + ?Sized> DeserializeWith<Archived<i64>, DateTime<Utc>, D>
88    for DateTimeWrapper
89where
90    Archived<i64>: Deserialize<i64, D>,
91{
92    fn deserialize_with(
93        field: &Archived<i64>,
94        deserializer: &mut D,
95    ) -> Result<DateTime<Utc>, <D as Fallible>::Error> {
96        let timestamp: i64 = field.deserialize(deserializer)?;
97        Ok(DateTime::from_timestamp(timestamp, 0).unwrap_or_else(Utc::now))
98    }
99}
100
101// Wrapper for Vec<PathBuf>
102#[derive(Debug, Clone, Copy, Default)]
103pub struct VecPathBuf;
104
105impl ArchiveWith<Vec<PathBuf>> for VecPathBuf {
106    type Archived = Archived<Vec<String>>;
107    type Resolver = <Vec<String> as Archive>::Resolver;
108
109    fn resolve_with(
110        field: &Vec<PathBuf>,
111        resolver: Self::Resolver,
112        out: Place<Self::Archived>,
113    ) {
114        let strings: Vec<String> = field
115            .iter()
116            .map(|p| p.to_string_lossy().to_string())
117            .collect();
118        strings.resolve(resolver, out);
119    }
120}
121
122impl<S: Fallible + ?Sized> SerializeWith<Vec<PathBuf>, S> for VecPathBuf
123where
124    Vec<String>: Serialize<S>,
125{
126    fn serialize_with(
127        field: &Vec<PathBuf>,
128        serializer: &mut S,
129    ) -> Result<Self::Resolver, <S as Fallible>::Error> {
130        let strings: Vec<String> = field
131            .iter()
132            .map(|p| p.to_string_lossy().to_string())
133            .collect();
134        strings.serialize(serializer)
135    }
136}
137
138impl<D: Fallible + ?Sized>
139    DeserializeWith<Archived<Vec<String>>, Vec<PathBuf>, D> for VecPathBuf
140where
141    Archived<Vec<String>>: Deserialize<Vec<String>, D>,
142{
143    fn deserialize_with(
144        field: &Archived<Vec<String>>,
145        deserializer: &mut D,
146    ) -> Result<Vec<PathBuf>, <D as Fallible>::Error> {
147        let strings: Vec<String> = field.deserialize(deserializer)?;
148        Ok(strings.into_iter().map(PathBuf::from).collect())
149    }
150}
151
152// Wrapper for Option<DateTime>
153#[derive(Debug, Clone, Copy, Default)]
154pub struct OptionDateTime;
155
156impl ArchiveWith<Option<DateTime<Utc>>> for OptionDateTime {
157    type Archived = Archived<Option<i64>>;
158    type Resolver = <Option<i64> as Archive>::Resolver;
159
160    fn resolve_with(
161        field: &Option<DateTime<Utc>>,
162        resolver: Self::Resolver,
163        out: Place<Self::Archived>,
164    ) {
165        let timestamp = field.map(|dt| dt.timestamp());
166        timestamp.resolve(resolver, out);
167    }
168}
169
170impl<S: Fallible + ?Sized> SerializeWith<Option<DateTime<Utc>>, S>
171    for OptionDateTime
172where
173    Option<i64>: Serialize<S>,
174{
175    fn serialize_with(
176        field: &Option<DateTime<Utc>>,
177        serializer: &mut S,
178    ) -> Result<Self::Resolver, <S as Fallible>::Error> {
179        let timestamp = field.map(|dt| dt.timestamp());
180        timestamp.serialize(serializer)
181    }
182}
183
184impl<D: Fallible + ?Sized>
185    DeserializeWith<Archived<Option<i64>>, Option<DateTime<Utc>>, D>
186    for OptionDateTime
187where
188    Archived<Option<i64>>: Deserialize<Option<i64>, D>,
189{
190    fn deserialize_with(
191        field: &Archived<Option<i64>>,
192        deserializer: &mut D,
193    ) -> Result<Option<DateTime<Utc>>, <D as Fallible>::Error> {
194        let timestamp: Option<i64> = field.deserialize(deserializer)?;
195        Ok(timestamp.and_then(|ts| DateTime::from_timestamp(ts, 0)))
196    }
197}
198
199// Wrapper for std::time::Duration
200#[derive(Debug, Clone, Copy, Default)]
201pub struct DurationWrapper;
202
203impl ArchiveWith<std::time::Duration> for DurationWrapper {
204    type Archived = Archived<u64>; // Store as total seconds
205    type Resolver = <u64 as Archive>::Resolver;
206
207    fn resolve_with(
208        field: &std::time::Duration,
209        resolver: Self::Resolver,
210        out: Place<Self::Archived>,
211    ) {
212        let secs = field.as_secs();
213        secs.resolve(resolver, out);
214    }
215}
216
217impl<S: Fallible + ?Sized> SerializeWith<std::time::Duration, S>
218    for DurationWrapper
219where
220    u64: Serialize<S>,
221{
222    fn serialize_with(
223        field: &std::time::Duration,
224        serializer: &mut S,
225    ) -> Result<Self::Resolver, <S as Fallible>::Error> {
226        let secs = field.as_secs();
227        secs.serialize(serializer)
228    }
229}
230
231impl<D: Fallible + ?Sized>
232    DeserializeWith<Archived<u64>, std::time::Duration, D> for DurationWrapper
233where
234    Archived<u64>: Deserialize<u64, D>,
235{
236    fn deserialize_with(
237        field: &Archived<u64>,
238        deserializer: &mut D,
239    ) -> Result<std::time::Duration, <D as Fallible>::Error> {
240        let secs: u64 = field.deserialize(deserializer)?;
241        Ok(std::time::Duration::from_secs(secs))
242    }
243}