zulip_api/filter/
operand.rs1use std::borrow::Cow;
2
3use serde::{Deserialize, Serialize};
4
5use crate::error::Error;
6use crate::result::Result;
7
8#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
10#[serde(untagged)]
11pub enum Operand {
12 Integer(u64),
13 IntegerList(Vec<u64>),
14 Text(String),
15 TextList(Vec<String>),
16}
17
18impl Operand {
19 pub const fn new() -> Self {
21 Self::Integer(0)
22 }
23
24 pub(crate) const fn variant_name(&self) -> &'static str {
26 match self {
27 Self::Integer(_) => "Operand::Integer",
28 Self::IntegerList(_) => "Operand::IntegerList",
29 Self::Text(_) => "Operand::Text",
30 Self::TextList(_) => "Operand::TextList",
31 }
32 }
33
34 pub fn as_integer(&self) -> Result<u64> {
36 match self {
37 Self::Integer(v) => Ok(*v),
38 o => Err(Error::invalid_field(
39 "operand",
40 o.variant_name(),
41 self.variant_name(),
42 )),
43 }
44 }
45
46 pub fn integer_list<'c, C: Into<Cow<'c, [u64]>>>(val: C) -> Self {
48 Self::IntegerList(C::into(val).into())
49 }
50
51 pub fn as_integer_list(&self) -> Result<&[u64]> {
53 match self {
54 Self::IntegerList(v) => Ok(v.as_slice()),
55 o => Err(Error::invalid_field(
56 "operand",
57 o.variant_name(),
58 self.variant_name(),
59 )),
60 }
61 }
62
63 pub fn text<'c, C: Into<Cow<'c, str>>>(val: C) -> Self {
65 Self::Text(C::into(val).into())
66 }
67
68 pub fn as_text(&self) -> Result<&str> {
70 match self {
71 Self::Text(v) => Ok(v.as_str()),
72 o => Err(Error::invalid_field(
73 "operand",
74 o.variant_name(),
75 self.variant_name(),
76 )),
77 }
78 }
79
80 pub fn text_list<'c, C: Into<Cow<'c, [String]>>>(val: C) -> Self {
82 Self::TextList(C::into(val).into())
83 }
84
85 pub fn as_text_list(&self) -> Result<&[String]> {
87 match self {
88 Self::TextList(v) => Ok(v.as_slice()),
89 o => Err(Error::invalid_field(
90 "operand",
91 o.variant_name(),
92 self.variant_name(),
93 )),
94 }
95 }
96}
97
98impl Default for Operand {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104impl From<u64> for Operand {
105 fn from(val: u64) -> Self {
106 Self::Integer(val)
107 }
108}
109
110impl From<Vec<u64>> for Operand {
111 fn from(val: Vec<u64>) -> Self {
112 Self::IntegerList(val)
113 }
114}
115
116impl From<&[u64]> for Operand {
117 fn from(val: &[u64]) -> Self {
118 Self::IntegerList(val.into())
119 }
120}
121
122impl<const N: usize> From<&[u64; N]> for Operand {
123 fn from(val: &[u64; N]) -> Self {
124 Self::IntegerList(val.into())
125 }
126}
127
128impl<const N: usize> From<[u64; N]> for Operand {
129 fn from(val: [u64; N]) -> Self {
130 Self::IntegerList(val.into_iter().collect())
131 }
132}
133
134impl From<&str> for Operand {
135 fn from(val: &str) -> Self {
136 Self::Text(val.into())
137 }
138}
139
140impl From<String> for Operand {
141 fn from(val: String) -> Self {
142 Self::Text(val)
143 }
144}
145
146impl From<Vec<String>> for Operand {
147 fn from(val: Vec<String>) -> Self {
148 Self::TextList(val)
149 }
150}
151
152impl From<&[String]> for Operand {
153 fn from(val: &[String]) -> Self {
154 Self::TextList(val.into())
155 }
156}
157
158impl From<&[&str]> for Operand {
159 fn from(val: &[&str]) -> Self {
160 Self::TextList(val.iter().map(|&s| String::from(s)).collect())
161 }
162}
163
164impl<const N: usize> From<&[String; N]> for Operand {
165 fn from(val: &[String; N]) -> Self {
166 Self::TextList(val.into())
167 }
168}
169
170impl<const N: usize> From<&[&str; N]> for Operand {
171 fn from(val: &[&str; N]) -> Self {
172 Self::TextList(val.iter().map(|&s| String::from(s)).collect())
173 }
174}
175
176impl<const N: usize> From<[String; N]> for Operand {
177 fn from(val: [String; N]) -> Self {
178 Self::TextList(val.into())
179 }
180}
181
182impl<const N: usize> From<[&str; N]> for Operand {
183 fn from(val: [&str; N]) -> Self {
184 Self::TextList(val.into_iter().map(String::from).collect())
185 }
186}
187
188impl std::fmt::Display for Operand {
189 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190 serde_json::to_string(self)
191 .map_err(|_| std::fmt::Error)
192 .and_then(|s| write!(f, "{s}"))
193 }
194}
195
196#[cfg(test)]
197mod tests {
198 use super::*;
199
200 #[test]
201 fn test_operand() {
202 (0..=u64::BITS)
203 .map(|r| ((1u128 << r) - 1) as u64)
204 .enumerate()
205 .for_each(|(i, int)| {
206 let list_len = i + 1;
207 let int_list = vec![int; list_len];
208 let text = format!("{int}");
209 let text_list = vec![text.clone(); list_len];
210
211 let op_int = Operand::Integer(int);
212 let op_int_list = Operand::IntegerList(int_list.clone());
213 let op_text = Operand::Text(text.clone());
214 let op_text_list = Operand::TextList(text_list.clone());
215
216 assert_eq!(op_int.as_integer(), Ok(int));
217 assert_eq!(op_int_list.as_integer_list(), Ok(int_list.as_slice()));
218 assert_eq!(op_text.as_text(), Ok(text.as_str()));
219 assert_eq!(op_text_list.as_text_list(), Ok(text_list.as_slice()));
220
221 [op_int, op_int_list, op_text, op_text_list]
222 .into_iter()
223 .for_each(|op| {
224 let op_json = format!("{op}");
225
226 assert_eq!(serde_json::to_string(&op).unwrap(), op_json);
227 assert_eq!(serde_json::from_str::<Operand>(&op_json).unwrap(), op);
228 });
229 });
230 }
231}