kutil_std/foster/
bytestr.rs

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