1use alloc::vec;
7
8use crate::{
9 tree::{
10 codec::{VcardCodec, encode::encode_component, mode::VcardEscaper},
11 value::node::VcardValueNode,
12 },
13 value::adr::VcardAdr,
14};
15
16impl<'v> VcardCodec<'v> for VcardAdr<'v> {
17 fn decode(node: &'v VcardValueNode<'_>) -> Self {
18 VcardAdr {
19 po_box: node.decode_at(0),
20 extended: node.decode_at(1),
21 street: node.decode_at(2),
22 locality: node.decode_at(3),
23 region: node.decode_at(4),
24 postal_code: node.decode_at(5),
25 country: node.decode_at(6),
26 room: node.decode_at(7),
27 apartment: node.decode_at(8),
28 floor: node.decode_at(9),
29 street_number: node.decode_at(10),
30 street_name: node.decode_at(11),
31 building: node.decode_at(12),
32 block: node.decode_at(13),
33 subdistrict: node.decode_at(14),
34 district: node.decode_at(15),
35 landmark: node.decode_at(16),
36 direction: node.decode_at(17),
37 }
38 }
39
40 fn encode(&self, escaper: VcardEscaper) -> VcardValueNode<'static> {
41 let mut components = vec![
42 encode_component(&self.po_box, escaper),
43 encode_component(&self.extended, escaper),
44 encode_component(&self.street, escaper),
45 encode_component(&self.locality, escaper),
46 encode_component(&self.region, escaper),
47 encode_component(&self.postal_code, escaper),
48 encode_component(&self.country, escaper),
49 ];
50
51 if self.has_extended_components() {
52 components.extend([
53 encode_component(&self.room, escaper),
54 encode_component(&self.apartment, escaper),
55 encode_component(&self.floor, escaper),
56 encode_component(&self.street_number, escaper),
57 encode_component(&self.street_name, escaper),
58 encode_component(&self.building, escaper),
59 encode_component(&self.block, escaper),
60 encode_component(&self.subdistrict, escaper),
61 encode_component(&self.district, escaper),
62 encode_component(&self.landmark, escaper),
63 encode_component(&self.direction, escaper),
64 ]);
65 }
66
67 VcardValueNode::from_components(components, escaper)
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use alloc::{borrow::Cow, string::ToString, vec};
74
75 use crate::{
76 tree::{
77 codec::{VcardCodec, mode::VcardEscaper},
78 value::node::VcardValueNode,
79 },
80 value::adr::VcardAdr,
81 };
82
83 #[test]
84 fn decodes_and_reencodes_the_rfc_9554_components() {
85 let node = VcardValueNode::parse(b";;;Quebec;;;Canada;8th wing;;2;2875;boul. Laurier");
86 let adr = VcardAdr::decode(&node);
87
88 assert_eq!(adr.locality, vec![Cow::Borrowed("Quebec")]);
89 assert_eq!(adr.room, vec![Cow::Borrowed("8th wing")]);
90 assert_eq!(adr.floor, vec![Cow::Borrowed("2")]);
91 assert_eq!(adr.street_number, vec![Cow::Borrowed("2875")]);
92 assert_eq!(adr.street_name, vec![Cow::Borrowed("boul. Laurier")]);
93 assert!(adr.has_extended_components());
94
95 assert_eq!(
97 adr.encode(VcardEscaper::Modern).to_string(),
98 ";;;Quebec;;;Canada;8th wing;;2;2875;boul. Laurier;;;;;;",
99 );
100 }
101
102 #[test]
103 fn a_classic_address_keeps_its_seven_slots() {
104 let adr = VcardAdr {
105 street: vec![Cow::Borrowed("2875 boul. Laurier")],
106 locality: vec![Cow::Borrowed("Quebec")],
107 ..VcardAdr::default()
108 };
109
110 assert!(!adr.has_extended_components());
111 assert_eq!(
112 adr.encode(VcardEscaper::Modern).to_string(),
113 ";;2875 boul. Laurier;Quebec;;;",
114 );
115 }
116}