Skip to main content

jsonld_core/
ty.rs

1use super::Term;
2use crate::{Id, ValidId};
3use iri_rs::IriBuf;
4use jsonld_syntax::Keyword;
5use std::{convert::TryFrom, fmt};
6
7/// Object type.
8///
9/// This is the value of a `@type` entry.
10#[derive(Clone, PartialEq, Eq, Hash, Debug)]
11pub enum Type<I = IriBuf> {
12    /// `@id`.
13    ///
14    /// The value must be interpreted as an IRI.
15    Id,
16
17    /// `@json`.
18    ///
19    /// The value is an arbitrary JSON value.
20    Json,
21
22    /// `@none`
23    None,
24
25    /// `@vocab`
26    Vocab,
27
28    /// IRI type.
29    Iri(I),
30}
31
32impl<I> Type<I> {
33    /// Turns this type into an IRI if possible.
34    ///
35    /// # Errors
36    ///
37    /// Returns `self` unchanged when the value is not an IRI.
38    pub fn into_iri(self) -> Result<I, Type<I>> {
39        match self {
40            Type::Iri(id) => Ok(id),
41            typ => Err(typ),
42        }
43    }
44
45    /// Maps the IRI of this type.
46    pub fn map<U>(self, f: impl FnOnce(I) -> U) -> Type<U> {
47        match self {
48            Type::Id => Type::Id,
49            Type::Json => Type::Json,
50            Type::None => Type::None,
51            Type::Vocab => Type::Vocab,
52            Type::Iri(t) => Type::Iri(f(t)),
53        }
54    }
55}
56
57impl<I: Clone> Type<&I> {
58    /// Clones the referenced IRI.
59    #[must_use]
60    pub fn cloned(self) -> Type<I> {
61        match self {
62            Type::Id => Type::Id,
63            Type::Json => Type::Json,
64            Type::None => Type::None,
65            Type::Vocab => Type::Vocab,
66            Type::Iri(t) => Type::Iri(t.clone()),
67        }
68    }
69}
70
71impl<I> Type<I> {
72    /// Returns a reference to the type IRI if any.
73    pub fn as_iri(&self) -> Option<&I> {
74        match self {
75            Type::Iri(id) => Some(id),
76            _ => None,
77        }
78    }
79}
80
81impl<I: AsRef<str>> Type<I> {
82    /// Returns a JSON-LD string representation of the type.
83    pub fn as_str(&self) -> &str {
84        match self {
85            Type::Id => "@id",
86            Type::Json => "@json",
87            Type::None => "@none",
88            Type::Vocab => "@vocab",
89            Type::Iri(id) => id.as_ref(),
90        }
91    }
92}
93
94impl<'a, I> From<&'a Type<I>> for Type<&'a I> {
95    fn from(t: &'a Type<I>) -> Type<&'a I> {
96        match t {
97            Type::Id => Type::Id,
98            Type::Json => Type::Json,
99            Type::None => Type::None,
100            Type::Vocab => Type::Vocab,
101            Type::Iri(id) => Type::Iri(id),
102        }
103    }
104}
105
106impl<I, B> From<Type<I>> for Term<I, B> {
107    fn from(t: Type<I>) -> Term<I, B> {
108        match t {
109            Type::Id => Term::Keyword(Keyword::Id),
110            Type::Json => Term::Keyword(Keyword::Json),
111            Type::None => Term::Keyword(Keyword::None),
112            Type::Vocab => Term::Keyword(Keyword::Vocab),
113            Type::Iri(id) => Term::Id(Id::Valid(ValidId::Iri(id))),
114        }
115    }
116}
117
118impl<I, B> TryFrom<Term<I, B>> for Type<I> {
119    type Error = Term<I, B>;
120
121    fn try_from(term: Term<I, B>) -> Result<Type<I>, Term<I, B>> {
122        match term {
123            Term::Keyword(Keyword::Id) => Ok(Type::Id),
124            Term::Keyword(Keyword::Json) => Ok(Type::Json),
125            Term::Keyword(Keyword::None) => Ok(Type::None),
126            Term::Keyword(Keyword::Vocab) => Ok(Type::Vocab),
127            Term::Id(Id::Valid(ValidId::Iri(id))) => Ok(Type::Iri(id)),
128            term => Err(term),
129        }
130    }
131}
132
133impl<I: fmt::Display> fmt::Display for Type<I> {
134    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135        match self {
136            Type::Id => write!(f, "@id"),
137            Type::Json => write!(f, "@json"),
138            Type::None => write!(f, "@none"),
139            Type::Vocab => write!(f, "@vocab"),
140            Type::Iri(id) => id.fmt(f),
141        }
142    }
143}