Skip to content

Commit e7f0159

Browse files
committed
fix(storage): read_into ignores the byte range for single-fragment reads
Fixes #25. The two single-fragment branches (compressed and uncompressed) in read_into now apply buffer.slice(range) before copying into the output slice, matching what read() already does. Added a regression test that stores a 100-byte fragment and reads bytes 10..50 into a 40-byte buffer. Signed-off-by: Fuad Hasan <fuad.cs22@gmail.com>
1 parent d57da2f commit e7f0159

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

lore-storage/src/read.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ pub async fn read_into(
549549
let (_, decompressed) = compress::decompress_async(fragment, buffer)
550550
.await
551551
.map_err(|e| StorageError::internal_with_context(e, "decompress failed"))?;
552+
let decompressed = decompressed.freeze().slice(range);
552553
if slice.len() != decompressed.len() {
553554
return Err(StorageError::internal(format!(
554555
"unexpected size: slice {} vs decompressed {}",
@@ -558,6 +559,7 @@ pub async fn read_into(
558559
}
559560
slice.copy_from_slice(decompressed.as_ref());
560561
} else {
562+
let buffer = buffer.slice(range);
561563
if slice.len() != buffer.len() {
562564
return Err(StorageError::internal(format!(
563565
"unexpected size: slice {} vs buffer {}",
@@ -950,4 +952,53 @@ mod tests {
950952
"expected AddressNotFound, got {err:?}"
951953
);
952954
}
955+
956+
#[tokio::test(flavor = "multi_thread")]
957+
async fn read_into_single_fragment_respects_range() {
958+
let (_dir, store) = make_test_store().await;
959+
960+
let mut payload = vec![0u8; 100];
961+
for (i, b) in payload.iter_mut().enumerate() {
962+
*b = i as u8;
963+
}
964+
965+
let hash_value = hash::hash_slice(&payload);
966+
let partition = Partition::from([0; 16]);
967+
let address = Address {
968+
hash: hash_value,
969+
context: Context::from([0; 16]),
970+
};
971+
let fragment = Fragment {
972+
flags: FragmentFlags::PayloadStoredLocal.bits(),
973+
size_payload: payload.len() as u32,
974+
size_content: payload.len() as u64,
975+
};
976+
977+
store
978+
.clone()
979+
.put(
980+
partition,
981+
address,
982+
fragment,
983+
Some(Bytes::from(payload.clone())),
984+
false,
985+
)
986+
.await
987+
.expect("put test data");
988+
989+
let mut out = [0u8; 40];
990+
read_into(
991+
store,
992+
partition,
993+
address,
994+
Some(10..50),
995+
&mut out,
996+
ReadOptions::default().no_verify(),
997+
None,
998+
)
999+
.await
1000+
.expect("read_into should respect range");
1001+
1002+
assert_eq!(&out[..], &payload[10..50]);
1003+
}
9531004
}

0 commit comments

Comments
 (0)