Skip to main content

ephemeris_documents/markdown/
marker_name.rs

1//! Validated marker names.
2
3use facet::Facet;
4
5use crate::error::MarkdownError;
6
7/// An owned marker name, validated when it is decoded.
8#[derive(Debug, Clone, Facet, PartialEq, Eq)]
9#[facet(proxy = String)]
10pub struct MarkerNameBuf(String);
11
12impl MarkerNameBuf {
13    /// Check that a marker name is non-empty and has no leading or trailing
14    /// whitespace.
15    ///
16    /// # Errors
17    /// Returns [`MarkdownError::MarkerNameInvalid`] otherwise.
18    pub(super) fn check(name: &str) -> Result<(), MarkdownError> {
19        if name.is_empty() || name != name.trim() {
20            Err(MarkdownError::MarkerNameInvalid)
21        } else {
22            Ok(())
23        }
24    }
25}
26
27impl TryFrom<String> for MarkerNameBuf {
28    type Error = MarkdownError;
29
30    fn try_from(name: String) -> Result<Self, Self::Error> {
31        Self::check(&name)?;
32        Ok(Self(name))
33    }
34}
35
36impl TryFrom<&str> for MarkerNameBuf {
37    type Error = MarkdownError;
38
39    fn try_from(name: &str) -> Result<Self, Self::Error> {
40        Self::try_from(name.to_owned())
41    }
42}
43
44impl From<&MarkerNameBuf> for String {
45    fn from(name: &MarkerNameBuf) -> Self {
46        name.0.clone()
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::MarkerNameBuf;
53    use crate::error::MarkdownError;
54
55    #[test]
56    fn marker_names_are_non_empty_and_trimmed() {
57        for name in ["", " ", " a", "a ", "\ta"] {
58            assert!(
59                matches!(
60                    MarkerNameBuf::check(name),
61                    Err(MarkdownError::MarkerNameInvalid)
62                ),
63                "{name:?}"
64            );
65            assert!(
66                matches!(
67                    MarkerNameBuf::try_from(name),
68                    Err(MarkdownError::MarkerNameInvalid)
69                ),
70                "{name:?}"
71            );
72        }
73        assert_eq!(
74            String::from(&MarkerNameBuf::try_from("a b").unwrap()),
75            "a b"
76        );
77    }
78}