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
use self::errors::*;
use crate::DmntkError;
use std::convert::TryFrom;
use uriparse::{RelativeReference, URI};
pub type OptHRef = Option<HRef>;
#[derive(Debug, Clone)]
pub struct HRef(String);
impl<'href> From<&'href HRef> for &'href str {
fn from(value: &'href HRef) -> Self {
&value.0
}
}
impl TryFrom<&str> for HRef {
type Error = DmntkError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if let Ok(relative_reference) = RelativeReference::try_from(value) {
let s = relative_reference.to_string();
return Ok(Self(if s.starts_with('#') { s.strip_prefix('#').unwrap().to_string() } else { s }));
}
if let Ok(uri) = URI::try_from(value) {
return Ok(Self(uri.to_string()));
}
Err(invalid_reference(value))
}
}
mod errors {
use crate::DmntkError;
#[derive(Debug, PartialEq)]
pub enum HRefError {
InvalidReference(String),
}
impl From<HRefError> for DmntkError {
fn from(e: HRefError) -> Self {
DmntkError::new("HRefError", &e.to_string())
}
}
impl std::fmt::Display for HRefError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
HRefError::InvalidReference(s) => write!(f, "invalid reference): `{}`", s),
}
}
}
pub fn invalid_reference(s: &str) -> DmntkError {
HRefError::InvalidReference(s.to_owned()).into()
}
}
#[cfg(test)]
mod tests {
use crate::HRef;
use std::convert::TryFrom;
fn assert_href(expected: &str, uri: &str) {
let href = &HRef::try_from(uri).unwrap();
let actual: &str = href.into();
assert_eq!(expected, actual);
}
#[test]
fn valid_references() {
assert_href("", "");
assert_href("ref", "#ref");
assert_href(":alfa", ":alfa");
assert_href("//beta/gamma", "//beta/gamma");
assert_href("ee412cf7-4dc9-4555-ab90-61907cb5b10e", "#ee412cf7-4dc9-4555-ab90-61907cb5b10e");
assert_href("_82032dc2-36a7-4477-9392-9921353c4b44", "#_82032dc2-36a7-4477-9392-9921353c4b44");
assert_href("https://dmntk.io/examples/example1#model2", "https://dmntk.io/examples/example1#model2");
}
#[test]
fn invalid_references() {
assert!(HRef::try_from("##").is_err());
}
}