sonic_rs/
input.rs

1use bytes::Bytes;
2use faststr::FastStr;
3
4use crate::{parser::as_str, util::private::Sealed};
5
6/// JsonSlice is a wrapper for different json input.
7#[doc(hidden)]
8#[non_exhaustive]
9#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
10pub enum JsonSlice<'de> {
11    Raw(&'de [u8]),
12    FastStr(FastStr), // note: FastStr maybe inlined and in the stack.
13}
14
15impl<'de> JsonSlice<'de> {
16    #[inline(always)]
17    pub(crate) unsafe fn as_faststr(&self) -> FastStr {
18        match self {
19            JsonSlice::Raw(sub) => FastStr::new(as_str(sub)),
20            JsonSlice::FastStr(f) => f.clone(),
21        }
22    }
23}
24
25impl Default for JsonSlice<'_> {
26    fn default() -> Self {
27        JsonSlice::Raw(&b"null"[..])
28    }
29}
30
31impl<'de> From<FastStr> for JsonSlice<'de> {
32    fn from(value: FastStr) -> Self {
33        JsonSlice::FastStr(value)
34    }
35}
36
37impl<'de> From<Bytes> for JsonSlice<'de> {
38    fn from(value: Bytes) -> Self {
39        JsonSlice::FastStr(unsafe { FastStr::from_bytes_unchecked(value) })
40    }
41}
42
43impl<'de> From<&'de [u8]> for JsonSlice<'de> {
44    fn from(value: &'de [u8]) -> Self {
45        JsonSlice::Raw(value)
46    }
47}
48
49impl<'de> From<&'de str> for JsonSlice<'de> {
50    fn from(value: &'de str) -> Self {
51        JsonSlice::Raw(value.as_bytes())
52    }
53}
54
55impl<'de> From<&'de String> for JsonSlice<'de> {
56    fn from(value: &'de String) -> Self {
57        JsonSlice::Raw(value.as_bytes())
58    }
59}
60
61impl From<String> for JsonSlice<'_> {
62    fn from(value: String) -> Self {
63        JsonSlice::FastStr(FastStr::new(value))
64    }
65}
66
67impl<'de> AsRef<[u8]> for JsonSlice<'de> {
68    fn as_ref(&self) -> &[u8] {
69        match self {
70            Self::Raw(r) => r,
71            Self::FastStr(s) => s.as_bytes(),
72        }
73    }
74}
75
76/// A trait for string/bytes-like types that can be parsed into JSON.
77pub trait JsonInput<'de>: Sealed {
78    fn need_utf8_valid(&self) -> bool;
79    fn to_json_slice(&self) -> JsonSlice<'de>;
80    #[allow(clippy::wrong_self_convention)]
81    fn from_subset(&self, sub: &'de [u8]) -> JsonSlice<'de>;
82    fn to_u8_slice(&self) -> &'de [u8];
83}
84
85impl<'de> JsonInput<'de> for &'de [u8] {
86    fn need_utf8_valid(&self) -> bool {
87        true
88    }
89
90    fn to_json_slice(&self) -> JsonSlice<'de> {
91        JsonSlice::Raw(self)
92    }
93
94    fn from_subset(&self, sub: &'de [u8]) -> JsonSlice<'de> {
95        sub.into()
96    }
97
98    fn to_u8_slice(&self) -> &'de [u8] {
99        self
100    }
101}
102
103impl<'de> JsonInput<'de> for &'de str {
104    fn need_utf8_valid(&self) -> bool {
105        false
106    }
107    fn to_json_slice(&self) -> JsonSlice<'de> {
108        JsonSlice::Raw((*self).as_bytes())
109    }
110
111    fn from_subset(&self, sub: &'de [u8]) -> JsonSlice<'de> {
112        sub.into()
113    }
114
115    fn to_u8_slice(&self) -> &'de [u8] {
116        (*self).as_bytes()
117    }
118}
119
120impl<'de> JsonInput<'de> for &'de Bytes {
121    fn need_utf8_valid(&self) -> bool {
122        true
123    }
124
125    fn to_json_slice(&self) -> JsonSlice<'de> {
126        let bytes = self.as_ref();
127        let newed = self.slice_ref(bytes);
128        JsonSlice::FastStr(unsafe { FastStr::from_bytes_unchecked(newed) })
129    }
130
131    fn from_subset(&self, sub: &'de [u8]) -> JsonSlice<'de> {
132        self.slice_ref(sub).into()
133    }
134
135    fn to_u8_slice(&self) -> &'de [u8] {
136        (*self).as_ref()
137    }
138}
139
140impl<'de> JsonInput<'de> for &'de FastStr {
141    fn need_utf8_valid(&self) -> bool {
142        false
143    }
144
145    fn to_json_slice(&self) -> JsonSlice<'de> {
146        JsonSlice::FastStr((**self).clone())
147    }
148
149    fn from_subset(&self, sub: &'de [u8]) -> JsonSlice<'de> {
150        self.slice_ref(as_str(sub)).into()
151    }
152
153    fn to_u8_slice(&self) -> &'de [u8] {
154        (*self).as_ref()
155    }
156}
157
158impl<'de> JsonInput<'de> for &'de String {
159    fn need_utf8_valid(&self) -> bool {
160        false
161    }
162
163    fn to_json_slice(&self) -> JsonSlice<'de> {
164        JsonSlice::Raw(self.as_bytes())
165    }
166
167    fn from_subset(&self, sub: &'de [u8]) -> JsonSlice<'de> {
168        sub.into()
169    }
170
171    fn to_u8_slice(&self) -> &'de [u8] {
172        (*self).as_bytes()
173    }
174}