1#[cfg(feature = "alloc")]
6use alloc::boxed::Box;
7use core::cmp::Ordering;
8use core::fmt;
9use core::ops::Deref;
10
11#[repr(transparent)]
45#[derive(#[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl ::core::cmp::PartialEq for PotentialUtf8 {
#[inline]
fn eq(&self, other: &PotentialUtf8) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl ::core::cmp::Eq for PotentialUtf8 {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<[u8]>;
}
}Eq, #[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl ::core::cmp::PartialOrd for PotentialUtf8 {
#[inline]
fn partial_cmp(&self, other: &PotentialUtf8)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
}
}PartialOrd, #[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl ::core::cmp::Ord for PotentialUtf8 {
#[inline]
fn cmp(&self, other: &PotentialUtf8) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord)]
46#[allow(clippy::exhaustive_structs)] pub struct PotentialUtf8(pub [u8]);
48
49impl fmt::Debug for PotentialUtf8 {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 match self.try_as_str() {
53 Ok(s) => fmt::Debug::fmt(s, f),
54 Err(_) => fmt::Debug::fmt(&self.0, f),
55 }
56 }
57}
58
59impl PotentialUtf8 {
60 #[inline]
62 pub const fn from_bytes(other: &[u8]) -> &Self {
63 unsafe { core::mem::transmute(other) }
65 }
66
67 #[inline]
69 pub const fn from_str(s: &str) -> &Self {
70 Self::from_bytes(s.as_bytes())
71 }
72
73 #[inline]
77 #[cfg(feature = "alloc")]
78 pub fn from_boxed_bytes(other: Box<[u8]>) -> Box<Self> {
79 unsafe { core::mem::transmute(other) }
81 }
82
83 #[inline]
87 #[cfg(feature = "alloc")]
88 pub fn from_boxed_str(other: Box<str>) -> Box<Self> {
89 Self::from_boxed_bytes(other.into_boxed_bytes())
90 }
91
92 #[inline]
94 pub const fn as_bytes(&self) -> &[u8] {
95 &self.0
96 }
97
98 #[inline]
112 pub fn try_as_str(&self) -> Result<&str, core::str::Utf8Error> {
113 core::str::from_utf8(&self.0)
114 }
115}
116
117impl<'a> From<&'a str> for &'a PotentialUtf8 {
118 #[inline]
119 fn from(other: &'a str) -> Self {
120 PotentialUtf8::from_str(other)
121 }
122}
123
124impl PartialEq<str> for PotentialUtf8 {
125 fn eq(&self, other: &str) -> bool {
126 self.eq(Self::from_str(other))
127 }
128}
129
130impl PartialOrd<str> for PotentialUtf8 {
131 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
132 self.partial_cmp(Self::from_str(other))
133 }
134}
135
136impl PartialEq<PotentialUtf8> for str {
137 fn eq(&self, other: &PotentialUtf8) -> bool {
138 PotentialUtf8::from_str(self).eq(other)
139 }
140}
141
142impl PartialOrd<PotentialUtf8> for str {
143 fn partial_cmp(&self, other: &PotentialUtf8) -> Option<Ordering> {
144 PotentialUtf8::from_str(self).partial_cmp(other)
145 }
146}
147
148#[cfg(feature = "alloc")]
149impl From<Box<str>> for Box<PotentialUtf8> {
150 #[inline]
151 fn from(other: Box<str>) -> Self {
152 PotentialUtf8::from_boxed_str(other)
153 }
154}
155
156impl Deref for PotentialUtf8 {
157 type Target = [u8];
158 fn deref(&self) -> &Self::Target {
159 &self.0
160 }
161}
162
163#[cfg(all(feature = "zerovec", feature = "alloc"))]
165impl<'a> zerovec::maps::ZeroMapKV<'a> for PotentialUtf8 {
166 type Container = zerovec::VarZeroVec<'a, PotentialUtf8>;
167 type Slice = zerovec::VarZeroSlice<PotentialUtf8>;
168 type GetType = PotentialUtf8;
169 type OwnedType = Box<PotentialUtf8>;
170}
171
172#[cfg(feature = "zerovec")]
182unsafe impl zerovec::ule::VarULE for PotentialUtf8 {
183 #[inline]
184 fn validate_bytes(_: &[u8]) -> Result<(), zerovec::ule::UleError> {
185 Ok(())
186 }
187 #[inline]
188 unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
189 PotentialUtf8::from_bytes(bytes)
190 }
191}
192
193#[cfg(feature = "serde")]
195impl serde_core::Serialize for PotentialUtf8 {
196 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
197 where
198 S: serde_core::Serializer,
199 {
200 use serde_core::ser::Error;
201 let s = self
202 .try_as_str()
203 .map_err(|_| S::Error::custom("invalid UTF-8 in PotentialUtf8"))?;
204 if serializer.is_human_readable() {
205 serializer.serialize_str(s)
206 } else {
207 serializer.serialize_bytes(s.as_bytes())
208 }
209 }
210}
211
212#[cfg(all(feature = "serde", feature = "alloc"))]
214impl<'de> serde_core::Deserialize<'de> for Box<PotentialUtf8> {
215 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
216 where
217 D: serde_core::Deserializer<'de>,
218 {
219 if deserializer.is_human_readable() {
220 let boxed_str = Box::<str>::deserialize(deserializer)?;
221 Ok(PotentialUtf8::from_boxed_str(boxed_str))
222 } else {
223 let boxed_bytes = Box::<[u8]>::deserialize(deserializer)?;
224 Ok(PotentialUtf8::from_boxed_bytes(boxed_bytes))
225 }
226 }
227}
228
229#[cfg(feature = "serde")]
231impl<'de, 'a> serde_core::Deserialize<'de> for &'a PotentialUtf8
232where
233 'de: 'a,
234{
235 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
236 where
237 D: serde_core::Deserializer<'de>,
238 {
239 if deserializer.is_human_readable() {
240 let s = <&str>::deserialize(deserializer)?;
241 Ok(PotentialUtf8::from_str(s))
242 } else {
243 let bytes = <&[u8]>::deserialize(deserializer)?;
244 Ok(PotentialUtf8::from_bytes(bytes))
245 }
246 }
247}
248
249#[repr(transparent)]
250#[derive(#[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl ::core::cmp::PartialEq for PotentialUtf16 {
#[inline]
fn eq(&self, other: &PotentialUtf16) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl ::core::cmp::Eq for PotentialUtf16 {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<[u16]>;
}
}Eq, #[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl ::core::cmp::PartialOrd for PotentialUtf16 {
#[inline]
fn partial_cmp(&self, other: &PotentialUtf16)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
}
}PartialOrd, #[automatically_derived]
#[allow(clippy::exhaustive_structs)]
impl ::core::cmp::Ord for PotentialUtf16 {
#[inline]
fn cmp(&self, other: &PotentialUtf16) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord)]
251#[allow(clippy::exhaustive_structs)] pub struct PotentialUtf16(pub [u16]);
253
254impl fmt::Debug for PotentialUtf16 {
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 for c in char::decode_utf16(self.0.iter().copied()) {
258 match c {
259 Ok(c) => f.write_fmt(format_args!("{0}", c))write!(f, "{c}")?,
260 Err(e) => f.write_fmt(format_args!("\\0x{0:x}", e.unpaired_surrogate()))write!(f, "\\0x{:x}", e.unpaired_surrogate())?,
261 }
262 }
263 Ok(())
264 }
265}
266
267impl PotentialUtf16 {
268 #[inline]
270 pub const fn from_slice(other: &[u16]) -> &Self {
271 unsafe { core::mem::transmute(other) }
273 }
274
275 pub fn chars(&self) -> impl Iterator<Item = char> + '_ {
276 char::decode_utf16(self.0.iter().copied()).map(|c| c.unwrap_or(char::REPLACEMENT_CHARACTER))
277 }
278}