Skip to main content

jsonld_expansion/
error.rs

1use jsonld_context_processing::algorithm::RejectVocab;
2use jsonld_syntax::ErrorCode;
3
4#[derive(Debug, thiserror::Error)]
5/// Error raised while expanding a document.
6pub enum Error<E = std::convert::Infallible> {
7    #[error("Invalid context: {0}")]
8    /// The value of an `@context` entry is not a valid JSON-LD context.
9    ContextSyntax(#[from] jsonld_syntax::context::InvalidContext),
10
11    #[error("Context processing failed: {0}")]
12    /// Processing a local, scoped or remote `@context` failed. This includes
13    /// the failures of the document loader fetching a remote context.
14    ContextProcessing(jsonld_context_processing::Error<E>),
15
16    #[error("Invalid `@index` value")]
17    /// An `@index` entry has a value that is not a string.
18    InvalidIndexValue,
19
20    #[error("Invalid set or list object")]
21    /// A `@set` or `@list` object has an entry other than `@set`/`@list` and
22    /// `@index`.
23    InvalidSetOrListObject,
24
25    #[error("Invalid `@reverse` property map")]
26    /// A key of a `@reverse` map expands to a keyword, or a keyword entry was
27    /// found while `@reverse` is the active property.
28    InvalidReversePropertyMap,
29
30    #[error("Invalid `@type` value")]
31    /// An `@type` entry is not a string or an array of strings, or one of its
32    /// values does not expand to an IRI or blank node identifier.
33    InvalidTypeValue,
34
35    #[error("Key `{0}` expansion failed")]
36    /// The given key could not be expanded into an IRI, and the [`Policy`] in
37    /// use rejects such keys instead of dropping them.
38    ///
39    /// [`Policy`]: crate::Policy
40    KeyExpansionFailed(String),
41
42    #[error("Invalid `@reverse` property value")]
43    /// A reverse property has a value that is not a node object, which cannot
44    /// be the subject of the reversed relation.
45    InvalidReversePropertyValue,
46
47    #[error("Invalid `@language` map value")]
48    /// A language map (`@container: @language`) has a value that is neither a
49    /// string, `null`, nor an array of those.
50    InvalidLanguageMapValue,
51
52    #[error("Colliding keywords")]
53    /// Two distinct keys of the same node object expand to the same keyword.
54    ///
55    /// In JSON-LD 1.1 this is tolerated for `@included` and `@type`, whose
56    /// values are merged instead.
57    CollidingKeywords,
58
59    #[error("Invalid `@id` value")]
60    /// An `@id` entry has a value that is not a string.
61    InvalidIdValue,
62
63    #[error("Invalid `@included` value")]
64    /// An `@included` entry contains something else than node objects.
65    InvalidIncludedValue,
66
67    #[error("Invalid `@reverse` value")]
68    /// A `@reverse` entry has a value that is not a map.
69    InvalidReverseValue,
70
71    #[error("Invalid `@nest` value")]
72    /// An `@nest` entry has a value that is not a map (or an array of maps),
73    /// or one of those maps has an entry expanding to `@value`.
74    InvalidNestValue,
75
76    #[error("Duplicate key `{0}`")]
77    /// The given key appears twice in the same JSON object.
78    DuplicateKey(jstrict::object::Key),
79
80    #[error(transparent)]
81    /// Expanding a scalar into a literal failed. See
82    /// [`LiteralExpansionError`](crate::LiteralExpansionError).
83    Literal(crate::LiteralExpansionError),
84
85    #[error(transparent)]
86    /// A value object (a map with an `@value` entry) is invalid. See
87    /// [`InvalidValue`](crate::InvalidValue).
88    Value(crate::InvalidValue),
89
90    #[error("Forbidden use of `@vocab`")]
91    /// A key could only be expanded through the vocabulary mapping (`@vocab`),
92    /// which the [`Policy`](crate::Policy) in use forbids.
93    ForbiddenVocab,
94
95    #[error("List of lists")]
96    /// A list object was found among the items of another list object.
97    ///
98    /// JSON-LD 1.0 only: 1.1 allows lists of lists.
99    ListOfLists,
100}
101
102impl<E> From<RejectVocab> for Error<E> {
103    fn from(_value: RejectVocab) -> Self {
104        Self::ForbiddenVocab
105    }
106}
107
108impl<E> Error<E> {
109    /// Returns the JSON-LD error code this error is reported under, as named by
110    /// the [JSON-LD API specification][spec].
111    ///
112    /// [spec]: https://www.w3.org/TR/json-ld11-api/#jsonlderror
113    pub fn code(&self) -> ErrorCode {
114        match self {
115            Self::ContextSyntax(e) => e.code(),
116            Self::ContextProcessing(e) => e.code(),
117            Self::InvalidIndexValue => ErrorCode::InvalidIndexValue,
118            Self::InvalidSetOrListObject => ErrorCode::InvalidSetOrListObject,
119            Self::InvalidReversePropertyMap => ErrorCode::InvalidReversePropertyMap,
120            Self::InvalidTypeValue => ErrorCode::InvalidTypeValue,
121            Self::KeyExpansionFailed(_) => ErrorCode::KeyExpansionFailed,
122            Self::InvalidReversePropertyValue => ErrorCode::InvalidReversePropertyValue,
123            Self::InvalidLanguageMapValue => ErrorCode::InvalidLanguageMapValue,
124            Self::CollidingKeywords => ErrorCode::CollidingKeywords,
125            Self::InvalidIdValue => ErrorCode::InvalidIdValue,
126            Self::InvalidIncludedValue => ErrorCode::InvalidIncludedValue,
127            Self::InvalidReverseValue => ErrorCode::InvalidReverseValue,
128            Self::InvalidNestValue => ErrorCode::InvalidNestValue,
129            Self::DuplicateKey(_) => ErrorCode::DuplicateKey,
130            Self::Literal(e) => e.code(),
131            Self::Value(e) => e.code(),
132            Self::ForbiddenVocab => ErrorCode::InvalidVocabMapping,
133            Self::ListOfLists => ErrorCode::ListOfLists,
134        }
135    }
136}
137
138impl<E> Error<E> {
139    /// Builds an [`Error::DuplicateKey`] from the pair of colliding entries
140    /// `jstrict` reports, keeping the key of the first one.
141    #[must_use]
142    pub fn duplicate_key_ref(jstrict::object::Duplicate(a, _b): jstrict::object::Duplicate<&jstrict::object::Entry>) -> Self {
143        Self::DuplicateKey(a.key.clone())
144    }
145}
146
147impl<E> From<jsonld_context_processing::Error<E>> for Error<E> {
148    fn from(e: jsonld_context_processing::Error<E>) -> Self {
149        Self::ContextProcessing(e)
150    }
151}
152
153impl<E> From<crate::LiteralExpansionError> for Error<E> {
154    fn from(e: crate::LiteralExpansionError) -> Self {
155        Self::Literal(e)
156    }
157}
158
159impl<E> From<crate::InvalidValue> for Error<E> {
160    fn from(e: crate::InvalidValue) -> Self {
161        Self::Value(e)
162    }
163}
164
165impl<E> From<crate::literal::NotALiteral> for Error<E> {
166    fn from(e: crate::literal::NotALiteral) -> Self {
167        Self::Literal(crate::LiteralExpansionError::NotALiteral(e))
168    }
169}