use crate::traits::{ReadBackend, WriteBackend, Construct, ValueOf, RootStatus, Dangling, Owned, Leak, Error, Tree, Sequence};
use crate::vector::Vector;
use crate::raw::Raw;
use crate::length::LengthMixed;
pub type OwnedList<C> = List<Owned, C>;
pub type DanglingList<C> = List<Dangling, C>;
pub struct List<R: RootStatus, C: Construct>(LengthMixed<R, C, Vector<Dangling, C>>);
impl<R: RootStatus, C: Construct> List<R, C> where
C::End: From<usize> + Into<usize>,
{
pub fn get<DB: ReadBackend<Construct=C>>(&self, db: &mut DB, index: usize) -> Result<ValueOf<C>, Error<DB::Error>> {
self.0.with(db, |tuple, db| tuple.get(db, index))
}
pub fn set<DB: WriteBackend<Construct=C>>(&mut self, db: &mut DB, index: usize, value: ValueOf<C>) -> Result<(), Error<DB::Error>> {
self.0.with_mut(db, |tuple, db| tuple.set(db, index, value))
}
pub fn push<DB: WriteBackend<Construct=C>>(&mut self, db: &mut DB, value: ValueOf<C>) -> Result<(), Error<DB::Error>> {
self.0.with_mut(db, |tuple, db| tuple.push(db, value))
}
pub fn pop<DB: WriteBackend<Construct=C>>(&mut self, db: &mut DB) -> Result<Option<ValueOf<C>>, Error<DB::Error>> {
self.0.with_mut(db, |tuple, db| tuple.pop(db))
}
pub fn deconstruct<DB: ReadBackend<Construct=C>>(self, db: &mut DB) -> Result<ValueOf<C>, Error<DB::Error>> {
self.0.deconstruct(db)
}
pub fn reconstruct<DB: WriteBackend<Construct=C>>(root: ValueOf<C>, db: &mut DB, max_len: Option<usize>) -> Result<Self, Error<DB::Error>> {
Ok(Self(LengthMixed::reconstruct(root, db, |tuple_raw, _db, len| {
Ok(Vector::<Dangling, C>::from_raw(tuple_raw, len, max_len))
})?))
}
}
impl<R: RootStatus, C: Construct> Tree for List<R, C> where
C::End: From<usize> + Into<usize>,
{
type RootStatus = R;
type Construct = C;
fn root(&self) -> ValueOf<C> {
self.0.root()
}
fn drop<DB: WriteBackend<Construct=C>>(self, db: &mut DB) -> Result<(), Error<DB::Error>> {
self.0.drop(db)
}
fn into_raw(self) -> Raw<R, C> {
self.0.into_raw()
}
}
impl<R: RootStatus, C: Construct> Sequence for List<R, C> where
C::End: From<usize> + Into<usize>,
{
fn len(&self) -> usize {
self.0.len()
}
}
impl<R: RootStatus, C: Construct> Leak for List<R, C> where
C::End: From<usize> + Into<usize>,
{
type Metadata = <LengthMixed<R, C, Vector<Dangling, C>> as Leak>::Metadata;
fn metadata(&self) -> Self::Metadata {
self.0.metadata()
}
fn from_leaked(metadata: Self::Metadata) -> Self {
Self(LengthMixed::from_leaked(metadata))
}
}
impl<C: Construct> List<Owned, C> where
C::End: From<usize> + Into<usize>
{
pub fn create<DB: WriteBackend<Construct=C>>(
db: &mut DB,
max_len: Option<usize>
) -> Result<Self, Error<DB::Error>> {
Ok(Self(LengthMixed::create(db, |db| Vector::<Owned, _>::create(db, 0, max_len))?))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Value;
use sha2::Sha256;
type InheritedInMemory = crate::memory::InMemoryBackend<crate::InheritedDigestConstruct<Sha256, ListValue>>;
type UnitInMemory = crate::memory::InMemoryBackend<crate::UnitDigestConstruct<Sha256, ListValue>>;
#[derive(Clone, PartialEq, Eq, Debug, Default)]
struct ListValue(Vec<u8>);
impl AsRef<[u8]> for ListValue {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl From<usize> for ListValue {
fn from(value: usize) -> Self {
ListValue((&(value as u64).to_le_bytes()[..]).into())
}
}
impl Into<usize> for ListValue {
fn into(self) -> usize {
let mut raw = [0u8; 8];
(&mut raw).copy_from_slice(&self.0[0..8]);
u64::from_le_bytes(raw) as usize
}
}
#[test]
fn test_push_pop_inherited() {
let mut db = InheritedInMemory::default();
let mut vec = List::create(&mut db, None).unwrap();
let mut roots = Vec::new();
for i in 0..100 {
assert_eq!(vec.len(), i);
vec.push(&mut db, Value::End(i.into())).unwrap();
roots.push(vec.root());
}
assert_eq!(vec.len(), 100);
for i in (0..100).rev() {
assert_eq!(vec.root(), roots.pop().unwrap());
let value = vec.pop(&mut db).unwrap();
assert_eq!(value, Some(Value::End(i.into())));
assert_eq!(vec.len(), i);
}
assert_eq!(vec.len(), 0);
}
#[test]
fn test_push_pop_unit() {
let mut db = UnitInMemory::default();
let mut vec = List::create(&mut db, None).unwrap();
let mut roots = Vec::new();
for i in 0..100 {
assert_eq!(vec.len(), i);
vec.push(&mut db, Value::End(i.into())).unwrap();
roots.push(vec.root());
}
assert_eq!(vec.len(), 100);
for i in (0..100).rev() {
assert_eq!(vec.root(), roots.pop().unwrap());
let value = vec.pop(&mut db).unwrap();
assert_eq!(value, Some(Value::End(i.into())));
assert_eq!(vec.len(), i);
}
assert_eq!(vec.len(), 0);
}
#[test]
fn test_set() {
let mut db = InheritedInMemory::default();
let mut vec = OwnedList::create(&mut db, None).unwrap();
for i in 0..100 {
assert_eq!(vec.len(), i);
vec.push(&mut db, Value::End(Default::default())).unwrap();
}
for i in 0..100 {
vec.set(&mut db, i, Value::End(i.into())).unwrap();
}
for i in 0..100 {
assert_eq!(vec.get(&mut db, i).unwrap(), Value::End(i.into()));
}
}
#[test]
fn test_deconstruct_reconstruct() {
let mut db = InheritedInMemory::default();
let mut vec = OwnedList::create(&mut db, None).unwrap();
for i in 0..100 {
assert_eq!(vec.len(), i);
vec.push(&mut db, Value::End(i.into())).unwrap();
}
let vec_hash = vec.deconstruct(&mut db).unwrap();
let vec = OwnedList::reconstruct(vec_hash, &mut db, None).unwrap();
assert_eq!(vec.len(), 100);
for i in (0..100).rev() {
assert_eq!(vec.get(&mut db, i).unwrap(), Value::End(i.into()));
}
}
}