Skip to main content

ical/tree/prop/
lens.rs

1//! # Property lens contract
2//!
3//! [`IcalPropLens`] ties a property (by type) to its decoded value type, an
4//! edit cursor, and the `decode` projection from the generic syntax node onto
5//! the type. The wire name comes from its [`IcalPropSpec::KIND`] supertrait,
6//! so the two stay in sync; each property implements it on the marker in its
7//! own module.
8
9use crate::{
10    tree::{codec::Codec, line::IcalLine, prop::IcalPropSpec},
11    version::IcalVersion,
12};
13
14/// A property identified by type: its decoded value type, edit cursor, and the
15/// `decode` projection from the generic syntax node onto the type. The wire
16/// name comes from its [`IcalPropSpec::KIND`] (a supertrait), so the two stay
17/// in sync.
18pub trait IcalPropLens: IcalPropSpec {
19    /// The decoded value type, borrowing the syntax node for reads. Its
20    /// [`Codec`] impl is what the default `decode` delegates to.
21    type Target<'v>: Codec<'v>;
22
23    /// The typed edit cursor over a content line.
24    type Cursor<'c, 'a>
25    where
26        'a: 'c;
27
28    /// Project a content line onto the decoded type, consulting the card
29    /// version where the value's shape is version-specific (`GEO`, the binary
30    /// props). The default ignores the version and decodes the value node
31    /// through the target's [`Codec`]; the version-specific lenses override it.
32    fn decode<'v>(line: &'v IcalLine<'_>, _version: IcalVersion) -> Self::Target<'v> {
33        <Self::Target<'v> as Codec<'v>>::decode(&line.value)
34    }
35
36    /// Wrap a content line in the typed cursor for in-place editing.
37    fn cursor<'c, 'a>(line: &'c mut IcalLine<'a>) -> Self::Cursor<'c, 'a>;
38}