@@ -27,6 +27,30 @@ struct ReadCacheInternal<R: Read + Seek> {
27
27
read : R ,
28
28
bufs : HashMap < ( u64 , u64 ) , Box < [ u8 ] > > ,
29
29
strings : HashMap < ( u64 , u8 ) , Box < [ u8 ] > > ,
30
+ len : Option < u64 > ,
31
+ }
32
+
33
+ impl < R : Read + Seek > ReadCacheInternal < R > {
34
+ /// Ensures this range is contained in the len of the file
35
+ fn range_in_bounds ( & mut self , range : & Range < u64 > ) -> Result < ( ) , ( ) > {
36
+ if range. start <= range. end && range. end <= self . len ( ) ? {
37
+ Ok ( ( ) )
38
+ } else {
39
+ Err ( ( ) )
40
+ }
41
+ }
42
+
43
+ /// The length of the underlying read, memoized
44
+ fn len ( & mut self ) -> Result < u64 , ( ) > {
45
+ match self . len {
46
+ Some ( len) => Ok ( len) ,
47
+ None => {
48
+ let len = self . read . seek ( SeekFrom :: End ( 0 ) ) . map_err ( |_| ( ) ) ?;
49
+ self . len = Some ( len) ;
50
+ Ok ( len)
51
+ }
52
+ }
53
+ }
30
54
}
31
55
32
56
impl < R : Read + Seek > ReadCache < R > {
@@ -37,6 +61,7 @@ impl<R: Read + Seek> ReadCache<R> {
37
61
read,
38
62
bufs : HashMap :: new ( ) ,
39
63
strings : HashMap :: new ( ) ,
64
+ len : None ,
40
65
} ) ,
41
66
}
42
67
}
@@ -64,15 +89,15 @@ impl<R: Read + Seek> ReadCache<R> {
64
89
65
90
impl < ' a , R : Read + Seek > ReadRef < ' a > for & ' a ReadCache < R > {
66
91
fn len ( self ) -> Result < u64 , ( ) > {
67
- let cache = & mut * self . cache . borrow_mut ( ) ;
68
- cache. read . seek ( SeekFrom :: End ( 0 ) ) . map_err ( |_| ( ) )
92
+ self . cache . borrow_mut ( ) . len ( )
69
93
}
70
94
71
95
fn read_bytes_at ( self , offset : u64 , size : u64 ) -> Result < & ' a [ u8 ] , ( ) > {
72
96
if size == 0 {
73
97
return Ok ( & [ ] ) ;
74
98
}
75
99
let cache = & mut * self . cache . borrow_mut ( ) ;
100
+ cache. range_in_bounds ( & ( offset..( offset. saturating_add ( size) ) ) ) ?;
76
101
let buf = match cache. bufs . entry ( ( offset, size) ) {
77
102
Entry :: Occupied ( entry) => entry. into_mut ( ) ,
78
103
Entry :: Vacant ( entry) => {
@@ -90,6 +115,7 @@ impl<'a, R: Read + Seek> ReadRef<'a> for &'a ReadCache<R> {
90
115
91
116
fn read_bytes_at_until ( self , range : Range < u64 > , delimiter : u8 ) -> Result < & ' a [ u8 ] , ( ) > {
92
117
let cache = & mut * self . cache . borrow_mut ( ) ;
118
+ cache. range_in_bounds ( & range) ?;
93
119
let buf = match cache. strings . entry ( ( range. start , delimiter) ) {
94
120
Entry :: Occupied ( entry) => entry. into_mut ( ) ,
95
121
Entry :: Vacant ( entry) => {
0 commit comments