kutil_std/foster/
byte_string.rs

1use super::{super::borrow::*, foster::*, has_length::*};
2
3use {
4    bytestring::*,
5    std::{cmp::*, fmt, hash::*},
6};
7
8/// [Foster] for [ByteString].
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 [ByteString] in a [Box] because [ByteString] has interior mutability and
14/// thus cannot be part of a constant value's type.
15pub type FosterByteString = Foster<Box<ByteString>, &'static str>;
16
17impl IntoOwned for FosterByteString {
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 FosterByteString {
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 FosterByteString {
37    fn from(string: &str) -> Self {
38        Self::Owned(Box::new(string.into()))
39    }
40}
41
42impl AsRef<str> for FosterByteString {
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 FosterByteString {
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_ref().eq(*other_string),
57            },
58
59            Self::Fostered(string) => match other {
60                Self::Owned(other_string) => {
61                    let other_string: &str = &other_string;
62                    (*string).eq(other_string)
63                }
64                Self::Fostered(other_string) => string.eq(other_string),
65            },
66        }
67    }
68}
69
70impl Eq for FosterByteString {}
71
72impl PartialOrd for FosterByteString {
73    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
74        match self {
75            Self::Owned(string) => match other {
76                Self::Owned(other_string) => string.partial_cmp(other_string),
77                Self::Fostered(other_string) => (***string).partial_cmp(*other_string),
78            },
79
80            Self::Fostered(string) => match other {
81                Self::Owned(other_string) => {
82                    let other_string: &str = &other_string;
83                    (*string).partial_cmp(other_string)
84                }
85                Self::Fostered(other_string) => string.partial_cmp(other_string),
86            },
87        }
88    }
89}
90
91impl Ord for FosterByteString {
92    fn cmp(&self, other: &Self) -> Ordering {
93        match self {
94            Self::Owned(string) => match other {
95                Self::Owned(other_string) => string.cmp(other_string),
96                Self::Fostered(other_string) => (***string).cmp(other_string),
97            },
98
99            Self::Fostered(string) => match other {
100                Self::Owned(other_string) => (*string).cmp(other_string),
101                Self::Fostered(other_string) => string.cmp(other_string),
102            },
103        }
104    }
105}
106
107impl Hash for FosterByteString {
108    fn hash<HasherT>(&self, state: &mut HasherT)
109    where
110        HasherT: Hasher,
111    {
112        match self {
113            Self::Owned(string) => state.write(string.as_bytes()),
114            Self::Fostered(string) => state.write(string.as_bytes()),
115        }
116    }
117}
118
119impl fmt::Display for FosterByteString {
120    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
121        match self {
122            Self::Owned(string) => string.fmt(formatter),
123            Self::Fostered(string) => string.fmt(formatter),
124        }
125    }
126}
127
128/// Delegates traits to a [FosterByteString] newtype.
129///
130/// Example:
131///
132/// ```
133/// #[derive(Clone, Debug)]
134/// pub struct MyType(FosterByteString);
135///
136/// delegate_newtype_of_foster_byte_string!(MyType);
137/// ```
138///
139#[macro_export]
140macro_rules! delegate_newtype_of_foster_byte_string {
141    ( $type:ty ) => {
142        impl $type {
143            /// Constructor.
144            pub const fn new_owned(string: ::std::boxed::Box<::bytestring::ByteString>) -> Self {
145                Self(::kutil_std::foster::Foster::new_owned(string))
146            }
147
148            /// Constructor.
149            pub const fn new_fostered(string: &'static str) -> Self {
150                Self(::kutil_std::foster::Foster::new_fostered(string))
151            }
152        }
153
154        impl ::kutil_std::borrow::IntoOwned for $type {
155            fn into_owned(self) -> Self {
156                match self.0 {
157                    ::kutil_std::foster::Foster::Owned(_) => self,
158                    ::kutil_std::foster::Foster::Fostered(string) => {
159                        Self::new_owned(::std::boxed::Box::new(string.into()))
160                    }
161                }
162            }
163        }
164
165        impl ::kutil_std::foster::HasLength for $type {
166            fn len(&self) -> usize {
167                self.0.len()
168            }
169        }
170
171        impl ::std::convert::From<::bytestring::ByteString> for $type {
172            fn from(string: ::bytestring::ByteString) -> Self {
173                string.into()
174            }
175        }
176
177        impl ::std::convert::From<String> for $type {
178            fn from(string: ::std::string::String) -> Self {
179                string.into()
180            }
181        }
182
183        impl ::std::convert::From<&str> for $type {
184            fn from(string: &str) -> Self {
185                Self(string.into())
186            }
187        }
188
189        impl ::std::convert::AsRef<str> for $type {
190            fn as_ref(&self) -> &str {
191                self.0.as_ref()
192            }
193        }
194
195        impl ::std::cmp::PartialEq for $type {
196            fn eq(&self, other: &Self) -> bool {
197                self.0.eq(&other.0)
198            }
199        }
200
201        impl ::std::cmp::Eq for $type {}
202
203        impl ::std::cmp::PartialOrd for $type {
204            fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
205                self.0.partial_cmp(&other.0)
206            }
207        }
208
209        impl ::std::cmp::Ord for $type {
210            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
211                self.0.cmp(&other.0)
212            }
213        }
214
215        impl ::std::hash::Hash for $type {
216            fn hash<HasherT>(&self, state: &mut HasherT)
217            where
218                HasherT: ::std::hash::Hasher,
219            {
220                self.0.hash(state)
221            }
222        }
223
224        impl ::std::fmt::Display for $type {
225            fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
226                ::std::fmt::Display::fmt(&self.0, formatter)
227            }
228        }
229    };
230}