-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathiri_datavalue.rs
116 lines (101 loc) · 3.85 KB
/
iri_datavalue.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//! This module provides implementations [DataValue]s that represent IRIs.
//!
//! In essence, IRIs are represented by Unicode strings, but they are considered
//! distinct from elements of [ValueDomain::PlainString]. Moreover, some IRI-specific
//! requirements and normalizations might apply.
use super::{DataValue, ValueDomain};
/// Physical representation of a Unicode string using String.
///
/// SPARQL states: "Pairs of IRIs are ordered by comparing them as simple literals.",
/// which means that their string representations should be compared according to the
/// [Unicode codepoint collation](https://www.w3.org/TR/xpath-functions/#dt-codepoint-collation).
/// As [specified in the rust documentation](https://doc.rust-lang.org/std/primitive.str.html#impl-Ord-for-str),
/// this is also the default order for strings in rust.
#[repr(transparent)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct IriDataValue(String);
impl IriDataValue {
/// Constructor. It is currently not checked whether the IRI is valid according to applicable specifications
/// and standards -- we just treat it like a string.
pub fn new(iri: String) -> Self {
IriDataValue(iri)
}
/// Nemo considers "plain" identifiers, such as a constant name `a` or a predicate name `edge`, as simple forms
/// of relative IRIs. This function checks if the given IRI is guaranteed to be of this form.
///
/// Not all relative IRIs are "names" in this sense, since, e.g., "/" and "#" is not allowed here. Moreover,
/// names in Nemo cannot start with numbers.
///
/// TODO: This should be aligned with how the parser works. Currently restricted to basic alpha-numeric names.
/// Note: Failing to recognize an IRI as possible name should not have severe consequences (we just put some <>
/// around such IRIs in formatting).
pub(crate) fn is_name(&self) -> bool {
let mut first = true;
for c in self.0.chars() {
match c {
'0'..='9' | '_' | '-' => {
if first {
return false;
}
}
'a'..='z' | 'A'..='Z' => {}
_ => {
return false;
}
}
first = false;
}
true
}
}
impl DataValue for IriDataValue {
fn datatype_iri(&self) -> String {
self.value_domain().type_iri()
}
fn lexical_value(&self) -> String {
self.0.to_owned()
}
fn value_domain(&self) -> ValueDomain {
ValueDomain::Iri
}
fn to_iri_unchecked(&self) -> String {
self.0.to_owned()
}
fn canonical_string(&self) -> String {
super::datavalue::quote_iri(self.0.as_str())
}
}
impl std::hash::Hash for IriDataValue {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.value_domain().hash(state);
self.0.hash(state);
}
}
impl std::fmt::Display for IriDataValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.is_name() {
f.write_str(self.0.as_str())
} else {
f.write_str(self.canonical_string().as_str())
}
}
}
#[cfg(test)]
mod test {
use super::IriDataValue;
use crate::datavalues::{DataValue, ValueDomain};
#[test]
fn test_iri() {
let value = "http://example.org/nemo";
let dv = IriDataValue::new(value.to_string());
assert_eq!(dv.lexical_value(), value.to_string());
assert_eq!(
dv.datatype_iri(),
"http://www.w3.org/2001/XMLSchema#anyURI".to_string()
);
assert_eq!(dv.value_domain(), ValueDomain::Iri);
assert_eq!(dv.canonical_string(), "<".to_string() + value + ">");
assert_eq!(dv.to_iri(), Some(value.to_string()));
assert_eq!(dv.to_iri_unchecked(), value.to_string());
}
}