use std::ops::Range;
use crate::file::Index;
use crate::Id;
use gix_error::bstr::ByteSlice;
use gix_error::{message, Message};
pub struct Entry {
pub kind: Id,
pub offset: Range<crate::file::Offset>,
}
impl Index {
pub const ENTRY_SIZE: usize = std::mem::size_of::<u32>() + std::mem::size_of::<u64>();
pub const EMPTY_SIZE: usize = Index::ENTRY_SIZE;
pub const fn size_for_entries(num_entries: usize) -> usize {
Self::ENTRY_SIZE * (num_entries + 1)
}
pub fn offset_by_id(&self, kind: Id) -> Result<Range<crate::file::Offset>, Message> {
self.chunks
.iter()
.find_map(|c| (c.kind == kind).then(|| c.offset.clone()))
.ok_or_else(make_message(kind))
}
pub fn usize_offset_by_id(&self, kind: Id) -> Result<Range<usize>, Message> {
self.chunks
.iter()
.find_map(|c| (c.kind == kind).then(|| crate::range::into_usize_or_panic(c.offset.clone())))
.ok_or_else(make_message(kind))
}
pub fn validated_usize_offset_by_id<T>(
&self,
kind: Id,
validate: impl FnOnce(Range<usize>) -> T,
) -> Result<T, Message> {
self.chunks
.iter()
.find_map(|c| (c.kind == kind).then(|| crate::range::into_usize_or_panic(c.offset.clone())))
.map(validate)
.ok_or_else(make_message(kind))
}
pub fn data_by_id<'a>(&self, data: &'a [u8], kind: Id) -> Result<&'a [u8], Message> {
let offset = self.offset_by_id(kind)?;
Ok(&data[crate::range::into_usize(offset)
.ok_or_else(|| message("The offsets into the file couldn't be represented by usize"))?])
}
pub fn highest_offset(&self) -> crate::file::Offset {
self.chunks.last().expect("at least one chunk").offset.end
}
}
fn make_message(kind: Id) -> impl FnOnce() -> Message {
move || message!("Chunk named '{}' was not found in chunk file index", kind.as_bstr())
}