use std::collections::HashMap;
#[cfg(feature = "serialize")]
use serde::{Serialize, Deserialize};
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct BumpyEntry<T> {
pub entry: T,
pub index: usize,
pub size: usize,
}
impl<T> From<(T, usize, usize)> for BumpyEntry<T> {
fn from(o: (T, usize, usize)) -> Self {
BumpyEntry {
entry: o.0,
index: o.1,
size: o.2,
}
}
}
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct BumpyVector<T> {
data: HashMap<usize, BumpyEntry<T>>,
max_size: usize,
}
impl<'a, T> BumpyVector<T> {
pub fn new(max_size: usize) -> Self {
BumpyVector {
data: HashMap::new(),
max_size: max_size,
}
}
fn get_entry_start(&self, starting_index: usize) -> Option<usize> {
let mut index = starting_index;
loop {
match self.data.get(&index) {
Some(d) => {
if d.size <= (starting_index - index) {
return None;
}
return Some(index);
},
None => {
if index == 0 {
return None;
}
index -= 1;
},
};
}
}
pub fn insert(&mut self, entry: BumpyEntry<T>) -> Result<(), &'static str> {
if entry.size == 0 {
return Err("Zero is an invalid size for an entry");
}
if entry.index + entry.size > self.max_size {
return Err("Invalid entry: entry exceeds max size");
}
if self.get_entry_start(entry.index).is_some() {
return Err("Invalid entry: overlaps another object");
}
for x in entry.index..(entry.index + entry.size) {
if self.data.contains_key(&x) {
return Err("Invalid entry: overlaps another object");
}
}
self.data.insert(entry.index, entry);
Ok(())
}
pub fn remove(&mut self, index: usize) -> Option<BumpyEntry<T>> {
let real_offset = self.get_entry_start(index);
if let Some(o) = real_offset {
if let Some(d) = self.data.remove(&o) {
return Some(d);
}
}
None
}
pub fn remove_range(&mut self, index: usize, length: usize) -> Vec<BumpyEntry<T>> {
let mut result: Vec<BumpyEntry<T>> = Vec::new();
for i in index..(index+length) {
if let Some(e) = self.remove(i) {
result.push(e);
}
}
result
}
pub fn get(&self, index: usize) -> Option<&BumpyEntry<T>> {
let real_offset = self.get_entry_start(index);
if let Some(o) = real_offset {
return self.data.get(&o);
}
None
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut BumpyEntry<T>> {
let real_offset = self.get_entry_start(index);
if let Some(o) = real_offset {
return self.data.get_mut(&o);
}
None
}
pub fn get_exact(&self, index: usize) -> Option<&BumpyEntry<T>> {
self.data.get(&index)
}
pub fn get_exact_mut(&mut self, index: usize) -> Option<&mut BumpyEntry<T>> {
self.data.get_mut(&index)
}
pub fn get_range(&self, start: usize, length: usize) -> Vec<&BumpyEntry<T>> {
let mut result: Vec<&BumpyEntry<T>> = Vec::new();
let mut i = match self.get_entry_start(start) {
Some(e) => e,
None => start,
};
while i < start + length && i < self.max_size {
if let Some(e) = self.data.get(&i) {
result.push(e);
if e.size == 0 {
panic!("Entry size cannot be 0!");
}
i += e.size;
} else {
i += 1;
}
}
result
}
pub fn len(&self) -> usize {
return self.data.len();
}
pub fn max_size(&self) -> usize {
return self.max_size;
}
}
impl<'a, T> IntoIterator for &'a BumpyVector<T> {
type Item = &'a BumpyEntry<T>;
type IntoIter = std::vec::IntoIter<&'a BumpyEntry<T>>;
fn into_iter(self) -> std::vec::IntoIter<&'a BumpyEntry<T>> {
return self.get_range(0, self.max_size).into_iter();
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_insert() {
let mut h: BumpyVector<&str> = BumpyVector::new(100);
h.insert(("hello", 10, 5).into()).unwrap();
assert_eq!(1, h.len());
assert!(h.get(8).is_none());
assert!(h.get(9).is_none());
assert_eq!("hello", h.get(10).unwrap().entry);
assert_eq!(10, h.get(10).unwrap().index);
assert_eq!(5, h.get(10).unwrap().size);
assert_eq!("hello", h.get(11).unwrap().entry);
assert_eq!(10, h.get(11).unwrap().index);
assert_eq!(5, h.get(11).unwrap().size);
assert_eq!("hello", h.get(12).unwrap().entry);
assert_eq!(10, h.get(12).unwrap().index);
assert_eq!(5, h.get(12).unwrap().size);
assert_eq!("hello", h.get(13).unwrap().entry);
assert_eq!(10, h.get(13).unwrap().index);
assert_eq!(5, h.get(13).unwrap().size);
assert_eq!("hello", h.get(14).unwrap().entry);
assert_eq!(10, h.get(14).unwrap().index);
assert_eq!(5, h.get(14).unwrap().size);
assert!(h.get(15).is_none());
assert!(h.get(16).is_none());
assert_eq!(1, h.len());
}
#[test]
fn test_zero_sized_insert() {
let mut h: BumpyVector<&str> = BumpyVector::new(100);
assert!(h.insert(("hello", 10, 0).into()).is_err());
assert_eq!(0, h.len());
}
#[test]
fn test_overlapping_one_byte_inserts() {
let mut h: BumpyVector<&str> = BumpyVector::new(100);
h.insert(("hello", 10, 2).into()).unwrap();
assert_eq!(1, h.len());
assert!(h.insert(("ok", 8, 1).into()).is_ok());
assert_eq!(2, h.len());
assert!(h.insert(("ok", 9, 1).into()).is_ok());
assert_eq!(3, h.len());
assert!(h.insert(("error", 10, 1).into()).is_err());
assert!(h.insert(("error", 11, 1).into()).is_err());
assert_eq!(3, h.len());
assert!(h.insert(("ok", 12, 1).into()).is_ok());
assert_eq!(4, h.len());
assert!(h.insert(("ok", 13, 1).into()).is_ok());
assert_eq!(5, h.len());
}
#[test]
fn test_overlapping_multi_byte_inserts() {
let mut h: BumpyVector<&str> = BumpyVector::new(100);
h.insert(("hello", 10, 3).into()).unwrap();
assert!(h.insert(("ok", 7, 3).into()).is_ok());
let mut h: BumpyVector<&str> = BumpyVector::new(100);
h.insert(BumpyEntry::from(("hello", 10, 3))).unwrap();
assert!(h.insert(("error", 8, 3).into()).is_err());
assert!(h.insert(("error", 9, 3).into()).is_err());
assert!(h.insert(("error", 10, 3).into()).is_err());
assert!(h.insert(("error", 11, 3).into()).is_err());
assert!(h.insert(("error", 12, 3).into()).is_err());
assert!(h.insert(BumpyEntry::from(("ok", 6, 3))).is_ok());
assert!(h.insert(("ok", 13, 3).into()).is_ok());
assert_eq!(3, h.len());
}
#[test]
fn test_remove() {
let mut h: BumpyVector<&str> = BumpyVector::new(100);
h.insert(("hello", 8, 2).into()).unwrap();
h.insert(("hello", 10, 2).into()).unwrap();
h.insert(("hello", 12, 2).into()).unwrap();
assert_eq!(3, h.len());
let e = h.remove(10).unwrap();
assert_eq!("hello", e.entry);
assert_eq!(10, e.index);
assert_eq!(2, e.size);
assert_eq!(2, h.len());
assert!(h.get(10).is_none());
assert!(h.get(11).is_none());
h.insert(("hello", 10, 2).into()).unwrap();
assert_eq!(3, h.len());
let e = h.remove(11).unwrap();
assert_eq!("hello", e.entry);
assert_eq!(10, e.index);
assert_eq!(2, e.size);
assert_eq!(2, h.len());
assert!(h.get(10).is_none());
assert!(h.get(11).is_none());
let result = h.remove(11);
assert!(result.is_none());
let e = h.remove(13).unwrap();
assert_eq!("hello", e.entry);
assert_eq!(12, e.index);
assert_eq!(2, e.size);
assert_eq!(1, h.len());
assert!(h.get(12).is_none());
assert!(h.get(13).is_none());
h.remove(8);
assert_eq!(0, h.len());
assert!(h.get(8).is_none());
assert!(h.get(9).is_none());
}
#[test]
fn test_beginning() {
let mut h: BumpyVector<&str> = BumpyVector::new(10);
h.insert(("hello", 0, 2).into()).unwrap();
assert_eq!(1, h.len());
assert_eq!("hello", h.get(0).unwrap().entry);
assert_eq!(0, h.get(0).unwrap().index);
assert_eq!(2, h.get(0).unwrap().size);
assert_eq!("hello", h.get(1).unwrap().entry);
assert_eq!(0, h.get(1).unwrap().index);
assert_eq!(2, h.get(1).unwrap().size);
assert!(h.get(2).is_none());
}
#[test]
fn test_max_size() {
let mut h: BumpyVector<&str> = BumpyVector::new(10);
assert_eq!(10, h.max_size());
h.insert(("hello", 7, 3).into()).unwrap();
assert_eq!(1, h.len());
let mut h: BumpyVector<&str> = BumpyVector::new(10);
assert!(h.insert(("hello", 8, 3).into()).is_err());
assert_eq!(0, h.len());
let mut h: BumpyVector<&str> = BumpyVector::new(10);
assert!(h.insert(("hello", 9, 3).into()).is_err());
assert_eq!(0, h.len());
let mut h: BumpyVector<&str> = BumpyVector::new(10);
assert!(h.insert(("hello", 10, 3).into()).is_err());
assert_eq!(0, h.len());
let mut h: BumpyVector<&str> = BumpyVector::new(10);
assert!(h.insert(("hello", 11, 3).into()).is_err());
assert_eq!(0, h.len());
}
#[test]
fn test_remove_range() {
let mut h: BumpyVector<&str> = BumpyVector::new(100);
h.insert(("hello", 8, 2).into()).unwrap();
h.insert(("hello", 10, 2).into()).unwrap();
h.insert(("hello", 12, 2).into()).unwrap();
assert_eq!(3, h.len());
let result = h.remove_range(8, 4);
assert_eq!(1, h.len());
assert_eq!(2, result.len());
assert_eq!("hello", result[0].entry);
assert_eq!(8, result[0].index);
assert_eq!(2, result[0].size);
assert_eq!("hello", result[1].entry);
assert_eq!(10, result[1].index);
assert_eq!(2, result[1].size);
let mut h: BumpyVector<&str> = BumpyVector::new(100);
h.insert(("hello", 8, 2).into()).unwrap();
h.insert(("hello", 10, 2).into()).unwrap();
h.insert(("hello", 12, 2).into()).unwrap();
assert_eq!(3, h.len());
let result = h.remove_range(9, 2);
assert_eq!(1, h.len());
assert_eq!(2, result.len());
assert_eq!("hello", result[0].entry);
assert_eq!(8, result[0].index);
assert_eq!(2, result[0].size);
assert_eq!("hello", result[1].entry);
assert_eq!(10, result[1].index);
assert_eq!(2, result[1].size);
let mut h: BumpyVector<&str> = BumpyVector::new(100);
h.insert(("hello", 8, 2).into()).unwrap();
h.insert(("hello", 10, 2).into()).unwrap();
h.insert(("hello", 12, 2).into()).unwrap();
assert_eq!(3, h.len());
let result = h.remove_range(0, 1000);
assert_eq!(0, h.len());
assert_eq!(3, result.len());
assert_eq!("hello", result[0].entry);
assert_eq!(8, result[0].index);
assert_eq!(2, result[0].size);
assert_eq!("hello", result[1].entry);
assert_eq!(10, result[1].index);
assert_eq!(2, result[1].size);
}
#[test]
fn test_get() {
let mut h: BumpyVector<&str> = BumpyVector::new(100);
h.insert(("hello", 8, 2).into()).unwrap();
assert!(h.get(7).is_none());
assert!(h.get(8).is_some());
assert!(h.get(9).is_some());
assert!(h.get(10).is_none());
}
#[test]
fn test_get_mut() {
let mut h: BumpyVector<String> = BumpyVector::new(100);
h.insert((String::from("hello"), 8, 2).into()).unwrap();
let s = h.get_mut(9).unwrap();
s.entry.make_ascii_uppercase();
let s2 = h.get(8).unwrap();
assert_eq!("HELLO", s2.entry);
}
#[test]
fn test_get_exact() {
let mut h: BumpyVector<&str> = BumpyVector::new(100);
h.insert(("hello", 8, 2).into()).unwrap();
assert!(h.get_exact(7).is_none());
assert!(h.get_exact(8).is_some());
assert!(h.get_exact(9).is_none());
assert!(h.get_exact(10).is_none());
}
#[test]
fn test_get_exact_mut() {
let mut h: BumpyVector<String> = BumpyVector::new(100);
h.insert((String::from("hello"), 8, 2).into()).unwrap();
assert!(h.get_exact_mut(9).is_none());
let s = h.get_exact_mut(8).unwrap();
s.entry.make_ascii_uppercase();
let s = h.get_exact(8).unwrap();
assert_eq!("HELLO", s.entry);
}
#[test]
fn test_get_range() {
let mut h: BumpyVector<&str> = BumpyVector::new(10);
h.insert(("a", 1, 2).into()).unwrap();
h.insert(("b", 3, 1).into()).unwrap();
h.insert(("c", 6, 3).into()).unwrap();
let result = h.get_range(2, 4);
assert_eq!(2, result.len());
let result = h.get_range(2, 5);
assert_eq!(3, result.len());
let result = h.get_range(1, 5);
assert_eq!(2, result.len());
let result = h.get_range(1, 6);
assert_eq!(3, result.len());
let result = h.get_range(0, 100);
assert_eq!(3, result.len());
}
#[test]
fn test_iterator() {
let mut h: BumpyVector<&str> = BumpyVector::new(10);
h.insert(("a", 1, 2).into()).unwrap();
h.insert(("b", 3, 1).into()).unwrap();
h.insert(("c", 6, 3).into()).unwrap();
let mut iter = h.into_iter();
let e = iter.next().unwrap();
assert_eq!("a", e.entry);
assert_eq!(1, e.index);
assert_eq!(2, e.size);
let e = iter.next().unwrap();
assert_eq!("b", e.entry);
assert_eq!(3, e.index);
assert_eq!(1, e.size);
let e = iter.next().unwrap();
assert_eq!("c", e.entry);
assert_eq!(6, e.index);
assert_eq!(3, e.size);
assert!(iter.next().is_none());
assert!(iter.next().is_none());
}
#[test]
#[cfg(feature = "serialize")] fn test_serialize() {
let mut h: BumpyVector<String> = BumpyVector::new(10);
h.insert((String::from("a"), 1, 2).into()).unwrap();
h.insert((String::from("b"), 3, 1).into()).unwrap();
h.insert((String::from("c"), 6, 3).into()).unwrap();
let serialized = ron::ser::to_string(&h).unwrap();
let h: BumpyVector<String> = ron::de::from_str(&serialized).unwrap();
assert_eq!("a", h.get(2).unwrap().entry);
assert_eq!(1, h.get(2).unwrap().index);
assert_eq!(2, h.get(2).unwrap().size);
assert_eq!("b", h.get(3).unwrap().entry);
assert!(h.get(4).is_none());
assert!(h.get(5).is_none());
assert_eq!("c", h.get(6).unwrap().entry);
assert_eq!(6, h.get(6).unwrap().index);
assert_eq!(3, h.get(6).unwrap().size);
}
#[test]
fn test_clone() {
let mut h: BumpyVector<String> = BumpyVector::new(10);
h.insert((String::from("a"), 1, 2).into()).unwrap();
h.insert((String::from("b"), 3, 1).into()).unwrap();
h.insert((String::from("c"), 6, 3).into()).unwrap();
let cloned = h.clone();
assert_eq!("a", cloned.get(2).unwrap().entry);
assert_eq!(1, cloned.get(2).unwrap().index);
assert_eq!(2, cloned.get(2).unwrap().size);
assert_eq!("b", cloned.get(3).unwrap().entry);
assert!(cloned.get(4).is_none());
assert!(cloned.get(5).is_none());
assert_eq!("c", cloned.get(6).unwrap().entry);
assert_eq!(6, cloned.get(6).unwrap().index);
assert_eq!(3, cloned.get(6).unwrap().size);
}
}