webauthn_rp

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

bin.rs (14409B)


      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         /// Number of bytes `u16` is made of.
    211         const SIZE: usize = 2;
    212         data.split_at_checked(SIZE)
    213             .ok_or(EncDecErr)
    214             .map(|(le_bytes, rem)| {
    215                 *data = rem;
    216                 let mut val = [0; SIZE];
    217                 val.copy_from_slice(le_bytes);
    218                 Self::from_le_bytes(val)
    219             })
    220     }
    221 }
    222 impl<'a> DecodeBuffer<'a> for u32 {
    223     type Err = EncDecErr;
    224     #[expect(
    225         clippy::little_endian_bytes,
    226         reason = "we must standardize the endianness to remove ambiguity"
    227     )]
    228     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    229         /// Number of bytes `u32` is made of.
    230         const SIZE: usize = 4;
    231         data.split_at_checked(SIZE)
    232             .ok_or(EncDecErr)
    233             .map(|(le_bytes, rem)| {
    234                 *data = rem;
    235                 let mut val = [0; SIZE];
    236                 val.copy_from_slice(le_bytes);
    237                 Self::from_le_bytes(val)
    238             })
    239     }
    240 }
    241 impl<'a> DecodeBuffer<'a> for u64 {
    242     type Err = EncDecErr;
    243     #[expect(
    244         clippy::little_endian_bytes,
    245         reason = "we must standardize the endianness to remove ambiguity"
    246     )]
    247     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    248         /// Number of bytes `u64` is made of.
    249         const SIZE: usize = 8;
    250         data.split_at_checked(SIZE)
    251             .ok_or(EncDecErr)
    252             .map(|(le_bytes, rem)| {
    253                 *data = rem;
    254                 let mut val = [0; SIZE];
    255                 val.copy_from_slice(le_bytes);
    256                 Self::from_le_bytes(val)
    257             })
    258     }
    259 }
    260 impl<'a> DecodeBuffer<'a> for u128 {
    261     type Err = EncDecErr;
    262     #[expect(
    263         clippy::little_endian_bytes,
    264         reason = "we must standardize the endianness to remove ambiguity"
    265     )]
    266     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    267         /// Number of bytes `u128` is made of.
    268         const SIZE: usize = 16;
    269         data.split_at_checked(SIZE)
    270             .ok_or(EncDecErr)
    271             .map(|(le_bytes, rem)| {
    272                 *data = rem;
    273                 let mut val = [0; SIZE];
    274                 val.copy_from_slice(le_bytes);
    275                 Self::from_le_bytes(val)
    276             })
    277     }
    278 }
    279 impl<'a> DecodeBuffer<'a> for bool {
    280     type Err = EncDecErr;
    281     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    282         u8::decode_from_buffer(data).and_then(|val| match val {
    283             FALSE => Ok(false),
    284             TRUE => Ok(true),
    285             _ => Err(EncDecErr),
    286         })
    287     }
    288 }
    289 // We don't implement `DecodeBuffer` for `&'a [T]` since we only ever need `&[u8]`; and one can specialize
    290 // the implementation such that it's _a lot_ faster than a generic `T`.
    291 impl<'a> DecodeBuffer<'a> for &'a [u8] {
    292     type Err = EncDecErr;
    293     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    294         u16::decode_from_buffer(data).and_then(|len| {
    295             data.split_at_checked(usize::from(len))
    296                 .ok_or(EncDecErr)
    297                 .map(|(val, rem)| {
    298                     *data = rem;
    299                     val
    300                 })
    301         })
    302     }
    303 }
    304 // We don't implement `DecodeBuffer` for `Vec<T>` since we only ever need `Vec<u8>`; and one can specialize
    305 // the implementation such that it's _a lot_ faster than a generic `T`.
    306 impl<'a> DecodeBuffer<'a> for Vec<u8> {
    307     type Err = EncDecErr;
    308     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    309         <&[u8]>::decode_from_buffer(data).map(ToOwned::to_owned)
    310     }
    311 }
    312 // We don't implement `DecodeBuffer` for `[T; LEN]` since we only ever need `[u8; LEN]`; and one can specialize
    313 // the implementation such that it's _a lot_ faster than a generic `T`.
    314 impl<'a, const LEN: usize> DecodeBuffer<'a> for [u8; LEN]
    315 where
    316     [u8; LEN]: Default,
    317 {
    318     type Err = EncDecErr;
    319     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    320         data.split_at_checked(LEN)
    321             .ok_or(EncDecErr)
    322             .map(|(val_slice, rem)| {
    323                 *data = rem;
    324                 let mut val = Self::default();
    325                 val.copy_from_slice(val_slice);
    326                 val
    327             })
    328     }
    329 }
    330 impl<'a, T> DecodeBuffer<'a> for Option<T>
    331 where
    332     T: DecodeBuffer<'a, Err = EncDecErr>,
    333 {
    334     type Err = EncDecErr;
    335     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    336         u8::decode_from_buffer(data).and_then(|tag| match tag {
    337             NONE => Ok(None),
    338             SOME => T::decode_from_buffer(data).map(Some),
    339             _ => Err(EncDecErr),
    340         })
    341     }
    342 }
    343 impl<'a, T, T2> DecodeBuffer<'a> for (T, T2)
    344 where
    345     T: DecodeBuffer<'a, Err = EncDecErr>,
    346     T2: DecodeBuffer<'a, Err = EncDecErr>,
    347 {
    348     type Err = EncDecErr;
    349     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    350         T::decode_from_buffer(data)
    351             .and_then(|val| T2::decode_from_buffer(data).map(|val2| (val, val2)))
    352     }
    353 }
    354 impl<'a> DecodeBuffer<'a> for &'a str {
    355     type Err = EncDecErr;
    356     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    357         <&[u8]>::decode_from_buffer(data)
    358             .and_then(|utf8| str::from_utf8(utf8).map_err(|_e| EncDecErr))
    359     }
    360 }
    361 impl<'a> DecodeBuffer<'a> for String {
    362     type Err = EncDecErr;
    363     fn decode_from_buffer(data: &mut &'a [u8]) -> Result<Self, Self::Err> {
    364         <&str>::decode_from_buffer(data).map(ToOwned::to_owned)
    365     }
    366 }
    367 /// Encodes `self` into a "primitive"-like type that can be saved to persistent storage
    368 /// and later decoded via [`Decode::decode`].
    369 ///
    370 /// The purpose of this trait is to transform `Self` into something "easily" consumable by persistent
    371 /// storage which already has some form of inherent metadata (e.g., a column in a relational database (RDB)).
    372 pub trait Encode {
    373     /// "Primitive"-like type that `self` will be converted into. This should be one of the following:
    374     /// * [`u8`]
    375     /// * [`i8`]
    376     /// * [`u16`]
    377     /// * [`i16`]
    378     /// * [`u32`]
    379     /// * [`i32`]
    380     /// * [`u64`]
    381     /// * [`i64`]
    382     /// * [`u128`]
    383     /// * [`i128`]
    384     /// * [`f32`]
    385     /// * [`f64`]
    386     /// * [`bool`]
    387     /// * `&[u8]`
    388     /// * [`&str`](prim@str)
    389     /// * `[u8; N]`
    390     /// * `Vec<u8>`
    391     /// * [`String`]
    392     type Output<'a>
    393     where
    394         Self: 'a;
    395     /// Error returned when encoding fails.
    396     type Err;
    397     /// Transforms `self` into a "primitive"-like type.
    398     ///
    399     /// # Errors
    400     ///
    401     /// Errors iff `self` cannot be encoded into [`Self::Output`].
    402     fn encode(&self) -> Result<Self::Output<'_>, Self::Err>;
    403 }
    404 /// Decodes a "primitive"-like instance that was created via [`Encode::encode`]
    405 /// into `Self`.
    406 pub trait Decode: Sized {
    407     /// "Primitive"-like input to be decoded.
    408     ///
    409     /// This should be the same as or the "owned" version of the corresponding [`Encode::Output`]. For example if
    410     /// `Encode::Output` is `&[u8]`, then this should be `&[u8]` or `Vec<u8>`.
    411     type Input<'a>;
    412     /// Error returned when decoding fails.
    413     type Err;
    414     /// Decodes `input` into `Self`. Note `input` must not have any trailing data.
    415     ///
    416     /// # Errors
    417     ///
    418     /// Errors iff `input` cannot be decoded into `Self`.
    419     fn decode(input: Self::Input<'_>) -> Result<Self, Self::Err>;
    420 }