xsd_types/value/string/
normalized.rs1use 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 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 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}