1
1
use std:: sync:: Arc ;
2
2
3
- const MAX_INLINE : usize = 39 ;
3
+ const MAX_INLINE : usize = 38 ;
4
4
5
5
#[ derive( Clone ) ]
6
6
pub enum Storage {
7
- /// hash is stored inline. if it is smaller than 39 bytes it should be padded with 0u8
8
- Inline ( [ u8 ; MAX_INLINE ] ) ,
7
+ /// hash is stored inline if it is smaller than MAX_INLINE
8
+ Inline ( u8 , [ u8 ; MAX_INLINE ] ) ,
9
9
/// hash is stored on the heap. this must be only used if the hash is actually larger than
10
- /// 39 bytes to ensure an unique representation.
10
+ /// MAX_INLINE bytes to ensure an unique representation.
11
11
Heap ( Arc < [ u8 ] > ) ,
12
12
}
13
13
14
14
impl Storage {
15
- /// The raw bytes. Note that this can be longer than the data this storage has been created from.
15
+ /// The raw bytes.
16
16
pub fn bytes ( & self ) -> & [ u8 ] {
17
17
match self {
18
- Storage :: Inline ( bytes) => bytes,
18
+ Storage :: Inline ( len , bytes) => & bytes[ .. ( * len as usize ) ] ,
19
19
Storage :: Heap ( data) => & data,
20
20
}
21
21
}
22
22
23
- /// creates storage from a vec. Note that this will not preserve the size .
23
+ /// creates storage from a vec. For a size up to MAX_INLINE, this will not allocate .
24
24
pub fn from_slice ( slice : & [ u8 ] ) -> Self {
25
- if slice. len ( ) <= MAX_INLINE {
25
+ let len = slice. len ( ) ;
26
+ if len <= MAX_INLINE {
26
27
let mut data: [ u8 ; MAX_INLINE ] = [ 0 ; MAX_INLINE ] ;
27
- data[ ..slice . len ( ) ] . copy_from_slice ( slice) ;
28
- Storage :: Inline ( data)
28
+ data[ ..len] . copy_from_slice ( slice) ;
29
+ Storage :: Inline ( len as u8 , data)
29
30
} else {
30
31
Storage :: Heap ( slice. into ( ) )
31
32
}
@@ -34,10 +35,21 @@ impl Storage {
34
35
35
36
#[ cfg( test) ]
36
37
mod tests {
37
- use super :: Storage ;
38
+ use super :: { Storage , MAX_INLINE } ;
38
39
39
40
#[ test]
40
- fn test_size ( ) {
41
+ fn struct_size ( ) {
42
+ // this should be true for both 32 and 64 bit archs
41
43
assert_eq ! ( std:: mem:: size_of:: <Storage >( ) , 40 ) ;
42
44
}
45
+
46
+ #[ test]
47
+ fn roundtrip ( ) {
48
+ // check that .bytes() returns whatever the storage was created with
49
+ for i in 0 ..( ( MAX_INLINE + 10 ) as u8 ) {
50
+ let data = ( 0 ..i) . collect :: < Vec < u8 > > ( ) ;
51
+ let storage = Storage :: from_slice ( & data) ;
52
+ assert_eq ! ( data, storage. bytes( ) ) ;
53
+ }
54
+ }
43
55
}
0 commit comments