Refactor parsers error types

Uses SyntaxError and ParseError everywhere
pull/567/head
Tpt 1 year ago committed by Thomas Tanon
parent 69d8ce6b4e
commit f6c8358b24
  1. 170
      lib/oxrdfxml/src/error.rs
  2. 2
      lib/oxrdfxml/src/lib.rs
  3. 155
      lib/oxrdfxml/src/parser.rs
  4. 2
      lib/oxttl/src/lib.rs
  5. 10
      lib/oxttl/src/n3.rs
  6. 8
      lib/oxttl/src/nquads.rs
  7. 8
      lib/oxttl/src/ntriples.rs
  8. 1
      lib/oxttl/src/toolkit/lexer.rs
  9. 2
      lib/oxttl/src/toolkit/mod.rs
  10. 71
      lib/oxttl/src/toolkit/parser.rs
  11. 8
      lib/oxttl/src/trig.rs
  12. 8
      lib/oxttl/src/turtle.rs
  13. 11
      lib/sparesults/src/error.rs
  14. 6
      lib/sparesults/src/xml.rs
  15. 48
      lib/src/io/error.rs

@ -4,16 +4,91 @@ use std::error::Error;
use std::sync::Arc; use std::sync::Arc;
use std::{fmt, io}; use std::{fmt, io};
/// Error that might be returned during parsing. /// Error returned during RDF/XML parsing.
///
/// It might wrap an IO error or be a parsing error.
#[derive(Debug)] #[derive(Debug)]
pub struct RdfXmlError { pub enum ParseError {
pub(crate) kind: RdfXmlErrorKind, /// I/O error during parsing (file not found...).
Io(io::Error),
/// An error in the file syntax.
Syntax(SyntaxError),
}
impl fmt::Display for ParseError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Io(e) => e.fmt(f),
Self::Syntax(e) => e.fmt(f),
}
}
}
impl Error for ParseError {
#[inline]
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Io(e) => Some(e),
Self::Syntax(e) => Some(e),
}
}
}
impl From<io::Error> for ParseError {
#[inline]
fn from(error: io::Error) -> Self {
Self::Io(error)
}
}
impl From<SyntaxError> for ParseError {
#[inline]
fn from(error: SyntaxError) -> Self {
Self::Syntax(error)
}
}
impl From<ParseError> for io::Error {
#[inline]
fn from(error: ParseError) -> Self {
match error {
ParseError::Io(error) => error,
ParseError::Syntax(error) => error.into(),
}
}
}
impl From<quick_xml::Error> for ParseError {
#[inline]
fn from(error: quick_xml::Error) -> Self {
match error {
quick_xml::Error::Io(error) => Self::Io(match Arc::try_unwrap(error) {
Ok(error) => error,
Err(error) => io::Error::new(error.kind(), error),
}),
error => Self::Syntax(SyntaxError {
inner: SyntaxErrorKind::Xml(error),
}),
}
}
}
impl From<quick_xml::events::attributes::AttrError> for ParseError {
#[inline]
fn from(error: quick_xml::events::attributes::AttrError) -> Self {
Self::Syntax(SyntaxError {
inner: SyntaxErrorKind::XmlAttribute(error),
})
}
}
/// An error in the syntax of the parsed file.
#[derive(Debug)]
pub struct SyntaxError {
pub(crate) inner: SyntaxErrorKind,
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum RdfXmlErrorKind { pub enum SyntaxErrorKind {
Xml(quick_xml::Error), Xml(quick_xml::Error),
XmlAttribute(quick_xml::events::attributes::AttrError), XmlAttribute(quick_xml::events::attributes::AttrError),
InvalidIri { InvalidIri {
@ -24,84 +99,67 @@ pub(crate) enum RdfXmlErrorKind {
tag: String, tag: String,
error: LanguageTagParseError, error: LanguageTagParseError,
}, },
Other(String), Msg {
msg: String,
},
} }
impl RdfXmlError { impl SyntaxError {
/// Builds an error from a printable error message.
#[inline]
pub(crate) fn msg(msg: impl Into<String>) -> Self { pub(crate) fn msg(msg: impl Into<String>) -> Self {
Self { Self {
kind: RdfXmlErrorKind::Other(msg.into()), inner: SyntaxErrorKind::Msg { msg: msg.into() },
} }
} }
} }
impl fmt::Display for RdfXmlError { impl fmt::Display for SyntaxError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind { match &self.inner {
RdfXmlErrorKind::Xml(error) => error.fmt(f), SyntaxErrorKind::Xml(error) => error.fmt(f),
RdfXmlErrorKind::XmlAttribute(error) => error.fmt(f), SyntaxErrorKind::XmlAttribute(error) => error.fmt(f),
RdfXmlErrorKind::InvalidIri { iri, error } => { SyntaxErrorKind::InvalidIri { iri, error } => {
write!(f, "error while parsing IRI '{}': {}", iri, error) write!(f, "error while parsing IRI '{}': {}", iri, error)
} }
RdfXmlErrorKind::InvalidLanguageTag { tag, error } => { SyntaxErrorKind::InvalidLanguageTag { tag, error } => {
write!(f, "error while parsing language tag '{}': {}", tag, error) write!(f, "error while parsing language tag '{}': {}", tag, error)
} }
RdfXmlErrorKind::Other(message) => write!(f, "{}", message), SyntaxErrorKind::Msg { msg } => f.write_str(msg),
} }
} }
} }
impl Error for RdfXmlError { impl Error for SyntaxError {
#[inline]
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
match &self.kind { match &self.inner {
RdfXmlErrorKind::Xml(error) => Some(error), SyntaxErrorKind::Xml(error) => Some(error),
RdfXmlErrorKind::XmlAttribute(error) => Some(error), SyntaxErrorKind::XmlAttribute(error) => Some(error),
RdfXmlErrorKind::InvalidIri { error, .. } => Some(error), SyntaxErrorKind::InvalidIri { error, .. } => Some(error),
RdfXmlErrorKind::InvalidLanguageTag { error, .. } => Some(error), SyntaxErrorKind::InvalidLanguageTag { error, .. } => Some(error),
RdfXmlErrorKind::Other(_) => None, SyntaxErrorKind::Msg { .. } => None,
}
}
}
impl From<quick_xml::Error> for RdfXmlError {
fn from(error: quick_xml::Error) -> Self {
Self {
kind: RdfXmlErrorKind::Xml(error),
} }
} }
} }
impl From<quick_xml::events::attributes::AttrError> for RdfXmlError { impl From<SyntaxError> for io::Error {
fn from(error: quick_xml::events::attributes::AttrError) -> Self { #[inline]
Self { fn from(error: SyntaxError) -> Self {
kind: RdfXmlErrorKind::XmlAttribute(error), match error.inner {
} SyntaxErrorKind::Xml(error) => match error {
}
}
impl From<io::Error> for RdfXmlError {
fn from(error: io::Error) -> Self {
Self {
kind: RdfXmlErrorKind::Xml(quick_xml::Error::Io(Arc::new(error))),
}
}
}
impl From<RdfXmlError> for io::Error {
fn from(error: RdfXmlError) -> Self {
match error.kind {
RdfXmlErrorKind::Xml(error) => match error {
quick_xml::Error::Io(error) => match Arc::try_unwrap(error) { quick_xml::Error::Io(error) => match Arc::try_unwrap(error) {
Ok(error) => error, Ok(error) => error,
Err(error) => io::Error::new(error.kind(), error), Err(error) => Self::new(error.kind(), error),
}, },
quick_xml::Error::UnexpectedEof(error) => { quick_xml::Error::UnexpectedEof(error) => {
io::Error::new(io::ErrorKind::UnexpectedEof, error) Self::new(io::ErrorKind::UnexpectedEof, error)
} }
error => io::Error::new(io::ErrorKind::InvalidData, error), error => Self::new(io::ErrorKind::InvalidData, error),
}, },
RdfXmlErrorKind::Other(error) => io::Error::new(io::ErrorKind::InvalidData, error), SyntaxErrorKind::Msg { msg } => Self::new(io::ErrorKind::InvalidData, msg),
_ => io::Error::new(io::ErrorKind::InvalidData, error), _ => Self::new(io::ErrorKind::InvalidData, error),
} }
} }
} }

