chore: use TryFrom syntax

pull/795/head
Jesse Wright 1 year ago
parent 1be3e0ac10
commit ecc4e5c047
  1. 30
      lib/oxrdf/src/blank_node.rs
  2. 15
      lib/oxrdf/src/cast_error.rs
  3. 2
      lib/oxrdf/src/lib.rs
  4. 30
      lib/oxrdf/src/literal.rs
  5. 31
      lib/oxrdf/src/named_node.rs
  6. 111
      lib/oxrdf/src/triple.rs

@ -2,6 +2,7 @@ use rand::random;
use std::io::Write; use std::io::Write;
use std::{fmt, str}; use std::{fmt, str};
use crate::cast_error::{TermCastError, TermCastErrorKind};
use crate::Term; use crate::Term;
/// An owned RDF [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). /// An owned RDF [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node).
@ -104,12 +105,19 @@ impl fmt::Display for BlankNode {
} }
} }
impl From<Term> for Option<BlankNode> { impl TryFrom<Term> for BlankNode {
type Error = TermCastError;
#[inline] #[inline]
fn from(term: Term) -> Self { fn try_from(term: Term) -> Result<Self, Self::Error> {
match term { if let Term::BlankNode(node) = term {
Term::BlankNode(node) => Some(node), Ok(node)
_ => None, } else {
Err(TermCastErrorKind::Msg(format!(
"Cannot convert a term to a blank node: {}",
term
))
.into())
} }
} }
} }
@ -376,14 +384,14 @@ mod tests {
#[test] #[test]
fn casting() { fn casting() {
let bnode: Option<BlankNode> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).into(); let bnode: Result<BlankNode, TermCastError> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).try_into();
assert_eq!(bnode, Some(BlankNode::new_from_unique_id(0x42))); assert_eq!(bnode.unwrap(), BlankNode::new_from_unique_id(0x42));
let literal: Option<BlankNode> = Term::Literal(Literal::new_simple_literal("Hello World!")).into(); let literal: Result<BlankNode, TermCastError> = Term::Literal(Literal::new_simple_literal("Hello World!")).try_into();
assert_eq!(literal, None); assert_eq!(literal.is_err(), true);
let named_node: Option<BlankNode> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).into(); let named_node: Result<BlankNode, TermCastError> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).try_into();
assert_eq!(named_node, None); assert_eq!(named_node.is_err(), true);
} }
#[test] #[test]

