Skip to main content

vcard/tree/value/
geo.rs

1//! # GEO value codec (RFC 6350 6.5.2)
2//!
3//! [`VcardCodec`] for the 2.1 / 3.0 coordinate pair. vCard 4.0 carries `GEO` as
4//! a URI, so that form never reaches this codec (the spec routes it to
5//! [`VcardUri`](crate::value::uri::VcardUri)).
6
7use alloc::vec;
8
9use crate::{
10    tree::{
11        codec::{VcardCodec, encode::encode_component, mode::VcardEscaper},
12        value::node::VcardValueNode,
13    },
14    value::geo::VcardGeo,
15};
16
17impl<'v> VcardCodec<'v> for VcardGeo<'v> {
18    fn decode(node: &'v VcardValueNode<'_>) -> Self {
19        // NOTE: 2.1 separates the pair with `,` (one component, two values),
20        // 3.0 with `;` (two components); the node's escaper tells them apart.
21        if node.escaper == VcardEscaper::V2_1 {
22            let mut parts = node.decode_at(0).into_iter();
23            VcardGeo {
24                latitude: parts.next().unwrap_or_default(),
25                longitude: parts.next().unwrap_or_default(),
26            }
27        } else {
28            VcardGeo {
29                latitude: node.decode_scalar_at(0),
30                longitude: node.decode_scalar_at(1),
31            }
32        }
33    }
34
35    fn encode(&self, escaper: VcardEscaper) -> VcardValueNode<'static> {
36        // NOTE: mirror of decode: 2.1 writes the pair as `lat,long` (one
37        // component, two values), 3.0 as `lat;long` (two components).
38        let components = if escaper == VcardEscaper::V2_1 {
39            vec![encode_component(
40                &[self.latitude.as_ref(), self.longitude.as_ref()],
41                escaper,
42            )]
43        } else {
44            vec![
45                encode_component(&[self.latitude.as_ref()], escaper),
46                encode_component(&[self.longitude.as_ref()], escaper),
47            ]
48        };
49
50        VcardValueNode::from_components(components, escaper)
51    }
52}