Skip to main content

defuse_borsh_utils/
duration.rs

1use core::{fmt::Display, marker::PhantomData, time::Duration};
2
3use borsh::{BorshDeserialize, BorshSerialize, io};
4
5use crate::{BorshDeserializeAs, BorshSerializeAs};
6
7pub struct DurationSeconds<I = u64>(PhantomData<I>);
8
9impl<I> BorshSerializeAs<Duration> for DurationSeconds<I>
10where
11    I: TryFrom<u64> + BorshSerialize,
12    I::Error: Display,
13{
14    fn serialize_as<W>(source: &Duration, writer: &mut W) -> io::Result<()>
15    where
16        W: io::Write,
17    {
18        I::try_from(source.as_secs())
19            .map_err(|err| io::Error::other(err.to_string()))?
20            .serialize(writer)
21    }
22}
23
24impl<I> BorshDeserializeAs<Duration> for DurationSeconds<I>
25where
26    I: TryInto<u64> + BorshDeserialize,
27    I::Error: Display,
28{
29    fn deserialize_as<R>(reader: &mut R) -> io::Result<Duration>
30    where
31        R: io::Read,
32    {
33        I::deserialize_reader(reader)?
34            .try_into()
35            .map(Duration::from_secs)
36            .map_err(|err| io::Error::other(err.to_string()))
37    }
38}
39
40pub struct DurationMilliSeconds<I = u64>(PhantomData<I>);
41
42impl<I> BorshSerializeAs<Duration> for DurationMilliSeconds<I>
43where
44    I: TryFrom<u128> + BorshSerialize,
45    I::Error: Display,
46{
47    fn serialize_as<W>(source: &Duration, writer: &mut W) -> io::Result<()>
48    where
49        W: io::Write,
50    {
51        I::try_from(source.as_millis())
52            .map_err(|err| io::Error::other(err.to_string()))?
53            .serialize(writer)
54    }
55}
56
57impl<I> BorshDeserializeAs<Duration> for DurationMilliSeconds<I>
58where
59    I: TryInto<u64> + BorshDeserialize,
60    I::Error: Display,
61{
62    fn deserialize_as<R>(reader: &mut R) -> io::Result<Duration>
63    where
64        R: io::Read,
65    {
66        I::deserialize_reader(reader)?
67            .try_into()
68            .map(Duration::from_millis)
69            .map_err(|err| io::Error::other(err.to_string()))
70    }
71}
72
73pub struct DurationMicroSeconds<I = u64>(PhantomData<I>);
74
75impl<I> BorshSerializeAs<Duration> for DurationMicroSeconds<I>
76where
77    I: TryFrom<u128> + BorshSerialize,
78    I::Error: Display,
79{
80    fn serialize_as<W>(source: &Duration, writer: &mut W) -> io::Result<()>
81    where
82        W: io::Write,
83    {
84        I::try_from(source.as_micros())
85            .map_err(|err| io::Error::other(err.to_string()))?
86            .serialize(writer)
87    }
88}
89
90impl<I> BorshDeserializeAs<Duration> for DurationMicroSeconds<I>
91where
92    I: TryInto<u64> + BorshDeserialize,
93    I::Error: Display,
94{
95    fn deserialize_as<R>(reader: &mut R) -> io::Result<Duration>
96    where
97        R: io::Read,
98    {
99        I::deserialize_reader(reader)?
100            .try_into()
101            .map(Duration::from_micros)
102            .map_err(|err| io::Error::other(err.to_string()))
103    }
104}
105
106pub struct DurationNanoSeconds<I = u64>(PhantomData<I>);
107
108impl<I> BorshSerializeAs<Duration> for DurationNanoSeconds<I>
109where
110    I: TryFrom<u128> + BorshSerialize,
111    I::Error: Display,
112{
113    fn serialize_as<W>(source: &Duration, writer: &mut W) -> io::Result<()>
114    where
115        W: io::Write,
116    {
117        I::try_from(source.as_nanos())
118            .map_err(|err| io::Error::other(err.to_string()))?
119            .serialize(writer)
120    }
121}
122
123impl<I> BorshDeserializeAs<Duration> for DurationNanoSeconds<I>
124where
125    I: TryInto<u64> + BorshDeserialize,
126    I::Error: Display,
127{
128    fn deserialize_as<R>(reader: &mut R) -> io::Result<Duration>
129    where
130        R: io::Read,
131    {
132        I::deserialize_reader(reader)?
133            .try_into()
134            .map(Duration::from_nanos)
135            .map_err(|err| io::Error::other(err.to_string()))
136    }
137}
138
139#[cfg(feature = "schema")]
140const _: () = {
141    use crate::schema::impl_borsh_schema_as;
142
143    impl_borsh_schema_as!(Duration, DurationSeconds);
144    impl_borsh_schema_as!(Duration, DurationMilliSeconds);
145    impl_borsh_schema_as!(Duration, DurationMicroSeconds);
146    impl_borsh_schema_as!(Duration, DurationNanoSeconds);
147};