1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2use std::{
3 borrow::Cow,
4 cmp::Ordering,
5 hash::{Hash, Hasher},
6 sync::Arc,
7};
8
9use crate::{Basic, Type};
10
11#[derive(Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
30pub struct Str<'a>(#[serde(borrow)] Inner<'a>);
31
32#[derive(Eq, Clone)]
33enum Inner<'a> {
34 Static(&'static str),
35 Borrowed(&'a str),
36 Owned(Arc<str>),
37}
38
39impl Default for Inner<'_> {
40 fn default() -> Self {
41 Self::Static("")
42 }
43}
44
45impl<'a> PartialEq for Inner<'a> {
46 fn eq(&self, other: &Inner<'a>) -> bool {
47 self.as_str() == other.as_str()
48 }
49}
50
51impl<'a> Ord for Inner<'a> {
52 fn cmp(&self, other: &Inner<'a>) -> Ordering {
53 self.as_str().cmp(other.as_str())
54 }
55}
56
57impl<'a> PartialOrd for Inner<'a> {
58 fn partial_cmp(&self, other: &Inner<'a>) -> Option<Ordering> {
59 Some(self.cmp(other))
60 }
61}
62
63impl Hash for Inner<'_> {
64 fn hash<H: Hasher>(&self, h: &mut H) {
65 self.as_str().hash(h)
66 }
67}
68
69impl Inner<'_> {
70 pub fn as_str(&self) -> &str {
72 match self {
73 Inner::Static(s) => s,
74 Inner::Borrowed(s) => s,
75 Inner::Owned(s) => s,
76 }
77 }
78}
79
80impl Serialize for Inner<'_> {
81 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
82 s.serialize_str(self.as_str())
83 }
84}
85
86impl<'de: 'a, 'a> Deserialize<'de> for Inner<'a> {
87 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
88 where
89 D: Deserializer<'de>,
90 {
91 <&'a str>::deserialize(deserializer).map(Inner::Borrowed)
92 }
93}
94
95impl Str<'_> {
96 pub const fn from_static(s: &'static str) -> Self {
98 Str(Inner::Static(s))
99 }
100
101 pub fn as_ref(&self) -> Str<'_> {
103 match &self.0 {
104 Inner::Static(s) => Str(Inner::Static(s)),
105 Inner::Borrowed(s) => Str(Inner::Borrowed(s)),
106 Inner::Owned(s) => Str(Inner::Borrowed(s)),
107 }
108 }
109
110 pub fn as_str(&self) -> &str {
112 self.0.as_str()
113 }
114
115 pub fn to_owned(&self) -> Str<'static> {
117 self.clone().into_owned()
118 }
119
120 pub fn into_owned(self) -> Str<'static> {
122 match self.0 {
123 Inner::Static(s) => Str(Inner::Static(s)),
124 Inner::Borrowed(s) => Str(Inner::Owned(s.to_owned().into())),
125 Inner::Owned(s) => Str(Inner::Owned(s)),
126 }
127 }
128}
129
130impl Basic for Str<'_> {
131 const SIGNATURE_CHAR: char = <&str>::SIGNATURE_CHAR;
132 const SIGNATURE_STR: &'static str = <&str>::SIGNATURE_STR;
133}
134
135impl Type for Str<'_> {
136 const SIGNATURE: &'static crate::Signature = &crate::Signature::Str;
137}
138
139impl<'a> From<&'a str> for Str<'a> {
140 fn from(value: &'a str) -> Self {
141 Self(Inner::Borrowed(value))
142 }
143}
144
145impl<'a> From<&'a String> for Str<'a> {
146 fn from(value: &'a String) -> Self {
147 Self(Inner::Borrowed(value))
148 }
149}
150
151impl From<String> for Str<'_> {
152 fn from(value: String) -> Self {
153 Self(Inner::Owned(value.into()))
154 }
155}
156
157impl From<Arc<str>> for Str<'_> {
158 fn from(value: Arc<str>) -> Self {
159 Self(Inner::Owned(value))
160 }
161}
162
163impl<'a> From<Cow<'a, str>> for Str<'a> {
164 fn from(value: Cow<'a, str>) -> Self {
165 match value {
166 Cow::Owned(value) => value.into(),
167 Cow::Borrowed(value) => value.into(),
168 }
169 }
170}
171
172impl<'a> From<Str<'a>> for String {
173 fn from(value: Str<'a>) -> String {
174 match value.0 {
175 Inner::Static(s) => s.into(),
176 Inner::Borrowed(s) => s.into(),
177 Inner::Owned(s) => s.to_string(),
178 }
179 }
180}
181
182impl<'a> From<&'a Str<'_>> for &'a str {
183 fn from(value: &'a Str<'_>) -> &'a str {
184 value.as_str()
185 }
186}
187
188impl std::ops::Deref for Str<'_> {
189 type Target = str;
190
191 fn deref(&self) -> &Self::Target {
192 self.as_str()
193 }
194}
195
196impl PartialEq<str> for Str<'_> {
197 fn eq(&self, other: &str) -> bool {
198 self.as_str() == other
199 }
200}
201
202impl PartialEq<&str> for Str<'_> {
203 fn eq(&self, other: &&str) -> bool {
204 self.as_str() == *other
205 }
206}
207
208impl std::fmt::Debug for Str<'_> {
209 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210 std::fmt::Debug::fmt(self.as_str(), f)
211 }
212}
213
214impl std::fmt::Display for Str<'_> {
215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216 std::fmt::Display::fmt(self.as_str(), f)
217 }
218}
219
220#[cfg(test)]
221mod tests {
222 use super::Str;
223
224 #[test]
225 fn from_string() {
226 let string = String::from("value");
227 let v = Str::from(&string);
228 assert_eq!(v.as_str(), "value");
229 }
230
231 #[test]
232 fn test_ordering() {
233 let first = Str::from("a".to_string());
234 let second = Str::from_static("b");
235 assert!(first < second);
236 }
237}