webauthn_rp

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

bin.rs (15251B)


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