nodo 0.18.5

A realtime framework for robotics
Documentation
use std::ops::{Index, IndexMut};

/// Small helper type which allows insertion/lookup of elements with arbitrary indicies. This
/// heavily relies on indices being reasonably compact.
/// I wanted to use a slab, however that one does not allow me to insert at a custom index.
#[derive(Clone)]
pub struct OptVec<T>(Vec<Option<T>>);

impl<T> Default for OptVec<T> {
    fn default() -> Self {
        Self(Vec::new())
    }
}

impl<T> OptVec<T> {
    pub fn insert(&mut self, index: usize, value: T) {
        if index >= self.0.len() {
            let n = index + 1 - self.0.len();
            self.0.reserve(n);
            for _ in 0..n {
                self.0.push(None);
            }
        }
        self.0[index] = Some(value);
    }

    pub fn iter(&self) -> impl Iterator<Item = (usize, &T)> {
        self.0
            .iter()
            .enumerate()
            .filter_map(|(k, v)| v.as_ref().map(|v| (k, v)))
    }

    pub fn map<S, F>(&self, mut f: F) -> OptVec<S>
    where
        F: FnMut(&T) -> S,
    {
        OptVec(self.0.iter().map(|v| v.as_ref().map(|v| f(v))).collect())
    }

    pub fn get(&self, idx: usize) -> Option<&T> {
        self.0.get(idx).and_then(|v| v.as_ref())
    }

    pub fn get_mut(&mut self, idx: usize) -> Option<&mut T> {
        self.0.get_mut(idx).and_then(|v| v.as_mut())
    }
}

impl<T> Index<usize> for OptVec<T> {
    type Output = T;

    fn index(&self, idx: usize) -> &T {
        self.0[idx].as_ref().unwrap()
    }
}

impl<T> IndexMut<usize> for OptVec<T> {
    fn index_mut(&mut self, idx: usize) -> &mut T {
        self.0[idx].as_mut().unwrap()
    }
}