html_types/attributes/
value.rs

1use derive_more::Display;
2use std::borrow::Cow;
3
4#[derive(Debug, PartialEq, Eq)]
5pub struct InvalidValueError {}
6
7#[derive(Clone, Debug, PartialEq, Eq, Display)]
8pub struct Value<'a>(Cow<'a, str>);
9
10macro_rules! value {
11    ($name:ident $tag:expr) => {
12        pub const $name: Value<'static> = Value(Cow::Borrowed($tag));
13    };
14}
15
16impl<'a> Value<'a> {
17    /// Function that determines whether a string slice would be
18    /// considered a valid value. Can be helpful elsewhere when specifing
19    /// more restrictive types
20    pub fn is_valid(str: &str) -> bool {
21        let allowed = |c: char| -> bool {
22            char::is_alphabetic(c)
23                || c == ':'
24                || c == '/'
25                || c == '.'
26                || char::is_whitespace(c)
27                || c == '-'
28        };
29        str.chars().all(allowed)
30    }
31
32    pub fn create(str: &'a str) -> Result<Value<'a>, InvalidValueError> {
33        match Self::is_valid(str) {
34            true => Ok(Value(Cow::Borrowed(str))),
35            false => Err(InvalidValueError {}),
36        }
37    }
38
39    pub fn owned<S>(str: S) -> Result<Value<'a>, InvalidValueError>
40    where
41        S: Into<String>,
42    {
43        let str = str.into();
44        let valid = Self::is_valid(&str);
45        match valid {
46            true => Ok(Value(Cow::Owned(str))),
47            false => Err(InvalidValueError {}),
48        }
49    }
50
51    // Common Html Attribute values
52    // Used to have easier 'static' access to these 'constants'
53
54    value!(TEXT_CSS "text/css");
55    value!(STYLESHEET "stylesheet");
56    value!(UTF_8 "UTF-8");
57    value!(EN "en");
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn url_is_valid() {
66        let url = "http://google.com";
67        let node = Value::create(url);
68        let expected = Result::Ok(Value(Cow::Borrowed(url)));
69        assert_eq!(node, expected);
70    }
71
72    #[test]
73    fn namespacing_is_valid() {
74        let id = "test-id";
75        let node = Value::create(id);
76        let expected = Result::Ok(Value(Cow::Borrowed(id)));
77        assert_eq!(node, expected);
78    }
79}