1use serde::{Serialize, Serializer};
2
3#[doc(hidden)]
7#[derive(Copy, Clone, Eq, PartialEq, Debug)]
8pub struct AlwaysTrue;
9
10impl serde::Serialize for AlwaysTrue {
11 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
12 where
13 S: Serializer,
14 {
15 serializer.serialize_bool(true)
16 }
17}
18
19#[cfg(feature = "deserialize")]
20impl<'de> serde::Deserialize<'de> for AlwaysTrue {
21 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
22 where
23 D: serde::Deserializer<'de>,
24 {
25 let bool_: bool = serde::Deserialize::deserialize(deserializer)?;
26 if !bool_ {
27 Err(serde::de::Error::custom("Expected value to always be `true`"))
28 } else {
29 Ok(AlwaysTrue)
30 }
31 }
32}
33
34#[doc(hidden)]
35mod miniserde_deser {
36 use miniserde::de::Visitor;
37 use miniserde::json::Value;
38 use miniserde::Deserialize;
39
40 use crate::miniserde_helpers::FromValueOpt;
41 use crate::{AlwaysTrue, Place};
42
43 impl Deserialize for AlwaysTrue {
44 fn begin(out: &mut Option<Self>) -> &mut dyn Visitor {
45 Place::new(out)
46 }
47 }
48
49 impl Visitor for Place<AlwaysTrue> {
50 fn boolean(&mut self, b: bool) -> miniserde::Result<()> {
51 if b {
52 self.out = Some(AlwaysTrue);
53 Ok(())
54 } else {
55 Err(miniserde::Error)
56 }
57 }
58 }
59
60 impl FromValueOpt for AlwaysTrue {
61 fn from_value(v: Value) -> Option<Self> {
62 let b = bool::from_value(v)?;
63 if b {
64 Some(AlwaysTrue)
65 } else {
66 None
67 }
68 }
69 }
70}
71
72pub type Timestamp = i64;
74
75#[derive(Copy, Clone, Debug, Serialize, Default)]
77pub struct RangeBoundsTs {
78 pub gt: Option<Timestamp>,
80 pub gte: Option<Timestamp>,
82 pub lt: Option<Timestamp>,
84 pub lte: Option<Timestamp>,
86}
87
88#[derive(Copy, Clone, Debug, Serialize)]
91#[serde(untagged)]
92pub enum RangeQueryTs {
93 Exact(Timestamp),
95 Bounds(RangeBoundsTs),
97}
98
99impl RangeQueryTs {
100 pub fn eq(value: Timestamp) -> Self {
102 Self::Exact(value)
103 }
104
105 pub fn gt(value: Timestamp) -> Self {
107 Self::Bounds(RangeBoundsTs { gt: Some(value), ..Default::default() })
108 }
109
110 pub fn gte(value: Timestamp) -> Self {
112 Self::Bounds(RangeBoundsTs { gte: Some(value), ..Default::default() })
113 }
114
115 pub fn lt(value: Timestamp) -> Self {
117 Self::Bounds(RangeBoundsTs { lt: Some(value), ..Default::default() })
118 }
119
120 pub fn lte(value: Timestamp) -> Self {
122 Self::Bounds(RangeBoundsTs { lte: Some(value), ..Default::default() })
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 fn urldecode(input: String) -> String {
131 input.replace("%5B", "[").replace("%5D", "]")
132 }
133
134 #[derive(Clone, Debug, Default, serde::Serialize)]
136 struct TestListCustomer {
137 #[serde(skip_serializing_if = "Option::is_none")]
138 pub created: Option<RangeQueryTs>,
139 #[serde(skip_serializing_if = "Option::is_none")]
140 pub ending_before: Option<String>,
141 #[serde(skip_serializing_if = "Option::is_none")]
142 pub limit: Option<i64>,
143 #[serde(skip_serializing_if = "Option::is_none")]
144 pub starting_after: Option<String>,
145 }
146
147 impl TestListCustomer {
148 fn new() -> Self {
149 Self::default()
150 }
151 }
152
153 #[test]
154 fn serialize_range_query() {
155 let query = RangeQueryTs::Bounds(RangeBoundsTs {
156 gt: None,
157 gte: Some(1501598702),
158 lt: Some(1504233902),
159 lte: None,
160 });
161 assert_eq!(urldecode(serde_qs::to_string(&query).unwrap()), "gte=1501598702<=1504233902");
162
163 let mut params = TestListCustomer::new();
164 params.created = Some(RangeQueryTs::eq(1501598702));
165 params.limit = Some(3);
166 assert_eq!(urldecode(serde_qs::to_string(¶ms).unwrap()), "created=1501598702&limit=3");
167
168 let mut params = TestListCustomer::new();
169 params.created = Some(RangeQueryTs::gte(1501598702));
170 params.limit = Some(3);
171 assert_eq!(
172 urldecode(serde_qs::to_string(¶ms).unwrap()),
173 "created[gte]=1501598702&limit=3"
174 );
175
176 let mut params = TestListCustomer::new();
177 params.created = Some(query);
178 params.limit = Some(3);
179 let encoded = urldecode(serde_qs::to_string(¶ms).unwrap());
180 assert_eq!(encoded, "created[gte]=1501598702&created[lt]=1504233902&limit=3");
181 }
182}