Files @ 1bc57ab68e0e
Branch filter:

Location: CSY/reowolf/src/collections/scoped_buffer.rs - annotation

1bc57ab68e0e 6.2 KiB application/rls-services+xml Show Source Show as Raw Download as Raw
Max Henger
Merge branch 'feat-builtin-ip' into 'master'

feat: Builtin internet component

See merge request nl-cwi-csy/reowolf!6
fc987660fdee
fc987660fdee
fc987660fdee
fc987660fdee
fc987660fdee
fc987660fdee
fc987660fdee
17fe648a8934
17fe648a8934
2df3ee19d578
fc2d65a1b906
fc2d65a1b906
fc2d65a1b906
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
fc987660fdee
fc987660fdee
2df3ee19d578
2df3ee19d578
fc987660fdee
fc987660fdee
87aa65714efe
97b87404ffa5
2df3ee19d578
2df3ee19d578
2df3ee19d578
fc987660fdee
fc987660fdee
fc987660fdee
fc987660fdee
87aa65714efe
fc987660fdee
fc987660fdee
2df3ee19d578
fc987660fdee
fc987660fdee
87aa65714efe
6af17d60c197
87aa65714efe
6af17d60c197
6af17d60c197
120857c65991
6af17d60c197
6af17d60c197
6af17d60c197
6af17d60c197
120857c65991
6af17d60c197
6af17d60c197
fc987660fdee
fc987660fdee
fc987660fdee
87aa65714efe
fc987660fdee
fc987660fdee
fc987660fdee
fc987660fdee
fc987660fdee
fc987660fdee
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
87aa65714efe
637115283740
fc987660fdee
fc987660fdee
637115283740
fc987660fdee
fc987660fdee
2df3ee19d578
fc987660fdee
fc987660fdee
2df3ee19d578
17fe648a8934
637115283740
17fe648a8934
87aa65714efe
17fe648a8934
17fe648a8934
fc987660fdee
fe0efc81bd4e
fc2d65a1b906
637115283740
fc987660fdee
637115283740
fc987660fdee
fc987660fdee
fc987660fdee
fc987660fdee
fe0efc81bd4e
fc2d65a1b906
637115283740
fc987660fdee
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
2df3ee19d578
637115283740
fc2d65a1b906
fc2d65a1b906
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
fc987660fdee
fc987660fdee
fc987660fdee
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
2df3ee19d578
17fe648a8934
17fe648a8934
2df3ee19d578
17fe648a8934
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
2df3ee19d578
17fe648a8934
17fe648a8934
17fe648a8934
113e4349a706
113e4349a706
113e4349a706
113e4349a706
87aa65714efe
fc987660fdee
e2849e9bfb16
2df3ee19d578
fc2d65a1b906
fc987660fdee
97b87404ffa5
97b87404ffa5
2df3ee19d578
2df3ee19d578
2df3ee19d578
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
2df3ee19d578
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
97b87404ffa5
fc987660fdee
/// scoped_buffer.rs
///
/// Solves the common pattern where we are performing some kind of recursive
/// pattern while using a temporary buffer. At the start, or during the
/// procedure, we push stuff into the buffer. At the end we take out what we
/// have put in.
///
/// It is unsafe because we're using pointers to circumvent borrowing rules in
/// the name of code cleanliness. The correctness of use is checked in debug
/// mode at runtime.

use std::iter::FromIterator;

macro_rules! hide {
    ($v:block) => {
        #[cfg(debug_assertions)] $v
    };
    ($v:expr) => {
        #[cfg(debug_assertions)] $v
    };
}

pub(crate) struct ScopedBuffer<T: Sized> {
    pub inner: Vec<T>,
}

impl<T: Sized> ScopedBuffer<T> {
    pub(crate) fn with_capacity(capacity: usize) -> Self {
        Self {
            inner: Vec::with_capacity(capacity),
        }
    }

    pub(crate) fn start_section(&mut self) -> ScopedSection<T> {
        let start_size = self.inner.len() as u32;
        ScopedSection {
            inner: &mut self.inner,
            start_size,
            #[cfg(debug_assertions)] cur_size: start_size,
        }
    }
}

impl<T: Clone> ScopedBuffer<T> {
    pub(crate) fn start_section_initialized(&mut self, initialize_with: &[T]) -> ScopedSection<T> {
        let start_size = self.inner.len() as u32;
        let _data_size = initialize_with.len() as u32;
        self.inner.extend_from_slice(initialize_with);
        ScopedSection{
            inner: &mut self.inner,
            start_size,
            #[cfg(debug_assertions)] cur_size: start_size + _data_size,
        }
    }
}