@ -10,5 +10,5 @@ mod serializer;
mod utils; mod utils;
pub use crate::serializer::{RdfXmlSerializer, ToWriteRdfXmlWriter}; pub use crate::serializer::{RdfXmlSerializer, ToWriteRdfXmlWriter};
pub use error::RdfXmlError; pub use error::{ParseError, SyntaxError};
pub use parser::{FromReadRdfXmlReader, RdfXmlParser}; pub use parser::{FromReadRdfXmlReader, RdfXmlParser};

@ -1,4 +1,4 @@
use crate::error::{RdfXmlError, RdfXmlErrorKind}; use crate::error::{ParseError, SyntaxError, SyntaxErrorKind};
use crate::utils::*; use crate::utils::*;
use oxilangtag::LanguageTag; use oxilangtag::LanguageTag;
use oxiri::{Iri, IriParseError}; use oxiri::{Iri, IriParseError};
@ -146,9 +146,9 @@ pub struct FromReadRdfXmlReader<R: Read> {
} }
impl<R: Read> Iterator for FromReadRdfXmlReader<R> { impl<R: Read> Iterator for FromReadRdfXmlReader<R> {
type Item = Result<Triple, RdfXmlError>; type Item = Result<Triple, ParseError>;
fn next(&mut self) -> Option<Result<Triple, RdfXmlError>> { fn next(&mut self) -> Option<Result<Triple, ParseError>> {
loop { loop {
if let Some(triple) = self.results.pop() { if let Some(triple) = self.results.pop() {
return Some(Ok(triple)); return Some(Ok(triple));
@ -168,7 +168,7 @@ impl<R: Read> FromReadRdfXmlReader<R> {
self.reader.reader.buffer_position() self.reader.reader.buffer_position()
} }
fn parse_step(&mut self) -> Result<(), RdfXmlError> { fn parse_step(&mut self) -> Result<(), ParseError> {
self.reader_buffer.clear(); self.reader_buffer.clear();
let event = self let event = self
.reader .reader
@ -295,7 +295,7 @@ struct RdfXmlReader<R: BufRead> {
} }
impl<R: BufRead> RdfXmlReader<R> { impl<R: BufRead> RdfXmlReader<R> {
fn parse_event(&mut self, event: Event, results: &mut Vec<Triple>) -> Result<(), RdfXmlError> { fn parse_event(&mut self, event: Event, results: &mut Vec<Triple>) -> Result<(), ParseError> {
match event { match event {
Event::Start(event) => self.parse_start_event(&event, results), Event::Start(event) => self.parse_start_event(&event, results),
Event::End(event) => self.parse_end_event(&event, results), Event::End(event) => self.parse_end_event(&event, results),
@ -306,9 +306,10 @@ impl<R: BufRead> RdfXmlReader<R> {
Event::Decl(decl) => { Event::Decl(decl) => {
if let Some(encoding) = decl.encoding() { if let Some(encoding) = decl.encoding() {
if !is_utf8(&encoding?) { if !is_utf8(&encoding?) {
return Err(RdfXmlError::msg( return Err(SyntaxError::msg(
"Only UTF-8 is supported by the RDF/XML parser", "Only UTF-8 is supported by the RDF/XML parser",
)); )
.into());
} }
} }
Ok(()) Ok(())
@ -321,7 +322,7 @@ impl<R: BufRead> RdfXmlReader<R> {
} }
} }
fn parse_doctype(&mut self, dt: &BytesText<'_>) -> Result<(), RdfXmlError> { fn parse_doctype(&mut self, dt: &BytesText<'_>) -> Result<(), ParseError> {
// we extract entities // we extract entities
for input in self for input in self
.reader .reader
@ -333,20 +334,20 @@ impl<R: BufRead> RdfXmlReader<R> {
if let Some(input) = input.strip_prefix("!ENTITY") { if let Some(input) = input.strip_prefix("!ENTITY") {
let input = input.trim_start().strip_prefix('%').unwrap_or(input); let input = input.trim_start().strip_prefix('%').unwrap_or(input);
let (entity_name, input) = input.trim_start().split_once(|c: char| c.is_ascii_whitespace()).ok_or_else(|| { let (entity_name, input) = input.trim_start().split_once(|c: char| c.is_ascii_whitespace()).ok_or_else(|| {
RdfXmlError::msg( SyntaxError::msg(
"<!ENTITY declarations should contain both an entity name and an entity value", "<!ENTITY declarations should contain both an entity name and an entity value",
) )
})?; })?;
let input = input.trim_start().strip_prefix('\"').ok_or_else(|| { let input = input.trim_start().strip_prefix('\"').ok_or_else(|| {
RdfXmlError::msg("<!ENTITY values should be enclosed in double quotes") SyntaxError::msg("<!ENTITY values should be enclosed in double quotes")
})?; })?;
let (entity_value, input) = input.split_once('"').ok_or_else(|| { let (entity_value, input) = input.split_once('"').ok_or_else(|| {
RdfXmlError::msg( SyntaxError::msg(
"<!ENTITY declarations values should be enclosed in double quotes", "<!ENTITY declarations values should be enclosed in double quotes",
) )
})?; })?;
input.trim_start().strip_prefix('>').ok_or_else(|| { input.trim_start().strip_prefix('>').ok_or_else(|| {
RdfXmlError::msg("<!ENTITY declarations values should end with >") SyntaxError::msg("<!ENTITY declarations values should end with >")
})?; })?;
// Resolves custom entities within the current entity definition. // Resolves custom entities within the current entity definition.
@ -363,7 +364,7 @@ impl<R: BufRead> RdfXmlReader<R> {
&mut self, &mut self,
event: &BytesStart<'_>, event: &BytesStart<'_>,
results: &mut Vec<Triple>, results: &mut Vec<Triple>,
) -> Result<(), RdfXmlError> { ) -> Result<(), ParseError> {
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)]
enum RdfXmlParseType { enum RdfXmlParseType {
Default, Default,
@ -425,15 +426,15 @@ impl<R: BufRead> RdfXmlReader<R> {
let tag = self.convert_attribute(&attribute)?; let tag = self.convert_attribute(&attribute)?;
language = Some( language = Some(
LanguageTag::parse(tag.to_ascii_lowercase()) LanguageTag::parse(tag.to_ascii_lowercase())
.map_err(|error| RdfXmlError { .map_err(|error| SyntaxError {
kind: RdfXmlErrorKind::InvalidLanguageTag { tag, error }, inner: SyntaxErrorKind::InvalidLanguageTag { tag, error },
})? })?
.into_inner(), .into_inner(),
); );
} else if attribute.key.as_ref() == b"xml:base" { } else if attribute.key.as_ref() == b"xml:base" {
let iri = self.convert_attribute(&attribute)?; let iri = self.convert_attribute(&attribute)?;
base_iri = Some(Iri::parse(iri.clone()).map_err(|error| RdfXmlError { base_iri = Some(Iri::parse(iri.clone()).map_err(|error| SyntaxError {
kind: RdfXmlErrorKind::InvalidIri { iri, error }, inner: SyntaxErrorKind::InvalidIri { iri, error },
})?) })?)
} else { } else {
// We ignore other xml attributes // We ignore other xml attributes
@ -443,28 +444,31 @@ impl<R: BufRead> RdfXmlReader<R> {
if *attribute_url == *RDF_ID { if *attribute_url == *RDF_ID {
let mut id = self.convert_attribute(&attribute)?; let mut id = self.convert_attribute(&attribute)?;
if !is_nc_name(&id) { if !is_nc_name(&id) {
return Err(RdfXmlError::msg(format!( return Err(SyntaxError::msg(format!(
"{} is not a valid rdf:ID value", "{} is not a valid rdf:ID value",
&id &id
))); ))
.into());
} }
id.insert(0, '#'); id.insert(0, '#');
id_attr = Some(id); id_attr = Some(id);
} else if *attribute_url == *RDF_BAG_ID { } else if *attribute_url == *RDF_BAG_ID {
let bag_id = self.convert_attribute(&attribute)?; let bag_id = self.convert_attribute(&attribute)?;
if !is_nc_name(&bag_id) { if !is_nc_name(&bag_id) {
return Err(RdfXmlError::msg(format!( return Err(SyntaxError::msg(format!(
"{} is not a valid rdf:bagID value", "{} is not a valid rdf:bagID value",
&bag_id &bag_id
))); ))
.into());
} }
} else if *attribute_url == *RDF_NODE_ID { } else if *attribute_url == *RDF_NODE_ID {
let id = self.convert_attribute(&attribute)?; let id = self.convert_attribute(&attribute)?;
if !is_nc_name(&id) { if !is_nc_name(&id) {
return Err(RdfXmlError::msg(format!( return Err(SyntaxError::msg(format!(
"{} is not a valid rdf:nodeID value", "{} is not a valid rdf:nodeID value",
&id &id
))); ))
.into());
} }
node_id_attr = Some(BlankNode::new_unchecked(id)); node_id_attr = Some(BlankNode::new_unchecked(id));
} else if *attribute_url == *RDF_ABOUT { } else if *attribute_url == *RDF_ABOUT {
@ -483,14 +487,15 @@ impl<R: BufRead> RdfXmlReader<R> {
} else if attribute_url == rdf::TYPE.as_str() { } else if attribute_url == rdf::TYPE.as_str() {
type_attr = Some(attribute); type_attr = Some(attribute);
} else if RESERVED_RDF_ATTRIBUTES.contains(&&*attribute_url) { } else if RESERVED_RDF_ATTRIBUTES.contains(&&*attribute_url) {
return Err(RdfXmlError::msg(format!( return Err(SyntaxError::msg(format!(
"{} is not a valid attribute", "{} is not a valid attribute",
&attribute_url &attribute_url
))); ))
.into());
} else { } else {
property_attrs.push(( property_attrs.push((
NamedNode::new(attribute_url.clone()).map_err(|error| RdfXmlError { NamedNode::new(attribute_url.clone()).map_err(|error| SyntaxError {
kind: RdfXmlErrorKind::InvalidIri { inner: SyntaxErrorKind::InvalidIri {
iri: attribute_url, iri: attribute_url,
error, error,
}, },
@ -506,10 +511,11 @@ impl<R: BufRead> RdfXmlReader<R> {
Some(iri) => { Some(iri) => {
let iri = resolve(&base_iri, iri)?; let iri = resolve(&base_iri, iri)?;
if self.known_rdf_id.contains(iri.as_str()) { if self.known_rdf_id.contains(iri.as_str()) {
return Err(RdfXmlError::msg(format!( return Err(SyntaxError::msg(format!(
"{} has already been used as rdf:ID value", "{} has already been used as rdf:ID value",
&iri &iri
))); ))
.into());
} }
self.known_rdf_id.insert(iri.as_str().into()); self.known_rdf_id.insert(iri.as_str().into());
Some(iri) Some(iri)
@ -547,9 +553,9 @@ impl<R: BufRead> RdfXmlReader<R> {
panic!("ParseTypeLiteralPropertyElt production children should never be considered as a RDF/XML content") panic!("ParseTypeLiteralPropertyElt production children should never be considered as a RDF/XML content")
} }
None => { None => {
return Err(RdfXmlError::msg( return Err(
"No state in the stack: the XML is not balanced", SyntaxError::msg("No state in the stack: the XML is not balanced").into(),
)); );
} }
}; };
@ -558,14 +564,15 @@ impl<R: BufRead> RdfXmlReader<R> {
if *tag_name == *RDF_RDF { if *tag_name == *RDF_RDF {
RdfXmlState::Rdf { base_iri, language } RdfXmlState::Rdf { base_iri, language }
} else if RESERVED_RDF_ELEMENTS.contains(&&*tag_name) { } else if RESERVED_RDF_ELEMENTS.contains(&&*tag_name) {
return Err(RdfXmlError::msg(format!( return Err(SyntaxError::msg(format!(
"Invalid node element tag name: {}", "Invalid node element tag name: {}",
&tag_name &tag_name
))); ))
.into());
} else { } else {
Self::build_node_elt( Self::build_node_elt(
NamedNode::new(tag_name.clone()).map_err(|error| RdfXmlError { NamedNode::new(tag_name.clone()).map_err(|error| SyntaxError {
kind: RdfXmlErrorKind::InvalidIri { inner: SyntaxErrorKind::InvalidIri {
iri: tag_name, iri: tag_name,
error, error,
}, },
@ -583,14 +590,15 @@ impl<R: BufRead> RdfXmlReader<R> {
} }
RdfXmlNextProduction::NodeElt => { RdfXmlNextProduction::NodeElt => {
if RESERVED_RDF_ELEMENTS.contains(&&*tag_name) { if RESERVED_RDF_ELEMENTS.contains(&&*tag_name) {
return Err(RdfXmlError::msg(format!( return Err(SyntaxError::msg(format!(
"Invalid property element tag name: {}", "Invalid property element tag name: {}",
&tag_name &tag_name
))); ))
.into());
} }
Self::build_node_elt( Self::build_node_elt(
NamedNode::new(tag_name.clone()).map_err(|error| RdfXmlError { NamedNode::new(tag_name.clone()).map_err(|error| SyntaxError {
kind: RdfXmlErrorKind::InvalidIri { inner: SyntaxErrorKind::InvalidIri {
iri: tag_name, iri: tag_name,
error, error,
}, },
@ -608,10 +616,10 @@ impl<R: BufRead> RdfXmlReader<R> {
RdfXmlNextProduction::PropertyElt { subject } => { RdfXmlNextProduction::PropertyElt { subject } => {
let iri = if *tag_name == *RDF_LI { let iri = if *tag_name == *RDF_LI {
let Some(RdfXmlState::NodeElt { li_counter, .. }) = self.state.last_mut() else { let Some(RdfXmlState::NodeElt { li_counter, .. }) = self.state.last_mut() else {
return Err(RdfXmlError::msg(format!( return Err(SyntaxError::msg(format!(
"Invalid property element tag name: {}", "Invalid property element tag name: {}",
&tag_name &tag_name
))); )).into());
}; };
*li_counter += 1; *li_counter += 1;
NamedNode::new_unchecked(format!( NamedNode::new_unchecked(format!(
@ -621,13 +629,14 @@ impl<R: BufRead> RdfXmlReader<R> {
} else if RESERVED_RDF_ELEMENTS.contains(&&*tag_name) } else if RESERVED_RDF_ELEMENTS.contains(&&*tag_name)
|| *tag_name == *RDF_DESCRIPTION || *tag_name == *RDF_DESCRIPTION
{ {
return Err(RdfXmlError::msg(format!( return Err(SyntaxError::msg(format!(
"Invalid property element tag name: {}", "Invalid property element tag name: {}",
&tag_name &tag_name
))); ))
.into());
} else { } else {
NamedNode::new(tag_name.clone()).map_err(|error| RdfXmlError { NamedNode::new(tag_name.clone()).map_err(|error| SyntaxError {
kind: RdfXmlErrorKind::InvalidIri { inner: SyntaxErrorKind::InvalidIri {
iri: tag_name, iri: tag_name,
error, error,
}, },
@ -644,7 +653,7 @@ impl<R: BufRead> RdfXmlReader<R> {
(Some(resource_attr), None) => Subject::from(resource_attr), (Some(resource_attr), None) => Subject::from(resource_attr),
(None, Some(node_id_attr)) => node_id_attr.into(), (None, Some(node_id_attr)) => node_id_attr.into(),
(None, None) => BlankNode::default().into(), (None, None) => BlankNode::default().into(),
(Some(_), Some(_)) => return Err(RdfXmlError::msg("Not both rdf:resource and rdf:nodeID could be set at the same time")) (Some(_), Some(_)) => return Err(SyntaxError::msg("Not both rdf:resource and rdf:nodeID could be set at the same time").into())
}; };
Self::emit_property_attrs(&object, property_attrs, &language, results); Self::emit_property_attrs(&object, property_attrs, &language, results);
if let Some(type_attr) = type_attr { if let Some(type_attr) = type_attr {
@ -711,7 +720,7 @@ impl<R: BufRead> RdfXmlReader<R> {
&mut self, &mut self,
event: &BytesEnd<'_>, event: &BytesEnd<'_>,
results: &mut Vec<Triple>, results: &mut Vec<Triple>,
) -> Result<(), RdfXmlError> { ) -> Result<(), ParseError> {
//Literal case //Literal case
if self.in_literal_depth > 0 { if self.in_literal_depth > 0 {
if let Some(RdfXmlState::ParseTypeLiteralPropertyElt { writer, .. }) = if let Some(RdfXmlState::ParseTypeLiteralPropertyElt { writer, .. }) =
@ -731,7 +740,7 @@ impl<R: BufRead> RdfXmlReader<R> {
Ok(()) Ok(())
} }
fn parse_text_event(&mut self, event: &BytesText<'_>) -> Result<(), RdfXmlError> { fn parse_text_event(&mut self, event: &BytesText<'_>) -> Result<(), ParseError> {
let text = event.unescape_with(|e| self.resolve_entity(e))?.to_string(); let text = event.unescape_with(|e| self.resolve_entity(e))?.to_string();
match self.state.last_mut() { match self.state.last_mut() {
Some(RdfXmlState::PropertyElt { object, .. }) => { Some(RdfXmlState::PropertyElt { object, .. }) => {
@ -748,21 +757,18 @@ impl<R: BufRead> RdfXmlReader<R> {
if event.iter().copied().all(is_whitespace) { if event.iter().copied().all(is_whitespace) {
Ok(()) Ok(())
} else { } else {
Err(RdfXmlError::msg(format!( Err(SyntaxError::msg(format!("Unexpected text event: '{}'", text)).into())
"Unexpected text event: '{}'",
text
)))
} }
} }
} }
} }
fn resolve_tag_name(&self, qname: QName<'_>) -> Result<String, RdfXmlError> { fn resolve_tag_name(&self, qname: QName<'_>) -> Result<String, ParseError> {
let (namespace, local_name) = self.reader.resolve_element(qname); let (namespace, local_name) = self.reader.resolve_element(qname);
self.resolve_ns_name(namespace, local_name) self.resolve_ns_name(namespace, local_name)
} }
fn resolve_attribute_name(&self, qname: QName<'_>) -> Result<String, RdfXmlError> { fn resolve_attribute_name(&self, qname: QName<'_>) -> Result<String, ParseError> {
let (namespace, local_name) = self.reader.resolve_attribute(qname); let (namespace, local_name) = self.reader.resolve_attribute(qname);
self.resolve_ns_name(namespace, local_name) self.resolve_ns_name(namespace, local_name)
} }
@ -771,7 +777,7 @@ impl<R: BufRead> RdfXmlReader<R> {
&self, &self,
namespace: ResolveResult, namespace: ResolveResult,
local_name: LocalName<'_>, local_name: LocalName<'_>,
) -> Result<String, RdfXmlError> { ) -> Result<String, ParseError> {
match namespace { match namespace {
ResolveResult::Bound(ns) => { ResolveResult::Bound(ns) => {
let mut value = Vec::with_capacity(ns.as_ref().len() + local_name.as_ref().len()); let mut value = Vec::with_capacity(ns.as_ref().len() + local_name.as_ref().len());
@ -784,12 +790,13 @@ impl<R: BufRead> RdfXmlReader<R> {
.to_string()) .to_string())
} }
ResolveResult::Unbound => { ResolveResult::Unbound => {
Err(RdfXmlError::msg("XML namespaces are required in RDF/XML")) Err(SyntaxError::msg("XML namespaces are required in RDF/XML").into())
} }
ResolveResult::Unknown(v) => Err(RdfXmlError::msg(format!( ResolveResult::Unknown(v) => Err(SyntaxError::msg(format!(
"Unknown prefix {}:", "Unknown prefix {}:",
self.reader.decoder().decode(&v)? self.reader.decoder().decode(&v)?
))), ))
.into()),
} }
} }
@ -804,24 +811,24 @@ impl<R: BufRead> RdfXmlReader<R> {
type_attr: Option<NamedNode>, type_attr: Option<NamedNode>,
property_attrs: Vec<(NamedNode, String)>, property_attrs: Vec<(NamedNode, String)>,
results: &mut Vec<Triple>, results: &mut Vec<Triple>,
) -> Result<RdfXmlState, RdfXmlError> { ) -> Result<RdfXmlState, SyntaxError> {
let subject = match (id_attr, node_id_attr, about_attr) { let subject = match (id_attr, node_id_attr, about_attr) {
(Some(id_attr), None, None) => Subject::from(id_attr), (Some(id_attr), None, None) => Subject::from(id_attr),
(None, Some(node_id_attr), None) => node_id_attr.into(), (None, Some(node_id_attr), None) => node_id_attr.into(),
(None, None, Some(about_attr)) => about_attr.into(), (None, None, Some(about_attr)) => about_attr.into(),
(None, None, None) => BlankNode::default().into(), (None, None, None) => BlankNode::default().into(),
(Some(_), Some(_), _) => { (Some(_), Some(_), _) => {
return Err(RdfXmlError::msg( return Err(SyntaxError::msg(
"Not both rdf:ID and rdf:nodeID could be set at the same time", "Not both rdf:ID and rdf:nodeID could be set at the same time",
)) ))
} }
(_, Some(_), Some(_)) => { (_, Some(_), Some(_)) => {
return Err(RdfXmlError::msg( return Err(SyntaxError::msg(
"Not both rdf:nodeID and rdf:resource could be set at the same time", "Not both rdf:nodeID and rdf:resource could be set at the same time",
)) ))
} }
(Some(_), _, Some(_)) => { (Some(_), _, Some(_)) => {
return Err(RdfXmlError::msg( return Err(SyntaxError::msg(
"Not both rdf:ID and rdf:resource could be set at the same time", "Not both rdf:ID and rdf:resource could be set at the same time",
)) ))
} }
@ -870,7 +877,7 @@ impl<R: BufRead> RdfXmlReader<R> {
&mut self, &mut self,
state: RdfXmlState, state: RdfXmlState,
results: &mut Vec<Triple>, results: &mut Vec<Triple>,
) -> Result<(), RdfXmlError> { ) -> Result<(), SyntaxError> {
match state { match state {
RdfXmlState::PropertyElt { RdfXmlState::PropertyElt {
iri, iri,
@ -925,7 +932,7 @@ impl<R: BufRead> RdfXmlReader<R> {
if emit { if emit {
let object = writer.into_inner(); let object = writer.into_inner();
if object.is_empty() { if object.is_empty() {
return Err(RdfXmlError::msg(format!( return Err(SyntaxError::msg(format!(
"No value found for rdf:XMLLiteral value of property {}", "No value found for rdf:XMLLiteral value of property {}",
iri iri
))); )));
@ -935,7 +942,7 @@ impl<R: BufRead> RdfXmlReader<R> {
iri, iri,
Literal::new_typed_literal( Literal::new_typed_literal(
str::from_utf8(&object).map_err(|_| { str::from_utf8(&object).map_err(|_| {
RdfXmlError::msg("The XML literal is not in valid UTF-8".to_owned()) SyntaxError::msg("The XML literal is not in valid UTF-8".to_owned())
})?, })?,
rdf::XML_LITERAL, rdf::XML_LITERAL,
), ),
@ -1008,7 +1015,7 @@ impl<R: BufRead> RdfXmlReader<R> {
} }
} }
fn convert_attribute(&self, attribute: &Attribute) -> Result<String, RdfXmlError> { fn convert_attribute(&self, attribute: &Attribute) -> Result<String, ParseError> {
Ok(attribute Ok(attribute
.decode_and_unescape_value_with(&self.reader, |e| self.resolve_entity(e))? .decode_and_unescape_value_with(&self.reader, |e| self.resolve_entity(e))?
.to_string()) .to_string())
@ -1018,8 +1025,8 @@ impl<R: BufRead> RdfXmlReader<R> {
&self, &self,
base_iri: &Option<Iri<String>>, base_iri: &Option<Iri<String>>,
attribute: &Attribute<'_>, attribute: &Attribute<'_>,
) -> Result<NamedNode, RdfXmlError> { ) -> Result<NamedNode, ParseError> {
resolve(base_iri, self.convert_attribute(attribute)?) Ok(resolve(base_iri, self.convert_attribute(attribute)?)?)
} }
fn resolve_entity(&self, e: &str) -> Option<&str> { fn resolve_entity(&self, e: &str) -> Option<&str> {
@ -1027,13 +1034,13 @@ impl<R: BufRead> RdfXmlReader<R> {
} }
} }
fn resolve(base_iri: &Option<Iri<String>>, relative_iri: String) -> Result<NamedNode, RdfXmlError> { fn resolve(base_iri: &Option<Iri<String>>, relative_iri: String) -> Result<NamedNode, SyntaxError> {
if let Some(base_iri) = base_iri { if let Some(base_iri) = base_iri {
Ok(NamedNode::new_unchecked( Ok(NamedNode::new_unchecked(
base_iri base_iri
.resolve(&relative_iri) .resolve(&relative_iri)
.map_err(|error| RdfXmlError { .map_err(|error| SyntaxError {
kind: RdfXmlErrorKind::InvalidIri { inner: SyntaxErrorKind::InvalidIri {
iri: relative_iri, iri: relative_iri,
error, error,
}, },
@ -1041,8 +1048,8 @@ fn resolve(base_iri: &Option<Iri<String>>, relative_iri: String) -> Result<Named
.into_inner(), .into_inner(),
)) ))
} else { } else {
NamedNode::new(relative_iri.clone()).map_err(|error| RdfXmlError { NamedNode::new(relative_iri.clone()).map_err(|error| SyntaxError {
kind: RdfXmlErrorKind::InvalidIri { inner: SyntaxErrorKind::InvalidIri {
iri: relative_iri, iri: relative_iri,
error, error,
}, },

@ -17,7 +17,7 @@ pub mod turtle;
pub use crate::n3::N3Parser; pub use crate::n3::N3Parser;
pub use crate::nquads::{NQuadsParser, NQuadsSerializer}; pub use crate::nquads::{NQuadsParser, NQuadsSerializer};
pub use crate::ntriples::{NTriplesParser, NTriplesSerializer}; pub use crate::ntriples::{NTriplesParser, NTriplesSerializer};
pub use crate::toolkit::{ParseError, ParseOrIoError}; pub use crate::toolkit::{ParseError, SyntaxError};
pub use crate::trig::{TriGParser, TriGSerializer}; pub use crate::trig::{TriGParser, TriGSerializer};
pub use crate::turtle::{TurtleParser, TurtleSerializer}; pub use crate::turtle::{TurtleParser, TurtleSerializer};

@ -2,9 +2,9 @@
use crate::lexer::{resolve_local_name, N3Lexer, N3LexerMode, N3LexerOptions, N3Token}; use crate::lexer::{resolve_local_name, N3Lexer, N3LexerMode, N3LexerOptions, N3Token};
use crate::toolkit::{ use crate::toolkit::{
FromReadIterator, Lexer, ParseError, Parser, RuleRecognizer, RuleRecognizerError, FromReadIterator, Lexer, Parser, RuleRecognizer, RuleRecognizerError, SyntaxError,
}; };
use crate::{ParseOrIoError, MAX_BUFFER_SIZE, MIN_BUFFER_SIZE}; use crate::{ParseError, MAX_BUFFER_SIZE, MIN_BUFFER_SIZE};
use oxiri::{Iri, IriParseError}; use oxiri::{Iri, IriParseError};
use oxrdf::vocab::{rdf, xsd}; use oxrdf::vocab::{rdf, xsd};
#[cfg(feature = "rdf-star")] #[cfg(feature = "rdf-star")]
@ -336,9 +336,9 @@ pub struct FromReadN3Reader<R: Read> {
} }
impl<R: Read> Iterator for FromReadN3Reader<R> { impl<R: Read> Iterator for FromReadN3Reader<R> {
type Item = Result<N3Quad, ParseOrIoError>; type Item = Result<N3Quad, ParseError>;
fn next(&mut self) -> Option<Result<N3Quad, ParseOrIoError>> { fn next(&mut self) -> Option<Result<N3Quad, ParseError>> {
self.inner.next() self.inner.next()
} }
} }
@ -406,7 +406,7 @@ impl LowLevelN3Reader {
/// ///
/// Returns [`None`] if the parsing is finished or more data is required. /// Returns [`None`] if the parsing is finished or more data is required.
/// If it is the case more data should be fed using [`extend_from_slice`](Self::extend_from_slice). /// If it is the case more data should be fed using [`extend_from_slice`](Self::extend_from_slice).
pub fn read_next(&mut self) -> Option<Result<N3Quad, ParseError>> { pub fn read_next(&mut self) -> Option<Result<N3Quad, SyntaxError>> {
self.parser.read_next() self.parser.read_next()
} }
} }

@ -1,7 +1,7 @@
//! A [N-Quads](https://www.w3.org/TR/n-quads/) streaming parser implemented by [`NQuadsParser`]. //! A [N-Quads](https://www.w3.org/TR/n-quads/) streaming parser implemented by [`NQuadsParser`].
use crate::line_formats::NQuadsRecognizer; use crate::line_formats::NQuadsRecognizer;
use crate::toolkit::{FromReadIterator, ParseError, ParseOrIoError, Parser}; use crate::toolkit::{FromReadIterator, ParseError, Parser, SyntaxError};
use oxrdf::{Quad, QuadRef}; use oxrdf::{Quad, QuadRef};
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
@ -157,9 +157,9 @@ pub struct FromReadNQuadsReader<R: Read> {
} }
impl<R: Read> Iterator for FromReadNQuadsReader<R> { impl<R: Read> Iterator for FromReadNQuadsReader<R> {
type Item = Result<Quad, ParseOrIoError>; type Item = Result<Quad, ParseError>;
fn next(&mut self) -> Option<Result<Quad, ParseOrIoError>> { fn next(&mut self) -> Option<Result<Quad, ParseError>> {
self.inner.next() self.inner.next()
} }
} }
@ -226,7 +226,7 @@ impl LowLevelNQuadsReader {
/// ///
/// Returns [`None`] if the parsing is finished or more data is required. /// Returns [`None`] if the parsing is finished or more data is required.
/// If it is the case more data should be fed using [`extend_from_slice`](Self::extend_from_slice). /// If it is the case more data should be fed using [`extend_from_slice`](Self::extend_from_slice).
pub fn read_next(&mut self) -> Option<Result<Quad, ParseError>> { pub fn read_next(&mut self) -> Option<Result<Quad, SyntaxError>> {
self.parser.read_next() self.parser.read_next()
} }
} }

@ -2,7 +2,7 @@
//! and a serializer implemented by [`NTriplesSerializer`]. //! and a serializer implemented by [`NTriplesSerializer`].
use crate::line_formats::NQuadsRecognizer; use crate::line_formats::NQuadsRecognizer;
use crate::toolkit::{FromReadIterator, ParseError, ParseOrIoError, Parser}; use crate::toolkit::{FromReadIterator, ParseError, Parser, SyntaxError};
use oxrdf::{Triple, TripleRef}; use oxrdf::{Triple, TripleRef};
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
@ -158,9 +158,9 @@ pub struct FromReadNTriplesReader<R: Read> {
} }
impl<R: Read> Iterator for FromReadNTriplesReader<R> { impl<R: Read> Iterator for FromReadNTriplesReader<R> {
type Item = Result<Triple, ParseOrIoError>; type Item = Result<Triple, ParseError>;
fn next(&mut self) -> Option<Result<Triple, ParseOrIoError>> { fn next(&mut self) -> Option<Result<Triple, ParseError>> {
Some(self.inner.next()?.map(Into::into)) Some(self.inner.next()?.map(Into::into))
} }
} }
@ -227,7 +227,7 @@ impl LowLevelNTriplesReader {
/// ///
/// Returns [`None`] if the parsing is finished or more data is required. /// Returns [`None`] if the parsing is finished or more data is required.
/// If it is the case more data should be fed using [`extend_from_slice`](Self::extend_from_slice). /// If it is the case more data should be fed using [`extend_from_slice`](Self::extend_from_slice).
pub fn read_next(&mut self) -> Option<Result<Triple, ParseError>> { pub fn read_next(&mut self) -> Option<Result<Triple, SyntaxError>> {
Some(self.parser.read_next()?.map(Into::into)) Some(self.parser.read_next()?.map(Into::into))
} }
} }

@ -92,6 +92,7 @@ impl<R: TokenRecognizer> Lexer<R> {
self.end = self.data.len(); self.end = self.data.len();
} }
#[inline]
pub fn end(&mut self) { pub fn end(&mut self) {
self.is_ending = true; self.is_ending = true;
} }

@ -7,5 +7,5 @@ mod parser;
pub use self::lexer::{Lexer, LexerError, TokenRecognizer, TokenRecognizerError}; pub use self::lexer::{Lexer, LexerError, TokenRecognizer, TokenRecognizerError};
pub use self::parser::{ pub use self::parser::{
FromReadIterator, ParseError, ParseOrIoError, Parser, RuleRecognizer, RuleRecognizerError, FromReadIterator, ParseError, Parser, RuleRecognizer, RuleRecognizerError, SyntaxError,
}; };

@ -60,18 +60,20 @@ impl<RR: RuleRecognizer> Parser<RR> {
self.lexer.extend_from_slice(other) self.lexer.extend_from_slice(other)
} }
#[inline]
pub fn end(&mut self) { pub fn end(&mut self) {
self.lexer.end() self.lexer.end()
} }
#[inline]
pub fn is_end(&self) -> bool { pub fn is_end(&self) -> bool {
self.state.is_none() && self.results.is_empty() && self.errors.is_empty() self.state.is_none() && self.results.is_empty() && self.errors.is_empty()
} }
pub fn read_next(&mut self) -> Option<Result<RR::Output, ParseError>> { pub fn read_next(&mut self) -> Option<Result<RR::Output, SyntaxError>> {
loop { loop {
if let Some(error) = self.errors.pop() { if let Some(error) = self.errors.pop() {
return Some(Err(ParseError { return Some(Err(SyntaxError {
position: self.position.clone(), position: self.position.clone(),
message: error.message, message: error.message,
})); }));
@ -114,33 +116,37 @@ impl<RR: RuleRecognizer> Parser<RR> {
} }
} }
/// An error from parsing. /// An error in the syntax of the parsed file.
/// ///
/// It is composed of a message and a byte range in the input. /// It is composed of a message and a byte range in the input.
#[derive(Debug)] #[derive(Debug)]
pub struct ParseError { pub struct SyntaxError {
position: Range<usize>, position: Range<usize>,
message: String, message: String,
} }
impl ParseError { impl SyntaxError {
/// The invalid byte range in the input. /// The invalid byte range in the input.
#[inline]
pub fn position(&self) -> Range<usize> { pub fn position(&self) -> Range<usize> {
self.position.clone() self.position.clone()
} }
/// The error message. /// The error message.
#[inline]
pub fn message(&self) -> &str { pub fn message(&self) -> &str {
&self.message &self.message
} }
/// Converts this error to an error message. /// Converts this error to an error message.
#[inline]
pub fn into_message(self) -> String { pub fn into_message(self) -> String {
self.message self.message
} }
} }
impl fmt::Display for ParseError { impl fmt::Display for SyntaxError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.position.start + 1 == self.position.end { if self.position.start + 1 == self.position.end {
write!( write!(
@ -158,15 +164,17 @@ impl fmt::Display for ParseError {
} }
} }
impl Error for ParseError {} impl Error for SyntaxError {}
impl From<ParseError> for io::Error { impl From<SyntaxError> for io::Error {
fn from(error: ParseError) -> Self { #[inline]
fn from(error: SyntaxError) -> Self {
io::Error::new(io::ErrorKind::InvalidData, error) io::Error::new(io::ErrorKind::InvalidData, error)
} }
} }
impl From<LexerError> for ParseError { impl From<LexerError> for SyntaxError {
#[inline]
fn from(e: LexerError) -> Self { fn from(e: LexerError) -> Self {
Self { Self {
position: e.position(), position: e.position(),
@ -175,48 +183,57 @@ impl From<LexerError> for ParseError {
} }
} }
/// The union of [`ParseError`] and [`std::io::Error`]. /// A parsing error.
///
/// It is the union of [`SyntaxError`] and [`std::io::Error`].
#[derive(Debug)] #[derive(Debug)]
pub enum ParseOrIoError { pub enum ParseError {
Parse(ParseError), /// I/O error during parsing (file not found...).
Io(io::Error), Io(io::Error),
/// An error in the file syntax.
Syntax(SyntaxError),
} }
impl fmt::Display for ParseOrIoError { impl fmt::Display for ParseError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::Parse(e) => e.fmt(f),
Self::Io(e) => e.fmt(f), Self::Io(e) => e.fmt(f),
Self::Syntax(e) => e.fmt(f),
} }
} }
} }
impl Error for ParseOrIoError { impl Error for ParseError {
#[inline]
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(match self { Some(match self {
Self::Parse(e) => e,
Self::Io(e) => e, Self::Io(e) => e,
Self::Syntax(e) => e,
}) })
} }
} }
impl From<ParseError> for ParseOrIoError { impl From<SyntaxError> for ParseError {
fn from(error: ParseError) -> Self { #[inline]
Self::Parse(error) fn from(error: SyntaxError) -> Self {
Self::Syntax(error)
} }
} }
impl From<io::Error> for ParseOrIoError { impl From<io::Error> for ParseError {
#[inline]
fn from(error: io::Error) -> Self { fn from(error: io::Error) -> Self {
Self::Io(error) Self::Io(error)
} }
} }
impl From<ParseOrIoError> for io::Error { impl From<ParseError> for io::Error {
fn from(error: ParseOrIoError) -> Self { #[inline]
fn from(error: ParseError) -> Self {
match error { match error {
ParseOrIoError::Parse(e) => e.into(), ParseError::Syntax(e) => e.into(),
ParseOrIoError::Io(e) => e, ParseError::Io(e) => e,
} }
} }
} }
@ -227,12 +244,12 @@ pub struct FromReadIterator<R: Read, RR: RuleRecognizer> {
} }
impl<R: Read, RR: RuleRecognizer> Iterator for FromReadIterator<R, RR> { impl<R: Read, RR: RuleRecognizer> Iterator for FromReadIterator<R, RR> {
type Item = Result<RR::Output, ParseOrIoError>; type Item = Result<RR::Output, ParseError>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while !self.parser.is_end() { while !self.parser.is_end() {
if let Some(result) = self.parser.read_next() { if let Some(result) = self.parser.read_next() {
return Some(result.map_err(ParseOrIoError::Parse)); return Some(result.map_err(ParseError::Syntax));
} }
if let Err(e) = self.parser.lexer.extend_from_read(&mut self.read) { if let Err(e) = self.parser.lexer.extend_from_read(&mut self.read) {
return Some(Err(e.into())); return Some(Err(e.into()));

@ -1,7 +1,7 @@
//! A [TriG](https://www.w3.org/TR/trig/) streaming parser implemented by [`TriGParser`]. //! A [TriG](https://www.w3.org/TR/trig/) streaming parser implemented by [`TriGParser`].
use crate::terse::TriGRecognizer; use crate::terse::TriGRecognizer;
use crate::toolkit::{FromReadIterator, ParseError, ParseOrIoError, Parser}; use crate::toolkit::{FromReadIterator, ParseError, Parser, SyntaxError};
use oxiri::{Iri, IriParseError}; use oxiri::{Iri, IriParseError};
use oxrdf::{vocab::xsd, GraphName, NamedNode, Quad, QuadRef, Subject, TermRef}; use oxrdf::{vocab::xsd, GraphName, NamedNode, Quad, QuadRef, Subject, TermRef};
use std::collections::HashMap; use std::collections::HashMap;
@ -186,9 +186,9 @@ pub struct FromReadTriGReader<R: Read> {
} }
impl<R: Read> Iterator for FromReadTriGReader<R> { impl<R: Read> Iterator for FromReadTriGReader<R> {
type Item = Result<Quad, ParseOrIoError>; type Item = Result<Quad, ParseError>;
fn next(&mut self) -> Option<Result<Quad, ParseOrIoError>> { fn next(&mut self) -> Option<Result<Quad, ParseError>> {
self.inner.next() self.inner.next()
} }
} }
@ -255,7 +255,7 @@ impl LowLevelTriGReader {
/// ///
/// Returns [`None`] if the parsing is finished or more data is required. /// Returns [`None`] if the parsing is finished or more data is required.
/// If it is the case more data should be fed using [`extend_from_slice`](Self::extend_from_slice). /// If it is the case more data should be fed using [`extend_from_slice`](Self::extend_from_slice).
pub fn read_next(&mut self) -> Option<Result<Quad, ParseError>> { pub fn read_next(&mut self) -> Option<Result<Quad, SyntaxError>> {
self.parser.read_next() self.parser.read_next()
} }
} }

@ -1,7 +1,7 @@
//! A [Turtle](https://www.w3.org/TR/turtle/) streaming parser implemented by [`TurtleParser`]. //! A [Turtle](https://www.w3.org/TR/turtle/) streaming parser implemented by [`TurtleParser`].
use crate::terse::TriGRecognizer; use crate::terse::TriGRecognizer;
use crate::toolkit::{FromReadIterator, ParseError, ParseOrIoError, Parser}; use crate::toolkit::{FromReadIterator, ParseError, Parser, SyntaxError};
use crate::trig::{LowLevelTriGWriter, ToWriteTriGWriter}; use crate::trig::{LowLevelTriGWriter, ToWriteTriGWriter};
use crate::TriGSerializer; use crate::TriGSerializer;
use oxiri::{Iri, IriParseError}; use oxiri::{Iri, IriParseError};
@ -187,9 +187,9 @@ pub struct FromReadTurtleReader<R: Read> {
} }
impl<R: Read> Iterator for FromReadTurtleReader<R> { impl<R: Read> Iterator for FromReadTurtleReader<R> {
type Item = Result<Triple, ParseOrIoError>; type Item = Result<Triple, ParseError>;
fn next(&mut self) -> Option<Result<Triple, ParseOrIoError>> { fn next(&mut self) -> Option<Result<Triple, ParseError>> {
Some(self.inner.next()?.map(Into::into)) Some(self.inner.next()?.map(Into::into))
} }
} }
@ -256,7 +256,7 @@ impl LowLevelTurtleReader {
/// ///
/// Returns [`None`] if the parsing is finished or more data is required. /// Returns [`None`] if the parsing is finished or more data is required.
/// If it is the case more data should be fed using [`extend_from_slice`](Self::extend_from_slice). /// If it is the case more data should be fed using [`extend_from_slice`](Self::extend_from_slice).
pub fn read_next(&mut self) -> Option<Result<Triple, ParseError>> { pub fn read_next(&mut self) -> Option<Result<Triple, SyntaxError>> {
Some(self.parser.read_next()?.map(Into::into)) Some(self.parser.read_next()?.map(Into::into))
} }
} }

@ -1,5 +1,6 @@
use oxrdf::TermParseError; use oxrdf::TermParseError;
use std::error::Error; use std::error::Error;
use std::sync::Arc;
use std::{fmt, io}; use std::{fmt, io};
/// Error returned during SPARQL result formats format parsing. /// Error returned during SPARQL result formats format parsing.
@ -59,7 +60,10 @@ impl From<quick_xml::Error> for ParseError {
#[inline] #[inline]
fn from(error: quick_xml::Error) -> Self { fn from(error: quick_xml::Error) -> Self {
match error { match error {
quick_xml::Error::Io(error) => Self::Io(io::Error::new(error.kind(), error)), quick_xml::Error::Io(error) => Self::Io(match Arc::try_unwrap(error) {
Ok(error) => error,
Err(error) => io::Error::new(error.kind(), error),
}),
error => Self::Syntax(SyntaxError { error => Self::Syntax(SyntaxError {
inner: SyntaxErrorKind::Xml(error), inner: SyntaxErrorKind::Xml(error),
}), }),
@ -117,7 +121,10 @@ impl From<SyntaxError> for io::Error {
fn from(error: SyntaxError) -> Self { fn from(error: SyntaxError) -> Self {
match error.inner { match error.inner {
SyntaxErrorKind::Xml(error) => match error { SyntaxErrorKind::Xml(error) => match error {
quick_xml::Error::Io(error) => Self::new(error.kind(), error), quick_xml::Error::Io(error) => match Arc::try_unwrap(error) {
Ok(error) => error,
Err(error) => Self::new(error.kind(), error),
},
quick_xml::Error::UnexpectedEof(error) => { quick_xml::Error::UnexpectedEof(error) => {
Self::new(io::ErrorKind::UnexpectedEof, error) Self::new(io::ErrorKind::UnexpectedEof, error)
} }

@ -10,6 +10,7 @@ use std::borrow::Cow;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::io::{self, BufRead, Write}; use std::io::{self, BufRead, Write};
use std::str; use std::str;
use std::sync::Arc;
pub fn write_boolean_xml_result<W: Write>(sink: W, value: bool) -> io::Result<W> { pub fn write_boolean_xml_result<W: Write>(sink: W, value: bool) -> io::Result<W> {
do_write_boolean_xml_result(sink, value).map_err(map_xml_error) do_write_boolean_xml_result(sink, value).map_err(map_xml_error)
@ -604,7 +605,10 @@ fn decode<'a, T>(
fn map_xml_error(error: quick_xml::Error) -> io::Error { fn map_xml_error(error: quick_xml::Error) -> io::Error {
match error { match error {
quick_xml::Error::Io(error) => io::Error::new(error.kind(), error), quick_xml::Error::Io(error) => match Arc::try_unwrap(error) {
Ok(error) => error,
Err(error) => io::Error::new(error.kind(), error),
},
quick_xml::Error::UnexpectedEof(_) => io::Error::new(io::ErrorKind::UnexpectedEof, error), quick_xml::Error::UnexpectedEof(_) => io::Error::new(io::ErrorKind::UnexpectedEof, error),
_ => io::Error::new(io::ErrorKind::InvalidData, error), _ => io::Error::new(io::ErrorKind::InvalidData, error),
} }

@ -1,5 +1,4 @@
use oxiri::IriParseError; use oxiri::IriParseError;
use oxrdfxml::RdfXmlError;
use std::error::Error; use std::error::Error;
use std::{fmt, io}; use std::{fmt, io};
@ -44,39 +43,40 @@ impl Error for ParseError {
} }
} }
impl From<oxttl::ParseError> for ParseError { impl From<oxttl::SyntaxError> for SyntaxError {
#[inline] #[inline]
fn from(error: oxttl::ParseError) -> Self { fn from(error: oxttl::SyntaxError) -> Self {
Self::Syntax(SyntaxError { SyntaxError {
inner: SyntaxErrorKind::Turtle(error), inner: SyntaxErrorKind::Turtle(error),
}) }
} }
} }
impl From<oxttl::ParseOrIoError> for ParseError { impl From<oxttl::ParseError> for ParseError {
#[inline] #[inline]
fn from(error: oxttl::ParseOrIoError) -> Self { fn from(error: oxttl::ParseError) -> Self {
match error { match error {
oxttl::ParseOrIoError::Parse(e) => e.into(), oxttl::ParseError::Syntax(e) => Self::Syntax(e.into()),
oxttl::ParseOrIoError::Io(e) => e.into(), oxttl::ParseError::Io(e) => Self::Io(e),
} }
} }
} }
#[allow(clippy::fallible_impl_from)] impl From<oxrdfxml::SyntaxError> for SyntaxError {
impl From<RdfXmlError> for ParseError {
#[inline] #[inline]
fn from(error: RdfXmlError) -> Self { fn from(error: oxrdfxml::SyntaxError) -> Self {
let error = io::Error::from(error); SyntaxError {
if error.get_ref().map_or( inner: SyntaxErrorKind::RdfXml(error),
false, }
<(dyn Error + Send + Sync + 'static)>::is::<RdfXmlError>, }
) { }
Self::Syntax(SyntaxError {
inner: SyntaxErrorKind::RdfXml(*error.into_inner().unwrap().downcast().unwrap()), impl From<oxrdfxml::ParseError> for ParseError {
}) #[inline]
} else { fn from(error: oxrdfxml::ParseError) -> Self {
Self::Io(error) match error {
oxrdfxml::ParseError::Syntax(e) => Self::Syntax(e.into()),
oxrdfxml::ParseError::Io(e) => Self::Io(e),
} }
} }
} }
@ -113,8 +113,8 @@ pub struct SyntaxError {
#[derive(Debug)] #[derive(Debug)]
enum SyntaxErrorKind { enum SyntaxErrorKind {
Turtle(oxttl::ParseError), Turtle(oxttl::SyntaxError),
RdfXml(RdfXmlError), RdfXml(oxrdfxml::SyntaxError),
InvalidBaseIri { iri: String, error: IriParseError }, InvalidBaseIri { iri: String, error: IriParseError },
} }

Loading…
Cancel
Save