Meteor default http auth

Я написал реализацию, и я рассмотрю основные моменты.

  • Полный код доступен в crates.io/arrayvec ( API doc )
  • Используйте атрибут (называемый Array) для абстракции по разным размерам массива.
/// Trait for fixed size arrays.
pub unsafe trait Array {
    /// The array's element type
    type Item;
    unsafe fn new() -> Self;
    fn as_ptr(&self) -> *const Self::Item;
    fn as_mut_ptr(&mut self) -> *mut Self::Item;
    fn capacity() -> usize;
}
  • В современном стиле ржавчины мы можем реализовать этот признак только для определенных размеров массива. Я покрываю некоторые небольшие размеры макросом:
macro_rules! fix_array_impl {
    ($len:expr ) => (
        unsafe impl Array for [T; $len] {
            type Item = T;
            /// Note: Returning an uninitialized value here only works
            /// if we can be sure the data is never used. The nullable pointer
            /// inside enum optimization conflicts with this this for example,
            /// so we need to be extra careful. See `Flag` enum.
            unsafe fn new() -> [T; $len] { mem::uninitialized() }
            fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
            fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _}
            fn capacity() -> usize { $len }
        }
    )
}

macro_rules! fix_array_impl_recursive {
    () => ();
    ($len:expr, $($more:expr,)*) => (
        fix_array_impl!($len);
        fix_array_impl_recursive!($($more,)*);
    );
}

fix_array_impl_recursive!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
                          16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
                          32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,);
  • Нам нужно подавить падение по умолчанию встроенного массива. Вы можете сделать это теоретически используя Option и используя ptr::write, чтобы перезаписать его с помощью None в последний момент в Drop.
  • Мы должны , однако использовать наш собственный enum, по аналогии с Option по одной причине: нам нужно избегать оптимизации с нулевым указателем, которая применяется к перечислениям, которые имеют то же представление, что и Option. Затем в Drop мы делаем решающее торможение деструктора по умолчанию для внутреннего массива: мы принудительно перезаписываем наше перечисление. Конечно, только после уничтожения всех элементов.
/// Make sure the non-nullable pointer optimization does not occur!
#[repr(u8)]
enum Flag {
    Dropped,
    Alive(T),
}

/// A vector with a fixed capacity.
pub struct ArrayVec {
    len: u8,
    xs: Flag,
}

impl Drop for ArrayVec {
    fn drop(&mut self) {
        // clear all elements, then inhibit drop of inner array
        while let Some(_) = self.pop() { }
        unsafe {
            ptr::write(&mut self.xs, Flag::Dropped);
        }
    }
}
impl Deref for ArrayVec {
    type Target = [A::Item];
    fn deref(&self) -> &[A::Item] {
        unsafe {
            slice::from_raw_parts(self.inner_ref().as_ptr(), self.len())
        }
    }
}
fn inner_mut(&mut self) -> &mut A {
    // FIXME: Optimize this, we know it's always present.
    match self.xs {
        Flag::Alive(ref mut xs) => xs,
        _ => unreachable!(),
    }
}

Спасибо, kmky за вопрос! Изучение этого ответа привело к созданию arrayvec, приведенному выше, и выявило некоторые моменты, которые были очень важны для обеспечения надежной структуры данных ржавчины.

0
задан Jibin Mathews 13 July 2018 в 18:19
поделиться