@ -0,0 +1,15 @@
use std::error::Error;
/// An error return if some content in the database is corrupted.
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct TermCastError(#[from] pub TermCastErrorKind);
/// An error return if some content in the database is corrupted.
#[derive(Debug, thiserror::Error)]
pub enum TermCastErrorKind {
#[error("{0}")]
Msg(String),
#[error("{0}")]
Other(#[source] Box<dyn Error + Send + Sync + 'static>),
}

@ -13,6 +13,7 @@ mod named_node;
mod parser; mod parser;
mod triple; mod triple;
mod variable; mod variable;
mod cast_error;
pub mod vocab; pub mod vocab;
pub use crate::blank_node::{BlankNode, BlankNodeIdParseError, BlankNodeRef}; pub use crate::blank_node::{BlankNode, BlankNodeIdParseError, BlankNodeRef};
@ -26,5 +27,6 @@ pub use crate::triple::{
SubjectRef, Term, TermRef, Triple, TripleRef, SubjectRef, Term, TermRef, Triple, TripleRef,
}; };
pub use crate::variable::{Variable, VariableNameParseError, VariableRef}; pub use crate::variable::{Variable, VariableNameParseError, VariableRef};
pub use crate::cast_error::{TermCastError, TermCastErrorKind};
pub use oxilangtag::LanguageTagParseError; pub use oxilangtag::LanguageTagParseError;
pub use oxiri::IriParseError; pub use oxiri::IriParseError;

@ -1,4 +1,5 @@
use crate::named_node::NamedNode; use crate::named_node::NamedNode;
use crate::cast_error::{TermCastError, TermCastErrorKind};
use crate::vocab::{rdf, xsd}; use crate::vocab::{rdf, xsd};
use crate::{NamedNodeRef, Term}; use crate::{NamedNodeRef, Term};
use oxilangtag::{LanguageTag, LanguageTagParseError}; use oxilangtag::{LanguageTag, LanguageTagParseError};
@ -161,12 +162,19 @@ impl fmt::Display for Literal {
} }
} }
impl From<Term> for Option<Literal> { impl TryFrom<Term> for Literal {
type Error = TermCastError;
#[inline] #[inline]
fn from(term: Term) -> Self { fn try_from(term: Term) -> Result<Self, Self::Error> {
match term { if let Term::Literal(node) = term {
Term::Literal(literal) => Some(literal), Ok(node)
_ => None, } else {
Err(TermCastErrorKind::Msg(format!(
"Cannot convert term to a literal: {}",
term
))
.into())
} }
} }
} }
@ -674,14 +682,14 @@ mod tests {
#[test] #[test]
fn casting() { fn casting() {
let literal: Option<Literal> = Term::Literal(Literal::new_simple_literal("Hello World!")).into(); let literal: Result<Literal, TermCastError> = Term::Literal(Literal::new_simple_literal("Hello World!")).try_into();
assert_eq!(literal, Some(Literal::new_simple_literal("Hello World!"))); assert_eq!(literal.unwrap(), Literal::new_simple_literal("Hello World!"));
let bnode: Option<Literal> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).into(); let bnode: Result<Literal, TermCastError> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).try_into();
assert_eq!(bnode, None); assert_eq!(bnode.is_err(), true);
let named_node: Option<Literal> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).into(); let named_node: Result<Literal, TermCastError> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).try_into();
assert_eq!(named_node, None); assert_eq!(named_node.is_err(), true);
} }
#[test] #[test]

@ -2,7 +2,7 @@ use oxiri::{Iri, IriParseError};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::fmt; use std::fmt;
use crate::Term; use crate::{cast_error::TermCastErrorKind, Term, TermCastError};
/// An owned RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri). /// An owned RDF [IRI](https://www.w3.org/TR/rdf11-concepts/#dfn-iri).
/// ///
@ -219,12 +219,19 @@ impl PartialOrd<NamedNodeRef<'_>> for NamedNode {
} }
} }
impl From<Term> for Option<NamedNode> { impl TryFrom<Term> for NamedNode {
type Error = TermCastError;
#[inline] #[inline]
fn from(term: Term) -> Self { fn try_from(term: Term) -> Result<Self, Self::Error> {
match term { if let Term::NamedNode(node) = term {
Term::NamedNode(node) => Some(node), Ok(node)
_ => None, } else {
Err(TermCastErrorKind::Msg(format!(
"Cannot convert term to a named node: {}",
term
))
.into())
} }
} }
} }
@ -257,13 +264,13 @@ mod tests {
#[test] #[test]
fn casting() { fn casting() {
let named_node: Option<NamedNode> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).into(); let named_node: Result<NamedNode, TermCastError> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).try_into();
assert_eq!(named_node, Some(NamedNode::new("http://example.org/test").unwrap())); assert_eq!(named_node.unwrap(), NamedNode::new("http://example.org/test").unwrap());
let literal: Option<NamedNode> = Term::Literal(Literal::new_simple_literal("Hello World!")).into(); let literal: Result<NamedNode, TermCastError> = Term::Literal(Literal::new_simple_literal("Hello World!")).try_into();
assert_eq!(literal, None); assert_eq!(literal.is_err(), true);
let bnode: Option<NamedNode> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).into(); let bnode: Result<NamedNode, TermCastError> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).try_into();
assert_eq!(bnode, None); assert_eq!(bnode.is_err(), true);
} }
} }

