Start on maintaining an insertions tree
I'm correctly assigning fragment ids to all fragments in the fragments tree, but I have a randomized test failure when making sure that the insertions tree matches the state of the fragments tree.
This commit is contained in:
parent
ec54010e3c
commit
dd38eb1264
4 changed files with 140 additions and 68 deletions
|
@ -2,20 +2,20 @@ use smallvec::{smallvec, SmallVec};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Locator(SmallVec<[u32; 4]>);
|
pub struct Locator(SmallVec<[u8; 4]>);
|
||||||
|
|
||||||
impl Locator {
|
impl Locator {
|
||||||
pub fn min() -> Self {
|
pub fn min() -> Self {
|
||||||
Self(smallvec![u32::MIN])
|
Self(smallvec![u8::MIN])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max() -> Self {
|
pub fn max() -> Self {
|
||||||
Self(smallvec![u32::MAX])
|
Self(smallvec![u8::MAX])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn between(lhs: &Self, rhs: &Self) -> Self {
|
pub fn between(lhs: &Self, rhs: &Self) -> Self {
|
||||||
let lhs = lhs.0.iter().copied().chain(iter::repeat(u32::MIN));
|
let lhs = lhs.0.iter().copied().chain(iter::repeat(u8::MIN));
|
||||||
let rhs = rhs.0.iter().copied().chain(iter::repeat(u32::MAX));
|
let rhs = rhs.0.iter().copied().chain(iter::repeat(u8::MAX));
|
||||||
let mut location = SmallVec::new();
|
let mut location = SmallVec::new();
|
||||||
for (lhs, rhs) in lhs.zip(rhs) {
|
for (lhs, rhs) in lhs.zip(rhs) {
|
||||||
let mid = lhs + (rhs.saturating_sub(lhs)) / 2;
|
let mid = lhs + (rhs.saturating_sub(lhs)) / 2;
|
||||||
|
|
|
@ -14,13 +14,13 @@ impl<T: Rng> Iterator for RandomCharIter<T> {
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
match self.0.gen_range(0..100) {
|
match self.0.gen_range(0..100) {
|
||||||
// whitespace
|
// whitespace
|
||||||
0..=19 => [' ', '\n', '\t'].choose(&mut self.0).copied(),
|
0..=5 => ['\n'].choose(&mut self.0).copied(),
|
||||||
// two-byte greek letters
|
// two-byte greek letters
|
||||||
20..=32 => char::from_u32(self.0.gen_range(('α' as u32)..('ω' as u32 + 1))),
|
// 20..=32 => char::from_u32(self.0.gen_range(('α' as u32)..('ω' as u32 + 1))),
|
||||||
// three-byte characters
|
// // three-byte characters
|
||||||
33..=45 => ['✋', '✅', '❌', '❎', '⭐'].choose(&mut self.0).copied(),
|
// 33..=45 => ['✋', '✅', '❌', '❎', '⭐'].choose(&mut self.0).copied(),
|
||||||
// four-byte characters
|
// // four-byte characters
|
||||||
46..=58 => ['🍐', '🏀', '🍗', '🎉'].choose(&mut self.0).copied(),
|
// 46..=58 => ['🍐', '🏀', '🍗', '🎉'].choose(&mut self.0).copied(),
|
||||||
// ascii letters
|
// ascii letters
|
||||||
_ => Some(self.0.gen_range(b'a'..b'z' + 1).into()),
|
_ => Some(self.0.gen_range(b'a'..b'z' + 1).into()),
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ fn test_random_edits(mut rng: StdRng) {
|
||||||
);
|
);
|
||||||
|
|
||||||
for _i in 0..operations {
|
for _i in 0..operations {
|
||||||
let (old_ranges, new_text, _) = buffer.randomly_edit(&mut rng, 5);
|
let (old_ranges, new_text, _) = buffer.randomly_edit(&mut rng, 1);
|
||||||
for old_range in old_ranges.iter().rev() {
|
for old_range in old_ranges.iter().rev() {
|
||||||
reference_string.replace_range(old_range.clone(), &new_text);
|
reference_string.replace_range(old_range.clone(), &new_text);
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,27 @@ fn test_random_edits(mut rng: StdRng) {
|
||||||
TextSummary::from(&reference_string[range])
|
TextSummary::from(&reference_string[range])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Ensure every fragment is ordered by locator in the fragment tree and corresponds
|
||||||
|
// to an insertion fragment in the insertions tree.
|
||||||
|
let mut prev_fragment_id = Locator::min();
|
||||||
|
for fragment in buffer.snapshot.fragments.items(&None) {
|
||||||
|
assert!(fragment.id > prev_fragment_id);
|
||||||
|
prev_fragment_id = fragment.id.clone();
|
||||||
|
|
||||||
|
let insertion_fragment = buffer
|
||||||
|
.snapshot
|
||||||
|
.insertions
|
||||||
|
.get(
|
||||||
|
&InsertionFragmentKey {
|
||||||
|
timestamp: fragment.insertion_timestamp,
|
||||||
|
split_offset: fragment.insertion_offset,
|
||||||
|
},
|
||||||
|
&(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(insertion_fragment.fragment_id, fragment.id);
|
||||||
|
}
|
||||||
|
|
||||||
if rng.gen_bool(0.3) {
|
if rng.gen_bool(0.3) {
|
||||||
buffer_versions.push((buffer.clone(), buffer.subscribe()));
|
buffer_versions.push((buffer.clone(), buffer.subscribe()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -359,7 +359,7 @@ impl Subscription {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct InsertionTimestamp {
|
pub struct InsertionTimestamp {
|
||||||
pub replica_id: ReplicaId,
|
pub replica_id: ReplicaId,
|
||||||
pub local: clock::Seq,
|
pub local: clock::Seq,
|
||||||
|
@ -385,7 +385,8 @@ impl InsertionTimestamp {
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
struct Fragment {
|
struct Fragment {
|
||||||
id: Locator,
|
id: Locator,
|
||||||
timestamp: InsertionTimestamp,
|
insertion_timestamp: InsertionTimestamp,
|
||||||
|
insertion_offset: usize,
|
||||||
len: usize,
|
len: usize,
|
||||||
visible: bool,
|
visible: bool,
|
||||||
deletions: HashSet<clock::Local>,
|
deletions: HashSet<clock::Local>,
|
||||||
|
@ -414,10 +415,10 @@ struct InsertionFragment {
|
||||||
fragment_id: Locator,
|
fragment_id: Locator,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
struct InsertionSummary {
|
struct InsertionFragmentKey {
|
||||||
max_timestamp: InsertionTimestamp,
|
timestamp: InsertionTimestamp,
|
||||||
max_split_offset: usize,
|
split_offset: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
@ -470,34 +471,26 @@ impl Buffer {
|
||||||
let mut version = clock::Global::new();
|
let mut version = clock::Global::new();
|
||||||
let visible_text = Rope::from(history.base_text.as_ref());
|
let visible_text = Rope::from(history.base_text.as_ref());
|
||||||
if visible_text.len() > 0 {
|
if visible_text.len() > 0 {
|
||||||
let timestamp = InsertionTimestamp {
|
let insertion_timestamp = InsertionTimestamp {
|
||||||
replica_id: 0,
|
replica_id: 0,
|
||||||
local: 1,
|
local: 1,
|
||||||
lamport: 1,
|
lamport: 1,
|
||||||
};
|
};
|
||||||
local_clock.observe(timestamp.local());
|
local_clock.observe(insertion_timestamp.local());
|
||||||
lamport_clock.observe(timestamp.lamport());
|
lamport_clock.observe(insertion_timestamp.lamport());
|
||||||
version.observe(timestamp.local());
|
version.observe(insertion_timestamp.local());
|
||||||
let fragment_id = Locator::between(&Locator::min(), &Locator::max());
|
let fragment_id = Locator::between(&Locator::min(), &Locator::max());
|
||||||
fragments.push(
|
let fragment = Fragment {
|
||||||
Fragment {
|
id: fragment_id,
|
||||||
id: fragment_id,
|
insertion_timestamp,
|
||||||
timestamp,
|
insertion_offset: 0,
|
||||||
len: visible_text.len(),
|
len: visible_text.len(),
|
||||||
visible: true,
|
visible: true,
|
||||||
deletions: Default::default(),
|
deletions: Default::default(),
|
||||||
max_undos: Default::default(),
|
max_undos: Default::default(),
|
||||||
},
|
};
|
||||||
&None,
|
insertions.push(InsertionFragment::new(&fragment), &());
|
||||||
);
|
fragments.push(fragment, &None);
|
||||||
insertions.push(
|
|
||||||
InsertionFragment {
|
|
||||||
timestamp,
|
|
||||||
split_offset: 0,
|
|
||||||
fragment_id,
|
|
||||||
},
|
|
||||||
&(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer {
|
Buffer {
|
||||||
|
@ -586,7 +579,7 @@ impl Buffer {
|
||||||
ranges: Vec::with_capacity(ranges.len()),
|
ranges: Vec::with_capacity(ranges.len()),
|
||||||
new_text: None,
|
new_text: None,
|
||||||
};
|
};
|
||||||
let mut insertions = Vec::new();
|
let mut new_insertions = Vec::new();
|
||||||
|
|
||||||
let mut ranges = ranges
|
let mut ranges = ranges
|
||||||
.map(|range| range.start.to_offset(&*self)..range.end.to_offset(&*self))
|
.map(|range| range.start.to_offset(&*self)..range.end.to_offset(&*self))
|
||||||
|
@ -612,6 +605,8 @@ impl Buffer {
|
||||||
if fragment_end > fragment_start {
|
if fragment_end > fragment_start {
|
||||||
let mut suffix = old_fragments.item().unwrap().clone();
|
let mut suffix = old_fragments.item().unwrap().clone();
|
||||||
suffix.len = fragment_end - fragment_start;
|
suffix.len = fragment_end - fragment_start;
|
||||||
|
suffix.insertion_offset += fragment_start - old_fragments.start().visible;
|
||||||
|
new_insertions.push(InsertionFragment::insert_new(&suffix));
|
||||||
new_ropes.push_fragment(&suffix, suffix.visible);
|
new_ropes.push_fragment(&suffix, suffix.visible);
|
||||||
new_fragments.push(suffix, &None);
|
new_fragments.push(suffix, &None);
|
||||||
}
|
}
|
||||||
|
@ -630,6 +625,15 @@ impl Buffer {
|
||||||
if fragment_start < range.start {
|
if fragment_start < range.start {
|
||||||
let mut prefix = old_fragments.item().unwrap().clone();
|
let mut prefix = old_fragments.item().unwrap().clone();
|
||||||
prefix.len = range.start - fragment_start;
|
prefix.len = range.start - fragment_start;
|
||||||
|
prefix.insertion_offset += fragment_start - old_fragments.start().visible;
|
||||||
|
|
||||||
|
// log::info!(
|
||||||
|
// "pushing prefix between {:?} and {:?}",
|
||||||
|
// new_fragments.summary().max_id,
|
||||||
|
// prefix.id
|
||||||
|
// );
|
||||||
|
prefix.id = Locator::between(&new_fragments.summary().max_id, &prefix.id);
|
||||||
|
new_insertions.push(InsertionFragment::insert_new(&prefix));
|
||||||
new_ropes.push_fragment(&prefix, prefix.visible);
|
new_ropes.push_fragment(&prefix, prefix.visible);
|
||||||
new_fragments.push(prefix, &None);
|
new_fragments.push(prefix, &None);
|
||||||
fragment_start = range.start;
|
fragment_start = range.start;
|
||||||
|
@ -642,17 +646,32 @@ impl Buffer {
|
||||||
old: fragment_start..fragment_start,
|
old: fragment_start..fragment_start,
|
||||||
new: new_start..new_start + new_text.len(),
|
new: new_start..new_start + new_text.len(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// log::info!(
|
||||||
|
// "pushing new fragment between {:?} and {:?}",
|
||||||
|
// new_fragments.summary().max_id,
|
||||||
|
// old_fragments
|
||||||
|
// .item()
|
||||||
|
// .map_or(&Locator::max(), |old_fragment| &old_fragment.id)
|
||||||
|
// );
|
||||||
|
|
||||||
|
let fragment = Fragment {
|
||||||
|
id: Locator::between(
|
||||||
|
&new_fragments.summary().max_id,
|
||||||
|
old_fragments
|
||||||
|
.item()
|
||||||
|
.map_or(&Locator::max(), |old_fragment| &old_fragment.id),
|
||||||
|
),
|
||||||
|
insertion_timestamp: timestamp,
|
||||||
|
insertion_offset: 0,
|
||||||
|
len: new_text.len(),
|
||||||
|
deletions: Default::default(),
|
||||||
|
max_undos: Default::default(),
|
||||||
|
visible: true,
|
||||||
|
};
|
||||||
|
new_insertions.push(InsertionFragment::insert_new(&fragment));
|
||||||
new_ropes.push_str(new_text);
|
new_ropes.push_str(new_text);
|
||||||
new_fragments.push(
|
new_fragments.push(fragment, &None);
|
||||||
Fragment {
|
|
||||||
timestamp,
|
|
||||||
len: new_text.len(),
|
|
||||||
deletions: Default::default(),
|
|
||||||
max_undos: Default::default(),
|
|
||||||
visible: true,
|
|
||||||
},
|
|
||||||
&None,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance through every fragment that intersects this range, marking the intersecting
|
// Advance through every fragment that intersects this range, marking the intersecting
|
||||||
|
@ -664,6 +683,8 @@ impl Buffer {
|
||||||
let intersection_end = cmp::min(range.end, fragment_end);
|
let intersection_end = cmp::min(range.end, fragment_end);
|
||||||
if fragment.visible {
|
if fragment.visible {
|
||||||
intersection.len = intersection_end - fragment_start;
|
intersection.len = intersection_end - fragment_start;
|
||||||
|
intersection.id =
|
||||||
|
Locator::between(&new_fragments.summary().max_id, &intersection.id);
|
||||||
intersection.deletions.insert(timestamp.local());
|
intersection.deletions.insert(timestamp.local());
|
||||||
intersection.visible = false;
|
intersection.visible = false;
|
||||||
}
|
}
|
||||||
|
@ -675,6 +696,7 @@ impl Buffer {
|
||||||
new: new_start..new_start,
|
new: new_start..new_start,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
new_insertions.push(InsertionFragment::insert_new(&intersection));
|
||||||
new_ropes.push_fragment(&intersection, fragment.visible);
|
new_ropes.push_fragment(&intersection, fragment.visible);
|
||||||
new_fragments.push(intersection, &None);
|
new_fragments.push(intersection, &None);
|
||||||
fragment_start = intersection_end;
|
fragment_start = intersection_end;
|
||||||
|
@ -695,6 +717,8 @@ impl Buffer {
|
||||||
if fragment_end > fragment_start {
|
if fragment_end > fragment_start {
|
||||||
let mut suffix = old_fragments.item().unwrap().clone();
|
let mut suffix = old_fragments.item().unwrap().clone();
|
||||||
suffix.len = fragment_end - fragment_start;
|
suffix.len = fragment_end - fragment_start;
|
||||||
|
suffix.insertion_offset += fragment_start - old_fragments.start().visible;
|
||||||
|
new_insertions.push(InsertionFragment::insert_new(&suffix));
|
||||||
new_ropes.push_fragment(&suffix, suffix.visible);
|
new_ropes.push_fragment(&suffix, suffix.visible);
|
||||||
new_fragments.push(suffix, &None);
|
new_fragments.push(suffix, &None);
|
||||||
}
|
}
|
||||||
|
@ -708,6 +732,7 @@ impl Buffer {
|
||||||
drop(old_fragments);
|
drop(old_fragments);
|
||||||
|
|
||||||
self.snapshot.fragments = new_fragments;
|
self.snapshot.fragments = new_fragments;
|
||||||
|
self.snapshot.insertions.edit(new_insertions, &());
|
||||||
self.snapshot.visible_text = visible_text;
|
self.snapshot.visible_text = visible_text;
|
||||||
self.snapshot.deleted_text = deleted_text;
|
self.snapshot.deleted_text = deleted_text;
|
||||||
self.update_subscriptions(edits);
|
self.update_subscriptions(edits);
|
||||||
|
@ -865,7 +890,7 @@ impl Buffer {
|
||||||
// timestamp.
|
// timestamp.
|
||||||
while let Some(fragment) = old_fragments.item() {
|
while let Some(fragment) = old_fragments.item() {
|
||||||
if fragment_start == range.start
|
if fragment_start == range.start
|
||||||
&& fragment.timestamp.lamport() > timestamp.lamport()
|
&& fragment.insertion_timestamp.lamport() > timestamp.lamport()
|
||||||
{
|
{
|
||||||
new_ropes.push_fragment(fragment, fragment.visible);
|
new_ropes.push_fragment(fragment, fragment.visible);
|
||||||
new_fragments.push(fragment.clone(), &None);
|
new_fragments.push(fragment.clone(), &None);
|
||||||
|
@ -900,7 +925,9 @@ impl Buffer {
|
||||||
new_ropes.push_str(new_text);
|
new_ropes.push_str(new_text);
|
||||||
new_fragments.push(
|
new_fragments.push(
|
||||||
Fragment {
|
Fragment {
|
||||||
timestamp,
|
id: todo!(),
|
||||||
|
insertion_timestamp: timestamp,
|
||||||
|
insertion_offset: todo!(),
|
||||||
len: new_text.len(),
|
len: new_text.len(),
|
||||||
deletions: Default::default(),
|
deletions: Default::default(),
|
||||||
max_undos: Default::default(),
|
max_undos: Default::default(),
|
||||||
|
@ -1008,7 +1035,9 @@ impl Buffer {
|
||||||
let fragment_was_visible = fragment.visible;
|
let fragment_was_visible = fragment.visible;
|
||||||
|
|
||||||
if fragment.was_visible(&undo.version, &self.undo_map)
|
if fragment.was_visible(&undo.version, &self.undo_map)
|
||||||
|| undo.counts.contains_key(&fragment.timestamp.local())
|
|| undo
|
||||||
|
.counts
|
||||||
|
.contains_key(&fragment.insertion_timestamp.local())
|
||||||
{
|
{
|
||||||
fragment.visible = fragment.is_visible(&self.undo_map);
|
fragment.visible = fragment.is_visible(&self.undo_map);
|
||||||
fragment.max_undos.observe(undo.id);
|
fragment.max_undos.observe(undo.id);
|
||||||
|
@ -2028,13 +2057,13 @@ impl<'a, D: TextDimension<'a> + Ord, F: FnMut(&FragmentSummary) -> bool> Iterato
|
||||||
|
|
||||||
impl Fragment {
|
impl Fragment {
|
||||||
fn is_visible(&self, undos: &UndoMap) -> bool {
|
fn is_visible(&self, undos: &UndoMap) -> bool {
|
||||||
!undos.is_undone(self.timestamp.local())
|
!undos.is_undone(self.insertion_timestamp.local())
|
||||||
&& self.deletions.iter().all(|d| undos.is_undone(*d))
|
&& self.deletions.iter().all(|d| undos.is_undone(*d))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn was_visible(&self, version: &clock::Global, undos: &UndoMap) -> bool {
|
fn was_visible(&self, version: &clock::Global, undos: &UndoMap) -> bool {
|
||||||
(version.observed(self.timestamp.local())
|
(version.observed(self.insertion_timestamp.local())
|
||||||
&& !undos.was_undone(self.timestamp.local(), version))
|
&& !undos.was_undone(self.insertion_timestamp.local(), version))
|
||||||
&& self
|
&& self
|
||||||
.deletions
|
.deletions
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -2047,14 +2076,14 @@ impl sum_tree::Item for Fragment {
|
||||||
|
|
||||||
fn summary(&self) -> Self::Summary {
|
fn summary(&self) -> Self::Summary {
|
||||||
let mut max_version = clock::Global::new();
|
let mut max_version = clock::Global::new();
|
||||||
max_version.observe(self.timestamp.local());
|
max_version.observe(self.insertion_timestamp.local());
|
||||||
for deletion in &self.deletions {
|
for deletion in &self.deletions {
|
||||||
max_version.observe(*deletion);
|
max_version.observe(*deletion);
|
||||||
}
|
}
|
||||||
max_version.join(&self.max_undos);
|
max_version.join(&self.max_undos);
|
||||||
|
|
||||||
let mut min_insertion_version = clock::Global::new();
|
let mut min_insertion_version = clock::Global::new();
|
||||||
min_insertion_version.observe(self.timestamp.local());
|
min_insertion_version.observe(self.insertion_timestamp.local());
|
||||||
let max_insertion_version = min_insertion_version.clone();
|
let max_insertion_version = min_insertion_version.clone();
|
||||||
if self.visible {
|
if self.visible {
|
||||||
FragmentSummary {
|
FragmentSummary {
|
||||||
|
@ -2086,6 +2115,7 @@ impl sum_tree::Summary for FragmentSummary {
|
||||||
type Context = Option<clock::Global>;
|
type Context = Option<clock::Global>;
|
||||||
|
|
||||||
fn add_summary(&mut self, other: &Self, _: &Self::Context) {
|
fn add_summary(&mut self, other: &Self, _: &Self::Context) {
|
||||||
|
self.max_id = other.max_id.clone();
|
||||||
self.text.visible += &other.text.visible;
|
self.text.visible += &other.text.visible;
|
||||||
self.text.deleted += &other.text.deleted;
|
self.text.deleted += &other.text.deleted;
|
||||||
self.max_version.join(&other.max_version);
|
self.max_version.join(&other.max_version);
|
||||||
|
@ -2116,22 +2146,43 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentTextSummary {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl sum_tree::Item for InsertionFragment {
|
impl sum_tree::Item for InsertionFragment {
|
||||||
type Summary = InsertionSummary;
|
type Summary = InsertionFragmentKey;
|
||||||
|
|
||||||
fn summary(&self) -> Self::Summary {
|
fn summary(&self) -> Self::Summary {
|
||||||
InsertionSummary {
|
InsertionFragmentKey {
|
||||||
max_timestamp: self.timestamp,
|
timestamp: self.timestamp,
|
||||||
max_split_offset: self.split_offset,
|
split_offset: self.split_offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl sum_tree::Summary for InsertionSummary {
|
impl sum_tree::KeyedItem for InsertionFragment {
|
||||||
|
type Key = InsertionFragmentKey;
|
||||||
|
|
||||||
|
fn key(&self) -> Self::Key {
|
||||||
|
sum_tree::Item::summary(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InsertionFragment {
|
||||||
|
fn new(fragment: &Fragment) -> Self {
|
||||||
|
Self {
|
||||||
|
timestamp: fragment.insertion_timestamp,
|
||||||
|
split_offset: fragment.insertion_offset,
|
||||||
|
fragment_id: fragment.id.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_new(fragment: &Fragment) -> sum_tree::Edit<Self> {
|
||||||
|
sum_tree::Edit::Insert(Self::new(fragment))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl sum_tree::Summary for InsertionFragmentKey {
|
||||||
type Context = ();
|
type Context = ();
|
||||||
|
|
||||||
fn add_summary(&mut self, summary: &Self, cx: &()) {
|
fn add_summary(&mut self, summary: &Self, _: &()) {
|
||||||
self.max_timestamp = summary.max_timestamp;
|
*self = *summary;
|
||||||
self.max_split_offset = summary.max_split_offset;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue