xsd_types/value/string/
normalized.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 normalized string `{0}`")]
8pub struct InvalidNormalizedStr<T = String>(pub T);
9
10#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[repr(transparent)]
12pub struct NormalizedStr(str);
13
14impl NormalizedStr {
15	pub fn new(value: &str) -> Result<&Self, InvalidNormalizedStr<&str>> {
16		if Self::validate(value) {
17			Ok(unsafe { Self::new_unchecked(value) })
18		} else {
19			Err(InvalidNormalizedStr(value))
20		}
21	}
22
23	fn validate(value: &str) -> bool {
24		value.chars().all(|c| !matches!(c, '\t' | '\n' | '\r'))
25	}
26
27	/// Creates a new normalized string from the input `value` without
28	/// validation.
29	///
30	/// # Safety
31	///
32	/// The input `value` must be an XSD normalized string.
33	pub unsafe fn new_unchecked(value: &str) -> &Self {
34		std::mem::transmute(value)
35	}
36
37	pub fn as_str(&self) -> &str {
38		&self.0
39	}
40}
41
42impl fmt::Display for NormalizedStr {
43	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44		self.0.fmt(f)
45	}
46}
47
48impl ToOwned for NormalizedStr {
49	type Owned = NormalizedString;
50
51	fn to_owned(&self) -> Self::Owned {
52		NormalizedString(self.0.to_owned())
53	}
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
57pub struct NormalizedString(String);
58
59impl NormalizedString {
60	pub fn new(value: String) -> Result<Self, InvalidNormalizedStr> {
61		if NormalizedStr::validate(&value) {
62			Ok(Self(value))
63		} else {
64			Err(InvalidNormalizedStr(value))
65		}
66	}
67
68	/// Creates a new normalized string from the input `value` without
69	/// validation.
70	///
71	/// # Safety
72	///
73	/// The input `value` must be an XSD normalized string.
74	pub unsafe fn new_unchecked(value: String) -> Self {
75		Self(value)
76	}
77
78	pub fn as_normalized_str(&self) -> &NormalizedStr {
79		unsafe { NormalizedStr::new_unchecked(self.0.as_str()) }
80	}
81
82	pub fn into_string(self) -> String {
83		self.0
84	}
85}
86
87impl fmt::Display for NormalizedString {
88	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89		self.0.fmt(f)
90	}
91}
92
93impl Borrow<NormalizedStr> for NormalizedString {
94	fn borrow(&self) -> &NormalizedStr {
95		self.as_normalized_str()
96	}
97}
98
99impl Deref for NormalizedString {
100	type Target = NormalizedStr;
101
102	fn deref(&self) -> &Self::Target {
103		self.as_normalized_str()
104	}
105}
106
107impl FromStr for NormalizedString {
108	type Err = InvalidNormalizedStr<String>;
109
110	fn from_str(s: &str) -> Result<Self, Self::Err> {
111		Self::new(s.to_owned())
112	}
113}
114
115impl ParseXsd for NormalizedString {
116	type LexicalForm = crate::lexical::NormalizedStr;
117}