#![deny(missing_docs)]
#![doc = include_str!("../README.md")]
use std::collections::{BTreeMap, HashMap};
use std::fmt::Display;
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FixedIndexVec<T> {
map: BTreeMap<usize, T>,
next_index: usize,
}
impl<T: Display> Display for FixedIndexVec<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut s = String::new();
for (i, v) in self.iter() {
s.push_str(&format!("{}: {}\n", i, v));
}
write!(f, "{}", s)
}
}
impl<T> FixedIndexVec<T> {
pub fn new() -> FixedIndexVec<T> {
FixedIndexVec {
map: BTreeMap::new(),
next_index: 0,
}
}
pub fn push(&mut self, value: T) {
self.map.insert(self.next_index, value);
self.next_index += 1;
}
pub fn insert(&mut self, value: T) {
self.push(value);
}
pub fn remove(&mut self, index: usize) -> Option<T> {
self.map.remove(&index)
}
pub fn get(&self, index: usize) -> Option<&T> {
self.map.get(&index)
}
pub fn iter(&self) -> impl Iterator<Item = (usize, &T)> {
self.map.iter().map(|(i, v)| (*i, v))
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn clear(&mut self) {
self.map.clear();
}
pub fn reset(&mut self) {
self.map.clear();
self.next_index = 0;
}
pub fn next_index(&self) -> usize {
self.next_index
}
pub fn first(&self) -> Option<(usize, &T)> {
self.iter().next()
}
pub fn last(&self) -> Option<(usize, &T)> {
self.iter().last()
}
}
impl<T> std::ops::Index<usize> for FixedIndexVec<T> {
type Output = T;
fn index(&self, index: usize) -> &T {
self.get(index).unwrap()
}
}
impl<T> FromIterator<T> for FixedIndexVec<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> FixedIndexVec<T> {
let mut map = BTreeMap::new();
for (i, v) in iter.into_iter().enumerate() {
map.insert(i, v);
}
FixedIndexVec {
next_index: map.len(),
map,
}
}
}
impl<T> Extend<T> for FixedIndexVec<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for v in iter.into_iter() {
self.push(v);
}
}
}
impl<T> From<Vec<T>> for FixedIndexVec<T> {
fn from(vec: Vec<T>) -> FixedIndexVec<T> {
vec.into_iter().collect()
}
}
impl<T, A> From<HashMap<A, T>> for FixedIndexVec<T> {
fn from(map: HashMap<A, T>) -> FixedIndexVec<T> {
map.into_values().collect()
}
}
impl<T, A> From<BTreeMap<A, T>> for FixedIndexVec<T> {
fn from(map: BTreeMap<A, T>) -> FixedIndexVec<T> {
map.into_values().collect()
}
}
#[cfg(test)]
mod tests {
use super::FixedIndexVec;
#[test]
fn test_send() {
fn assert_send<T: Send>() {}
assert_send::<FixedIndexVec<i32>>();
assert_send::<FixedIndexVec<f32>>();
assert_send::<FixedIndexVec<String>>();
}
#[test]
fn test_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<FixedIndexVec<i32>>();
assert_sync::<FixedIndexVec<f32>>();
assert_sync::<FixedIndexVec<String>>();
}
}