rust/hedgewars-server/src/core/indexslab.rs
author S.D.
Tue, 27 Sep 2022 14:59:03 +0300
changeset 15900 fc3cb23fd26f
parent 15465 61a0bd0bb021
permissions -rw-r--r--
Allow to see rooms of incompatible versions in the lobby For the new clients the room version is shown in a separate column. There is also a hack for previous versions clients: the room vesion specifier is prepended to the room names for rooms of incompatible versions, and the server shows 'incompatible version' error if the client tries to join them.

use std::{
    iter,
    mem::replace,
    ops::{Index, IndexMut},
};

pub struct IndexSlab<T> {
    data: Vec<Option<T>>,
}

impl<T> IndexSlab<T> {
    pub fn new() -> Self {
        Self { data: Vec::new() }
    }

    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            data: Vec::with_capacity(capacity),
        }
    }

    pub fn get(&self, index: usize) -> Option<&T> {
        self.data[index].as_ref()
    }

    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
        self.data[index].as_mut()
    }

    pub fn insert(&mut self, index: usize, value: T) {
        if index >= self.data.len() {
            self.data.reserve(index - self.data.len() + 1);
            self.data.extend((self.data.len()..index).map(|_| None));
            self.data.push(Some(value))
        } else {
            self.data[index] = Some(value);
        }
    }

    pub fn contains(&self, index: usize) -> bool {
        self.data.get(index).and_then(|x| x.as_ref()).is_some()
    }

    pub fn remove(&mut self, index: usize) -> Option<T> {
        if let Some(x) = self.data.get_mut(index) {
            replace(x, None)
        } else {
            None
        }
    }

    pub fn iter(&self) -> impl Iterator<Item = (usize, &T)> + Clone {
        self.data
            .iter()
            .enumerate()
            .filter_map(|(index, opt)| opt.as_ref().and_then(|x| Some((index, x))))
    }

    pub fn iter_mut(&mut self) -> impl Iterator<Item = (usize, &mut T)> {
        self.data
            .iter_mut()
            .enumerate()
            .filter_map(|(index, opt)| opt.as_mut().and_then(|x| Some((index, x))))
    }
}

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

    fn index(&self, index: usize) -> &Self::Output {
        self.data[index].as_ref().unwrap()
    }
}

impl<T> IndexMut<usize> for IndexSlab<T> {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        self.data[index].as_mut().unwrap()
    }
}