Coverage Report

Created: 2026-09-14 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tinystr-0.8.4/src/unvalidated.rs
Line
Count
Source
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
5
use crate::ParseError;
6
use crate::TinyAsciiStr;
7
use 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(PartialEq, PartialOrd, Eq, Ord, Clone, Copy)]
17
pub struct UnvalidatedTinyAsciiStr<const N: usize>(pub(crate) [u8; N]);
18
19
impl<const N: usize> fmt::Debug for UnvalidatedTinyAsciiStr<N> {
20
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21
        // Debug as a string if possible
22
0
        match self.try_into_tinystr() {
23
0
            Ok(s) => fmt::Debug::fmt(&s, f),
24
0
            Err(_) => fmt::Debug::fmt(&self.0, f),
25
        }
26
0
    }
27
}
28
29
impl<const N: usize> UnvalidatedTinyAsciiStr<N> {
30
    #[inline]
31
    /// Converts into a [`TinyAsciiStr`]. Fails if the bytes are not valid ASCII.
32
0
    pub fn try_into_tinystr(self) -> Result<TinyAsciiStr<N>, ParseError> {
33
0
        TinyAsciiStr::try_from_raw(self.0)
34
0
    }
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
0
    pub fn try_from_utf8(bytes: &[u8]) -> Result<Self, ParseError> {
40
0
        if bytes.len() > N {
41
0
            return Err(ParseError::TooLong {
42
0
                max: N,
43
0
                len: bytes.len(),
44
0
            });
45
0
        }
46
0
        let mut target = [0u8; N];
47
0
        target[0..bytes.len()].copy_from_slice(bytes);
48
0
        Ok(Self(target))
49
0
    }
50
51
    #[inline]
52
    /// Creates one of these from a raw byte array.
53
0
    pub const fn from_utf8_unchecked(bytes: [u8; N]) -> Self {
54
0
        Self(bytes)
55
0
    }
56
57
    #[inline]
58
    /// Returns the empty string.
59
0
    pub const fn default() -> Self {
60
0
        TinyAsciiStr::EMPTY.to_unvalidated()
61
0
    }
62
}
63
64
impl<const N: usize> Default for UnvalidatedTinyAsciiStr<N> {
65
0
    fn default() -> Self {
66
0
        Self::default()
67
0
    }
68
}
69
70
impl<const N: usize> TinyAsciiStr<N> {
71
    #[inline]
72
    // Converts into a [`UnvalidatedTinyAsciiStr`]
73
0
    pub const fn to_unvalidated(self) -> UnvalidatedTinyAsciiStr<N> {
74
0
        UnvalidatedTinyAsciiStr(*self.all_bytes())
75
0
    }
76
}
77
78
impl<const N: usize> From<TinyAsciiStr<N>> for UnvalidatedTinyAsciiStr<N> {
79
0
    fn from(other: TinyAsciiStr<N>) -> Self {
80
0
        other.to_unvalidated()
81
0
    }
82
}
83
84
#[cfg(feature = "serde")]
85
impl<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
97
macro_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
118
deserialize!(1);
119
deserialize!(2);
120
deserialize!(3);
121
deserialize!(4);
122
deserialize!(5);
123
deserialize!(6);
124
deserialize!(7);
125
deserialize!(8);
126
deserialize!(9);
127
deserialize!(10);
128
deserialize!(11);
129
deserialize!(12);
130
deserialize!(13);
131
deserialize!(14);
132
deserialize!(15);
133
deserialize!(16);
134
deserialize!(17);
135
deserialize!(18);
136
deserialize!(19);
137
deserialize!(20);
138
deserialize!(21);
139
deserialize!(22);
140
deserialize!(23);
141
deserialize!(24);
142
deserialize!(25);
143
deserialize!(26);
144
deserialize!(27);
145
deserialize!(28);
146
deserialize!(29);
147
deserialize!(30);
148
deserialize!(31);
149
deserialize!(32);