vue_sfc/ast/
raw.rs

1use std::{
2    borrow::{Borrow, Cow},
3    fmt::Display,
4    ops::Deref,
5};
6
7pub use self::error::InvalidRaw;
8
9mod error {
10    use std::error::Error;
11    use std::fmt::Display;
12
13    /// Returned when a function was unable to convert a string to a [`Raw`][super::Raw].
14    #[derive(Debug)]
15    pub struct InvalidRaw;
16
17    impl Display for InvalidRaw {
18        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19            write!(f, "raw section must not be empty once end-trimmed")
20        }
21    }
22
23    impl Error for InvalidRaw {}
24}
25
26/// Represent non-empty text before, after or between blocks.
27#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
28#[must_use]
29pub struct Raw<'a>(Cow<'a, str>);
30
31impl<'a> Raw<'a> {
32    /// Attempts to convert a string to a [`Raw`].
33    ///
34    /// # Errors
35    /// Will return an error if the string is empty once end-trimmed.
36    pub fn from_cow(src: Cow<'a, str>) -> Result<Self, InvalidRaw> {
37        let trimmed = match src {
38            Cow::Borrowed(string) => Cow::Borrowed(string.trim_end()),
39            Cow::Owned(mut string) => {
40                string.truncate(string.trim_end().len());
41
42                Cow::Owned(string)
43            }
44        };
45
46        if trimmed.is_empty() {
47            return Err(InvalidRaw);
48        }
49
50        Ok(Self(trimmed))
51    }
52
53    /// Convert a string into a [`Raw`] **without** validating
54    /// (unless `debug_assertions` is enabled).
55    ///
56    /// # Panics
57    /// If `debug_assertions` is enabled, validate the input and panic on failure.
58    ///
59    /// # Safety
60    /// See string prerequisites of [`Raw::from_cow`].
61    pub unsafe fn from_cow_unchecked(src: Cow<'a, str>) -> Self {
62        if cfg!(debug_assertions) {
63            match Self::from_cow(src) {
64                Ok(val) => val,
65                Err(err) => {
66                    panic!("Raw::from_cow_unchecked(): {err}")
67                }
68            }
69        } else {
70            Self(src)
71        }
72    }
73
74    #[must_use]
75    pub fn as_str(&self) -> &str {
76        &self.0
77    }
78}
79
80impl Display for Raw<'_> {
81    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82        self.as_str().fmt(f)
83    }
84}
85
86impl Deref for Raw<'_> {
87    type Target = str;
88
89    fn deref(&self) -> &Self::Target {
90        self.as_str()
91    }
92}
93
94impl Borrow<str> for Raw<'_> {
95    fn borrow(&self) -> &str {
96        self.as_str()
97    }
98}
99
100impl<'a> TryFrom<&'a str> for Raw<'a> {
101    type Error = InvalidRaw;
102    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
103        Self::from_cow(Cow::Borrowed(value))
104    }
105}
106
107impl<'a> TryFrom<String> for Raw<'a> {
108    type Error = InvalidRaw;
109    fn try_from(value: String) -> Result<Self, Self::Error> {
110        Self::from_cow(Cow::Owned(value))
111    }
112}
113
114impl<'a> TryFrom<Cow<'a, str>> for Raw<'a> {
115    type Error = InvalidRaw;
116    fn try_from(value: Cow<'a, str>) -> Result<Self, Self::Error> {
117        Self::from_cow(value)
118    }
119}