Add blake3 and blake3_file functions (#1860)

This commit is contained in:
Trevor Gross 2024-02-11 15:56:04 -05:00 committed by GitHub
parent a2ff42e6c3
commit dc952f9c43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 148 additions and 7 deletions

97
Cargo.lock generated
View File

@ -68,6 +68,18 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "arrayref"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
[[package]]
name = "arrayvec"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "atty"
version = "0.2.14"
@ -91,6 +103,21 @@ version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "blake3"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
"constant_time_eq",
"memmap2",
"rayon",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
@ -117,6 +144,15 @@ version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -145,6 +181,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "constant_time_eq"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2"
[[package]]
name = "cpufeatures"
version = "0.2.12"
@ -163,6 +205,31 @@ dependencies = [
"rustversion",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]]
name = "crypto-common"
version = "0.1.6"
@ -389,6 +456,7 @@ version = "1.24.0"
dependencies = [
"ansi_term",
"atty",
"blake3",
"camino",
"clap",
"cradle",
@ -476,6 +544,15 @@ version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "memmap2"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6"
dependencies = [
"libc",
]
[[package]]
name = "nix"
version = "0.27.1"
@ -582,6 +659,26 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"

View File

@ -20,6 +20,7 @@ members = [".", "bin/ref-type", "bin/generate-book", "bin/update-contributors"]
[dependencies]
ansi_term = "0.12.0"
atty = "0.2.0"
blake3 = { version = "1.5.0", features = ["rayon", "mmap"] }
camino = "1.0.4"
clap = { version = "2.33.0", features = ["wrap_help"] }
ctrlc = { version = "3.1.1", features = ["termination"] }

View File

@ -1456,12 +1456,16 @@ which will halt execution.
#### UUID and Hash Generation
- `sha256(string)` - Return the SHA-256 hash of `string` as a hexadecimal
- `blake3(string)`<sup>master</sup> - Return [BLAKE3] hash of `string` as hexadecimal string.
- `blake3_file(path)`<sup>master</sup> - Return [BLAKE3] hash of file at `path` as hexadecimal
string.
- `sha256(string)` - Return the SHA-256 hash of `string` as hexadecimal string.
- `sha256_file(path)` - Return SHA-256 hash of file at `path` as hexadecimal
string.
- `sha256_file(path)` - Return the SHA-256 hash of the file at `path` as a
hexadecimal string.
- `uuid()` - Generate a random version 4 UUID.
[BLAKE3]: https://github.com/BLAKE3-team/BLAKE3/
#### Semantic Versions
- `semver_matches(version, requirement)`<sup>1.16.0</sup> - Check whether a

View File

@ -21,6 +21,8 @@ pub(crate) fn get(name: &str) -> Option<Function> {
let function = match name {
"absolute_path" => Unary(absolute_path),
"arch" => Nullary(arch),
"blake3" => Unary(blake3),
"blake3_file" => Unary(blake3_file),
"canonicalize" => Unary(canonicalize),
"cache_directory" => Nullary(|_| dir("cache", dirs::cache_dir)),
"capitalize" => Unary(capitalize),
@ -107,6 +109,19 @@ fn arch(_context: &FunctionContext) -> Result<String, String> {
Ok(target::arch().to_owned())
}
fn blake3(_context: &FunctionContext, s: &str) -> Result<String, String> {
Ok(blake3::hash(s.as_bytes()).to_string())
}
fn blake3_file(context: &FunctionContext, path: &str) -> Result<String, String> {
let path = context.search.working_directory.join(path);
let mut hasher = blake3::Hasher::new();
hasher
.update_mmap_rayon(&path)
.map_err(|err| format!("Failed to hash `{}`: {err}", path.display()))?;
Ok(hasher.finalize().to_string())
}
fn canonicalize(_context: &FunctionContext, path: &str) -> Result<String, String> {
let canonical =
std::fs::canonicalize(path).map_err(|err| format!("I/O error canonicalizing path: {err}"))?;
@ -377,12 +392,12 @@ fn sha256(_context: &FunctionContext, s: &str) -> Result<String, String> {
fn sha256_file(context: &FunctionContext, path: &str) -> Result<String, String> {
use sha2::{Digest, Sha256};
let justpath = context.search.working_directory.join(path);
let path = context.search.working_directory.join(path);
let mut hasher = Sha256::new();
let mut file = fs::File::open(&justpath)
.map_err(|err| format!("Failed to open file at `{:?}`: {err}", justpath.to_str()))?;
let mut file =
fs::File::open(&path).map_err(|err| format!("Failed to open `{}`: {err}", path.display()))?;
std::io::copy(&mut file, &mut hasher)
.map_err(|err| format!("Failed to read file at `{:?}`: {err}", justpath.to_str()))?;
.map_err(|err| format!("Failed to read `{}`: {err}", path.display()))?;
let hash = hasher.finalize();
Ok(format!("{hash:x}"))
}

View File

@ -663,6 +663,30 @@ fn just_pid() {
assert_eq!(stdout.parse::<u32>().unwrap(), pid);
}
#[test]
fn blake3() {
Test::new()
.justfile("x := blake3('5943ee37-0000-1000-8000-010203040506')")
.args(["--evaluate", "x"])
.stdout("026c9f740a793ff536ddf05f8915ea4179421f47f0fa9545476076e9ba8f3f2b")
.run();
}
#[test]
fn blake3_file() {
Test::new()
.justfile("x := blake3_file('sub/blakefile')")
.tree(tree! {
sub: {
blakefile: "just is great\n",
}
})
.current_dir("sub")
.args(["--evaluate", "x"])
.stdout("8379241877190ca4b94076a8c8f89fe5747f95c62f3e4bf41f7408a0088ae16d")
.run();
}
#[cfg(unix)]
#[test]
fn canonicalize() {