phonenumber_fixed/metadata/
database.rs1use std::path::Path;
16use std::fs::File;
17use std::io::{Cursor, BufReader};
18use std::borrow::Borrow;
19use std::hash::Hash;
20use std::sync::{Arc, Mutex};
21
22use bincode::Options;
23use fnv::FnvHashMap;
24use regex_cache::{RegexCache, CachedRegex, CachedRegexBuilder};
25use bincode;
26
27use crate::error;
28use crate::metadata::loader;
29
30const DATABASE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/database.bin"));
31
32lazy_static! {
33 pub static ref DEFAULT: Database =
35 Database::from(bincode::options()
36 .with_varint_encoding().deserialize(DATABASE).unwrap()).unwrap();
37}
38
39#[derive(Clone, Debug)]
41pub struct Database {
42 cache: Arc<Mutex<RegexCache>>,
43 by_id: FnvHashMap<String, Arc<super::Metadata>>,
44 by_code: FnvHashMap<u16, Vec<Arc<super::Metadata>>>,
45 regions: FnvHashMap<u16, Vec<String>>,
46}
47
48impl Database {
49 pub fn load<P: AsRef<Path>>(path: P) -> Result<Self, error::LoadMetadata> {
51 Database::from(loader::load(BufReader::new(File::open(path)?))?)
52 }
53
54 pub fn parse<S: AsRef<str>>(content: S) -> Result<Self, error::LoadMetadata> {
56 Database::from(loader::load(Cursor::new(content.as_ref()))?)
57 }
58
59 pub fn from(meta: Vec<loader::Metadata>) -> Result<Self, error::LoadMetadata> {
61 fn tranpose<T, E>(value: Option<Result<T, E>>) -> Result<Option<T>, E> {
62 match value {
63 None =>
64 Ok(None),
65
66 Some(Ok(value)) =>
67 Ok(Some(value)),
68
69 Some(Err(err)) =>
70 Err(err),
71 }
72 }
73
74 let cache = Arc::new(Mutex::new(RegexCache::new(100)));
75 let regex = |value: String| -> Result<CachedRegex, error::LoadMetadata> {
76 Ok(CachedRegexBuilder::new(cache.clone(), &value)
77 .ignore_whitespace(true).build()?)
78 };
79
80 let descriptor = |desc: loader::Descriptor| -> Result<super::Descriptor, error::LoadMetadata> {
81 desc.national_number.as_ref().unwrap();
82 desc.national_number.as_ref().unwrap();
83
84 Ok(super::Descriptor {
85 national_number: desc.national_number.ok_or_else(||
86 error::LoadMetadata::from(error::Metadata::MissingValue {
87 phase: "descriptor".into(),
88 name: "national_number".into(),
89 })).and_then(®ex)?,
90
91 possible_length: desc.possible_length,
92 possible_local_length: desc.possible_local_length,
93 example: desc.example,
94 })
95 };
96
97 let format = |format: loader::Format| -> Result<super::Format, error::LoadMetadata> {
98 Ok(super::Format {
99 pattern: format.pattern.ok_or_else(||
100 error::LoadMetadata::from(error::Metadata::MissingValue {
101 phase: "format".into(),
102 name: "pattern".into(),
103 })).and_then(®ex)?,
104
105 format: format.format.ok_or_else(||
106 error::LoadMetadata::from(error::Metadata::MissingValue {
107 phase: "format".into(),
108 name: "format".into()
109 }))?,
110
111 leading_digits: format.leading_digits.into_iter()
112 .map(®ex).collect::<Result<_, _>>()?,
113
114 national_prefix: format.national_prefix_formatting_rule,
115 national_prefix_optional: format.national_prefix_optional_when_formatting,
116
117 domestic_carrier: format.domestic_carrier,
118 })
119 };
120
121 let metadata = |meta: loader::Metadata| -> Result<super::Metadata, error::LoadMetadata> {
122 Ok(super::Metadata {
123 descriptors: super::Descriptors {
124 general: descriptor(meta.general.ok_or_else(||
125 error::LoadMetadata::from(error::Metadata::MissingValue {
126 phase: "metadata".into(),
127 name: "generalDesc".into(),
128 }))?)?,
129
130 fixed_line: tranpose(meta.fixed_line.map(&descriptor))?,
131 mobile: tranpose(meta.mobile.map(&descriptor))?,
132 toll_free: tranpose(meta.toll_free.map(&descriptor))?,
133 premium_rate: tranpose(meta.premium_rate.map(&descriptor))?,
134 shared_cost: tranpose(meta.shared_cost.map(&descriptor))?,
135 personal_number: tranpose(meta.personal_number.map(&descriptor))?,
136 voip: tranpose(meta.voip.map(&descriptor))?,
137 pager: tranpose(meta.pager.map(&descriptor))?,
138 uan: tranpose(meta.uan.map(&descriptor))?,
139 emergency: tranpose(meta.emergency.map(&descriptor))?,
140 voicemail: tranpose(meta.voicemail.map(&descriptor))?,
141 short_code: tranpose(meta.short_code.map(&descriptor))?,
142 standard_rate: tranpose(meta.standard_rate.map(&descriptor))?,
143 carrier: tranpose(meta.carrier.map(&descriptor))?,
144 no_international: tranpose(meta.no_international.map(&descriptor))?,
145 },
146
147 id: meta.id.ok_or_else(||
148 error::LoadMetadata::from(error::Metadata::MissingValue {
149 phase: "metadata".into(),
150 name: "id".into()
151 }))?,
152
153 country_code: meta.country_code.ok_or_else(||
154 error::LoadMetadata::from(error::Metadata::MissingValue {
155 phase: "metadata".into(),
156 name: "countryCode".into(),
157 }))?,
158
159 international_prefix: tranpose(meta.international_prefix.map(®ex))?,
160 preferred_international_prefix: meta.preferred_international_prefix,
161 national_prefix: meta.national_prefix,
162 preferred_extension_prefix: meta.preferred_extension_prefix,
163 national_prefix_for_parsing: tranpose(meta.national_prefix_for_parsing.map(®ex))?,
164 national_prefix_transform_rule: meta.national_prefix_transform_rule,
165
166 formats: meta.formats.into_iter().map(&format).collect::<Result<_, _>>()?,
167 international_formats: meta.international_formats.into_iter().map(&format).collect::<Result<_, _>>()?,
168
169 main_country_for_code: meta.main_country_for_code,
170 leading_digits: tranpose(meta.leading_digits.map(®ex))?,
171 mobile_number_portable: meta.mobile_number_portable,
172 })
173 };
174
175 let mut by_id = FnvHashMap::default();
176 let mut by_code = FnvHashMap::default();
177 let mut regions = FnvHashMap::default();
178
179 for meta in meta {
180 let meta = Arc::new(metadata(meta)?);
181
182 by_id.insert(meta.id.clone(), meta.clone());
183
184 let by_code = by_code.entry(meta.country_code)
185 .or_insert_with(Vec::new);
186
187 let regions = regions.entry(meta.country_code)
188 .or_insert_with(Vec::new);
189
190 if meta.main_country_for_code {
191 by_code.insert(0, meta.clone());
192 regions.insert(0, meta.id.clone())
193 }
194 else {
195 by_code.push(meta.clone());
196 regions.push(meta.id.clone());
197 }
198 }
199
200 Ok(Database {
201 cache: cache.clone(),
202 by_id: by_id,
203 by_code: by_code,
204 regions: regions,
205 })
206 }
207
208 pub fn cache(&self) -> Arc<Mutex<RegexCache>> {
210 self.cache.clone()
211 }
212
213 pub fn by_id<Q>(&self, key: &Q) -> Option<&super::Metadata>
215 where Q: ?Sized + Hash + Eq,
216 String: Borrow<Q>,
217 {
218 self.by_id.get(key).map(AsRef::as_ref)
219 }
220
221 pub fn by_code<Q>(&self, key: &Q) -> Option<Vec<&super::Metadata>>
223 where Q: ?Sized + Hash + Eq,
224 u16: Borrow<Q>,
225 {
226 self.by_code.get(key).map(|m| m.iter().map(AsRef::as_ref).collect())
227 }
228
229 pub fn region<Q>(&self, code: &Q) -> Option<Vec<&str>>
231 where Q: ?Sized + Hash + Eq,
232 u16: Borrow<Q>
233 {
234 self.regions.get(code).map(|m| m.iter().map(AsRef::as_ref).collect())
235 }
236}