sophia_api/term/
var_name.rs1use super::*;
6use lazy_static::lazy_static;
7use regex::Regex;
8use sophia_iri::wrap;
9use std::borrow::Borrow;
10use std::fmt::Debug;
11use thiserror::Error;
12
13lazy_static! {
14 static ref VARNAME: Regex = Regex::new(r"(?x)
26 ^
27 [_A-Za-z0-9\u{C0}-\u{D6}\u{D8}-\u{F6}\u{F8}-\u{2FF}\u{370}-\u{37D}\u{37F}-\u{1FFF}\u{200C}-\u{200D}\u{2070}-\u{218F}\u{2C00}-\u{2FEF}\u{3001}-\u{D7FF}\u{F900}-\u{FDCF}\u{FDF0}-\u{FFFD}\U{10000}-\U{EFFFF}]
28 [_A-Za-z0-9\u{B7}\u{C0}-\u{D6}\u{D8}-\u{F6}\u{F8}-\u{2FF}\u{300}-\u{37D}\u{37F}-\u{1FFF}\u{200C}-\u{200D}\u{203F}-\u{2040}\u{2070}-\u{218F}\u{2C00}-\u{2FEF}\u{3001}-\u{D7FF}\u{F900}-\u{FDCF}\u{FDF0}-\u{FFFD}\U{10000}-\U{EFFFF}]*
29 $
30 ").unwrap();
31}
32
33wrap! { VarName borrowing str :
34 pub fn new(name: T) -> Result<Self, InvalidVarName> {
37 if VARNAME.is_match(name.borrow()) {
38 Ok(VarName(name))
39 } else {
40 Err(InvalidVarName(name.borrow().to_string()))
41 }
42 }
43
44 pub fn as_str(&self) -> &str {
46 self.0.borrow()
47 }
48}
49#[derive(Debug, Error)]
51#[error("The given variable name '{0}' does not comply with SPARQL's VARNAME")]
52pub struct InvalidVarName(pub String);
53
54impl<T> Term for VarName<T>
55where
56 T: Borrow<str> + Debug,
57{
58 type BorrowTerm<'x> = &'x Self where T: 'x;
59
60 fn kind(&self) -> TermKind {
61 TermKind::Variable
62 }
63 fn variable(&self) -> Option<VarName<MownStr>> {
64 Some(self.as_ref().map_unchecked(MownStr::from_str))
65 }
66 fn borrow_term(&self) -> Self::BorrowTerm<'_> {
67 self
68 }
69}
70
71#[cfg(test)]
72mod test {
73 use super::*;
74 use test_case::test_case;
75
76 #[test_case("x")]
77 #[test_case("foo_bar_baz")]
78 #[test_case("hé_hé")]
79 #[test_case("1")]
80 #[test_case("abc42")]
81 fn valid(tag: &str) {
82 assert!(VarName::new(tag).is_ok());
83 }
84
85 #[test_case(""; "empty")]
86 #[test_case(" "; "space")]
87 #[test_case("."; "dot")]
88 #[test_case("a.b"; "with dot")]
89 #[test_case("a,b"; "with comma")]
90 #[test_case("a b"; "with space")]
91 fn invalid(tag: &str) {
92 assert!(VarName::new(tag).is_err());
93 }
94}