webauthn_rp

WebAuthn Level 3 RP library.
git clone https://git.philomathiclife.com/repos/webauthn_rp
Log | Files | Refs | README

bin.rs (14076B)


      1 extern crate alloc;
      2 use alloc::borrow::Cow;
      3 use core::str;
      4 /// Unit error returned from [`Encode::encode_into_buffer`] and
      5 /// [`Decode::decode_from_buffer`] to simply signal an error occurred.
      6 pub(super) struct EncDecErr;
      7 /// Encodes data as a binary format into a passed `Vec` buffer with the possibility
      8 /// of erring.
      9 pub(super) trait EncodeBufferFallible {
     10     /// Error when [`Self::encode_into_buffer`] fails.
     11     type Err;
     12     /// Writes `self` into `buffer`.
     13     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err>;
     14 }
     15 /// Encodes data as a binary format into a passed `Vec` buffer.
     16 pub(super) trait EncodeBuffer {
     17     /// Writes `self` into `buffer`.
     18     fn encode_into_buffer(&self, buffer: &mut Vec<u8>);
     19 }
     20 impl EncodeBuffer for u8 {
     21     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     22         buffer.push(*self);
     23     }
     24 }
     25 impl EncodeBuffer for u16 {
     26     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     27         buffer.extend_from_slice(self.to_le_bytes().as_slice());
     28     }
     29 }
     30 impl EncodeBuffer for u32 {
     31     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     32         buffer.extend_from_slice(self.to_le_bytes().as_slice());
     33     }
     34 }
     35 impl EncodeBuffer for u64 {
     36     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     37         buffer.extend_from_slice(self.to_le_bytes().as_slice());
     38     }
     39 }
     40 impl EncodeBuffer for u128 {
     41     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     42         buffer.extend_from_slice(self.to_le_bytes().as_slice());
     43     }
     44 }
     45 // `false as u8` is defined as 0.
     46 /// `false` tag.
     47 #[expect(clippy::as_conversions, reason = "this is safe, and we want a const")]
     48 const FALSE: u8 = false as u8;
     49 // `true as u8` is defined as 1.
     50 /// `true` tag.
     51 #[expect(clippy::as_conversions, reason = "this is safe, and we want a const")]
     52 const TRUE: u8 = true as u8;
     53 impl EncodeBuffer for bool {
     54     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     55         buffer.push(if *self { TRUE } else { FALSE });
     56     }
     57 }
     58 // We don't implement `EncodeBuffer` for `[T]` since we only ever need `[u8]`; and one can specialize
     59 // the implementation such that it's _a lot_ faster than a generic `T`.
     60 impl EncodeBufferFallible for [u8] {
     61     type Err = EncDecErr;
     62     /// # Errors
     63     ///
     64     /// Errors iff `self.len() > usize::from(u16::MAX)`.
     65     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err> {
     66         u16::try_from(self.len())
     67             .map_err(|_e| EncDecErr)
     68             .map(|len| {
     69                 len.encode_into_buffer(buffer);
     70                 buffer.extend_from_slice(self);
     71             })
     72     }
     73 }
     74 // We don't implement `EncodeBuffer` for `Vec<T>` since we only ever need `Vec<u8>`; and one can specialize
     75 // the implementation such that it's _a lot_ faster than a generic `T`.
     76 impl EncodeBufferFallible for Vec<u8> {
     77     type Err = EncDecErr;
     78     /// # Errors
     79     ///
     80     /// See [`[u8]::encode_into_buffer`].
     81     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err> {
     82         self.as_slice().encode_into_buffer(buffer)
     83     }
     84 }
     85 // We don't implement `EncodeBuffer` for `[T; LEN]` since we only ever need `[u8; LEN]`; and one can specialize
     86 // the implementation such that it's _a lot_ faster than a generic `T`.
     87 impl<const LEN: usize> EncodeBuffer for [u8; LEN]
     88 where
     89     [u8; LEN]: Default,
     90 {
     91     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
     92         buffer.extend_from_slice(self.as_slice());
     93     }
     94 }
     95 /// [`Option::None`] tag.
     96 const NONE: u8 = 0;
     97 /// [`Option::Some`] tag.
     98 const SOME: u8 = 1;
     99 impl<T: EncodeBuffer> EncodeBuffer for Option<T> {
    100     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    101         match *self {
    102             None => {
    103                 buffer.push(NONE);
    104             }
    105             Some(ref val) => {
    106                 buffer.push(SOME);
    107                 val.encode_into_buffer(buffer);
    108             }
    109         }
    110     }
    111 }
    112 impl<T: EncodeBuffer, T2: EncodeBuffer> EncodeBuffer for (T, T2) {
    113     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    114         self.0.encode_into_buffer(buffer);
    115         self.1.encode_into_buffer(buffer);
    116     }
    117 }
    118 impl EncodeBufferFallible for str {
    119     type Err = EncDecErr;
    120     /// # Errors
    121     ///
    122     /// See [`[u8]::encode_into_buffer`].
    123     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err> {
    124         self.as_bytes().encode_into_buffer(buffer)
    125     }
    126 }
    127 impl EncodeBufferFallible for String {
    128     type Err = EncDecErr;
    129     /// # Errors
    130     ///
    131     /// See [`[u8]::encode_into_buffer`].
    132     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err> {
    133         self.as_str().encode_into_buffer(buffer)
    134     }
    135 }
    136 impl EncodeBufferFallible for Cow<'_, str> {
    137     type Err = EncDecErr;
    138     /// # Errors
    139     ///
    140     /// See [`[u8]::encode_into_buffer`].
    141     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err> {
    142         self.as_ref().encode_into_buffer(buffer)
    143     }
    144 }
    145 impl<T: EncodeBuffer + ?Sized> EncodeBuffer for &T {
    146     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    147         (**self).encode_into_buffer(buffer);
    148     }
    149 }
    150 impl<T: EncodeBuffer + ?Sized> EncodeBuffer for &mut T {
    151     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) {
    152         (**self).encode_into_buffer(buffer);
    153     }
    154 }
    155 impl<T: EncodeBufferFallible + ?Sized> EncodeBufferFallible for &T {
    156     type Err = T::Err;
    157     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err> {
    158         (**self).encode_into_buffer(buffer)
    159     }
    160 }
    161 impl<T: EncodeBufferFallible + ?Sized> EncodeBufferFallible for &mut T {
    162     type Err = T::Err;
    163     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err> {
    164         (**self).encode_into_buffer(buffer)
    165     }
    166 }
    167 impl<T: EncodeBufferFallible> EncodeBufferFallible for Option<T> {
    168     type Err = T::Err;
    169     fn encode_into_buffer(&self, buffer: &mut Vec<u8>) -> Result<(), Self::Err> {
    170         match *self {
    171             None => {
    172                 buffer.push(NONE);
    173                 Ok(())
    174             }
    175             Some(ref val) => {
    176                 buffer.push(SOME);
    177                 val.encode_into_buffer(buffer)
    178             }
    179         }
    180     }
    181 }
    182 /// Decodes binary data generated by [`EncodeBuffer::encode_into_buffer`].
    183 pub(super) trait DecodeBuffer<'a>: Sized {
    184     /// Error returned from [`Self::decode_from_buffer`].
    185     type Err;
    186     /// Transforms a sub-`slice` of `data` into `Self`; and upon success,
    187     /// mutates `data` to be the remaining portion.
    188     ///
    189     /// # Errors
    190     ///
    191     /// Errors iff `data` cannot be decoded into `Self`.
    192     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err>;
    193 }
    194 impl<'a> DecodeBuffer<'a> for u8 {
    195     type Err = EncDecErr;
    196     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    197         data.split_first().ok_or(EncDecErr).map(|(&val, rem)| {
    198             *data = rem;
    199             val
    200         })
    201     }
    202 }
    203 impl<'a> DecodeBuffer<'a> for u16 {
    204     type Err = EncDecErr;
    205     #[expect(
    206         clippy::little_endian_bytes,
    207         reason = "we must standardize the endianness to remove ambiguity"
    208     )]
    209     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    210         data.split_at_checked(2)
    211             .ok_or(EncDecErr)
    212             .map(|(le_bytes, rem)| {
    213                 *data = rem;
    214                 let mut val = [0; 2];
    215                 val.copy_from_slice(le_bytes);
    216                 Self::from_le_bytes(val)
    217             })
    218     }
    219 }
    220 impl<'a> DecodeBuffer<'a> for u32 {
    221     type Err = EncDecErr;
    222     #[expect(
    223         clippy::little_endian_bytes,
    224         reason = "we must standardize the endianness to remove ambiguity"
    225     )]
    226     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    227         data.split_at_checked(4)
    228             .ok_or(EncDecErr)
    229             .map(|(le_bytes, rem)| {
    230                 *data = rem;
    231                 let mut val = [0; 4];
    232                 val.copy_from_slice(le_bytes);
    233                 Self::from_le_bytes(val)
    234             })
    235     }
    236 }
    237 impl<'a> DecodeBuffer<'a> for u64 {
    238     type Err = EncDecErr;
    239     #[expect(
    240         clippy::little_endian_bytes,
    241         reason = "we must standardize the endianness to remove ambiguity"
    242     )]
    243     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    244         data.split_at_checked(8)
    245             .ok_or(EncDecErr)
    246             .map(|(le_bytes, rem)| {
    247                 *data = rem;
    248                 let mut val = [0; 8];
    249                 val.copy_from_slice(le_bytes);
    250                 Self::from_le_bytes(val)
    251             })
    252     }
    253 }
    254 impl<'a> DecodeBuffer<'a> for u128 {
    255     type Err = EncDecErr;
    256     #[expect(
    257         clippy::little_endian_bytes,
    258         reason = "we must standardize the endianness to remove ambiguity"
    259     )]
    260     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    261         data.split_at_checked(8)
    262             .ok_or(EncDecErr)
    263             .map(|(le_bytes, rem)| {
    264                 *data = rem;
    265                 let mut val = [0; 16];
    266                 val.copy_from_slice(le_bytes);
    267                 Self::from_le_bytes(val)
    268             })
    269     }
    270 }
    271 impl<'a> DecodeBuffer<'a> for bool {
    272     type Err = EncDecErr;
    273     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    274         u8::decode_from_buffer(data).and_then(|val| match val {
    275             FALSE => Ok(false),
    276             TRUE => Ok(true),
    277             _ => Err(EncDecErr),
    278         })
    279     }
    280 }
    281 // We don't implement `DecodeBuffer` for `&'a [T]` since we only ever need `&[u8]`; and one can specialize
    282 // the implementation such that it's _a lot_ faster than a generic `T`.
    283 impl<'a> DecodeBuffer<'a> for &'a [u8] {
    284     type Err = EncDecErr;
    285     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    286         u16::decode_from_buffer(data).and_then(|len| {
    287             data.split_at_checked(usize::from(len))
    288                 .ok_or(EncDecErr)
    289                 .map(|(val, rem)| {
    290                     *data = rem;
    291                     val
    292                 })
    293         })
    294     }
    295 }
    296 // We don't implement `DecodeBuffer` for `Vec<T>` since we only ever need `Vec<u8>`; and one can specialize
    297 // the implementation such that it's _a lot_ faster than a generic `T`.
    298 impl<'a> DecodeBuffer<'a> for Vec<u8> {
    299     type Err = EncDecErr;
    300     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    301         <&[u8]>::decode_from_buffer(data).map(ToOwned::to_owned)
    302     }
    303 }
    304 // We don't implement `DecodeBuffer` for `[T; LEN]` since we only ever need `[u8; LEN]`; and one can specialize
    305 // the implementation such that it's _a lot_ faster than a generic `T`.
    306 impl<'a, const LEN: usize> DecodeBuffer<'a> for [u8; LEN]
    307 where
    308     [u8; LEN]: Default,
    309 {
    310     type Err = EncDecErr;
    311     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    312         data.split_at_checked(LEN)
    313             .ok_or(EncDecErr)
    314             .map(|(val_slice, rem)| {
    315                 *data = rem;
    316                 let mut val = Self::default();
    317                 val.copy_from_slice(val_slice);
    318                 val
    319             })
    320     }
    321 }
    322 impl<'a, T> DecodeBuffer<'a> for Option<T>
    323 where
    324     T: DecodeBuffer<'a, Err = EncDecErr>,
    325 {
    326     type Err = EncDecErr;
    327     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    328         u8::decode_from_buffer(data).and_then(|tag| match tag {
    329             NONE => Ok(None),
    330             SOME => T::decode_from_buffer(data).map(Some),
    331             _ => Err(EncDecErr),
    332         })
    333     }
    334 }
    335 impl<'a, T, T2> DecodeBuffer<'a> for (T, T2)
    336 where
    337     T: DecodeBuffer<'a, Err = EncDecErr>,
    338     T2: DecodeBuffer<'a, Err = EncDecErr>,
    339 {
    340     type Err = EncDecErr;
    341     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    342         T::decode_from_buffer(data)
    343             .and_then(|val| T2::decode_from_buffer(data).map(|val2| (val, val2)))
    344     }
    345 }
    346 impl<'a> DecodeBuffer<'a> for &'a str {
    347     type Err = EncDecErr;
    348     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    349         <&[u8]>::decode_from_buffer(data)
    350             .and_then(|utf8| str::from_utf8(utf8).map_err(|_e| EncDecErr))
    351     }
    352 }
    353 impl<'a> DecodeBuffer<'a> for String {
    354     type Err = EncDecErr;
    355     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    356         <&str>::decode_from_buffer(data).map(ToOwned::to_owned)
    357     }
    358 }
    359 /// Encodes `self` into a "primitive"-like type that can be saved to persistent storage
    360 /// and later decoded via [`Decode::decode`].
    361 ///
    362 /// The purpose of this trait is to transform `Self` into something "easily" consumable by persistent
    363 /// storage which already has some form of inherent metadata (e.g., a column in a relational database (RDB)).
    364 pub trait Encode {
    365     /// "Primitive"-like type that `self` will be converted into. This should be one of the following:
    366     /// * [`u8`]
    367     /// * [`i8`]
    368     /// * [`u16`]
    369     /// * [`i16`]
    370     /// * [`u32`]
    371     /// * [`i32`]
    372     /// * [`u64`]
    373     /// * [`i64`]
    374     /// * [`u128`]
    375     /// * [`i128`]
    376     /// * [`f32`]
    377     /// * [`f64`]
    378     /// * [`bool`]
    379     /// * `&[u8]`
    380     /// * [`&str`](prim@str)
    381     /// * `[u8; N]`
    382     /// * `Vec<u8>`
    383     /// * [`String`]
    384     type Output<'a>
    385     where
    386         Self: 'a;
    387     /// Error returned when encoding fails.
    388     type Err;
    389     /// Transforms `self` into a "primitive"-like type.
    390     ///
    391     /// # Errors
    392     ///
    393     /// Errors iff `self` cannot be encoded into [`Self::Output`].
    394     fn encode(&self) -> Result<Self::Output<'_>, Self::Err>;
    395 }
    396 /// Decodes a "primitive"-like instance that was created via [`Encode::encode`]
    397 /// into `Self`.
    398 pub trait Decode: Sized {
    399     /// "Primitive"-like input to be decoded.
    400     ///
    401     /// This should be the same as or the "owned" version of the corresponding [`Encode::Output`]. For example if
    402     /// `Encode::Output` is `&[u8]`, then this should be `&[u8]` or `Vec<u8>`.
    403     type Input<'a>;
    404     /// Error returned when decoding fails.
    405     type Err;
    406     /// Decodes `input` into `Self`. Note `input` must not have any trailing data.
    407     ///
    408     /// # Errors
    409     ///
    410     /// Errors iff `input` cannot be decoded into `Self`.
    411     fn decode(input: Self::Input<'_>) -> Result<Self, Self::Err>;
    412 }