kutil_std/foster/
string.rs

1use super::{super::borrow::*, foster::*, has_length::*};
2
3use std::{cmp::*, fmt, hash::*};
4
5/// [Foster] for [String].
6///
7/// Supports [IntoOwned], [HasLength], [AsRef]\<str\>, [Eq]/[PartialEq], [Ord]/[PartialOrd],
8/// [Hash], and [Display](fmt::Display).
9pub type FosterString = Foster<String, &'static str>;
10
11impl IntoOwned for FosterString {
12    /// Into owned.
13    fn into_owned(self) -> Self {
14        match self {
15            Self::Owned(_) => self,
16            Self::Fostered(string) => Self::Owned(string.into()),
17        }
18    }
19}
20
21impl HasLength for FosterString {
22    fn len(&self) -> usize {
23        match self {
24            Self::Owned(string) => string.len(),
25            Self::Fostered(string) => string.len(),
26        }
27    }
28}
29
30impl From<&str> for FosterString {
31    fn from(string: &str) -> Self {
32        Self::Owned(string.into())
33    }
34}
35
36impl AsRef<str> for FosterString {
37    fn as_ref(&self) -> &str {
38        match self {
39            Self::Owned(string) => string,
40            Self::Fostered(string) => string,
41        }
42    }
43}
44
45impl PartialEq for FosterString {
46    fn eq(&self, other: &Self) -> bool {
47        match self {
48            Self::Owned(string) => match other {
49                Self::Owned(other_string) => string.eq(other_string),
50                Self::Fostered(other_string) => string.eq(other_string),
51            },
52
53            Self::Fostered(string) => match other {
54                Self::Owned(other_string) => string.eq(other_string),
55                Self::Fostered(other_string) => string.eq(other_string),
56            },
57        }
58    }
59}
60
61impl Eq for FosterString {}
62
63impl PartialOrd for FosterString {
64    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
65        match self {
66            Self::Owned(string) => match other {
67                Self::Owned(other_string) => string.partial_cmp(other_string),
68                Self::Fostered(other_string) => string.as_str().partial_cmp(*other_string),
69            },
70
71            Self::Fostered(string) => match other {
72                Self::Owned(other_string) => (*string).partial_cmp(other_string.as_str()),
73                Self::Fostered(other_string) => string.partial_cmp(other_string),
74            },
75        }
76    }
77}
78
79impl Ord for FosterString {
80    fn cmp(&self, other: &Self) -> Ordering {
81        match self {
82            Self::Owned(string) => match other {
83                Self::Owned(other_string) => string.cmp(other_string),
84                Self::Fostered(other_string) => string.as_str().cmp(other_string),
85            },
86
87            Self::Fostered(string) => match other {
88                Self::Owned(other_string) => (*string).cmp(other_string),
89                Self::Fostered(other_string) => string.cmp(other_string),
90            },
91        }
92    }
93}
94
95impl Hash for FosterString {
96    fn hash<HasherT>(&self, state: &mut HasherT)
97    where
98        HasherT: Hasher,
99    {
100        match self {
101            Self::Owned(string) => state.write(string.as_bytes()),
102            Self::Fostered(string) => state.write(string.as_bytes()),
103        }
104    }
105}
106
107impl fmt::Display for FosterString {
108    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
109        match self {
110            Self::Owned(string) => fmt::Display::fmt(string, formatter),
111            Self::Fostered(string) => fmt::Display::fmt(string, formatter),
112        }
113    }
114}
115
116/// Delegates traits to a [FosterString] newtype.
117///
118/// Example:
119///
120/// ```
121/// #[derive(Clone, Debug)]
122/// pub struct MyType(FosterString);
123///
124/// delegate_newtype_of_foster_string!(MyType);
125/// ```
126///
127#[macro_export]
128macro_rules! delegate_newtype_of_foster_string {
129    ( $type:ty ) => {
130        impl $type {
131            /// Constructor.
132            pub const fn new_owned(string: ::std::string::String) -> Self {
133                Self(::kutil_std::foster::Foster::new_owned(string))
134            }
135
136            /// Constructor.
137            pub const fn new_fostered(string: &'static str) -> Self {
138                Self(::kutil_std::foster::Foster::new_fostered(string))
139            }
140        }
141
142        impl ::kutil_std::borrow::IntoOwned for $type {
143            fn into_owned(self) -> Self {
144                match self.0 {
145                    ::kutil_std::foster::Foster::Owned(_) => self,
146                    ::kutil_std::foster::Foster::Fostered(string) => Self::new_owned(string.into()),
147                }
148            }
149        }
150
151        impl ::kutil_std::foster::HasLength for $type {
152            fn len(&self) -> usize {
153                self.0.len()
154            }
155        }
156
157        impl ::std::convert::From<::std::string::String> for $type {
158            fn from(string: ::std::string::String) -> Self {
159                string.into()
160            }
161        }
162
163        impl ::std::convert::From<&str> for $type {
164            fn from(string: &str) -> Self {
165                Self(string.into())
166            }
167        }
168
169        impl ::std::convert::AsRef<str> for $type {
170            fn as_ref(&self) -> &str {
171                self.0.as_ref()
172            }
173        }
174
175        impl ::std::cmp::PartialEq for $type {
176            fn eq(&self, other: &Self) -> bool {
177                self.0.eq(&other.0)
178            }
179        }
180
181        impl ::std::cmp::Eq for $type {}
182
183        impl ::std::cmp::PartialOrd for $type {
184            fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
185                self.0.partial_cmp(&other.0)
186            }
187        }
188
189        impl ::std::cmp::Ord for $type {
190            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
191                self.0.cmp(&other.0)
192            }
193        }
194
195        impl ::std::hash::Hash for $type {
196            fn hash<HasherT>(&self, state: &mut HasherT)
197            where
198                HasherT: ::std::hash::Hasher,
199            {
200                self.0.hash(state)
201            }
202        }
203
204        impl ::std::fmt::Display for $type {
205            fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
206                ::std::fmt::Display::fmt(&self.0, formatter)
207            }
208        }
209    };
210}