Mercurial > hg
diff rust/hg-core/src/revlog/index.rs @ 45601:900b9b79b99c
hg-core: make `Index` owner of its bytes (D8958#inline-14994 followup 1/2)
Prevent building `Index` every time it is needed. It was a bad idea anyway.
When `Index::new` will return `Result` it will avoid things like `Revlog::len`
returning `Result<usize>` instead of `usize`.
[X] make `Index` owner of its bytes
[ ] make `Index::new` return an error if `offset != bytes.len()`
Differential Revision: https://phab.mercurial-scm.org/D9106
author | Antoine cezar<acezar@chwitlabs.fr> |
---|---|
date | Mon, 28 Sep 2020 15:13:51 +0200 |
parents | da30e4b553c3 |
children | 1cef583541c0 |
line wrap: on
line diff
--- a/rust/hg-core/src/revlog/index.rs Mon Sep 28 14:33:52 2020 +0200 +++ b/rust/hg-core/src/revlog/index.rs Mon Sep 28 15:13:51 2020 +0200 @@ -1,3 +1,5 @@ +use std::ops::Deref; + use byteorder::{BigEndian, ByteOrder}; use crate::revlog::{Revision, NULL_REVISION}; @@ -5,19 +7,18 @@ pub const INDEX_ENTRY_SIZE: usize = 64; /// A Revlog index -#[derive(Debug)] -pub struct Index<'a> { - bytes: &'a [u8], +pub struct Index { + bytes: Box<dyn Deref<Target = [u8]> + Send>, /// Offsets of starts of index blocks. /// Only needed when the index is interleaved with data. offsets: Option<Vec<usize>>, } -impl<'a> Index<'a> { +impl Index { /// Create an index from bytes. /// Calculate the start of each entry when is_inline is true. - pub fn new(bytes: &'a [u8], is_inline: bool) -> Self { - if is_inline { + pub fn new(bytes: Box<dyn Deref<Target = [u8]> + Send>) -> Self { + if is_inline(&bytes) { let mut offset: usize = 0; let mut offsets = Vec::new(); @@ -44,6 +45,19 @@ } } + /// Value of the inline flag. + pub fn is_inline(&self) -> bool { + is_inline(&self.bytes) + } + + /// Return a slice of bytes if `revlog` is inline. Panic if not. + pub fn data(&self, start: usize, end: usize) -> &[u8] { + if !self.is_inline() { + panic!("tried to access data in the index of a revlog that is not inline"); + } + &self.bytes[start..end] + } + /// Return number of entries of the revlog index. pub fn len(&self) -> usize { if let Some(offsets) = &self.offsets { @@ -172,6 +186,14 @@ } } +/// Value of the inline flag. +pub fn is_inline(index_bytes: &[u8]) -> bool { + match &index_bytes[0..=1] { + [0, 0] | [0, 2] => false, + _ => true, + } +} + #[cfg(test)] mod tests { use super::*; @@ -269,6 +291,39 @@ } #[test] + fn is_not_inline_when_no_inline_flag_test() { + let bytes = IndexEntryBuilder::new() + .is_first(true) + .with_general_delta(false) + .with_inline(false) + .build(); + + assert_eq!(is_inline(&bytes), false) + } + + #[test] + fn is_inline_when_inline_flag_test() { + let bytes = IndexEntryBuilder::new() + .is_first(true) + .with_general_delta(false) + .with_inline(true) + .build(); + + assert_eq!(is_inline(&bytes), true) + } + + #[test] + fn is_inline_when_inline_and_generaldelta_flags_test() { + let bytes = IndexEntryBuilder::new() + .is_first(true) + .with_general_delta(true) + .with_inline(true) + .build(); + + assert_eq!(is_inline(&bytes), true) + } + + #[test] fn test_offset() { let bytes = IndexEntryBuilder::new().with_offset(1).build(); let entry = IndexEntry {