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::TinyAsciiStr;
6use crate::TinyStrError;
7
8/// A fixed-length bytes array that is expected to be an ASCII string but does not enforce that invariant.
9///
10/// Use this type instead of `TinyAsciiStr` if you don't need to enforce ASCII during deserialization. For
11/// example, strings that are keys of a map don't need to ever be reified as `TinyAsciiStr`s.
12///
13/// The main advantage of this type over `[u8; N]` is that it serializes as a string in
14/// human-readable formats like JSON.
15#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy)]
16pub struct UnvalidatedTinyAsciiStr<const N: usize>(pub(crate) [u8; N]);
17
18impl<const N: usize> UnvalidatedTinyAsciiStr<N> {
19 #[inline]
20 // Converts into a [`TinyAsciiStr`]. Fails if the bytes are not valid ASCII.
21 pub fn try_into_tinystr(&self) -> Result<TinyAsciiStr<N>, TinyStrError> {
22 TinyAsciiStr::try_from_raw(self.0)
23 }
24
25 #[doc(hidden)]
26 pub const fn from_bytes_unchecked(bytes: [u8; N]) -> Self {
27 Self(bytes)
28 }
29}
30
31impl<const N: usize> TinyAsciiStr<N> {
32 #[inline]
33 // Converts into a [`UnvalidatedTinyAsciiStr`]
34 pub const fn to_unvalidated(self) -> UnvalidatedTinyAsciiStr<N> {
35 UnvalidatedTinyAsciiStr(*self.all_bytes())
36 }
37}
38
39#[cfg(feature = "serde")]
40impl<const N: usize> serde::Serialize for UnvalidatedTinyAsciiStr<N> {
41 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
42 where
43 S: serde::Serializer,
44 {
45 use serde::ser::Error;
46 self.try_into_tinystr()
47 .map_err(|_| S::Error::custom("invalid ascii in UnvalidatedTinyAsciiStr"))?
48 .serialize(serializer)
49 }
50}
51
52macro_rules! deserialize {
53 ($size:literal) => {
54 #[cfg(feature = "serde")]
55 impl<'de, 'a> serde::Deserialize<'de> for UnvalidatedTinyAsciiStr<$size>
56 where
57 'de: 'a,
58 {
59 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
60 where
61 D: serde::Deserializer<'de>,
62 {
63 if deserializer.is_human_readable() {
64 Ok(TinyAsciiStr::deserialize(deserializer)?.to_unvalidated())
65 } else {
66 Ok(Self(<[u8; $size]>::deserialize(deserializer)?))
67 }
68 }
69 }
70 };
71}
72
73deserialize!(1);
74deserialize!(2);
75deserialize!(3);
76deserialize!(4);
77deserialize!(5);
78deserialize!(6);
79deserialize!(7);
80deserialize!(8);
81deserialize!(9);
82deserialize!(10);
83deserialize!(11);
84deserialize!(12);
85deserialize!(13);
86deserialize!(14);
87deserialize!(15);
88deserialize!(16);
89deserialize!(17);
90deserialize!(18);
91deserialize!(19);
92deserialize!(20);
93deserialize!(21);
94deserialize!(22);
95deserialize!(23);
96deserialize!(24);
97deserialize!(25);
98deserialize!(26);
99deserialize!(27);
100deserialize!(28);
101deserialize!(29);
102deserialize!(30);
103deserialize!(31);
104deserialize!(32);
105