use std::ops::{Deref, DerefMut};
use rt_ref::{BorrowFail, Cell, Ref, RefMut};
#[derive(Debug)]
pub struct RtVec<V>(Vec<Cell<V>>);
impl<V> Default for RtVec<V> {
fn default() -> Self {
Self(Default::default())
}
}
macro_rules! borrow_panic {
($index:ident) => {
panic!(
"Expected to borrow index `{index}`, but it does not exist.",
index = $index
)
};
}
impl<V> RtVec<V> {
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(capacity: usize) -> Self {
Self(Vec::with_capacity(capacity))
}
pub fn capacity(&self) -> usize {
self.0.capacity()
}
pub fn push(&mut self, v: V) {
self.0.push(Cell::new(v));
}
pub fn insert(&mut self, index: usize, v: V) {
self.0.insert(index, Cell::new(v));
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn remove(&mut self, index: usize) -> V {
let cell = self.0.remove(index);
Cell::into_inner(cell)
}
pub fn swap_remove(&mut self, index: usize) -> V {
let cell = self.0.swap_remove(index);
Cell::into_inner(cell)
}
pub fn borrow(&self, index: usize) -> Ref<V> {
self.0
.get(index)
.map(|cell| Ref::new(cell.borrow()))
.unwrap_or_else(|| borrow_panic!(index))
}
pub fn try_borrow(&self, index: usize) -> Result<Ref<V>, BorrowFail> {
self.0
.get(index)
.ok_or(BorrowFail::ValueNotFound)
.and_then(|cell| cell.try_borrow().map(Ref::new))
}
pub fn borrow_mut(&self, index: usize) -> RefMut<V> {
self.0
.get(index)
.map(|cell| RefMut::new(cell.borrow_mut()))
.unwrap_or_else(|| borrow_panic!(index))
}
pub fn try_borrow_mut(&self, index: usize) -> Result<RefMut<V>, BorrowFail> {
self.0
.get(index)
.ok_or(BorrowFail::ValueNotFound)
.and_then(|r_cell| {
r_cell
.try_borrow_mut()
.map(|cell_ref_mut| RefMut::new(cell_ref_mut))
})
}
pub fn get(&self, index: usize) -> Option<Ref<V>> {
self.0.get(index).map(|cell| Ref::new(cell.borrow()))
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut V> {
self.get_value_mut(index)
}
pub fn get_value_mut(&mut self, index: usize) -> Option<&mut V> {
self.0.get_mut(index).map(Cell::get_mut)
}
pub fn get_raw(&self, index: usize) -> Option<&Cell<V>> {
self.0.get(index)
}
}
impl<V> Deref for RtVec<V> {
type Target = Vec<Cell<V>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<V> DerefMut for RtVec<V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[cfg(test)]
mod tests {
use rt_ref::BorrowFail;
use super::RtVec;
#[derive(Debug, Default, PartialEq)]
struct Res;
#[derive(Debug, Default, PartialEq)]
struct Value(u32);
#[test]
fn insert() {
let mut rt_vec = RtVec::new();
rt_vec.insert(0, Res);
assert_eq!(Res, *rt_vec.borrow(0));
}
#[test]
fn with_capacity_reserves_enough_capacity() {
let rt_vec: RtVec<i32> = RtVec::with_capacity(100);
assert!(rt_vec.capacity() >= 100);
}
#[test]
fn deref_and_deref_mut() {
let mut rt_vec = RtVec::new();
rt_vec.insert(0, 0);
rt_vec.insert(1, 1);
rt_vec.iter_mut().for_each(|v| *v.borrow_mut() += 1);
let a = rt_vec.remove(0);
assert_eq!(1, a);
let b = rt_vec.iter().next();
assert_eq!(Some(2), b.map(|v| *v.borrow()));
}
#[test]
fn is_empty_returns_true_when_map_does_not_contain_items() {
let rt_vec = RtVec::<u32>::new();
assert!(rt_vec.is_empty());
}
#[test]
fn is_empty_returns_false_when_map_contains_items() {
let mut rt_vec = RtVec::new();
rt_vec.push(0);
assert!(!rt_vec.is_empty());
}
#[test]
fn get_mut_returns_mutable_reference_to_value() {
let mut rt_vec = RtVec::new();
rt_vec.push(Value(1));
let value = rt_vec.get_mut(0);
assert!(value.is_some());
if let Some(value) = value {
*value = Value(2);
}
let value = rt_vec.get_mut(0).map(|value| value.0);
assert_eq!(Some(2), value);
}
#[test]
#[should_panic(expected = "but it was already borrowed")]
fn read_write_fails() {
let mut rt_vec = RtVec::new();
rt_vec.push(Res);
let _read = rt_vec.borrow(0);
let _write = rt_vec.borrow_mut(0);
}
#[test]
#[should_panic(expected = "but it was already borrowed mutably")]
fn write_read_fails() {
let mut rt_vec = RtVec::new();
rt_vec.push(Res);
let _write = rt_vec.borrow_mut(0);
let _read = rt_vec.borrow(0);
}
#[test]
fn remove_insert() {
let mut rt_vec = RtVec::new();
rt_vec.push(Res);
assert_eq!(Res, *rt_vec.borrow(0));
rt_vec.remove(0);
assert_eq!(None, rt_vec.get(0));
rt_vec.push(Res);
assert_eq!(Res, *rt_vec.borrow(0));
}
#[test]
fn swap_remove() {
let mut rt_vec = RtVec::new();
rt_vec.push(0);
rt_vec.push(1);
rt_vec.push(2);
rt_vec.swap_remove(1);
assert_eq!(2, *rt_vec.borrow(1));
}
#[test]
#[should_panic(expected = "Expected to borrow index `0`, but it does not exist.")]
fn borrow_before_insert_panics() {
let rt_vec = RtVec::<i32>::new();
rt_vec.borrow(0);
}
#[test]
#[should_panic(expected = "Expected to borrow index `0`, but it does not exist.")]
fn borrow_mut_before_insert_panics() {
let rt_vec = RtVec::<i32>::new();
rt_vec.borrow_mut(0);
}
#[test]
fn borrow_mut_try_borrow_returns_borrow_conflict_imm() {
let mut rt_vec = RtVec::new();
rt_vec.push(Res);
let _res = rt_vec.borrow_mut(0);
assert_eq!(Err(BorrowFail::BorrowConflictImm), rt_vec.try_borrow(0));
}
#[test]
fn borrow_try_borrow_mut_returns_borrow_conflict_mut() {
let mut rt_vec = RtVec::new();
rt_vec.push(Res);
let _res = rt_vec.borrow(0);
assert_eq!(Err(BorrowFail::BorrowConflictMut), rt_vec.try_borrow_mut(0));
}
#[test]
fn borrow_mut_borrow_mut_returns_borrow_conflict_mut() {
let mut rt_vec = RtVec::new();
rt_vec.push(Res);
let _res = rt_vec.borrow_mut(0);
assert_eq!(Err(BorrowFail::BorrowConflictMut), rt_vec.try_borrow_mut(0));
}
#[test]
fn try_borrow_before_insert_returns_value_not_found() {
let rt_vec = RtVec::<Res>::new();
assert_eq!(Err(BorrowFail::ValueNotFound), rt_vec.try_borrow(0));
}
#[test]
fn try_borrow_mut_before_insert_returns_value_not_found() {
let rt_vec = RtVec::<Res>::new();
assert_eq!(Err(BorrowFail::ValueNotFound), rt_vec.try_borrow_mut(0));
}
#[test]
#[should_panic(expected = "Expected to borrow index `0`, but it does not exist.")]
fn borrow_before_insert_panics_value_not_found() {
let rt_vec = RtVec::<Res>::new();
rt_vec.borrow(0);
}
#[test]
#[should_panic(expected = "Expected to borrow index `0`, but it does not exist.")]
fn borrow_mut_before_insert_panics_value_not_found() {
let rt_vec = RtVec::<Res>::new();
rt_vec.borrow_mut(0);
}
}