summaryrefslogtreecommitdiffstats
path: root/third_party/rust/tinystr/src/unvalidated.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/tinystr/src/unvalidated.rs')
-rw-r--r--third_party/rust/tinystr/src/unvalidated.rs104
1 files changed, 104 insertions, 0 deletions
diff --git a/third_party/rust/tinystr/src/unvalidated.rs b/third_party/rust/tinystr/src/unvalidated.rs
new file mode 100644
index 0000000000..2fffbbc119
--- /dev/null
+++ b/third_party/rust/tinystr/src/unvalidated.rs
@@ -0,0 +1,104 @@
+// 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
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+use crate::TinyAsciiStr;
+use crate::TinyStrError;
+
+/// 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(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy)]
+pub struct UnvalidatedTinyAsciiStr<const N: usize>(pub(crate) [u8; N]);
+
+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())
+ }
+}
+
+#[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);