1use core::ops::Deref;
3
4use embedded_io::Write;
5
6use crate::{CborLen, Decode, Encode, Encoder, InvalidHeader, TAGGED, primitive, type_of};
7
8#[derive(#[automatically_derived]
impl<E: ::core::fmt::Debug> ::core::fmt::Debug for Error<E> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Error::Malformed(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Malformed", &__self_0),
Error::InvalidTag =>
::core::fmt::Formatter::write_str(f, "InvalidTag"),
Error::Inner(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Inner",
&__self_0),
}
}
}Debug, #[automatically_derived]
impl<E: ::core::clone::Clone> ::core::clone::Clone for Error<E> {
#[inline]
fn clone(&self) -> Error<E> {
match self {
Error::Malformed(__self_0) =>
Error::Malformed(::core::clone::Clone::clone(__self_0)),
Error::InvalidTag => Error::InvalidTag,
Error::Inner(__self_0) =>
Error::Inner(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl<E: ::core::marker::Copy> ::core::marker::Copy for Error<E> { }Copy, #[automatically_derived]
impl<E: ::core::cmp::PartialEq> ::core::cmp::PartialEq for Error<E> {
#[inline]
fn eq(&self, other: &Error<E>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Error::Malformed(__self_0), Error::Malformed(__arg1_0)) =>
__self_0 == __arg1_0,
(Error::Inner(__self_0), Error::Inner(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl<E: ::core::cmp::Eq> ::core::cmp::Eq for Error<E> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<primitive::Error>;
let _: ::core::cmp::AssertParamIsEq<E>;
}
}Eq)]
10pub enum Error<E> {
11 Malformed(primitive::Error),
13 InvalidTag,
15 Inner(E),
17}
18
19impl<E: core::fmt::Display> core::fmt::Display for Error<E> {
20 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
21 match self {
22 Error::Malformed(e) => f.write_fmt(format_args!("{0}", e))write!(f, "{}", e),
23 Error::InvalidTag => f.write_fmt(format_args!("invalid tag"))write!(f, "invalid tag"),
24 Error::Inner(e) => f.write_fmt(format_args!("in tagged value: {0}", e))write!(f, "in tagged value: {}", e),
25 }
26 }
27}
28
29impl<E> From<primitive::Error> for Error<E> {
30 fn from(e: primitive::Error) -> Self {
31 Error::Malformed(e)
32 }
33}
34
35impl<E> From<crate::EndOfInput> for Error<E> {
36 fn from(e: crate::EndOfInput) -> Self {
37 Error::Malformed(primitive::Error::EndOfInput(e))
38 }
39}
40
41impl<E: core::error::Error + 'static> core::error::Error for Error<E> {
42 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
43 match self {
44 Error::Malformed(e) => Some(e),
45 Error::InvalidTag => None,
46 Error::Inner(e) => Some(e),
47 }
48 }
49}
50
51#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug + ?Sized, const N : u64> ::core::fmt::Debug for
Tagged<T, N> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Tagged",
&&self.0)
}
}Debug, #[automatically_derived]
impl<T: ::core::marker::Copy + ?Sized, const N : u64> ::core::marker::Copy for
Tagged<T, N> {
}Copy, #[automatically_derived]
impl<T: ::core::clone::Clone + ?Sized, const N : u64> ::core::clone::Clone for
Tagged<T, N> {
#[inline]
fn clone(&self) -> Tagged<T, N> {
Tagged(::core::clone::Clone::clone(&self.0))
}
}Clone, #[automatically_derived]
impl<T: ::core::default::Default + ?Sized, const N : u64>
::core::default::Default for Tagged<T, N> {
#[inline]
fn default() -> Tagged<T, N> {
Tagged(::core::default::Default::default())
}
}Default, #[automatically_derived]
impl<T: ::core::cmp::PartialEq + ?Sized, const N : u64> ::core::cmp::PartialEq
for Tagged<T, N> {
#[inline]
fn eq(&self, other: &Tagged<T, N>) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl<T: ::core::cmp::Eq + ?Sized, const N : u64> ::core::cmp::Eq for
Tagged<T, N> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<T>;
}
}Eq, #[automatically_derived]
impl<T: ::core::cmp::PartialOrd + ?Sized, const N : u64>
::core::cmp::PartialOrd for Tagged<T, N> {
#[inline]
fn partial_cmp(&self, other: &Tagged<T, N>)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
}
}PartialOrd, #[automatically_derived]
impl<T: ::core::cmp::Ord + ?Sized, const N : u64> ::core::cmp::Ord for
Tagged<T, N> {
#[inline]
fn cmp(&self, other: &Tagged<T, N>) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord, #[automatically_derived]
impl<T: ::core::hash::Hash + ?Sized, const N : u64> ::core::hash::Hash for
Tagged<T, N> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.0, state)
}
}Hash)]
69#[repr(transparent)]
70pub struct Tagged<T: ?Sized, const N: u64>(pub T);
71
72impl<T, const N: u64> Tagged<T, N> {
73 pub fn into(self) -> T {
75 self.0
76 }
77}
78
79impl<T, const N: u64> From<T> for Tagged<T, N> {
80 fn from(val: T) -> Self {
81 Self(val)
82 }
83}
84
85impl<'a, T: ?Sized, const N: u64> From<&'a T> for &'a Tagged<T, N> {
86 fn from(val: &T) -> Self {
87 unsafe { &*(val as *const T as *const Tagged<T, N>) }
89 }
90}
91
92impl<T: ?Sized, const N: u64> AsRef<T> for Tagged<T, N> {
93 fn as_ref(&self) -> &T {
94 &self.0
95 }
96}
97
98impl<T: ?Sized, const N: u64> AsMut<T> for Tagged<T, N> {
99 fn as_mut(&mut self) -> &mut T {
100 &mut self.0
101 }
102}
103
104impl<T: ?Sized, const N: u64> Deref for Tagged<T, N> {
105 type Target = T;
106
107 fn deref(&self) -> &Self::Target {
108 &self.0
109 }
110}
111
112impl<T: ?Sized, const N: u64> core::ops::DerefMut for Tagged<T, N> {
113 fn deref_mut(&mut self) -> &mut Self::Target {
114 &mut self.0
115 }
116}
117
118impl<'a, T, const N: u64> Decode<'a> for Tagged<T, N>
119where
120 T: Decode<'a>,
121{
122 type Error = Error<T::Error>;
123
124 fn decode(d: &mut crate::Decoder<'a>) -> Result<Self, Self::Error> {
125 let b = d
126 .peek()
127 .map_err(|e| Error::Malformed(primitive::Error::from(e)))?;
128 if TAGGED != type_of(b) {
129 return Err(Error::Malformed(primitive::Error::InvalidHeader(
130 InvalidHeader,
131 )));
132 }
133 if d.unsigned().map_err(Error::Malformed)? != N {
134 return Err(Error::InvalidTag);
135 }
136
137 T::decode(d).map(Tagged::<T, N>).map_err(Error::Inner)
138 }
139}
140
141impl<const N: u64, T: Encode + ?Sized> Encode for Tagged<T, N> {
142 fn encode<W: Write>(&self, e: &mut Encoder<W>) -> Result<(), W::Error> {
143 e.type_len(TAGGED, N)?;
144 self.0.encode(e)
145 }
146}
147
148impl<const N: u64, T: CborLen + ?Sized> CborLen for Tagged<T, N> {
149 fn cbor_len(&self) -> usize {
150 N.cbor_len() + self.0.cbor_len()
151 }
152}
153
154#[derive(#[automatically_derived]
impl ::core::clone::Clone for IanaTag {
#[inline]
fn clone(&self) -> IanaTag { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for IanaTag { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for IanaTag {
#[inline]
fn eq(&self, other: &IanaTag) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::PartialOrd for IanaTag {
#[inline]
fn partial_cmp(&self, other: &IanaTag)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Eq for IanaTag {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}Eq, #[automatically_derived]
impl ::core::cmp::Ord for IanaTag {
#[inline]
fn cmp(&self, other: &IanaTag) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
}
}Ord, #[automatically_derived]
impl ::core::fmt::Debug for IanaTag {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
IanaTag::DateTime => "DateTime",
IanaTag::Timestamp => "Timestamp",
IanaTag::PosBignum => "PosBignum",
IanaTag::NegBignum => "NegBignum",
IanaTag::Decimal => "Decimal",
IanaTag::Bigfloat => "Bigfloat",
IanaTag::ToBase64Url => "ToBase64Url",
IanaTag::ToBase64 => "ToBase64",
IanaTag::ToBase16 => "ToBase16",
IanaTag::Cbor => "Cbor",
IanaTag::Uri => "Uri",
IanaTag::Base64Url => "Base64Url",
IanaTag::Base64 => "Base64",
IanaTag::Regex => "Regex",
IanaTag::Mime => "Mime",
IanaTag::MultiDimArrayR => "MultiDimArrayR",
IanaTag::HomogenousArray => "HomogenousArray",
IanaTag::TypedArrayU8 => "TypedArrayU8",
IanaTag::TypedArrayU16B => "TypedArrayU16B",
IanaTag::TypedArrayU32B => "TypedArrayU32B",
IanaTag::TypedArrayU64B => "TypedArrayU64B",
IanaTag::TypedArrayU8Clamped => "TypedArrayU8Clamped",
IanaTag::TypedArrayU16L => "TypedArrayU16L",
IanaTag::TypedArrayU32L => "TypedArrayU32L",
IanaTag::TypedArrayU64L => "TypedArrayU64L",
IanaTag::TypedArrayI8 => "TypedArrayI8",
IanaTag::TypedArrayI16B => "TypedArrayI16B",
IanaTag::TypedArrayI32B => "TypedArrayI32B",
IanaTag::TypedArrayI64B => "TypedArrayI64B",
IanaTag::TypedArrayI16L => "TypedArrayI16L",
IanaTag::TypedArrayI32L => "TypedArrayI32L",
IanaTag::TypedArrayI64L => "TypedArrayI64L",
IanaTag::TypedArrayF16B => "TypedArrayF16B",
IanaTag::TypedArrayF32B => "TypedArrayF32B",
IanaTag::TypedArrayF64B => "TypedArrayF64B",
IanaTag::TypedArrayF128B => "TypedArrayF128B",
IanaTag::TypedArrayF16L => "TypedArrayF16L",
IanaTag::TypedArrayF32L => "TypedArrayF32L",
IanaTag::TypedArrayF64L => "TypedArrayF64L",
IanaTag::TypedArrayF128L => "TypedArrayF128L",
IanaTag::MultiDimArrayC => "MultiDimArrayC",
})
}
}Debug, #[automatically_derived]
impl ::core::hash::Hash for IanaTag {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}Hash)]
158#[repr(u64)]
159#[non_exhaustive]
160pub enum IanaTag {
161 DateTime = 0x00,
162 Timestamp = 0x01,
163 PosBignum = 0x02,
164 NegBignum = 0x03,
165 Decimal = 0x04,
166 Bigfloat = 0x05,
167 ToBase64Url = 0x15,
168 ToBase64 = 0x16,
169 ToBase16 = 0x17,
170 Cbor = 0x18,
171 Uri = 0x20,
172 Base64Url = 0x21,
173 Base64 = 0x22,
174 Regex = 0x23,
175 Mime = 0x24,
176 MultiDimArrayR = 0x28, HomogenousArray = 0x29,
179 TypedArrayU8 = 0x40,
180 TypedArrayU16B = 0x41,
181 TypedArrayU32B = 0x42,
182 TypedArrayU64B = 0x43,
183 TypedArrayU8Clamped = 0x44,
184 TypedArrayU16L = 0x45,
185 TypedArrayU32L = 0x46,
186 TypedArrayU64L = 0x47,
187 TypedArrayI8 = 0x48,
188 TypedArrayI16B = 0x49,
189 TypedArrayI32B = 0x4a,
190 TypedArrayI64B = 0x4b,
191 TypedArrayI16L = 0x4d,
192 TypedArrayI32L = 0x4e,
193 TypedArrayI64L = 0x4f,
194 TypedArrayF16B = 0x50,
195 TypedArrayF32B = 0x51,
196 TypedArrayF64B = 0x52,
197 TypedArrayF128B = 0x53,
198 TypedArrayF16L = 0x54,
199 TypedArrayF32L = 0x55,
200 TypedArrayF64L = 0x56,
201 TypedArrayF128L = 0x57,
202 MultiDimArrayC = 0x410, }
204
205impl TryFrom<u64> for IanaTag {
206 type Error = Unknown;
207
208 fn try_from(t: u64) -> Result<Self, Self::Error> {
209 match t {
210 0x00 => Ok(Self::DateTime),
211 0x01 => Ok(Self::Timestamp),
212 0x02 => Ok(Self::PosBignum),
213 0x03 => Ok(Self::NegBignum),
214 0x04 => Ok(Self::Decimal),
215 0x05 => Ok(Self::Bigfloat),
216 0x15 => Ok(Self::ToBase64Url),
217 0x16 => Ok(Self::ToBase64),
218 0x17 => Ok(Self::ToBase16),
219 0x18 => Ok(Self::Cbor),
220 0x20 => Ok(Self::Uri),
221 0x21 => Ok(Self::Base64Url),
222 0x22 => Ok(Self::Base64),
223 0x23 => Ok(Self::Regex),
224 0x24 => Ok(Self::Mime),
225 0x28 => Ok(Self::MultiDimArrayR),
226 0x29 => Ok(Self::HomogenousArray),
227 0x40 => Ok(Self::TypedArrayU8),
228 0x41 => Ok(Self::TypedArrayU16B),
229 0x42 => Ok(Self::TypedArrayU32B),
230 0x43 => Ok(Self::TypedArrayU64B),
231 0x44 => Ok(Self::TypedArrayU8Clamped),
232 0x45 => Ok(Self::TypedArrayU16L),
233 0x46 => Ok(Self::TypedArrayU32L),
234 0x47 => Ok(Self::TypedArrayU64L),
235 0x48 => Ok(Self::TypedArrayI8),
236 0x49 => Ok(Self::TypedArrayI16B),
237 0x4a => Ok(Self::TypedArrayI32B),
238 0x4b => Ok(Self::TypedArrayI64B),
239 0x4d => Ok(Self::TypedArrayI16L),
240 0x4e => Ok(Self::TypedArrayI32L),
241 0x4f => Ok(Self::TypedArrayI64L),
242 0x50 => Ok(Self::TypedArrayF16B),
243 0x51 => Ok(Self::TypedArrayF32B),
244 0x52 => Ok(Self::TypedArrayF64B),
245 0x53 => Ok(Self::TypedArrayF128B),
246 0x54 => Ok(Self::TypedArrayF16L),
247 0x55 => Ok(Self::TypedArrayF32L),
248 0x56 => Ok(Self::TypedArrayF64L),
249 0x57 => Ok(Self::TypedArrayF128L),
250 0x410 => Ok(Self::MultiDimArrayC),
251 _ => Err(Unknown),
252 }
253 }
254}
255
256#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Unknown {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Unknown")
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Unknown {
#[inline]
fn clone(&self) -> Unknown { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Unknown { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for Unknown {
#[inline]
fn eq(&self, other: &Unknown) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Unknown {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Unknown {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {}
}Hash)]
258pub struct Unknown;
259
260impl core::fmt::Display for Unknown {
261 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
262 f.write_fmt(format_args!("unknown IANA tag"))write!(f, "unknown IANA tag")
263 }
264}
265
266impl core::error::Error for Unknown {}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271 use crate::test;
272
273 #[test]
274 fn u32() {
275 let cbor = [0xc0, 0x18, 0x2a];
276 assert!(test::<Tagged<u32, 0>>(Tagged(42), &cbor).unwrap());
277 }
278
279 #[test]
280 fn string() {
281 let cbor = [
282 0xc0, 0x74, 0x32, 0x30, 0x31, 0x33, 0x2d, 0x30, 0x33, 0x2d, 0x32, 0x31, 0x54, 0x32,
283 0x30, 0x3a, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x5a,
284 ];
285 assert!(test::<Tagged<&str, 0>>(Tagged("2013-03-21T20:04:00Z"), &cbor).unwrap());
286 }
287
288 #[test]
289 fn bignum() {
290 let cbor = [0xc2, 0x42, 0x01, 0x00];
291 assert!(test::<Tagged<&[u8], 2>>(Tagged(&[0x01, 0x00]), &cbor).unwrap());
292 }
293
294 #[test]
295 fn uri() {
296 let cbor = [
297 0xd8, 0x20, 0x6b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x61, 0x2e, 0x62, 0x63,
298 ];
299 assert!(test::<Tagged<&str, 32>>(Tagged("http://a.bc"), &cbor).unwrap());
300 }
301
302 #[test]
303 fn invalid() {
304 use crate::Decoder;
305 let cbor = [0xc0, 0x18, 0x2a];
306 let err = <Tagged<u32, 1>>::decode(&mut Decoder(&cbor)).unwrap_err();
307 assert_eq!(err, Error::InvalidTag);
308 }
309
310 #[test]
311 fn untagged() {
312 use crate::Decoder;
313 let cbor = [0x18, 0x2a];
314 let err = <Tagged<u32, 0>>::decode(&mut Decoder(&cbor)).unwrap_err();
315 assert_eq!(
316 err,
317 Error::Malformed(primitive::Error::InvalidHeader(InvalidHeader))
318 );
319 }
320}