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