tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

lib.rs (13493B)


      1 // Copyright 2019 The Servo Project Developers. See the COPYRIGHT
      2 // file at the top-level directory of this distribution and at
      3 // http://rust-lang.org/COPYRIGHT.
      4 //
      5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
      6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
      7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
      8 // option. This file may not be copied, modified, or distributed
      9 // except according to those terms.
     10 
     11 //! Fast binary serialization and deserialization for types with a known maximum size.
     12 //!
     13 //! ## Binary Encoding Scheme
     14 //!
     15 //! ## Usage
     16 //!
     17 //! ## Comparison to bincode
     18 
     19 #[cfg(feature = "derive")]
     20 pub use peek_poke_derive::*;
     21 
     22 use core::{marker::PhantomData, mem::size_of, slice};
     23 use crate::{slice_ext::*, vec_ext::*};
     24 
     25 mod slice_ext;
     26 mod vec_ext;
     27 
     28 union MaybeUninitShim<T: Copy> {
     29    uninit: (),
     30    init: T,
     31 }
     32 
     33 /// Peek helper for constructing a `T` by `Copy`ing into an uninitialized stack
     34 /// allocation.
     35 ///
     36 /// # Safety
     37 ///
     38 /// * `bytes` must denote a valid pointer to a block of memory.
     39 ///
     40 /// * `bytes` must point to at least the number of bytes returned by
     41 ///   `Poke::max_size()`.
     42 pub unsafe fn peek_from_uninit<T: Copy + Peek>(bytes: *const u8) -> (T, *const u8) {
     43    let mut val = MaybeUninitShim { uninit: () };
     44    let bytes = <T>::peek_from(bytes, &mut val.init);
     45    (val.init, bytes)
     46 }
     47 
     48 /// Peek helper for constructing a `T` by `Default` initialized stack
     49 /// allocation.
     50 ///
     51 /// # Safety
     52 ///
     53 /// * `bytes` must denote a valid pointer to a block of memory.
     54 ///
     55 /// * `bytes` must point to at least the number of bytes returned by
     56 ///   `Poke::max_size()`.
     57 pub unsafe fn peek_from_default<T: Default + Peek>(bytes: *const u8) -> (T, *const u8) {
     58    let mut val = T::default();
     59    let bytes = <T>::peek_from(bytes, &mut val);
     60    (val, bytes)
     61 }
     62 
     63 /// Peek inplace a `T` from a slice of bytes, returning a slice of the remaining
     64 /// bytes. `src` must contain at least `T::max_size()` bytes.
     65 ///
     66 /// [`ensure_red_zone`] can be used to add required padding.
     67 pub fn peek_from_slice<'a, T: Peek>(src: &'a [u8], dst: &mut T) -> &'a [u8] {
     68    unsafe {
     69        // If src.len() == T::max_size() then src is at the start of the red-zone.
     70        assert!(T::max_size() < src.len(), "WRDL: unexpected end of display list");
     71        let end_ptr = T::peek_from(src.as_ptr(), dst);
     72        let len = end_ptr as usize - src.as_ptr() as usize;
     73        // Did someone break the T::peek_from() can't read more than T::max_size()
     74        // bytes contract?
     75        assert!(len <= src.len(), "WRDL: Peek::max_size was wrong");
     76        slice::from_raw_parts(end_ptr, src.len() - len)
     77    }
     78 }
     79 
     80 /// Poke helper to insert a serialized version of `src` at the beginning for `dst`.
     81 pub fn poke_inplace_slice<T: Poke>(src: &T, dst: &mut [u8]) {
     82    assert!(T::max_size() <= dst.len(),  "WRDL: buffer too small to write into");
     83    unsafe {
     84        src.poke_into(dst.as_mut_ptr());
     85    }
     86 }
     87 
     88 /// Poke helper to append a serialized version of `src` to the end of `dst`.
     89 pub fn poke_into_vec<T: Poke>(src: &T, dst: &mut Vec<u8>) {
     90    dst.reserve(T::max_size());
     91    unsafe {
     92        let ptr = dst.as_end_mut_ptr();
     93        let end_ptr = src.poke_into(ptr);
     94        dst.set_end_ptr(end_ptr);
     95    }
     96 }
     97 
     98 // TODO: Is returning the len of the iterator of any practical use?
     99 pub fn poke_extend_vec<I>(src: I, dst: &mut Vec<u8>) -> usize
    100 where
    101    I: ExactSizeIterator,
    102    I::Item: Poke,
    103 {
    104    let len = src.len();
    105    let max_size = len * I::Item::max_size();
    106    dst.reserve(max_size);
    107    unsafe {
    108        let ptr = dst.as_end_mut_ptr();
    109        // Guard against the possibility of a misbehaved implementation of
    110        // ExactSizeIterator by writing at most `len` items.
    111        let end_ptr = src.take(len).fold(ptr, |ptr, item| item.poke_into(ptr));
    112        dst.set_end_ptr(end_ptr);
    113    }
    114 
    115    len
    116 }
    117 
    118 /// Add `T::max_size()` "red zone" (padding of zeroes) to the end of the vec of
    119 /// `bytes`. This allows deserialization to assert that at least `T::max_size()`
    120 /// bytes exist at all times.
    121 pub fn ensure_red_zone<T: Poke>(bytes: &mut Vec<u8>) {
    122    bytes.reserve(T::max_size());
    123    unsafe {
    124        let end_ptr = bytes.as_end_mut_ptr();
    125        end_ptr.write_bytes(0, T::max_size());
    126        bytes.set_end_ptr(end_ptr.add(T::max_size()));
    127    }
    128 }
    129 
    130 /// Remove the "red zone" (padding of zeroes) from the end of the vec of `bytes`.
    131 /// This is effectively the inverse of `ensure_red_zone`, with the caveat that
    132 /// space reserved for the red zone is not un-reserved. Callers are repsonsible
    133 /// for making sure the vec actually has a red zone, otherwise data bytes can
    134 /// get stripped instead.
    135 pub fn strip_red_zone<T: Poke>(bytes: &mut Vec<u8>) {
    136    assert!(bytes.len() >= T::max_size());
    137    unsafe {
    138        let end_ptr = bytes.as_end_mut_ptr();
    139        bytes.set_end_ptr(end_ptr.sub(T::max_size()));
    140    }
    141 }
    142 
    143 #[inline]
    144 unsafe fn read_verbatim<T>(src: *const u8, dst: *mut T) -> *const u8 {
    145    *dst = (src as *const T).read_unaligned();
    146    src.add(size_of::<T>())
    147 }
    148 
    149 #[inline]
    150 unsafe fn write_verbatim<T>(src: T, dst: *mut u8) -> *mut u8 {
    151    (dst as *mut T).write_unaligned(src);
    152    dst.add(size_of::<T>())
    153 }
    154 
    155 #[cfg(feature = "extras")]
    156 mod euclid;
    157 
    158 /// A trait for values that provide serialization into buffers of bytes.
    159 ///
    160 /// # Example
    161 ///
    162 /// ```no_run
    163 /// use peek_poke::Poke;
    164 ///
    165 /// struct Bar {
    166 ///     a: u32,
    167 ///     b: u8,
    168 ///     c: i16,
    169 /// }
    170 ///
    171 /// unsafe impl Poke for Bar {
    172 ///     fn max_size() -> usize {
    173 ///         <u32>::max_size() + <u8>::max_size() + <i16>::max_size()
    174 ///     }
    175 ///     unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
    176 ///         let bytes = self.a.poke_into(bytes);
    177 ///         let bytes = self.b.poke_into(bytes);
    178 ///         self.c.poke_into(bytes)
    179 ///     }
    180 /// }
    181 /// ```
    182 ///
    183 /// # Safety
    184 ///
    185 /// The `Poke` trait is an `unsafe` trait for the reasons, and implementors must
    186 /// ensure that they adhere to these contracts:
    187 ///
    188 /// * `max_size()` query and calculations in general must be correct.  Callers
    189 ///    of this trait are expected to rely on the contract defined on each
    190 ///    method, and implementors must ensure such contracts remain true.
    191 pub unsafe trait Poke {
    192    /// Return the maximum number of bytes that the serialized version of `Self`
    193    /// will occupy.
    194    ///
    195    /// # Safety
    196    ///
    197    /// Implementors of `Poke` guarantee to not write more than the result of
    198    /// calling `max_size()` into the buffer pointed to by `bytes` when
    199    /// `poke_into()` is called.
    200    fn max_size() -> usize;
    201    /// Serialize into the buffer pointed to by `bytes`.
    202    ///
    203    /// Returns a pointer to the next byte after the serialized representation of `Self`.
    204    ///
    205    /// # Safety
    206    ///
    207    /// This function is unsafe because undefined behavior can result if the
    208    /// caller does not ensure all of the following:
    209    ///
    210    /// * `bytes` must denote a valid pointer to a block of memory.
    211    ///
    212    /// * `bytes` must pointer to at least the number of bytes returned by
    213    ///   `max_size()`.
    214    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8;
    215 }
    216 
    217 /// A trait for values that provide deserialization from buffers of bytes.
    218 ///
    219 /// # Example
    220 ///
    221 /// ```ignore
    222 /// use peek_poke::Peek;
    223 ///
    224 /// struct Bar {
    225 ///     a: u32,
    226 ///     b: u8,
    227 ///     c: i16,
    228 /// }
    229 ///
    230 /// ...
    231 ///
    232 /// impl Peek for Bar {
    233 ///     unsafe fn peek_from(&mut self, bytes: *const u8) -> *const u8 {
    234 ///         let bytes = self.a.peek_from(bytes);
    235 ///         let bytes = self.b.peek_from(bytes);
    236 ///         self.c.peek_from(bytes)
    237 ///     }
    238 /// }
    239 /// ```
    240 ///
    241 /// # Safety
    242 ///
    243 /// The `Peek` trait contains unsafe methods for the following reasons, and
    244 /// implementors must ensure that they adhere to these contracts:
    245 ///
    246 /// * Callers of this trait are expected to rely on the contract defined on each
    247 ///   method, and implementors must ensure that `peek_from()` doesn't read more
    248 ///   bytes from `bytes` than is returned by `Peek::max_size()`.
    249 pub trait Peek: Poke {
    250    /// Deserialize from the buffer pointed to by `bytes`.
    251    ///
    252    /// Returns a pointer to the next byte after the unconsumed bytes not used
    253    /// to deserialize the representation of `Self`.
    254    ///
    255    /// # Safety
    256    ///
    257    /// This function is unsafe because undefined behavior can result if the
    258    /// caller does not ensure all of the following:
    259    ///
    260    /// * `bytes` must denote a valid pointer to a block of memory.
    261    ///
    262    /// * `bytes` must pointer to at least the number of bytes returned by
    263    ///   `Poke::max_size()`.
    264    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8;
    265 }
    266 
    267 macro_rules! impl_poke_for_deref {
    268    (<$($desc:tt)+) => {
    269        unsafe impl <$($desc)+ {
    270            #[inline(always)]
    271            fn max_size() -> usize {
    272                <T>::max_size()
    273            }
    274            unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
    275                (**self).poke_into(bytes)
    276            }
    277        }
    278    }
    279 }
    280 
    281 impl_poke_for_deref!(<'a, T: Poke> Poke for &'a T);
    282 impl_poke_for_deref!(<'a, T: Poke> Poke for &'a mut T);
    283 
    284 macro_rules! impl_for_primitive {
    285    ($($ty:ty)+) => {
    286        $(unsafe impl Poke for $ty {
    287            #[inline(always)]
    288            fn max_size() -> usize {
    289                size_of::<Self>()
    290            }
    291            #[inline(always)]
    292            unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
    293                write_verbatim(*self, bytes)
    294            }
    295        }
    296        impl Peek for $ty {
    297            #[inline(always)]
    298            unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
    299                read_verbatim(bytes, output)
    300            }
    301        })+
    302    };
    303 }
    304 
    305 impl_for_primitive! {
    306    i8 i16 i32 i64 isize
    307    u8 u16 u32 u64 usize
    308    f32 f64
    309 }
    310 
    311 unsafe impl Poke for bool {
    312    #[inline(always)]
    313    fn max_size() -> usize {
    314        u8::max_size()
    315    }
    316    #[inline]
    317    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
    318        (*self as u8).poke_into(bytes)
    319    }
    320 }
    321 
    322 impl Peek for bool {
    323    #[inline]
    324    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
    325        let mut int_bool = 0u8;
    326        let ptr = <u8>::peek_from(bytes, &mut int_bool);
    327        *output = int_bool != 0;
    328        ptr
    329    }
    330 }
    331 
    332 unsafe impl<T> Poke for PhantomData<T> {
    333    #[inline(always)]
    334    fn max_size() -> usize {
    335        0
    336    }
    337    #[inline(always)]
    338    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
    339        bytes
    340    }
    341 }
    342 
    343 impl<T> Peek for PhantomData<T> {
    344    #[inline(always)]
    345    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
    346        *output = PhantomData;
    347        bytes
    348    }
    349 }
    350 
    351 unsafe impl<T: Poke> Poke for Option<T> {
    352    #[inline(always)]
    353    fn max_size() -> usize {
    354        u8::max_size() + T::max_size()
    355    }
    356 
    357    #[inline]
    358    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
    359        match self {
    360            None => 0u8.poke_into(bytes),
    361            Some(ref v) => {
    362                let bytes = 1u8.poke_into(bytes);
    363                v.poke_into(bytes)
    364            }
    365        }
    366    }
    367 }
    368 
    369 impl<T: Default + Peek> Peek for Option<T> {
    370    #[inline]
    371    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
    372        let (variant, bytes) = peek_from_default::<u8>(bytes);
    373        match variant {
    374            0 => {
    375                *output = None;
    376                bytes
    377            }
    378            1 => {
    379                let (val, bytes) = peek_from_default(bytes);
    380                *output = Some(val);
    381                bytes
    382            }
    383            _ => unreachable!(),
    384        }
    385    }
    386 }
    387 
    388 macro_rules! impl_for_arrays {
    389    ($($len:tt)+) => {
    390        $(unsafe impl<T: Poke> Poke for [T; $len] {
    391            fn max_size() -> usize {
    392                $len * T::max_size()
    393            }
    394            unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
    395                self.iter().fold(bytes, |bytes, e| e.poke_into(bytes))
    396            }
    397        }
    398        impl<T: Peek> Peek for [T; $len] {
    399            unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
    400                (&mut *output).iter_mut().fold(bytes, |bytes, e| <T>::peek_from(bytes, e))
    401            }
    402        })+
    403    }
    404 }
    405 
    406 impl_for_arrays! {
    407     1  2  3  4  5  6  7  8  9 10
    408    11 12 13 14 15 16 17 18 19 20
    409    21 22 23 24 25 26 27 28 29 30
    410    31 32
    411 }
    412 
    413 unsafe impl Poke for () {
    414    fn max_size() -> usize {
    415        0
    416    }
    417    unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
    418        bytes
    419    }
    420 }
    421 impl Peek for () {
    422    unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
    423        *output = ();
    424        bytes
    425    }
    426 }
    427 
    428 macro_rules! impl_for_tuple {
    429    ($($n:tt: $ty:ident),+) => {
    430        unsafe impl<$($ty: Poke),+> Poke for ($($ty,)+) {
    431            #[inline(always)]
    432            fn max_size() -> usize {
    433                0 $(+ <$ty>::max_size())+
    434            }
    435            unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
    436                $(let bytes = self.$n.poke_into(bytes);)+
    437                bytes
    438            }
    439        }
    440        impl<$($ty: Peek),+> Peek for ($($ty,)+) {
    441            unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
    442                $(let bytes = $ty::peek_from(bytes, &mut (*output).$n);)+
    443                bytes
    444            }
    445        }
    446    }
    447 }
    448 
    449 impl_for_tuple!(0: A);
    450 impl_for_tuple!(0: A, 1: B);
    451 impl_for_tuple!(0: A, 1: B, 2: C);
    452 impl_for_tuple!(0: A, 1: B, 2: C, 3: D);
    453 impl_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E);