ferric_fred/
region_type.rs1use std::fmt;
2
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
16#[non_exhaustive]
17pub enum RegionType {
18 State,
20 County,
22 Msa,
24 Country,
26 Bea,
28 Other(String),
31}
32
33impl RegionType {
34 fn from_token(token: &str) -> Self {
36 match token {
37 "state" => Self::State,
38 "county" => Self::County,
39 "msa" => Self::Msa,
40 "country" => Self::Country,
41 "bea" => Self::Bea,
42 other => Self::Other(other.to_owned()),
43 }
44 }
45
46 pub fn query_code(&self) -> &str {
50 match self {
51 Self::State => "state",
52 Self::County => "county",
53 Self::Msa => "msa",
54 Self::Country => "country",
55 Self::Bea => "bea",
56 Self::Other(token) => token,
57 }
58 }
59}
60
61impl fmt::Display for RegionType {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 f.write_str(self.query_code())
64 }
65}
66
67impl<'de> Deserialize<'de> for RegionType {
68 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
69 where
70 D: Deserializer<'de>,
71 {
72 let token = String::deserialize(deserializer)?;
73 Ok(Self::from_token(&token))
74 }
75}
76
77impl Serialize for RegionType {
78 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
80 where
81 S: Serializer,
82 {
83 serializer.serialize_str(self.query_code())
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn known_token_maps_to_variant() {
93 assert_eq!(
94 serde_json::from_str::<RegionType>("\"state\"").unwrap(),
95 RegionType::State
96 );
97 }
98
99 #[test]
100 fn unknown_token_is_preserved_verbatim() {
101 assert_eq!(
102 serde_json::from_str::<RegionType>("\"frb\"").unwrap(),
103 RegionType::Other("frb".to_owned())
104 );
105 }
106
107 #[test]
108 fn query_codes_match_fred() {
109 assert_eq!(RegionType::State.query_code(), "state");
110 assert_eq!(RegionType::Msa.query_code(), "msa");
111 assert_eq!(RegionType::Other("frb".to_owned()).query_code(), "frb");
112 }
113
114 #[test]
115 fn serializes_to_its_token_and_round_trips() {
116 assert_eq!(
117 serde_json::to_string(&RegionType::Country).unwrap(),
118 "\"country\""
119 );
120 let other = RegionType::Other("censusregion".to_owned());
121 let json = serde_json::to_string(&other).unwrap();
122 assert_eq!(serde_json::from_str::<RegionType>(&json).unwrap(), other);
123 }
124}