Skip to main content

tinystr/
unvalidated.rs

1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5use crate::ParseError;
6use crate::TinyAsciiStr;
7use core::fmt;
8
9/// A fixed-length bytes array that is expected to be an ASCII string but does not enforce that invariant.
10///
11/// Use this type instead of `TinyAsciiStr` if you don't need to enforce ASCII during deserialization. For
12/// example, strings that are keys of a map don't need to ever be reified as `TinyAsciiStr`s.
13///
14/// The main advantage of this type over `[u8; N]` is that it serializes as a string in
15/// human-readable formats like JSON.
16#[derive(#[automatically_derived]
impl<const N : usize> ::core::cmp::PartialEq for UnvalidatedTinyAsciiStr<N> {
    #[inline]
    fn eq(&self, other: &UnvalidatedTinyAsciiStr<N>) -> bool {
        self.0 == other.0
    }
}PartialEq, #[automatically_derived]
impl<const N : usize> ::core::cmp::PartialOrd for UnvalidatedTinyAsciiStr<N> {
    #[inline]
    fn partial_cmp(&self, other: &UnvalidatedTinyAsciiStr<N>)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd, #[automatically_derived]
impl<const N : usize> ::core::cmp::Eq for UnvalidatedTinyAsciiStr<N> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<[u8; N]>;
    }
}Eq, #[automatically_derived]
impl<const N : usize> ::core::cmp::Ord for UnvalidatedTinyAsciiStr<N> {
    #[inline]
    fn cmp(&self, other: &UnvalidatedTinyAsciiStr<N>)
        -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.0, &other.0)
    }
}Ord, #[automatically_derived]
impl<const N : usize> ::core::clone::Clone for UnvalidatedTinyAsciiStr<N> {
    #[inline]
    fn clone(&self) -> UnvalidatedTinyAsciiStr<N> {
        let _: ::core::clone::AssertParamIsClone<[u8; N]>;
        *self
    }
}Clone, #[automatically_derived]
impl<const N : usize> ::core::marker::Copy for UnvalidatedTinyAsciiStr<N> { }Copy)]
17pub struct UnvalidatedTinyAsciiStr<const N: usize>(pub(crate) [u8; N]);
18
19impl<const N: usize> fmt::Debug for UnvalidatedTinyAsciiStr<N> {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        // Debug as a string if possible
22        match self.try_into_tinystr() {
23            Ok(s) => fmt::Debug::fmt(&s, f),
24            Err(_) => fmt::Debug::fmt(&self.0, f),
25        }
26    }
27}
28
29impl<const N: usize> UnvalidatedTinyAsciiStr<N> {
30    #[inline]
31    /// Converts into a [`TinyAsciiStr`]. Fails if the bytes are not valid ASCII.
32    pub fn try_into_tinystr(self) -> Result<TinyAsciiStr<N>, ParseError> {
33        TinyAsciiStr::try_from_raw(self.0)
34    }
35
36    #[inline]
37    /// Creates one of these from a byte slice. Fails if the bytes are too long, but
38    /// does not check whether the bytes are a valid ASCII string.
39    pub fn try_from_utf8(bytes: &[u8]) -> Result<Self, ParseError> {
40        if bytes.len() > N {
41            return Err(ParseError::TooLong {
42                max: N,
43                len: bytes.len(),
44            });
45        }
46        let mut target = [0u8; N];
47        target[0..bytes.len()].copy_from_slice(bytes);
48        Ok(Self(target))
49    }
50
51    #[inline]
52    /// Creates one of these from a raw byte array.
53    pub const fn from_utf8_unchecked(bytes: [u8; N]) -> Self {
54        Self(bytes)
55    }
56
57    #[inline]
58    /// Returns the empty string.
59    pub const fn default() -> Self {
60        TinyAsciiStr::EMPTY.to_unvalidated()
61    }
62}
63
64impl<const N: usize> Default for UnvalidatedTinyAsciiStr<N> {
65    fn default() -> Self {
66        Self::default()
67    }
68}
69
70impl<const N: usize> TinyAsciiStr<N> {
71    #[inline]
72    // Converts into a [`UnvalidatedTinyAsciiStr`]
73    pub const fn to_unvalidated(self) -> UnvalidatedTinyAsciiStr<N> {
74        UnvalidatedTinyAsciiStr(*self.all_bytes())
75    }
76}
77
78impl<const N: usize> From<TinyAsciiStr<N>> for UnvalidatedTinyAsciiStr<N> {
79    fn from(other: TinyAsciiStr<N>) -> Self {
80        other.to_unvalidated()
81    }
82}
83
84#[cfg(feature = "serde")]
85impl<const N: usize> serde_core::Serialize for UnvalidatedTinyAsciiStr<N> {
86    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
87    where
88        S: serde_core::Serializer,
89    {
90        use serde_core::ser::Error;
91        self.try_into_tinystr()
92            .map_err(|_| S::Error::custom("invalid ascii in UnvalidatedTinyAsciiStr"))?
93            .serialize(serializer)
94    }
95}
96
97macro_rules! deserialize {
98    ($size:literal) => {
99        #[cfg(feature = "serde")]
100        impl<'de, 'a> serde_core::Deserialize<'de> for UnvalidatedTinyAsciiStr<$size>
101        where
102            'de: 'a,
103        {
104            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
105            where
106                D: serde_core::Deserializer<'de>,
107            {
108                if deserializer.is_human_readable() {
109                    Ok(TinyAsciiStr::deserialize(deserializer)?.to_unvalidated())
110                } else {
111                    Ok(Self(<[u8; $size]>::deserialize(deserializer)?))
112                }
113            }
114        }
115    };
116}
117
118deserialize!(1);
119deserialize!(2);
120deserialize!(3);
121deserialize!(4);
122deserialize!(5);
123deserialize!(6);
124deserialize!(7);
125deserialize!(8);
126deserialize!(9);
127deserialize!(10);
128deserialize!(11);
129deserialize!(12);
130deserialize!(13);
131deserialize!(14);
132deserialize!(15);
133deserialize!(16);
134deserialize!(17);
135deserialize!(18);
136deserialize!(19);
137deserialize!(20);
138deserialize!(21);
139deserialize!(22);
140deserialize!(23);
141deserialize!(24);
142deserialize!(25);
143deserialize!(26);
144deserialize!(27);
145deserialize!(28);
146deserialize!(29);
147deserialize!(30);
148deserialize!(31);
149deserialize!(32);