activity_vocabulary_core/
lib.rs

1use std::{
2    collections::{BTreeMap, HashMap},
3    fmt::Debug,
4    hash::Hash,
5    marker::PhantomData,
6};
7
8use serde::{de::Visitor, ser::SerializeSeq, Deserialize, Serialize};
9
10pub mod xsd;
11
12#[derive(PartialEq, Eq, Clone, Debug, Hash)]
13pub enum Remotable<T> {
14    Remote(url::Url),
15    Inline(T),
16}
17
18pub trait ObjectId {
19    fn object_id(&self) -> Option<&url::Url>;
20}
21
22impl<T: ObjectId> ObjectId for Remotable<T> {
23    fn object_id(&self) -> Option<&url::Url> {
24        match self {
25            Remotable::Remote(id) => Some(id),
26            Remotable::Inline(object) => object.object_id(),
27        }
28    }
29}
30
31impl<T: Serialize> Serialize for Remotable<T> {
32    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
33    where
34        S: serde::Serializer,
35    {
36        match self {
37            Remotable::Inline(inline) => inline.serialize(serializer),
38            Remotable::Remote(remote) => remote.serialize(serializer),
39        }
40    }
41}
42
43impl<'de, T: Deserialize<'de>> Deserialize<'de> for Remotable<T> {
44    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
45    where
46        D: serde::Deserializer<'de>,
47    {
48        let value = serde_value::Value::deserialize(deserializer)?;
49        let deserializer = serde_value::ValueDeserializer::<D::Error>::new(value.clone());
50        match T::deserialize(deserializer) {
51            Ok(inline) => Ok(Self::Inline(inline)),
52            Err(inline_err) => url::Url::deserialize(serde_value::ValueDeserializer::new(value))
53                .map_err(|e: D::Error| serde::de::Error::custom(format!("{inline_err} & {e}")))
54                .map(Self::Remote),
55        }
56    }
57}
58
59#[derive(PartialEq, Eq, Clone, Debug, Hash)]
60pub struct Property<T>(pub Vec<T>);
61
62impl<T: Serialize> Serialize for Property<T> {
63    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
64    where
65        S: serde::Serializer,
66    {
67        if let [inner] = &self.0[..] {
68            inner.serialize(serializer)
69        } else if self.0.len() > 1 {
70            self.0.serialize(serializer)
71        } else {
72            serializer.serialize_none()
73        }
74    }
75}
76
77impl<'de, T: Deserialize<'de>> Deserialize<'de> for Property<T> {
78    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
79    where
80        D: serde::Deserializer<'de>,
81    {
82        let content = serde::__private::de::Content::deserialize(deserializer)?;
83        let deserializer = serde::__private::de::ContentRefDeserializer::<D::Error>::new(&content);
84        match Vec::<T>::deserialize(deserializer) {
85            Ok(inner) => Ok(Self(inner)),
86            Err(seq_err) => match Option::<T>::deserialize(deserializer) {
87                Ok(inner) => Ok(Self(inner.into_iter().collect())),
88                Err(opt_err) => Err(serde::de::Error::custom(format!("{seq_err} & {opt_err}"))),
89            },
90        }
91    }
92}
93
94impl<T> Default for Property<T> {
95    fn default() -> Self {
96        Self(Default::default())
97    }
98}
99
100#[derive(PartialEq, Clone, Debug)]
101pub enum Or<T, U> {
102    Prim(T),
103    Snd(U),
104}
105
106impl<'de, L: Deserialize<'de>, R: Deserialize<'de>> Deserialize<'de> for Or<L, R> {
107    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
108    where
109        D: serde::Deserializer<'de>,
110    {
111        let content = serde::__private::de::Content::deserialize(deserializer)?;
112        let deserializer = serde::__private::de::ContentRefDeserializer::<D::Error>::new(&content);
113        match L::deserialize(deserializer) {
114            Ok(left) => Ok(Self::Prim(left)),
115            Err(left_err) => R::deserialize(deserializer)
116                .map_err(|right_err| {
117                    serde::de::Error::custom(format!("{left_err} and {right_err}"))
118                })
119                .map(Self::Snd),
120        }
121    }
122}
123
124impl<T: Serialize, U: Serialize> Serialize for Or<T, U> {
125    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
126    where
127        S: serde::Serializer,
128    {
129        match self {
130            Self::Prim(value) => value.serialize(serializer),
131            Self::Snd(value) => value.serialize(serializer),
132        }
133    }
134}
135
136//pub type Remotable<T> = Or<T, Link>;
137pub type Untypable<T> = Or<T, serde_json::Value>;
138
139impl<L, R> Or<L, R> {
140    pub fn prim(&self) -> Option<&L> {
141        match self {
142            Self::Prim(l) => Some(l),
143            Self::Snd(_) => None,
144        }
145    }
146    pub fn snd(&self) -> Option<&R> {
147        match self {
148            Self::Prim(_) => None,
149            Self::Snd(r) => Some(r),
150        }
151    }
152}
153
154impl<P, S> From<P> for Or<P, S> {
155    fn from(value: P) -> Self {
156        Or::Prim(value)
157    }
158}
159
160impl<L: Default, R> Default for Or<L, R> {
161    fn default() -> Self {
162        Or::Prim(L::default())
163    }
164}
165
166pub trait SkipSerialization {
167    fn should_skip(&self) -> bool;
168}
169
170impl<T> SkipSerialization for Option<T> {
171    fn should_skip(&self) -> bool {
172        self.is_none()
173    }
174}
175
176impl<T> SkipSerialization for Property<T> {
177    fn should_skip(&self) -> bool {
178        self.0.is_empty()
179    }
180}
181
182impl<K, V> SkipSerialization for HashMap<K, V> {
183    fn should_skip(&self) -> bool {
184        self.is_empty()
185    }
186}
187
188#[derive(Debug, Clone, PartialEq, Default)]
189pub struct LangContainer<T> {
190    pub default: Option<T>,
191    pub per_lang: HashMap<String, T>,
192}
193
194impl<'de, T: Deserialize<'de>> Deserialize<'de> for LangContainer<T> {
195    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
196    where
197        D: serde::Deserializer<'de>,
198    {
199        let value = serde_value::Value::deserialize(deserializer)?;
200        let deserializer = serde_value::ValueDeserializer::<D::Error>::new(value.clone());
201        match T::deserialize(deserializer) {
202            Ok(inline) => Ok(Self {
203                default: Some(inline),
204                per_lang: Default::default(),
205            }),
206            Err(inline_err) => {
207                HashMap::<String, T>::deserialize(serde_value::ValueDeserializer::new(value))
208                    .map_err(|e: D::Error| serde::de::Error::custom(format!("{inline_err} & {e}")))
209                    .map(|per_lang| Self {
210                        default: Default::default(),
211                        per_lang,
212                    })
213            }
214        }
215    }
216}
217
218impl<T> LangContainer<T> {
219    pub fn merge(&mut self, other: Self) {
220        match (&mut self.default, other.default) {
221            (Some(x), Some(y)) => *x = y,
222            (None, Some(y)) => self.default = Some(y),
223            (_, None) => (),
224        }
225        self.per_lang.extend(other.per_lang)
226    }
227}
228
229impl<T: MergeableProperty> LangContainer<T> {
230    pub fn deep_merge(&mut self, other: Self) {
231        match (&mut self.default, other.default) {
232            (Some(x), Some(y)) => x.merge(y),
233            (None, Some(y)) => self.default = Some(y),
234            (_, None) => (),
235        }
236        for (k, v) in other.per_lang {
237            match &mut self.per_lang.get_mut(&k) {
238                Some(occupied) => occupied.merge(v),
239                None => {
240                    self.per_lang.insert(k, v);
241                }
242            }
243        }
244    }
245}
246
247pub trait MergeableProperty {
248    fn merge(&mut self, other: Self);
249}
250
251impl<T> MergeableProperty for Property<T> {
252    fn merge(&mut self, other: Self) {
253        self.0.extend(other.0)
254    }
255}
256
257impl<K: Eq + Hash, V> MergeableProperty for HashMap<K, V> {
258    fn merge(&mut self, other: Self) {
259        self.extend(other)
260    }
261}
262
263impl<T: MergeableProperty> MergeableProperty for Option<T> {
264    fn merge(&mut self, other: Self) {
265        match (self.as_mut(), other) {
266            (Some(x), Some(y)) => x.merge(y),
267            (None, Some(y)) => {
268                *self = Some(y);
269            }
270            (Some(_), None) => (),
271            (None, None) => (),
272        }
273    }
274}
275
276#[derive(PartialEq, Eq, Clone, Debug)]
277pub struct Context {
278    urls: Vec<url::Url>,
279    inline: HashMap<String, serde_json::Value>,
280}
281
282impl Serialize for Context {
283    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
284    where
285        S: serde::Serializer,
286    {
287        if self.inline.is_empty() {
288            if let &[url] = &self.urls.as_slice() {
289                url.serialize(serializer)
290            } else {
291                self.urls.serialize(serializer)
292            }
293        } else if self.urls.is_empty() {
294            self.inline.serialize(serializer)
295        } else {
296            let mut serializer = serializer.serialize_seq(Some(self.urls.len() + 1))?;
297            for url in &self.urls {
298                serializer.serialize_element(url)?;
299            }
300            serializer.serialize_element(&self.inline)?;
301            serializer.end()
302        }
303    }
304}
305
306enum ContextArrayElement {
307    Url(url::Url),
308    Inline(HashMap<String, serde_json::Value>),
309}
310
311struct ContextArrayElementVisitor;
312impl<'de> Visitor<'de> for ContextArrayElementVisitor {
313    type Value = ContextArrayElement;
314    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
315        formatter.write_str("element of @context[]")
316    }
317
318    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
319    where
320        A: serde::de::MapAccess<'de>,
321    {
322        let mut r = HashMap::new();
323        while let Some((k, v)) = map.next_entry::<String, serde_json::Value>()? {
324            r.insert(k, v);
325        }
326        Ok(ContextArrayElement::Inline(r))
327    }
328
329    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
330    where
331        E: serde::de::Error,
332    {
333        Ok(ContextArrayElement::Url(
334            v.parse().map_err(serde::de::Error::custom)?,
335        ))
336    }
337}
338
339impl<'de> Deserialize<'de> for ContextArrayElement {
340    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
341    where
342        D: serde::Deserializer<'de>,
343    {
344        deserializer.deserialize_any(ContextArrayElementVisitor)
345    }
346}
347
348struct ContextVisitor;
349impl<'de> Visitor<'de> for ContextVisitor {
350    type Value = Context;
351
352    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
353        formatter.write_str("@context")
354    }
355
356    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
357    where
358        E: serde::de::Error,
359    {
360        let visitor = ContextArrayElementVisitor;
361        let ContextArrayElement::Url(url) = visitor.visit_str(v)? else {
362            unreachable!()
363        };
364        Ok(Self::Value {
365            urls: vec![url],
366            inline: Default::default(),
367        })
368    }
369
370    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
371    where
372        A: serde::de::SeqAccess<'de>,
373    {
374        let mut inline = HashMap::new();
375        let mut urls = Vec::new();
376        while let Some(element) = seq.next_element::<ContextArrayElement>()? {
377            match element {
378                ContextArrayElement::Inline(new) => {
379                    inline.extend(new);
380                }
381                ContextArrayElement::Url(url) => {
382                    urls.push(url);
383                }
384            }
385        }
386        Ok(Self::Value { inline, urls })
387    }
388
389    fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
390    where
391        A: serde::de::MapAccess<'de>,
392    {
393        let visitor = ContextArrayElementVisitor;
394        let ContextArrayElement::Inline(inline) = visitor.visit_map(map)? else {
395            unreachable!()
396        };
397        Ok(Self::Value {
398            inline,
399            urls: Default::default(),
400        })
401    }
402}
403
404impl<'de> Deserialize<'de> for Context {
405    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
406    where
407        D: serde::Deserializer<'de>,
408    {
409        deserializer.deserialize_any(ContextVisitor)
410    }
411}
412
413#[derive(Serialize, Deserialize)]
414pub struct WithContext<T> {
415    #[serde(rename = "@context", skip_serializing_if = "Option::is_none")]
416    pub context: Option<Context>,
417    #[serde(flatten)]
418    pub body: T,
419}
420
421pub struct TaggedContentVisitor<T> {
422    name: &'static str,
423    tag: &'static str,
424    _tag: PhantomData<T>,
425}
426
427impl<T> TaggedContentVisitor<T> {
428    pub fn new(name: &'static str, tag: &'static str) -> Self {
429        Self {
430            name,
431            tag,
432            _tag: Default::default(),
433        }
434    }
435}
436
437impl<'de, T: Deserialize<'de> + Debug + Default> Visitor<'de> for TaggedContentVisitor<T> {
438    type Value = (T, serde_value::Value);
439
440    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
441        formatter.write_str(self.name)
442    }
443
444    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
445    where
446        A: serde::de::MapAccess<'de>,
447    {
448        let mut content = BTreeMap::new();
449        let mut tag = None;
450        while let Some((k, v)) = map.next_entry::<serde_value::Value, serde_value::Value>()? {
451            if let serde_value::Value::String(label) = &k {
452                if label == self.tag {
453                    tag = Some(T::deserialize(serde_value::ValueDeserializer::new(
454                        v.clone(),
455                    ))?)
456                }
457            }
458            content.insert(k, v);
459        }
460        Ok((tag.unwrap_or_default(), serde_value::Value::Map(content)))
461    }
462}