#[cfg(debug_assertions)]
impl<T: Sized> Drop for ScopedBuffer<T> {
    fn drop(&mut self) {
        // Make sure that everyone cleaned up the buffer neatly
        debug_assert!(self.inner.is_empty(), "dropped non-empty scoped buffer");
    }
}

/// A section of the buffer. Keeps track of where we started the section. When
/// done with the section one must call `into_vec` or `forget` to remove the
/// section from the underlying buffer. This will also be done upon dropping the
/// ScopedSection in case errors are being handled.
pub(crate) struct ScopedSection<T: Sized> {
    inner: *mut Vec<T>,
    start_size: u32,
    #[cfg(debug_assertions)] cur_size: u32,
}

impl<T: Sized> ScopedSection<T> {
    /// Pushes value into section
    #[inline]
    pub(crate) fn push(&mut self, value: T) {
        self.check_length();
        let vec = unsafe{&mut *self.inner};
        vec.push(value);
        hide!(self.cur_size += 1);
    }

    #[inline]
    pub(crate) fn len(&self) -> usize {
        self.check_length();
        let vec = unsafe{&mut *self.inner};
        return vec.len() - self.start_size as usize;
    }

    #[inline]
    #[allow(unused_mut)] // used in debug mode
    pub(crate) fn forget(mut self) {
        self.check_length();
        let vec = unsafe{&mut *self.inner};
        hide!(self.cur_size = self.start_size);
        vec.truncate(self.start_size as usize);
    }

    #[inline]
    #[allow(unused_mut)] // used in debug mode
    pub(crate) fn into_vec(mut self) -> Vec<T> {
        self.check_length();
        let vec = unsafe{&mut *self.inner};
        hide!(self.cur_size = self.start_size);
        let section = Vec::from_iter(vec.drain(self.start_size as usize..));
        section
    }

    #[inline]
    pub(crate) fn check_length(&self) {
        hide!({
            let vec = unsafe{&*self.inner};
            debug_assert_eq!(
                vec.len(), self.cur_size as usize,
                "incorrect use of ScopedSection: underlying storage vector has changed size"
            )
        })
    }
}

impl<T: Sized + PartialEq> ScopedSection<T> {
    #[inline]
    pub(crate) fn push_unique(&mut self, value: T) {
        self.check_length();
        let vec = unsafe{&mut *self.inner};
        for item in &vec[self.start_size as usize..] {
            if *item == value {
                // item already exists
                return;
            }
        }

        vec.push(value);
        hide!(self.cur_size += 1);
    }

    #[inline]
    pub(crate) fn contains(&self, value: &T) -> bool {
        self.check_length();
        let vec = unsafe{&*self.inner};
        for index in self.start_size as usize..vec.len() {
            if &vec[index] == value {
                return true;
            }
        }

        return false;
    }
}

impl<T: Copy> ScopedSection<T> {
    pub(crate) fn iter_copied(&self) -> ScopedIter<T> {
        return ScopedIter{
            inner: self.inner,
            cur_index: self.start_size,
            last_index: unsafe{ (*self.inner).len() as u32 },
        }
    }
}

impl<T> std::ops::Index<usize> for ScopedSection<T> {
    type Output = T;

    fn index(&self, index: usize) -> &Self::Output {
        let vec = unsafe{&*self.inner};
        return &vec[self.start_size as usize + index]
    }
}

impl<T> std::ops::IndexMut<usize> for ScopedSection<T> {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        let vec = unsafe{&mut *self.inner};
        return &mut vec[self.start_size as usize + index]
    }
}

// note: this `Drop` impl used to be debug-only, requiring the programmer to
// call `into_vec` or `forget`. But this is rather error prone. So we'll check
// in debug mode, but always truncate in release mode (even though this is a
// noop in most cases).
impl<T: Sized> Drop for ScopedSection<T> {
    fn drop(&mut self) {
        let vec = unsafe{&mut *self.inner};
        hide!(debug_assert_eq!(vec.len(), self.cur_size as usize));
        vec.truncate(self.start_size as usize);
    }
}

/// Small utility for iterating over a section of the buffer. Same conditions as
/// the buffer apply: each time we retrieve an element the buffer must have the
/// same size as the moment of creation.
pub(crate) struct ScopedIter<T: Copy> {
    inner: *mut Vec<T>,
    cur_index: u32,
    last_index: u32,
}

impl<T: Copy> Iterator for ScopedIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        hide!(debug_assert_eq!(self.last_index as usize, unsafe { (*self.inner).len() }));
        if self.cur_index >= self.last_index {
            return None;
        }

        let vec = unsafe{ &*self.inner };
        let index = self.cur_index as usize;
        self.cur_index += 1;
        return Some(vec[index]);
    }
}