feat: add term casting

pull/795/head
Jesse Wright 1 year ago
parent e48b268fc5
commit b888d019cb
  1. 26
      lib/oxrdf/src/blank_node.rs
  2. 27
      lib/oxrdf/src/literal.rs
  3. 33
      lib/oxrdf/src/named_node.rs
  4. 122
      lib/oxrdf/src/triple.rs

@ -2,6 +2,8 @@ use rand::random;
use std::io::Write; use std::io::Write;
use std::{fmt, str}; use std::{fmt, str};
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).
/// ///
/// The common way to create a new blank node is to use the [`BlankNode::default()`] function. /// The common way to create a new blank node is to use the [`BlankNode::default()`] function.
@ -102,6 +104,16 @@ impl fmt::Display for BlankNode {
} }
} }
impl From<Term> for Option<BlankNode> {
#[inline]
fn from(term: Term) -> Self {
match term {
Term::BlankNode(node) => Some(node),
_ => None,
}
}
}
impl Default for BlankNode { impl Default for BlankNode {
/// Builds a new RDF [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) with a unique id. /// Builds a new RDF [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) with a unique id.
#[inline] #[inline]
@ -352,6 +364,8 @@ pub struct BlankNodeIdParseError;
mod tests { mod tests {
#![allow(clippy::panic_in_result_fn)] #![allow(clippy::panic_in_result_fn)]
use crate::{Literal, NamedNode};
use super::*; use super::*;
#[test] #[test]
@ -360,6 +374,18 @@ mod tests {
assert_eq!(b.as_str(), "42"); assert_eq!(b.as_str(), "42");
} }
#[test]
fn casting() {
let bnode: Option<BlankNode> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).into();
assert_eq!(bnode, Some(BlankNode::new_from_unique_id(0x42)));
let literal: Option<BlankNode> = Term::Literal(Literal::new_simple_literal("Hello World!")).into();
assert_eq!(literal, None);
let named_node: Option<BlankNode> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).into();
assert_eq!(named_node, None);
}
#[test] #[test]
fn as_str_full() { fn as_str_full() {
let b = BlankNode::new_from_unique_id(0x7777_6666_5555_4444_3333_2222_1111_0000); let b = BlankNode::new_from_unique_id(0x7777_6666_5555_4444_3333_2222_1111_0000);

@ -1,6 +1,6 @@
use crate::named_node::NamedNode; use crate::named_node::NamedNode;
use crate::vocab::{rdf, xsd}; use crate::vocab::{rdf, xsd};
use crate::NamedNodeRef; use crate::{NamedNodeRef, Term};
use oxilangtag::{LanguageTag, LanguageTagParseError}; use oxilangtag::{LanguageTag, LanguageTagParseError};
#[cfg(feature = "oxsdatatypes")] #[cfg(feature = "oxsdatatypes")]
use oxsdatatypes::*; use oxsdatatypes::*;
@ -161,6 +161,16 @@ impl fmt::Display for Literal {
} }
} }
impl From<Term> for Option<Literal> {
#[inline]
fn from(term: Term) -> Self {
match term {
Term::Literal(literal) => Some(literal),
_ => None,
}
}
}
impl<'a> From<&'a str> for Literal { impl<'a> From<&'a str> for Literal {
#[inline] #[inline]
fn from(value: &'a str) -> Self { fn from(value: &'a str) -> Self {
@ -637,6 +647,8 @@ pub fn print_quoted_str(string: &str, f: &mut impl Write) -> fmt::Result {
mod tests { mod tests {
#![allow(clippy::panic_in_result_fn)] #![allow(clippy::panic_in_result_fn)]
use crate::BlankNode;
use super::*; use super::*;
#[test] #[test]
@ -659,6 +671,19 @@ mod tests {
); );
} }
#[test]
fn casting() {
let literal: Option<Literal> = Term::Literal(Literal::new_simple_literal("Hello World!")).into();
assert_eq!(literal, Some(Literal::new_simple_literal("Hello World!")));
let bnode: Option<Literal> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).into();
assert_eq!(bnode, None);
let named_node: Option<Literal> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).into();
assert_eq!(named_node, None);
}
#[test] #[test]
fn test_float_format() { fn test_float_format() {
assert_eq!("INF", Literal::from(f32::INFINITY).value()); assert_eq!("INF", Literal::from(f32::INFINITY).value());

@ -2,6 +2,8 @@ use oxiri::{Iri, IriParseError};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::fmt; use std::fmt;
use crate::Term;
/// 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).
/// ///
/// The default string formatter is returning an N-Triples, Turtle, and SPARQL compatible representation: /// The default string formatter is returning an N-Triples, Turtle, and SPARQL compatible representation:
@ -217,6 +219,16 @@ impl PartialOrd<NamedNodeRef<'_>> for NamedNode {
} }
} }
impl From<Term> for Option<NamedNode> {
#[inline]
fn from(term: Term) -> Self {
match term {
Term::NamedNode(node) => Some(node),
_ => None,
}
}
}
impl From<Iri<String>> for NamedNode { impl From<Iri<String>> for NamedNode {
#[inline] #[inline]
fn from(iri: Iri<String>) -> Self { fn from(iri: Iri<String>) -> Self {
@ -234,3 +246,24 @@ impl<'a> From<Iri<&'a str>> for NamedNodeRef<'a> {
} }
} }
} }
#[cfg(test)]
mod tests {
#![allow(clippy::panic_in_result_fn)]
use crate::{Literal, BlankNode};
use super::*;
#[test]
fn casting() {
let named_node: Option<NamedNode> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).into();
assert_eq!(named_node, Some(NamedNode::new("http://example.org/test").unwrap()));
let literal: Option<NamedNode> = Term::Literal(Literal::new_simple_literal("Hello World!")).into();
assert_eq!(literal, None);
let bnode: Option<NamedNode> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).into();
assert_eq!(bnode, None);
}
}

