VecVersion: make it read-only, only the latest version can be modified

This commit is contained in:
Egor Suvorov
2022-11-24 01:28:13 +02:00
parent 45617ceaef
commit e5550a01b0
3 changed files with 108 additions and 56 deletions

View File

@@ -42,17 +42,25 @@ pub trait RangeModification<Key> {
fn compose(later: &Self, earlier: &mut Self);
}
pub trait VecVersion<Modification: RangeModification<Key>, Key>: Clone {
pub trait VecReadableVersion<Modification: RangeModification<Key>, Key> {
fn get(&self, keys: Range<Key>) -> Modification::Result;
fn modify(&mut self, keys: Range<Key>, modification: Modification);
}
pub trait VecFrozenVersion<Modification: RangeModification<Key>, Key>:
Clone + VecReadableVersion<Modification, Key>
{
}
pub trait PersistentVecStorage<
Modification: RangeModification<Key>,
Initializer: LazyRangeInitializer<Modification::Result, Key>,
Key,
>
>: VecReadableVersion<Modification, Key>
{
type Version: VecVersion<Modification, Key>;
fn new(all_keys: Range<Key>, initializer: Initializer) -> Self::Version;
fn new(all_keys: Range<Key>, initializer: Initializer) -> Self;
type FrozenVersion: VecFrozenVersion<Modification, Key>;
fn modify(&mut self, keys: Range<Key>, modification: Modification);
fn freeze(&mut self) -> Self::FrozenVersion;
}

View File

@@ -1,16 +1,49 @@
use crate::{
LazyRangeInitializer, PersistentVecStorage, RangeModification, RangeQueryResult, VecVersion,
LazyRangeInitializer, PersistentVecStorage, RangeModification, RangeQueryResult,
VecFrozenVersion, VecReadableVersion,
};
use std::marker::PhantomData;
use std::ops::Range;
use std::rc::Rc;
pub struct NaiveVecVersion<Modification: RangeModification<Key>, Key> {
pub struct NaiveFrozenVersion<Modification: RangeModification<Key>, Key> {
all_keys: Range<Key>,
values: Vec<Modification::Result>,
values: Rc<Box<Vec<Modification::Result>>>,
}
impl<Modification: RangeModification<Key>, Key: Clone> Clone for NaiveVecVersion<Modification, Key>
where
Modification::Result: Clone,
pub trait IndexableKey: Clone {
fn index(all_keys: &Range<Self>, key: &Self) -> usize;
fn element_range(all_keys: &Range<Self>, index: usize) -> Range<Self>;
}
fn get<Modification: RangeModification<Key>, Key: IndexableKey>(
all_keys: &Range<Key>,
values: &Vec<Modification::Result>,
keys: Range<Key>,
) -> Modification::Result {
let mut result = Modification::Result::new_for_empty_range();
let mut result_range = keys.start.clone()..keys.start.clone();
for index in
IndexableKey::index(&all_keys, &keys.start)..IndexableKey::index(&all_keys, &keys.end)
{
let element_range = IndexableKey::element_range(&all_keys, index);
Modification::Result::add(&mut result, &result_range, &values[index], &element_range);
result_range.end = element_range.end;
}
result
}
impl<Modification: RangeModification<Key>, Key: IndexableKey> VecReadableVersion<Modification, Key>
for NaiveFrozenVersion<Modification, Key>
{
fn get(&self, keys: Range<Key>) -> Modification::Result {
get::<Modification, Key>(&self.all_keys, &self.values, keys)
}
}
// Manual implementation of `Clone` becase `derive` requires `Modification: Clone`
impl<'a, Modification: RangeModification<Key>, Key: Clone> Clone
for NaiveFrozenVersion<Modification, Key>
{
fn clone(&self) -> Self {
Self {
@@ -20,61 +53,72 @@ where
}
}
pub trait IndexableKey: Clone {
fn index(all_keys: &Range<Self>, key: &Self) -> usize;
fn element_range(all_keys: &Range<Self>, index: usize) -> Range<Self>;
impl<'a, Modification: RangeModification<Key>, Key: IndexableKey>
VecFrozenVersion<Modification, Key> for NaiveFrozenVersion<Modification, Key>
{
}
impl<Modification: RangeModification<Key>, Key: IndexableKey> VecVersion<Modification, Key>
for NaiveVecVersion<Modification, Key>
// TODO: is it at all possible to store previous versions in this struct,
// without any Rc<>?
pub struct NaiveVecStorage<
Modification: RangeModification<Key>,
Initializer: LazyRangeInitializer<Modification::Result, Key>,
Key: IndexableKey,
> {
all_keys: Range<Key>,
last_version: Vec<Modification::Result>,
_initializer: PhantomData<Initializer>,
}
impl<
Modification: RangeModification<Key>,
Initializer: LazyRangeInitializer<Modification::Result, Key>,
Key: IndexableKey,
> VecReadableVersion<Modification, Key> for NaiveVecStorage<Modification, Initializer, Key>
where
Modification::Result: Clone,
{
fn get(&self, keys: Range<Key>) -> Modification::Result {
let mut result = Modification::Result::new_for_empty_range();
let mut result_range = keys.start.clone()..keys.start.clone();
for index in IndexableKey::index(&self.all_keys, &keys.start)
..IndexableKey::index(&self.all_keys, &keys.end)
{
let element_range = IndexableKey::element_range(&self.all_keys, index);
Modification::Result::add(
&mut result,
&result_range,
&self.values[index],
&element_range,
);
result_range.end = element_range.end;
}
result
get::<Modification, Key>(&self.all_keys, &self.last_version, keys)
}
}
impl<
Modification: RangeModification<Key>,
Initializer: LazyRangeInitializer<Modification::Result, Key>,
Key: IndexableKey,
> PersistentVecStorage<Modification, Initializer, Key>
for NaiveVecStorage<Modification, Initializer, Key>
where
Modification::Result: Clone,
{
fn new(all_keys: Range<Key>, initializer: Initializer) -> Self {
let mut values = Vec::with_capacity(IndexableKey::index(&all_keys, &all_keys.end));
for index in 0..values.capacity() {
values.push(initializer.get(&IndexableKey::element_range(&all_keys, index)));
}
NaiveVecStorage {
all_keys,
last_version: values,
_initializer: PhantomData,
}
}
type FrozenVersion = NaiveFrozenVersion<Modification, Key>;
fn modify(&mut self, keys: Range<Key>, modification: Modification) {
for index in IndexableKey::index(&self.all_keys, &keys.start)
..IndexableKey::index(&self.all_keys, &keys.end)
{
let element_range = IndexableKey::element_range(&self.all_keys, index);
modification.apply(&mut self.values[index], &element_range);
modification.apply(&mut self.last_version[index], &element_range);
}
}
fn freeze(&mut self) -> Self::FrozenVersion {
NaiveFrozenVersion::<Modification, Key> {
all_keys: self.all_keys.clone(),
values: Rc::new(Box::new(self.last_version.clone())),
}
}
}
pub struct NaiveVecStorage;
impl<
Modification: RangeModification<Key>,
Initializer: LazyRangeInitializer<Modification::Result, Key>,
Key: IndexableKey,
> PersistentVecStorage<Modification, Initializer, Key> for NaiveVecStorage
where
Modification::Result: Clone,
{
type Version = NaiveVecVersion<Modification, Key>;
fn new(all_keys: Range<Key>, initializer: Initializer) -> Self::Version {
let mut values = Vec::with_capacity(IndexableKey::index(&all_keys, &all_keys.end));
for index in 0..values.capacity() {
values.push(initializer.get(&IndexableKey::element_range(&all_keys, index)));
}
NaiveVecVersion { all_keys, values }
}
}

View File

@@ -1,7 +1,7 @@
use persistent_range_query::naive::*;
use persistent_range_query::ops::rsq::*;
use persistent_range_query::ops::SameElementsInitializer;
use persistent_range_query::{PersistentVecStorage, VecVersion};
use persistent_range_query::{PersistentVecStorage, VecReadableVersion};
use std::ops::Range;
#[derive(Copy, Clone, Debug)]
@@ -25,13 +25,13 @@ impl SumOfSameElements<K> for i32 {
#[test]
fn test_naive() {
let mut s: NaiveVecVersion<AddAssignModification<i32>, _> =
let mut s: NaiveVecStorage<AddAssignModification<i32>, _, _> =
NaiveVecStorage::new(K(0)..K(12), SameElementsInitializer::new(0i32));
assert_eq!(*s.get(K(0)..K(12)).sum(), 0);
s.modify(K(2)..K(5), AddAssignModification::Add(3));
assert_eq!(*s.get(K(0)..K(12)).sum(), 3 + 3 + 3);
let s_old = s.clone();
let s_old = s.freeze();
s.modify(K(3)..K(6), AddAssignModification::Assign(10));
assert_eq!(*s.get(K(0)..K(12)).sum(), 3 + 10 + 10 + 10);