xsd_types/value/string/
token.rs

1use core::fmt;
2use std::{borrow::Borrow, ops::Deref, str::FromStr};
3
4use crate::ParseXsd;
5
6#[derive(Debug, thiserror::Error)]
7#[error("invalid token `{0}`")]
8pub struct InvalidToken<T = String>(pub T);
9
10#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[repr(transparent)]
12pub struct Token(str);
13
14impl Token {
15	pub fn new(value: &str) -> Result<&Self, InvalidToken<&str>> {
16		if Self::validate(value) {
17			Ok(unsafe { Self::new_unchecked(value) })
18		} else {
19			Err(InvalidToken(value))
20		}
21	}
22
23	fn validate(value: &str) -> bool {
24		let mut leading = true;
25		let mut space = false;
26
27		for c in value.chars() {
28			if c == ' ' {
29				if space {
30					return false;
31				}
32
33				space = true
34			} else {
35				space = false
36			}
37
38			if matches!(c, '\t' | '\n' | '\r') || (space && leading) {
39				return false;
40			}
41
42			leading = false;
43		}
44
45		!space
46	}
47
48	/// Creates a new token string from the input `value` without validation.
49	///
50	/// # Safety
51	///
52	/// The input `value` must be an XSD token string.
53	pub unsafe fn new_unchecked(value: &str) -> &Self {
54		std::mem::transmute(value)
55	}
56
57	pub fn as_str(&self) -> &str {
58		&self.0
59	}
60}
61
62impl fmt::Display for Token {
63	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64		self.0.fmt(f)
65	}
66}
67
68impl ToOwned for Token {
69	type Owned = TokenBuf;
70
71	fn to_owned(&self) -> Self::Owned {
72		TokenBuf(self.0.to_owned())
73	}
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
77pub struct TokenBuf(String);
78
79impl TokenBuf {
80	pub fn new(value: String) -> Result<Self, InvalidToken> {
81		if Token::validate(&value) {
82			Ok(Self(value))
83		} else {
84			Err(InvalidToken(value))
85		}
86	}
87
88	/// Creates a new token string from the input `value` without validation.
89	///
90	/// # Safety
91	///
92	/// The input `value` must be an XSD token string.
93	pub unsafe fn new_unchecked(value: String) -> Self {
94		Self(value)
95	}
96
97	pub fn as_token(&self) -> &Token {
98		unsafe { Token::new_unchecked(self.0.as_str()) }
99	}
100
101	pub fn into_string(self) -> String {
102		self.0
103	}
104}
105
106impl fmt::Display for TokenBuf {
107	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108		self.0.fmt(f)
109	}
110}
111
112impl Borrow<Token> for TokenBuf {
113	fn borrow(&self) -> &Token {
114		self.as_token()
115	}
116}
117
118impl Deref for TokenBuf {
119	type Target = Token;
120
121	fn deref(&self) -> &Self::Target {
122		self.as_token()
123	}
124}
125
126impl FromStr for TokenBuf {
127	type Err = InvalidToken;
128
129	fn from_str(s: &str) -> Result<Self, Self::Err> {
130		Self::new(s.to_owned())
131	}
132}
133
134impl ParseXsd for TokenBuf {
135	type LexicalForm = crate::lexical::Token;
136}