@ -195,6 +195,19 @@ impl fmt::Display for Subject {
} }
} }
impl From<Term> for Option<Subject> {
#[inline]
fn from(term: Term) -> Self {
match term {
Term::NamedNode(node) => Some(Subject::NamedNode(node)),
Term::BlankNode(node) => Some(Subject::BlankNode(node)),
#[cfg(feature = "rdf-star")]
Term::Triple(triple) => Some(Subject::Triple(triple)),
Term::Literal(_) => None
}
}
}
impl From<NamedNode> for Subject { impl From<NamedNode> for Subject {
#[inline] #[inline]
fn from(node: NamedNode) -> Self { fn from(node: NamedNode) -> Self {
@ -738,6 +751,23 @@ impl Triple {
} }
} }
/// Builds an RDF [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple).
#[inline]
pub fn new_maybe(
subject: impl Into<Option<Subject>>,
predicate: impl Into<Option<NamedNode>>,
object: impl Into<Option<Term>>,
) -> Option<Self> {
match (subject.into(), predicate.into(), 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).
#[inline] #[inline]
pub fn in_graph(self, graph_name: impl Into<GraphName>) -> Quad { pub fn in_graph(self, graph_name: impl Into<GraphName>) -> Quad {
@ -766,6 +796,18 @@ impl fmt::Display for Triple {
} }
} }
#[cfg(feature = "rdf-star")]
impl From<Term> for Option<Box<Triple>> {
#[inline]
fn from(term: Term) -> Self {
match term {
#[cfg(feature = "rdf-star")]
Term::Triple(triple) => Some(triple),
_ => None,
}
}
}
/// A borrowed [RDF triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple). /// A borrowed [RDF triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple).
/// ///
/// The default string formatter is returning an N-Triples, Turtle, and SPARQL compatible representation: /// The default string formatter is returning an N-Triples, Turtle, and SPARQL compatible representation:
@ -1224,3 +1266,83 @@ impl<'a> From<QuadRef<'a>> for Quad {
quad.into_owned() quad.into_owned()
} }
} }
#[cfg(test)]
mod tests {
#![allow(clippy::panic_in_result_fn)]
use crate::{Literal, BlankNode};
use super::*;
#[test]
#[cfg(feature = "rdf-star")]
fn casting_triple() {
let triple = Triple {
subject: NamedNode::new("http://example.org/s").unwrap().into(),
predicate: NamedNode::new("http://example.org/p").unwrap(),
object: NamedNode::new("http://example.org/o").unwrap().into(),
};
let triple_box = Box::new(triple);
let t: Option<Box<Triple>> = Term::Triple(triple_box.clone()).into();
assert_eq!(t, Some(triple_box.clone()));
let literal: Option<Box<Triple>> = Term::Literal(Literal::new_simple_literal("Hello World!")).into();
assert_eq!(literal, None);
let bnode: Option<Box<Triple>> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).into();
assert_eq!(bnode, None);
let named_node: Option<Box<Triple>> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).into();
assert_eq!(named_node, None);
}
#[test]
#[cfg(feature = "rdf-star")]
fn constructing_triple() {
let optional_triple = Triple::new_maybe(
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 = Triple::new_maybe(
Term::BlankNode(BlankNode::new("abc123").unwrap()),
Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()),
Term::NamedNode(NamedNode::new("http://example.org/test").unwrap())
);
let triple: Triple = Triple::new(
Subject::NamedNode(NamedNode::new("http://example.org/test").unwrap()),
NamedNode::new("http://example.org/test").unwrap(),
Term::NamedNode(NamedNode::new("http://example.org/test").unwrap())
);
assert_eq!(optional_triple, Some(triple));
assert_eq!(bad_triple, None);
}
#[test]
#[cfg(feature = "rdf-star")]
fn casting_subject() {
let triple = Triple {
subject: NamedNode::new("http://example.org/s").unwrap().into(),
predicate: NamedNode::new("http://example.org/p").unwrap(),
object: NamedNode::new("http://example.org/o").unwrap().into(),
};
let triple_box = Box::new(triple);
let t: Option<Subject> = Term::Triple(triple_box.clone()).into();
assert_eq!(t, Some(Subject::Triple(triple_box.clone())));
let literal: Option<Subject> = Term::Literal(Literal::new_simple_literal("Hello World!")).into();
assert_eq!(literal, None);
let bnode: Option<Subject> = Term::BlankNode(BlankNode::new_from_unique_id(0x42)).into();
assert_eq!(bnode, Some(Subject::BlankNode(BlankNode::new_from_unique_id(0x42))));
let named_node: Option<Subject> = Term::NamedNode(NamedNode::new("http://example.org/test").unwrap()).into();
assert_eq!(named_node, Some(Subject::NamedNode(NamedNode::new("http://example.org/test").unwrap())));
}
}

Loading…
Cancel
Save