#[non_exhaustive]pub enum AlertTrigger {
OffsetTrigger(OffsetTrigger),
AbsoluteTrigger(AbsoluteTrigger),
Unknown(Value),
}Expand description
Alert trigger — either offset-based, absolute, or an unknown future type (RFC 8984 §4.5.2).
The @type field on the wire selects the variant. The Unknown variant
preserves any unrecognised trigger type for round-trip fidelity, as
required by the spec: “Implementations MUST NOT trigger for trigger types
they do not understand but MUST preserve them.”
Serde is implemented manually because #[serde(tag = "@type", other)]
with a tuple variant is not supported by serde’s derive macros; other
only works with unit variants in internally-tagged enums.
§Deserialization behaviour on malformed input
The custom Deserialize impl is deliberately permissive about the JSON
shape of the input — only the @type tag drives the dispatch. Any
input whose @type is missing, is not a string, or names a tag other
than "OffsetTrigger" / "AbsoluteTrigger" is captured as
AlertTrigger::Unknown carrying the original serde_json::Value
unchanged. This includes:
- top-level non-objects:
null, arrays, numbers, strings, booleans - objects without an
@typekey - objects whose
@typeis a non-string value (null,42,[]) - objects whose
@typeis a string outside the known set
The rationale is round-trip fidelity per the spec’s preserve-mandate:
rejecting at deserialize time would force consumers to drop data they
are supposed to preserve. Consumers that need a stricter check should
pattern-match on the variant and inspect the carried Value. A future
well-typed AlertTrigger variant only ever displaces input that
previously matched on @type exactly, so this permissive behaviour is
forward-compatible with the spec’s evolution.
§Maintainer note: do NOT “clean up” this enum
The Unknown(serde_json::Value) variant exists because RFC 8984 §4.5.2
requires preservation of unrecognised trigger types. The following
three “cleanups” all violate that MUST and break the regression tests
alert_trigger_unknown_dispatch_on_hostile_input and
alert_trigger_unknown_round_trips_through_serialize (both in this
file), as well as alert_unknown_trigger_roundtrip in
crate-jmap-calendars-types/tests/types_test.rs:
-
Remove the
Unknownvariant. An exhaustive enum forces deserialize to either fail on an unknown@type(data loss + error) or silently drop the input (data loss). Both violateMUST preserve them. -
Replace
Unknown(Value)with#[serde(other)]on a unit variant. A unit variant discards the carried JSON payload. The spec preserve- mandate requires the bytes round-trip, not just the variant discriminator.Unknown(String)andUnknown { at_type: String }have the same defect — they drop the inner fields. -
Add
#[serde(deny_unknown_fields)]toAlertTriggeror toOffsetTrigger/AbsoluteTrigger. A peer that emits an extension field on a known trigger type (e.g.OffsetTriggerwith a vendor field) would fail to deserialize entirely. The catch-allextramap on the inner structs is the workspace’s extras-preservation mechanism for that case;deny_unknown_fieldsfights it.
If you are reading this comment because you have a fourth “cleanup” in mind: confirm against the regression test and the spec passage (RFC 8984 §4.5.2) before proposing it. The design defense is bd:JMAP-1rwf.8.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
OffsetTrigger(OffsetTrigger)
Offset-based trigger: fires at offset relative to event start/end.
AbsoluteTrigger(AbsoluteTrigger)
Absolute trigger: fires at a specific UTC date-time.
Unknown(Value)
Any other trigger type; preserved opaquely as raw JSON.
Trait Implementations§
Source§impl Clone for AlertTrigger
impl Clone for AlertTrigger
Source§fn clone(&self) -> AlertTrigger
fn clone(&self) -> AlertTrigger
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more