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::Deserialize;
37 use miniserde::de::Visitor;
38 use miniserde::json::Value;
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 { Some(AlwaysTrue) } else { None }
64 }
65 }
66}
67
68pub type Timestamp = i64;
70
71#[derive(Copy, Clone, Debug, Serialize, Default)]
73pub struct RangeBoundsTs {
74 pub gt: Option<Timestamp>,
76 pub gte: Option<Timestamp>,
78 pub lt: Option<Timestamp>,
80 pub lte: Option<Timestamp>,
82}
83
84#[derive(Copy, Clone, Debug, Serialize)]
87#[serde(untagged)]
88pub enum RangeQueryTs {
89 Exact(Timestamp),
91 Bounds(RangeBoundsTs),
93}
94
95impl RangeQueryTs {
96 pub fn eq(value: Timestamp) -> Self {
98 Self::Exact(value)
99 }
100
101 pub fn gt(value: Timestamp) -> Self {
103 Self::Bounds(RangeBoundsTs { gt: Some(value), ..Default::default() })
104 }
105
106 pub fn gte(value: Timestamp) -> Self {
108 Self::Bounds(RangeBoundsTs { gte: Some(value), ..Default::default() })
109 }
110
111 pub fn lt(value: Timestamp) -> Self {
113 Self::Bounds(RangeBoundsTs { lt: Some(value), ..Default::default() })
114 }
115
116 pub fn lte(value: Timestamp) -> Self {
118 Self::Bounds(RangeBoundsTs { lte: Some(value), ..Default::default() })
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 fn urldecode(input: String) -> String {
127 input.replace("%5B", "[").replace("%5D", "]")
128 }
129
130 #[derive(Clone, Debug, Default, serde::Serialize)]
132 struct TestListCustomer {
133 #[serde(skip_serializing_if = "Option::is_none")]
134 pub created: Option<RangeQueryTs>,
135 #[serde(skip_serializing_if = "Option::is_none")]
136 pub ending_before: Option<String>,
137 #[serde(skip_serializing_if = "Option::is_none")]
138 pub limit: Option<i64>,
139 #[serde(skip_serializing_if = "Option::is_none")]
140 pub starting_after: Option<String>,
141 }
142
143 impl TestListCustomer {
144 fn new() -> Self {
145 Self::default()
146 }
147 }
148
149 #[test]
150 fn serialize_range_query() {
151 let query = RangeQueryTs::Bounds(RangeBoundsTs {
152 gt: None,
153 gte: Some(1501598702),
154 lt: Some(1504233902),
155 lte: None,
156 });
157 assert_eq!(urldecode(serde_qs::to_string(&query).unwrap()), "gte=1501598702<=1504233902");
158
159 let mut params = TestListCustomer::new();
160 params.created = Some(RangeQueryTs::eq(1501598702));
161 params.limit = Some(3);
162 assert_eq!(urldecode(serde_qs::to_string(¶ms).unwrap()), "created=1501598702&limit=3");
163
164 let mut params = TestListCustomer::new();
165 params.created = Some(RangeQueryTs::gte(1501598702));
166 params.limit = Some(3);
167 assert_eq!(
168 urldecode(serde_qs::to_string(¶ms).unwrap()),
169 "created[gte]=1501598702&limit=3"
170 );
171
172 let mut params = TestListCustomer::new();
173 params.created = Some(query);
174 params.limit = Some(3);
175 let encoded = urldecode(serde_qs::to_string(¶ms).unwrap());
176 assert_eq!(encoded, "created[gte]=1501598702&created[lt]=1504233902&limit=3");
177 }
178}