Trait sophia_api::term::TTerm
source · [−]pub trait TTerm {
fn kind(&self) -> TermKind;
fn value_raw(&self) -> RawValue<'_>;
fn as_dyn(&self) -> &dyn TTerm;
fn value(&self) -> MownStr<'_> { ... }
fn datatype(&self) -> Option<SimpleIri<'_>> { ... }
fn language(&self) -> Option<&str> { ... }
fn is_absolute(&self) -> bool { ... }
}
Expand description
Trait for all RDF terms.
Sophia supports 4 kinds of terms: IRI references (absolute or relative), literals, blank nodes and variables. Note that strict RDF does not support relative IRI references nor variables.
Types representing terms, of one or more of the kinds above, can implement this trait and be used with the rest of the Sophia API.
Design considerations
The design of this trait is not as “pure” as it could have been:
-
it merges into a single trait four “kinds” which could arguably be considered as four different abstract types;
-
it is rather opinionated on how implementation should store their data internally, and has a very constrained contract (see below);
-
it relies on the “semi-abstract” methods
value_raw
, which mostly makes sense for the default implementation of other methods.
These choices were made to allow for efficient implementations of the overall API.
Contract
In addition to the specific contract of each method, any type implementing this trait must uphold the following guarantees:
-
if it implements
Hash
, it must be consistent with (or, even better, based on)term_hash()
; -
if it implements
PartialEq
, it must be consistent with (or, even better, based on)term_eq()
; -
if it implements
PartialCmp
, it must be consistent with (or, even better, based on)term_cmp
; -
if it implements
Borrow
<dyn
TTerm
+ 'a>
it must have equivalent implementations toterm_hash()
andterm_eq()
so that the contract ofBorrow
upholds with the implementations ondyn
TTerm
.
[Borrow]<dyn TTerm + 'a>
Implementing Borrow
<dyn
TTerm
+ 'a>
for a term increases the ergonomics
when the type is used as key in a HashSet
or similar.
It allows to search for keys with any implementation of the TTerm
trait, e.g.:
use sophia_term::Term;
use sophia_api::term::{SimpleIri, TTerm as _};
let t: Term<String> = Term::new_iri("http://example.com/test")?;
let mut map = HashSet::new();
map.insert(t);
let iri = SimpleIri::new("http://example.com/", Some("test"))?;
assert!(map.get(iri.as_dyn()).is_some());
Implementation
Besides the contract mentioned above, it should be noted that
someone wants to implement Borrow<dyn TTerm + 'a>
instead of
Borrow<dyn TTerm>
for a custom term. The reason is that Rust assumes that
every dyn Trait
object has a 'static
lifetime which means that
borrowing dyn TTerm
requires borrowing of the value for the 'static
lifetime. To remove this assumption implement Borrow<dyn TTerm + 'a>
instead, e.g.:
use std::borrow::Borrow;
impl<'a> Borrow<dyn TTerm + 'a> for MyTerm {
fn borrow(&self) -> &(dyn TTerm + 'a) {
self
}
}
Required methods
Return the “value” of this term, possibly split in two substrings. The second part might only be non-empty if this term is an IRI reference.
See also value
.
Note to implementors
The second part of the raw value is intended for some implementations of IRIs, storing both a “namespace” and a “suffix”. For other kinds of term, the second part must always be None.
This method ensures that all implementations of TTerm
can be turned into a trait object.
Why is this required?
After all, in most cases, passing &t
instead of t.as_dyn()
will work just as well.
The reason is that most methods of the API will accept references
to terms, as &T
where T: TTerm + ?Sized
,
and such references can not be cast to dyn TTerm
(see https://stackoverflow.com/a/57432042/1235487 for more details).
Provided methods
Return the “value” of this term, which depends on its kind:
- for an IRI reference, its value;
- for a literal, its lexical value;
- for a blank node, its local identifier;
- for a variable, its name.
Performance
The returned MownStr
is always borrowed (equivalent to a &str
),
except for IRI references where this method may allocate a new string
(depending on implementations).
If this allocation is undesirable, use value_raw
instead.
Note to implementors
Should not be overridden; must be consistent with value_raw
.
Return the datatype IRI of this term if it is a literal.
NB: all literals have a datatype,
even simple literals (whose implicit type is xsd:string
)
and language tagged strings (whose implicit type is rdf:langString
).
Return the language tag of this term if it is a language-tagged literal.
Note to implementors
The default implementation always return None
,
so unless your type may represent a language-tagged literal,
you do not need to override it.
fn is_absolute(&self) -> bool
fn is_absolute(&self) -> bool
All terms are absolute, except for:
- relative IRI references,
- literals whose datatype is a relative IRI reference.
Trait Implementations
This method returns an ordering between self
and other
values if one exists. Read more
This method tests less than (for self
and other
) and is used by the <
operator. Read more
This method tests less than or equal to (for self
and other
) and is used by the <=
operator. Read more
This method tests greater than (for self
and other
) and is used by the >
operator. Read more