proto_types/duration/
duration_impls.rs1use crate::Duration;
2
3impl Duration {
4 pub fn new(seconds: i64, nanos: i32) -> Self {
5 let mut instance = Duration { seconds, nanos };
6 instance.normalize();
7 instance
8 }
9}
10
11#[cfg(feature = "totokens")]
12mod totokens {
13 use proc_macro2::TokenStream;
14 use quote::{quote, ToTokens};
15
16 use crate::Duration;
17
18 impl ToTokens for Duration {
19 fn to_tokens(&self, tokens: &mut TokenStream) {
20 let seconds = self.seconds;
21 let nanos = self.nanos;
22
23 tokens.extend(quote! {
24 ::protocheck::types::Duration {
25 seconds: #seconds,
26 nanos: #nanos,
27 }
28 });
29 }
30 }
31}
32
33impl std::cmp::PartialOrd for Duration {
34 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
35 Some(self.cmp(other))
36 }
37}
38
39impl std::cmp::Ord for Duration {
40 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
41 (self.seconds, self.nanos).cmp(&(other.seconds, other.nanos))
42 }
43}
44
45#[cfg(all(feature = "serde", feature = "chrono"))]
46mod serde {
47 use core::fmt;
48
49 use chrono::Duration as ChronoDuration;
50 use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
51
52 use crate::Duration;
53 impl Serialize for Duration {
54 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55 where
56 S: Serializer,
57 {
58 let self_normalized = self.normalized();
59
60 let chrono_dur: ChronoDuration = self_normalized.try_into().map_err(|e| {
61 ser::Error::custom(format!(
62 "Failed to convert duration for serialization: {}",
63 e
64 ))
65 })?;
66
67 let seconds = chrono_dur.num_seconds();
68 let nanos = chrono_dur.subsec_nanos();
69
70 let formatted_string = if nanos == 0 {
71 format!("{}s", seconds)
73 } else {
74 let fractional_seconds_str = format!("{:09}", nanos);
75
76 let trimmed_fractional_seconds = fractional_seconds_str.trim_end_matches('0');
77
78 format!("{}.{}s", seconds, trimmed_fractional_seconds)
79 };
80
81 serializer.serialize_str(&formatted_string)
82 }
83 }
84
85 impl<'de> Deserialize<'de> for Duration {
86 fn deserialize<D>(deserializer: D) -> Result<Duration, D::Error>
87 where
88 D: Deserializer<'de>,
89 {
90 struct DurationVisitor;
91
92 impl de::Visitor<'_> for DurationVisitor {
93 type Value = Duration;
94
95 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
96 formatter.write_str("A duration ending in 's'")
97 }
98
99 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
100 where
101 E: de::Error,
102 {
103 if !value.ends_with('s') {
104 return Err(de::Error::custom("Duration should end with 's'"));
105 }
106
107 let duration_str = &value[..value.len() - 1]; let mut parts = duration_str.split('.'); let seconds: i64 = parts
112 .next()
113 .ok_or_else(|| de::Error::custom("Missing seconds"))?
114 .parse()
115 .map_err(de::Error::custom)?;
116
117 let nanos: i32 = match parts.next() {
118 Some(fraction) => {
119 let mut fraction_str = fraction.to_string(); if fraction_str.len() > 9 {
122 return Err(de::Error::custom(format!(
124 "Fractional part has more than 9 digits: {}",
125 fraction_str.len()
126 )));
127 }
128 fraction_str.reserve(9 - fraction_str.len()); for _ in fraction_str.len()..9 {
130 fraction_str.push('0');
131 }
132
133 fraction_str.parse().map_err(de::Error::custom)?
134 }
135 None => 0,
136 };
137
138 let mut duration = Duration { seconds, nanos };
139 duration.normalize(); Ok(duration)
142 }
143 }
144
145 deserializer.deserialize_str(DurationVisitor)
146 }
147 }
148}