diff --git a/Cargo.lock b/Cargo.lock index c48511f1..99dbafc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,9 +63,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.57" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" +checksum = "a26fa4d7e3f2eebadf743988fc8aec9fa9a9e82611acafd77c1462ed6262440a" [[package]] name = "atty" @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byteorder" @@ -146,12 +146,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cast" -version = "0.2.7" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" -dependencies = [ - "rustc_version", -] +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cfg-if" @@ -181,9 +178,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.18" +version = "3.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd" dependencies = [ "atty", "bitflags", @@ -196,18 +193,18 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", ] [[package]] name = "console" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" +checksum = "89eab4d20ce20cea182308bca13088fecea9c05f6776cf287205d41a0ed3c847" dependencies = [ "encode_unicode", "libc", @@ -218,18 +215,18 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "dc948ebb96241bb40ab73effeb80d9f93afaad49359d159a5e61be51619fe813" dependencies = [ "libc", ] [[package]] name = "criterion" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" dependencies = [ "atty", "cast", @@ -253,9 +250,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" +checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" dependencies = [ "cast", "itertools", @@ -263,9 +260,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -273,9 +270,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -284,26 +281,26 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "lazy_static", "memoffset", + "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", - "lazy_static", + "once_cell", ] [[package]] @@ -384,9 +381,9 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "encode_unicode" @@ -409,9 +406,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -446,9 +443,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hermit-abi" @@ -470,9 +467,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.2" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", "hashbrown", @@ -507,15 +504,15 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" dependencies = [ "wasm-bindgen", ] @@ -528,15 +525,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" dependencies = [ "autocfg", "scopeguard", @@ -553,9 +550,9 @@ dependencies = [ [[package]] name = "lz4_flex" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74141c8af4bb8136dafb5705826bdd9dce823021db897c1129191804140ddf84" +checksum = "c038063f7a78126c539d666a0323a2032de5e7366012cd14a6eafc5ba290bbd6" dependencies = [ "twox-hash", ] @@ -602,9 +599,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "once_cell" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] name = "oorandom" @@ -620,9 +617,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "os_str_bytes" -version = "6.1.0" +version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" [[package]] name = "papergrid" @@ -658,9 +655,9 @@ dependencies = [ [[package]] name = "plotters" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +checksum = "716b4eeb6c4a1d3ecc956f75b43ec2e8e8ba80026413e70a3f41fd3313d3492b" dependencies = [ "num-traits", "plotters-backend", @@ -671,15 +668,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] @@ -714,9 +711,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" dependencies = [ "unicode-ident", ] @@ -729,9 +726,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -803,18 +800,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.5.6" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -829,24 +826,15 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.26" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "same-file" @@ -863,17 +851,11 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "semver" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" - [[package]] name = "serde" -version = "1.0.137" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" [[package]] name = "serde_cbor" @@ -887,9 +869,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", @@ -898,11 +880,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ - "itoa 1.0.2", + "itoa 1.0.3", "ryu", "serde", ] @@ -922,15 +904,15 @@ dependencies = [ [[package]] name = "signature" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +checksum = "f0ea32af43239f0d353a7dd75a22d94c329c8cdaafdcb4c1c1335aa10c298a4a" [[package]] name = "smallvec" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "snap" @@ -958,9 +940,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.96" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" dependencies = [ "proc-macro2", "quote", @@ -1046,18 +1028,18 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09" dependencies = [ "proc-macro2", "quote", @@ -1092,9 +1074,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" [[package]] name = "unicode-width" @@ -1120,7 +1102,7 @@ dependencies = [ [[package]] name = "vach" -version = "0.4.0" +version = "0.4.1" dependencies = [ "aes-gcm", "brotli", @@ -1134,44 +1116,26 @@ dependencies = [ "thiserror", ] -[[package]] -name = "vach" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1d23f7b1db590938bd4d33aeeb80603082d77c69fdd8c9b3b796b92376fec2" -dependencies = [ - "aes-gcm", - "brotli", - "ed25519-dalek", - "lz4_flex", - "num_cpus", - "rand", - "rayon", - "snap", - "thiserror", -] - [[package]] name = "vach-benchmarks" version = "0.1.0" dependencies = [ "criterion", - "rayon", - "vach 0.4.0", + "vach", ] [[package]] name = "vach-cli" -version = "0.4.0" +version = "0.4.1" dependencies = [ "anyhow", - "clap 3.1.18", + "clap 3.2.20", "indicatif", "log", "pretty_env_logger", "tabled", "term_size", - "vach 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vach", "walkdir", ] @@ -1200,9 +1164,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1210,13 +1174,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -1225,9 +1189,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1235,9 +1199,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" dependencies = [ "proc-macro2", "quote", @@ -1248,15 +1212,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/README.md b/README.md index 0661cdd1..d1b9e679 100644 --- a/README.md +++ b/README.md @@ -78,15 +78,12 @@ use std::fs::File; use vach::prelude::{Archive, Resource, Flags}; let target = File::open("sounds.vach")?; -let archive = Archive::from_handle(target)?; -let resource: Resource = archive.fetch("ambient")?; +let mut archive = Archive::new(target)?; +let resource: Resource = archive.fetch_mut("ambient")?; // By default all resources are flagged as NOT authenticated println!("{}", Sound::new(&resource.data)?); assert!(!resource.authenticated); - -let mut buffer = Vec::new(); -let (flags, content_version, is_authenticated) = archive.fetch_write("ftstep", &mut buffer)?; ``` ##### > Build a signed `.vach` file @@ -148,10 +145,10 @@ let mut public_key_bytes: [u8; crate::PUBLIC_KEY_LENGTH] = include_bytes!(PUBLIC let mut config = ArchiveConfig::default().key(PublicKey::from_bytes(&public_key_bytes)?); let target = File::open("sounds.vach")?; -let archive = Archive::with_config(target, &config)?; +let mut archive = Archive::with_config(target, &config)?; // Resources are marked as secure (=true) if the signatures match the data -let resource = archive.fetch("ambient")?; +let resource = archive.fetch_mut("ambient")?; println!("{}", Sound::new(&resource.data)?); assert!(resource.authenticated); ``` @@ -172,21 +169,21 @@ let mut builder = Builder::new(); let config = BuilderConfig::default().magic(*MAGIC); // Add data -builder.add_leaf(Leaf::from_handle(data_1).id("d1").compress(CompressMode::Always))?; -builder.add_leaf(Leaf::from_handle(data_2).id("d2").compress(CompressMode::Never))?; -builder.add_leaf(Leaf::from_handle(data_3).id("d3").compress(CompressMode::Detect))?; +builder.add_leaf(Leaf::new(data_1).id("d1").compress(CompressMode::Always))?; +builder.add_leaf(Leaf::new(data_2).id("d2").compress(CompressMode::Never))?; +builder.add_leaf(Leaf::new(data_3).id("d3").compress(CompressMode::Detect))?; // Dump data builder.dump(&mut target, &config)?; // Load data let config = ArchiveConfig::default().magic(*MAGIC); -let archive = Archive::with_config(target, &config)?; +let mut archive = Archive::with_config(target, &config)?; // Quick assertions -assert_eq!(archive.fetch("d1")?.data.as_slice(), data_1); -assert_eq!(archive.fetch("d2")?.data.as_slice(), data_2); -assert_eq!(archive.fetch("d3")?.data.as_slice(), data_3); +assert_eq!(archive.fetch_mut("d1")?.data.as_slice(), data_1); +assert_eq!(archive.fetch_mut("d2")?.data.as_slice(), data_2); +assert_eq!(archive.fetch_mut("d3")?.data.as_slice(), data_3); ``` > For more information on how to use the library, read the documentation. [Always read the documentation!](https://youtu.be/TUE_HSgQiG0?t=91) or read the tests, they offer great insight into how the crate works. diff --git a/vach-benchmarks/Cargo.toml b/vach-benchmarks/Cargo.toml index bd630566..b59709bc 100644 --- a/vach-benchmarks/Cargo.toml +++ b/vach-benchmarks/Cargo.toml @@ -8,7 +8,6 @@ publish = false [dependencies] criterion = "0.3.5" vach = { path = "../vach", features = ["compression", "crypto"] } -rayon = "*" [[bench]] name = "benchmark" diff --git a/vach-benchmarks/benches/main.rs b/vach-benchmarks/benches/main.rs index a529644b..1107da10 100644 --- a/vach-benchmarks/benches/main.rs +++ b/vach-benchmarks/benches/main.rs @@ -1,8 +1,6 @@ -use std::collections::HashMap; use std::io; -use criterion::{Criterion, black_box, criterion_group, criterion_main, Throughput}; -use rayon::iter::{ParallelIterator, IntoParallelRefIterator}; +use criterion::{Criterion, black_box, criterion_group, criterion_main, Throughput}; use vach::prelude::*; use vach::crypto_utils::gen_keypair; @@ -57,13 +55,13 @@ pub fn criterion_benchmark(c: &mut Criterion) { // Add data builder - .add_leaf(Leaf::from_handle(data_1).id("d1").compress(CompressMode::Always)) + .add_leaf(Leaf::new(data_1).id("d1").compress(CompressMode::Always)) .unwrap(); builder - .add_leaf(Leaf::from_handle(data_2).id("d2").compress(CompressMode::Never)) + .add_leaf(Leaf::new(data_2).id("d2").compress(CompressMode::Never)) .unwrap(); builder - .add_leaf(Leaf::from_handle(data_3).id("d3").compress(CompressMode::Detect)) + .add_leaf(Leaf::new(data_3).id("d3").compress(CompressMode::Detect)) .unwrap(); // Dump data @@ -80,12 +78,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { { // Builds an archive source from which to benchmark - let template = Leaf::default() - .encrypt(false) - .sign(false) - .compress(CompressMode::Never) - .compression_algo(CompressionAlgorithm::LZ4); - let mut builder = Builder::new().template(template); + let mut builder = Builder::new().template(Leaf::default().encrypt(false).sign(false)); // Add data builder.add(data_1, "d1").unwrap(); @@ -99,28 +92,23 @@ pub fn criterion_benchmark(c: &mut Criterion) { // Load data throughput_group.throughput(Throughput::Elements(3)); - let archive = Archive::with_config(&mut target, &h_config).unwrap(); - let mut sink = Sink::new(); + let mut archive = Archive::with_config(&mut target, &h_config).unwrap(); - throughput_group.bench_function("Archive::fetch_write(---)", |b| { + throughput_group.bench_function("Archive::fetch(---)", |b| { // Load data b.iter(|| { - archive.fetch_write("d1", &mut sink).unwrap(); - archive.fetch_write("d2", &mut sink).unwrap(); - archive.fetch_write("d3", &mut sink).unwrap(); + archive.fetch("d1").unwrap(); + archive.fetch("d2").unwrap(); + archive.fetch("d3").unwrap(); }); }); - throughput_group.bench_function("Archive::fetch_batch(---)", |b| { + throughput_group.bench_function("Archive::fetch_mut(---)", |b| { // Load data b.iter(|| { - let resources = ["d2", "d1", "d3"] - .as_slice() - .par_iter() - .map(|id| (id, archive.fetch(&id))) - .collect::>(); - - criterion::black_box(resources) + archive.fetch_mut("d1").unwrap(); + archive.fetch_mut("d2").unwrap(); + archive.fetch_mut("d3").unwrap(); }); }); diff --git a/vach-cli/Cargo.toml b/vach-cli/Cargo.toml index f6cd7c2d..bc100aaa 100644 --- a/vach-cli/Cargo.toml +++ b/vach-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vach-cli" -version = "0.4.0" +version = "0.4.1" edition = "2021" authors = [ "Jasper Fortuin ", @@ -29,5 +29,5 @@ pretty_env_logger = "0.4.0" term_size = "0.3.2" [dependencies.vach] -version = "0.4.0" +path = "../vach" features = ["compression", "multithreaded", "crypto"] diff --git a/vach-cli/src/commands/pack.rs b/vach-cli/src/commands/pack.rs index ee841d72..b0321eb4 100644 --- a/vach-cli/src/commands/pack.rs +++ b/vach-cli/src/commands/pack.rs @@ -208,20 +208,9 @@ impl CommandTrait for Evaluator { ); // Since it wraps it's internal state in an arc, we can safely clone and send across threads - let callback = |id: &str, _: &RegistryEntry| { + let callback = |leaf: &Leaf, _: &RegistryEntry| { pbar.inc(1); - - // Prevent column from wrapping around - let mut msg = id.to_string(); - if let Some((terminal_width, _)) = term_size::dimensions() { - // Make sure progress bar never get's longer than terminal size - if msg.len() + 140 >= terminal_width { - msg.truncate(terminal_width - 140); - msg.push_str("..."); - } - }; - - pbar.set_message(msg) + pbar.set_message(leaf.id.to_string()) }; // Build a builder-config using the above extracted data diff --git a/vach-cli/src/commands/unpack.rs b/vach-cli/src/commands/unpack.rs index 343d9b21..483b0958 100644 --- a/vach-cli/src/commands/unpack.rs +++ b/vach-cli/src/commands/unpack.rs @@ -1,6 +1,6 @@ use std::fs::{self, File}; use std::str::FromStr; -use std::io::{Read, Seek}; +use std::io::{Read, Seek, Write}; use std::path::PathBuf; use std::time::Instant; @@ -123,19 +123,11 @@ fn extract_archive(archive: &Archive, target_fo let entry_vec = archive.entries().iter().map(|a| (a.0, a.1.offset)).collect::>(); // ignore the unprofessional match clause - match entry_vec.as_slice().par_iter().try_for_each(|(id, offset)| { - // Prevent column from wrapping around - if let Some((terminal_width, _)) = term_size::dimensions() { - let mut msg = id.to_string(); - // Make sure progress bar never get's longer than terminal size - if msg.len() + 140 >= terminal_width { - msg.truncate(terminal_width - 140); - msg.push_str("..."); - } - - // Set's the Progress Bar message - pbar.set_message(msg.to_string()); - }; + if let Err(err) = entry_vec.as_slice().par_iter().try_for_each(|(id, offset)| { + let msg = id.to_string(); + + // Set's the Progress Bar message + pbar.set_message(msg); // Process filesystem let mut save_path = target_folder.clone(); @@ -147,18 +139,18 @@ fn extract_archive(archive: &Archive, target_fo // Write to file and update process queue let mut file = File::create(save_path)?; - archive.fetch_write(id, &mut file)?; + let resource = archive.fetch(id)?; + file.write_all(&resource.data)?; // Increment Progress Bar pbar.inc(*offset); Ok(()) }) { - Ok(it) => it, - Err(err) => return Err(err), + return Err(err); }; // Finished extracting - pbar.finish_and_clear(); + pbar.finish(); log::info!( "Extracted {} files in {}s", archive.entries().len(), diff --git a/vach-mimetype.xml b/vach-mimetype.xml new file mode 100644 index 00000000..541d14ab --- /dev/null +++ b/vach-mimetype.xml @@ -0,0 +1,13 @@ + + + + VACH + Virtual No-So-Virtual Archive + A simple read-only archive format implented in Rust + + + + + + + diff --git a/vach/Cargo.toml b/vach/Cargo.toml index 9872c87a..db90afa7 100644 --- a/vach/Cargo.toml +++ b/vach/Cargo.toml @@ -2,7 +2,7 @@ name = "vach" # NOTE: Make sure spec.txt and vach::VERSION constants are all synced up -version = "0.4.0" +version = "0.4.1" edition = "2021" authors = [ @@ -31,21 +31,21 @@ aes-gcm = { version = "0.9.4", features = ["aes"], optional = true } # Compression dependencies lz4_flex = { version = "0.9.2", optional = true, default-features = false, features = [ "checked-decode", - "frame" + "frame", ] } snap = { version = "1.0.5", optional = true } brotli = { version = "3.3.4", optional = true } # Multithreaded features -parking_lot = { version = "0.12.1", optional = true } +parking_lot = { version = "0.12.1" } rayon = { version = "1.5.2", optional = true } num_cpus = { version = "1.13.1", optional = true } [features] default = ["builder", "archive"] -archive = ["parking_lot"] -builder = ["parking_lot"] +archive = [] +builder = [] crypto = ["ed25519-dalek", "aes-gcm", "rand"] multithreaded = ["rayon", "num_cpus"] diff --git a/vach/README.md b/vach/README.md index a03df34a..2ebefa28 100644 --- a/vach/README.md +++ b/vach/README.md @@ -1,9 +1,5 @@ -

- vach -

-

A simple archiving format, designed for storing assets in compact secure containers

-

+GitHub last commit docs.rs Crate Version on Crates.io
@@ -35,8 +31,8 @@ use vach::prelude::{Archive, Resource, Flags}; let source = File::open("sounds.vach")?; -let archive = Archive::from_handle(source)?; -let resource: Resource = archive.fetch("footstep.wav")?; +let mut archive = Archive::new(source)?; +let resource: Resource = archive.fetch_mut("footstep.wav")?; // By default all resources are flagged as NOT secure assert!(!resource.authenticated); @@ -47,7 +43,7 @@ println!("{}", Sound::new(resource.data.as_slice())?); // Read data directly into an `io::Write` stream let mut buffer = Vec::new(); -let (flags, content_version, is_secure) = archive.fetch_write("ftstep", &mut buffer)?; +let (flags, content_version, is_secure) = archive.fetch_mut("ftstep", &mut buffer)?; ``` > For more information on how to use the crate, read the [documentation](https://docs.rs/vach) or pass by the [repository](https://github.com/zeskeertwee/vach). Maybe also check out the [CLI](https://crates.io/crates/vach-cli), for a more user-friendly use of `vach` diff --git a/vach/src/global/header.rs b/vach/src/global/header.rs index 3b510962..88b3d830 100644 --- a/vach/src/global/header.rs +++ b/vach/src/global/header.rs @@ -147,7 +147,7 @@ impl Header { /// Validates a `Header` with a template [ArchiveConfig] /// ### Errors /// - (in)validation of magic and archive version - pub fn validate(config: &ArchiveConfig, header: &Header) -> InternalResult { + pub(crate) fn validate(config: &ArchiveConfig, header: &Header) -> InternalResult { // Validate magic if header.magic != config.magic { return Err(InternalError::MalformedArchiveSource(header.magic)); @@ -163,7 +163,7 @@ impl Header { /// ### Errors /// - `io` errors - pub fn from_handle(mut handle: T) -> InternalResult

{ + pub(crate) fn from_handle(mut handle: T) -> InternalResult
{ #![allow(clippy::uninit_assumed_init)] let mut buffer: [u8; Header::BASE_SIZE] = [0u8; Header::BASE_SIZE]; diff --git a/vach/src/global/reg_entry.rs b/vach/src/global/reg_entry.rs index 383147c3..9e3efc33 100644 --- a/vach/src/global/reg_entry.rs +++ b/vach/src/global/reg_entry.rs @@ -1,7 +1,5 @@ -use crate::global::flags::Flags; - use std::{io::Read, fmt}; -use super::result::InternalResult; +use super::{result::InternalResult, flags::Flags}; #[cfg(feature = "crypto")] use crate::crypto; diff --git a/vach/src/lib.rs b/vach/src/lib.rs index 76fa6fa6..2b05b3c6 100644 --- a/vach/src/lib.rs +++ b/vach/src/lib.rs @@ -4,6 +4,7 @@ #![deny(missing_docs)] /*! +![GitHub last commit](https://img.shields.io/github/last-commit/zeskeertwee/vach?logo=rust&logoColor=orange&style=flat-square) #### A simple archiving format, designed for storing assets in compact secure containers `vach` is an archiving and resource transmission format. @@ -20,7 +21,7 @@ It was built to be secure, contained and protected. A big benefit of `vach` is t ### 🔫 Cargo Features - `archive` and `builder` (default): Turning them off turns off their respective modules. For example a game only needs the `archive` feature but a tool for packing assets would only need the `builder` feature. -- `multithreaded`: Pulls [rayon](https://crates.io/crates/rayon) as a dependency and adds `Send + Sync` as a trait bound to many generic types. This allows for the auto-parallelization of the `Builder::dump(---)` function. +- `multithreaded`: Pulls [rayon](https://crates.io/crates/rayon) as a dependency and adds [`Send`] as a trait bound to many generic types. This allows for the auto-parallelization of the `Builder::dump(---)` function. - `compression`: Pulls `snap`, `lz4_flex` and `brotli` as dependencies and allows for compression in `vach` archives. - `crypto`: Enables encryption and authentication functionality by pulling the `ed25519_dalek` and `aes_gcm` crates @@ -55,15 +56,14 @@ use std::fs::File; use vach::prelude::{Archive, Resource, Flags}; let target = File::open("sounds.vach")?; -let archive = Archive::from_handle(target)?; -let resource: Resource = archive.fetch("ambient")?; +let mut archive = Archive::new(target)?; +let resource: Resource = archive.fetch_mut("ambient")?; // By default all resources are flagged as NOT authenticated println!("{}", Sound::new(&resource.data)?); assert!(!resource.authenticated); -let mut buffer = Vec::new(); -let (flags, content_version, is_secure) = archive.fetch_write("ftstep", &mut buffer)?; +let resource = archive.fetch_mut("ftstep")?; ``` ##### > Build a signed `.vach` file @@ -103,7 +103,7 @@ let target = File::open("sounds.vach")?; let archive = Archive::with_config(target, &config)?; // Resources are marked as secure (=true) if the signatures match the data -let resource = archive.fetch("ambient")?; +let mut resource = archive.fetch_mut("ambient")?; println!("{}", Sound::new(&resource.data)?); assert!(resource.authenticated); ``` @@ -137,6 +137,7 @@ let keypair : Keypair = Keypair::from_bytes(&keypair_bytes).unwrap(); mod tests; pub(crate) mod global; + #[cfg(feature = "archive")] #[cfg_attr(docsrs, doc(cfg(feature = "archive")))] pub(crate) mod loader; diff --git a/vach/src/loader/archive.rs b/vach/src/loader/archive.rs index 7ac31796..115017da 100644 --- a/vach/src/loader/archive.rs +++ b/vach/src/loader/archive.rs @@ -1,11 +1,9 @@ use std::{ str, - io::{self, Read, Seek, SeekFrom, Write}, - collections::HashMap, + io::{Read, Seek, SeekFrom}, + collections::BTreeMap, }; -use parking_lot::Mutex; - use super::resource::Resource; use crate::{ global::{ @@ -17,26 +15,29 @@ use crate::{ }, }; +use parking_lot::Mutex; + #[cfg(feature = "crypto")] use crate::crypto; #[cfg(feature = "compression")] -use crate::global::compressor::{Compressor, CompressionAlgorithm}; +use crate::global::compressor::*; /// A wrapper for loading data from archive sources. /// It also provides query functions for fetching [`Resource`]s and [`RegistryEntry`]s. +/// `fetch` and `fetch_mut`, with `fetch` involving a locking operation therefore only requires immutable access. /// Specify custom `MAGIC` or provide a `PublicKey` for decrypting and authenticating resources using [`ArchiveConfig`]. /// > **A word of advice:** -/// > Does not buffer the underlying handle, so consider wrapping `handle` in a `BufReader` +/// > Do not wrap Archive in a [Mutex] or [RefCell](std::cell::RefCell), use `Archive::fetch`, [`Archive`] employs a [`Mutex`] internally in an optimized manner that reduces time spent locked. #[derive(Debug)] pub struct Archive { /// Wrapping `handle` in a Mutex means that we only ever lock when reading from the underlying buffer, thus ensuring maximum performance across threads - /// Since all the other work is done per thread + /// Since all other work is done per thread handle: Mutex, // Archive metadata header: Header, - entries: HashMap, + entries: BTreeMap, // Optional parts #[cfg(feature = "crypto")] @@ -164,13 +165,13 @@ where { /// Load an [`Archive`] with the default settings from a source. /// The same as doing: - /// ```ignore + /// ```skip /// Archive::with_config(HANDLE, &ArchiveConfig::default())?; /// ``` /// ### Errors /// - If the internal call to `Archive::with_config(-)` returns an error #[inline(always)] - pub fn from_handle(handle: T) -> InternalResult> { + pub fn new(handle: T) -> InternalResult> { Archive::with_config(handle, &ArchiveConfig::default()) } @@ -189,7 +190,7 @@ where Header::validate(config, &header)?; // Generate and store Registry Entries - let mut entries = HashMap::with_capacity(header.capacity as usize); + let mut entries = BTreeMap::new(); // Construct entries map for _ in 0..header.capacity { @@ -231,13 +232,12 @@ where } } - pub(crate) fn fetch_raw(&self, entry: &RegistryEntry) -> InternalResult> { + /// Given a data source and a [`RegistryEntry`], gets the adjacent raw data + pub(crate) fn fetch_raw(handle: &mut T, entry: &RegistryEntry) -> InternalResult> { let mut buffer = Vec::with_capacity(entry.offset as usize + 64); + handle.seek(SeekFrom::Start(entry.location))?; - let mut guard = self.handle.lock(); - guard.seek(SeekFrom::Start(entry.location))?; - - let mut take = guard.by_ref().take(entry.offset); + let mut take = handle.take(entry.offset); take.read_to_end(&mut buffer)?; Ok(buffer) @@ -251,7 +251,7 @@ where /// Returns an immutable reference to the underlying [`HashMap`]. This hashmap stores [`RegistryEntry`] values and uses `String` keys. #[inline(always)] - pub fn entries(&self) -> &HashMap { + pub fn entries(&self) -> &BTreeMap { &self.entries } @@ -267,11 +267,14 @@ where T: Read + Seek, { /// Fetch a [`Resource`] with the given `ID`. - /// If the `ID` does not exist within the source, [`InternalError::MissingResourceError`] is returned. + /// Locks the underlying [`Mutex`], for a cheaper non-locking operation refer to `Archive::fetch_mut` pub fn fetch(&self, id: impl AsRef) -> InternalResult { // The reason for this function's unnecessary complexity is it uses the provided functions independently, thus preventing an unnecessary allocation [MAYBE TOO MUCH?] if let Some(entry) = self.fetch_entry(&id) { - let raw = self.fetch_raw(&entry)?; + let raw = { + let mut guard = self.handle.lock(); + Archive::::fetch_raw(&mut guard, &entry)? + }; // Prepare contextual variables let independent = (&entry, id.as_ref(), raw); @@ -290,12 +293,13 @@ where } } - /// Fetch data with the given `ID` and write it directly into the given `target: impl Read`. - /// Returns a tuple containing the `Flags`, `content_version` and `authenticity` (boolean) of the data. - /// If no leaf with the specified `ID` exists, [`InternalError::MissingResourceError`] is returned. - pub fn fetch_write(&self, id: impl AsRef, target: &mut dyn Write) -> InternalResult<(Flags, u8, bool)> { + /// Cheaper alternative to `fetch` that works best for single threaded applications. + /// It does not lock the underlying [Mutex], since it requires a mutable reference. + /// Therefore the borrow checker statically guarantees the operation is safe. Refer to [`Mutex::get_mut`](Mutex). + pub fn fetch_mut(&mut self, id: impl AsRef) -> InternalResult { + // The reason for this function's unnecessary complexity is it uses the provided functions independently, thus preventing an unnecessary allocation [MAYBE TOO MUCH?] if let Some(entry) = self.fetch_entry(&id) { - let raw = self.fetch_raw(&entry)?; + let raw = Archive::::fetch_raw(self.handle.get_mut(), &entry)?; // Prepare contextual variables let independent = (&entry, id.as_ref(), raw); @@ -303,8 +307,12 @@ where // Decompress and|or decrypt the data let (buffer, is_secure) = self.process(independent)?; - io::copy(&mut buffer.as_slice(), target)?; - Ok((entry.flags, entry.content_version, is_secure)) + Ok(Resource { + content_version: entry.content_version, + flags: entry.flags, + data: buffer, + authenticated: is_secure, + }) } else { return Err(InternalError::MissingResourceError(id.as_ref().to_string())); } diff --git a/vach/src/tests/mod.rs b/vach/src/tests/mod.rs index 639550b2..3fb3378a 100644 --- a/vach/src/tests/mod.rs +++ b/vach/src/tests/mod.rs @@ -24,7 +24,7 @@ const CUSTOM_FLAG_4: u32 = 0b0000_0000_0000_0000_0000_0000_0001_0000; #[cfg(feature = "archive")] fn custom_bitflags() -> InternalResult { let target = File::open(SIMPLE_TARGET)?; - let archive = Archive::from_handle(target)?; + let archive = Archive::new(target)?; let entry = archive.fetch_entry("poem").unwrap(); let flags = entry.flags; @@ -86,7 +86,7 @@ fn builder_no_signature() -> InternalResult { poem_flags.set(CUSTOM_FLAG_1 | CUSTOM_FLAG_2 | CUSTOM_FLAG_3 | CUSTOM_FLAG_4, true)?; builder.add_leaf( - Leaf::from_handle(File::open("test_data/poem.txt")?) + Leaf::new(File::open("test_data/poem.txt")?) .compress(CompressMode::Always) .version(10) .id("poem") @@ -94,7 +94,7 @@ fn builder_no_signature() -> InternalResult { )?; builder.add_leaf( - Leaf::from_handle(b"Hello, Cassandra!" as &[u8]) + Leaf::new(b"Hello, Cassandra!" as &[u8]) .compress(CompressMode::Never) .id("greeting"), )?; @@ -109,8 +109,8 @@ fn builder_no_signature() -> InternalResult { #[cfg(all(feature = "compression", feature = "archive"))] fn simple_fetch() -> InternalResult { let target = File::open(SIMPLE_TARGET)?; - let archive = Archive::from_handle(target)?; - let resource = archive.fetch("poem")?; + let mut archive = Archive::new(target)?; + let resource = archive.fetch_mut("poem")?; // Windows bullshit #[cfg(target_os = "windows")] @@ -127,7 +127,7 @@ fn simple_fetch() -> InternalResult { println!("{}", String::from_utf8(resource.data).unwrap()); - let hello = archive.fetch("greeting")?; + let hello = archive.fetch_mut("greeting")?; assert_eq!("Hello, Cassandra!", String::from_utf8(hello.data).unwrap()); assert!(!hello.flags.contains(Flags::COMPRESSED_FLAG)); @@ -139,7 +139,7 @@ fn simple_fetch() -> InternalResult { fn builder_with_signature() -> InternalResult { let mut builder = Builder::default(); - let cb = |_: &str, entry: &RegistryEntry| { + let cb = |_: &Leaf, entry: &RegistryEntry| { dbg!(entry); }; let mut build_config = BuilderConfig::default().callback(&cb); @@ -161,7 +161,7 @@ fn builder_with_signature() -> InternalResult { } #[test] -#[cfg(all(feature = "archive", feature = "crypto"))] +#[cfg(all(feature = "archive", feature = "crypto", feature = "compression"))] fn fetch_with_signature() -> InternalResult { let target = File::open(SIGNED_TARGET)?; @@ -170,17 +170,17 @@ fn fetch_with_signature() -> InternalResult { let keypair = &KEYPAIR[crate::SECRET_KEY_LENGTH..]; config.load_public_key(keypair)?; - let archive = Archive::with_config(target, &config)?; - let resource = archive.fetch("test_data/song.txt")?; + let mut archive = Archive::with_config(target, &config)?; + let resource = archive.fetch_mut("test_data/song.txt")?; let song = str::from_utf8(resource.data.as_slice()).unwrap(); // The adjacent resource was flagged to not be signed - let not_signed_resource = archive.fetch("not_signed")?; + let not_signed_resource = archive.fetch_mut("not_signed")?; assert!(!not_signed_resource.flags.contains(Flags::SIGNED_FLAG)); assert!(!not_signed_resource.authenticated); // The adjacent resource was flagged to not be signed - let not_signed_resource = archive.fetch("not_signed")?; + let not_signed_resource = archive.fetch_mut("not_signed")?; assert!(!not_signed_resource.flags.contains(Flags::SIGNED_FLAG)); assert!(!not_signed_resource.authenticated); @@ -203,39 +203,6 @@ fn fetch_with_signature() -> InternalResult { Ok(()) } -#[test] -#[cfg(all(feature = "archive", feature = "crypto"))] -fn fetch_write_with_signature() -> InternalResult { - let target = File::open(SIGNED_TARGET)?; - - // Load keypair - let mut config = ArchiveConfig::default(); - let keypair = &KEYPAIR[crate::SECRET_KEY_LENGTH..]; - config.load_public_key(keypair)?; - - let archive = Archive::with_config(target, &config)?; - let mut song = Vec::new(); - - let metadata = archive.fetch_write("test_data/poem.txt", &mut song)?; - assert!(metadata.2); - assert!(metadata.0.contains(Flags::SIGNED_FLAG)); - - // Windows bullshit - #[cfg(target_os = "windows")] - { - assert_eq!(song.len(), 359); - } - #[cfg(not(any(target_os = "windows", target_os = "ios")))] - { - assert_eq!(song.len(), 345); - } - - // Assert identity of retrieved data - println!("{}", String::from_utf8(song).unwrap()); - - Ok(()) -} - #[test] #[cfg(feature = "crypto")] fn edcryptor_test() -> InternalResult { @@ -264,7 +231,7 @@ fn builder_with_encryption() -> InternalResult { builder.add_dir("test_data", None)?; builder.add_leaf( - Leaf::from_handle(b"Snitches get stitches, iOS sucks" as &[u8]) + Leaf::new(b"Snitches get stitches, iOS sucks" as &[u8]) .sign(false) .compression_algo(CompressionAlgorithm::Brotli(11)) .compress(CompressMode::Always) @@ -290,8 +257,8 @@ fn fetch_from_encrypted() -> InternalResult { let public_key = &KEYPAIR[crate::SECRET_KEY_LENGTH..]; config.load_public_key(public_key)?; - let archive = Archive::with_config(target, &config)?; - let resource = archive.fetch("test_data/song.txt")?; + let mut archive = Archive::with_config(target, &config)?; + let resource = archive.fetch_mut("test_data/song.txt")?; let song = str::from_utf8(resource.data.as_slice()).unwrap(); // Windows bullshit @@ -334,9 +301,9 @@ fn consolidated_example() -> InternalResult { // Add data let template = Leaf::default().encrypt(true).version(59); - builder.add_leaf(Leaf::from_handle(data_1).id("d1").template(&template))?; - builder.add_leaf(Leaf::from_handle(data_2).id("d2").template(&template))?; - builder.add_leaf(Leaf::from_handle(data_3).id("d3").template(&template))?; + builder.add_leaf(Leaf::new(data_1).id("d1").template(&template))?; + builder.add_leaf(Leaf::new(data_2).id("d2").template(&template))?; + builder.add_leaf(Leaf::new(data_3).id("d3").template(&template))?; // Dump data let then = Instant::now(); @@ -350,15 +317,15 @@ fn consolidated_example() -> InternalResult { config.load_public_key(&keypair_bytes[32..])?; let then = Instant::now(); - let archive = Archive::with_config(target, &config)?; + let mut archive = Archive::with_config(target, &config)?; println!("Archive initialization took: {}us", then.elapsed().as_micros()); // Quick assertions let then = Instant::now(); - assert_eq!(archive.fetch("d1")?.data.as_slice(), data_1); - assert_eq!(archive.fetch("d2")?.data.as_slice(), data_2); - assert_eq!(archive.fetch("d3")?.data.as_slice(), data_3); + assert_eq!(archive.fetch_mut("d1")?.data.as_slice(), data_1); + assert_eq!(archive.fetch_mut("d2")?.data.as_slice(), data_2); + assert_eq!(archive.fetch_mut("d3")?.data.as_slice(), data_3); println!("Fetching took: {}us on average", then.elapsed().as_micros() / 4u128); @@ -377,19 +344,19 @@ fn test_compressors() -> InternalResult { let mut builder = Builder::new(); builder.add_leaf( - Leaf::from_handle(input.as_slice()) + Leaf::new(input.as_slice()) .id("LZ4") .compression_algo(CompressionAlgorithm::LZ4) .compress(CompressMode::Always), )?; builder.add_leaf( - Leaf::from_handle(input.as_slice()) + Leaf::new(input.as_slice()) .id("BROTLI") .compression_algo(CompressionAlgorithm::Brotli(9)) .compress(CompressMode::Always), )?; builder.add_leaf( - Leaf::from_handle(input.as_slice()) + Leaf::new(input.as_slice()) .id("SNAPPY") .compression_algo(CompressionAlgorithm::Snappy) .compress(CompressMode::Always), @@ -397,11 +364,11 @@ fn test_compressors() -> InternalResult { builder.dump(&mut target, &BuilderConfig::default())?; - let archive = Archive::from_handle(&mut target)?; + let mut archive = Archive::new(&mut target)?; - let d1 = archive.fetch("LZ4")?; - let d2 = archive.fetch("BROTLI")?; - let d3 = archive.fetch("SNAPPY")?; + let d1 = archive.fetch_mut("LZ4")?; + let d2 = archive.fetch_mut("BROTLI")?; + let d3 = archive.fetch_mut("SNAPPY")?; // Identity tests assert_eq!(d1.data.len(), INPUT_LEN); @@ -453,7 +420,7 @@ fn test_batch_fetching() -> InternalResult { // Process data builder.dump(&mut target, &BuilderConfig::default())?; - let archive = Archive::from_handle(target)?; + let archive = Archive::new(target)?; let mut resources = ids .as_slice() .par_iter() diff --git a/vach/src/writer/builder/config.rs b/vach/src/writer/builder/config.rs index b55a5c29..601f4780 100644 --- a/vach/src/writer/builder/config.rs +++ b/vach/src/writer/builder/config.rs @@ -1,6 +1,9 @@ use std::fmt::Debug; -use crate::global::{flags::Flags, reg_entry::RegistryEntry}; +use crate::{ + global::{flags::Flags, reg_entry::RegistryEntry}, + builder::Leaf, +}; #[cfg(feature = "crypto")] use crate::crypto; @@ -17,15 +20,20 @@ pub struct BuilderConfig<'a> { #[cfg_attr(docsrs, doc(cfg(feature = "crypto")))] pub keypair: Option, /// An optional callback that is called every time a [Leaf](crate::builder::Leaf) finishes processing. - /// The callback get passed to it: the leaf's id and the generated registry entry. Respectively. + /// The callback get passed to it: a reference to the leaf and the generated registry entry. Use the RegEntry to get info on how the data was integrated for the given [`Leaf`]. /// > **To avoid** the `implementation of "FnOnce" is not general enough` error consider adding types to the closure's parameters, as this is a type inference error. Rust somehow cannot infer enough information, [link](https://www.reddit.com/r/rust/comments/ntqu68/implementation_of_fnonce_is_not_general_enough/). /// Usage: /// ``` - /// use vach::builder::BuilderConfig; + /// use vach::prelude::{RegistryEntry, BuilderConfig, Leaf}; /// /// let builder_config = BuilderConfig::default(); + /// fn callback(leaf: &Leaf, reg_entry: &RegistryEntry) { + /// println!("Leaf: {leaf:?} has been processed into Entry: {reg_entry:?}") + /// } + /// + /// builder_config.callback(&callback); /// ``` - pub progress_callback: Option<&'a (dyn Fn(&str, &RegistryEntry) + Send + Sync)>, + pub progress_callback: Option<&'a (dyn Fn(&Leaf, &RegistryEntry) + Send + Sync)>, } impl<'a> Debug for BuilderConfig<'a> { @@ -82,12 +90,12 @@ impl<'a> BuilderConfig<'a> { /// Setter for the `progress_callback` field ///``` - /// use vach::prelude::{BuilderConfig, RegistryEntry}; + /// use vach::prelude::{BuilderConfig, RegistryEntry, Leaf}; /// - /// let callback = |_: &str, entry: &RegistryEntry| { println!("Number of bytes written: {}", entry.offset) }; + /// let callback = |_: &Leaf, entry: &RegistryEntry| { println!("Number of bytes written: {}", entry.offset) }; /// let config = BuilderConfig::default().callback(&callback); ///``` - pub fn callback(mut self, callback: &'a (dyn Fn(&str, &RegistryEntry) + Send + Sync)) -> BuilderConfig<'a> { + pub fn callback(mut self, callback: &'a (dyn Fn(&Leaf, &RegistryEntry) + Send + Sync)) -> BuilderConfig<'a> { self.progress_callback = Some(callback); self } diff --git a/vach/src/writer/builder/mod.rs b/vach/src/writer/builder/mod.rs index b18c6db4..731f87d0 100644 --- a/vach/src/writer/builder/mod.rs +++ b/vach/src/writer/builder/mod.rs @@ -1,4 +1,4 @@ -use std::io::{BufWriter, Write, Seek, SeekFrom}; +use std::io::{BufWriter, Write, Seek, SeekFrom, Read}; use std::collections::HashSet; use std::path::Path; use std::sync::atomic::{AtomicU64, AtomicUsize}; @@ -11,10 +11,10 @@ use parking_lot::{Mutex}; mod config; pub use config::BuilderConfig; -use super::leaf::{Leaf, HandleTrait}; +use super::leaf::Leaf; #[cfg(feature = "compression")] -use {crate::global::compressor::Compressor, super::compress_mode::CompressMode, std::io::Read}; +use {crate::global::compressor::Compressor, super::compress_mode::CompressMode}; use crate::global::error::InternalError; use crate::global::result::InternalResult; @@ -25,18 +25,6 @@ use crate::{ #[cfg(feature = "crypto")] use {crate::crypto::Encryptor, ed25519_dalek::Signer}; -/// A toggle blanket-trait wrapping around `io::Write + Seek` allowing for seamless switching between single and multithreaded execution, by implementing `Send + Sync` -#[cfg(feature = "multithreaded")] -pub trait DumpTrait: Write + Seek + Send + Sync {} -#[cfg(feature = "multithreaded")] -impl DumpTrait for T {} - -#[cfg(not(feature = "multithreaded"))] -/// A toggle blanket-trait wrapping around `io::Write + Seek` allowing for seamless switching between single and multithreaded execution, by implementing `Send + Sync` -pub trait DumpTrait: Write + Seek {} -#[cfg(not(feature = "multithreaded"))] -impl DumpTrait for T {} - /// The archive builder. Provides an interface with which one can configure and build valid `vach` archives. #[derive(Default)] pub struct Builder<'a> { @@ -56,9 +44,9 @@ impl<'a> Builder<'a> { /// The `data` is wrapped in the default [`Leaf`], without cloning the original data. /// The second argument is the `ID` with which the embedded data will be tagged /// ### Errors - /// Returns an `Err(())` if a Leaf with the specified ID exists. - pub fn add(&mut self, data: D, id: impl AsRef) -> InternalResult { - let leaf = Leaf::from_handle(data) + /// - if a Leaf with the specified ID exists. + pub fn add(&mut self, data: D, id: impl AsRef) -> InternalResult { + let leaf = Leaf::new(data) .id(id.as_ref().to_string()) .template(&self.leaf_template); @@ -74,10 +62,10 @@ impl<'a> Builder<'a> { /// Loads all files from a directory, parses them into [`Leaf`]s and appends them into the processing queue. /// An optional [`Leaf`] is passed as a template from which the new [`Leaf`]s shall implement, pass `None` to use the [`Builder`] internal default template. - /// Appended [`Leaf`]s have an `ID` in the form of of: `directory_name/file_name`. For example: "sounds/footstep.wav", "sample/script.data" + /// Appended [`Leaf`]s have an `ID` in the form of of: `directory_name/file_name`. For example: `sounds/footstep.wav1, `sample/script.data` /// ## Errors /// - Any of the underlying calls to the filesystem fail. - /// - The internal call to `Builder::add_leaf()` returns an error. + /// - The internal call to `Builder::add_leaf()` fails. pub fn add_dir(&mut self, path: impl AsRef, template: Option<&Leaf<'a>>) -> InternalResult { use std::fs; @@ -93,7 +81,7 @@ impl<'a> Builder<'a> { if !uri.is_dir() { // Therefore a file let file = fs::File::open(uri)?; - let leaf = Leaf::from_handle(file) + let leaf = Leaf::new(file) .template(template.unwrap_or(&self.leaf_template)) .id(&format!("{}/{}", v.get(v.len() - 2).unwrap(), v.last().unwrap())); @@ -140,7 +128,7 @@ impl<'a> Builder<'a> { /// - Underlying `io` errors /// - If the optional compression or compression stages fails /// - If the requirements of a given stage, compression or encryption, are not met. Like not providing a keypair if a [`Leaf`] is to be encrypted. - pub fn dump(&mut self, mut target: W, config: &BuilderConfig) -> InternalResult { + pub fn dump(&mut self, mut target: W, config: &BuilderConfig) -> InternalResult { // Keep track of how many bytes are written, and where bytes are being written #[cfg(feature = "multithreaded")] use rayon::prelude::*; @@ -319,6 +307,7 @@ impl<'a> Builder<'a> { entry.signature = Some(keypair.sign(&raw)); entry.flags.force_set(Flags::SIGNED_FLAG, true); + // RAW has exhausted it's usefulness, we save memory by deallocating drop(raw); }; } @@ -346,7 +335,7 @@ impl<'a> Builder<'a> { // Call the progress callback bound within the [`BuilderConfig`] if let Some(callback) = config.progress_callback { - callback(&leaf.id, &entry); + callback(&leaf, &entry); } Ok(()) diff --git a/vach/src/writer/compress_mode.rs b/vach/src/writer/compress_mode.rs index 98a9c6a7..2a85db41 100644 --- a/vach/src/writer/compress_mode.rs +++ b/vach/src/writer/compress_mode.rs @@ -15,6 +15,6 @@ pub enum CompressMode { #[cfg(feature = "compression")] impl Default for CompressMode { fn default() -> CompressMode { - CompressMode::Detect + CompressMode::Never } } diff --git a/vach/src/writer/leaf.rs b/vach/src/writer/leaf.rs index 2edfc78b..88c68501 100644 --- a/vach/src/writer/leaf.rs +++ b/vach/src/writer/leaf.rs @@ -7,24 +7,12 @@ use {crate::global::compressor::CompressionAlgorithm, super::compress_mode::Comp use std::{io::Read, fmt}; -#[cfg(feature = "multithreaded")] -/// A toggle blanket-trait wrapping around [`io::Read`](std::io::Read) allowing for seamless switching between single or multithreaded execution -pub trait HandleTrait: Read + Send + Sync {} -#[cfg(feature = "multithreaded")] -impl HandleTrait for T {} - -#[cfg(not(feature = "multithreaded"))] -/// A toggle blanket-trait wrapping around [`io::Read`](std::io::Read) allowing for seamless switching between single or multithreaded execution -pub trait HandleTrait: Read {} -#[cfg(not(feature = "multithreaded"))] -impl HandleTrait for T {} - /// A wrapper around an [`io::Read`](std::io::Read) handle. /// Allows for multiple types of data implementing [`io::Read`](std::io::Read) to be used under one struct. /// Also used to configure how data will be processed and embedded into an write target. pub struct Leaf<'a> { /// The lifetime simply reflects to the [`Builder`](crate::builder::Builder)'s lifetime, meaning the handle must live longer than or the same as the Builder - pub(crate) handle: Box, + pub(crate) handle: Box, /// The `ID` under which the embedded data will be referenced pub id: String, @@ -48,7 +36,7 @@ pub struct Leaf<'a> { pub encrypt: bool, /// Whether to include a signature with this [`Leaf`], defaults to false. /// If set to true then a hash generated and validated when loaded. - /// > *NOTE:* **Turning `sign` on severely hurts the performance of `Archive::fetch(---)`**. This is because signature authentication is an intentionally taxing process, thus preventing brute-forcing of archives. + /// > *NOTE:* **Turning `sign` on severely hurts the performance of `Archive::fetch(---)`**. This is because signature authentication is an intentionally taxing process, which prevents brute-forcing. #[cfg(feature = "crypto")] #[cfg_attr(docsrs, doc(cfg(feature = "crypto")))] pub sign: bool, @@ -62,9 +50,9 @@ impl<'a> Leaf<'a> { /// use vach::prelude::Leaf; /// use std::io::Cursor; /// - /// let leaf = Leaf::from_handle(Cursor::new(vec![])); + /// let leaf = Leaf::new(Cursor::new(vec![])); ///``` - pub fn from_handle(handle: H) -> Leaf<'a> { + pub fn new(handle: R) -> Leaf<'a> { Leaf { handle: Box::new(handle), ..Default::default() @@ -72,7 +60,7 @@ impl<'a> Leaf<'a> { } /// Consume the [Leaf] and return the underlying Boxed handle - pub fn into_inner(self) -> Box { + pub fn into_inner(self) -> Box { self.handle } @@ -83,7 +71,7 @@ impl<'a> Leaf<'a> { /// use vach::prelude::Leaf; /// let template = Leaf::default().version(12); /// - /// let leaf = Leaf::from_handle(Cursor::new(vec![])).template(&template); + /// let leaf = Leaf::new(Cursor::new(vec![])).template(&template); /// assert_eq!(&leaf.content_version, &template.content_version); /// ``` pub fn template(self, other: &Leaf<'a>) -> Self { diff --git a/vach/test_data/encrypted/target.vach b/vach/test_data/encrypted/target.vach index ee78be35..0a2e3bc2 100644 Binary files a/vach/test_data/encrypted/target.vach and b/vach/test_data/encrypted/target.vach differ diff --git a/vach/test_data/signed/target.vach b/vach/test_data/signed/target.vach index 98f070fa..60cb8656 100644 Binary files a/vach/test_data/signed/target.vach and b/vach/test_data/signed/target.vach differ diff --git a/vach/test_data/simple/target.vach b/vach/test_data/simple/target.vach index ec525509..b4729a79 100644 Binary files a/vach/test_data/simple/target.vach and b/vach/test_data/simple/target.vach differ