Skip to main content

oxjsonld/
error.rs

1pub use json_event_parser::TextPosition;
2use json_event_parser::{JsonParseError, JsonSyntaxError};
3use std::fmt::Formatter;
4use std::ops::Range;
5use std::{fmt, io};
6
7/// Error returned during JSON-LD parsing.
8#[derive(Debug, thiserror::Error)]
9pub enum JsonLdParseError {
10    /// I/O error during parsing (file not found...).
11    #[error(transparent)]
12    Io(#[from] io::Error),
13    /// An error in the file syntax.
14    #[error(transparent)]
15    Syntax(#[from] JsonLdSyntaxError),
16}
17
18impl From<JsonLdParseError> for io::Error {
19    #[inline]
20    fn from(error: JsonLdParseError) -> Self {
21        match error {
22            JsonLdParseError::Io(error) => error,
23            JsonLdParseError::Syntax(error) => error.into(),
24        }
25    }
26}
27
28#[doc(hidden)]
29impl From<JsonParseError> for JsonLdParseError {
30    #[inline]
31    fn from(error: JsonParseError) -> Self {
32        match error {
33            JsonParseError::Io(error) => Self::Io(error),
34            JsonParseError::Syntax(error) => Self::Syntax(error.into()),
35        }
36    }
37}
38
39/// An error in the syntax of the parsed file.
40#[derive(Debug, thiserror::Error)]
41#[error(transparent)]
42pub struct JsonLdSyntaxError(#[from] SyntaxErrorKind);
43
44#[derive(Debug, thiserror::Error)]
45enum SyntaxErrorKind {
46    #[error(transparent)]
47    Json(#[from] JsonSyntaxError),
48    #[error("{msg}")]
49    Msg { msg: String, code: JsonLdErrorCode },
50}
51
52impl JsonLdSyntaxError {
53    /// The [JSON-LD error code](https://www.w3.org/TR/json-ld-api/#dom-jsonlderrorcode) related to this error.
54    pub fn code(&self) -> Option<JsonLdErrorCode> {
55        match &self.0 {
56            SyntaxErrorKind::Json(_) => None,
57            SyntaxErrorKind::Msg { code, .. } => Some(*code),
58        }
59    }
60
61    /// The location of the error inside of the file.
62    pub fn location(&self) -> Option<Range<TextPosition>> {
63        match &self.0 {
64            SyntaxErrorKind::Json(e) => Some(e.location()),
65            SyntaxErrorKind::Msg { .. } => None,
66        }
67    }
68
69    /// Builds an error from a printable error message and an error code.
70    pub(crate) fn msg_and_code(msg: impl Into<String>, code: JsonLdErrorCode) -> Self {
71        Self(SyntaxErrorKind::Msg {
72            msg: msg.into(),
73            code,
74        })
75    }
76}
77
78impl From<JsonLdSyntaxError> for io::Error {
79    #[inline]
80    fn from(error: JsonLdSyntaxError) -> Self {
81        match error.0 {
82            SyntaxErrorKind::Json(error) => error.into(),
83            SyntaxErrorKind::Msg { msg, .. } => Self::new(io::ErrorKind::InvalidData, msg),
84        }
85    }
86}
87
88#[doc(hidden)]
89impl From<JsonSyntaxError> for JsonLdSyntaxError {
90    #[inline]
91    fn from(error: JsonSyntaxError) -> Self {
92        Self(SyntaxErrorKind::Json(error))
93    }
94}
95
96/// A [JSON-LD error code](https://www.w3.org/TR/json-ld-api/#dom-jsonlderrorcode)
97#[derive(Debug, Clone, Copy)]
98#[non_exhaustive]
99pub enum JsonLdErrorCode {
100    /// Two properties which expand to the same keyword have been detected.
101    /// This might occur if a keyword and an alias thereof are used at the same time.
102    CollidingKeywords,
103    /// Multiple conflicting indexes have been found for the same node.
104    ConflictingIndexes,
105    /// Maximum number of @context URLs exceeded.
106    ContextOverflow,
107    /// A cycle in IRI mappings has been detected.
108    CyclicIriMapping,
109    /// An @id entry was encountered whose value was not a string.
110    InvalidIdValue,
111    /// An invalid value for @import has been found.
112    InvalidImportValue,
113    /// An included block contains an invalid value.
114    InvalidIncludedValue,
115    /// An @index entry was encountered whose value was not a string.
116    InvalidIndexValue,
117    /// An invalid value for @nest has been found.
118    InvalidNestValue,
119    /// An invalid value for @prefix has been found.
120    InvalidPrefixValue,
121    /// An invalid value for @propagate has been found.
122    InvalidPropagateValue,
123    /// An invalid value for @protected has been found.
124    InvalidProtectedValue,
125    /// An invalid value for an @reverse entry has been detected, i.e., the value was not a map.
126    InvalidReverseValue,
127    /// The @version entry was used in a context with an out of range value.
128    InvalidVersionValue,
129    /// The value of @direction is not "ltr", "rtl", or null and thus invalid.
130    InvalidBaseDirection,
131    /// An invalid base IRI has been detected, i.e., it is neither an IRI nor null.
132    InvalidBaseIri,
133    /// An @container entry was encountered whose value was not one of the following strings:
134    /// @list, @set, @language, @index, @id, @graph, or @type.
135    InvalidContainerMapping,
136    /// An entry in a context is invalid due to processing mode incompatibility.
137    InvalidContextEntry,
138    /// An attempt was made to nullify a context containing protected term definitions.
139    InvalidContextNullification,
140    /// The value of the default language is not a string or null and thus invalid.
141    InvalidDefaultLanguage,
142    /// A local context contains a term that has an invalid or missing IRI mapping.
143    InvalidIriMapping,
144    /// An invalid JSON literal was detected.
145    InvalidJsonLiteral,
146    /// An invalid keyword alias definition has been encountered.
147    InvalidKeywordAlias,
148    /// An invalid value in a language map has been detected.
149    /// It MUST be a string or an array of strings.
150    InvalidLanguageMapValue,
151    /// An @language entry in a term definition was encountered
152    /// whose value was neither a string nor null and thus invalid.
153    InvalidLanguageMapping,
154    /// A language-tagged string with an invalid language value was detected.
155    InvalidLanguageTaggedString,
156    /// A number, true, or false with an associated language tag was detected.
157    InvalidLanguageTaggedValue,
158    /// An invalid local context was detected.
159    InvalidLocalContext,
160    /// No valid context document has been found for a referenced remote context.
161    InvalidRemoteContext,
162    /// An invalid reverse property definition has been detected.
163    InvalidReverseProperty,
164    /// An invalid reverse property map has been detected.
165    /// No keywords apart from @context are allowed in reverse property maps.
166    InvalidReversePropertyMap,
167    /// An invalid value for a reverse property has been detected.
168    /// The value of an inverse property must be a node object.
169    InvalidReversePropertyValue,
170    /// The local context defined within a term definition is invalid.
171    InvalidScopedContext,
172    /// A set object or list object with disallowed entries has been detected.
173    InvalidSetOrListObject,
174    /// The key ordering is not compatible with the streaming profile.
175    InvalidStreamingKeyOrder,
176    /// An invalid term definition has been detected.
177    InvalidTermDefinition,
178    /// An @type entry in a term definition was encountered whose value could not be expanded to an IRI.
179    InvalidTypeMapping,
180    /// An invalid value for an @type entry has been detected,
181    /// i.e., the value was neither a string nor an array of strings.
182    InvalidTypeValue,
183    /// A typed value with an invalid type was detected.
184    InvalidTypedValue,
185    /// A value object with disallowed entries has been detected.
186    InvalidValueObject,
187    /// An invalid value for the @value entry of a value object has been detected,
188    /// i.e., it is neither a scalar nor null.
189    InvalidValueObjectValue,
190    /// An invalid vocabulary mapping has been detected, i.e., it is neither an IRI nor null.
191    InvalidVocabMapping,
192    /// When compacting an IRI would result in an IRI which could be confused with a compact IRI
193    /// (because its IRI scheme matches a term definition and it has no IRI authority).
194    IriConfusedWithPrefix,
195    /// A keyword redefinition has been detected.
196    KeywordRedefinition,
197    /// The document could not be loaded or parsed as JSON.
198    LoadingDocumentFailed,
199    /// There was a problem encountered loading a remote context.
200    LoadingRemoteContextFailed,
201    /// An attempt was made to change the processing mode which is incompatible with the previous specified version.
202    ProcessingModeConflict,
203    /// An attempt was made to redefine a protected term.
204    ProtectedTermRedefinition,
205}
206
207impl fmt::Display for JsonLdErrorCode {
208    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
209        f.write_str(match self {
210            Self::CollidingKeywords => "colliding keywords",
211            Self::ConflictingIndexes => "conflicting indexes",
212            Self::ContextOverflow => "context overflow",
213            Self::CyclicIriMapping => "cyclic IRI mapping",
214            Self::InvalidIdValue => "invalid @id value",
215            Self::InvalidImportValue => "invalid @import value",
216            Self::InvalidIncludedValue => "invalid @included value",
217            Self::InvalidIndexValue => "invalid @index value",
218            Self::InvalidNestValue => "invalid @nest value",
219            Self::InvalidPrefixValue => "invalid @prefix value",
220            Self::InvalidPropagateValue => "invalid @propagate value",
221            Self::InvalidProtectedValue => "invalid @protected value",
222            Self::InvalidReverseValue => "invalid @reverse value",
223            Self::InvalidVersionValue => "invalid @version value",
224            Self::InvalidBaseDirection => "invalid base direction",
225            Self::InvalidBaseIri => "invalid base IRI",
226            Self::InvalidContainerMapping => "invalid container mapping",
227            Self::InvalidContextEntry => "invalid context entry",
228            Self::InvalidContextNullification => "invalid context nullification",
229            Self::InvalidDefaultLanguage => "invalid default language",
230            Self::InvalidIriMapping => "invalid IRI mapping",
231            Self::InvalidJsonLiteral => "invalid JSON literal",
232            Self::InvalidKeywordAlias => "invalid keyword alias",
233            Self::InvalidLanguageMapValue => "invalid language map value",
234            Self::InvalidLanguageMapping => "invalid language mapping",
235            Self::InvalidLanguageTaggedString => "invalid language-tagged string",
236            Self::InvalidLanguageTaggedValue => "invalid language-tagged value",
237            Self::InvalidLocalContext => "invalid local context",
238            Self::InvalidRemoteContext => "invalid remote context",
239            Self::InvalidReverseProperty => "invalid reverse property",
240            Self::InvalidReversePropertyMap => "invalid reverse property map",
241            Self::InvalidReversePropertyValue => "invalid reverse property value",
242            Self::InvalidScopedContext => "invalid scoped context",
243            Self::InvalidSetOrListObject => "invalid set or list object",
244            Self::InvalidStreamingKeyOrder => "invalid streaming key order",
245            Self::InvalidTermDefinition => "invalid term definition",
246            Self::InvalidTypeMapping => "invalid type mapping",
247            Self::InvalidTypeValue => "invalid type value",
248            Self::InvalidTypedValue => "invalid typed value",
249            Self::InvalidValueObject => "invalid value object",
250            Self::InvalidValueObjectValue => "invalid value object value",
251            Self::InvalidVocabMapping => "invalid vocab mapping",
252            Self::IriConfusedWithPrefix => "IRI confused with prefix",
253            Self::KeywordRedefinition => "keyword redefinition",
254            Self::LoadingDocumentFailed => "loading document failed",
255            Self::LoadingRemoteContextFailed => "loading remote context failed",
256            Self::ProcessingModeConflict => "processing mode conflict",
257            Self::ProtectedTermRedefinition => "protected term redefinition",
258        })
259    }
260}