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::spec::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 calendar
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}