twitter_stream_message/message/
warning.rs

1use std::borrow::Cow;
2use std::fmt;
3
4use serde::de::{
5    Deserialize,
6    Deserializer,
7    Error,
8    IgnoredAny,
9    MapAccess,
10    Visitor,
11};
12
13use user::UserId;
14
15#[derive(Clone, Debug, Eq, PartialEq, Hash)]
16pub struct Warning<'a> {
17    pub message: Cow<'a, str>,
18    pub code: WarningCode<'a>,
19}
20
21#[derive(Clone, Debug, Eq, PartialEq, Hash)]
22pub enum WarningCode<'a> {
23    FallingBehind(u64),
24    FollowsOverLimit(UserId),
25    Custom(Cow<'a, str>),
26}
27
28impl<'de: 'a, 'a> Deserialize<'de> for Warning<'a> {
29    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
30        d.deserialize_map(WarningVisitor)
31    }
32}
33
34struct WarningVisitor;
35
36impl<'a> Visitor<'a> for WarningVisitor {
37    type Value = Warning<'a>;
38
39    fn visit_map<A: MapAccess<'a>>(self, mut a: A)
40        -> Result<Warning<'a>, A::Error>
41    {
42        use util::CowStr;
43
44        string_enums! {
45            pub enum Code<'a> {
46                FallingBehind("FALLING_BEHIND"),
47                FollowsOverLimit("FOLLOWS_OVER_LIMIT");
48                Custom(_),
49            }
50        }
51
52        let mut code = None;
53        let mut message: Option<CowStr> = None;
54        let mut percent_full: Option<u64> = None;
55        let mut user_id: Option<UserId> = None;
56
57        while let Some(k) = a.next_key::<CowStr>()? {
58            match &*k {
59                "code" => code = Some(a.next_value::<Code>()?),
60                "message" => message = Some(a.next_value()?),
61                "percent_full" => percent_full = Some(a.next_value()?),
62                "user_id" => user_id = Some(a.next_value()?),
63                _ => { a.next_value::<IgnoredAny>()?; },
64            }
65
66            macro_rules! end {
67                () => {{
68                    while a.next_entry::<IgnoredAny,IgnoredAny>()?.is_some() {}
69                }};
70            }
71
72            match (code.as_ref(), message.as_ref(), percent_full, user_id) {
73                (Some(&Code::FallingBehind), Some(_), Some(percent_full), _) =>
74                {
75                    end!();
76                    return Ok(Warning {
77                        message: message.unwrap().0,
78                        code: WarningCode::FallingBehind(percent_full),
79                    });
80                },
81                (Some(&Code::FollowsOverLimit), Some(_), _, Some(user_id)) => {
82                    end!();
83                    return Ok(Warning {
84                        message: message.unwrap().0,
85                        code: WarningCode::FollowsOverLimit(user_id),
86                    });
87                },
88                (Some(&Code::Custom(_)), Some(_), _, _) => {
89                    end!();
90                    if let Some(Code::Custom(code)) = code {
91                        return Ok(Warning {
92                            message: message.unwrap().0,
93                            code: WarningCode::Custom(code),
94                        });
95                    } else {
96                        unreachable!();
97                    }
98                },
99                _ => (),
100            }
101        }
102
103        if code.is_none() {
104            Err(A::Error::missing_field("code"))
105        } else if message.is_none() {
106            Err(A::Error::missing_field("message"))
107        } else if code == Some(Code::FallingBehind) {
108            Err(A::Error::missing_field("percent_full"))
109        } else {
110            Err(A::Error::missing_field("user_id"))
111        }
112    }
113
114    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
115        write!(f, "a map")
116    }
117}