Revision control
Copy as Markdown
Other Tools
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
use crate::TinyAsciiStr;
use crate::TinyStrError;
use core::fmt;
/// A fixed-length bytes array that is expected to be an ASCII string but does not enforce that invariant.
///
/// Use this type instead of `TinyAsciiStr` if you don't need to enforce ASCII during deserialization. For
/// example, strings that are keys of a map don't need to ever be reified as `TinyAsciiStr`s.
///
/// The main advantage of this type over `[u8; N]` is that it serializes as a string in
/// human-readable formats like JSON.
#[derive(PartialEq, PartialOrd, Eq, Ord, Clone, Copy)]
pub struct UnvalidatedTinyAsciiStr<const N: usize>(pub(crate) [u8; N]);
impl<const N: usize> fmt::Debug for UnvalidatedTinyAsciiStr<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Debug as a string if possible
match self.try_into_tinystr() {
Ok(s) => fmt::Debug::fmt(&s, f),
Err(_) => fmt::Debug::fmt(&self.0, f),
}
}
}
impl<const N: usize> UnvalidatedTinyAsciiStr<N> {
#[inline]
// Converts into a [`TinyAsciiStr`]. Fails if the bytes are not valid ASCII.
pub fn try_into_tinystr(&self) -> Result<TinyAsciiStr<N>, TinyStrError> {
TinyAsciiStr::try_from_raw(self.0)
}
#[doc(hidden)]
pub const fn from_bytes_unchecked(bytes: [u8; N]) -> Self {
Self(bytes)
}
}
impl<const N: usize> TinyAsciiStr<N> {
#[inline]
// Converts into a [`UnvalidatedTinyAsciiStr`]
pub const fn to_unvalidated(self) -> UnvalidatedTinyAsciiStr<N> {
UnvalidatedTinyAsciiStr(*self.all_bytes())
}
}
impl<const N: usize> From<TinyAsciiStr<N>> for UnvalidatedTinyAsciiStr<N> {
fn from(other: TinyAsciiStr<N>) -> Self {
other.to_unvalidated()
}
}
#[cfg(feature = "serde")]
impl<const N: usize> serde::Serialize for UnvalidatedTinyAsciiStr<N> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::Error;
self.try_into_tinystr()
.map_err(|_| S::Error::custom("invalid ascii in UnvalidatedTinyAsciiStr"))?
.serialize(serializer)
}
}
macro_rules! deserialize {
($size:literal) => {
#[cfg(feature = "serde")]
impl<'de, 'a> serde::Deserialize<'de> for UnvalidatedTinyAsciiStr<$size>
where
'de: 'a,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
if deserializer.is_human_readable() {
Ok(TinyAsciiStr::deserialize(deserializer)?.to_unvalidated())
} else {
Ok(Self(<[u8; $size]>::deserialize(deserializer)?))
}
}
}
};
}
deserialize!(1);
deserialize!(2);
deserialize!(3);
deserialize!(4);
deserialize!(5);
deserialize!(6);
deserialize!(7);
deserialize!(8);
deserialize!(9);
deserialize!(10);
deserialize!(11);
deserialize!(12);
deserialize!(13);
deserialize!(14);
deserialize!(15);
deserialize!(16);
deserialize!(17);
deserialize!(18);
deserialize!(19);
deserialize!(20);
deserialize!(21);
deserialize!(22);
deserialize!(23);
deserialize!(24);
deserialize!(25);
deserialize!(26);
deserialize!(27);
deserialize!(28);
deserialize!(29);
deserialize!(30);
deserialize!(31);
deserialize!(32);