@ -1,7 +1,8 @@
use crate::blank_node::BlankNode; use crate::blank_node::BlankNode;
use crate::cast_error::TermCastErrorKind;
use crate::literal::Literal; use crate::literal::Literal;
use crate::named_node::NamedNode; use crate::named_node::NamedNode;
use crate::{BlankNodeRef, LiteralRef, NamedNodeRef}; use crate::{BlankNodeRef, LiteralRef, NamedNodeRef, TermCastError};
use std::fmt; use std::fmt;
/// The owned union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). /// The owned union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri) and [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node).
@ -195,15 +196,21 @@ impl fmt::Display for Subject {
} }
} }
impl From<Term> for Option<Subject> { impl TryFrom<Term> for Subject {
type Error = TermCastError;
#[inline] #[inline]
fn from(term: Term) -> Self { fn try_from(term: Term) -> Result<Self, Self::Error> {
match term { match term {
Term::NamedNode(node) => Some(Subject::NamedNode(node)), Term::NamedNode(node) => Ok(Subject::NamedNode(node)),
Term::BlankNode(node) => Some(Subject::BlankNode(node)), Term::BlankNode(node) => Ok(Subject::BlankNode(node)),
#[cfg(feature = "rdf-star")] #[cfg(feature = "rdf-star")]
Term::Triple(triple) => Some(Subject::Triple(triple)), Term::Triple(triple) => Ok(Subject::Triple(triple)),
Term::Literal(_) => None Term::Literal(literal) => Err(TermCastErrorKind::Msg(format!(
"Cannot convert a literal to a subject: {}",
literal
))
.into()),
} }
} }
} }
@ -753,22 +760,16 @@ impl Triple {
/// Builds an RDF [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple). /// Builds an RDF [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple).
#[inline] #[inline]
pub fn new_maybe( pub fn new_from_terms(
subject: impl Into<Term>, subject: impl Into<Term>,
predicate: impl Into<Term>, predicate: impl Into<Term>,
object: impl Into<Term>, object: impl Into<Term>,
) -> Option<Self> { ) -> Result<Self, TermCastError> {
match ( Ok(Self {
Into::<Option<Subject>>::into(Into::<Term>::into(subject)), subject: TryInto::<Subject>::try_into(subject.into())?,
Into::<Option<NamedNode>>::into(Into::<Term>::into(predicate)), predicate: TryInto::<NamedNode>::try_into(predicate.into())?,
Into::<Option<Term>>::into(Into::<Term>::into(object))) { object: object.into(),
(Some(subject), Some(predicate), Some(object)) => Some(Self { })
subject,
predicate,
object,
}),
_ => None,
}
} }
/// Encodes that this triple is in an [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset). /// Encodes that this triple is in an [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset).
@ -800,13 +801,19 @@ impl fmt::Display for Triple {
} }
#[cfg(feature = "rdf-star")] #[cfg(feature = "rdf-star")]
impl From<Term> for Option<Box<Triple>> { impl TryFrom<Term> for Box<Triple> {
type Error = TermCastError;
#[inline] #[inline]
fn from(term: Term) -> Self { fn try_from(term: Term) -> Result<Self, Self::Error> {
match term { if let Term::Triple(node) = term {
#[cfg(feature = "rdf-star")] Ok(node)
Term::Triple(triple) => Some(triple), } else {
_ => None, Err(TermCastErrorKind::Msg(format!(
"Cannot convert term to a triple: {}",
term
))
.into())
} }
} }
} }
@ -1286,42 +1293,42 @@ mod tests {
}; };
let triple_box = Box::new(triple); let triple_box = Box::new(triple);
let t: Option<Box<Triple>> = Term::Triple(triple_box.clone()).into(); let t: Result<Box<Triple>, TermCastError> = Term::Triple(triple_box.clone()).try_into();
assert_eq!(t, Some(triple_box.clone())); assert_eq!(t.unwrap(), triple_box.clone());
let literal: Option<Box<Triple>> = Term::Literal(Literal::new_simple_literal("Hello World!")).into(); let literal: Result<Box<Triple>, TermCastError> = Term::Literal(Literal::new_simple_literal("Hello World!")).try_into();
assert_eq!(literal, None); assert_eq!(literal.is_err(), true);
let bnode: Option<Box<Triple>> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).into(); let bnode: Result<Box<Triple>, TermCastError> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).try_into();
assert_eq!(bnode, None); assert_eq!(bnode.is_err(), true);
let named_node: Option<Box<Triple>> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).into(); let named_node: Result<Box<Triple>, TermCastError> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).try_into();
assert_eq!(named_node, None); assert_eq!(named_node.is_err(), true);
} }
#[test] #[test]
fn constructing_triple() { fn constructing_triple() {
use super::*; use super::*;
let optional_triple = Triple::new_maybe( let optional_triple = Triple::new_from_terms(
Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()), Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()),
Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()), Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()),
Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()) Term::NamedNode(NamedNode::new("http://example.org/test").unwrap())
); );
let optional_triple_2 = Triple::new_maybe( let optional_triple_2 = Triple::new_from_terms(
NamedNode::new("http://example.org/test").unwrap(), NamedNode::new("http://example.org/test").unwrap(),
NamedNode::new("http://example.org/test").unwrap(), NamedNode::new("http://example.org/test").unwrap(),
NamedNode::new("http://example.org/test").unwrap() NamedNode::new("http://example.org/test").unwrap()
); );
let bad_triple = Triple::new_maybe( let bad_triple = Triple::new_from_terms(
Term::BlankNode(BlankNode::new("abc123").unwrap()), Term::BlankNode(BlankNode::new("abc123").unwrap()),
Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()), Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()),
Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()) Term::NamedNode(NamedNode::new("http://example.org/test").unwrap())
); );
let bad_triple_2 = Triple::new_maybe( let bad_triple_2 = Triple::new_from_terms(
BlankNode::new("abc123").unwrap(), BlankNode::new("abc123").unwrap(),
NamedNode::new("http://example.org/test").unwrap(), NamedNode::new("http://example.org/test").unwrap(),
NamedNode::new("http://example.org/test").unwrap() NamedNode::new("http://example.org/test").unwrap()
@ -1339,11 +1346,13 @@ mod tests {
NamedNode::new("http://example.org/test").unwrap() NamedNode::new("http://example.org/test").unwrap()
); );
assert_eq!(optional_triple, Some(triple)); let unwrapped = optional_triple.unwrap();
assert_eq!(optional_triple, Some(triple_2.clone()));
assert_eq!(optional_triple_2, Some(triple_2)); assert_eq!(unwrapped, triple);
assert_eq!(bad_triple, None); assert_eq!(unwrapped, triple_2.clone());
assert_eq!(bad_triple_2, None); assert_eq!(optional_triple_2.unwrap(), triple_2);
assert_eq!(bad_triple.is_err(), true);
assert_eq!(bad_triple_2.is_err(), true);
} }
#[test] #[test]
@ -1355,16 +1364,16 @@ mod tests {
}; };
let triple_box = Box::new(triple); let triple_box = Box::new(triple);
let t: Option<Subject> = Term::Triple(triple_box.clone()).into(); let t: Result<Subject, TermCastError> = Term::Triple(triple_box.clone()).try_into();
assert_eq!(t, Some(Subject::Triple(triple_box.clone()))); assert_eq!(t.unwrap(), Subject::Triple(triple_box.clone()));
let literal: Option<Subject> = Term::Literal(Literal::new_simple_literal("Hello World!")).into(); let literal: Result<Subject, TermCastError> = Term::Literal(Literal::new_simple_literal("Hello World!")).try_into();
assert_eq!(literal, None); assert_eq!(literal.is_err(), true);
let bnode: Option<Subject> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).into(); let bnode: Result<Subject, TermCastError> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).try_into();
assert_eq!(bnode, Some(Subject::BlankNode(BlankNode::new_from_unique_id(0x42)))); assert_eq!(bnode.unwrap(), Subject::BlankNode(BlankNode::new_from_unique_id(0x42)));
let named_node: Option<Subject> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).into(); let named_node: Result<Subject, TermCastError> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).try_into();
assert_eq!(named_node, Some(Subject::NamedNode(NamedNode::new("http://example.org/test").unwrap()))); assert_eq!(named_node.unwrap(), Subject::NamedNode(NamedNode::new("http://example.org/test").unwrap()));
} }
} }

Loading…
Cancel
Save