zoom_api/
utils.rs

1use std::{fmt, str::FromStr};
2
3use parse_link_header::LinkMap;
4use serde::de::{self, Visitor};
5
6pub struct NextLink(pub String);
7
8pub fn next_link(l: &LinkMap) -> Option<NextLink> {
9    l.get(&Some("next".to_string()))
10        .map(|link| link.raw_uri.to_string())
11        .map(NextLink)
12}
13
14pub mod date_format {
15    use chrono::NaiveDate;
16    use serde::{self, Deserialize, Deserializer};
17
18    // The signature of a deserialize_with function must follow the pattern:
19    //
20    //    fn deserialize<'de, D>(D) -> Result<T, D::Error>
21    //    where
22    //        D: Deserializer<'de>
23    //
24    // although it may also be generic over the output types T.
25    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<NaiveDate>, D::Error>
26    where
27        D: Deserializer<'de>,
28    {
29        let s: Option<String> = Option::deserialize(deserializer)?;
30        if let Some(s) = s {
31            if s.is_empty() {
32                Ok(None)
33            } else {
34                // This is standard.
35                match serde_json::from_str::<NaiveDate>(&format!("\"{}\"", s)) {
36                    Ok(t) => Ok(Some(t)),
37                    Err(e) => Err(serde::de::Error::custom(format!(
38                        "deserializing {} as NaiveDate failed: {}",
39                        s, e
40                    ))),
41                }
42            }
43        } else {
44            Ok(None)
45        }
46    }
47}
48
49pub mod date_time_format {
50    use chrono::{DateTime, TimeZone, Utc};
51    use serde::{self, Deserialize, Deserializer};
52
53    // The date format Ramp returns looks like this: "2021-04-24T01:03:21"
54    const FORMAT: &str = "%Y-%m-%dT%H:%M:%S%:z";
55
56    // The signature of a deserialize_with function must follow the pattern:
57    //
58    //    fn deserialize<'de, D>(D) -> Result<T, D::Error>
59    //    where
60    //        D: Deserializer<'de>
61    //
62    // although it may also be generic over the output types T.
63    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<DateTime<Utc>>, D::Error>
64    where
65        D: Deserializer<'de>,
66    {
67        let s: Option<String> = Option::deserialize(deserializer)?;
68        if let Some(mut s) = s {
69            // This is standard.
70            match serde_json::from_str::<DateTime<Utc>>(&format!("\"{}\"", s)) {
71                Ok(t) => Ok(Some(t)),
72                Err(_) => {
73                    // This is google calendar.
74                    match Utc.datetime_from_str(&s, "%Y-%m-%dT%H:%M:%S%.3fZ") {
75                        Ok(t) => Ok(Some(t)),
76                        Err(_) => match Utc.datetime_from_str(&s, FORMAT) {
77                            Ok(t) => Ok(Some(t)),
78                            Err(_) => match Utc.datetime_from_str(&s, "%+") {
79                                Ok(t) => Ok(Some(t)),
80                                Err(_) => match chrono::NaiveDate::parse_from_str(&s, "%Y-%m-%d") {
81                                    Ok(d) => Ok(Some(DateTime::<Utc>::from_utc(
82                                        chrono::NaiveDateTime::new(
83                                            d,
84                                            chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
85                                        ),
86                                        Utc,
87                                    ))),
88                                    Err(_) => {
89                                        s = format!("{}+00:00", s);
90                                        match Utc.datetime_from_str(&s, FORMAT) {
91                                            Ok(r) => Ok(Some(r)),
92                                            Err(_) => match Utc.datetime_from_str(&s, "%+") {
93                                                Ok(d) => Ok(Some(d)),
94                                                Err(e) => Err(serde::de::Error::custom(format!(
95                                                    "deserializing {} as DateTime<Utc> failed: {}",
96                                                    s, e
97                                                ))),
98                                            },
99                                        }
100                                    }
101                                },
102                            },
103                        },
104                    }
105                }
106            }
107        } else {
108            Ok(None)
109        }
110    }
111}
112
113pub mod deserialize_empty_url {
114    use serde::{self, Deserialize, Deserializer};
115
116    // The signature of a deserialize_with function must follow the pattern:
117    //
118    //    fn deserialize<'de, D>(D) -> Result<T, D::Error>
119    //    where
120    //        D: Deserializer<'de>
121    //
122    // although it may also be generic over the output types T.
123    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<url::Url>, D::Error>
124    where
125        D: Deserializer<'de>,
126    {
127        if let Ok(s) = String::deserialize(deserializer) {
128            if s.is_empty() {
129                return Ok(None);
130            }
131
132            match url::Url::parse(&s) {
133                Ok(u) => return Ok(Some(u)),
134                Err(e) => {
135                    return Err(serde::de::Error::custom(format!(
136                        "error url parsing {}: {}",
137                        s, e
138                    )))
139                }
140            }
141        }
142
143        Ok(None)
144    }
145}
146
147pub mod deserialize_null_string {
148    use serde::{self, Deserialize, Deserializer};
149
150    // The signature of a deserialize_with function must follow the pattern:
151    //
152    //    fn deserialize<'de, D>(D) -> Result<T, D::Error>
153    //    where
154    //        D: Deserializer<'de>
155    //
156    // although it may also be generic over the output types T.
157    pub fn deserialize<'de, D>(deserializer: D) -> Result<String, D::Error>
158    where
159        D: Deserializer<'de>,
160    {
161        let s = String::deserialize(deserializer).unwrap_or_default();
162
163        Ok(s)
164    }
165}
166
167struct BoolVisitor;
168
169impl Visitor<'_> for BoolVisitor {
170    type Value = bool;
171
172    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
173        formatter.write_str("a boolean")
174    }
175
176    fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
177    where
178        E: de::Error,
179    {
180        Ok(value)
181    }
182
183    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
184    where
185        E: de::Error,
186    {
187        match FromStr::from_str(value) {
188            Ok(s) => Ok(s),
189            Err(_) => Err(de::Error::invalid_value(
190                de::Unexpected::Str(value),
191                &"bool",
192            )),
193        }
194    }
195
196    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
197    where
198        E: de::Error,
199    {
200        match FromStr::from_str(&value) {
201            Ok(s) => Ok(s),
202            Err(_) => Err(de::Error::invalid_value(
203                de::Unexpected::Str(&value),
204                &"bool",
205            )),
206        }
207    }
208}
209
210pub mod deserialize_null_boolean {
211    use serde::{self, Deserializer};
212
213    // The signature of a deserialize_with function must follow the pattern:
214    //
215    //    fn deserialize<'de, D>(D) -> Result<T, D::Error>
216    //    where
217    //        D: Deserializer<'de>
218    //
219    // although it may also be generic over the output types T.
220    pub fn deserialize<'de, D>(deserializer: D) -> Result<bool, D::Error>
221    where
222        D: Deserializer<'de>,
223    {
224        let s = deserializer
225            .deserialize_bool(crate::utils::BoolVisitor)
226            .unwrap_or_default();
227
228        Ok(s)
229    }
230}
231
232struct I32Visitor;
233
234impl Visitor<'_> for I32Visitor {
235    type Value = i32;
236
237    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
238        formatter.write_str("an integer between -2^31 and 2^31")
239    }
240
241    fn visit_i8<E>(self, value: i8) -> Result<Self::Value, E>
242    where
243        E: de::Error,
244    {
245        Ok(value as i32)
246    }
247
248    fn visit_i16<E>(self, value: i16) -> Result<Self::Value, E>
249    where
250        E: de::Error,
251    {
252        Ok(value as i32)
253    }
254
255    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
256    where
257        E: de::Error,
258    {
259        Ok(value)
260    }
261
262    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
263    where
264        E: de::Error,
265    {
266        use std::i32;
267        if value >= i64::from(i32::MIN) && value <= i64::from(i32::MAX) {
268            Ok(value as i32)
269        } else {
270            Err(E::custom(format!("i32 out of range: {}", value)))
271        }
272    }
273
274    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
275    where
276        E: de::Error,
277    {
278        Ok(value as i32)
279    }
280}
281
282pub mod deserialize_null_i32 {
283    use serde::{self, Deserializer};
284
285    // The signature of a deserialize_with function must follow the pattern:
286    //
287    //    fn deserialize<'de, D>(D) -> Result<T, D::Error>
288    //    where
289    //        D: Deserializer<'de>
290    //
291    // although it may also be generic over the output types T.
292    pub fn deserialize<'de, D>(deserializer: D) -> Result<i32, D::Error>
293    where
294        D: Deserializer<'de>,
295    {
296        let s = deserializer
297            .deserialize_i32(crate::utils::I32Visitor)
298            .unwrap_or_default();
299
300        Ok(s)
301    }
302}
303
304struct I64Visitor;
305
306impl Visitor<'_> for I64Visitor {
307    type Value = i64;
308
309    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
310        formatter.write_str("an integer")
311    }
312
313    fn visit_i8<E>(self, value: i8) -> Result<Self::Value, E>
314    where
315        E: de::Error,
316    {
317        Ok(value as i64)
318    }
319
320    fn visit_i16<E>(self, value: i16) -> Result<Self::Value, E>
321    where
322        E: de::Error,
323    {
324        Ok(value as i64)
325    }
326
327    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
328    where
329        E: de::Error,
330    {
331        Ok(value as i64)
332    }
333
334    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
335    where
336        E: de::Error,
337    {
338        Ok(value)
339    }
340
341    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
342    where
343        E: de::Error,
344    {
345        Ok(value as i64)
346    }
347}
348
349pub mod deserialize_null_i64 {
350    use serde::{self, Deserializer};
351
352    // The signature of a deserialize_with function must follow the pattern:
353    //
354    //    fn deserialize<'de, D>(D) -> Result<T, D::Error>
355    //    where
356    //        D: Deserializer<'de>
357    //
358    // although it may also be generic over the output types T.
359    pub fn deserialize<'de, D>(deserializer: D) -> Result<i64, D::Error>
360    where
361        D: Deserializer<'de>,
362    {
363        let s = deserializer
364            .deserialize_i64(crate::utils::I64Visitor)
365            .unwrap_or_default();
366
367        Ok(s)
368    }
369}
370
371struct F32Visitor;
372
373impl Visitor<'_> for F32Visitor {
374    type Value = f32;
375
376    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
377        formatter.write_str("a float between -2^31 and 2^31")
378    }
379
380    fn visit_i8<E>(self, value: i8) -> Result<Self::Value, E>
381    where
382        E: de::Error,
383    {
384        Ok(value as f32)
385    }
386
387    fn visit_i16<E>(self, value: i16) -> Result<Self::Value, E>
388    where
389        E: de::Error,
390    {
391        Ok(value as f32)
392    }
393
394    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
395    where
396        E: de::Error,
397    {
398        Ok(value as f32)
399    }
400
401    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
402    where
403        E: de::Error,
404    {
405        use std::i32;
406        if value >= i64::from(i32::MIN) && value <= i64::from(i32::MAX) {
407            Ok(value as f32)
408        } else {
409            Err(E::custom(format!("f32 out of range: {}", value)))
410        }
411    }
412
413    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
414    where
415        E: de::Error,
416    {
417        Ok(value as f32)
418    }
419
420    fn visit_f32<E>(self, value: f32) -> Result<Self::Value, E>
421    where
422        E: de::Error,
423    {
424        Ok(value)
425    }
426
427    fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
428    where
429        E: de::Error,
430    {
431        use std::f32;
432        if value >= f64::from(f32::MIN) && value <= f64::from(f32::MAX) {
433            Ok(value as f32)
434        } else {
435            Err(E::custom(format!("f32 out of range: {}", value)))
436        }
437    }
438}
439
440pub mod deserialize_null_f32 {
441    use serde::{self, Deserializer};
442
443    // The signature of a deserialize_with function must follow the pattern:
444    //
445    //    fn deserialize<'de, D>(D) -> Result<T, D::Error>
446    //    where
447    //        D: Deserializer<'de>
448    //
449    // although it may also be generic over the output types T.
450    pub fn deserialize<'de, D>(deserializer: D) -> Result<f32, D::Error>
451    where
452        D: Deserializer<'de>,
453    {
454        let s = deserializer
455            .deserialize_f32(crate::utils::F32Visitor)
456            .unwrap_or_default();
457
458        Ok(s)
459    }
460}
461
462struct F64Visitor;
463
464impl Visitor<'_> for F64Visitor {
465    type Value = f64;
466
467    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
468        formatter.write_str("a float")
469    }
470
471    fn visit_i8<E>(self, value: i8) -> Result<Self::Value, E>
472    where
473        E: de::Error,
474    {
475        Ok(value as f64)
476    }
477
478    fn visit_i16<E>(self, value: i16) -> Result<Self::Value, E>
479    where
480        E: de::Error,
481    {
482        Ok(value as f64)
483    }
484
485    fn visit_i32<E>(self, value: i32) -> Result<Self::Value, E>
486    where
487        E: de::Error,
488    {
489        Ok(value as f64)
490    }
491
492    fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
493    where
494        E: de::Error,
495    {
496        Ok(value as f64)
497    }
498
499    fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
500    where
501        E: de::Error,
502    {
503        Ok(value as f64)
504    }
505
506    fn visit_f32<E>(self, value: f32) -> Result<Self::Value, E>
507    where
508        E: de::Error,
509    {
510        Ok(value as f64)
511    }
512
513    fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
514    where
515        E: de::Error,
516    {
517        Ok(value)
518    }
519}
520
521pub mod deserialize_null_f64 {
522    use serde::{self, Deserializer};
523
524    // The signature of a deserialize_with function must follow the pattern:
525    //
526    //    fn deserialize<'de, D>(D) -> Result<T, D::Error>
527    //    where
528    //        D: Deserializer<'de>
529    //
530    // although it may also be generic over the output types T.
531    pub fn deserialize<'de, D>(deserializer: D) -> Result<f64, D::Error>
532    where
533        D: Deserializer<'de>,
534    {
535        let s = deserializer
536            .deserialize_f64(crate::utils::F64Visitor)
537            .unwrap_or_default();
538
539        Ok(s)
540    }
541}
542
543pub fn zero_i32(num: &i32) -> bool {
544    *num == 0
545}
546
547pub fn zero_i64(num: &i64) -> bool {
548    *num == 0
549}
550
551pub fn zero_f32(num: &f32) -> bool {
552    *num == 0.0
553}
554
555pub fn zero_f64(num: &f64) -> bool {
556    *num == 0.0
557}
558
559pub mod google_calendar_date_time_format {
560    use chrono::{DateTime, Utc};
561    use serde::{self, Serializer};
562
563    // Google Calendar doesn't accept actual normal date formats they want this.
564    const FORMAT: &str = "%Y-%m-%dT%H:%M:%S%.3fZ";
565
566    // The signature of a serialize_with function must follow the pattern:
567    //
568    //    fn serialize<S>(&T, S) -> Result<S::Ok, S::Error>
569    //    where
570    //        S: Serializer
571    //
572    // although it may also be generic over the input types T.
573    pub fn serialize<S>(date: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
574    where
575        S: Serializer,
576    {
577        if date.is_some() {
578            let s = format!("{}", date.unwrap().format(FORMAT));
579            return serializer.serialize_str(&s);
580        }
581
582        serializer.serialize_none()
583    }
584}
585
586struct VectorVisitor<T>(std::marker::PhantomData<fn() -> Vec<T>>);
587
588impl<'de, T> Visitor<'de> for VectorVisitor<T>
589where
590    T: de::Deserialize<'de>,
591{
592    type Value = Vec<T>;
593
594    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
595        formatter.write_str("a very special vector")
596    }
597
598    fn visit_seq<A: de::SeqAccess<'de>>(self, mut access: A) -> Result<Self::Value, A::Error> {
599        let mut things: Vec<T> = Default::default();
600
601        // While there are entries remaining in the input, add them
602        // into our vector.
603        while let Some(t) = access.next_element::<T>()? {
604            things.push(t);
605        }
606
607        Ok(things)
608    }
609}
610
611pub mod deserialize_null_vector {
612    use serde::{self, Deserialize, Deserializer};
613
614    use super::VectorVisitor;
615
616    // The signature of a deserialize_with function must follow the pattern:
617    //
618    //    fn deserialize<'de, D>(D) -> Result<T, D::Error>
619    //    where
620    //        D: Deserializer<'de>
621    //
622    // although it may also be generic over the output types T.
623    pub fn deserialize<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
624    where
625        T: Deserialize<'de>,
626        D: Deserializer<'de>,
627    {
628        if let Ok(r) = deserializer.deserialize_seq(VectorVisitor::<T>(std::marker::PhantomData)) {
629            return Ok(r);
630        }
631
632        Ok(Default::default())
633    }
634}
635
636#[cfg(test)]
637mod tests {
638    use super::next_link;
639
640    #[test]
641    fn test_hyperx_next_link_compat() {
642        let value = "<https://previous-link>; rel=\"prev\", <https://next-link>; rel=\"next\", <https://last-link>; rel=\"last\", <https://first-link>; rel=\"first\"";
643
644        let link = parse_link_header::parse(value).unwrap();
645        let next = next_link(&link).unwrap().0;
646
647        assert_eq!("https://next-link", next);
648    }
649}