Skip to main content

ical/tree/codec/
mode.rs

1//! # Escaping mode
2//!
3//! The one place the codec consults the calendar version.
4//!
5//! Value escaping differs between vCalendar 1.0 (versit) and iCalendar 2.0
6//! (RFC 5545 3.3.11), and parameter encoding (RFC 6868) exists only from 2.0.
7//!
8//! A value node and a parameter node therefore each carry an [`Escaper`]
9//! telling the sibling [`escape`](crate::tree::codec::escape) and
10//! [`unescape`](crate::tree::codec::unescape) codecs which rules to apply.
11
12use crate::version::IcalVersion;
13
14/// The escaping rules to apply, selected by the calendar version.
15#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
16pub enum Escaper {
17    /// vCalendar 1.0 (versit): `\;` is resolved on read and a backslash before
18    /// anything else is literal; writing also escapes a newline, which versit
19    /// has none of its own for and which raw would end the line.
20    V1_0,
21    /// iCalendar 2.0 (RFC 5545 3.3.11): the value escapes `\\`, `\,`, `\;` and
22    /// `\n`, plus the RFC 6868 parameter value encoding.
23    #[default]
24    Modern,
25}
26
27impl Escaper {
28    /// The escaping rules a calendar of `version` uses.
29    pub fn for_version(version: IcalVersion) -> Self {
30        match version {
31            IcalVersion::V1_0 => Self::V1_0,
32            IcalVersion::V2_0 => Self::Modern,
33        }
34    }
35
36    /// The escaping rules for a raw `VERSION` wire string (e.g. `"1.0"`).
37    pub fn for_version_str(version: &str) -> Self {
38        match version.parse() {
39            Ok(IcalVersion::V1_0) => Self::V1_0,
40            _ => Self::Modern,
41        }
42    }
43
44    /// Whether this version carries the RFC 6868 parameter value encoding,
45    /// which updates RFC 5545 and so reaches iCalendar 2.0 alone: vCalendar 1.0
46    /// predates it, and a caret in one of its parameters is a literal caret.
47    pub fn has_param_encoding(self) -> bool {
48        matches!(self, Self::Modern)
49    }
50
51    /// Whether this version wraps a parameter value carrying a delimiter in
52    /// double quotes: RFC 5545 section 3.1 keeps `,`, `;` and `:` out of a
53    /// bare `paramtext` and gives `quoted-string` for a value that needs one,
54    /// while vCalendar 1.0 has no such production and reads its double quote
55    /// as content.
56    ///
57    /// A different question from [`has_param_encoding`], which is RFC 6868's
58    /// caret encoding, though the two versions this crate knows happen to
59    /// answer both the same way.
60    ///
61    /// [`has_param_encoding`]: Self::has_param_encoding
62    pub fn has_param_quoting(self) -> bool {
63        matches!(self, Self::Modern)
64    }
65}