1use core::{
2 borrow::{Borrow, BorrowMut},
3 fmt,
4 ops::{Deref, DerefMut},
5 ptr,
6};
7
8use crate::{
9 errors::{TryFromBytesError, TryFromStrError},
10 Char,
11};
12
13#[derive(Clone)]
14#[repr(transparent)]
15pub struct OwnedChar {
29 b: [u8; 4],
30}
31
32impl OwnedChar {
33 #[must_use]
34 #[inline]
35 pub const unsafe fn new_unchecked(b: [u8; 4]) -> Self {
42 Self { b }
43 }
44
45 #[must_use]
46 #[inline]
47 pub unsafe fn from_bytes_unchecked(bytes: &[u8]) -> Self {
54 let mut c = [0; 4];
55 c[..bytes.len()].copy_from_slice(bytes);
56
57 Self { b: c }
58 }
59
60 #[must_use]
61 #[inline]
62 pub unsafe fn buffer_mut(&mut self) -> &mut [u8; 4] {
67 &mut self.b
68 }
69
70 #[must_use]
71 #[inline]
72 pub const fn into_bytes(self) -> [u8; 4] {
83 self.b
84 }
85}
86
87impl AsRef<Char> for OwnedChar {
88 #[inline]
89 fn as_ref(&self) -> &Char {
90 unsafe { &*ptr::from_ref(self).cast() }
95 }
96}
97
98impl AsMut<Char> for OwnedChar {
99 #[inline]
100 fn as_mut(&mut self) -> &mut Char {
101 unsafe { &mut *ptr::from_mut(self).cast() }
106 }
107}
108
109impl Borrow<Char> for OwnedChar {
110 #[inline]
111 fn borrow(&self) -> &Char {
112 self.as_ref()
113 }
114}
115
116impl BorrowMut<Char> for OwnedChar {
117 #[inline]
118 fn borrow_mut(&mut self) -> &mut Char {
119 self.as_mut()
120 }
121}
122
123impl Deref for OwnedChar {
124 type Target = Char;
125
126 #[inline]
127 fn deref(&self) -> &Self::Target {
128 self.as_ref()
129 }
130}
131
132impl DerefMut for OwnedChar {
133 #[inline]
134 fn deref_mut(&mut self) -> &mut Self::Target {
135 self.as_mut()
136 }
137}
138
139impl fmt::Debug for OwnedChar {
140 #[inline]
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 self.as_ref().fmt(f)
143 }
144}
145
146impl fmt::Display for OwnedChar {
147 #[inline]
148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149 self.as_ref().fmt(f)
150 }
151}
152
153impl From<char> for OwnedChar {
154 #[inline]
155 fn from(value: char) -> Self {
156 let mut c = [0; 4];
157 value.encode_utf8(&mut c);
158 Self { b: c }
159 }
160}
161
162impl From<&Char> for OwnedChar {
163 #[inline]
164 fn from(value: &Char) -> Self {
165 value.as_owned()
166 }
167}
168
169impl TryFrom<&str> for OwnedChar {
170 type Error = TryFromStrError;
171
172 #[inline]
173 fn try_from(value: &str) -> Result<Self, Self::Error> {
174 <&Char>::try_from(value)?;
175
176 let mut c = [0; 4];
177 c[..value.len()].copy_from_slice(value.as_bytes());
178
179 Ok(Self { b: c })
180 }
181}
182
183impl TryFrom<&[u8]> for OwnedChar {
184 type Error = TryFromBytesError;
185
186 #[inline]
187 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
188 <&Char>::try_from(value)?;
189
190 let mut c = [0; 4];
191 c[..value.len()].copy_from_slice(value);
192
193 Ok(Self { b: c })
194 }
195}
196
197impl TryFrom<[u8; 4]> for OwnedChar {
198 type Error = TryFromBytesError;
199
200 #[inline]
201 fn try_from(value: [u8; 4]) -> Result<Self, Self::Error> {
202 <&Char>::try_from(&value[..]).map(|_| Self { b: value })
203 }
204}
205
206impl<T> PartialEq<T> for OwnedChar
207where
208 Char: PartialEq<T>,
209{
210 #[inline]
211 fn eq(&self, other: &T) -> bool {
212 self.as_ref().eq(other)
213 }
214}
215
216impl Eq for OwnedChar {}
217
218impl<T> PartialOrd<T> for OwnedChar
219where
220 Char: PartialOrd<T>,
221{
222 #[inline]
223 fn partial_cmp(&self, other: &T) -> Option<core::cmp::Ordering> {
224 self.as_ref().partial_cmp(other)
225 }
226}
227
228impl Ord for OwnedChar {
229 #[inline]
230 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
231 self.as_ref().cmp(other)
232 }
233}
234
235#[cfg(test)]
236mod test {
237 use crate::{OwnedChar, StrExt};
238
239 #[test]
240 fn test_from_char_ref() {
241 let s = "abc";
242 let c = s.get_char(1).unwrap().as_owned();
243 assert_eq!(c.as_bytes(), &[98]);
244 assert_eq!(c, 'b');
245 }
246
247 #[test]
248 fn test_from_char() {
249 let c = OwnedChar::from('b');
250 assert_eq!(c.as_bytes(), &[98]);
251 assert_eq!(c, 'b');
252 }
253}