1616//! - [tile_test.go](https://cs.opensource.google/go/x/mod/+/refs/tags/v0.21.0:sumdb/tlog/tile_test.go)
1717
1818use crate :: tlog:: {
19- node_hash, split_stored_hash_index, stored_hash_index, sub_tree_index, Error , Hash , HashReader ,
20- HASH_SIZE ,
19+ node_hash, split_stored_hash_index, stored_hash_index, sub_tree_index, Hash , HashReader ,
20+ TlogError , HASH_SIZE ,
2121} ;
2222use std:: collections:: HashMap ;
23+ use std:: fmt;
2324use std:: str:: FromStr ;
2425
2526// To limit the size of any particular directory listing, we encode the (possibly very large)
@@ -49,11 +50,32 @@ const PATH_BASE: u64 = 1000;
4950/// <https://research.swtch.com/tlog#tiling_a_log>.
5051#[ derive( Debug , Eq , Hash , PartialEq , Default , Clone , Copy ) ]
5152pub struct Tile {
52- h : u8 , // height of tile (1 ≤ H ≤ 30)
53- l : u8 , // level in tiling (0 ≤ L ≤ 63)
54- n : u64 , // number within level (0 ≤ N, unbounded)
55- w : u32 , // width of tile (1 ≤ W ≤ 2**H; 2**H is complete tile)
56- data_path_opt : Option < & ' static str > , // whether or not this is a data tile, and the data path element to use for encoding
53+ h : u8 , // height of tile (1 ≤ H ≤ 30)
54+ l : u8 , // level in tiling (0 ≤ L ≤ 63)
55+ n : u64 , // number within level (0 ≤ N, unbounded)
56+ w : u32 , // width of tile (1 ≤ W ≤ 2**H; 2**H is complete tile)
57+ data_path_opt : Option < PathElem > , // whether or not this is a data tile, and the data path element to use for encoding
58+ }
59+
60+ #[ derive( Debug , Eq , Hash , PartialEq , Clone , Copy ) ]
61+ pub enum PathElem {
62+ Data ,
63+ Entries ,
64+ Custom ( & ' static str ) ,
65+ }
66+
67+ impl fmt:: Display for PathElem {
68+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
69+ write ! (
70+ f,
71+ "{}" ,
72+ match self {
73+ Self :: Data => "data" ,
74+ Self :: Entries => "entries" ,
75+ Self :: Custom ( p) => p,
76+ }
77+ )
78+ }
5779}
5880
5981impl Tile {
@@ -62,7 +84,7 @@ impl Tile {
6284 /// # Panics
6385 ///
6486 /// Panics if any of the tile parameters are outside the valid ranges.
65- pub fn new ( h : u8 , l : u8 , n : u64 , w : u32 , data_path_opt : Option < & ' static str > ) -> Self {
87+ pub fn new ( h : u8 , l : u8 , n : u64 , w : u32 , data_path_opt : Option < PathElem > ) -> Self {
6688 assert ! (
6789 ( 1 ..=30 ) . contains( & h) && l < 64 && ( 1 ..=( 1 << h) ) . contains( & w) ,
6890 "invalid tile"
@@ -102,9 +124,8 @@ impl Tile {
102124 }
103125
104126 /// Sets `data_path_opt` to convert the tile to a data tile, where `path`
105- /// determines the path element to use when encoding the tile path
106- /// (typically "entries" or "data").
107- pub fn set_data_with_path ( & mut self , path : & ' static str ) {
127+ /// determines the path element to use when encoding the tile path.
128+ pub fn set_data_with_path ( & mut self , path : PathElem ) {
108129 self . data_path_opt = Some ( path) ;
109130 }
110131
@@ -169,14 +190,14 @@ impl Tile {
169190 ///
170191 /// Returns an error if `t` is not `Tile::from_index_internal(t.H,
171192 /// index)` or a wider version, or `data` is not `t`'s tile data (of length at least `t.W*HASH_SIZE`).
172- pub fn hash_at_index ( & self , data : & [ u8 ] , index : u64 ) -> Result < Hash , Error > {
193+ pub fn hash_at_index ( & self , data : & [ u8 ] , index : u64 ) -> Result < Hash , TlogError > {
173194 if self . data_path_opt . is_some ( ) || data. len ( ) < self . w as usize * HASH_SIZE {
174- return Err ( Error :: InvalidTile ) ;
195+ return Err ( TlogError :: InvalidTile ) ;
175196 }
176197
177198 let ( t1, start, end) = Tile :: from_index_internal ( self . h , index) ;
178199 if self . l != t1. l || self . n != t1. n || self . w < t1. w {
179- return Err ( Error :: InvalidTile ) ;
200+ return Err ( TlogError :: InvalidTile ) ;
180201 }
181202
182203 Ok ( Tile :: subtree_hash ( & data[ start..end] ) )
@@ -206,7 +227,7 @@ impl Tile {
206227 & format ! ( ".p/{}" , self . w)
207228 } ;
208229 let l_str = if let Some ( elem) = self . data_path_opt {
209- elem
230+ & elem. to_string ( )
210231 } else {
211232 & format ! ( "{}" , self . l)
212233 } ;
@@ -259,7 +280,7 @@ impl Tile {
259280
260281 let h = u8:: from_str ( components[ 1 ] ) . map_err ( |_| BadPathError ( path. into ( ) ) ) ?;
261282 let ( l, data_path_opt) = if components[ 2 ] == "data" {
262- ( 0 , Some ( "data" ) )
283+ ( 0 , Some ( PathElem :: Data ) )
263284 } else {
264285 (
265286 u8:: from_str ( components[ 2 ] ) . map_err ( |_| BadPathError ( path. into ( ) ) ) ?,
@@ -322,7 +343,7 @@ impl Tile {
322343 /// # Panics
323344 ///
324345 /// Panics if `read_hashes` does not return the same number of hashes as passed-in indexes.
325- pub fn read_data < R : HashReader > ( & self , r : & R ) -> Result < Vec < u8 > , Error > {
346+ pub fn read_data < R : HashReader > ( & self , r : & R ) -> Result < Vec < u8 > , TlogError > {
326347 let mut size = self . w as usize ;
327348 if size == 0 {
328349 size = 1 << self . h ;
@@ -398,7 +419,7 @@ impl TlogTile {
398419 /// # Panics
399420 ///
400421 /// Panics if any of the tile parameters are outside the valid ranges.
401- pub fn new ( l : u8 , n : u64 , w : u32 , data_elem : Option < & ' static str > ) -> Self {
422+ pub fn new ( l : u8 , n : u64 , w : u32 , data_elem : Option < PathElem > ) -> Self {
402423 TlogTile ( Tile :: new ( Self :: HEIGHT , l, n, w, data_elem) )
403424 }
404425
@@ -439,8 +460,8 @@ impl TlogTile {
439460#[ derive( Debug ) ]
440461pub struct BadPathError ( String ) ;
441462
442- impl std :: fmt:: Display for BadPathError {
443- fn fmt ( & self , f : & mut std :: fmt:: Formatter < ' _ > ) -> std :: fmt:: Result {
463+ impl fmt:: Display for BadPathError {
464+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
444465 write ! ( f, "malformed tile path: {}" , self . 0 )
445466 }
446467}
@@ -465,7 +486,7 @@ pub trait TileReader {
465486 /// # Errors
466487 ///
467488 /// Returns an error if unable to read all of the requested tiles.
468- fn read_tiles ( & self , tiles : & [ Tile ] ) -> Result < Vec < Vec < u8 > > , Error > ;
489+ fn read_tiles ( & self , tiles : & [ Tile ] ) -> Result < Vec < Vec < u8 > > , TlogError > ;
469490
470491 /// Informs the [`TileReader`] that the tile data returned by [`TileReader::read_tiles`] has been
471492 /// confirmed as valid and can be saved in persistent storage (on disk).
@@ -507,7 +528,7 @@ impl HashReader for TileHashReader<'_> {
507528 ///
508529 /// Panics if any calls to `Tile::parent` fail to find a parent tile. This differs from the Go
509530 /// implementation which returns an empty Tile{} when it fails to find a parent.
510- fn read_hashes ( & self , indexes : & [ u64 ] ) -> Result < Vec < Hash > , Error > {
531+ fn read_hashes ( & self , indexes : & [ u64 ] ) -> Result < Vec < Hash > , TlogError > {
511532 let h = self . tr . height ( ) ;
512533
513534 let mut tile_order = HashMap :: new ( ) ; // tile_order[tileKey(tiles[i])] = i
@@ -536,7 +557,7 @@ impl HashReader for TileHashReader<'_> {
536557 let mut index_tile_order = vec ! [ 0 ; indexes. len( ) ] ;
537558 for ( i, & x) in indexes. iter ( ) . enumerate ( ) {
538559 if x >= stored_hash_index ( 0 , self . tree_size ) {
539- return Err ( Error :: IndexesNotInTree ) ;
560+ return Err ( TlogError :: IndexesNotInTree ) ;
540561 }
541562
542563 let tile = Tile :: from_index ( h, x) ;
@@ -564,7 +585,7 @@ impl HashReader for TileHashReader<'_> {
564585 if p. w != ( 1 << p. h ) {
565586 // Only full tiles have parents.
566587 // This tile has a parent, so it must be full.
567- return Err ( Error :: BadMath ) ;
588+ return Err ( TlogError :: BadMath ) ;
568589 }
569590 tile_order. insert ( p, tiles. len ( ) ) ;
570591 if k == 0 {
@@ -577,11 +598,11 @@ impl HashReader for TileHashReader<'_> {
577598 // Fetch all the tile data.
578599 let data = self . tr . read_tiles ( & tiles) ?;
579600 if data. len ( ) != tiles. len ( ) {
580- return Err ( Error :: BadMath ) ;
601+ return Err ( TlogError :: BadMath ) ;
581602 }
582603 for ( i, tile) in tiles. iter ( ) . enumerate ( ) {
583604 if data[ i] . len ( ) != tile. w as usize * HASH_SIZE {
584- return Err ( Error :: BadMath ) ;
605+ return Err ( TlogError :: BadMath ) ;
585606 }
586607 }
587608
@@ -595,19 +616,19 @@ impl HashReader for TileHashReader<'_> {
595616 th = node_hash ( h, th) ;
596617 }
597618 if th != self . tree_hash {
598- return Err ( Error :: InconsistentTile ) ;
619+ return Err ( TlogError :: InconsistentTile ) ;
599620 }
600621
601622 // Authenticate full tiles against their parents.
602623 for i in stx. len ( ) ..tiles. len ( ) {
603624 let tile = tiles[ i] ;
604625 let p = tile. parent ( 1 , self . tree_size ) . unwrap ( ) ;
605626 let Some ( j) = tile_order. get ( & p) else {
606- return Err ( Error :: BadMath ) ;
627+ return Err ( TlogError :: BadMath ) ;
607628 } ;
608629 let h = p. hash_at_index ( & data[ * j] , stored_hash_index ( p. l * p. h , tile. n ) ) ?;
609630 if h != Tile :: subtree_hash ( & data[ i] ) {
610- return Err ( Error :: InconsistentTile ) ;
631+ return Err ( TlogError :: InconsistentTile ) ;
611632 }
612633 }
613634
0 commit comments