twitter_stream_message/message/
warning.rs1use 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}