1use crate::{CborError, DecodeLimits, ErrorCode};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct CanonicalCborRef<'a> {
13 bytes: &'a [u8],
14}
15
16impl<'a> CanonicalCborRef<'a> {
17 #[inline]
18 pub(crate) const fn new(bytes: &'a [u8]) -> Self {
19 Self { bytes }
20 }
21
22 #[inline]
24 #[must_use]
25 pub const fn as_bytes(self) -> &'a [u8] {
26 self.bytes
27 }
28
29 #[cfg(feature = "unsafe")]
35 #[cfg_attr(docsrs, doc(cfg(feature = "unsafe")))]
36 #[inline]
37 #[must_use]
38 pub const unsafe fn from_canonical(bytes: &'a [u8]) -> Self {
39 Self { bytes }
40 }
41
42 #[inline]
44 #[must_use]
45 pub const fn len(self) -> usize {
46 self.bytes.len()
47 }
48
49 #[inline]
51 #[must_use]
52 pub const fn is_empty(self) -> bool {
53 self.bytes.is_empty()
54 }
55
56 #[cfg(feature = "sha2")]
58 #[cfg_attr(docsrs, doc(cfg(feature = "sha2")))]
59 #[must_use]
60 pub fn sha256(self) -> [u8; 32] {
61 use sha2::{Digest, Sha256};
62 let mut h = Sha256::new();
63 h.update(self.bytes);
64 let out = h.finalize();
65 let mut digest = [0u8; 32];
66 digest.copy_from_slice(out.as_slice());
67 digest
68 }
69
70 #[cfg(feature = "alloc")]
74 #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
75 pub fn to_owned(self) -> Result<CanonicalCbor, CborError> {
80 use crate::alloc_util::try_vec_from_slice;
81
82 Ok(CanonicalCbor {
83 bytes: try_vec_from_slice(self.bytes, 0)?,
84 })
85 }
86
87 #[inline]
89 #[must_use]
90 pub fn bytes_eq(self, other: Self) -> bool {
91 self.bytes == other.bytes
92 }
93}
94
95impl AsRef<[u8]> for CanonicalCborRef<'_> {
96 fn as_ref(&self) -> &[u8] {
97 self.bytes
98 }
99}
100
101#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105pub struct EncodedTextKey<'a> {
106 bytes: &'a [u8],
107}
108
109impl<'a> EncodedTextKey<'a> {
110 #[cfg(feature = "alloc")]
111 #[inline]
112 pub(crate) const fn new_unchecked(bytes: &'a [u8]) -> Self {
113 Self { bytes }
114 }
115
116 pub fn parse(bytes: &'a [u8]) -> Result<Self, CborError> {
122 if bytes.is_empty() {
123 return Err(CborError::new(ErrorCode::UnexpectedEof, 0));
124 }
125 let limits = DecodeLimits::for_bytes(bytes.len());
126 crate::validate_canonical(bytes, limits)?;
127 if bytes[0] >> 5 != 3 {
128 return Err(CborError::new(ErrorCode::MapKeyMustBeText, 0));
129 }
130 Ok(Self { bytes })
131 }
132
133 #[inline]
135 #[must_use]
136 pub const fn as_bytes(self) -> &'a [u8] {
137 self.bytes
138 }
139}
140
141impl AsRef<[u8]> for EncodedTextKey<'_> {
142 fn as_ref(&self) -> &[u8] {
143 self.bytes
144 }
145}
146
147#[cfg(feature = "alloc")]
148use alloc::vec::Vec;
149
150#[cfg(feature = "alloc")]
154#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
155#[derive(Debug, Clone, PartialEq, Eq)]
156pub struct CanonicalCbor {
157 bytes: Vec<u8>,
158}
159
160#[cfg(feature = "alloc")]
161impl CanonicalCbor {
162 #[inline]
163 pub(crate) const fn new_unchecked(bytes: Vec<u8>) -> Self {
164 Self { bytes }
165 }
166
167 #[inline]
169 #[must_use]
170 pub fn bytes_eq(&self, other: &Self) -> bool {
171 self.bytes == other.bytes
172 }
173
174 pub fn from_slice(bytes: &[u8], limits: DecodeLimits) -> Result<Self, CborError> {
180 let canon = crate::validate_canonical(bytes, limits)?;
181 canon.to_owned()
182 }
183
184 pub fn from_vec(bytes: Vec<u8>, limits: DecodeLimits) -> Result<Self, CborError> {
190 crate::validate_canonical(&bytes, limits)?;
191 Ok(Self { bytes })
192 }
193
194 pub fn from_vec_default_limits(bytes: Vec<u8>) -> Result<Self, CborError> {
200 let limits = DecodeLimits::for_bytes(bytes.len());
201 Self::from_vec(bytes, limits)
202 }
203
204 #[inline]
206 #[must_use]
207 pub fn as_bytes(&self) -> &[u8] {
208 &self.bytes
209 }
210
211 #[inline]
213 #[must_use]
214 pub fn as_ref(&self) -> CanonicalCborRef<'_> {
215 CanonicalCborRef::new(self.as_bytes())
216 }
217
218 #[inline]
220 #[must_use]
221 pub fn into_bytes(self) -> Vec<u8> {
222 self.bytes
223 }
224
225 #[cfg(feature = "sha2")]
227 #[cfg_attr(docsrs, doc(cfg(feature = "sha2")))]
228 #[must_use]
229 pub fn sha256(&self) -> [u8; 32] {
230 CanonicalCborRef::new(&self.bytes).sha256()
231 }
232}
233
234#[cfg(feature = "alloc")]
235impl AsRef<[u8]> for CanonicalCbor {
236 fn as_ref(&self) -> &[u8] {
237 &self.bytes
238 }
239}
240
241#[cfg(feature = "serde")]
242mod serde_impls {
243 use super::{CanonicalCbor, CanonicalCborRef};
244 use crate::{validate_canonical, DecodeLimits};
245 use serde::de::{Error as DeError, Visitor};
246 use serde::{Deserialize, Deserializer, Serialize, Serializer};
247
248 impl Serialize for CanonicalCborRef<'_> {
249 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
250 serializer.serialize_bytes(self.as_bytes())
251 }
252 }
253
254 #[cfg(feature = "alloc")]
255 impl Serialize for CanonicalCbor {
256 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
257 serializer.serialize_bytes(self.as_bytes())
258 }
259 }
260
261 #[cfg(feature = "alloc")]
264 impl<'de> Deserialize<'de> for CanonicalCbor {
265 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
266 struct V;
267
268 impl<'de> Visitor<'de> for V {
269 type Value = CanonicalCbor;
270
271 fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
272 write!(f, "canonical CBOR bytes")
273 }
274
275 fn visit_byte_buf<E: DeError>(
276 self,
277 v: alloc::vec::Vec<u8>,
278 ) -> Result<Self::Value, E> {
279 let limits = DecodeLimits::for_bytes(v.len());
280 validate_canonical(&v, limits).map_err(E::custom)?;
281 Ok(CanonicalCbor::new_unchecked(v))
282 }
283
284 fn visit_borrowed_bytes<E: DeError>(self, v: &'de [u8]) -> Result<Self::Value, E> {
285 let limits = DecodeLimits::for_bytes(v.len());
286 validate_canonical(v, limits).map_err(E::custom)?;
287 let out = crate::alloc_util::try_vec_from_slice(v, 0).map_err(E::custom)?;
288 Ok(CanonicalCbor::new_unchecked(out))
289 }
290 }
291
292 deserializer.deserialize_bytes(V)
293 }
294 }
295}