1#![deny(missing_docs,
4 missing_debug_implementations, missing_copy_implementations,
5 trivial_casts, trivial_numeric_casts,
6 unstable_features, unsafe_code,
7 unused_import_braces, unused_qualifications)]
8
9use roxmltree;
11
12#[derive(Debug, PartialEq)]
14pub struct USPSAddress {
15 pub firmname: Option<String>,
17 pub address1: Option<String>,
19 pub address2: Option<String>,
21 pub city: Option<String>,
23 pub state: Option<String>,
25 pub urbanization: Option<String>,
27 pub zip5: Option<String>,
29 pub zip4: Option<String>,
31
32 pub city_abbreviation: Option<String>,
34 pub delivery_point: Option<String>,
36 pub carrier_route: Option<String>,
38 pub footnotes: Option<String>,
40 pub dpv_cmra: Option<String>,
42 pub dpv_confirmation: Option<String>,
44 pub dpv_footnotes: Option<String>,
46 pub business: Option<String>,
48 pub central_delivery_point: Option<String>,
50 pub vacant: Option<String>,
52}
53
54impl Default for USPSAddress {
56 fn default() -> Self {
57 USPSAddress {
58 firmname: None,
59 address1: None,
60 address2: None,
61 city: None,
62 state: None,
63 urbanization: None,
64 zip5: None,
65 zip4: None,
66
67 city_abbreviation: None,
68 delivery_point: None,
69 carrier_route: None,
70 footnotes: None,
71 dpv_confirmation: None,
72 dpv_cmra: None,
73 dpv_footnotes: None,
74 business: None,
75 central_delivery_point: None,
76 vacant: None,
77 }
78 }
79}
80
81impl USPSAddress {
82 pub fn init(firmname: &str,
89 address_1: &str,
90 address_2: &str,
91 city: &str,
92 state: &str,
93 urbanization: &str,
94 zip5: &str,
95 zip4: &str) -> Self {
96
97 let firmname = match firmname { "" => None, _ => Some(firmname.into()) };
98 let address1 = match address_1 { "" => None, _ => Some(address_1.into()) };
99 let address2 = match address_2 { "" => None, _ => Some(address_2.into()) };
100 let city = match city { "" => None, _ => Some(city.into()) };
101 let state = match state { "" => None, _ => Some(state.into()) };
102 let urbanization = match urbanization { "" => None, _ => Some(urbanization.into()) };
103 let zip5 = match zip5 { "" => None, _ => Some(zip5.into()) };
104 let zip4 = match zip4 { "" => None, _ => Some(zip4.into()) };
105
106 USPSAddress {
107 firmname,
108 address1,
109 address2,
110 city,
111 state,
112 urbanization,
113 zip5,
114 zip4,
115 ..Default::default()
116 }
117 }
118
119 pub fn quick(address_1: &str,
126 address_2: &str,
127 city: &str,
128 state: &str,
129 zip5: &str) -> Self {
130
131 let address1 = match address_1 { "" => None, _ => Some(address_1.into()) };
132 let address2 = match address_2 { "" => None, _ => Some(address_2.into()) };
133 let city = match city { "" => None, _ => Some(city.into()) };
134 let state = match state { "" => None, _ => Some(state.into()) };
135 let zip5 = match zip5 { "" => None, _ => Some(zip5.into()) };
136
137 USPSAddress {
138 firmname: None,
139 address1,
140 address2,
141 city,
142 state,
143 urbanization: None,
144 zip5,
145 zip4: None,
146 ..Default::default()
147 }
148 }
149
150 pub(in crate) fn from_xml(xml: roxmltree::Document) -> Self {
151 let mut address = USPSAddress::default();
152
153 for node in xml.descendants() {
154 if node.is_element() {
155 let text = Some(String::from(node.text().unwrap_or("")));
156 println!("{:?}", node.tag_name().name());
157 println!("{:?}", node.text().unwrap_or("gay"));
158 match node.tag_name().name() {
159 "FirmName" => address.firmname = text,
160 "Address1" => address.address1 = text,
161 "Address2" => address.address2 = text,
162 "City" => address.city = text,
163 "CityAbbreviation" => address.city_abbreviation = text,
164 "State" => address.state = text,
165 "Urbanization" => address.urbanization = text,
166 "Zip5" => address.zip5 = text,
167 "Zip4" => address.zip4 = text,
168 "DeliveryPoint" => address.delivery_point = text,
169 "CarrierRoute" => address.carrier_route = text,
170 "Footnotes" => address.footnotes = text,
171 "DPVConfirmation" => address.dpv_confirmation = text,
172 "DPVCMRA" => address.dpv_cmra = text,
173 "DPVFootnotes" => address.dpv_footnotes = text,
174 "Business" => address.business = text,
175 "CentralDeliveryPoint" => address.central_delivery_point = text,
176 "Vacant" => address.vacant = text,
177 _ => ()
178 }
179 }
180 }
181
182 address
183 }
184
185 pub(in crate) fn xml(&self) -> String {
187 let mut s = String::with_capacity(150);
188 s.push_str("<Address ID=\"0\">");
189
190 s.push_str("<FirmName>");
191 if let Some(ref a) = self.firmname { s.push_str(a); }
192 s.push_str("</FirmName>");
193
194 s.push_str("<Address1>");
195 if let Some(ref a) = self.address1 { s.push_str(a); }
196 s.push_str("</Address1>");
197
198 s.push_str("<Address2>");
199 if let Some(ref a) = self.address2 { s.push_str(a); }
200 s.push_str("</Address2>");
201
202 s.push_str("<City>");
203 if let Some(ref a) = self.city { s.push_str(a); }
204 s.push_str("</City>");
205
206 if let Some(ref a) = self.state {
207 s.push_str("<State>");
208 s.push_str(a);
209 s.push_str("</State>");
210 }
211
212 if let Some(ref a) = self.urbanization {
213 s.push_str("<Urbanization>");
214 s.push_str(a);
215 s.push_str("</Urbanization>");
216 }
217
218 s.push_str("<Zip5>");
219 if let Some(ref a) = self.zip5 { s.push_str(a); }
220 s.push_str("</Zip5>");
221
222 s.push_str("<Zip4>");
223 if let Some(ref a) = self.zip4 { s.push_str(a); }
224 s.push_str("</Zip4>");
225
226 s.push_str("</Address>");
227 s
228 }
229}
230
231#[cfg(test)]
232mod address_tests {
233 use super::*;
234
235 #[test]
236 fn init_constructor() {
237 let dummy_struct = USPSAddress {
238 firmname: None,
239 address1: Some(String::from("123 Main St")),
240 address2: None,
241 city: Some(String::from("Seattle")),
242 state: Some(String::from("WA")),
243 urbanization: None,
244 zip5: Some(String::from("98119")),
245 zip4: None,
246 ..Default::default()
247 };
248
249 let constructed = USPSAddress::init("", "123 Main St", "", "Seattle", "WA", "", "98119", "");
250
251 assert_eq!(constructed, dummy_struct);
252 }
253
254 #[test]
255 fn quick_constructor() {
256 let dummy_struct = USPSAddress {
257 firmname: None,
258 address1: Some(String::from("123 Main St")),
259 address2: None,
260 city: Some(String::from("Seattle")),
261 state: Some(String::from("WA")),
262 urbanization: None,
263 zip5: Some(String::from("98119")),
264 zip4: None,
265 ..Default::default()
266 };
267
268 let constructed = USPSAddress::quick("123 Main St", "", "Seattle", "WA", "98119");
269
270 assert_eq!(constructed, dummy_struct);
271 }
272
273 #[test]
274 fn to_xml_1() {
275 let a = USPSAddress::quick("123 Main St", "", "Seattle", "WA", "98119");
276 let s = String::from("<Address ID=\"0\"><FirmName></FirmName><Address1>123 Main St</Address1><Address2></Address2><City>Seattle</City><State>WA</State><Zip5>98119</Zip5><Zip4></Zip4></Address>");
277 assert_eq!(a.xml(), s);
278 }
279
280 #[test]
281 fn to_xml_2() {
282 let a = USPSAddress::init("Acme, LLC", "123 Main St", "Apt 456", "Seattle", "WA", "", "98119", "1234");
283 let s = String::from("<Address ID=\"0\"><FirmName>Acme, LLC</FirmName><Address1>123 Main St</Address1><Address2>Apt 456</Address2><City>Seattle</City><State>WA</State><Zip5>98119</Zip5><Zip4>1234</Zip4></Address>");
284 assert_eq!(a.xml(), s);
285 }
286}
287