diff --git a/lib/src/sparql/error.rs b/lib/src/sparql/error.rs index 0e60d6ab..2e9a84e6 100644 --- a/lib/src/sparql/error.rs +++ b/lib/src/sparql/error.rs @@ -1,5 +1,6 @@ use crate::error::Infallible; use crate::sparql::ParseError; +use crate::store::numeric_encoder::DecoderError; use std::error; use std::fmt; use std::io; @@ -107,3 +108,9 @@ impl From for EvaluationError { Self::Io(error) } } + +impl> From> for EvaluationError { + fn from(error: DecoderError) -> Self { + io::Error::from(error).into() + } +} diff --git a/lib/src/store/numeric_encoder.rs b/lib/src/store/numeric_encoder.rs index 60a1f1d3..1de7c532 100644 --- a/lib/src/store/numeric_encoder.rs +++ b/lib/src/store/numeric_encoder.rs @@ -12,7 +12,7 @@ use std::hash::Hash; use std::hash::Hasher; use std::io::Read; use std::mem::size_of; -use std::{io, str}; +use std::{fmt, io, str}; #[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Copy, Clone, Hash)] #[repr(transparent)] @@ -1097,35 +1097,38 @@ pub fn parse_day_time_duration_str(value: &str) -> Option { value.parse().map(EncodedTerm::DayTimeDurationLiteral).ok() } -pub(crate) trait Decoder { - fn decode_term(&self, encoded: EncodedTerm) -> Result; +pub(crate) trait Decoder: StrLookup { + fn decode_term(&self, encoded: EncodedTerm) -> Result>; fn decode_named_or_blank_node( &self, encoded: EncodedTerm, - ) -> Result { + ) -> Result> { match self.decode_term(encoded)? { Term::NamedNode(named_node) => Ok(named_node.into()), Term::BlankNode(blank_node) => Ok(blank_node.into()), - Term::Literal(_) => Err(invalid_data_error( - "A literal has ben found instead of a named node", - )), + Term::Literal(_) => Err(DecoderError::Decoder { + msg: "A literal has ben found instead of a named node".to_owned(), + }), } } - fn decode_named_node(&self, encoded: EncodedTerm) -> Result { + fn decode_named_node( + &self, + encoded: EncodedTerm, + ) -> Result> { match self.decode_term(encoded)? { Term::NamedNode(named_node) => Ok(named_node), - Term::BlankNode(_) => Err(invalid_data_error( - "A blank node has been found instead of a named node", - )), - Term::Literal(_) => Err(invalid_data_error( - "A literal has ben found instead of a named node", - )), + Term::BlankNode(_) => Err(DecoderError::Decoder { + msg: "A blank node has been found instead of a named node".to_owned(), + }), + Term::Literal(_) => Err(DecoderError::Decoder { + msg: "A literal has ben found instead of a named node".to_owned(), + }), } } - fn decode_triple(&self, encoded: &EncodedQuad) -> Result { + fn decode_triple(&self, encoded: &EncodedQuad) -> Result> { Ok(Triple::new( self.decode_named_or_blank_node(encoded.subject)?, self.decode_named_node(encoded.predicate)?, @@ -1133,7 +1136,7 @@ pub(crate) trait Decoder { )) } - fn decode_quad(&self, encoded: &EncodedQuad) -> Result { + fn decode_quad(&self, encoded: &EncodedQuad) -> Result> { Ok(Quad::new( self.decode_named_or_blank_node(encoded.subject)?, self.decode_named_node(encoded.predicate)?, @@ -1147,11 +1150,11 @@ pub(crate) trait Decoder { } impl Decoder for S { - fn decode_term(&self, encoded: EncodedTerm) -> Result { + fn decode_term(&self, encoded: EncodedTerm) -> Result> { match encoded { - EncodedTerm::DefaultGraph => Err(invalid_data_error( - "The default graph tag is not a valid term", - )), + EncodedTerm::DefaultGraph => Err(DecoderError::Decoder { + msg: "The default graph tag is not a valid term".to_owned(), + }), EncodedTerm::NamedNode { iri_id } => { Ok(NamedNode::new_unchecked(get_required_str(self, iri_id)?).into()) } @@ -1193,13 +1196,52 @@ impl Decoder for S { } } -fn get_required_str(lookup: &impl StrLookup, id: StrHash) -> Result { - lookup.get_str(id).map_err(|e| e.into())?.ok_or_else(|| { - invalid_data_error(format!( - "Not able to find the string with id {:?} in the string store", - id - )) - }) +fn get_required_str( + lookup: &L, + id: StrHash, +) -> Result> { + lookup + .get_str(id) + .map_err(DecoderError::Store)? + .ok_or_else(|| DecoderError::Decoder { + msg: format!( + "Not able to find the string with id {:?} in the string store", + id + ), + }) +} + +#[derive(Debug)] +pub(crate) enum DecoderError { + Store(E), + Decoder { msg: String }, +} + +impl fmt::Display for DecoderError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Store(e) => e.fmt(f), + Self::Decoder { msg } => write!(f, "{}", msg), + } + } +} + +impl Error for DecoderError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + Self::Store(e) => Some(e), + Self::Decoder { .. } => None, + } + } +} + +impl> From> for io::Error { + fn from(e: DecoderError) -> Self { + match e { + DecoderError::Store(e) => e.into(), + DecoderError::Decoder { msg } => invalid_data_error(msg), + } + } } #[test] diff --git a/lib/src/store/rocksdb.rs b/lib/src/store/rocksdb.rs index 709bfa52..174f187a 100644 --- a/lib/src/store/rocksdb.rs +++ b/lib/src/store/rocksdb.rs @@ -127,7 +127,7 @@ impl RocksDbStore { let graph_name = graph_name.map(|g| g.into()); let store = self.clone(); self.encoded_quads_for_pattern(subject, predicate, object, graph_name) - .map(move |quad| store.decode_quad(&quad?)) + .map(move |quad| Ok(store.decode_quad(&quad?)?)) } /// Checks if this store contains a given quad diff --git a/lib/src/store/sled.rs b/lib/src/store/sled.rs index 40c56a21..4787be0f 100644 --- a/lib/src/store/sled.rs +++ b/lib/src/store/sled.rs @@ -125,7 +125,7 @@ impl SledStore { let graph_name = graph_name.map(|g| g.into()); let this = self.clone(); self.encoded_quads_for_pattern(subject, predicate, object, graph_name) - .map(move |quad| this.decode_quad(&quad?)) + .map(move |quad| Ok(this.decode_quad(&quad?)?)) } /// Checks if this store contains a given quad