1#[derive(Deserialize, Debug, Clone)]
8pub struct CanIUse
9{
10 agents: HashMap<AgentName, AgentDetail>,
11 statuses: HashMap<Status, String>,
12 #[serde(rename = "cats")] child_categories: HashMap<ParentCategory, Vec<Category>>,
13 #[serde(deserialize_with = "CanIUse::updated_deserialize")] updated: DateTime<Utc>,
14 #[serde(rename = "data")] features: HashMap<FeatureName, FeatureDetail>,
15}
16
17impl Default for CanIUse
18{
19 #[inline(always)]
21 fn default() -> Self
22 {
23 match include_str!("data-2.0.json").parse()
24 {
25 Err(error) => panic!("Invalid data embedded: {}", error),
26 Ok(canIUse) => canIUse
27 }
28 }
29}
30
31impl FromStr for CanIUse
32{
33 type Err = ::serde_json::error::Error;
34
35 #[inline(always)]
37 fn from_str(can_i_use_database_json: &str) -> Result<Self, Self::Err>
38 {
39 ::serde_json::from_str(can_i_use_database_json)
40 }
41}
42
43impl CanIUse
44{
45 #[inline(always)]
47 pub fn from_path<P: AsRef<Path>>(can_i_use_database_file_path: P) -> Result<Self, Box<::std::error::Error>>
48 {
49 Self::from_reader(File::open(can_i_use_database_file_path)?)
50 }
51
52 #[inline(always)]
54 pub fn from_reader<R: Read>(reader_of_stream_of_can_i_use_json_bytes: R) -> Result<Self, Box<::std::error::Error>>
55 {
56 Ok(serde_json::from_reader(reader_of_stream_of_can_i_use_json_bytes)?)
57 }
58
59 #[inline(always)]
61 pub fn from_slice(raw_can_i_use_json_bytes: &[u8]) -> Result<Self, ::serde_json::error::Error>
62 {
63 Ok(serde_json::from_slice(raw_can_i_use_json_bytes)?)
64 }
65
66 #[inline(always)]
68 pub fn last_updated(&self) -> DateTime<Utc>
69 {
70 self.updated
71 }
72
73 #[inline(always)]
75 pub fn known_agent_names(&self) -> AgentNameIterator
76 {
77 AgentNameIterator(self.agents.keys())
78 }
79
80 #[inline(always)]
82 pub fn known_statuses(&self) -> StatusIterator
83 {
84 StatusIterator(self.statuses.keys())
85 }
86
87 #[inline(always)]
89 pub fn known_parent_categories(&self) -> ParentCategoryIterator
90 {
91 ParentCategoryIterator(self.child_categories.keys())
92 }
93
94 #[inline(always)]
96 pub fn known_feature_names(&self) -> FeatureNameIterator
97 {
98 FeatureNameIterator(self.features.keys())
99 }
100
101 #[inline(always)]
102 fn agent<'a>(&'a self, agent_name: &'a AgentName) -> Option<Agent<'a>>
103 {
104 self.agents.get(agent_name).map(|agent_detail| Agent
105 {
106 agent_name,
107 agent_detail,
108 })
109 }
110
111 #[inline(always)]
112 fn feature<'a>(&'a self, feature_name: &'a FeatureName) -> Option<Feature<'a>>
113 {
114 self.features.get(feature_name).map(|feature_detail| Feature
115 {
116 feature_name,
117 feature_detail,
118 })
119 }
120
121 #[inline(always)]
122 fn status_description<'a>(&'a self, statusName: &Status) -> Option<&'a str>
123 {
124 self.statuses.get(statusName).map(|value| value.as_str())
125 }
126
127 #[inline(always)]
128 fn child_categories<'a>(&'a self, parentCategory: &ParentCategory) -> Option<&'a [Category]>
129 {
130 self.child_categories.get(parentCategory).map(|value| &value[..])
131 }
132
133 #[inline(always)]
134 fn updated_deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
135 {
136 struct OurVisitor;
137
138 impl<'de> Visitor<'de> for OurVisitor
139 {
140 type Value = u64;
141
142 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result
143 {
144 formatter.write_str("a positive integer")
145 }
146
147 fn visit_u8<E: de::Error>(self, value: u8) -> Result<Self::Value, E>
148 {
149 Ok(value as Self::Value)
150 }
151
152 fn visit_u16<E: de::Error>(self, value: u16) -> Result<Self::Value, E>
153 {
154 Ok(value as Self::Value)
155 }
156
157 fn visit_u32<E: de::Error>(self, value: u32) -> Result<Self::Value, E>
158 {
159 Ok(value as Self::Value)
160 }
161
162 fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E>
163 {
164 Ok(value)
165 }
166
167 fn visit_i8<E: de::Error>(self, value: i8) -> Result<Self::Value, E>
168 {
169 if value >= 0
170 {
171 Ok(value as Self::Value)
172 }
173 else
174 {
175 Err(E::custom(format!("i8 should not be negative '{}'", value)))
176 }
177 }
178
179 fn visit_i16<E: de::Error>(self, value: i16) -> Result<Self::Value, E>
180 {
181 if value >= 0
182 {
183 Ok(value as Self::Value)
184 }
185 else
186 {
187 Err(E::custom(format!("i16 should not be negative '{}'", value)))
188 }
189 }
190
191 fn visit_i32<E: de::Error>(self, value: i32) -> Result<Self::Value, E>
192 {
193 if value >= 0
194 {
195 Ok(value as Self::Value)
196 }
197 else
198 {
199 Err(E::custom(format!("i32 should not be negative '{}'", value)))
200 }
201 }
202
203 fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E>
204 {
205 if value >= 0
206 {
207 Ok(value as Self::Value)
208 }
209 else
210 {
211 Err(E::custom(format!("i64 should not be negative '{}'", value)))
212 }
213 }
214 }
215
216 let time = deserializer.deserialize_u64(OurVisitor)?;
217 let utc = Utc;
219 Ok(utc.timestamp(time as i64, 0))
220 }
221}
222
223lazy_static!
224{
225 #[derive(Debug)] pub static ref EmbeddedCanIUseDatabase: CanIUse = CanIUse::default();
227}