Mercurial > hg
changeset 51188:1ef4a36a934d
rust-index: add an abstraction to support bytes added at runtimes
In order to support appending data to the Rust index, we need to abstract
data access away from the immutable (on-disk) bytes, to seemlessly fetch
either from the preexisting data or from the newly added data.
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Mon, 26 Jun 2023 19:16:07 +0200 |
parents | 8c4e8d06432e |
children | b4d152a28742 |
files | rust/hg-core/src/revlog/index.rs |
diffstat | 1 files changed, 44 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/hg-core/src/revlog/index.rs Thu Jun 29 16:09:57 2023 +0200 +++ b/rust/hg-core/src/revlog/index.rs Mon Jun 26 19:16:07 2023 +0200 @@ -79,9 +79,50 @@ } } +/// Abstracts the access to the index bytes since they can be spread between +/// the immutable (bytes) part and the mutable (added) part if any appends +/// happened. This makes it transparent for the callers. +struct IndexData { + /// Immutable bytes, most likely taken from disk + bytes: Box<dyn Deref<Target = [u8]> + Send>, + /// Bytes that were added after reading the index + added: Vec<u8>, +} + +impl IndexData { + pub fn new(bytes: Box<dyn Deref<Target = [u8]> + Send>) -> Self { + Self { + bytes, + added: vec![], + } + } + + pub fn len(&self) -> usize { + self.bytes.len() + self.added.len() + } +} + +impl std::ops::Index<std::ops::Range<usize>> for IndexData { + type Output = [u8]; + + fn index(&self, index: std::ops::Range<usize>) -> &Self::Output { + let start = index.start; + let end = index.end; + let immutable_len = self.bytes.len(); + if start < immutable_len { + if end > immutable_len { + panic!("index data cannot span existing and added ranges"); + } + &self.bytes[index] + } else { + &self.added[start - immutable_len..end - immutable_len] + } + } +} + /// A Revlog index pub struct Index { - bytes: Box<dyn Deref<Target = [u8]> + Send>, + bytes: IndexData, /// Offsets of starts of index blocks. /// Only needed when the index is interleaved with data. offsets: Option<Vec<usize>>, @@ -150,7 +191,7 @@ if offset == bytes.len() { Ok(Self { - bytes, + bytes: IndexData::new(bytes), offsets: Some(offsets), uses_generaldelta, }) @@ -159,7 +200,7 @@ } } else { Ok(Self { - bytes, + bytes: IndexData::new(bytes), offsets: None, uses_generaldelta, })