1+ use gix_error:: bstr:: ByteSlice ;
2+ use gix_error:: ParseError ;
13use std:: ops:: Range ;
24
3- mod error {
4- /// The value returned by [`crate::file::Index::from_bytes()`]
5- #[ derive( Debug , thiserror:: Error ) ]
6- #[ allow( missing_docs) ]
7- pub enum Error {
8- #[ error( "Sentinel value encountered while still processing chunks." ) ]
9- EarlySentinelValue ,
10- #[ error( "Sentinel value wasn't found, saw {:?}" , std:: str :: from_utf8( actual. as_ref( ) ) . unwrap_or( "<non-ascii>" ) ) ]
11- MissingSentinelValue { actual : crate :: Id } ,
12- #[ error( "The chunk offset {offset} went past the file of length {file_length} - was it truncated?" ) ]
13- ChunkSizeOutOfBounds {
14- offset : crate :: file:: Offset ,
15- file_length : u64 ,
16- } ,
17- #[ error( "All chunk offsets must be incrementing." ) ]
18- NonIncrementalChunkOffsets ,
19- #[ error( "The chunk of kind {:?} was encountered more than once" , std:: str :: from_utf8( kind. as_ref( ) ) . unwrap_or( "<non-ascii>" ) ) ]
20- DuplicateChunk { kind : crate :: Id } ,
21- #[ error( "The table of contents would be {expected} bytes, but got only {actual}" ) ]
22- TocTooSmall { actual : usize , expected : usize } ,
23- #[ error( "Empty chunk indices are not allowed as the point of chunked files is to have chunks." ) ]
24- Empty ,
25- }
26- }
27- pub use error:: Error ;
28-
295use crate :: { file, file:: index} ;
306
317impl file:: Index {
328 /// Provided a mapped file at the beginning via `data`, starting at `toc_offset` decode all chunk information to return
339 /// an index with `num_chunks` chunks.
34- pub fn from_bytes ( data : & [ u8 ] , toc_offset : usize , num_chunks : u32 ) -> Result < Self , Error > {
10+ pub fn from_bytes ( data : & [ u8 ] , toc_offset : usize , num_chunks : u32 ) -> Result < Self , ParseError > {
3511 if num_chunks == 0 {
36- return Err ( Error :: Empty ) ;
12+ return Err ( ParseError :: new (
13+ "Empty chunk indices are not allowed as the point of chunked files is to have chunks." ,
14+ ) ) ;
3715 }
3816
3917 let data_len: u64 = data. len ( ) as u64 ;
4018 let mut chunks = Vec :: with_capacity ( num_chunks as usize ) ;
4119 let mut toc_entry = & data[ toc_offset..] ;
4220 let expected_min_size = ( num_chunks as usize + 1 ) * file:: Index :: ENTRY_SIZE ;
4321 if toc_entry. len ( ) < expected_min_size {
44- return Err ( Error :: TocTooSmall {
45- expected : expected_min_size,
46- actual : toc_entry. len ( ) ,
47- } ) ;
22+ return Err ( format ! (
23+ "The table of contents would be { expected_min_size} bytes, but got only {toc_entry_len}" ,
24+ toc_entry_len = toc_entry. len( )
25+ ) ) ? ;
4826 }
4927
50- for _ in 0 ..num_chunks {
28+ for chunk_idx in 0 ..num_chunks {
5129 let ( kind, offset) = toc_entry. split_at ( 4 ) ;
5230 let kind = to_kind ( kind) ;
5331 if kind == crate :: SENTINEL {
54- return Err ( Error :: EarlySentinelValue ) ;
32+ return Err ( format ! (
33+ "Sentinel value encountered while processing chunks {chunk_idx} of {num_chunks}"
34+ ) ) ?;
5535 }
5636 if chunks. iter ( ) . any ( |c : & index:: Entry | c. kind == kind) {
57- return Err ( Error :: DuplicateChunk { kind } ) ;
37+ return Err ( format ! (
38+ "The chunk of kind '{}' was encountered more than once" ,
39+ kind. as_bstr( )
40+ ) ) ?;
5841 }
5942
6043 let offset = be_u64 ( offset) ;
6144 if offset > data_len {
62- return Err ( Error :: ChunkSizeOutOfBounds {
63- offset,
64- file_length : data_len,
65- } ) ;
45+ return Err ( format ! (
46+ "The chunk offset {offset} went past the file of length {data_len} - was it truncated?" ,
47+ ) ) ?;
6648 }
6749 toc_entry = & toc_entry[ file:: Index :: ENTRY_SIZE ..] ;
6850 let next_offset = be_u64 ( & toc_entry[ 4 ..] ) ;
6951 if next_offset > data_len {
70- return Err ( Error :: ChunkSizeOutOfBounds {
71- offset : next_offset,
72- file_length : data_len,
73- } ) ;
52+ return Err ( format ! (
53+ "The chunk offset {next_offset} went past the file of length {data_len} - was it truncated?"
54+ ) ) ?;
7455 }
7556 if next_offset <= offset {
76- return Err ( Error :: NonIncrementalChunkOffsets ) ;
57+ return Err ( "All chunk offsets must be incrementing." ) ? ;
7758 }
7859 chunks. push ( index:: Entry {
7960 kind,
@@ -86,7 +67,7 @@ impl file::Index {
8667
8768 let sentinel = to_kind ( & toc_entry[ ..4 ] ) ;
8869 if sentinel != crate :: SENTINEL {
89- return Err ( Error :: MissingSentinelValue { actual : sentinel } ) ;
70+ return Err ( format ! ( "Sentinel value wasn't found, saw '{}'" , sentinel . as_bstr ( ) ) ) ? ;
9071 }
9172
9273 Ok ( file:: Index {
0 commit comments