vue_sfc/ast/block/attribute/
name.rs1use std::{
2 borrow::{Borrow, Cow},
3 fmt::Display,
4 ops::Deref,
5};
6
7pub use self::error::InvalidAttributeName;
8
9mod error {
10 use std::error::Error;
11 use std::fmt::Display;
12
13 #[derive(Debug)]
16 pub struct InvalidAttributeName(pub(super) char);
17
18 impl Display for InvalidAttributeName {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 write!(f, "illegal char: `{}`", self.0)
21 }
22 }
23
24 impl Error for InvalidAttributeName {}
25}
26
27#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
29#[must_use]
30pub struct AttributeName<'a>(Cow<'a, str>);
31
32impl<'a> AttributeName<'a> {
33 pub fn from_cow(mut src: Cow<'a, str>) -> Result<Self, InvalidAttributeName> {
45 if let Some(ch) = src.chars().find(|ch| {
46 matches!(
47 ch,
48 '\u{0009}'
49 | '\u{000A}'
50 | '\u{000C}'
51 | '\u{0020}'
52 | '\u{002F}'
53 | '\u{003D}'
54 | '\u{003E}'
55 )
56 }) {
57 return Err(InvalidAttributeName(ch));
58 }
59
60 if src.contains(|ch: char| ch.is_ascii_uppercase()) {
61 src.to_mut().make_ascii_lowercase();
62
63 Ok(Self(src))
64 } else {
65 Ok(Self(src))
66 }
67 }
68
69 pub unsafe fn from_cow_unchecked(src: Cow<'a, str>) -> Self {
78 if cfg!(debug_assertions) {
79 match Self::from_cow(src) {
80 Ok(val) => val,
81 Err(err) => {
82 panic!("AttributeName::from_cow_unchecked(): {err}")
83 }
84 }
85 } else {
86 Self(src)
87 }
88 }
89
90 #[must_use]
91 pub fn as_str(&self) -> &str {
92 &self.0
93 }
94}
95
96impl Deref for AttributeName<'_> {
97 type Target = str;
98
99 fn deref(&self) -> &Self::Target {
100 self.as_str()
101 }
102}
103
104impl Borrow<str> for AttributeName<'_> {
105 fn borrow(&self) -> &str {
106 self.as_str()
107 }
108}
109
110impl Display for AttributeName<'_> {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 self.as_str().fmt(f)
113 }
114}
115
116impl<'a> TryFrom<&'a str> for AttributeName<'a> {
117 type Error = InvalidAttributeName;
118 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
119 Self::from_cow(Cow::Borrowed(value))
120 }
121}
122
123impl<'a> TryFrom<String> for AttributeName<'a> {
124 type Error = InvalidAttributeName;
125 fn try_from(value: String) -> Result<Self, Self::Error> {
126 Self::from_cow(Cow::Owned(value))
127 }
128}
129
130impl<'a> TryFrom<Cow<'a, str>> for AttributeName<'a> {
131 type Error = InvalidAttributeName;
132 fn try_from(value: Cow<'a, str>) -> Result<Self, Self::Error> {
133 Self::from_cow(value)
134 }
135}