@@ -159,7 +159,7 @@ impl Client {
159
159
/// Read offset + len from a single blob.
160
160
///
161
161
/// If `len` is `None` it will read the full blob.
162
- pub async fn read_at ( & self , hash : Hash , offset : u64 , len : Option < usize > ) -> Result < Reader > {
162
+ pub async fn read_at ( & self , hash : Hash , offset : u64 , len : ReadAtLen ) -> Result < Reader > {
163
163
Reader :: from_rpc_read_at ( & self . rpc , hash, offset, len) . await
164
164
}
165
165
@@ -178,12 +178,7 @@ impl Client {
178
178
/// Read all bytes of single blob at `offset` for length `len`.
179
179
///
180
180
/// This allocates a buffer for the full length.
181
- pub async fn read_at_to_bytes (
182
- & self ,
183
- hash : Hash ,
184
- offset : u64 ,
185
- len : Option < usize > ,
186
- ) -> Result < Bytes > {
181
+ pub async fn read_at_to_bytes ( & self , hash : Hash , offset : u64 , len : ReadAtLen ) -> Result < Bytes > {
187
182
Reader :: from_rpc_read_at ( & self . rpc , hash, offset, len)
188
183
. await ?
189
184
. read_to_bytes ( )
@@ -484,6 +479,28 @@ impl SimpleStore for Client {
484
479
}
485
480
}
486
481
482
+ /// Defines the way to read bytes.
483
+ #[ derive( Debug , Serialize , Deserialize , Default , Clone , Copy ) ]
484
+ pub enum ReadAtLen {
485
+ /// Reads all available bytes.
486
+ #[ default]
487
+ All ,
488
+ /// Reads exactly this many bytes, erroring out on larger or smaller.
489
+ Exact ( u64 ) ,
490
+ /// Reads at most this many bytes.
491
+ AtMost ( u64 ) ,
492
+ }
493
+
494
+ impl ReadAtLen {
495
+ pub ( crate ) fn as_result_len ( & self , size_remaining : u64 ) -> u64 {
496
+ match self {
497
+ ReadAtLen :: All => size_remaining,
498
+ ReadAtLen :: Exact ( len) => * len,
499
+ ReadAtLen :: AtMost ( len) => std:: cmp:: min ( * len, size_remaining) ,
500
+ }
501
+ }
502
+ }
503
+
487
504
/// Whether to wrap the added data in a collection.
488
505
#[ derive( Debug , Serialize , Deserialize , Default , Clone ) ]
489
506
pub enum WrapOption {
@@ -872,14 +889,14 @@ impl Reader {
872
889
}
873
890
874
891
pub ( crate ) async fn from_rpc_read ( rpc : & RpcClient , hash : Hash ) -> anyhow:: Result < Self > {
875
- Self :: from_rpc_read_at ( rpc, hash, 0 , None ) . await
892
+ Self :: from_rpc_read_at ( rpc, hash, 0 , ReadAtLen :: All ) . await
876
893
}
877
894
878
895
async fn from_rpc_read_at (
879
896
rpc : & RpcClient ,
880
897
hash : Hash ,
881
898
offset : u64 ,
882
- len : Option < usize > ,
899
+ len : ReadAtLen ,
883
900
) -> anyhow:: Result < Self > {
884
901
let stream = rpc
885
902
. server_streaming ( ReadAtRequest { hash, offset, len } )
@@ -898,9 +915,7 @@ impl Reader {
898
915
Ok ( _) => Err ( io:: Error :: new ( io:: ErrorKind :: Other , "Expected data frame" ) ) ,
899
916
Err ( err) => Err ( io:: Error :: new ( io:: ErrorKind :: Other , format ! ( "{err}" ) ) ) ,
900
917
} ) ;
901
- let len = len
902
- . map ( |l| l as u64 )
903
- . unwrap_or_else ( || size. value ( ) - offset) ;
918
+ let len = len. as_result_len ( size. value ( ) - offset) ;
904
919
Ok ( Self :: new ( size. value ( ) , len, is_complete, Box :: pin ( stream) ) )
905
920
}
906
921
@@ -1120,66 +1135,114 @@ mod tests {
1120
1135
assert_eq ! ( & res, & buf[ ..] ) ;
1121
1136
1122
1137
// Read at smaller than blob_get_chunk_size
1123
- let res = client. blobs ( ) . read_at_to_bytes ( hash, 0 , Some ( 100 ) ) . await ?;
1138
+ let res = client
1139
+ . blobs ( )
1140
+ . read_at_to_bytes ( hash, 0 , ReadAtLen :: Exact ( 100 ) )
1141
+ . await ?;
1124
1142
assert_eq ! ( res. len( ) , 100 ) ;
1125
1143
assert_eq ! ( & res[ ..] , & buf[ 0 ..100 ] ) ;
1126
1144
1127
- let res = client. blobs ( ) . read_at_to_bytes ( hash, 20 , Some ( 120 ) ) . await ?;
1145
+ let res = client
1146
+ . blobs ( )
1147
+ . read_at_to_bytes ( hash, 20 , ReadAtLen :: Exact ( 120 ) )
1148
+ . await ?;
1128
1149
assert_eq ! ( res. len( ) , 120 ) ;
1129
1150
assert_eq ! ( & res[ ..] , & buf[ 20 ..140 ] ) ;
1130
1151
1131
1152
// Read at equal to blob_get_chunk_size
1132
1153
let res = client
1133
1154
. blobs ( )
1134
- . read_at_to_bytes ( hash, 0 , Some ( 1024 * 64 ) )
1155
+ . read_at_to_bytes ( hash, 0 , ReadAtLen :: Exact ( 1024 * 64 ) )
1135
1156
. await ?;
1136
1157
assert_eq ! ( res. len( ) , 1024 * 64 ) ;
1137
1158
assert_eq ! ( & res[ ..] , & buf[ 0 ..1024 * 64 ] ) ;
1138
1159
1139
1160
let res = client
1140
1161
. blobs ( )
1141
- . read_at_to_bytes ( hash, 20 , Some ( 1024 * 64 ) )
1162
+ . read_at_to_bytes ( hash, 20 , ReadAtLen :: Exact ( 1024 * 64 ) )
1142
1163
. await ?;
1143
1164
assert_eq ! ( res. len( ) , 1024 * 64 ) ;
1144
1165
assert_eq ! ( & res[ ..] , & buf[ 20 ..( 20 + 1024 * 64 ) ] ) ;
1145
1166
1146
1167
// Read at larger than blob_get_chunk_size
1147
1168
let res = client
1148
1169
. blobs ( )
1149
- . read_at_to_bytes ( hash, 0 , Some ( 10 + 1024 * 64 ) )
1170
+ . read_at_to_bytes ( hash, 0 , ReadAtLen :: Exact ( 10 + 1024 * 64 ) )
1150
1171
. await ?;
1151
1172
assert_eq ! ( res. len( ) , 10 + 1024 * 64 ) ;
1152
1173
assert_eq ! ( & res[ ..] , & buf[ 0 ..( 10 + 1024 * 64 ) ] ) ;
1153
1174
1154
1175
let res = client
1155
1176
. blobs ( )
1156
- . read_at_to_bytes ( hash, 20 , Some ( 10 + 1024 * 64 ) )
1177
+ . read_at_to_bytes ( hash, 20 , ReadAtLen :: Exact ( 10 + 1024 * 64 ) )
1157
1178
. await ?;
1158
1179
assert_eq ! ( res. len( ) , 10 + 1024 * 64 ) ;
1159
1180
assert_eq ! ( & res[ ..] , & buf[ 20 ..( 20 + 10 + 1024 * 64 ) ] ) ;
1160
1181
1161
1182
// full length
1162
- let res = client. blobs ( ) . read_at_to_bytes ( hash, 20 , None ) . await ?;
1183
+ let res = client
1184
+ . blobs ( )
1185
+ . read_at_to_bytes ( hash, 20 , ReadAtLen :: All )
1186
+ . await ?;
1163
1187
assert_eq ! ( res. len( ) , 1024 * 128 - 20 ) ;
1164
1188
assert_eq ! ( & res[ ..] , & buf[ 20 ..] ) ;
1165
1189
1166
1190
// size should be total
1167
- let reader = client. blobs ( ) . read_at ( hash, 0 , Some ( 20 ) ) . await ?;
1191
+ let reader = client
1192
+ . blobs ( )
1193
+ . read_at ( hash, 0 , ReadAtLen :: Exact ( 20 ) )
1194
+ . await ?;
1168
1195
assert_eq ! ( reader. size( ) , 1024 * 128 ) ;
1169
1196
assert_eq ! ( reader. response_size, 20 ) ;
1170
1197
1198
+ // last chunk - exact
1199
+ let res = client
1200
+ . blobs ( )
1201
+ . read_at_to_bytes ( hash, 1024 * 127 , ReadAtLen :: Exact ( 1024 ) )
1202
+ . await ?;
1203
+ assert_eq ! ( res. len( ) , 1024 ) ;
1204
+ assert_eq ! ( res, & buf[ 1024 * 127 ..] ) ;
1205
+
1206
+ // last chunk - open
1207
+ let res = client
1208
+ . blobs ( )
1209
+ . read_at_to_bytes ( hash, 1024 * 127 , ReadAtLen :: All )
1210
+ . await ?;
1211
+ assert_eq ! ( res. len( ) , 1024 ) ;
1212
+ assert_eq ! ( res, & buf[ 1024 * 127 ..] ) ;
1213
+
1214
+ // last chunk - larger
1215
+ let mut res = client
1216
+ . blobs ( )
1217
+ . read_at ( hash, 1024 * 127 , ReadAtLen :: AtMost ( 2048 ) )
1218
+ . await ?;
1219
+ assert_eq ! ( res. size, 1024 * 128 ) ;
1220
+ assert_eq ! ( res. response_size, 1024 ) ;
1221
+ let res = res. read_to_bytes ( ) . await ?;
1222
+ assert_eq ! ( res. len( ) , 1024 ) ;
1223
+ assert_eq ! ( res, & buf[ 1024 * 127 ..] ) ;
1224
+
1171
1225
// out of bounds - too long
1172
- let res = client. blobs ( ) . read_at ( hash, 0 , Some ( 1024 * 128 + 1 ) ) . await ;
1226
+ let res = client
1227
+ . blobs ( )
1228
+ . read_at ( hash, 0 , ReadAtLen :: Exact ( 1024 * 128 + 1 ) )
1229
+ . await ;
1173
1230
let err = res. unwrap_err ( ) ;
1174
1231
assert ! ( err. to_string( ) . contains( "out of bound" ) ) ;
1175
1232
1176
1233
// out of bounds - offset larger than blob
1177
- let res = client. blobs ( ) . read_at ( hash, 1024 * 128 + 1 , None ) . await ;
1234
+ let res = client
1235
+ . blobs ( )
1236
+ . read_at ( hash, 1024 * 128 + 1 , ReadAtLen :: All )
1237
+ . await ;
1178
1238
let err = res. unwrap_err ( ) ;
1179
1239
assert ! ( err. to_string( ) . contains( "out of range" ) ) ;
1180
1240
1181
1241
// out of bounds - offset + length too large
1182
- let res = client. blobs ( ) . read_at ( hash, 1024 * 127 , Some ( 1025 ) ) . await ;
1242
+ let res = client
1243
+ . blobs ( )
1244
+ . read_at ( hash, 1024 * 127 , ReadAtLen :: Exact ( 1025 ) )
1245
+ . await ;
1183
1246
let err = res. unwrap_err ( ) ;
1184
1247
assert ! ( err. to_string( ) . contains( "out of bound" ) ) ;
1185
1248
0 commit comments