1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use core::fmt;
use std::{borrow::Borrow, ops::Deref, str::FromStr};

use crate::ParseXsd;

#[derive(Debug, thiserror::Error)]
#[error("invalid normalized string `{0}`")]
pub struct InvalidNormalizedStr<T = String>(pub T);

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct NormalizedStr(str);

impl NormalizedStr {
	pub fn new(value: &str) -> Result<&Self, InvalidNormalizedStr<&str>> {
		if Self::validate(value) {
			Ok(unsafe { Self::new_unchecked(value) })
		} else {
			Err(InvalidNormalizedStr(value))
		}
	}

	fn validate(value: &str) -> bool {
		value.chars().all(|c| !matches!(c, '\t' | '\n' | '\r'))
	}

	/// Creates a new normalized string from the input `value` without
	/// validation.
	///
	/// # Safety
	///
	/// The input `value` must be an XSD normalized string.
	pub unsafe fn new_unchecked(value: &str) -> &Self {
		std::mem::transmute(value)
	}

	pub fn as_str(&self) -> &str {
		&self.0
	}
}

impl fmt::Display for NormalizedStr {
	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
		self.0.fmt(f)
	}
}

impl ToOwned for NormalizedStr {
	type Owned = NormalizedString;

	fn to_owned(&self) -> Self::Owned {
		NormalizedString(self.0.to_owned())
	}
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NormalizedString(String);

impl NormalizedString {
	pub fn new(value: String) -> Result<Self, InvalidNormalizedStr> {
		if NormalizedStr::validate(&value) {
			Ok(Self(value))
		} else {
			Err(InvalidNormalizedStr(value))
		}
	}

	/// Creates a new normalized string from the input `value` without
	/// validation.
	///
	/// # Safety
	///
	/// The input `value` must be an XSD normalized string.
	pub unsafe fn new_unchecked(value: String) -> Self {
		Self(value)
	}

	pub fn as_normalized_str(&self) -> &NormalizedStr {
		unsafe { NormalizedStr::new_unchecked(self.0.as_str()) }
	}

	pub fn into_string(self) -> String {
		self.0
	}
}

impl fmt::Display for NormalizedString {
	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
		self.0.fmt(f)
	}
}

impl Borrow<NormalizedStr> for NormalizedString {
	fn borrow(&self) -> &NormalizedStr {
		self.as_normalized_str()
	}
}

impl Deref for NormalizedString {
	type Target = NormalizedStr;

	fn deref(&self) -> &Self::Target {
		self.as_normalized_str()
	}
}

impl FromStr for NormalizedString {
	type Err = InvalidNormalizedStr<String>;

	fn from_str(s: &str) -> Result<Self, Self::Err> {
		Self::new(s.to_owned())
	}
}

impl ParseXsd for NormalizedString {
	type LexicalForm = crate::lexical::NormalizedStr;
}