use std::marker::PhantomData;
use std::fmt::{self, Formatter};
use std::hash::{self, Hasher};
use std::cmp::Ordering;
#[derive(Clone)]
pub struct Reservoir<T>(Vec<T>);
impl<T> Reservoir<T> {
pub const SMALL_CAPACITY: usize = 64;
pub const MEDIUM_CAPACITY: usize = 256;
pub const LARGE_CAPACITY: usize = 1024;
pub fn new(capacity: usize) -> Self {
Reservoir(Vec::with_capacity(capacity))
}
pub fn get(&self, handle: Handle<T>) -> &T {
&self.0[handle.0]
}
pub fn get_mut(&mut self, handle: Handle<T>) -> &mut T {
&mut self.0[handle.0]
}
pub fn insert(&mut self, data: T) -> Handle<T> {
self.0.push(data);
Handle(self.0.len() - 1, PhantomData)
}
}
impl<T> Default for Reservoir<T> {
fn default() -> Self {
Reservoir::new(Self::MEDIUM_CAPACITY)
}
}
pub struct Handle<T>(usize, PhantomData<T>);
impl<T> Clone for Handle<T> {
fn clone(&self) -> Self {
Handle(self.0, self.1)
}
}
impl<T> fmt::Debug for Handle<T> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Handle({})", self.0)
}
}
impl<T> hash::Hash for Handle<T> {
fn hash<H>(&self, state: &mut H) where H: Hasher {
self.0.hash(state)
}
}
impl<T> PartialEq for Handle<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T> PartialOrd for Handle<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<T> Ord for Handle<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}
impl<T> Copy for Handle<T> {}
impl<T> Eq for Handle<T> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sanity_check() {
let mut r: Reservoir<String> = Reservoir::default();
let h = r.insert(String::from("hello"));
assert_eq!("hello", r.get(h));
r.get_mut(h).push('!');
assert_eq!("hello!", r.get(h));
}
}