Skip to content

Commit 5bb55de

Browse files
committed
feat: add compute_stream_hash method as lower-level way of hashing objects.
1 parent 0f3a4b0 commit 5bb55de

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

gix-object/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ serde = ["dep:serde", "bstr/serde", "smallvec/serde", "gix-hash/serde", "gix-act
2828
verbose-object-parsing-errors = []
2929

3030
[dependencies]
31-
gix-features = { version = "^0.35.0", path = "../gix-features", features = ["rustsha1"] }
31+
gix-features = { version = "^0.35.0", path = "../gix-features", features = ["rustsha1", "progress"] }
3232
gix-hash = { version = "^0.13.0", path = "../gix-hash" }
3333
gix-validate = { version = "^0.8.0", path = "../gix-validate" }
3434
gix-actor = { version = "^0.27.0", path = "../gix-actor" }

gix-object/src/lib.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,8 @@ pub mod decode {
364364
}
365365
}
366366

367-
/// A standalone function to compute a hash of kind `hash_kind` for an object of `object_kind` and its `data`.
367+
/// A function to compute a hash of kind `hash_kind` for an object of `object_kind` and its `data`.
368+
#[doc(alias = "hash_object", alias = "git2")]
368369
pub fn compute_hash(hash_kind: gix_hash::Kind, object_kind: Kind, data: &[u8]) -> gix_hash::ObjectId {
369370
let header = encode::loose_header(object_kind, data.len() as u64);
370371

@@ -374,3 +375,23 @@ pub fn compute_hash(hash_kind: gix_hash::Kind, object_kind: Kind, data: &[u8]) -
374375

375376
hasher.digest().into()
376377
}
378+
379+
/// A function to compute a hash of kind `hash_kind` for an object of `object_kind` and its data read from `stream`
380+
/// which has to yield exactly `stream_len` bytes.
381+
/// Use `progress` to learn about progress in bytes processed and `should_interrupt` to be able to abort the operation
382+
/// if set to `true`.
383+
#[doc(alias = "hash_file", alias = "git2")]
384+
pub fn compute_stream_hash(
385+
hash_kind: gix_hash::Kind,
386+
object_kind: Kind,
387+
stream: &mut dyn std::io::Read,
388+
stream_len: u64,
389+
progress: &mut dyn gix_features::progress::Progress,
390+
should_interrupt: &std::sync::atomic::AtomicBool,
391+
) -> std::io::Result<gix_hash::ObjectId> {
392+
let header = encode::loose_header(object_kind, stream_len);
393+
let mut hasher = gix_features::hash::hasher(hash_kind);
394+
395+
hasher.update(&header);
396+
gix_features::hash::bytes_with_hasher(stream, stream_len, hasher, progress, should_interrupt)
397+
}

gix-object/tests/object.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::path::PathBuf;
2+
use std::sync::atomic::AtomicBool;
23

34
use gix_hash::ObjectId;
45

@@ -21,6 +22,35 @@ fn compute_hash() {
2122
);
2223
}
2324

25+
#[test]
26+
fn compute_stream_hash() {
27+
let hk = gix_hash::Kind::Sha1;
28+
assert_eq!(
29+
gix_object::compute_stream_hash(
30+
hk,
31+
gix_object::Kind::Blob,
32+
&mut &[][..],
33+
0,
34+
&mut gix_features::progress::Discard,
35+
&AtomicBool::default()
36+
)
37+
.expect("in-memory works"),
38+
gix_hash::ObjectId::empty_blob(hk)
39+
);
40+
assert_eq!(
41+
gix_object::compute_stream_hash(
42+
hk,
43+
gix_object::Kind::Tree,
44+
&mut &[][..],
45+
0,
46+
&mut gix_features::progress::Discard,
47+
&AtomicBool::default()
48+
)
49+
.expect("in-memory works"),
50+
gix_hash::ObjectId::empty_tree(hk)
51+
);
52+
}
53+
2454
use gix_testtools::Result;
2555

2656
#[cfg(not(windows))]

0 commit comments

Comments
 (0)