messagebird_async/sms/
originator.rs

1use super::*;
2
3use serde::de::{self, Deserialize, Deserializer, Unexpected, Visitor};
4
5use std::fmt;
6
7use regex::Regex;
8
9// TODO impl into() for Originator
10// requires manual Serialize/Deserialize impl
11#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
12pub struct TelephoneNumber(pub String);
13
14impl TelephoneNumber {
15    pub fn as_str(&self) -> &str {
16        self.0.as_str()
17    }
18}
19
20impl FromStr for TelephoneNumber {
21    type Err = MessageBirdError;
22    fn from_str(s: &str) -> Result<Self, Self::Err> {
23        lazy_static! {
24            static ref RE: Regex = Regex::new(r"^\+?[1-9][0-9]+$").unwrap();
25        }
26        if RE.is_match(s) {
27            Ok(TelephoneNumber(String::from(s)))
28        } else {
29            Err(MessageBirdError::FormatError {
30                chunk: String::from(s),
31            })
32        }
33    }
34}
35
36impl From<u64> for TelephoneNumber {
37    //type Err = MessageBirdError;
38    fn from(raw: u64) -> Self {
39        TelephoneNumber(raw.to_string())
40    }
41}
42
43// requires manual Serialize/Deserialize impl
44#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
45pub struct AlphaNumeric(pub String);
46
47impl AlphaNumeric {
48    pub fn as_str(&self) -> &str {
49        self.0.as_str()
50    }
51}
52
53impl FromStr for AlphaNumeric {
54    type Err = MessageBirdError;
55    fn from_str(s: &str) -> Result<Self, Self::Err> {
56        lazy_static! {
57            static ref RE: Regex = Regex::new(r"^[A-Za-z0-9_-]+$").unwrap();
58        }
59        if RE.is_match(s) {
60            Ok(AlphaNumeric(String::from(s)))
61        } else {
62            Err(MessageBirdError::FormatError {
63                chunk: String::from(s),
64            })
65        }
66    }
67}
68
69/// Origin of a message
70///
71/// Defines the source of a message, which can either be an arbitrary
72/// alphanumeric string or a telephone number
73#[derive(Debug, Clone, Serialize, Eq, PartialEq)]
74#[serde(rename_all = "camelCase")]
75#[serde(untagged)]
76pub enum Originator {
77    TelephoneNumber(TelephoneNumber),
78    Other(AlphaNumeric),
79}
80
81impl Originator {
82    pub fn as_str(&self) -> &str {
83        match self {
84            Originator::TelephoneNumber(ref telephonenumber) => telephonenumber.as_str(),
85            Originator::Other(ref alphanumeric) => alphanumeric.as_str(),
86        }
87    }
88}
89
90impl Default for Originator {
91    fn default() -> Self {
92        AlphaNumeric::from_str("inbox").unwrap().into()
93    }
94}
95
96impl FromStr for Originator {
97    type Err = MessageBirdError;
98    fn from_str(s: &str) -> Result<Self, Self::Err> {
99        TelephoneNumber::from_str(s)
100            .and_then(|telephonenumber| Ok(Originator::TelephoneNumber(telephonenumber)))
101            .or_else(|_e| {
102                AlphaNumeric::from_str(s)
103                    .and_then(|alphanumeric| Ok(Originator::Other(alphanumeric)))
104            })
105    }
106}
107
108impl From<u64> for Originator {
109    fn from(raw: u64) -> Self {
110        Originator::TelephoneNumber(raw.into())
111    }
112}
113
114// impl FromStr for PayloadType {
115//     type Err = MessageBirdError;
116//     fn from_str(s: &str) -> Result<Self, Self::Err> {
117//         serde_plain::from_str::<Self>(s).map_err(|_e| {
118//             MessageBirdError::ParseError
119//         })
120//     }
121// }
122
123impl ToString for Originator {
124    fn to_string(&self) -> String {
125        serde_plain::to_string(self).unwrap()
126    }
127}
128
129impl From<TelephoneNumber> for Originator {
130    fn from(telephonenumber: TelephoneNumber) -> Self {
131        Originator::TelephoneNumber(telephonenumber)
132    }
133}
134
135impl From<AlphaNumeric> for Originator {
136    fn from(alphanumeric: AlphaNumeric) -> Self {
137        Originator::Other(alphanumeric)
138    }
139}
140
141struct OriginatorVisitor;
142
143impl<'de> Visitor<'de> for OriginatorVisitor {
144    type Value = Originator;
145
146    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
147        formatter.write_str("a valid originator")
148    }
149
150    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
151    where
152        E: de::Error,
153    {
154        Originator::from_str(value)
155            .map_err(|_e| de::Error::invalid_value(Unexpected::Str(value), &self))
156    }
157}
158
159impl<'de> Deserialize<'de> for Originator {
160    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
161    where
162        D: Deserializer<'de>,
163    {
164        deserializer.deserialize_str(OriginatorVisitor)
165    }
166}
167
168#[cfg(test)]
169mod test {
170    use super::*;
171    static RAW: &str = r#"
172"123456789"
173"#;
174
175    deser_roundtrip!(originator_deser, Originator, RAW);
176    serde_roundtrip!(
177        originator_serde,
178        Originator,
179        TelephoneNumber::from_str("49123456789").unwrap().into()
180    );
181}