Skip to main content

things3_cloud/wire/
mod.rs

1//! Things Cloud sync protocol wire-format types.
2//!
3//! Observed item shape in history pages:
4//! `{ uuid: { "t": operation, "e": entity, "p": properties } }`.
5//! Replaying items in order by UUID yields current state.
6
7use serde::{Deserialize, Deserializer};
8
9pub mod area;
10pub mod checklist;
11pub mod notes;
12pub mod recurrence;
13pub mod tags;
14pub mod task;
15pub mod tombstone;
16pub mod wire_object;
17
18#[derive(Deserialize)]
19#[serde(untagged)]
20enum OneOrMany<T> {
21    One(T),
22    Many(Vec<T>),
23}
24
25pub(crate) fn deserialize_optional_field<'de, D, T>(
26    deserializer: D,
27) -> Result<Option<Option<T>>, D::Error>
28where
29    D: Deserializer<'de>,
30    T: Deserialize<'de>,
31{
32    Option::<T>::deserialize(deserializer).map(Some)
33}
34
35pub(crate) fn deserialize_default_on_null<'de, D, T>(deserializer: D) -> Result<T, D::Error>
36where
37    D: Deserializer<'de>,
38    T: Deserialize<'de> + Default,
39{
40    Option::<T>::deserialize(deserializer).map(Option::unwrap_or_default)
41}
42
43pub(crate) fn deserialize_vec_or_single<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
44where
45    D: Deserializer<'de>,
46    T: Deserialize<'de>,
47{
48    Option::<OneOrMany<T>>::deserialize(deserializer).map(|value| match value {
49        None => Vec::new(),
50        Some(OneOrMany::One(v)) => vec![v],
51        Some(OneOrMany::Many(v)) => v,
52    })
53}