oxigraph/storage/
error.rs

1use crate::io::{RdfFormat, RdfParseError};
2use crate::storage::numeric_encoder::EncodedTerm;
3use oxiri::IriParseError;
4use oxrdf::TermRef;
5use std::error::Error;
6use std::io;
7
8/// An error related to storage operations (reads, writes...).
9#[derive(Debug, thiserror::Error)]
10#[non_exhaustive]
11pub enum StorageError {
12    /// Error from the OS I/O layer.
13    #[error(transparent)]
14    Io(#[from] io::Error),
15    /// Error related to data corruption.
16    #[error(transparent)]
17    Corruption(#[from] CorruptionError),
18    #[doc(hidden)]
19    #[error("{0}")]
20    Other(#[source] Box<dyn Error + Send + Sync + 'static>),
21}
22
23impl From<StorageError> for io::Error {
24    #[inline]
25    fn from(error: StorageError) -> Self {
26        match error {
27            StorageError::Io(error) => error,
28            StorageError::Corruption(error) => error.into(),
29            StorageError::Other(error) => Self::other(error),
30        }
31    }
32}
33
34/// An error return if some content in the database is corrupted.
35#[derive(Debug, thiserror::Error)]
36#[error(transparent)]
37pub struct CorruptionError(#[from] CorruptionErrorKind);
38
39/// An error return if some content in the database is corrupted.
40#[derive(Debug, thiserror::Error)]
41enum CorruptionErrorKind {
42    #[error("{0}")]
43    Msg(String),
44    #[error("{0}")]
45    Other(#[source] Box<dyn Error + Send + Sync + 'static>),
46}
47
48impl CorruptionError {
49    /// Builds an error from a printable error message.
50    #[inline]
51    pub(crate) fn new(error: impl Into<Box<dyn Error + Send + Sync + 'static>>) -> Self {
52        Self(CorruptionErrorKind::Other(error.into()))
53    }
54
55    #[inline]
56    pub(crate) fn from_encoded_term(encoded: &EncodedTerm, term: &TermRef<'_>) -> Self {
57        // TODO: eventually use a dedicated error enum value
58        Self::msg(format!("Invalid term encoding {encoded:?} for {term}"))
59    }
60
61    #[inline]
62    #[cfg(all(not(target_family = "wasm"), feature = "rocksdb"))]
63    pub(crate) fn from_missing_column_family_name(name: &'static str) -> Self {
64        // TODO: eventually use a dedicated error enum value
65        Self::msg(format!("Column family {name} does not exist"))
66    }
67
68    /// Builds an error from a printable error message.
69    #[inline]
70    pub(crate) fn msg(msg: impl Into<String>) -> Self {
71        Self(CorruptionErrorKind::Msg(msg.into()))
72    }
73}
74
75impl From<CorruptionError> for io::Error {
76    #[inline]
77    fn from(error: CorruptionError) -> Self {
78        Self::new(io::ErrorKind::InvalidData, error)
79    }
80}
81
82/// An error raised while loading a file into a [`Store`](crate::store::Store).
83#[derive(Debug, thiserror::Error)]
84pub enum LoaderError {
85    /// An error raised while reading the file.
86    #[error(transparent)]
87    Parsing(#[from] RdfParseError),
88    /// An error raised during the insertion in the store.
89    #[error(transparent)]
90    Storage(#[from] StorageError),
91    /// The base IRI is invalid.
92    #[error("Invalid base IRI '{iri}': {error}")]
93    InvalidBaseIri {
94        /// The IRI itself.
95        iri: String,
96        /// The parsing error.
97        #[source]
98        error: IriParseError,
99    },
100}
101
102impl From<LoaderError> for io::Error {
103    #[inline]
104    fn from(error: LoaderError) -> Self {
105        match error {
106            LoaderError::Storage(error) => error.into(),
107            LoaderError::Parsing(error) => error.into(),
108            LoaderError::InvalidBaseIri { .. } => {
109                Self::new(io::ErrorKind::InvalidInput, error.to_string())
110            }
111        }
112    }
113}
114
115/// An error raised while writing a file from a [`Store`](crate::store::Store).
116#[derive(Debug, thiserror::Error)]
117pub enum SerializerError {
118    /// An error raised while writing the content.
119    #[error(transparent)]
120    Io(#[from] io::Error),
121    /// An error raised during the lookup in the store.
122    #[error(transparent)]
123    Storage(#[from] StorageError),
124    /// A format compatible with [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) is required.
125    #[error("A RDF format supporting datasets was expected, {0} found")]
126    DatasetFormatExpected(RdfFormat),
127}
128
129impl From<SerializerError> for io::Error {
130    #[inline]
131    fn from(error: SerializerError) -> Self {
132        match error {
133            SerializerError::Storage(error) => error.into(),
134            SerializerError::Io(error) => error,
135            SerializerError::DatasetFormatExpected(_) => {
136                Self::new(io::ErrorKind::InvalidInput, error.to_string())
137            }
138        }
139    }
140}