commit
146792b65f
@ -0,0 +1,4 @@
|
|||||||
|
target/
|
||||||
|
output/
|
||||||
|
*~
|
||||||
|
#*#
|
@ -0,0 +1,440 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "async-std"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "538ecb01eb64eecd772087e5b6f7540cbc917f047727339a472dafed2185b267"
|
||||||
|
dependencies = [
|
||||||
|
"async-task",
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-timer",
|
||||||
|
"kv-log-macro",
|
||||||
|
"log",
|
||||||
|
"memchr",
|
||||||
|
"mio",
|
||||||
|
"mio-uds",
|
||||||
|
"num_cpus",
|
||||||
|
"once_cell",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-task"
|
||||||
|
version = "1.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ac2c016b079e771204030951c366db398864f5026f84a44dafb0ff20f02085d"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi 0.3.8",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||||
|
dependencies = [
|
||||||
|
"block-padding",
|
||||||
|
"byte-tools",
|
||||||
|
"byteorder",
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-padding"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
|
||||||
|
dependencies = [
|
||||||
|
"byte-tools",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byte-tools"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
"maybe-uninit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"maybe-uninit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"lazy_static",
|
||||||
|
"maybe-uninit",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fake-simd"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-zircon"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"fuchsia-zircon-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuchsia-zircon-sys"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-io"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-timer"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashlink"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"async-std",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iovec"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kernel32-sys"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.2.8",
|
||||||
|
"winapi-build",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kv-log-macro"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "maybe-uninit"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.6.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"fuchsia-zircon",
|
||||||
|
"fuchsia-zircon-sys",
|
||||||
|
"iovec",
|
||||||
|
"kernel32-sys",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"miow",
|
||||||
|
"net2",
|
||||||
|
"slab",
|
||||||
|
"winapi 0.2.8",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio-uds"
|
||||||
|
version = "0.6.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
|
||||||
|
dependencies = [
|
||||||
|
"iovec",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miow"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||||
|
dependencies = [
|
||||||
|
"kernel32-sys",
|
||||||
|
"net2",
|
||||||
|
"winapi 0.2.8",
|
||||||
|
"ws2_32-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "net2"
|
||||||
|
version = "0.2.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"winapi 0.3.8",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opaque-debug"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"digest",
|
||||||
|
"fake-simd",
|
||||||
|
"opaque-debug",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-build"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ws2_32-sys"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.2.8",
|
||||||
|
"winapi-build",
|
||||||
|
]
|
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "hashlink"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Avril <flanchan@cumallover.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
sha2 = "0.8.1"
|
||||||
|
async-std = "1.3.0"
|
@ -0,0 +1,135 @@
|
|||||||
|
extern crate sha2;
|
||||||
|
extern crate async_std;
|
||||||
|
use sha2::{Sha256, Digest};
|
||||||
|
use async_std::io::ReadExt;
|
||||||
|
|
||||||
|
pub struct FileHash([u8; 32]);
|
||||||
|
|
||||||
|
fn copy_slice<T: Copy>(src: &[T], dst: &mut [T]) -> usize {
|
||||||
|
let mut c =0;
|
||||||
|
for (d, s) in dst.iter_mut().zip(src.iter()) {
|
||||||
|
*d = *s;
|
||||||
|
c += 1;
|
||||||
|
}
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
const BLOCK_SIZE: usize = 32;
|
||||||
|
async fn copy_to_hash<F: FnMut(&[u8])>(src: &mut async_std::fs::File, mut do_block: F) -> Result<usize, async_std::io::Error>
|
||||||
|
{
|
||||||
|
assert!(BLOCK_SIZE>0);
|
||||||
|
|
||||||
|
let mut res: usize =0;
|
||||||
|
let mut buf: [u8; BLOCK_SIZE] = [0; BLOCK_SIZE];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let n = src.read(&mut buf).await?;
|
||||||
|
if n == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
do_block(&buf[..n]);
|
||||||
|
res+=n;
|
||||||
|
}
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileHash {
|
||||||
|
pub fn create(file: &mut std::fs::File) -> Result<Self, std::io::Error> {
|
||||||
|
let mut hash = Sha256::default();
|
||||||
|
std::io::copy(file, &mut hash)?;
|
||||||
|
|
||||||
|
let mut u: [u8; 32] = [0; 32];
|
||||||
|
copy_slice(&hash.result()[..], &mut u);
|
||||||
|
Ok(Self(u))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_async(file: &mut async_std::fs::File) -> Result<Self, async_std::io::Error> {
|
||||||
|
let mut hash = Sha256::default();
|
||||||
|
//async_std::io::copy(file, &mut hash).await?;
|
||||||
|
|
||||||
|
copy_to_hash(file, |buffer| {
|
||||||
|
&hash.input(buffer);
|
||||||
|
}).await?;
|
||||||
|
|
||||||
|
let mut u: [u8; 32] = [0; 32];
|
||||||
|
copy_slice(&hash.result()[..], &mut u);
|
||||||
|
|
||||||
|
Ok(Self(u))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> std::slice::Iter<u8>
|
||||||
|
{
|
||||||
|
self.0.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter_mut(&mut self) -> std::slice::IterMut<u8>
|
||||||
|
{
|
||||||
|
self.0.iter_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for FileHash {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
let mut u: [u8; 32] = [0; 32];
|
||||||
|
copy_slice(&self.0, &mut u);
|
||||||
|
Self(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<[u8; 32]> for FileHash {
|
||||||
|
fn as_ref(&self) -> &[u8; 32] {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsMut<[u8; 32]> for FileHash {
|
||||||
|
fn as_mut(&mut self) -> &mut [u8; 32] {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FileHash {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self([0; 32])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hex_string(bytes: &[u8]) -> String {
|
||||||
|
bytes.iter().map(|x| format!("{:02x}", x)).collect::<String>()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for FileHash {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", hex_string(&self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::cmp::PartialEq for FileHash {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.0.iter()
|
||||||
|
.zip(other.0
|
||||||
|
.iter())
|
||||||
|
.map(|(x, y)| x^y)
|
||||||
|
.fold(0, |x, y| x|y) == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::cmp::Eq for FileHash{}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a mut FileHash {
|
||||||
|
type Item = &'a mut u8;
|
||||||
|
type IntoIter = std::slice::IterMut<'a, u8>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.0.iter_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a FileHash {
|
||||||
|
type Item = &'a u8;
|
||||||
|
type IntoIter = std::slice::Iter<'a, u8>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter
|
||||||
|
{
|
||||||
|
self.0.iter()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
|
extern crate sha2;
|
||||||
|
|
||||||
|
use std::fs::{File};
|
||||||
|
use std::fs;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use sha2::{Sha256};
|
||||||
|
|
||||||
|
mod hash;
|
||||||
|
mod traverse;
|
||||||
|
mod pool;
|
||||||
|
mod rotating_list;
|
||||||
|
|
||||||
|
fn funcall<T: FnOnce()>(w: T)
|
||||||
|
{
|
||||||
|
w();
|
||||||
|
}
|
||||||
|
|
||||||
|
const THREADS: usize = 3;
|
||||||
|
const OUTPUT_DIR: &'static str = "./output";
|
||||||
|
const INPUT_DIR: &'static str = "./target";
|
||||||
|
|
||||||
|
macro_rules! join_path {
|
||||||
|
($($path:expr),*) => {
|
||||||
|
{
|
||||||
|
let mut buf = std::path::PathBuf::new();
|
||||||
|
$(
|
||||||
|
buf.push($path);
|
||||||
|
)+
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_path(path: &Path) -> Result<PathBuf, &'static str> {
|
||||||
|
let mut buf = PathBuf::new();
|
||||||
|
buf.push(OUTPUT_DIR);
|
||||||
|
if let Some(path) = path.to_str() {
|
||||||
|
buf.push(&path[INPUT_DIR.len()+1..]);
|
||||||
|
Ok(buf)
|
||||||
|
} else {
|
||||||
|
Err("Bad pathspec")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let root = traverse::DirectoryIterator::begin(INPUT_DIR).unwrap();
|
||||||
|
|
||||||
|
let mut pools = create_pools!(THREADS);
|
||||||
|
|
||||||
|
if !Path::new(OUTPUT_DIR).exists() {
|
||||||
|
if let Err(err) = fs::create_dir(OUTPUT_DIR) {
|
||||||
|
println!("Could not create output directory: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let hardlink_dir = join_path!(OUTPUT_DIR, ".hashlink");
|
||||||
|
|
||||||
|
if !hardlink_dir.exists() {
|
||||||
|
if let Err(err) = fs::create_dir(hardlink_dir.as_path()) {
|
||||||
|
println!("Could not create .hashlink directory: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for dir in root {
|
||||||
|
let hardlink_dir = hardlink_dir.to_path_buf();
|
||||||
|
send!(pools.get(), move || {
|
||||||
|
if let Ok(mut file) = File::open(&dir) {
|
||||||
|
if let Ok(hash) = hash::FileHash::create(&mut file) {
|
||||||
|
|
||||||
|
let hlpath = join_path!(hardlink_dir, hash.to_string());
|
||||||
|
|
||||||
|
if let Ok(dst) = output_path(Path::new(&dir)) {
|
||||||
|
println!("{} -> {}", dir, hash);
|
||||||
|
|
||||||
|
if let Some(parent) = dst.parent() {
|
||||||
|
if !parent.exists() {
|
||||||
|
if let Err(_) = fs::create_dir(parent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hlpath.exists() {
|
||||||
|
if let Err(_) = std::fs::copy(&dir, &hlpath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::hard_link(hlpath, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
use std::thread;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::sync::mpsc::{channel, Sender, Receiver, SendError, RecvError};
|
||||||
|
use std::rc::*;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! create_pools {
|
||||||
|
($n:expr) => {
|
||||||
|
{
|
||||||
|
let mut pools = $crate::rotating_list::RotatingList::new();
|
||||||
|
|
||||||
|
for _ in 0..$n {
|
||||||
|
let mut pool = $crate::pool::Pool::spawn(|x| {
|
||||||
|
funcall(x);
|
||||||
|
});
|
||||||
|
pool.join_on_drop = true;
|
||||||
|
|
||||||
|
pools.push(pool);
|
||||||
|
}
|
||||||
|
pools
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! send {
|
||||||
|
($i:expr, $($e:expr),+) => {
|
||||||
|
$(
|
||||||
|
$i.send($e).unwrap();
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Pool<T>
|
||||||
|
where T:std::marker::Send+ 'static
|
||||||
|
{
|
||||||
|
sender: Sender<Option<T>>,
|
||||||
|
thread: Option<thread::JoinHandle<()>>,
|
||||||
|
|
||||||
|
pub join_on_drop: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:std::marker::Send+ 'static> Pool<T>
|
||||||
|
{
|
||||||
|
pub fn spawn<F: FnMut(T) + std::marker::Send + 'static>(mut lam: F) -> Self {
|
||||||
|
let (tx, rx): (Sender<Option<T>>, Receiver<Option<T>>) = channel();
|
||||||
|
|
||||||
|
let thread = Some(thread::spawn(move || {
|
||||||
|
loop {
|
||||||
|
let value = match rx.recv() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => break,
|
||||||
|
};
|
||||||
|
if let Some(value) = value {
|
||||||
|
lam(value);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
Self {
|
||||||
|
sender: tx,
|
||||||
|
thread: thread,
|
||||||
|
|
||||||
|
join_on_drop: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn join(&mut self)
|
||||||
|
{
|
||||||
|
if let Some(thread) = self.thread.take() {
|
||||||
|
let _ = thread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn close(&mut self) -> Result<(), SendError<Option<T>>>
|
||||||
|
{
|
||||||
|
self.sender.send(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send(&mut self, value: T) -> Result<(), SendError<Option<T>>>
|
||||||
|
{
|
||||||
|
self.sender.send(Some(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:std::marker::Send+ 'static> Drop for Pool<T>
|
||||||
|
{
|
||||||
|
fn drop(&mut self)
|
||||||
|
{
|
||||||
|
let _ = self.close();
|
||||||
|
if self.join_on_drop {
|
||||||
|
self.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
|
||||||
|
pub struct RotatingList<T>(usize, Vec<T>);
|
||||||
|
|
||||||
|
impl<T> RotatingList<T>
|
||||||
|
{
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(0, Vec::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, value: T)
|
||||||
|
{
|
||||||
|
self.1.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&mut self) -> &mut T
|
||||||
|
{
|
||||||
|
if self.0 >= self.1.len() {
|
||||||
|
self.0 = 0;
|
||||||
|
}
|
||||||
|
self.0 += 1;
|
||||||
|
|
||||||
|
&mut self.1[self.0-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&mut self) -> &mut Vec<T> {
|
||||||
|
&mut self.1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
use std::fs::{ReadDir, DirEntry};
|
||||||
|
use std::vec::*;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
pub struct DirectoryIterator<P>
|
||||||
|
{
|
||||||
|
root: P,
|
||||||
|
dirs: Vec<DirEntry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn traverse<P>(path: P, out: &mut Vec<DirEntry>) -> io::Result<()>
|
||||||
|
where P:AsRef<Path>
|
||||||
|
{
|
||||||
|
for entry in std::fs::read_dir(path)? {
|
||||||
|
match entry {
|
||||||
|
Ok(entry) => out.push(entry),
|
||||||
|
Err(_) => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P> DirectoryIterator<P>
|
||||||
|
where P: AsRef<Path>
|
||||||
|
{
|
||||||
|
pub fn begin(path: P) -> Result<Self, std::io::Error> {
|
||||||
|
|
||||||
|
let mut cache = Vec::new();
|
||||||
|
|
||||||
|
traverse(&path, &mut cache)?;
|
||||||
|
|
||||||
|
Ok(Self{
|
||||||
|
root: path,
|
||||||
|
dirs: cache,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: AsRef<Path>> Iterator for DirectoryIterator<P>
|
||||||
|
{
|
||||||
|
type Item = String;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item>
|
||||||
|
{
|
||||||
|
let current = self.dirs.pop();
|
||||||
|
|
||||||
|
if let Some(current) = current {
|
||||||
|
let path = current.path();
|
||||||
|
|
||||||
|
if path.is_dir() {
|
||||||
|
let _ = traverse(&path, &mut self.dirs);
|
||||||
|
self.next()
|
||||||
|
} else {
|
||||||
|
|
||||||
|
match path.as_path().to_str() {
|
||||||
|
Some(path) => Some(path.to_string()),
|
||||||
|
None => self.next(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue