proto_types/protovalidate/
into_comparable.rs1use paste::paste;
2
3use super::comparable_rules::{ComparableGreaterThan, ComparableLessThan, ComparableRules};
4use crate::{
5 protovalidate::{
6 double_rules::{GreaterThan as DoubleGreaterThan, LessThan as DoubleLessThan},
7 duration_rules::{GreaterThan as DurationGreaterThan, LessThan as DurationLessThan},
8 fixed32_rules::{GreaterThan as Fixed32GreaterThan, LessThan as Fixed32LessThan},
9 fixed64_rules::{GreaterThan as Fixed64GreaterThan, LessThan as Fixed64LessThan},
10 float_rules::{GreaterThan as FloatGreaterThan, LessThan as FloatLessThan},
11 int32_rules::{GreaterThan as Int32GreaterThan, LessThan as Int32LessThan},
12 int64_rules::{GreaterThan as Int64GreaterThan, LessThan as Int64LessThan},
13 s_fixed32_rules::{GreaterThan as SFixed32GreaterThan, LessThan as SFixed32LessThan},
14 s_fixed64_rules::{GreaterThan as SFixed64GreaterThan, LessThan as SFixed64LessThan},
15 s_int32_rules::{GreaterThan as SInt32GreaterThan, LessThan as SInt32LessThan},
16 s_int64_rules::{GreaterThan as SInt64GreaterThan, LessThan as SInt64LessThan},
17 timestamp_rules::{GreaterThan as TimestampGreaterThan, LessThan as TimestampLessThan},
18 u_int32_rules::{GreaterThan as UInt32GreaterThan, LessThan as UInt32LessThan},
19 u_int64_rules::{GreaterThan as UInt64GreaterThan, LessThan as UInt64LessThan},
20 DurationRules, TimestampComparableRules, TimestampRules,
21 },
22 Duration, Timestamp, TimestampError,
23};
24
25pub trait IntoComparable<T> {
26 fn into_comparable(self) -> T;
27}
28
29impl TimestampRules {
30 pub fn comparable_rules(&self) -> Result<TimestampComparableRules, String> {
31 let format_timestamp = |t: Timestamp, msg: &str| -> Result<String, String> {
32 t.format(&format!("{} {}", msg, "%d %b %Y %R %Z"))
33 .map_err(|e: TimestampError| {
34 format!(
35 "failed to convert protobuf timestamp to chrono timestamp: {}",
36 e
37 )
38 })
39 };
40
41 let mut greater_than: Option<ComparableGreaterThan<Timestamp>> = None;
42
43 if let Some(gt_rule) = self.greater_than {
44 greater_than = match gt_rule {
45 TimestampGreaterThan::Gt(v) => Some(ComparableGreaterThan::Gt {
46 val: v,
47 error_message: format_timestamp(v, "must be later than")?,
48 }),
49
50 TimestampGreaterThan::Gte(v) => Some(ComparableGreaterThan::Gte {
51 val: v,
52 error_message: format_timestamp(v, "cannot be earlier than")?,
53 }),
54 _ => None,
55 }
56 }
57
58 let mut less_than: Option<ComparableLessThan<Timestamp>> = None;
59
60 if let Some(gt_rule) = self.less_than {
61 less_than = match gt_rule {
62 TimestampLessThan::Lt(v) => Some(ComparableLessThan::Lt {
63 val: v,
64 error_message: format_timestamp(v, "must be earlier than")?,
65 }),
66
67 TimestampLessThan::Lte(v) => Some(ComparableLessThan::Lte {
68 val: v,
69 error_message: format_timestamp(v, "cannot be later than")?,
70 }),
71 _ => None,
72 }
73 }
74
75 let comparable_rules = ComparableRules {
76 less_than,
77 greater_than,
78 };
79
80 let lt_now = matches!(self.less_than, Some(TimestampLessThan::LtNow(true)));
81
82 let gt_now = matches!(self.greater_than, Some(TimestampGreaterThan::GtNow(true)));
83
84 Ok(TimestampComparableRules {
85 comparable_rules: comparable_rules.validate().map_err(|e| e.to_string())?,
86 lt_now,
87 gt_now,
88 })
89 }
90}
91
92impl DurationRules {
93 pub fn comparable_rules(&self) -> Result<ComparableRules<Duration>, &'static str> {
94 let greater_than = self.greater_than.map(|rule| match rule {
95 DurationGreaterThan::Gt(val) => ComparableGreaterThan::Gt {
96 val,
97 error_message: format!("must be longer than {}", val),
98 },
99 DurationGreaterThan::Gte(val) => ComparableGreaterThan::Gte {
100 val,
101 error_message: format!("cannot be shorter than {}", val),
102 },
103 });
104
105 let less_than = self.less_than.map(|rule| match rule {
106 DurationLessThan::Lt(val) => ComparableLessThan::Lt {
107 val,
108 error_message: format!("must be shorter than {}", val),
109 },
110 DurationLessThan::Lte(val) => ComparableLessThan::Lte {
111 val,
112 error_message: format!("cannot be longer than {}", val),
113 },
114 });
115
116 let comparable_rules = ComparableRules {
117 greater_than,
118 less_than,
119 };
120 comparable_rules.validate()
121 }
122}
123
124macro_rules! into_comparable {
125 ($target_type:ty, $rule_type:ident) => {
126 paste! {
127 impl IntoComparable<ComparableLessThan<$target_type>> for [< $rule_type LessThan >] {
128 fn into_comparable(self) -> ComparableLessThan<$target_type> {
129 match self {
130 Self::Lt(val) => ComparableLessThan::Lt { val, error_message: format!("must be smaller than {}", val) },
131 Self::Lte(val) => ComparableLessThan::Lte { val, error_message: format!("cannot be greater than {}", val) },
132 }
133 }
134 }
135
136 impl IntoComparable<ComparableGreaterThan<$target_type>> for [< $rule_type GreaterThan >] {
137 fn into_comparable(self) -> ComparableGreaterThan<$target_type> {
138 match self {
139 Self::Gt(val) => ComparableGreaterThan::Gt { val, error_message: format!("must be greater than {}", val) },
140 Self::Gte(val) => ComparableGreaterThan::Gte { val, error_message: format!("cannot be smaller than {}", val) },
141 }
142 }
143 }
144 }
145 };
146}
147
148into_comparable!(f32, Float);
149into_comparable!(f64, Double);
150into_comparable!(i64, Int64);
151into_comparable!(i32, Int32);
152into_comparable!(i64, SInt64);
153into_comparable!(i32, SInt32);
154into_comparable!(i64, SFixed64);
155into_comparable!(i32, SFixed32);
156into_comparable!(u64, UInt64);
157into_comparable!(u32, UInt32);
158into_comparable!(u64, Fixed64);
159into_comparable!(u32, Fixed32);