diff options
853 files changed, 78283 insertions, 49657 deletions
diff --git a/.gitreview b/.gitreview new file mode 100644 index 000000000000..6139d7bdadb8 --- /dev/null +++ b/.gitreview @@ -0,0 +1,5 @@ +[gerrit] +host=cl.tvl.fyi +port=29418 +project=depot +defaultbranch=canon diff --git a/.mailmap b/.mailmap index 06e6c9a44997..a583a1ea96ae 100644 --- a/.mailmap +++ b/.mailmap @@ -1 +1,2 @@ Alyssa Ross <hi@alyssa.is> +Aspen Smith <root@gws.fyi> <aspen@gws.fyi> <grfn@gws.fyi> diff --git a/.nixery/default.nix b/.nixery/default.nix index 19da286ee345..5a3325ea796c 100644 --- a/.nixery/default.nix +++ b/.nixery/default.nix @@ -1,6 +1,6 @@ # See README.md -{ depot ? import ../. {}, ... }: +{ depot ? import ../. { }, ... }: -depot.third_party.nixpkgs.extend(_: _: { +depot.third_party.nixpkgs.extend (_: _: { tvl = depot; }) diff --git a/README.md b/README.md index f58f937cef38..2ef7592688f7 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,9 @@ partially see this as [an experiment][] in tooling for monorepos. ## Services -* Source code is available primarily through Sourcegraph on - [cs.tvl.fyi](https://cs.tvl.fyi), where it is searchable and even semantically - indexed. A lower-tech view of the repository is also available via cgit-pink - on [code.tvl.fyi](https://code.tvl.fyi). +* Source code can be viewed primarily via `cgit-pink` on + [code.tvl.fyi](https://code.tvl.fyi), with code search being available through + Livegrep on [grep.tvl.fyi](https://grep.tvl.fyi). The repository can be cloned using `git` from `https://cl.tvl.fyi/depot`. diff --git a/corp/rih/backend/Cargo.lock b/corp/rih/backend/Cargo.lock index afbe6fbc0bf4..97b76ca60ca0 100644 --- a/corp/rih/backend/Cargo.lock +++ b/corp/rih/backend/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "ascii" @@ -42,13 +42,13 @@ checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", ] [[package]] @@ -69,9 +69,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "aws-creds" @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "aws-region" -version = "0.25.3" +version = "0.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056557a61427d0e5ba29dd931031c8ffed4ee7a550e7cd55692a9d8deb0a9dba" +checksum = "e9aed3f9c7eac9be28662fdb3b0f4d1951e812f7c64fed4f0327ba702f459b3b" dependencies = [ "thiserror", ] @@ -107,9 +107,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bitflags" -version = "1.3.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -132,21 +132,30 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.0.79" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -156,33 +165,33 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "winapi", + "windows-targets", ] [[package]] name = "chunked_transfer" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cca491388666e04d7248af3f60f0c40cfb0991c72205595d7c396e3510207d1a" +checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -198,6 +207,16 @@ dependencies = [ ] [[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -236,44 +255,30 @@ checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" [[package]] name = "errno" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] name = "fastrand" -version = "1.9.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "filetime" -version = "0.2.21" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", - "windows-sys 0.48.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] @@ -284,9 +289,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -303,9 +308,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -323,18 +328,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -353,9 +349,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -364,28 +360,28 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "iana-time-zone" -version = "0.1.56" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -399,76 +395,67 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", ] [[package]] -name = "instant" -version = "0.1.12" +name = "itoa" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] -name = "io-lifetimes" -version = "1.0.11" +name = "js-sys" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", + "wasm-bindgen", ] [[package]] -name = "itoa" -version = "1.0.6" +name = "libc" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] -name = "js-sys" -version = "0.3.63" +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "wasm-bindgen", + "bitflags", + "libc", + "redox_syscall", ] [[package]] -name = "libc" -version = "0.2.144" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" - -[[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" -version = "0.4.18" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "maybe-async" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305" +checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -479,9 +466,9 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -491,9 +478,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -518,38 +505,44 @@ dependencies = [ ] [[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "ordered-multimap" @@ -563,21 +556,30 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -600,9 +602,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -639,30 +641,21 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] @@ -689,13 +682,28 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", - "untrusted", + "spin 0.5.2", + "untrusted 0.7.1", "web-sys", "winapi", ] [[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + +[[package]] name = "rouille" version = "3.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -758,35 +766,34 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ "bitflags", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" dependencies = [ "log", - "ring", + "ring 0.16.20", "sct", "webpki", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safemem" @@ -796,56 +803,57 @@ checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] name = "serde" -version = "1.0.163" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "sha1_smol" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -853,33 +861,34 @@ dependencies = [ ] [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] -name = "subtle" -version = "2.5.0" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] -name = "syn" -version = "1.0.109" +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.18" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -888,35 +897,35 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", + "once_cell", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", ] [[package]] @@ -930,13 +939,16 @@ dependencies = [ [[package]] name = "time" -version = "0.3.21" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ + "deranged", "itoa", "libc", + "num-conv", "num_threads", + "powerfmt", "serde", "time-core", "time-macros", @@ -944,16 +956,17 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -971,9 +984,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -995,36 +1008,36 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -1036,10 +1049,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] name = "url" -version = "2.4.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -1048,9 +1067,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.3.3" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", "serde", @@ -1058,9 +1077,9 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -1070,34 +1089,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.18", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1105,28 +1125,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" -version = "0.3.63" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -1134,12 +1154,12 @@ dependencies = [ [[package]] name = "webpki" -version = "0.22.0" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -1174,142 +1194,113 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets", ] [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.42.2", + "windows-targets", ] [[package]] name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] -name = "windows_i686_gnu" -version = "0.48.0" +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" +name = "windows_x86_64_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" +name = "zerocopy-derive" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/corp/rih/frontend/Cargo.lock b/corp/rih/frontend/Cargo.lock index 2d2f5ea84b92..9ce686ff35d6 100644 --- a/corp/rih/frontend/Cargo.lock +++ b/corp/rih/frontend/Cargo.lock @@ -1500,19 +1500,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -1537,9 +1538,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1547,9 +1548,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -1560,9 +1561,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" diff --git a/corp/rih/frontend/Cargo.toml b/corp/rih/frontend/Cargo.toml index f01378c7e61e..193fa919b45e 100644 --- a/corp/rih/frontend/Cargo.toml +++ b/corp/rih/frontend/Cargo.toml @@ -19,7 +19,7 @@ yew-router = "0.17" wasm-bindgen-futures = "0.4" # needs to be in sync with nixpkgs -wasm-bindgen = "= 0.2.91" +wasm-bindgen = "= 0.2.93" uuid = { version = "1.3.3", features = ["v4", "serde"] } [dependencies.serde] diff --git a/corp/russian/predlozhnik/Cargo.lock b/corp/russian/predlozhnik/Cargo.lock index 1cacb43b3928..514050e55340 100644 --- a/corp/russian/predlozhnik/Cargo.lock +++ b/corp/russian/predlozhnik/Cargo.lock @@ -363,19 +363,20 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -400,9 +401,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -410,9 +411,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -423,9 +424,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" diff --git a/corp/russian/predlozhnik/Cargo.toml b/corp/russian/predlozhnik/Cargo.toml index 87537b560bf5..63760812470a 100644 --- a/corp/russian/predlozhnik/Cargo.toml +++ b/corp/russian/predlozhnik/Cargo.toml @@ -9,4 +9,4 @@ lazy_static = "1.4" yew = "0.19" # needs to be in sync with nixpkgs -wasm-bindgen = "= 0.2.91" +wasm-bindgen = "= 0.2.93" diff --git a/corp/russian/predlozhnik/default.nix b/corp/russian/predlozhnik/default.nix index 2137be111278..495e977c1317 100644 --- a/corp/russian/predlozhnik/default.nix +++ b/corp/russian/predlozhnik/default.nix @@ -44,7 +44,6 @@ pkgs.rustPlatform.buildRustPackage rec { export PATH=${lib.makeBinPath deps}:$PATH mkdir home export HOME=$PWD/.home - env trunk build --release -d $out ''; diff --git a/docs/REVIEWS.md b/docs/REVIEWS.md index d76f11f41074..9d2356744d12 100644 --- a/docs/REVIEWS.md +++ b/docs/REVIEWS.md @@ -5,10 +5,10 @@ TVL Code Reviews **Table of Contents** - [TVL Code Reviews](#tvl-code-reviews) + - [Registration](#registration) - [Gerrit setup](#gerrit-setup) - [Gerrit workflows](#gerrit-workflows) - [Review process & approvals](#review-process--approvals) - - [Registration](#registration) - [Submitting changes via email](#submitting-changes-via-email) - [Gerrit for Github users](#gerrit-for-github-users) @@ -22,6 +22,28 @@ contribution guidelines](./CONTRIBUTING.md). All changes are tracked at [cl.tvl.fyi](https://cl.tvl.fyi) using Gerrit. See [Registration](#registration) for information on how to register an account. +## Registration + +The preferred method of contributions & review is done via Gerrit. + +TVL’s Gerrit supports single sign-on (SSO) using a GitHub, StackOverflow or +GitLab.com account. + +Additionally if you want prefer not to use an SSO option or wish to have a +backup authentication strategy in the event of downed server or a keycloak +issue (recommended), you can create a TVL-specific LDAP account on the Gerrit +instance by following these instructions: + +1. Be a member of `#tvl` on [hackint][]. +2. Clone the depot locally (via `git clone "https://cl.tvl.fyi/depot"`). +3. Create a user entry in our LDAP server in [ops/users][ops-users]. + + The entry can be generated using [//web/pwcrypt](https://signup.tvl.fyi/). +4. Create a commit adding yourself (see e.g. + [CL/2671](https://cl.tvl.fyi/c/depot/+/2671)) +5. If only using LDAP, submit the patch via email (see + [Submitting changes via email](#submitting-changes-via-email)) + ## Gerrit setup Gerrit uses the concept of change IDs to track commits across rebases and other @@ -111,23 +133,8 @@ formalised checks before submitting: If all these conditions are fulfilled, the **change author submits their change themselves**. -## Registration - -You may log into Gerrit using a GitHub, StackOverflow or GitLab.com account. - -If you would like to have a TVL-specific account on the Gerrit -instance, follow these instructions: - -1. Be a member of `#tvl` on [hackint][]. -2. Clone the depot locally (via `git clone "https://cl.tvl.fyi/depot"`). -3. Create a user entry in our LDAP server in [ops/users][ops-users]. - - The entry can be generated using [//web/pwcrypt](https://signup.tvl.fyi/). -4. Create a commit adding yourself (see e.g. - [CL/2671](https://cl.tvl.fyi/c/depot/+/2671)) -5. Submit the commit via email (see below). - ## Submitting changes via email + Please keep in mind this process is more complicated and requires more work from both sides: diff --git a/docs/importing-projects.md b/docs/importing-projects.md new file mode 100644 index 000000000000..c68c8b1906ae --- /dev/null +++ b/docs/importing-projects.md @@ -0,0 +1,91 @@ +Importing projects into depot +============================= + +Before importing an existing `git`-based project into depot, a few questions +need to be answered: + + +* Is the project licensed under a free software license, or public domain? +* Do you need to import existing history? +* Do you need to export new history with hashes that continue on from the old + history? (e.g. importing an existing repository, and exporting from depot to + the old upstream) + +Think about this and then pick an approach below: + +## Import with no history (just commit) + +Simply copy the files to where you want them to be in depot, and commit. Nothing +else to do! + +## Import without continuous history (subtree merge) + +This import approach lets you drop an existing project into depot, keep its +existing history, but not retain the ability to continue external history. + +This means that if you, for example, import a project from a different git host +using this method, and then continue to commit to it inside of depot, you will +not be able to export a history consistent with your previous hashes using +`josh`. + +Commit hashes before the import will exist in depot and be valid. + +Still, this approach might be viable if a project "moves into" depot, or has +nothing depending on it externally. + +1. Pick a location in depot where you want your project to be (`$loc` from now on). +2. Fetch your project into the same git store as your depot clone (e.g. by + adding it as an upstream and fetching it). +3. Pick the commit you want to merge (`$commit` from now on). +4. Run `git subtree add --prefix=$loc $commit`, which will create the correct + merge commit. +5. Ensure Gerrit [knows about your commit](#preparing-merges-in-gerrit) for the + parent that is being merged. +6. Modify the merge commit's message to start with `subtree($project_name):`. + Gerrit **will not** allow merge commits that do not follow this format. +7. Push your subtree commit for review as normal. + +## Import with continuous history + +This approach imports the history using `josh`, which means that external +history before/after the import is consistent (you can continue committing in +`depot`, export the history back out, and from an external perspective nothing +changes). + +This is what we did with repositories like `nix-1p` and `nixery`. + +Note: Inside of depot, the pre-import commit hashes will **not make sense**. +`josh` will rewrite them in such a way that exporting the project will yield the +same hashes, but this rewriting changes the hashes of your commits inside of +depot. + +1. Pick a location in depot where you want your project to be (`$loc`). +2. Fetch your project into the same git store as your depot clone (e.g. by + adding it as an upstream and fetching it). +3. Check out the commit you want to merge into depot. +4. Run `josh-filter ":prefix=$loc"`, and take note of the `FILTERED_HEAD` ref + that it produces (`$filtered` from now on). +5. Ensure Gerrit [knows about the filtered commit](#preparing-merges-in-gerrit). +6. Merge the filtered commit into depot using a standard merge, but make sure to + add the `--allow-unrelated-histories` flag. Your commit message **must** + start with `subtree($project_name):`, otherwise Gerrit will not let you push + a merge. +7. Push the merge commit for review as usual. + +------------------------------------------------------ + +## Preparing merges in Gerrit + +When pushing a merge to Gerrit, it needs to know about all ancestors of the +merge, otherwise it will try to interpret commits as new CLs and reject them for +not having a change ID (or create a huge number of CLs, if they do have one). + +To prevent this, we have a special git ref called `subtree-staging` which you +can push external trees to. + +Access to `subtree-staging` has to be granted by a TVL admin, so ping tazjin, +lukegb, flokli, sterni and so on before proceeding. + +1. Determine the commit you want to merge (`$commit`). +2. Run `git push -f $commit origin/subtree-staging` (or replace `origin` with + whatever the TVL Gerrit remote is called in your clone). diff --git a/fun/clbot/clbot.go b/fun/clbot/clbot.go index e5a5990ef25a..40b044f45d39 100644 --- a/fun/clbot/clbot.go +++ b/fun/clbot/clbot.go @@ -41,7 +41,8 @@ var ( notifyRepo = flag.String("notify_repo", "depot", "Repo name to notify about") notifyBranches = stringSetFlag{} - neverPing = flag.String("never_ping", "marcus", "Comma-separated terms that should never ping users") + neverPing = flag.String("never_ping", "marcus", "Comma-separated terms that should never ping users") + onlyDisplay = flag.String("only_display", "", "Comma-separated substrings of the gerrit CL Change Subject that should be shown (everything else is dropped)") ) func init() { @@ -51,7 +52,7 @@ func init() { type stringSetFlag map[string]bool func (f stringSetFlag) String() string { - return fmt.Sprintf("%q", map[string]bool(f)) + return fmt.Sprintf("%v", map[string]bool(f)) } func (f stringSetFlag) Set(s string) error { if s == "" { @@ -193,6 +194,21 @@ func nopingAll(username, message string) string { return strings.ReplaceAll(message, username, noping(username)) } +// changeShouldBeSkipped applies the list of channels in `onlyDisplay` +// to whether we should skip displaying a CL. +func changeShouldBeSkipped(onlyDisplay string, changeSubject string) bool { + // case when we don’t want to filter + if onlyDisplay == "" { + return false + } + for _, needle := range strings.Split(onlyDisplay, ",") { + if strings.Contains(changeSubject, needle) { + return false + } + } + return true +} + func patchSetURL(c gerritevents.Change, p gerritevents.PatchSet) string { return fmt.Sprintf("https://cl.tvl.fyi/%d", c.Number) } @@ -248,13 +264,13 @@ func main() { var parsedMsg string switch e := e.(type) { case *gerritevents.PatchSetCreated: - if e.Change.Project != *notifyRepo || !notifyBranches[e.Change.Branch] || e.PatchSet.Number != 1 { + if e.Change.Project != *notifyRepo || !notifyBranches[e.Change.Branch] || e.PatchSet.Number != 1 || changeShouldBeSkipped(*onlyDisplay, e.Change.Subject) { continue } user := username(e.PatchSet.Uploader) parsedMsg = nopingAll(user, fmt.Sprintf("CL/%d proposed by %s - %s - %s", e.Change.Number, user, e.Change.Subject, patchSetURL(e.Change, e.PatchSet))) case *gerritevents.ChangeMerged: - if e.Change.Project != *notifyRepo || !notifyBranches[e.Change.Branch] { + if e.Change.Project != *notifyRepo || !notifyBranches[e.Change.Branch] || changeShouldBeSkipped(*onlyDisplay, e.Change.Subject) { continue } owner := username(e.Change.Owner) diff --git a/fun/clbot/clbot_test.go b/fun/clbot/clbot_test.go new file mode 100644 index 000000000000..567540c364f7 --- /dev/null +++ b/fun/clbot/clbot_test.go @@ -0,0 +1,24 @@ +package main + +import ( + "testing" +) + +func TestChangeShouldBeSkipped(t *testing.T) { + dontSkipAny := "" + if changeShouldBeSkipped(dontSkipAny, "mysubject") { + t.Fatal("dontSkipAny should not not be skip any") + } + + showThese := "A,B" + if changeShouldBeSkipped(showThese, "A") { + t.Fatal("A should be shown") + } + if changeShouldBeSkipped(showThese, "B") { + t.Fatal("B should be shown") + } + if !changeShouldBeSkipped(showThese, "C") { + t.Fatal("C should not be shown") + } + +} diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/bar b/nix/buildBazelPackageNG/.skip-subtree index e69de29bb2d1..e69de29bb2d1 100644 --- a/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/bar +++ b/nix/buildBazelPackageNG/.skip-subtree diff --git a/nix/buildBazelPackageNG/bazelRulesJavaHook/default.nix b/nix/buildBazelPackageNG/bazelRulesJavaHook/default.nix new file mode 100644 index 000000000000..38edcccaa59c --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesJavaHook/default.nix @@ -0,0 +1,9 @@ +{ makeSetupHook }: + +makeSetupHook +{ + name = "rules_java_bazel_hook"; + substitutions = { + local_java = ./local_java; + }; +} ./setup-hook.sh diff --git a/nix/buildBazelPackageNG/bazelRulesJavaHook/local_java/BUILD.bazel b/nix/buildBazelPackageNG/bazelRulesJavaHook/local_java/BUILD.bazel new file mode 100644 index 000000000000..8bea4954cd54 --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesJavaHook/local_java/BUILD.bazel @@ -0,0 +1,3 @@ +alias(name = "jdk", actual = "@local_jdk//:jdk") +alias(name = "toolchain", actual = "@local_jdk//:toolchain") +alias(name = "bootstrap_runtime_toolchain", actual = "@local_jdk//:bootstrap_runtime_toolchain") diff --git a/nix/buildBazelPackageNG/bazelRulesJavaHook/local_java/WORKSPACE b/nix/buildBazelPackageNG/bazelRulesJavaHook/local_java/WORKSPACE new file mode 100644 index 000000000000..5b3107898d75 --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesJavaHook/local_java/WORKSPACE @@ -0,0 +1 @@ +workspace(name = "local_java") diff --git a/nix/buildBazelPackageNG/bazelRulesJavaHook/setup-hook.sh b/nix/buildBazelPackageNG/bazelRulesJavaHook/setup-hook.sh new file mode 100644 index 000000000000..f7f7e3afe5bf --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesJavaHook/setup-hook.sh @@ -0,0 +1,17 @@ +prePatchHooks+=(_setupLocalJavaRepo) + +javaVersions=(11 17 21) +javaPlatforms=( + "linux" "linux_aarch64" "linux_ppc64le" "linux_s390x" + "macos" "macos_aarch64" + "win" "win_arm64") + +_setupLocalJavaRepo() { + for javaVersion in ${javaVersions[@]}; do + for javaPlatform in ${javaPlatforms[@]}; do + bazelFlagsArray+=( + "--override_repository=remotejdk${javaVersion}_${javaPlatform}=@local_java@" + ) + done + done +} diff --git a/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/default.nix b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/default.nix new file mode 100644 index 000000000000..21703dea0a82 --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/default.nix @@ -0,0 +1,55 @@ +{ stdenvNoCC +, lib +, makeSetupHook +, fetchFromGitHub +, coreutils +, gnugrep +, nodejs +, yarn +, git +, cacert +}: +let + rulesNodeJS = stdenvNoCC.mkDerivation rec { + pname = "bazelbuild-rules_nodejs"; + version = "5.8.5"; + + src = fetchFromGitHub { + owner = "bazelbuild"; + repo = "rules_nodejs"; + rev = version; + hash = "sha256-6UbYRrOnS93+pK4VI016gQZv2jLCzkJn6wJ4vZNCNjY="; + }; + + dontBuild = true; + + postPatch = '' + shopt -s globstar + for i in **/*.bzl **/*.sh **/*.cjs; do + substituteInPlace "$i" \ + --replace-quiet '#!/usr/bin/env bash' '#!${stdenvNoCC.shell}' \ + --replace-quiet '#!/bin/bash' '#!${stdenvNoCC.shell}' + done + sed -i '/^#!/a export PATH=${lib.makeBinPath [ coreutils gnugrep ]}:$PATH' internal/node/launcher.sh + ''; + + installPhase = '' + cp -R . $out + ''; + }; +in +makeSetupHook +{ + name = "bazelbuild-rules_nodejs-5-hook"; + propagatedBuildInputs = [ + nodejs + yarn + git + cacert + ]; + substitutions = { + inherit nodejs yarn cacert rulesNodeJS; + local_node = ./local_node; + local_yarn = ./local_yarn; + }; +} ./setup-hook.sh diff --git a/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/BUILD b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/BUILD new file mode 100644 index 000000000000..d764d23ffd1a --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/BUILD @@ -0,0 +1,20 @@ +load("@build_bazel_rules_nodejs//nodejs:toolchain.bzl", _node_toolchain = "node_toolchain") + +package(default_visibility = ["//visibility:public"]) + +exports_files([ + "bin/node", + "bin/npm", +]) + +_node_toolchain( + name = "node_toolchain", + target_tool_path = "__NODEJS__/bin/node", + npm_path = "__NODEJS__/bin/npm", +) + +toolchain( + name = "nodejs", + toolchain = ":node_toolchain", + toolchain_type = "@build_bazel_rules_nodejs//nodejs:toolchain_type", +) diff --git a/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/WORKSPACE b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/WORKSPACE new file mode 100644 index 000000000000..5bc1698b62d5 --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/WORKSPACE @@ -0,0 +1 @@ +workspace(name = "nodejs") diff --git a/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/bin/node b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/bin/node new file mode 100644 index 000000000000..ef1f010f0bf3 --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/bin/node @@ -0,0 +1,3 @@ +#!/bin/sh + +exec "__NODEJS__/bin/node" "$@" diff --git a/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/bin/npm b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/bin/npm new file mode 100644 index 000000000000..63a985dbde20 --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_node/bin/npm @@ -0,0 +1,3 @@ +#!/bin/sh + +exec "__NODEJS__/bin/npm" "$@" diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/foo/git-hates-directories b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_yarn/BUILD index e69de29bb2d1..e69de29bb2d1 100644 --- a/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/foo/git-hates-directories +++ b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_yarn/BUILD diff --git a/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_yarn/WORKSPACE b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_yarn/WORKSPACE new file mode 100644 index 000000000000..2a1b7d4653a1 --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_yarn/WORKSPACE @@ -0,0 +1 @@ +workspace(name = "yarn") diff --git a/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_yarn/bin/yarn b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_yarn/bin/yarn new file mode 100644 index 000000000000..2009572e4eff --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/local_yarn/bin/yarn @@ -0,0 +1,2 @@ +#!/bin/sh +exec "__YARN__/bin/yarn" "$@" diff --git a/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/setup-hook.sh b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/setup-hook.sh new file mode 100644 index 000000000000..5e3cf1eb94c2 --- /dev/null +++ b/nix/buildBazelPackageNG/bazelRulesNodeJS5Hook/setup-hook.sh @@ -0,0 +1,63 @@ +prePatchHooks+=(_setupLocalNodeRepos) +preBuildHooks+=(_setupYarnCache) + +case "$bazelPhase" in + cache) + postInstallHooks+=(_copyYarnCache) + ;; + build) + preBuildHooks+=(_linkYarnCache) + ;; + *) + echo "Unexpected bazelPhase '$bazelPhase' (want cache or build)" >&2 + exit 1 + ;; +esac + + +_setupLocalNodeRepos() { + cp -R @local_node@ $HOME/local_node + chmod -R +w $HOME/local_node + substituteInPlace $HOME/local_node/bin/node \ + --replace-fail '__NODEJS__' '@nodejs@' + substituteInPlace $HOME/local_node/bin/npm \ + --replace-fail '__NODEJS__' '@nodejs@' + substituteInPlace $HOME/local_node/BUILD \ + --replace-fail '__NODEJS__' '@nodejs@' + chmod -R +x $HOME/local_node/bin/* + + cp -R @local_yarn@ $HOME/local_yarn + chmod -R +w $HOME/local_yarn + substituteInPlace $HOME/local_yarn/bin/yarn \ + --replace-fail '__YARN__' '@yarn@' + chmod -R +x $HOME/local_yarn/bin/* + + bazelFlagsArray+=( + "--override_repository=build_bazel_rules_nodejs=@rulesNodeJS@" + + "--override_repository=nodejs_linux_amd64=$HOME/local_node" + "--override_repository=nodejs_linux_arm64=$HOME/local_node" + "--override_repository=nodejs_linux_s390x=$HOME/local_node" + "--override_repository=nodejs_linux_ppc64le=$HOME/local_node" + "--override_repository=nodejs_darwin_amd64=$HOME/local_node" + "--override_repository=nodejs_darwin_arm64=$HOME/local_node" + "--override_repository=nodejs_windows_amd64=$HOME/local_node" + "--override_repository=nodejs_windows_arm64=$HOME/local_node" + "--override_repository=nodejs=$HOME/local_node" + + "--override_repository=yarn=$HOME/local_yarn" + ) +} + +_setupYarnCache() { + @yarn@/bin/yarn config set cafile "@cacert@/etc/ssl/certs/ca-bundle.crt" + @yarn@/bin/yarn config set yarn-offline-mirror "$HOME/yarn-offline-mirror" +} + +_copyYarnCache() { + cp -R "$HOME/yarn-offline-mirror" "$out/yarn-offline-mirror" +} + +_linkYarnCache() { + ln -sf "$cache/yarn-offline-mirror" "$HOME/yarn-offline-mirror" +} diff --git a/nix/buildBazelPackageNG/buildBazelPackageNG.nix b/nix/buildBazelPackageNG/buildBazelPackageNG.nix new file mode 100644 index 000000000000..39c67adea797 --- /dev/null +++ b/nix/buildBazelPackageNG/buildBazelPackageNG.nix @@ -0,0 +1,110 @@ +{ stdenv +, lib +, pkgs +, coreutils +}: + +{ name ? "${baseAttrs.pname}-${baseAttrs.version}" +, bazelTargets +, bazel ? pkgs.bazel +, depsHash +, extraCacheInstall ? "" +, extraBuildSetup ? "" +, extraBuildInstall ? "" +, ... +}@baseAttrs: + +let + cleanAttrs = lib.flip removeAttrs [ + "bazelTargets" + "depsHash" + "extraCacheInstall" + "extraBuildSetup" + "extraBuildInstall" + ]; + attrs = cleanAttrs baseAttrs; + + base = stdenv.mkDerivation (attrs // { + nativeBuildInputs = (attrs.nativeBuildInputs or [ ]) ++ [ + bazel + ]; + + preUnpack = '' + if [[ ! -d $HOME ]]; then + export HOME=$NIX_BUILD_TOP/home + mkdir -p $HOME + fi + ''; + + bazelTargetNames = builtins.attrNames bazelTargets; + }); + + cache = base.overrideAttrs (base: { + name = "${name}-deps"; + + bazelPhase = "cache"; + + buildPhase = '' + runHook preBuild + + bazel sync --repository_cache=repository-cache $bazelFlags "''${bazelFlagsArray[@]}" + bazel build --repository_cache=repository-cache --nobuild $bazelFlags "''${bazelFlagsArray[@]}" $bazelTargetNames + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir $out + echo "${bazel.version}" > $out/bazel_version + cp -R repository-cache $out/repository-cache + ${extraCacheInstall} + + runHook postInstall + ''; + + outputHashMode = "recursive"; + outputHash = depsHash; + }); + + build = base.overrideAttrs (base: { + bazelPhase = "build"; + + inherit cache; + + nativeBuildInputs = (base.nativeBuildInputs or [ ]) ++ [ + coreutils + ]; + + buildPhase = '' + runHook preBuild + + ${extraBuildSetup} + bazel build --repository_cache=$cache/repository-cache $bazelFlags "''${bazelFlagsArray[@]}" $bazelTargetNames + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + ${builtins.concatStringsSep "\n" (lib.mapAttrsToList (target: outPath: lib.optionalString (outPath != null) '' + TARGET_OUTPUTS="$(bazel cquery --repository_cache=$cache/repository-cache $bazelFlags "''${bazelFlagsArray[@]}" --output=files "${target}")" + if [[ "$(echo "$TARGET_OUTPUTS" | wc -l)" -gt 1 ]]; then + echo "Installing ${target}'s outputs ($TARGET_OUTPUTS) into ${outPath} as a directory" + mkdir -p "${outPath}" + cp $TARGET_OUTPUTS "${outPath}" + else + echo "Installing ${target}'s output ($TARGET_OUTPUTS) to ${outPath}" + mkdir -p "${dirOf outPath}" + cp "$TARGET_OUTPUTS" "${outPath}" + fi + '') bazelTargets)} + ${extraBuildInstall} + + runHook postInstall + ''; + }); +in +build diff --git a/nix/buildBazelPackageNG/default.nix b/nix/buildBazelPackageNG/default.nix new file mode 100644 index 000000000000..c1584e66a5ef --- /dev/null +++ b/nix/buildBazelPackageNG/default.nix @@ -0,0 +1,6 @@ +{ pkgs, ... }: + +(pkgs.callPackage ./buildBazelPackageNG.nix { }) // { + bazelRulesJavaHook = pkgs.callPackage ./bazelRulesJavaHook { }; + bazelRulesNodeJS5Hook = pkgs.callPackage ./bazelRulesNodeJS5Hook { }; +} diff --git a/nix/writers/default.nix b/nix/writers/default.nix index 55355913a9f4..e849f1cb0e24 100644 --- a/nix/writers/default.nix +++ b/nix/writers/default.nix @@ -23,7 +23,6 @@ let { name , dependencies ? [ ] , doCheck ? true - , }: src: (if doCheck then testRustSimple else pkgs.lib.id) (pkgs.buildRustCrate ({ diff --git a/ops/besadii/default.nix b/ops/besadii/default.nix index 1199c56cfb94..424fa19b2b44 100644 --- a/ops/besadii/default.nix +++ b/ops/besadii/default.nix @@ -1,5 +1,5 @@ # This program is used as a Gerrit hook to trigger builds on -# Buildkite, Sourcegraph reindexing and other maintenance tasks. +# Buildkite and perform other maintenance tasks. { depot, ... }: depot.nix.buildGo.program { diff --git a/ops/besadii/main.go b/ops/besadii/main.go index 809acc29e8b4..aacd8f176ecf 100644 --- a/ops/besadii/main.go +++ b/ops/besadii/main.go @@ -8,7 +8,6 @@ // // Gerrit (ref-updated) hook: // - Trigger Buildkite CI builds -// - Trigger SourceGraph repository index updates // // Buildkite (post-command) hook: // - Submit CL verification status back to Gerrit @@ -55,10 +54,6 @@ type config struct { BuildkiteProject string `json:"buildkiteProject"` BuildkiteToken string `json:"buildkiteToken"` GerritChangeName string `json:"gerritChangeName"` - - // Optional configuration for Sourcegraph trigger updates. - SourcegraphUrl string `json:"sourcegraphUrl"` - SourcegraphToken string `json:"sourcegraphToken"` } // buildTrigger represents the information passed to besadii when it @@ -154,11 +149,6 @@ func loadConfig() (*config, error) { return nil, fmt.Errorf("invalid 'gerritChangeName': %s", cfg.GerritChangeName) } - // Rudimentary config validation logic - if cfg.SourcegraphUrl != "" && cfg.SourcegraphToken == "" { - return nil, fmt.Errorf("'SourcegraphToken' must be set if 'SourcegraphUrl' is set") - } - if cfg.Repository == "" || cfg.Branch == "" { return nil, fmt.Errorf("missing repository configuration (required: repository, branch)") } @@ -299,26 +289,6 @@ func triggerBuild(cfg *config, log *syslog.Writer, trigger *buildTrigger) error return nil } -// Trigger a Sourcegraph repository index update. -// -// https://docs.sourcegraph.com/admin/repo/webhooks -func triggerIndexUpdate(cfg *config, log *syslog.Writer) error { - req, err := http.NewRequest("POST", cfg.SourcegraphUrl, nil) - if err != nil { - return err - } - - req.Header.Add("Authorization", "token "+cfg.SourcegraphToken) - - _, err = http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("failed to trigger Sourcegraph index update: %w", err) - } - - log.Info("triggered sourcegraph index update") - return nil -} - // Gerrit passes more flags than we want, but Rob Pike decided[0] in // 2013 that the Go art project will not allow users to ignore flags // because he "doesn't like it". This function allows users to ignore @@ -458,13 +428,6 @@ func gerritHookMain(cfg *config, log *syslog.Writer, trigger *buildTrigger) { if err != nil { log.Err(fmt.Sprintf("failed to trigger Buildkite build: %s", err)) } - - if cfg.SourcegraphUrl != "" && trigger.ref == cfg.Branch { - err = triggerIndexUpdate(cfg, log) - if err != nil { - log.Err(fmt.Sprintf("failed to trigger sourcegraph index update: %s", err)) - } - } } func postCommandMain(cfg *config) { diff --git a/ops/buildkite/tvl.tf b/ops/buildkite/tvl.tf index 4c45909a0c36..ee032a5143cb 100644 --- a/ops/buildkite/tvl.tf +++ b/ops/buildkite/tvl.tf @@ -8,7 +8,9 @@ terraform { } backend "s3" { - endpoint = "https://objects.dc-sto1.glesys.net" + endpoints = { + s3 = "https://objects.dc-sto1.glesys.net" + } bucket = "tvl-state" key = "terraform/tvl-buildkite" region = "glesys" @@ -16,6 +18,8 @@ terraform { skip_credentials_validation = true skip_region_validation = true skip_metadata_api_check = true + skip_requesting_account_id = true + skip_s3_checksum = true } } diff --git a/ops/journaldriver/Cargo.lock b/ops/journaldriver/Cargo.lock index 97bbe16ceb4c..eaf87cc525e3 100644 --- a/ops/journaldriver/Cargo.lock +++ b/ops/journaldriver/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "base64" @@ -25,9 +25,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "build-env" @@ -37,11 +37,11 @@ checksum = "e068f31938f954b695423ecaf756179597627d0828c0d3e48c0a722a8b23cf9e" [[package]] name = "cc" -version = "1.0.84" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f8e7c90afad890484a21653d08b6e209ae34770fb5ee298f9c699fcc1e5c856" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ - "libc", + "shlex", ] [[package]] @@ -73,9 +73,9 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.44" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" +checksum = "1e2161dd6eba090ff1594084e95fd67aeccf04382ffea77999ea94ed42ec67b6" dependencies = [ "curl-sys", "libc", @@ -83,14 +83,14 @@ dependencies = [ "openssl-sys", "schannel", "socket2", - "winapi", + "windows-sys 0.52.0", ] [[package]] name = "curl-sys" -version = "0.4.68+curl-8.4.0" +version = "0.4.74+curl-8.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4a0d18d88360e374b16b2273c832b5e57258ffc1d4aa4f96b108e0738d5752f" +checksum = "8af10b986114528fcdc4b63b6f5f021b7057618411046a4de2ba0f0149a097bf" dependencies = [ "cc", "libc", @@ -98,14 +98,14 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", "serde", @@ -113,9 +113,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -125,16 +125,6 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -178,9 +168,9 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "humantime" @@ -190,20 +180,20 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ "hermit-abi", - "rustix", - "windows-sys", + "libc", + "windows-sys 0.52.0", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "journaldriver" @@ -224,15 +214,15 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libsystemd-sys" @@ -247,9 +237,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.12" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "libc", @@ -258,16 +248,10 @@ dependencies = [ ] [[package]] -name = "linux-raw-sys" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" - -[[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "medallion" @@ -285,21 +269,27 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.59" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags", "cfg-if", @@ -329,9 +319,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.95" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -341,9 +331,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "powerfmt" @@ -353,27 +343,27 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -383,9 +373,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -394,52 +384,39 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "rustix" -version = "0.38.21" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "serde" -version = "1.0.192" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", @@ -448,30 +425,37 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "socket2" -version = "0.4.10" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] name = "syn" -version = "2.0.39" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -494,21 +478,22 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -523,10 +508,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -549,54 +535,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] -name = "winapi" -version = "0.3.9" +name = "winapi-util" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-sys 0.59.0", ] [[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-util" -version = "0.1.6" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "winapi", + "windows-targets", ] [[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 = "windows-sys" -version = "0.48.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -605,42 +579,48 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/ops/keycloak/main.tf b/ops/keycloak/main.tf index 923ac1939712..d5698700ce58 100644 --- a/ops/keycloak/main.tf +++ b/ops/keycloak/main.tf @@ -10,20 +10,29 @@ terraform { } backend "s3" { - endpoint = "https://objects.dc-sto1.glesys.net" - bucket = "tvl-state" - key = "terraform/tvl-keycloak" - region = "glesys" + endpoints = { + s3 = "https://objects.dc-sto1.glesys.net" + } + bucket = "tvl-state" + key = "terraform/tvl-keycloak" + region = "glesys" skip_credentials_validation = true skip_region_validation = true skip_metadata_api_check = true + skip_requesting_account_id = true + skip_s3_checksum = true } } provider "keycloak" { client_id = "terraform" url = "https://auth.tvl.fyi" + # NOTE: Docs mention this applies to "users of the legacy distribution of keycloak". + # However, we get a "failed to perform initial login to Keycloak: error + # sending POST request to https://auth.tvl.fyi/realms/master/protocol/openid-connect/token: 404 Not Found" + # if we don't set this. + base_path = "/auth" } resource "keycloak_realm" "tvl" { diff --git a/ops/keycloak/user_sources.tf b/ops/keycloak/user_sources.tf index 01307fff8df5..7fa71e36fbb2 100644 --- a/ops/keycloak/user_sources.tf +++ b/ops/keycloak/user_sources.tf @@ -22,6 +22,13 @@ resource "keycloak_ldap_user_federation" "tvl_ldap" { "inetOrgPerson", "organizationalPerson", ] + + lifecycle { + # Without this, terraform wants to recreate the resource. + ignore_changes = [ + delete_default_mappers + ] + } } # keycloak_oidc_identity_provider.github will be destroyed @@ -29,7 +36,7 @@ resource "keycloak_ldap_user_federation" "tvl_ldap" { resource "keycloak_oidc_identity_provider" "github" { alias = "github" provider_id = "github" - client_id = "6d7f8bb2e82bb6739556" + client_id = "Iv23liXfGNIr7InMg5Uo" client_secret = var.github_client_secret realm = keycloak_realm.tvl.id backchannel_supported = false diff --git a/ops/kontemplate/default.nix b/ops/kontemplate/default.nix index 1190869c3fda..be01f9e4f698 100644 --- a/ops/kontemplate/default.nix +++ b/ops/kontemplate/default.nix @@ -12,12 +12,11 @@ { lib, pkgs, ... }: -pkgs.buildGoPackage rec { +pkgs.buildGoModule rec { name = "kontemplate-${version}"; version = "canon"; src = ./.; - goPackagePath = "github.com/tazjin/kontemplate"; - goDeps = ./deps.nix; + buildInputs = [ pkgs.parallel ]; # Enable checks and configure check-phase to include vet: @@ -28,6 +27,8 @@ pkgs.buildGoPackage rec { done ''; + vendorHash = "sha256-xPGVM2dq5fAVOiuodOXhDm3v3k+ncNLhlk6aCtF5S9E="; + meta = with lib; { description = "A resource templating helper for Kubernetes"; homepage = "http://kontemplate.works/"; diff --git a/ops/kontemplate/deps.nix b/ops/kontemplate/deps.nix deleted file mode 100644 index 7693968bd550..000000000000 --- a/ops/kontemplate/deps.nix +++ /dev/null @@ -1,111 +0,0 @@ -# This file was generated by https://github.com/kamilchm/go2nix v1.3.0 -[ - { - goPackagePath = "github.com/Masterminds/goutils"; - fetch = { - type = "git"; - url = "https://github.com/Masterminds/goutils"; - rev = "41ac8693c5c10a92ea1ff5ac3a7f95646f6123b0"; - sha256 = "180px47gj936qyk5bkv5mbbgiil9abdjq6kwkf7sq70vyi9mcfiq"; - }; - } - { - goPackagePath = "github.com/Masterminds/semver"; - fetch = { - type = "git"; - url = "https://github.com/Masterminds/semver"; - rev = "5bc3b9184d48f1412b300b87a200cf020d9254cf"; - sha256 = "1vdfm653v50jf63cw0kg2hslx50cn4mk6lj3p51bi11jrg48kfng"; - }; - } - { - goPackagePath = "github.com/Masterminds/sprig"; - fetch = { - type = "git"; - url = "https://github.com/Masterminds/sprig"; - rev = "6f509977777c33eae63b2136d97f7b976cb971cc"; - sha256 = "05h9k6fhjxnpwlihj3z02q9kvqvnq53jix0ab84sx0666bci3cdh"; - }; - } - { - goPackagePath = "github.com/alecthomas/template"; - fetch = { - type = "git"; - url = "https://github.com/alecthomas/template"; - rev = "fb15b899a75114aa79cc930e33c46b577cc664b1"; - sha256 = "1vlasv4dgycydh5wx6jdcvz40zdv90zz1h7836z7lhsi2ymvii26"; - }; - } - { - goPackagePath = "github.com/alecthomas/units"; - fetch = { - type = "git"; - url = "https://github.com/alecthomas/units"; - rev = "c3de453c63f4bdb4dadffab9805ec00426c505f7"; - sha256 = "0js37zlgv37y61j4a2d46jh72xm5kxmpaiw0ya9v944bjpc386my"; - }; - } - { - goPackagePath = "github.com/ghodss/yaml"; - fetch = { - type = "git"; - url = "https://github.com/ghodss/yaml"; - rev = "25d852aebe32c875e9c044af3eef9c7dc6bc777f"; - sha256 = "1w9yq0bxzygc4qwkwwiy7k1k1yviaspcqqv18255k2xkjv5ipccz"; - }; - } - { - goPackagePath = "github.com/google/uuid"; - fetch = { - type = "git"; - url = "https://github.com/google/uuid"; - rev = "c2e93f3ae59f2904160ceaab466009f965df46d6"; - sha256 = "0zw8fvl6jqg0fmv6kmvhss0g4gkrbvgyvl2zgy5wdbdlgp4fja0h"; - }; - } - { - goPackagePath = "github.com/huandu/xstrings"; - fetch = { - type = "git"; - url = "https://github.com/huandu/xstrings"; - rev = "8bbcf2f9ccb55755e748b7644164cd4bdce94c1d"; - sha256 = "1ivvc95514z63k7cpz71l0dwlanffmsh1pijhaqmp41kfiby8rsx"; - }; - } - { - goPackagePath = "github.com/imdario/mergo"; - fetch = { - type = "git"; - url = "https://github.com/imdario/mergo"; - rev = "4c317f2286be3bd0c4f1a0e622edc6398ec4656d"; - sha256 = "0bihha1qsgfjk14yv1hwddv3d8dzxpbjlaxwwyys6lhgxz1cr9h9"; - }; - } - { - goPackagePath = "golang.org/x/crypto"; - fetch = { - type = "git"; - url = "https://go.googlesource.com/crypto"; - rev = "9756ffdc24725223350eb3266ffb92590d28f278"; - sha256 = "0q7hxaaq6lp0v8qqzifvysl47z5rfdlrxkh3d29vsl3wyby3dxl8"; - }; - } - { - goPackagePath = "gopkg.in/alecthomas/kingpin.v2"; - fetch = { - type = "git"; - url = "https://gopkg.in/alecthomas/kingpin.v2"; - rev = "947dcec5ba9c011838740e680966fd7087a71d0d"; - sha256 = "0mndnv3hdngr3bxp7yxfd47cas4prv98sqw534mx7vp38gd88n5r"; - }; - } - { - goPackagePath = "gopkg.in/yaml.v2"; - fetch = { - type = "git"; - url = "https://gopkg.in/yaml.v2"; - rev = "51d6538a90f86fe93ac480b35f37b2be17fef232"; - sha256 = "01wj12jzsdqlnidpyjssmj0r4yavlqy7dwrg7adqd8dicjc4ncsa"; - }; - } -] diff --git a/ops/kontemplate/go.mod b/ops/kontemplate/go.mod new file mode 100644 index 000000000000..e3ae158ea2e2 --- /dev/null +++ b/ops/kontemplate/go.mod @@ -0,0 +1,25 @@ +module github.com/tazjin/kontemplate + +go 1.22.3 + +require ( + github.com/Masterminds/sprig/v3 v3.2.3 + github.com/alecthomas/kingpin/v2 v2.4.0 + github.com/ghodss/yaml v1.0.0 +) + +require ( + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect + github.com/google/uuid v1.1.1 // indirect + github.com/huandu/xstrings v1.3.3 // indirect + github.com/imdario/mergo v0.3.11 // indirect + github.com/mitchellh/copystructure v1.0.0 // indirect + github.com/mitchellh/reflectwalk v1.0.0 // indirect + github.com/shopspring/decimal v1.2.0 // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/xhit/go-str2duration/v2 v2.1.0 // indirect + golang.org/x/crypto v0.3.0 // indirect + gopkg.in/yaml.v2 v2.3.0 // indirect +) diff --git a/ops/kontemplate/go.sum b/ops/kontemplate/go.sum new file mode 100644 index 000000000000..754cffbcb8f6 --- /dev/null +++ b/ops/kontemplate/go.sum @@ -0,0 +1,75 @@ +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/ops/kontemplate/main.go b/ops/kontemplate/main.go index e55d42465c6b..c98229f5cd97 100644 --- a/ops/kontemplate/main.go +++ b/ops/kontemplate/main.go @@ -21,9 +21,9 @@ import ( "os/exec" "strings" + "github.com/alecthomas/kingpin/v2" "github.com/tazjin/kontemplate/context" "github.com/tazjin/kontemplate/templater" - "gopkg.in/alecthomas/kingpin.v2" ) const version string = "1.8.0" diff --git a/ops/kontemplate/templater/templater.go b/ops/kontemplate/templater/templater.go index a8f0c670a603..86cbad459f5b 100644 --- a/ops/kontemplate/templater/templater.go +++ b/ops/kontemplate/templater/templater.go @@ -20,7 +20,7 @@ import ( "strings" "text/template" - "github.com/Masterminds/sprig" + "github.com/Masterminds/sprig/v3" "github.com/tazjin/kontemplate/context" "github.com/tazjin/kontemplate/util" ) diff --git a/ops/kontemplate/util/util.go b/ops/kontemplate/util/util.go index 56fa1e3fc9c5..f96f5c1d7aa4 100644 --- a/ops/kontemplate/util/util.go +++ b/ops/kontemplate/util/util.go @@ -29,13 +29,29 @@ func Merge(in1 *map[string]interface{}, in2 *map[string]interface{}) *map[string return in1 } + // The maps are map[string]interface{} with unknown depth. + // Loop over both maps into every level and merge them. new := make(map[string]interface{}) + for k, v := range *in1 { new[k] = v } for k, v := range *in2 { - new[k] = v + if existing, ok := new[k]; ok { + // If both values are maps, merge them recursively + if existingMap, ok := existing.(map[string]interface{}); ok { + if newMap, ok := v.(map[string]interface{}); ok { + new[k] = *Merge(&existingMap, &newMap) + } else { + new[k] = v + } + } else { + new[k] = v + } + } else { + new[k] = v + } } return &new diff --git a/ops/kontemplate/util/util_test.go b/ops/kontemplate/util/util_test.go index 53c56081758c..328add3d250f 100644 --- a/ops/kontemplate/util/util_test.go +++ b/ops/kontemplate/util/util_test.go @@ -47,6 +47,9 @@ func TestMergeWithNilMap(t *testing.T) { func TestMergeMaps(t *testing.T) { map1 := map[string]interface{}{ "foo": "bar", + "baz": map[string]interface{}{ + "qux": "quux", + }, } map2 := map[string]interface{}{ @@ -56,6 +59,9 @@ func TestMergeMaps(t *testing.T) { result := Merge(&map1, &map2) expected := map[string]interface{}{ "foo": "bar", + "baz": map[string]interface{}{ + "qux": "quux", + }, "bar": "baz", } diff --git a/ops/machines/all-systems.nix b/ops/machines/all-systems.nix index c4382fbddb2a..14a8b6b26a11 100644 --- a/ops/machines/all-systems.nix +++ b/ops/machines/all-systems.nix @@ -3,6 +3,7 @@ (with depot.ops.machines; [ sanduny whitby + nixery-01 ]) ++ (with depot.users.tazjin.nixos; [ diff --git a/ops/machines/whitby/default.nix b/ops/machines/whitby/default.nix index 6a8ee56abc47..7bc02a3fe524 100644 --- a/ops/machines/whitby/default.nix +++ b/ops/machines/whitby/default.nix @@ -11,8 +11,10 @@ in imports = [ (mod "atward.nix") (mod "cgit.nix") + (mod "cheddar.nix") (mod "clbot.nix") (mod "gerrit-autosubmit.nix") + (mod "harmonia.nix") (mod "irccat.nix") (mod "josh.nix") (mod "journaldriver.nix") @@ -24,7 +26,7 @@ in (mod "paroxysm.nix") (mod "restic.nix") (mod "smtprelay.nix") - (mod "sourcegraph.nix") + (mod "teleirc.nix") (mod "tvl-buildkite.nix") (mod "tvl-slapd/default.nix") (mod "tvl-users.nix") @@ -228,10 +230,16 @@ in grafana.file = secretFile "grafana"; irccat.file = secretFile "irccat"; keycloak-db.file = secretFile "keycloak-db"; - nix-cache-priv.file = secretFile "nix-cache-priv"; owothia.file = secretFile "owothia"; panettone.file = secretFile "panettone"; smtprelay.file = secretFile "smtprelay"; + teleirc.file = secretFile "teleirc"; + + nix-cache-priv = { + file = secretFile "nix-cache-priv"; + mode = "0440"; + group = "harmonia"; + }; buildkite-agent-token = { file = secretFile "buildkite-agent-token"; @@ -304,6 +312,9 @@ in agentCount = 32; }; + # Run Markdown/code renderer + services.depot.cheddar.enable = true; + # Start a local SMTP relay to Gmail (used by gerrit) services.depot.smtprelay = { enable = true; @@ -345,7 +356,12 @@ in # Start the Gerrit->IRC bot services.depot.clbot = { enable = true; - channels = [ "#tvix-dev" "#tvl" ]; + channels = { + "#tvl" = { }; + "#tvix-dev" = { + only_display = "tvix,nix-compat,third_party,third-party,3p"; + }; + }; # See //fun/clbot for details. flags = { @@ -367,9 +383,6 @@ in }; services.depot = { - # Run a SourceGraph code search instance - sourcegraph.enable = true; - # Run a livegrep code search instance livegrep.enable = true; @@ -410,6 +423,9 @@ in }; }; + # Run the Telegram<>IRC bridge for Volga Sprint. + teleirc.enable = true; + # Run atward, the search engine redirection thing. atward.enable = true; @@ -467,11 +483,14 @@ in ]; }; - services.nix-serve = { + # Run a Harmonia binary cache. + # + # TODO(tazjin): switch to upstream module after fix for Nix 2.3 + services.depot.harmonia = { enable = true; - port = 6443; - secretKeyFile = config.age.secretsDir + "/nix-cache-priv"; - bindAddress = "localhost"; + signKeyPaths = [ (config.age.secretsDir + "/nix-cache-priv") ]; + settings.bind = "127.0.0.1:6443"; + settings.priority = 50; }; services.fail2ban.enable = true; @@ -607,7 +626,8 @@ in http-port = 5925; # kycl hostname = "auth.tvl.fyi"; http-relative-path = "/auth"; - proxy = "edge"; + proxy-headers = "xforwarded"; + http-enabled = true; }; database = { diff --git a/ops/modules/cheddar.nix b/ops/modules/cheddar.nix new file mode 100644 index 000000000000..8c3036978988 --- /dev/null +++ b/ops/modules/cheddar.nix @@ -0,0 +1,29 @@ +{ depot, config, pkgs, lib, ... }: + +let + cfg = config.services.depot.cheddar; + description = "cheddar - markdown/highlighting server"; +in +{ + options.services.depot.cheddar = with lib; { + enable = mkEnableOption description; + port = mkOption { + description = "Port on which cheddar should listen"; + type = types.int; + default = 4238; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.cheddar-server = { + inherit description; + wantedBy = [ "multi-user.target" ]; + script = "${depot.tools.cheddar}/bin/cheddar --listen 0.0.0.0:${toString cfg.port} --sourcegraph-server"; + + serviceConfig = { + DynamicUser = true; + Restart = "always"; + }; + }; + }; +} diff --git a/ops/modules/clbot.nix b/ops/modules/clbot.nix index bdddff6c810b..0a436a8749d0 100644 --- a/ops/modules/clbot.nix +++ b/ops/modules/clbot.nix @@ -7,6 +7,7 @@ let inherit (lib) listToAttrs + mapAttrsToList mkEnableOption mkIf mkOption @@ -25,13 +26,13 @@ let ${pkgs.systemd}/bin/systemd-escape '${name}' >> $out '')); - mkUnit = flags: channel: { + mkUnit = channel: channelFlags: { name = "clbot-${systemdEscape channel}"; value = { description = "${description} to ${channel}"; wantedBy = [ "multi-user.target" ]; - script = "${depot.fun.clbot}/bin/clbot ${mkFlags (cfg.flags // { + script = "${depot.fun.clbot}/bin/clbot ${mkFlags (cfg.flags // channelFlags // { irc_channel = channel; })} -alsologtostderr"; @@ -53,8 +54,8 @@ in }; channels = mkOption { - type = with types; listOf str; - description = "Channels in which to post (generates one unit per channel)"; + type = with types; attrsOf (attrsOf str); + description = "Channels in which to post (generates one unit per channel); nested attrs are used as extra flags to the service, which override the attrs in `flags`"; }; secretsFile = mkOption { @@ -77,6 +78,6 @@ in }; }; - systemd.services = listToAttrs (map (mkUnit cfg.flags) cfg.channels); + systemd.services = listToAttrs (mapAttrsToList mkUnit cfg.channels); }; } diff --git a/ops/modules/harmonia.nix b/ops/modules/harmonia.nix new file mode 100644 index 000000000000..ae0bdc2cf01e --- /dev/null +++ b/ops/modules/harmonia.nix @@ -0,0 +1,110 @@ +# This is a fork of the nixpkgs module for Harmonia, which adds compatibility +# with Nix 2.3. +# +# We will upstream this eventually. +{ config, pkgs, lib, ... }: +let + cfg = config.services.depot.harmonia; + format = pkgs.formats.toml { }; + + credentials = lib.imap0 + (i: signKeyPath: { + id = "sign-key-${builtins.toString i}"; + path = signKeyPath; + }) + cfg.signKeyPaths; +in +{ + options = { + services.depot.harmonia = { + enable = lib.mkEnableOption "Harmonia: Nix binary cache written in Rust"; + + signKeyPaths = lib.mkOption { + type = lib.types.listOf lib.types.path; + default = [ ]; + description = "Paths to the signing keys to use for signing the cache"; + }; + + package = lib.mkPackageOption pkgs "harmonia" { }; + + settings = lib.mkOption { + inherit (format) type; + default = { }; + description = '' + Settings to merge with the default configuration. + For the list of the default configuration, see <https://github.com/nix-community/harmonia/tree/master#configuration>. + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + users.users.harmonia = { + isSystemUser = true; + group = "harmonia"; + }; + users.groups.harmonia = { }; + + systemd.services.harmonia = { + description = "harmonia binary cache service"; + + requires = [ "nix-daemon.socket" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + environment = { + CONFIG_FILE = format.generate "harmonia.toml" cfg.settings; + SIGN_KEY_PATHS = lib.strings.concatMapStringsSep " " + ( + credential: "%d/${credential.id}" + ) + credentials; + # Note: it's important to set this for nix-store, because it wants to use + # $HOME in order to use a temporary cache dir. bizarre failures will occur + # otherwise + HOME = "/run/harmonia"; + }; + + serviceConfig = { + ExecStart = lib.getExe cfg.package; + User = "harmonia"; + Group = "harmonia"; + Restart = "on-failure"; + PrivateUsers = true; + DeviceAllow = [ "" ]; + UMask = "0066"; + RuntimeDirectory = "harmonia"; + LoadCredential = builtins.map (credential: "${credential.id}:${credential.path}") credentials; + SystemCallFilter = [ + "@system-service" + "~@privileged" + "~@resources" + ]; + CapabilityBoundingSet = ""; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectControlGroups = true; + ProtectKernelLogs = true; + ProtectHostname = true; + ProtectClock = true; + RestrictRealtime = true; + MemoryDenyWriteExecute = true; + ProcSubset = "pid"; + ProtectProc = "invisible"; + RestrictNamespaces = true; + SystemCallArchitectures = "native"; + PrivateNetwork = false; + PrivateTmp = true; + PrivateDevices = true; + PrivateMounts = true; + NoNewPrivileges = true; + ProtectSystem = "strict"; + ProtectHome = true; + LockPersonality = true; + RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; + LimitNOFILE = 65536; + }; + }; + }; +} + diff --git a/ops/modules/sourcegraph.nix b/ops/modules/sourcegraph.nix deleted file mode 100644 index cbf836ab64d5..000000000000 --- a/ops/modules/sourcegraph.nix +++ /dev/null @@ -1,60 +0,0 @@ -# Run sourcegraph, including its entire machinery, in a container. -# Running it outside of a container is a futile endeavour for now. -{ depot, config, pkgs, lib, ... }: - -let - cfg = config.services.depot.sourcegraph; -in -{ - options.services.depot.sourcegraph = with lib; { - enable = mkEnableOption "SourceGraph code search engine"; - - port = mkOption { - description = "Port on which SourceGraph should listen"; - type = types.int; - default = 3463; - }; - - cheddarPort = mkOption { - description = "Port on which cheddar should listen"; - type = types.int; - default = 4238; - }; - }; - - config = lib.mkIf cfg.enable { - # Run a cheddar syntax highlighting server - systemd.services.cheddar-server = { - wantedBy = [ "multi-user.target" ]; - script = "${depot.tools.cheddar}/bin/cheddar --listen 0.0.0.0:${toString cfg.cheddarPort} --sourcegraph-server"; - - serviceConfig = { - DynamicUser = true; - Restart = "always"; - }; - }; - - virtualisation.oci-containers.containers.sourcegraph = { - image = "sourcegraph/server:3.40.0"; - - ports = [ - "127.0.0.1:${toString cfg.port}:7080" - ]; - - volumes = [ - "/var/lib/sourcegraph/etc:/etc/sourcegraph" - "/var/lib/sourcegraph/data:/var/opt/sourcegraph" - ]; - - # TODO(tazjin): Figure out what changed in the protocol. - # environment.SRC_SYNTECT_SERVER = "http://172.17.0.1:${toString cfg.cheddarPort}"; - - # Sourcegraph needs a higher nofile limit, it logs warnings - # otherwise (unclear whether it actually affects the service). - extraOptions = [ - "--ulimit" - "nofile=10000:10000" - ]; - }; - }; -} diff --git a/ops/modules/teleirc.nix b/ops/modules/teleirc.nix new file mode 100644 index 000000000000..9f9ac059ce38 --- /dev/null +++ b/ops/modules/teleirc.nix @@ -0,0 +1,40 @@ +# Run the Telegram<>IRC sync bot for the Volga Sprint channel. +# +# This module is written in a pretty ad-hoc style, as it is sort of a +# throwaway thing (will be removed again after the event). +{ depot, config, lib, pkgs, ... }: + +let + cfg = config.services.depot.owothia; + description = "IRC<>Telegram sync for Volga Sprint channel"; + configFile = builtins.toFile "teleirc.env" '' + # connect through tvlbot's ZNC bouncer + IRC_SERVER="localhost" + IRC_PORT=2627 + IRC_USE_SSL=false + IRC_CHANNEL="#volgasprint" + IRC_BLACKLIST="tvlbot" + IRC_BOT_NAME="tvlbot" + IRC_BOT_REALNAME="TVL bot for Volga Sprint" + IRC_BOT_IDENT="tvlbot" + IRC_SEND_STICKER_EMOJI=false # look into this + TELEGRAM_CHAT_ID=-1002153072030 + ''; +in +{ + options.services.depot.teleirc.enable = lib.mkEnableOption description; + + config = lib.mkIf cfg.enable { + systemd.services.teleirc = { + inherit description; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + DynamicUser = true; + Restart = "always"; + EnvironmentFile = "/run/agenix/teleirc"; + ExecStart = "${depot.third_party.teleirc}/bin/teleirc -conf ${configFile}"; + }; + }; + }; +} diff --git a/ops/modules/tvl-headscale.nix b/ops/modules/tvl-headscale.nix index a07021c78861..6e805e4ac728 100644 --- a/ops/modules/tvl-headscale.nix +++ b/ops/modules/tvl-headscale.nix @@ -22,11 +22,7 @@ settings = { server_url = "https://net.tvl.fyi"; - dns_config.nameservers = [ - "8.8.8.8" - "1.1.1.1" - "77.88.8.8" - ]; + dns.magic_dns = false; # TLS is handled by nginx tls_cert_path = null; diff --git a/ops/modules/www/cache.tvl.su.nix b/ops/modules/www/cache.tvl.su.nix index 99bc008cd6a5..27d1c06dd3a7 100644 --- a/ops/modules/www/cache.tvl.su.nix +++ b/ops/modules/www/cache.tvl.su.nix @@ -17,13 +17,8 @@ alias /run/agenix/nix-cache-pub; } - location = /nix-cache-info { - add_header Content-Type text/plain; - return 200 "StoreDir: /nix/store\nWantMassQuery: 1\nPriority: 50\n"; - } - location / { - proxy_pass http://localhost:${toString config.services.nix-serve.port}; + proxy_pass http://${config.services.depot.harmonia.settings.bind}; } ''; }; diff --git a/ops/modules/www/cs.tvl.fyi.nix b/ops/modules/www/cs.tvl.fyi.nix index fac814baf064..9555acf9ac47 100644 --- a/ops/modules/www/cs.tvl.fyi.nix +++ b/ops/modules/www/cs.tvl.fyi.nix @@ -1,3 +1,5 @@ +# This configuration redirects from the previous Sourcegraph instance to +# livegrep/cgit where appropriate. { config, ... }: { @@ -13,17 +15,50 @@ forceSSL = true; extraConfig = '' - location = / { - return 301 https://cs.tvl.fyi/depot; + set $lineno ""; + + # depot root + location = /depot { + return 301 https://code.tvl.fyi/tree/; } - location / { - proxy_set_header X-Sg-Auth "Anonymous"; - proxy_pass http://localhost:${toString config.services.depot.sourcegraph.port}; + # folder/file on canon + location ~ ^/depot/-/(blob|tree)/([^\s]*)$ { + set $path $2; + if ($args ~ ^L(\d+)(-\d+)?$) { + set $lineno "#n$1"; + } + + return 302 https://code.tvl.fyi/tree/$path$lineno; + } + + # folder/file on specific commit + location ~ ^/depot@([a-f0-9]+)/-/(blob|tree)/([^\s]*)$ { + set $commit $1; + set $path $3; + + if ($args ~ ^L(\d+)(-\d+)?$) { + set $lineno "#n$1"; + } + + return 302 https://code.tvl.fyi/tree/$path?id=$commit$lineno; + } + + # commit info + location ~ ^/depot/-/commit/([a-f0-9]+)$ { + set $commit $1; + return 302 https://code.tvl.fyi/commit/?id=$commit; } - location /users/Anonymous/settings { - return 301 https://cs.tvl.fyi; + # search handler + # This only redirects to the new search, it doesn't try to parse and + # rewrite the query. + location /search { + return 302 https://grep.tvl.fyi/search; + } + + location / { + return 404 "TVL code search has moved to grep.tvl.fyi and we could not figure out how to rewrite your query. Sorry!"; } ''; }; diff --git a/ops/modules/www/tazj.in.nix b/ops/modules/www/tazj.in.nix deleted file mode 100644 index ea3cf1dc44ab..000000000000 --- a/ops/modules/www/tazj.in.nix +++ /dev/null @@ -1,54 +0,0 @@ -# serve tazjin's website & blog -{ depot, config, lib, pkgs, ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts."tazj.in" = { - enableACME = true; - forceSSL = true; - root = depot.users.tazjin.homepage; - serverAliases = [ "www.tazj.in" ]; - - extraConfig = '' - location = /en/rss.xml { - return 301 https://tazj.in/feed.atom; - } - - ${depot.users.tazjin.blog.oldRedirects} - location /blog/ { - alias ${depot.users.tazjin.blog.rendered}/; - - if ($request_uri ~ ^/(.*)\.html$) { - return 302 /$1; - } - - try_files $uri $uri.html $uri/ =404; - } - - location = /predlozhnik { - return 302 https://predlozhnik.ru; - } - - # redirect for easier entry on a TV - location = /tv { - return 302 https://tazj.in/blobs/play.html - } - - # Temporary place for serving static files. - location /blobs/ { - alias /var/lib/tazjins-blobs/; - } - ''; - }; - - services.nginx.virtualHosts."git.tazj.in" = { - enableACME = true; - forceSSL = true; - extraConfig = "return 301 https://code.tvl.fyi$request_uri;"; - }; - }; -} diff --git a/ops/pipelines/static-pipeline.yaml b/ops/pipelines/static-pipeline.yaml index af4f9d784e60..090518423eb3 100644 --- a/ops/pipelines/static-pipeline.yaml +++ b/ops/pipelines/static-pipeline.yaml @@ -50,7 +50,7 @@ steps: - label: ":llama:" key: "pipeline-gen" concurrency_group: 'depot-nix-eval' - concurrency: 5 # much more than this and whitby will OOM + concurrency: 3 # much more than this and whitby will OOM command: | set -ue @@ -88,10 +88,12 @@ steps: continue_on_failure: true # Exit with success or failure depending on whether any other steps - # failed. + # failed (but not retried). # # This information is checked by querying the Buildkite GraphQL API - # and fetching the count of failed steps. + # and fetching all failed steps, then filtering out the ones that were + # retried (retried jobs create new jobs, which would also show up in the + # query). # # This step must be :duck: (yes, really!) because the post-command # hook will inspect this name. @@ -109,8 +111,8 @@ steps: readonly FAILED_JOBS=$(curl 'https://graphql.buildkite.com/v1' \ --silent \ -H "Authorization: Bearer $(cat ${BUILDKITE_TOKEN_PATH})" \ - -d "{\"query\": \"query BuildStatusQuery { build(uuid: \\\"$BUILDKITE_BUILD_ID\\\") { jobs(passed: false) { count } } }\"}" | \ - jq -r '.data.build.jobs.count') + -d "{\"query\": \"query BuildStatusQuery { build(uuid: \\\"$BUILDKITE_BUILD_ID\\\") { jobs(passed: false, first: 500 ) { edges { node { ... on JobTypeCommand { retried } } } } } }\"}" | \ + jq -r '.data.build.jobs.edges | map(select(.node.retried == false)) | length') echo "$$FAILED_JOBS build jobs failed." diff --git a/ops/secrets/secrets.nix b/ops/secrets/secrets.nix index 5cbf2bf612a2..bc32d23597dd 100644 --- a/ops/secrets/secrets.nix +++ b/ops/secrets/secrets.nix @@ -9,6 +9,12 @@ let # zamalek "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDBRXeb8EuecLHP0bW4zuebXp4KRnXgJTZfeVWXQ1n1R" + + # khamovnik + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID1ptE5HvGSXxSXo+aHBTKa5PBlAM1HqmpzWz0yAhHLj" + + # arbat + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ1Eai0p7eF7XML5wokqF4GlVZM+YXEORfs/GPGwEky7" ]; aspen = [ @@ -47,6 +53,7 @@ in "owothia.age" = whitbyDefault; "panettone.age" = whitbyDefault; "smtprelay.age" = whitbyDefault; + "teleirc.age" = whitbyDefault; "tf-buildkite.age" = terraform; "tf-glesys.age" = terraform; "tf-keycloak.age" = terraform; diff --git a/ops/secrets/teleirc.age b/ops/secrets/teleirc.age new file mode 100644 index 000000000000..ebc88fc9ef1d --- /dev/null +++ b/ops/secrets/teleirc.age Binary files differdiff --git a/ops/secrets/tf-keycloak.age b/ops/secrets/tf-keycloak.age index 237b9377bd79..7d470a6a304e 100644 --- a/ops/secrets/tf-keycloak.age +++ b/ops/secrets/tf-keycloak.age Binary files differdiff --git a/ops/terraform/deploy-nixos/README.md b/ops/terraform/deploy-nixos/README.md index fd0bd1b4423a..2580a7c0e102 100644 --- a/ops/terraform/deploy-nixos/README.md +++ b/ops/terraform/deploy-nixos/README.md @@ -25,8 +25,17 @@ deploy is necessary. ```terraform module "deploy_somehost" { + # Clone just this directory through josh. Add a `ref=` parameter to pin to a specific commit. source = "git::https://code.tvl.fyi/depot.git:/ops/terraform/deploy-nixos.git" + + # The attribute.path pointing to the expression to instantiate. attrpath = "ops.nixos.somehost" + + # The path to the Nix file to invoke. Optional. + # If omitted, will shell out to git to determine the repo root, and Nix will + # use `default.nix` in there. + entrypoint = "${path.module}/../../somewhere.nix" + target_host = "somehost.tvl.su" target_user = "someone" target_user_ssh_key = tls_private_key.somehost.private_key_pem @@ -37,9 +46,6 @@ module "deploy_somehost" { Several things can be improved about this module, for example: -* The repository root (relative to which the attribute path is evaluated) could - be made configurable. - * The remote system closure could be discovered to restore remote system state after manual deploys on the target (i.e. "stomping" of changes). diff --git a/ops/users/default.nix b/ops/users/default.nix index c54a681dce17..a94f355e0f68 100644 --- a/ops/users/default.nix +++ b/ops/users/default.nix @@ -22,6 +22,16 @@ password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$5NEYPJ19nDITK5sGr4bzhQ$Xzpzth6y4w+HGvioHiYgzqFiwMDx0B7HAh+PVbkRuuk"; } { + username = "azahi"; + email = "azat@bahawi.net"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$BVRzgfs8YIorOTq62B00CQ$5UXHyG/Ivn5TqB7UNgfjYJMxTjun3NDvAStWFom4oas"; + } + { + username = "chickadee"; + email = "matthewktromp@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$HoZjVdJ90JmTEJf1MMLuDg$5Pa8kpJdFVsIxgoOTDsH0gv6CLumSIkMqYEn5UVfjwU"; + } + { username = "cschilling"; email = "christian.schilling.de@gmail.com"; password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$9VN3IS6ViW5FFbVKWOZI6Q$gZxuYAYk0Opq4E5i8cbcNjfznCQNc+RiP7Xv1CUnrQU"; @@ -32,11 +42,21 @@ password = "{ARGON2}$argon2id$v=19$m=65536,t=4,p=1$TxjbMGenhEmkyYLrg5uGhbr60THB86YeRZg5bPdiTJo$k9gbRlAPjmxwdUwzbavvsAVkckgQZ0jS2oTtvZBPysk"; } { + username = "domenkozar"; + email = "domen@cachix.org"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$c9WgMrTqPJZenOr5+wlnnQ$XOpRZRTkduzP2+NJBxkg2jhffurg7PDla4/RoAyclwI"; + } + { username = "edef"; email = "edef@edef.eu"; password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$OORx4ERbkgvTmuYCJA8cIw$i5qaBzHkRVw7Tl+wZsTFTDqJwF0vuZqhW3VpknMYMc0"; } { + username = "elle"; + email = "lnajt4@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$b5Bfq6u+fEKbtpixOl+yPw$nCyTLbSDYsw30ZiSxhJ6N99IIPQAnS2XRNlpEx9os+0"; + } + { username = "ericvolp12"; email = "ericvolp12@gmail.com"; password = "{SSHA}pSepaQ+/5KBLfJtRR5rfxGU8goAsXgvk"; @@ -107,6 +127,16 @@ password = "{SSHA}7a85VNhpFElFw+N5xcjgGmt4HnBsaGp4"; } { + username = "marijan"; + email = "marijan.petricevic94@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$KG+6Kx+qi5FA4JmBgIOBDA$bQm9u/9A5VbpVmNuMDqJa+iDCU0JCyboevQ3eEzlMdE"; + } + { + username = "mrflos"; + email = "mrflos@yeswiki.pro"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$/D1y+6n3+0GigG9mCMqK8A$9PseWm3+QATxN/M3Wu4JM+CnIppLD/LbQaVEKLItv9o"; + } + { username = "noteed"; email = "noteed@gmail.com"; password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$rcLfF9xXysSx5sahVQLiMA$EgRgAVXn8+r2Csa3XgIHIEBf3hX4Y58pOHf2eDaBUnA"; @@ -149,6 +179,11 @@ password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$wOPEl9D3kSke//oLtbvqrg$j0npwwXgaXQ/emefKUwL59tH8hdmtzbgH2rQzWSmE2Y"; } { + username = "yl3dy"; + email = "aleksandr.kiselyov@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$vPvOa0/7RzDLuD/icQuIzQ$IVMSI7hh/frihuL11sNRj6Jz8TTn1wZZHjZZGszz3pI"; + } + { username = "implr"; email = "implr@hackerspace.pl"; password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$SHRFps5sVgyUXYdmqGPw9g$tEx9DwKK1RjWlw52GLwOZ/iHep+QJboaZE83f1pXSwQ"; @@ -229,4 +264,49 @@ email = "tvl@alice-carroll.pet"; password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$mt/0RzKw4RHxm7ybpMHP5Q$P/SDBMv5si9D98NFO/eZgh2+InlByqYxqAvQWhl+p0c"; } + { + username = "yuka"; + email = "tvl@yuka.dev"; + password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$aEyiAIuynQMwfY7xE+pMxg$QdghylHO2JZMR/YyYf4UAnhhb/gBdAkoDeANEwdixxU"; + } + { + username = "benjaminedwardwebb"; + email = "benjaminedwardwebb@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$kdFNmxgIGsF8TkB/GoPy1A$GUXd3M35Jqxqlfra4gPCcFW3ehE0RVrlHOzaoD7Pu7s"; + } + { + username = "fmzakari"; + email = "farid.m.zakaria@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$NzSX6x2+mApMvhNrvVIWaQ$/GUwbj+6GUyJL8XSgxTThc3TmVTM4WLQ+6KMC4NwovE"; + } + { + username = "toastal"; + email = "toastal@posteo.net"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$txwVjPn9kKPUgsZnPtpyaA$pE0ISDGScCE4JCKcmbnzC+GZZ4PP6MqKJKmR/sxo6TY"; + } + { + username = "sinavir"; + email = "tvix@sinavir.fr"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$5GXvoN/enVljV97yE/Zasg$OrgY9/ge2LoxNm9OOqxh/kKLxoAvU54MbQa9WWiT0jY"; + } + { + username = "emery"; + email = "emery@dmz.rs"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$b2k5UpTJafqM7yjHfVRjBg$zFGy/ZeI9Hb71TUfJwFp7qDKyUl8tdyFDUK1uNBYfUI"; + } + { + username = "aziz"; + email = "abd.aziz89@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$xTvdtTF+gavMfF8556CiiQ$IshnauhlEr80skpv5s6ueJLkQxlynzBt6oCp3cQrNCY"; + } + { + username = "nikiv"; + email = "nikita@nikiv.dev"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$79mMAD2XYa5dg7D9ueWMpw$Edf5WODrFpkNDyWaMdLKcgcErFLx4khmPIk8wzmYGUE"; + } + { + username = "ein-shved"; + email = "mestofel13@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$D4wzfJoyFye48QNdrC66VA$aBJ/ZaL+rTgXoQa/nFdpHap3G/Oju8WlHaWTii95X8E"; + } ] diff --git a/third_party/cgit/default.nix b/third_party/cgit/default.nix index c783bda16ed2..bac6a3264e6e 100644 --- a/third_party/cgit/default.nix +++ b/third_party/cgit/default.nix @@ -27,12 +27,25 @@ stdenv.mkDerivation rec { # # TODO(tazjin): Add an assert for this somewhere so we notice it on # channel bumps. - preBuild = '' - rm -rf git # remove submodule dir ... - cp -r --no-preserve=ownership,mode ${pkgs.srcOnly depot.third_party.git} git - makeFlagsArray+=(prefix="$out" CGIT_SCRIPT_PATH="$out/cgit/") - cat tvl-extra.css >> cgit.css - ''; + preBuild = + let + # we have to give cgit a git with dottime support to build + git' = pkgs.git.overrideAttrs (old: { + src = pkgs.fetchurl { + url = "https://github.com/git/git/archive/refs/tags/v2.44.2.tar.gz"; + hash = "sha256-3h0LBfAD4MXfZc0tjWQDO81UdbRo3w5C0W7j7rr9m9I="; + }; + patches = (old.patches or [ ]) ++ [ + ../git/0001-feat-third_party-git-date-add-dottime-format.patch + ]; + }); + in + '' + rm -rf git # remove submodule dir ... + cp -r --no-preserve=ownership,mode ${pkgs.srcOnly git'} git + makeFlagsArray+=(prefix="$out" CGIT_SCRIPT_PATH="$out/cgit/") + cat tvl-extra.css >> cgit.css + ''; stripDebugList = [ "cgit" ]; diff --git a/third_party/chicago95/default.nix b/third_party/chicago95/default.nix new file mode 100644 index 000000000000..8703ec3548ad --- /dev/null +++ b/third_party/chicago95/default.nix @@ -0,0 +1,47 @@ +# A rendition of everyone's favourite computer theme. +{ pkgs, ... }: + +let + # Chicago95 has no GTK-4 theme (because GTK-4 removed important features that + # it needs), but there is a project with an approximation. + # + # This is a bit of a hack, but I inject that project's GTK-4 theme as if it + # was a part of Chicago95. + # + # This other project is GPL-3.0, under which Chicago95 is also distributed. + gtk4ProjectSrc = pkgs.fetchFromGitHub { + owner = "B00merang-Project"; + repo = "Windows-95"; + rev = "055abd7a3608afdcb2ef021732e07020f2b416b2"; + hash = "sha256:1li6wzyn3y09d188xki1h96pmn4xcx2lklfc4rkiq2y2r22wx7kz"; + }; +in +pkgs.stdenvNoCC.mkDerivation { + pname = "Chicago95"; + version = "master"; + + src = pkgs.fetchFromGitHub { + owner = "grassmunk"; + repo = "Chicago95"; + rev = "bdf5cf36a16102aaac297f3de887c601c2b1146f"; + hash = "sha256:11fsy3bam1rhp1292zflvzmf1432z1p0ncwy3601wl2f8rnvfdfm"; + }; + + # The project has a Makefile, but it's broken in all sorts of ways, so we just + # copy the important stuff manually. + dontBuild = true; + installPhase = '' + mkdir -p $out/share/{icons,fonts,themes,sounds,qt5ct/colors} + + cp -r Theme/Chicago95 $out/share/themes + cp -r Icons/* $out/share/icons + cp -r Cursors/* $out/share/icons + cp -r Fonts/* $out/share/fonts + cp Extras/Chicago95_qt.conf $out/share/qt5ct/colors + + cp -r ${gtk4ProjectSrc}/gtk-4.0 $out/share/themes/Chicago95 + ''; + + meta.license = pkgs.lib.licenses.gpl3; +} + diff --git a/third_party/ddclient/default.nix b/third_party/ddclient/default.nix deleted file mode 100644 index 28b036ea66fc..000000000000 --- a/third_party/ddclient/default.nix +++ /dev/null @@ -1,12 +0,0 @@ -# Users of this package & module should replace it with something like -# inadyn, after https://github.com/NixOS/nixpkgs/issues/242330 is -# landed. -# -# TODO(aspen): replace ddclient with inadyn or something else. -{ pkgs, ... }: - -(pkgs.callPackage ./pkg.nix { }).overrideAttrs (old: { - passthru = old.passthru // { - module = ./module.nix; - }; -}) diff --git a/third_party/ddclient/module.nix b/third_party/ddclient/module.nix deleted file mode 100644 index c8d68f9be932..000000000000 --- a/third_party/ddclient/module.nix +++ /dev/null @@ -1,230 +0,0 @@ -# SPDX-License-Identifier: MIT -# SPDX-FileCopyrightText: Copyright (c) 2003-2023 The Nixpkgs/NixOS contributors -{ config, pkgs, lib, ... }: - -let - cfg = config.services.deprecated-ddclient; - boolToStr = bool: if bool then "yes" else "no"; - dataDir = "/var/lib/ddclient"; - StateDirectory = builtins.baseNameOf dataDir; - RuntimeDirectory = StateDirectory; - - configFile' = pkgs.writeText "ddclient.conf" '' - # This file can be used as a template for configFile or is automatically generated by Nix options. - cache=${dataDir}/ddclient.cache - foreground=YES - use=${cfg.use} - login=${cfg.username} - password=${if cfg.protocol == "nsupdate" then "/run/${RuntimeDirectory}/ddclient.key" else "@password_placeholder@"} - protocol=${cfg.protocol} - ${lib.optionalString (cfg.script != "") "script=${cfg.script}"} - ${lib.optionalString (cfg.server != "") "server=${cfg.server}"} - ${lib.optionalString (cfg.zone != "") "zone=${cfg.zone}"} - ssl=${boolToStr cfg.ssl} - wildcard=YES - quiet=${boolToStr cfg.quiet} - verbose=${boolToStr cfg.verbose} - ${cfg.extraConfig} - ${lib.concatStringsSep "," cfg.domains} - ''; - configFile = if (cfg.configFile != null) then cfg.configFile else configFile'; - - preStart = '' - install --mode=600 --owner=$USER ${configFile} /run/${RuntimeDirectory}/ddclient.conf - ${lib.optionalString (cfg.configFile == null) (if (cfg.protocol == "nsupdate") then '' - install --mode=600 --owner=$USER ${cfg.passwordFile} /run/${RuntimeDirectory}/ddclient.key - '' else if (cfg.passwordFile != null) then '' - "${pkgs.replace-secret}/bin/replace-secret" "@password_placeholder@" "${cfg.passwordFile}" "/run/${RuntimeDirectory}/ddclient.conf" - '' else '' - sed -i '/^password=@password_placeholder@$/d' /run/${RuntimeDirectory}/ddclient.conf - '')} - ''; - -in - -with lib; - -{ - ###### interface - - options = { - - services.deprecated-ddclient = with lib.types; { - - enable = mkOption { - default = false; - type = bool; - description = lib.mdDoc '' - Whether to synchronise your machine's IP address with a dynamic DNS provider (e.g. dyndns.org). - ''; - }; - - package = mkOption { - type = package; - default = pkgs.ddclient; - defaultText = lib.literalExpression "pkgs.ddclient"; - description = lib.mdDoc '' - The ddclient executable package run by the service. - ''; - }; - - domains = mkOption { - default = [ "" ]; - type = listOf str; - description = lib.mdDoc '' - Domain name(s) to synchronize. - ''; - }; - - username = mkOption { - # For `nsupdate` username contains the path to the nsupdate executable - default = lib.optionalString (cfg.protocol == "nsupdate") "${pkgs.bind.dnsutils}/bin/nsupdate"; - defaultText = ""; - type = str; - description = lib.mdDoc '' - User name. - ''; - }; - - passwordFile = mkOption { - default = null; - type = nullOr str; - description = lib.mdDoc '' - A file containing the password or a TSIG key in named format when using the nsupdate protocol. - ''; - }; - - interval = mkOption { - default = "10min"; - type = str; - description = lib.mdDoc '' - The interval at which to run the check and update. - See {command}`man 7 systemd.time` for the format. - ''; - }; - - configFile = mkOption { - default = null; - type = nullOr path; - description = lib.mdDoc '' - Path to configuration file. - When set this overrides the generated configuration from module options. - ''; - example = "/root/nixos/secrets/ddclient.conf"; - }; - - protocol = mkOption { - default = "dyndns2"; - type = str; - description = lib.mdDoc '' - Protocol to use with dynamic DNS provider (see https://sourceforge.net/p/ddclient/wiki/protocols). - ''; - }; - - server = mkOption { - default = ""; - type = str; - description = lib.mdDoc '' - Server address. - ''; - }; - - ssl = mkOption { - default = true; - type = bool; - description = lib.mdDoc '' - Whether to use SSL/TLS to connect to dynamic DNS provider. - ''; - }; - - quiet = mkOption { - default = false; - type = bool; - description = lib.mdDoc '' - Print no messages for unnecessary updates. - ''; - }; - - script = mkOption { - default = ""; - type = str; - description = lib.mdDoc '' - script as required by some providers. - ''; - }; - - use = mkOption { - default = "web, web=checkip.dyndns.com/, web-skip='Current IP Address: '"; - type = str; - description = lib.mdDoc '' - Method to determine the IP address to send to the dynamic DNS provider. - ''; - }; - - verbose = mkOption { - default = false; - type = bool; - description = lib.mdDoc '' - Print verbose information. - ''; - }; - - zone = mkOption { - default = ""; - type = str; - description = lib.mdDoc '' - zone as required by some providers. - ''; - }; - - extraConfig = mkOption { - default = ""; - type = lines; - description = lib.mdDoc '' - Extra configuration. Contents will be added verbatim to the configuration file. - ::: {.note} - `daemon` should not be added here because it does not work great with the systemd-timer approach the service uses. - ::: - ''; - }; - }; - }; - - - ###### implementation - - config = mkMerge [ - (mkIf cfg.enable { - systemd.services.ddclient = { - description = "Dynamic DNS Client"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - restartTriggers = optional (cfg.configFile != null) cfg.configFile; - path = lib.optional (lib.hasPrefix "if," cfg.use) pkgs.iproute2; - - serviceConfig = { - DynamicUser = true; - RuntimeDirectoryMode = "0700"; - inherit RuntimeDirectory; - inherit StateDirectory; - Type = "oneshot"; - ExecStartPre = "!${pkgs.writeShellScript "ddclient-prestart" preStart}"; - ExecStart = "${lib.getBin cfg.package}/bin/ddclient -file /run/${RuntimeDirectory}/ddclient.conf"; - }; - }; - - systemd.timers.ddclient = { - description = "Run ddclient"; - wantedBy = [ "timers.target" ]; - timerConfig = { - OnBootSec = cfg.interval; - OnUnitInactiveSec = cfg.interval; - }; - }; - }) - { - ids.uids.ddclient = 30; - ids.gids.ddclient = 30; - } - ]; -} diff --git a/third_party/ddclient/pkg.nix b/third_party/ddclient/pkg.nix deleted file mode 100644 index 586f3891ac96..000000000000 --- a/third_party/ddclient/pkg.nix +++ /dev/null @@ -1,45 +0,0 @@ -# SPDX-License-Identifier: MIT -# SPDX-FileCopyrightText: Copyright (c) 2003-2023 The Nixpkgs/NixOS contributors -{ lib, fetchFromGitHub, perlPackages, autoreconfHook, iproute2, perl }: - -perlPackages.buildPerlPackage rec { - pname = "ddclient"; - version = "3.10.0"; - - outputs = [ "out" ]; - - src = fetchFromGitHub { - owner = "ddclient"; - repo = "ddclient"; - rev = "v${version}"; - sha256 = "sha256-wWUkjXwVNZRJR1rXPn3IkDRi9is9vsRuNC/zq8RpB1E="; - }; - - postPatch = '' - touch Makefile.PL - ''; - - nativeBuildInputs = [ autoreconfHook ]; - - buildInputs = with perlPackages; [ IOSocketINET6 IOSocketSSL JSONPP ]; - - installPhase = '' - runHook preInstall - # patch sheebang ddclient script which only exists after buildPhase - preConfigure - install -Dm755 ddclient $out/bin/ddclient - install -Dm644 -t $out/share/doc/ddclient COP* README.* ChangeLog.md - runHook postInstall - ''; - - # TODO: run upstream tests - doCheck = false; - - meta = with lib; { - description = "Client for updating dynamic DNS service entries"; - homepage = "https://ddclient.net/"; - license = licenses.gpl2Plus; - platforms = platforms.linux; - maintainers = with maintainers; [ SuperSandro2000 ]; - }; -} diff --git a/third_party/exwm/exwm-core.el b/third_party/exwm/exwm-core.el index e0d644d941ed..a7fdfce71097 100644 --- a/third_party/exwm/exwm-core.el +++ b/third_party/exwm/exwm-core.el @@ -82,6 +82,7 @@ Here are some predefined candidates: (defvar exwm-input--simulation-keys) (defvar exwm-input-line-mode-passthrough) (defvar exwm-input-prefix-keys) +(defvar exwm-workspace--list) (declare-function exwm-input--fake-key "exwm-input.el" (event)) (declare-function exwm-input--on-KeyPress-line-mode "exwm-input.el" (key-press raw-data)) @@ -94,6 +95,8 @@ Here are some predefined candidates: (declare-function exwm-manage--kill-buffer-query-function "exwm-manage.el") (declare-function exwm-workspace-move-window "exwm-workspace.el" (frame-or-index &optional id)) +(declare-function exwm-workspace-switch "exwm-workspace.el" + (frame-or-index &optional force)) (define-minor-mode exwm-debug "Debug-logging enabled if non-nil." @@ -229,6 +232,14 @@ If CONN is non-nil, use it instead of the value of the variable (setq ret-depth depth)) (list ret-visual ret-depth ret-colormap))) +(defun exwm--mode-name () + "Mode name string used in `exwm-mode' buffers." + (let ((name "EXWM")) + (if (cl-some (lambda (i) (frame-parameter i 'exwm-urgency)) + exwm-workspace--list) + (propertize name 'face 'font-lock-warning-face) + name))) + ;; Internal variables (defvar-local exwm--id nil) ;window ID (defvar-local exwm--configurations nil) ;initial configurations. @@ -311,7 +322,7 @@ One of `line-mode' or `char-mode'.") ;; Also, inactive entries should be disabled rather than hidden. (easy-menu-define exwm-mode-menu exwm-mode-map "Menu for `exwm-mode'." - '("EXWM" + `("EXWM" "---" "*General*" "---" @@ -336,22 +347,20 @@ One of `line-mode' or `char-mode'.") ["Send key" exwm-input-send-next-key (eq exwm--input-mode 'line-mode)] ;; This is merely a reference. ("Send simulation key" :filter - (lambda (&rest _args) - (let (result) - (maphash - (lambda (key value) - (when (sequencep key) - (setq result (append result - `([ - ,(format "Send '%s'" - (key-description value)) - (lambda () - (interactive) - (dolist (i ',value) - (exwm-input--fake-key i))) - :keys ,(key-description key)]))))) - exwm-input--simulation-keys) - result))) + ,(lambda (&rest _args) + (let (result) + (maphash + (lambda (key value) + (when (sequencep key) + (setq result (append result + `([,(format "Send '%s'" + (key-description value)) + ,(lambda () + (interactive) + (mapc #'exwm-input--fake-key value)) + :keys ,(key-description key)]))))) + exwm-input--simulation-keys) + result))) ["Define global binding" exwm-input-set-key] @@ -368,26 +377,20 @@ One of `line-mode' or `char-mode'.") ["Switch workspace" exwm-workspace-switch] ;; Place this entry at bottom to avoid selecting others by accident. ("Switch to" :filter - (lambda (&rest _args) - (mapcar (lambda (i) - `[,(format "Workspace %d" i) - (lambda () - (interactive) - (exwm-workspace-switch ,i)) - (/= ,i exwm-workspace-current-index)]) - (number-sequence 0 (1- (exwm-workspace--count)))))))) + ,(lambda (&rest _args) + (mapcar (lambda (i) + `[,(format "Workspace %d" i) + ,(lambda () + (interactive) + (exwm-workspace-switch i)) + (/= ,i exwm-workspace-current-index)]) + (number-sequence 0 (1- (length exwm-workspace--list)))))))) (define-derived-mode exwm-mode nil "EXWM" "Major mode for managing X windows. \\{exwm-mode-map}" - ;; - (setq mode-name - '(:eval (propertize "EXWM" 'face - (when (cl-some (lambda (i) - (frame-parameter i 'exwm-urgency)) - exwm-workspace--list) - 'font-lock-warning-face)))) + :interactive nil :abbrev-table nil :syntax-table nil ;; Change major-mode is not allowed (add-hook 'change-major-mode-hook #'kill-buffer nil t) ;; Kill buffer -> close window @@ -396,7 +399,8 @@ One of `line-mode' or `char-mode'.") ;; Redirect events when executing keyboard macros. (push `(executing-kbd-macro . ,exwm--kmacro-map) minor-mode-overriding-map-alist) - (setq buffer-read-only t + (setq mode-name '(:eval (exwm--mode-name)) + buffer-read-only t cursor-type nil left-margin-width nil right-margin-width nil diff --git a/third_party/exwm/exwm-floating.el b/third_party/exwm/exwm-floating.el index 34d06a30db09..574a78f01562 100644 --- a/third_party/exwm/exwm-floating.el +++ b/third_party/exwm/exwm-floating.el @@ -67,11 +67,11 @@ This hook runs in the context of the corresponding buffer." (defcustom exwm-floating-border-width 1 "Border width of floating windows." - :type '(integer - :validate (lambda (widget) - (when (< (widget-value widget) 0) - (widget-put widget :error "Border width is at least 0") - widget))) + :type `(integer + :validate ,(lambda (widget) + (when (< (widget-value widget) 0) + (widget-put widget :error "Border width is at least 0") + widget))) :initialize #'custom-initialize-default :set (lambda (symbol value) (let ((delta (- value exwm-floating-border-width)) diff --git a/third_party/exwm/exwm-input.el b/third_party/exwm/exwm-input.el index f1f035c91ad9..eac0ef6a374e 100644 --- a/third_party/exwm/exwm-input.el +++ b/third_party/exwm/exwm-input.el @@ -46,7 +46,7 @@ '(?\C-x ?\C-u ?\C-h ?\M-x ?\M-` ?\M-& ?\M-:) "List of prefix keys EXWM should forward to Emacs when in `line-mode'. -The point is to make keys like 'C-x C-f' forwarded to Emacs in `line-mode'. +The point is to make keys like `C-x C-f' forwarded to Emacs in `line-mode'. There is no need to add prefix keys for global/simulation keys or those defined in `exwm-mode-map' here." :type '(repeat key-sequence) diff --git a/third_party/exwm/exwm-layout.el b/third_party/exwm/exwm-layout.el index 8649c11ffd42..83421b2e9975 100644 --- a/third_party/exwm/exwm-layout.el +++ b/third_party/exwm/exwm-layout.el @@ -602,9 +602,7 @@ See also `exwm-layout-enlarge-window'." ;; Auto refresh layout (exwm--log) (add-hook 'window-configuration-change-hook #'exwm-layout--refresh) - ;; The behavior of `window-configuration-change-hook' will be changed. - (when (fboundp 'window-pixel-width-before-size-change) - (add-hook 'window-size-change-functions #'exwm-layout--refresh)) + (add-hook 'window-size-change-functions #'exwm-layout--refresh) (unless (exwm-workspace--minibuffer-own-frame-p) ;; Refresh when minibuffer grows (add-hook 'minibuffer-setup-hook #'exwm-layout--on-minibuffer-setup t) @@ -616,8 +614,7 @@ See also `exwm-layout-enlarge-window'." "Exit the layout module." (exwm--log) (remove-hook 'window-configuration-change-hook #'exwm-layout--refresh) - (when (fboundp 'window-pixel-width-before-size-change) - (remove-hook 'window-size-change-functions #'exwm-layout--refresh)) + (remove-hook 'window-size-change-functions #'exwm-layout--refresh) (remove-hook 'minibuffer-setup-hook #'exwm-layout--on-minibuffer-setup) (when exwm-layout--timer (cancel-timer exwm-layout--timer) diff --git a/third_party/exwm/exwm-systemtray.el b/third_party/exwm/exwm-systemtray.el index 9e57dae4ebb8..2b46568152b4 100644 --- a/third_party/exwm/exwm-systemtray.el +++ b/third_party/exwm/exwm-systemtray.el @@ -46,15 +46,6 @@ (visible :initarg :visible)) :documentation "Attributes of a system tray icon.") -(defclass xcb:systemtray:-ClientMessage - (xcb:icccm:--ClientMessage xcb:ClientMessage) - ((format :initform 32) - (type :initform 'xcb:Atom:MANAGER) - (time :initarg :time :type xcb:TIMESTAMP) ;new slot - (selection :initarg :selection :type xcb:ATOM) ;new slot - (owner :initarg :owner :type xcb:WINDOW)) ;new slot - :documentation "A systemtray client message.") - (defgroup exwm-systemtray nil "System tray." :group 'exwm) @@ -542,7 +533,7 @@ Argument DATA contains the raw event data." :destination exwm--root :event-mask xcb:EventMask:StructureNotify :event (xcb:marshal - (make-instance 'xcb:systemtray:-ClientMessage + (make-instance 'xcb:icccm:-ManagerSelection :window exwm--root :time xcb:Time:CurrentTime :selection diff --git a/third_party/exwm/exwm-workspace.el b/third_party/exwm/exwm-workspace.el index 89be6971598c..9337dc08ab8e 100644 --- a/third_party/exwm/exwm-workspace.el +++ b/third_party/exwm/exwm-workspace.el @@ -1257,12 +1257,10 @@ ALIST is an action alist, as accepted by function `display-buffer'." ;; fail to retrieve the correct window. It's likely there are ;; other related issues. ;; This is not required by Emacs 24. - (when (fboundp 'window-preserve-size) - (let ((window (get-buffer-window "*Completions*" - exwm-workspace--current))) - (when window - (fit-window-to-buffer window) - (window-preserve-size window))))) + (let ((window (get-buffer-window "*Completions*" exwm-workspace--current))) + (when window + (fit-window-to-buffer window) + (window-preserve-size window)))) (defun exwm-workspace--on-minibuffer-exit () "Run in `minibuffer-exit-hook' to hide the minibuffer container." diff --git a/third_party/exwm/exwm-xsettings.el b/third_party/exwm/exwm-xsettings.el index 99d6b9c4ac87..596588b8237c 100644 --- a/third_party/exwm/exwm-xsettings.el +++ b/third_party/exwm/exwm-xsettings.el @@ -293,7 +293,7 @@ SERIAL is a sequence number." :destination exwm--root :event-mask xcb:EventMask:StructureNotify :event (xcb:marshal - (make-instance 'xcb:xsettings:-ClientMessage + (make-instance 'xcb:icccm:-ManagerSelection :window exwm--root :time xcb:Time:CurrentTime :selection exwm-xsettings--XSETTINGS_S0-atom diff --git a/third_party/exwm/exwm.el b/third_party/exwm/exwm.el index c4900eab48ca..1186a40f441d 100644 --- a/third_party/exwm/exwm.el +++ b/third_party/exwm/exwm.el @@ -4,8 +4,8 @@ ;; Author: Chris Feng <chris.w.feng@gmail.com> ;; Maintainer: Adrián Medraño Calvo <adrian@medranocalvo.com>, Steven Allen <steven@stebalien.com>, Daniel Mendler <mail@daniel-mendler.de> -;; Version: 0.28 -;; Package-Requires: ((emacs "27.1") (xelb "0.18")) +;; Version: 0.30 +;; Package-Requires: ((emacs "27.1") (xelb "0.19")) ;; Keywords: unix ;; URL: https://github.com/emacs-exwm/exwm @@ -493,23 +493,20 @@ RAW-DATA contains unmarshalled ClientMessage event data." ;; _NET_ACTIVE_WINDOW. ((= type xcb:Atom:_NET_ACTIVE_WINDOW) (let ((buffer (exwm--id->buffer id)) - iconic window) + window) (if (buffer-live-p buffer) ;; Either an `exwm-mode' buffer (an X window) or a floating frame. (with-current-buffer buffer (when (eq exwm--frame exwm-workspace--current) (if exwm--floating-frame (select-frame exwm--floating-frame) - (setq iconic (exwm-layout--iconic-state-p)) - (when iconic + (setq window (get-buffer-window nil t)) + (unless window ;; State change: iconic => normal. - (set-window-buffer (frame-selected-window exwm--frame) - (current-buffer))) + (setq window (frame-selected-window exwm--frame)) + (set-window-buffer window (current-buffer))) ;; Focus transfer. - (setq window (get-buffer-window nil t)) - (when (or iconic - (not (eq window (selected-window)))) - (select-window window))))) + (select-window window)))) ;; A workspace. (dolist (f exwm-workspace--list) (when (eq id (frame-parameter f 'exwm-outer-id)) diff --git a/third_party/geesefs/default.nix b/third_party/geesefs/default.nix deleted file mode 100644 index 98448bb737c6..000000000000 --- a/third_party/geesefs/default.nix +++ /dev/null @@ -1,25 +0,0 @@ -# Finally, a good FUSE FS implementation over S3. -# https://github.com/yandex-cloud/geesefs - -{ pkgs, ... }: - -pkgs.buildGoModule rec { - pname = "geesefs"; - version = "0.40.1"; - - src = pkgs.fetchFromGitHub { - owner = "yandex-cloud"; - repo = "geesefs"; - rev = "v${version}"; - hash = "sha256:0ig8h17z8n5j8qb7k2jyh40vv77zazhnz8bxdam9xihxksj8mizp"; - }; - - subPackages = [ "." ]; - buildInputs = [ pkgs.fuse ]; - vendorHash = "sha256:11i7cmnlxi00d0csgpv8drfcw0aqshwc4hfs0jw7zwafdhnlyy0j"; - - meta = with pkgs.lib; { - license = licenses.asl20; - maintainers = [ maintainers.tazjin ]; - }; -} diff --git a/third_party/gerrit/0001-Syntax-highlight-nix.patch b/third_party/gerrit/0001-Syntax-highlight-nix.patch index bdc3fd3b5510..d17dc27db094 100644 --- a/third_party/gerrit/0001-Syntax-highlight-nix.patch +++ b/third_party/gerrit/0001-Syntax-highlight-nix.patch @@ -1,4 +1,4 @@ -From 084e4f92fb58f7cd85303ba602fb3c40133c8fcc Mon Sep 17 00:00:00 2001 +From 216843cff4a8e41ad9887118751a412c1a22ce72 Mon Sep 17 00:00:00 2001 From: Luke Granger-Brown <git@lukegb.com> Date: Thu, 2 Jul 2020 23:02:32 +0100 Subject: [PATCH 1/3] Syntax highlight nix @@ -9,23 +9,23 @@ Subject: [PATCH 1/3] Syntax highlight nix 2 files changed, 2 insertions(+) diff --git a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts -index a9f88bdd81..385249f280 100644 +index 50742903de..d1e89920cc 100644 --- a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts +++ b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts -@@ -93,6 +93,7 @@ const LANGUAGE_MAP = new Map<string, string>([ +@@ -98,6 +98,7 @@ const LANGUAGE_MAP = new Map<string, string>([ ['text/x-vhdl', 'vhdl'], ['text/x-yaml', 'yaml'], ['text/vbscript', 'vbscript'], + ['text/x-nix', 'nix'], ]); - const CLASS_PREFIX = 'gr-diff gr-syntax gr-syntax-'; + const CLASS_PREFIX = 'gr-syntax gr-syntax-'; diff --git a/resources/com/google/gerrit/server/mime/mime-types.properties b/resources/com/google/gerrit/server/mime/mime-types.properties -index 2f9561ba2e..739818ec05 100644 +index 642ef474a5..97f1ff835b 100644 --- a/resources/com/google/gerrit/server/mime/mime-types.properties +++ b/resources/com/google/gerrit/server/mime/mime-types.properties -@@ -149,6 +149,7 @@ mscin = text/x-mscgen - msgenny = text/x-msgenny +@@ -154,6 +154,7 @@ msgenny = text/x-msgenny + mts = application/typescript nb = text/x-mathematica nginx.conf = text/x-nginx-conf +nix = text/x-nix @@ -33,5 +33,5 @@ index 2f9561ba2e..739818ec05 100644 nsi = text/x-nsis nt = text/n-triples -- -2.37.3 +2.45.1 diff --git a/third_party/gerrit/0002-Syntax-highlight-rules.pl.patch b/third_party/gerrit/0002-Syntax-highlight-rules.pl.patch index 4b91e2c3541f..d0da61dd0f21 100644 --- a/third_party/gerrit/0002-Syntax-highlight-rules.pl.patch +++ b/third_party/gerrit/0002-Syntax-highlight-rules.pl.patch @@ -1,4 +1,4 @@ -From aedf8ac8fa5113843bcd83ff85e2d9f3bffdb16c Mon Sep 17 00:00:00 2001 +From 63f1ff6ea749ae2af29a53463bca81bc3f4bf25b Mon Sep 17 00:00:00 2001 From: Luke Granger-Brown <git@lukegb.com> Date: Thu, 2 Jul 2020 23:02:43 +0100 Subject: [PATCH 2/3] Syntax highlight rules.pl @@ -9,10 +9,10 @@ Subject: [PATCH 2/3] Syntax highlight rules.pl 2 files changed, 2 insertions(+) diff --git a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts -index 385249f280..7cb3068494 100644 +index d1e89920cc..5d62af1c64 100644 --- a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts +++ b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts -@@ -68,6 +68,7 @@ const LANGUAGE_MAP = new Map<string, string>([ +@@ -72,6 +72,7 @@ const LANGUAGE_MAP = new Map<string, string>([ ['text/x-perl', 'perl'], ['text/x-pgsql', 'pgsql'], // postgresql ['text/x-php', 'php'], @@ -21,10 +21,10 @@ index 385249f280..7cb3068494 100644 ['text/x-protobuf', 'protobuf'], ['text/x-puppet', 'puppet'], diff --git a/resources/com/google/gerrit/server/mime/mime-types.properties b/resources/com/google/gerrit/server/mime/mime-types.properties -index 739818ec05..58eb727bf9 100644 +index 97f1ff835b..85d630340f 100644 --- a/resources/com/google/gerrit/server/mime/mime-types.properties +++ b/resources/com/google/gerrit/server/mime/mime-types.properties -@@ -200,6 +200,7 @@ rq = application/sparql-query +@@ -208,6 +208,7 @@ rq = application/sparql-query rs = text/x-rustsrc rss = application/xml rst = text/x-rst @@ -33,5 +33,5 @@ index 739818ec05..58eb727bf9 100644 s = text/x-gas sas = text/x-sas -- -2.37.3 +2.45.1 diff --git a/third_party/gerrit/0003-Add-titles-to-CLs-over-HTTP.patch b/third_party/gerrit/0003-Add-titles-to-CLs-over-HTTP.patch index c4edee3a40c3..a5881e5a6c27 100644 --- a/third_party/gerrit/0003-Add-titles-to-CLs-over-HTTP.patch +++ b/third_party/gerrit/0003-Add-titles-to-CLs-over-HTTP.patch @@ -1,19 +1,19 @@ -From f49c50ca9a84ca374b7bd91c171bbea0457f2c7a Mon Sep 17 00:00:00 2001 +From ca2df6d7f53441d443d42908e30bf60fbfc15392 Mon Sep 17 00:00:00 2001 From: Luke Granger-Brown <git@lukegb.com> Date: Thu, 2 Jul 2020 23:03:02 +0100 Subject: [PATCH 3/3] Add titles to CLs over HTTP --- - .../gerrit/httpd/raw/IndexHtmlUtil.java | 13 +++- + .../gerrit/httpd/raw/IndexHtmlUtil.java | 12 +++- .../google/gerrit/httpd/raw/IndexServlet.java | 8 ++- .../google/gerrit/httpd/raw/StaticModule.java | 5 +- .../gerrit/httpd/raw/TitleComputer.java | 67 +++++++++++++++++++ .../gerrit/httpd/raw/PolyGerritIndexHtml.soy | 4 +- - 5 files changed, 89 insertions(+), 8 deletions(-) + 5 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 java/com/google/gerrit/httpd/raw/TitleComputer.java diff --git a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java -index 72bfe40c3b..439bd73b44 100644 +index a92dd18f04..f87c46d321 100644 --- a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java +++ b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java @@ -41,6 +41,7 @@ import java.util.Collections; @@ -24,7 +24,7 @@ index 72bfe40c3b..439bd73b44 100644 import java.util.Set; import java.util.function.Function; -@@ -62,13 +63,14 @@ public class IndexHtmlUtil { +@@ -63,13 +64,14 @@ public class IndexHtmlUtil { String faviconPath, Map<String, String[]> urlParameterMap, Function<String, SanitizedContent> urlInScriptTagOrdainer, @@ -36,22 +36,21 @@ index 72bfe40c3b..439bd73b44 100644 data.putAll( staticTemplateData( canonicalURL, cdnPath, faviconPath, urlParameterMap, urlInScriptTagOrdainer)) -- .putAll(dynamicTemplateData(gerritApi, requestedURL)); -+ .putAll(dynamicTemplateData(gerritApi, requestedURL, titleComputer)); +- .putAll(dynamicTemplateData(gerritApi, requestedURL, canonicalURL)); ++ .putAll(dynamicTemplateData(gerritApi, requestedURL, canonicalURL, titleComputer)); Set<String> enabledExperiments = new HashSet<>(); enabledExperiments.addAll(experimentFeatures.getEnabledExperimentFeatures()); // Add all experiments enabled through url -@@ -81,7 +83,8 @@ public class IndexHtmlUtil { +@@ -82,7 +84,7 @@ public class IndexHtmlUtil { /** Returns dynamic parameters of {@code index.html}. */ public static ImmutableMap<String, Object> dynamicTemplateData( -- GerritApi gerritApi, String requestedURL) throws RestApiException, URISyntaxException { -+ GerritApi gerritApi, String requestedURL, TitleComputer titleComputer) -+ throws RestApiException, URISyntaxException { +- GerritApi gerritApi, String requestedURL, String canonicalURL) ++ GerritApi gerritApi, String requestedURL, String canonicalURL, TitleComputer titleComputer) + throws RestApiException, URISyntaxException { ImmutableMap.Builder<String, Object> data = ImmutableMap.builder(); Map<String, SanitizedContent> initialData = new HashMap<>(); - Server serverApi = gerritApi.config().server(); -@@ -129,6 +132,10 @@ public class IndexHtmlUtil { +@@ -141,6 +143,10 @@ public class IndexHtmlUtil { } data.put("gerritInitialData", initialData); @@ -102,17 +101,17 @@ index fcb821e5ae..e1464b992b 100644 } catch (URISyntaxException | RestApiException e) { throw new IOException(e); diff --git a/java/com/google/gerrit/httpd/raw/StaticModule.java b/java/com/google/gerrit/httpd/raw/StaticModule.java -index 15dcf42e0e..9f56bf33ce 100644 +index b00294f73e..f1c1aae12c 100644 --- a/java/com/google/gerrit/httpd/raw/StaticModule.java +++ b/java/com/google/gerrit/httpd/raw/StaticModule.java -@@ -241,10 +241,11 @@ public class StaticModule extends ServletModule { +@@ -224,10 +224,11 @@ public class StaticModule extends ServletModule { @CanonicalWebUrl @Nullable String canonicalUrl, @GerritServerConfig Config cfg, GerritApi gerritApi, - ExperimentFeatures experimentFeatures) { + ExperimentFeatures experimentFeatures, + TitleComputer titleComputer) { - String cdnPath = options.devCdn().orElse(cfg.getString("gerrit", null, "cdnPath")); + String cdnPath = options.devCdn().orElseGet(() -> cfg.getString("gerrit", null, "cdnPath")); String faviconPath = cfg.getString("gerrit", null, "faviconPath"); - return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, experimentFeatures); + return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, experimentFeatures, titleComputer); @@ -193,7 +192,7 @@ index 0000000000..8fd2053ad0 + } +} diff --git a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy -index dbfef44dfe..347ee75aab 100644 +index 5ff1822cd9..81c3cdf0e1 100644 --- a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy +++ b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy @@ -33,10 +33,12 @@ @@ -211,5 +210,5 @@ index dbfef44dfe..347ee75aab 100644 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">{\n} -- -2.37.3 +2.45.1 diff --git a/third_party/gerrit/bazelrc b/third_party/gerrit/bazelrc new file mode 100644 index 000000000000..f77da77b46ee --- /dev/null +++ b/third_party/gerrit/bazelrc @@ -0,0 +1,11 @@ +# Not using common --repository_cache because Gerrit's bazelrc overrides this... +build --repository_cache=repository-cache +build --action_env=SSL_CERT_FILE +build --action_env=GERRIT_CACHE_HOME +build --tool_java_runtime_version=local_jdk --java_runtime_version=local_jdk +build --workspace_status_command="cat .version" + +# Disable errorprone +build --javacopt="-XepDisableAllChecks" + +sync --repository_cache=repository-cache diff --git a/third_party/gerrit/default.nix b/third_party/gerrit/default.nix index a137946264ed..fdf4a8d9d460 100644 --- a/third_party/gerrit/default.nix +++ b/third_party/gerrit/default.nix @@ -1,41 +1,33 @@ { depot, pkgs, ... }: let - bazelRunScript = pkgs.writeShellScriptBin "bazel-run" '' - yarn config set cache-folder "$bazelOut/external/yarn_cache" - export HOME="$bazelOut/external/home" - mkdir -p "$bazelOut/external/home" - exec /bin/bazel "$@" - ''; - bazelTop = pkgs.buildFHSUserEnv { - name = "bazel"; - targetPkgs = pkgs: [ - (pkgs.bazel_5.override { enableNixHacks = true; }) - pkgs.jdk17_headless - pkgs.zlib - pkgs.python3 - pkgs.curl - pkgs.nodejs - pkgs.yarn - pkgs.git - bazelRunScript - ]; - runScript = "/bin/bazel-run"; - }; - bazel = bazelTop // { override = x: bazelTop; }; - version = "3.9.1"; + inherit (depot.nix) buildBazelPackageNG; + inherit (buildBazelPackageNG) bazelRulesJavaHook bazelRulesNodeJS5Hook; in -pkgs.lib.makeOverridable pkgs.buildBazelPackage { +pkgs.lib.makeOverridable depot.nix.buildBazelPackageNG rec { pname = "gerrit"; - inherit version; + version = "3.10.0"; - src = pkgs.fetchgit { + bazel = pkgs.bazel_7; + + src = (pkgs.fetchgit { url = "https://gerrit.googlesource.com/gerrit"; - rev = "620a819cbf3c64fff7a66798822775ad42c91d8e"; - branchName = "v${version}"; - sha256 = "sha256:1mdxbgnx3mpxand4wq96ic38bb4yh45q271h40jrk7dk23sgmz02"; + rev = "v${version}"; fetchSubmodules = true; - }; + deepClone = true; + hash = "sha256-FpKuzityHuHNYBIOL8YUjCLlkuVBfxjvHECb26NsZNE="; + }).overrideAttrs (_: { + env.NIX_PREFETCH_GIT_CHECKOUT_HOOK = '' + pushd "$dir" >/dev/null + ${pkgs.python3}/bin/python tools/workspace_status_release.py | sort > .version + popd >/dev/null + + # delete all the .git; we can't do this using fetchgit if deepClone is on, + # but our mischief has already been achieved by the python command above :) + find "$dir" -name .git -print0 | xargs -0 rm -rf + ''; + }); + depsHash = "sha256-OS2kLXjtuWf+XRyQO2qGvEaAOvxqu20+gXR+fsCvpMc="; patches = [ ./0001-Syntax-highlight-nix.patch @@ -43,97 +35,52 @@ pkgs.lib.makeOverridable pkgs.buildBazelPackage { ./0003-Add-titles-to-CLs-over-HTTP.patch ]; - bazelTargets = [ "release" "api-skip-javadoc" ]; - inherit bazel; + nativeBuildInputs = with pkgs; [ + bazelRulesJavaHook + bazelRulesNodeJS5Hook - bazelFlags = [ - "--repository_cache=" - "--disk_cache=" + curl + jdk + python3 + unzip ]; - removeRulesCC = false; - fetchConfigured = true; + prePatch = '' + rm .bazelversion - fetchAttrs = { - sha256 = "sha256:119mqli75c9fy05ddrlh2brjxb354yvv1ijjkk1y1yqcaqppwwb8"; - preBuild = '' - rm .bazelversion - ''; + ln -sf ${./bazelrc} user.bazelrc - installPhase = '' - runHook preInstall - - # Remove all built in external workspaces, Bazel will recreate them when building - rm -rf $bazelOut/external/{bazel_tools,\@bazel_tools.marker} - rm -rf $bazelOut/external/{embedded_jdk,\@embedded_jdk.marker} - rm -rf $bazelOut/external/{local_config_cc,\@local_config_cc.marker} - rm -rf $bazelOut/external/{local_*,\@local_*.marker} - - # Clear markers - find $bazelOut/external -name '@*\.marker' -exec sh -c 'echo > {}' \; - - # Remove all vcs files - rm -rf $(find $bazelOut/external -type d -name .git) - rm -rf $(find $bazelOut/external -type d -name .svn) - rm -rf $(find $bazelOut/external -type d -name .hg) - - # Removing top-level symlinks along with their markers. - # This is needed because they sometimes point to temporary paths (?). - # For example, in Tensorflow-gpu build: - #sha256:06bmzbcb9717s4b016kcbn8nr9pgaz04i8bnzg7ybkbdwpl8vxvv"; platforms -> NIX_BUILD_TOP/tmp/install/35282f5123611afa742331368e9ae529/_embedded_binaries/platforms - find $bazelOut/external -maxdepth 1 -type l | while read symlink; do - name="$(basename "$symlink")" - rm -rf "$symlink" "$bazelOut/external/@$name.marker" - done - - # Patching symlinks to remove build directory reference - find $bazelOut/external -type l | while read symlink; do - new_target="$(readlink "$symlink" | sed "s,$NIX_BUILD_TOP,NIX_BUILD_TOP,")" - rm "$symlink" - ln -sf "$new_target" "$symlink" - done - - echo '${bazel.name}' > $bazelOut/external/.nix-bazel-version - - # Gerrit fixups: - # Normalize permissions on .yarn-{tarball,metadata} files - test -d $bazelOut/external/yarn_cache && find $bazelOut/external/yarn_cache \( -name .yarn-tarball.tgz -or -name .yarn-metadata.json \) -exec chmod 644 {} + - - mkdir $bazelOut/_bits/ - find . -name node_modules -prune -print | while read d; do - echo "$d" "$(dirname $d)" - mkdir -p $bazelOut/_bits/$(dirname $d) - cp -R "$d" "$bazelOut/_bits/$(dirname $d)/node_modules" - done - - (cd $bazelOut/ && tar czf $out --sort=name --mtime='@1' --owner=0 --group=0 --numeric-owner external/ _bits/) - - runHook postInstall - ''; - }; + ln -sf ${./workspace_overrides.bzl} workspace_overrides.bzl + substituteInPlace WORKSPACE \ + --replace-fail 'load("@io_bazel_rules_webtesting//web:repositories.bzl"' 'load("//:workspace_overrides.bzl"' \ + --replace-fail 'load("@io_bazel_rules_webtesting//web/versioned:browsers-0.3.3.bzl"' 'load("//:workspace_overrides.bzl"' - buildAttrs = { - preConfigure = '' - rm .bazelversion + patchShebangs Documentation/replace_macros.py + ''; - [ "$(ls -A $bazelOut/_bits)" ] && cp -R $bazelOut/_bits/* ./ || true - ''; - postPatch = '' - # Disable all errorprone checks, since we might be using a different version. - sed -i \ - -e '/-Xep:/d' \ - -e '/-XepExcludedPaths:/a "-XepDisableAllChecks",' \ - tools/BUILD - ''; - installPhase = '' - mkdir -p "$out"/webapps/ "$out"/share/api/ - cp bazel-bin/release.war "$out"/webapps/gerrit-${version}.war - unzip bazel-bin/api-skip-javadoc.zip -d "$out"/share/api - ''; + postPatch = '' + sed -Ei 's,^(STABLE_BUILD_GERRIT_LABEL.*)$,\1-dirty-nix,' .version + ''; - nativeBuildInputs = with pkgs; [ - unzip - ]; + preBuild = '' + export GERRIT_CACHE_HOME=$HOME/gerrit-cache + ''; + + extraCacheInstall = '' + cp -R $GERRIT_CACHE_HOME $out/gerrit-cache + ''; + + extraBuildSetup = '' + ln -sf $cache/gerrit-cache $GERRIT_CACHE_HOME + ''; + extraBuildInstall = '' + mkdir -p "$out"/share/api/ + unzip bazel-bin/api-skip-javadoc.zip -d "$out"/share/api + ''; + + bazelTargets = { + "//:release" = "$out/webapps/gerrit-${version}.war"; + "//:api-skip-javadoc" = null; }; passthru = { @@ -154,5 +101,5 @@ pkgs.lib.makeOverridable pkgs.buildBazelPackage { ]; }; - meta.ci.targets = [ "deps" ]; + meta.ci.targets = [ "cache" ]; } diff --git a/third_party/gerrit/detzip.go b/third_party/gerrit/detzip.go deleted file mode 100644 index 511c18ecfe17..000000000000 --- a/third_party/gerrit/detzip.go +++ /dev/null @@ -1,97 +0,0 @@ -package main - -import ( - "archive/zip" - "flag" - "fmt" - "io" - "log" - "os" - "path/filepath" - "sort" - "strings" -) - -var ( - exclude = flag.String("exclude", "", "comma-separated list of filenames to exclude (in any directory)") -) - -func init() { - flag.Usage = func() { - fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s [zip file] [directory]:\n", os.Args[0]) - flag.PrintDefaults() - } -} - -func listToMap(ss []string) map[string]bool { - m := make(map[string]bool) - for _, s := range ss { - m[s] = true - } - return m -} - -func main() { - flag.Parse() - if flag.NArg() != 2 { - flag.Usage() - os.Exit(1) - } - - outPath := flag.Arg(0) - dirPath := flag.Arg(1) - - excludeFiles := listToMap(strings.Split(*exclude, ",")) - - // Aggregate all files first. - var files []string - filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if info.IsDir() { - return nil - } - if excludeFiles[info.Name()] { - return nil - } - files = append(files, path) - return nil - }) - - // Create zip - outW, err := os.Create(outPath) - if err != nil { - log.Fatalf("Create(%q): %v", outPath, err) - } - - zipW := zip.NewWriter(outW) - - // Output files in alphabetical order - sort.Strings(files) - for _, f := range files { - fw, err := zipW.CreateHeader(&zip.FileHeader{ - Name: f, - Method: zip.Store, - }) - if err != nil { - log.Fatalf("creating %q in zip: %v", f, err) - } - - ff, err := os.Open(f) - if err != nil { - log.Fatalf("opening %q: %v", f, err) - } - if _, err := io.Copy(fw, ff); err != nil { - log.Fatalf("copying %q to zip: %v", f, err) - } - ff.Close() - } - - if err := zipW.Close(); err != nil { - log.Fatalf("writing ZIP central directory: %v", err) - } - if err := outW.Close(); err != nil { - log.Fatalf("closing ZIP file: %v", err) - } -} diff --git a/third_party/gerrit/workspace_overrides.bzl b/third_party/gerrit/workspace_overrides.bzl new file mode 100644 index 000000000000..839368606557 --- /dev/null +++ b/third_party/gerrit/workspace_overrides.bzl @@ -0,0 +1,5 @@ +def web_test_repositories(): + pass + +def browser_repositories(*args, **kwargs): + pass diff --git a/third_party/gerrit_plugins/builder.nix b/third_party/gerrit_plugins/builder.nix index 50a4e78ae7cf..a478dfe5d71d 100644 --- a/third_party/gerrit_plugins/builder.nix +++ b/third_party/gerrit_plugins/builder.nix @@ -2,30 +2,33 @@ { buildGerritBazelPlugin = { name + , version , src - , depsOutputHash + , depsHash ? null , overlayPluginCmd ? '' cp -R "${src}" "$out/plugins/${name}" + echo "STABLE_BUILD_${lib.toUpper name}_LABEL v${version}-nix${if patches != [] then "-dirty" else ""}" >> $out/.version '' + , postOverlayPlugin ? "" , postPatch ? "" , patches ? [ ] - }: ((depot.third_party.gerrit.override { + }: ((depot.third_party.gerrit.override (old: { name = "${name}.jar"; src = pkgs.runCommandLocal "${name}-src" { } '' cp -R "${depot.third_party.gerrit.src}" "$out" - chmod +w "$out/plugins" + chmod -R +w "$out" ${overlayPluginCmd} + ${postOverlayPlugin} ''; + depsHash = (if depsHash != null then depsHash else old.depsHash); - bazelTargets = [ "//plugins/${name}" ]; - }).overrideAttrs (super: { - deps = super.deps.overrideAttrs (superDeps: { - outputHash = depsOutputHash; - }); - installPhase = '' - cp "bazel-bin/plugins/${name}/${name}.jar" "$out" - ''; + bazelTargets = { + "//plugins/${name}" = "$out"; + }; + + extraBuildInstall = ""; + })).overrideAttrs (super: { postPatch = '' ${super.postPatch or ""} pushd "plugins/${name}" diff --git a/third_party/gerrit_plugins/code-owners/default.nix b/third_party/gerrit_plugins/code-owners/default.nix index 0dc3ef83ae7f..c849bfb52d41 100644 --- a/third_party/gerrit_plugins/code-owners/default.nix +++ b/third_party/gerrit_plugins/code-owners/default.nix @@ -5,11 +5,11 @@ let in buildGerritBazelPlugin rec { name = "code-owners"; - depsOutputHash = "sha256:0jv62cc1kpgsmwk119i9njmqn6w6k8frlbgcw87y8nfbpprmcf01"; + version = "7de40d8"; src = pkgs.fetchgit { url = "https://gerrit.googlesource.com/plugins/code-owners"; - rev = "e654ae5bda2085bce9a99942bec440e004a114f3"; - sha256 = "sha256:14d3x3iqskgw16pvyaa0swh252agj84p9pzlf24l8lgx9d7y4biz"; + rev = "7de40d8b30e55eb64316b6fc3d0d00da9caddade"; + hash = "sha256-0sLwUcG9RN1o9vZGW8ErwL7UgJapgYoo8XMGsWLO25Q="; }; patches = [ ./using-usernames.patch diff --git a/third_party/gerrit_plugins/oauth/default.nix b/third_party/gerrit_plugins/oauth/default.nix index e7626fa88c38..811614d66a18 100644 --- a/third_party/gerrit_plugins/oauth/default.nix +++ b/third_party/gerrit_plugins/oauth/default.nix @@ -5,15 +5,14 @@ let in buildGerritBazelPlugin rec { name = "oauth"; - depsOutputHash = "sha256:01z7rn8hnms3cp7mq27yk063lpy4pmqwpfrcc3cfl0r43k889zz3"; + version = "982316"; src = pkgs.fetchgit { url = "https://gerrit.googlesource.com/plugins/oauth"; - rev = "b27cf3ea820eec2ddd22d217fc839261692ccdb0"; - sha256 = "1m654ibgzprrhcl0wpzqrmq8drpgx6rzlw0ha16l1fi2zv5idkk2"; + rev = "98231604d60788bb43490f1a301d792817ac8008"; + hash = "sha256-AuVO1Yys8BYqGHZI/adszCUg0JM2v4Td4fe26LdOPLM="; }; - overlayPluginCmd = '' - chmod +w "$out" "$out/plugins/external_plugin_deps.bzl" - cp -R "${src}" "$out/plugins/${name}" + depsHash = "sha256-7SC4NXm4zGeJrYBqtEvcrLmsZmXEX8P21J0kwHBDBZ4="; + postOverlayPlugin = '' cp "${src}/external_plugin_deps.bzl" "$out/plugins/external_plugin_deps.bzl" ''; } diff --git a/third_party/git/default.nix b/third_party/git/default.nix index eed07b5616c6..19613fd69555 100644 --- a/third_party/git/default.nix +++ b/third_party/git/default.nix @@ -4,6 +4,6 @@ pkgs.git.overrideAttrs (old: { patches = (old.patches or [ ]) ++ [ - ./0001-feat-third_party-git-date-add-dottime-format.patch + # ./0001-feat-third_party-git-date-add-dottime-format.patch ]; }) diff --git a/third_party/gitignoreSource/default.nix b/third_party/gitignoreSource/default.nix index 150de7c990e4..78a7414ed3ad 100644 --- a/third_party/gitignoreSource/default.nix +++ b/third_party/gitignoreSource/default.nix @@ -1,15 +1,7 @@ -{ pkgs, ... }: +{ depot, lib, ... }: let - gitignoreNix = import - (pkgs.fetchFromGitHub { - owner = "hercules-ci"; - repo = "gitignore"; - rev = "f9e996052b5af4032fe6150bba4a6fe4f7b9d698"; - sha256 = "0jrh5ghisaqdd0vldbywags20m2cxpkbbk5jjjmwaw0gr8nhsafv"; - }) - { inherit (pkgs) lib; }; - + gitignoreNix = import depot.third_party.sources."gitignore.nix" { inherit lib; }; in { __functor = _: gitignoreNix.gitignoreSource; diff --git a/third_party/nixpkgs/default.nix b/third_party/nixpkgs/default.nix index b79a963e5c9f..3ec49ea084d8 100644 --- a/third_party/nixpkgs/default.nix +++ b/third_party/nixpkgs/default.nix @@ -52,7 +52,16 @@ let # Overlay for packages that should come from the stable channel # instead (e.g. because something is broken in unstable). # Use `stableNixpkgs` from above. - stableOverlay = _unstableSelf: unstableSuper: { }; + stableOverlay = _unstableSelf: unstableSuper: { + # newer trunk fails somewhere within reqwest, trying to read a mystery file + trunk = stableNixpkgs.trunk; + + # the big lis package change breaks everything in //3p/lisp, undo it for now. + lispPackages = stableNixpkgs.lispPackages; + + # mypaint is broken on stable (2024-09-05) + mypaint = stableNixpkgs.mypaint; + }; # Overlay to expose the nixpkgs commits we are using to other Nix code. commitsOverlay = _: _: { diff --git a/third_party/overlays/patches/cbtemulator-uds.patch b/third_party/overlays/patches/cbtemulator-uds.patch deleted file mode 100644 index a19255306f88..000000000000 --- a/third_party/overlays/patches/cbtemulator-uds.patch +++ /dev/null @@ -1,140 +0,0 @@ -commit 1397e10225d8c6fd079a86fccd58fb5d0f4200bc -Author: Florian Klink <flokli@flokli.de> -Date: Fri Mar 29 10:06:34 2024 +0100 - - feat(bigtable/emulator): allow listening on Unix Domain Sockets - - cbtemulator listening on unix domain sockets is much easier than trying - to allocate free TCP ports, especially if many cbtemulators are run at - the same time in integration tests. - - This adds an additional flag, address, which has priority if it's set, - rather than host:port. - - `NewServer` already takes a `laddr string`, so we simply check for it to - contain slashes, and if so, listen on unix, rather than TCP. - -diff --git a/bigtable/bttest/inmem.go b/bigtable/bttest/inmem.go -index 556abc2a85..33e4bf2667 100644 ---- a/bttest/inmem.go -+++ b/bttest/inmem.go -@@ -40,6 +40,7 @@ import ( - "math" - "math/rand" - "net" -+ "os" - "regexp" - "sort" - "strings" -@@ -106,7 +107,15 @@ type server struct { - // The Server will be listening for gRPC connections, without TLS, - // on the provided address. The resolved address is named by the Addr field. - func NewServer(laddr string, opt ...grpc.ServerOption) (*Server, error) { -- l, err := net.Listen("tcp", laddr) -+ var l net.Listener -+ var err error -+ -+ // If the address contains slashes, listen on a unix domain socket instead. -+ if strings.Contains(laddr, "/") { -+ l, err = net.Listen("unix", laddr) -+ } else { -+ l, err = net.Listen("tcp", laddr) -+ } - if err != nil { - return nil, err - } -diff --git a/bigtable/cmd/emulator/cbtemulator.go b/bigtable/cmd/emulator/cbtemulator.go -index 144c09ffb1..deaf69b717 100644 ---- a/cmd/emulator/cbtemulator.go -+++ b/cmd/emulator/cbtemulator.go -@@ -27,8 +27,9 @@ import ( - ) - - var ( -- host = flag.String("host", "localhost", "the address to bind to on the local machine") -- port = flag.Int("port", 9000, "the port number to bind to on the local machine") -+ host = flag.String("host", "localhost", "the address to bind to on the local machine") -+ port = flag.Int("port", 9000, "the port number to bind to on the local machine") -+ address = flag.String("address", "", "address:port number or unix socket path to listen on. Has priority over host/port") - ) - - const ( -@@ -42,7 +43,15 @@ func main() { - grpc.MaxRecvMsgSize(maxMsgSize), - grpc.MaxSendMsgSize(maxMsgSize), - } -- srv, err := bttest.NewServer(fmt.Sprintf("%s:%d", *host, *port), opts...) -+ -+ var laddr string -+ if *address != "" { -+ laddr = *address -+ } else { -+ laddr = fmt.Sprintf("%s:%d", *host, *port) -+ } -+ -+ srv, err := bttest.NewServer(laddr, opts...) - if err != nil { - log.Fatalf("failed to start emulator: %v", err) - } -commit ce16f843d6c93159d86b3807c6d9ff66e43aac67 -Author: Florian Klink <flokli@flokli.de> -Date: Fri Mar 29 11:53:15 2024 +0100 - - feat(bigtable): clean up unix socket on close - - Call srv.Close when receiving an interrupt, and delete the unix domain - socket in that function. - -diff --git a/bigtable/bttest/inmem.go b/bigtable/bttest/inmem.go -index 33e4bf2667..0dc96024b1 100644 ---- a/bttest/inmem.go -+++ b/bttest/inmem.go -@@ -148,6 +148,11 @@ func (s *Server) Close() { - - s.srv.Stop() - s.l.Close() -+ -+ // clean up unix socket -+ if strings.Contains(s.Addr, "/") { -+ _ = os.Remove(s.Addr) -+ } - } - - func (s *server) CreateTable(ctx context.Context, req *btapb.CreateTableRequest) (*btapb.Table, error) { -diff --git a/bigtable/cmd/emulator/cbtemulator.go b/bigtable/cmd/emulator/cbtemulator.go -index deaf69b717..5a9e8f7a8c 100644 ---- a/cmd/emulator/cbtemulator.go -+++ b/cmd/emulator/cbtemulator.go -@@ -18,9 +18,12 @@ cbtemulator launches the in-memory Cloud Bigtable server on the given address. - package main - - import ( -+ "context" - "flag" - "fmt" - "log" -+ "os" -+ "os/signal" - - "cloud.google.com/go/bigtable/bttest" - "google.golang.org/grpc" -@@ -51,11 +54,18 @@ func main() { - laddr = fmt.Sprintf("%s:%d", *host, *port) - } - -+ ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) -+ defer stop() -+ - srv, err := bttest.NewServer(laddr, opts...) - if err != nil { - log.Fatalf("failed to start emulator: %v", err) - } - - fmt.Printf("Cloud Bigtable emulator running on %s\n", srv.Addr) -- select {} -+ select { -+ case <-ctx.Done(): -+ srv.Close() -+ stop() -+ } - } diff --git a/third_party/overlays/patches/crate2nix-0001-Fix-Use-mkDerivation-with-src-instead-of-runCommand.patch b/third_party/overlays/patches/crate2nix-0001-Fix-Use-mkDerivation-with-src-instead-of-runCommand.patch new file mode 100644 index 000000000000..fbc18860ac81 --- /dev/null +++ b/third_party/overlays/patches/crate2nix-0001-Fix-Use-mkDerivation-with-src-instead-of-runCommand.patch @@ -0,0 +1,109 @@ +From 96f66ec32e003c6c215aa2a644281289a71dae7d Mon Sep 17 00:00:00 2001 +From: Ilan Joselevich <personal@ilanjoselevich.com> +Date: Sun, 4 Aug 2024 02:35:27 +0300 +Subject: [PATCH] Fix: Use mkDerivation with src instead of runCommand for test + derivation + +The problem with using runCommand and recreating the src directory with +lndir is that it changes the file types of individual files, they will +now be a symlink instead of a regular file. If you have a crate that tests +that a file is of regular type then it will fail inside the crate2nix derivation. +--- + templates/nix/crate2nix/default.nix | 81 ++++++++----------- + 1 file changed, 35 insertions(+), 46 deletions(-) + +diff --git a/templates/nix/crate2nix/default.nix b/templates/nix/crate2nix/default.nix +index c53925e..90e10c6 100644 +--- a/templates/nix/crate2nix/default.nix ++++ b/templates/nix/crate2nix/default.nix +@@ -120,52 +120,41 @@ rec { + testPostRun + ]); + in +- pkgs.runCommand "run-tests-${testCrate.name}" +- { +- inherit testCrateFlags; +- buildInputs = testInputs; +- } '' +- set -e +- +- export RUST_BACKTRACE=1 +- +- # recreate a file hierarchy as when running tests with cargo +- +- # the source for test data +- # It's necessary to locate the source in $NIX_BUILD_TOP/source/ +- # instead of $NIX_BUILD_TOP/ +- # because we compiled those test binaries in the former and not the latter. +- # So all paths will expect source tree to be there and not in the build top directly. +- # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. +- # NOTE: There could be edge cases if `crate.sourceRoot` does exist but +- # it's very hard to reason about them. +- # Open a bug if you run into this! +- mkdir -p source/ +- cd source/ +- +- ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} +- +- # build outputs +- testRoot=target/debug +- mkdir -p $testRoot +- +- # executables of the crate +- # we copy to prevent std::env::current_exe() to resolve to a store location +- for i in ${crate}/bin/*; do +- cp "$i" "$testRoot" +- done +- chmod +w -R . +- +- # test harness executables are suffixed with a hash, like cargo does +- # this allows to prevent name collision with the main +- # executables of the crate +- hash=$(basename $out) +- for file in ${drv}/tests/*; do +- f=$testRoot/$(basename $file)-$hash +- cp $file $f +- ${testCommand} +- done +- ''; ++ pkgs.stdenvNoCC.mkDerivation { ++ name = "run-tests-${testCrate.name}"; ++ ++ inherit (crate) src; ++ ++ inherit testCrateFlags; ++ ++ buildInputs = testInputs; ++ ++ buildPhase = '' ++ set -e ++ export RUST_BACKTRACE=1 ++ ++ # build outputs ++ testRoot=target/debug ++ mkdir -p $testRoot ++ ++ # executables of the crate ++ # we copy to prevent std::env::current_exe() to resolve to a store location ++ for i in ${crate}/bin/*; do ++ cp "$i" "$testRoot" ++ done ++ chmod +w -R . ++ ++ # test harness executables are suffixed with a hash, like cargo does ++ # this allows to prevent name collision with the main ++ # executables of the crate ++ hash=$(basename $out) ++ for file in ${drv}/tests/*; do ++ f=$testRoot/$(basename $file)-$hash ++ cp $file $f ++ ${testCommand} ++ done ++ ''; ++ }; + in + pkgs.runCommand "${crate.name}-linked" + { +-- +2.44.0 + diff --git a/third_party/overlays/patches/crate2nix-run-tests-in-build-source.patch b/third_party/overlays/patches/crate2nix-run-tests-in-build-source.patch deleted file mode 100644 index 52793270e6e8..000000000000 --- a/third_party/overlays/patches/crate2nix-run-tests-in-build-source.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 7cf084f73f7d15fe0538a625182fa7179c083b3d Mon Sep 17 00:00:00 2001 -From: Raito Bezarius <masterancpp@gmail.com> -Date: Tue, 16 Jan 2024 02:10:48 +0100 -Subject: [PATCH] fix(template): run tests in `/build/source` instead `/build` - -Previously, the source tree was located inline in `/build` during tests, this was a mistake -because the crates more than often are built in `/build/source` as per the `sourceRoot` system. - -This can cause issues with test binaries hardcoding `/build/source/...` as their choice for doing things, -causing them to be confused in the test phase which is relocated without rewriting the paths inside test binaries. - -We fix that by relocating ourselves in the right hierarchy. - -This is a "simple" fix in the sense that more edge cases could exist but they are hard to reason about -because they would be crates using custom `sourceRoot`, i.e. having `crate.sourceRoot` set and then it becomes -a bit hard to reproduce the hierarchy, you need to analyze whether the path is absolute or relative, - -If it's relative, you can just reuse it and reproduce that specific hierarchy. -If it's absolute, you need to cut the "absolute" meaningless part, e.g. `$NIX_BUILD_TOP/` and proceed like -it's a relative path IMHO. ---- - crate2nix/Cargo.nix | 10 ++++++++++ - crate2nix/templates/nix/crate2nix/default.nix | 10 ++++++++++ - -diff --git a/Cargo.nix b/Cargo.nix -index 6ef7a49..172ff34 100644 ---- a/Cargo.nix -+++ b/Cargo.nix -@@ -2889,6 +2889,16 @@ rec { - # recreate a file hierarchy as when running tests with cargo - - # the source for test data -+ # It's necessary to locate the source in $NIX_BUILD_TOP/source/ -+ # instead of $NIX_BUILD_TOP/ -+ # because we compiled those test binaries in the former and not the latter. -+ # So all paths will expect source tree to be there and not in the build top directly. -+ # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. -+ # TODO(raitobezarius): I believe there could be more edge cases if `crate.sourceRoot` -+ # do exist but it's very hard to reason about them, so let's wait until the first bug report. -+ mkdir -p source/ -+ cd source/ -+ - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} - - # build outputs -diff --git a/crate2nix/templates/nix/crate2nix/default.nix b/crate2nix/templates/nix/crate2nix/default.nix -index e4fc2e9..dfb14c4 100644 ---- a/templates/nix/crate2nix/default.nix -+++ b/templates/nix/crate2nix/default.nix -@@ -135,6 +135,16 @@ rec { - # recreate a file hierarchy as when running tests with cargo - - # the source for test data -+ # It's necessary to locate the source in $NIX_BUILD_TOP/source/ -+ # instead of $NIX_BUILD_TOP/ -+ # because we compiled those test binaries in the former and not the latter. -+ # So all paths will expect source tree to be there and not in the build top directly. -+ # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. -+ # TODO(raitobezarius): I believe there could be more edge cases if `crate.sourceRoot` -+ # do exist but it's very hard to reason about them, so let's wait until the first bug report. -+ mkdir -p source/ -+ cd source/ -+ - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} - - # build outputs --- -2.43.0 - diff --git a/third_party/overlays/patches/treefmt-fix-no-cache.patch b/third_party/overlays/patches/treefmt-fix-no-cache.patch new file mode 100644 index 000000000000..2ad9d595e106 --- /dev/null +++ b/third_party/overlays/patches/treefmt-fix-no-cache.patch @@ -0,0 +1,43 @@ +From 601af097720079ea40db100b1dd6aefba4685e7c Mon Sep 17 00:00:00 2001 +From: Florian Klink <flokli@flokli.de> +Date: Mon, 1 Jul 2024 17:34:08 +0300 +Subject: [PATCH] fix: only try opening the cache if cache is enabled + +Otherwise `--no-cache` still fails to open the cache. +--- + cli/format.go | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/cli/format.go b/cli/format.go +index 492a4f3..8ccf578 100644 +--- a/cli/format.go ++++ b/cli/format.go +@@ -118,9 +118,11 @@ func (f *Format) Run() (err error) { + f.formatters[name] = formatter + } + +- // open the cache +- if err = cache.Open(f.TreeRoot, f.ClearCache, f.formatters); err != nil { +- return err ++ // open the cache if configured ++ if !f.NoCache { ++ if cache.Open(f.TreeRoot, f.ClearCache, f.formatters); err != nil { ++ return err ++ } + } + + // create an app context and listen for shutdown +@@ -148,7 +150,9 @@ func (f *Format) Run() (err error) { + f.processedCh = make(chan *walk.File, cap(f.filesCh)) + + // start concurrent processing tasks in reverse order +- eg.Go(f.updateCache(ctx)) ++ if !f.NoCache { ++ eg.Go(f.updateCache(ctx)) ++ } + eg.Go(f.applyFormatters(ctx)) + eg.Go(f.walkFilesystem(ctx)) + +-- +2.44.1 + diff --git a/third_party/overlays/tvl.nix b/third_party/overlays/tvl.nix index 23f56e2f98af..3835f07c9664 100644 --- a/third_party/overlays/tvl.nix +++ b/third_party/overlays/tvl.nix @@ -21,17 +21,6 @@ depot.nix.readTree.drvTargets { withAWS = false; }); - # To match telega in emacs-overlay or wherever - tdlib = super.tdlib.overrideAttrs (_: { - version = "1.8.24"; - src = self.fetchFromGitHub { - owner = "tdlib"; - repo = "td"; - rev = "d79bd4b69403868897496da39b773ab25c69f6af"; - sha256 = "0bc5akzw12qwj45rzqkrhw65qlrn9q8pzmvc5aiqv4bvhkb1ghl0"; - }; - }); - home-manager = super.home-manager.overrideAttrs (_: { src = depot.third_party.sources.home-manager; version = "git-" @@ -69,6 +58,17 @@ depot.nix.readTree.drvTargets { sha256 = "1mmlrd2zpcwiv8gh10y7lrpflnbmsycdascrxjr3bfcwa8yx7901"; }; }; + + # Override telega sources until MELPA updates in nixpkgs resume. + telega = esuper.telega.overrideAttrs (_: { + version = "0.8.291"; # unstable + src = self.fetchFromGitHub { + owner = "zevlg"; + repo = "telega.el"; + rev = "58b4963b292ceb723d665df100b519eb5a99c676"; + sha256 = "1q3ydbm0jhrsyvvdn0mpmxvskq0l53jkh40a5hlx7i3qkinbhbry"; + }; + }); }) ); @@ -79,10 +79,6 @@ depot.nix.readTree.drvTargets { }; }); - # nix-serve does not work with nix 2.4 - # https://github.com/edolstra/nix-serve/issues/28 - nix-serve = super.nix-serve.override { nix = self.nix_2_3; }; - # Avoid builds of mkShell derivations in CI. mkShell = super.lib.makeOverridable (args: (super.mkShell args).overrideAttrs (_: { passthru = { @@ -90,51 +86,14 @@ depot.nix.readTree.drvTargets { }; })); - # https://github.com/googleapis/google-cloud-go/pull/9665 - cbtemulator = super.cbtemulator.overrideAttrs (old: { + crate2nix = super.crate2nix.overrideAttrs (old: { patches = old.patches or [ ] ++ [ - ./patches/cbtemulator-uds.patch - ]; - }); - - crate2nix = super.rustPlatform.buildRustPackage rec { - pname = "crate2nix"; - version = "0.13.0"; - - src = super.fetchFromGitHub { - owner = "nix-community"; - repo = "crate2nix"; - rev = "ceb06eb7e76afb9e01a5f069aae136f97df72730"; - hash = "sha256-JTMe8GViCQt51WUiaaoIPmWtwEeeYrl6pBxo2DNuKig="; - }; - - patches = [ + # TODO(Kranzes): Remove in next release. + ./patches/crate2nix-0001-Fix-Use-mkDerivation-with-src-instead-of-runCommand.patch + # https://github.com/nix-community/crate2nix/pull/301 ./patches/crate2nix-tests-debug.patch - ./patches/crate2nix-run-tests-in-build-source.patch ]; - - sourceRoot = "${src.name}/crate2nix"; - - cargoHash = "sha256-dhlSXY1CJE+JJt+6Y7W1MVMz36nwr6ny543py1TcjyY="; - - nativeBuildInputs = [ super.makeWrapper ]; - - # Tests use nix(1), which tries (and fails) to set up /nix/var inside the - # sandbox - doCheck = false; - - postFixup = '' - wrapProgram $out/bin/crate2nix \ - --suffix PATH ":" ${lib.makeBinPath (with self; [ cargo nix_latest nix-prefetch-git ])} - - rm -rf $out/lib $out/bin/crate2nix.d - mkdir -p \ - $out/share/bash-completion/completions \ - $out/share/zsh/vendor-completions - $out/bin/crate2nix completions -s 'bash' -o $out/share/bash-completion/completions - $out/bin/crate2nix completions -s 'zsh' -o $out/share/zsh/vendor-completions - ''; - }; + }); evans = super.evans.overrideAttrs (old: { patches = old.patches or [ ] ++ [ @@ -144,6 +103,25 @@ depot.nix.readTree.drvTargets { ]; }); + # https://github.com/NixOS/nixpkgs/pull/329415/files + grpc-health-check = super.rustPlatform.buildRustPackage { + pname = "grpc-health-check"; + version = "unstable-2022-08-19"; + + src = super.fetchFromGitHub { + owner = "paypizza"; + repo = "grpc-health-check"; + rev = "f61bb5e10beadc5ed53144cc540d66e19fc510bd"; + hash = "sha256-nKut9c1HHIacdRcmvlXe0GrtkgCWN6sxJ4ImO0CIDdo="; + }; + + cargoHash = "sha256-lz+815iE+oXBQ3PfqBO0QBpZY6x1SNR7OU7BjkRszzI="; + + nativeBuildInputs = [ super.protobuf ]; + # tests fail + doCheck = false; + }; + # Imports a patch that fixes usage of this package on versions # >=1.9. The patch has been proposed upstream, but so far with no # reactions from the maintainer: @@ -152,4 +130,49 @@ depot.nix.readTree.drvTargets { tpm2-pkcs11 = super.tpm2-pkcs11.overrideAttrs (old: { patches = (old.patches or [ ]) ++ [ ./patches/tpm2-pkcs11-190-dbupgrade.patch ]; }); + + # Dependency isn't supported by Python 3.12 + html5validator = super.html5validator.override { + python3 = self.python311; + }; + + # macFUSE bump containing fix for https://github.com/osxfuse/osxfuse/issues/974 + # https://github.com/NixOS/nixpkgs/pull/320197 + fuse = + if super.stdenv.isDarwin then + super.fuse.overrideAttrs + (old: rec { + version = "4.8.0"; + src = super.fetchurl { + url = "https://github.com/osxfuse/osxfuse/releases/download/macfuse-${version}/macfuse-${version}.dmg"; + hash = "sha256-ucTzO2qdN4QkowMVvC3+4pjEVjbwMsB0xFk+bvQxwtQ="; + }; + }) else super.fuse; + + # somebody renamed 'utillinux' upstream, but didn't rename all use-cases, + # leading to some packages being broken. + # + # temporarily restore the old name to make things work again. + utillinux = self.util-linux; + + # Override niri to a version with interactive move until a new release is cut upstream. + niri = + let + src = self.fetchFromGitHub { + owner = "yalter"; + repo = "niri"; + rev = "0866990b7d706cdb3af2e9f0008bb9e7281a0e26"; + hash = "sha256:088yb86pryrcklwggx072dhswhjvx9ylkzdhrfkpfc56a85mp6vk"; + }; + in + super.niri.overrideAttrs (old: { + inherit src; + cargoDeps = self.rustPlatform.importCargoLock { + lockFile = "${src}/Cargo.lock"; + outputHashes = { + "smithay-0.3.0" = "sha256:10ihl9hvvi8aw30qv8ihv888ngr7wf7p9nwabf2jvhlc9443jq35"; + "libspa-0.8.0" = "sha256:1n8ngihd75i3vgbfnfhpj8mi6shlrhbhvwfyms14m03613jp37lj"; + }; + }; + }); } diff --git a/third_party/radicle-explorer/0001-remove-dependency-on-plausible.patch b/third_party/radicle-explorer/0001-remove-dependency-on-plausible.patch new file mode 100644 index 000000000000..0f4a6219b298 --- /dev/null +++ b/third_party/radicle-explorer/0001-remove-dependency-on-plausible.patch @@ -0,0 +1,78 @@ +From cc4718cbea1bd70de21a2be515a944802246ffc7 Mon Sep 17 00:00:00 2001 +From: Vincent Ambo <mail@tazj.in> +Date: Sun, 15 Sep 2024 03:08:28 +0300 +Subject: [PATCH] remove dependency on plausible + +We don't need spyware, thanks. +--- + package-lock.json | 9 --------- + package.json | 1 - + src/App.svelte | 8 -------- + 3 files changed, 18 deletions(-) + +diff --git a/package-lock.json b/package-lock.json +index d52de6c0..d96e342f 100644 +--- a/package-lock.json ++++ b/package-lock.json +@@ -29,7 +29,6 @@ + "marked-katex-extension": "^5.1.1", + "marked-linkify-it": "^3.1.11", + "md5": "^2.3.0", +- "plausible-tracker": "^0.3.9", + "svelte": "^4.2.19", + "twemoji": "^14.0.2", + "zod": "^3.23.8" +@@ -3697,14 +3696,6 @@ + "url": "https://github.com/sponsors/jonschlinkert" + } + }, +- "node_modules/plausible-tracker": { +- "version": "0.3.9", +- "resolved": "https://registry.npmjs.org/plausible-tracker/-/plausible-tracker-0.3.9.tgz", +- "integrity": "sha512-hMhneYm3GCPyQon88SZrVJx+LlqhM1kZFQbuAgXPoh/Az2YvO1B6bitT9qlhpiTdJlsT5lsr3gPmzoVjb5CDXA==", +- "engines": { +- "node": ">=10" +- } +- }, + "node_modules/playwright": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz", +diff --git a/package.json b/package.json +index 6d569ad9..61e8d892 100644 +--- a/package.json ++++ b/package.json +@@ -73,7 +73,6 @@ + "marked-katex-extension": "^5.1.1", + "marked-linkify-it": "^3.1.11", + "md5": "^2.3.0", +- "plausible-tracker": "^0.3.9", + "svelte": "^4.2.19", + "twemoji": "^14.0.2", + "zod": "^3.23.8" +diff --git a/src/App.svelte b/src/App.svelte +index 8161c390..4281ba61 100644 +--- a/src/App.svelte ++++ b/src/App.svelte +@@ -1,6 +1,4 @@ + <script lang="ts"> +- import Plausible from "plausible-tracker"; +- + import * as router from "@app/lib/router"; + import { unreachable } from "@app/lib/utils"; + +@@ -28,12 +26,6 @@ + + void router.loadFromLocation(); + +- if (import.meta.env.PROD) { +- const plausible = Plausible({ domain: "app.radicle.xyz" }); +- +- plausible.enableAutoPageviews(); +- } +- + $: document.documentElement.setAttribute("data-codefont", $codeFont); + $: document.documentElement.setAttribute("data-theme", $theme); + </script> +-- +2.46.0 + diff --git a/third_party/radicle-explorer/default.nix b/third_party/radicle-explorer/default.nix new file mode 100644 index 000000000000..7bf7dc3798d9 --- /dev/null +++ b/third_party/radicle-explorer/default.nix @@ -0,0 +1,66 @@ +# radicle-explorer is the web UI for Radicle. +# +# They have an upstream Nix derivation, but it only works with experimental +# features Nix and is quite messy, so this is a copy of the relevant parts. +{ lib, pkgs, ... }: + +let + twemoji-assets = pkgs.fetchFromGitHub { + owner = "twitter"; + repo = "twemoji"; + rev = "v14.0.2"; + hash = "sha256-YoOnZ5uVukzi/6bLi22Y8U5TpplPzB7ji42l+/ys5xI="; + }; + + httpdSrc = pkgs.radicle-httpd.src; +in +lib.fix (self: pkgs.buildNpmPackage rec { + pname = "radicle-explorer"; + version = (builtins.fromJSON (builtins.readFile "${src}/package.json")).version; + + # source should be synced with the httpd, which is already in nixpkgs + src = pkgs.fetchgit { + inherit (httpdSrc) url rev; + hash = "sha256:09m13238h6j7g02r6332ihgyyzbjx90pgz14rz29pgv7936h6il8"; + }; + + # This might change during nixpkgs bumps and will need updating. Need to fix + # upstream so that there is a normal, callable derivation. + npmDepsHash = "sha256:1hbrzfjkfc0q8qk03yi6qb9zqm57h7hnkn7fl0yxkrzbrljaljaz"; + + patches = [ + ./0001-remove-dependency-on-plausible.patch + ]; + + postPatch = '' + patchShebangs --build ./scripts + mkdir -p "public/twemoji" + cp -t public/twemoji -r -- ${twemoji-assets}/assets/svg/* + : >scripts/install-twemoji-assets + ''; + dontConfigure = true; + doCheck = false; + + installPhase = '' + runHook preInstall + mkdir -p "$out" + cp -r -t "$out" build/* + runHook postInstall + ''; + + # Override the build-time configuration with other preferred seeds which are + # displayed on the landing page. + passthru.withPreferredSeeds = seeds: + let + originalConfig = builtins.fromJSON (builtins.readFile "${src}/config/default.json"); + config = originalConfig // { + preferredSeeds = seeds; + }; + newConfig = pkgs.writeText "local.json" (builtins.toJSON config); + in + self.overrideAttrs (_: { + preBuild = '' + cp ${newConfig} config/local.json + ''; + }); +}) diff --git a/third_party/rust-crates/default.nix b/third_party/rust-crates/default.nix index 697e47cddefc..a473a8346a6b 100644 --- a/third_party/rust-crates/default.nix +++ b/third_party/rust-crates/default.nix @@ -292,130 +292,4 @@ depot.nix.readTree.drvTargets rec{ sha256 = "1kd047p8jv6mhmfzddjvfa2nwkfrb3l1wml6lfm51n1cr06cc9lz"; }; - libz-sys = buildRustCrate { - pname = "libz-sys"; - version = "1.1.2"; - sha256 = "1y7v6bkwr4b6yaf951p1ns7mx47b29ziwdd5wziaic14gs1gwq30"; - buildDependencies = [ - cc - pkg-config - ]; - }; - - libgit2-sys = buildRustCrate { - pname = "libgit2-sys"; - version = "0.16.2+1.7.2"; - sha256 = "0bs446idbmg8s13jvb0ck6qmrskcdn2mp3d4mn9ggxbmiw4ryd3g"; - dependencies = [ - libc - libz-sys - ]; - libPath = "lib.rs"; - libName = "libgit2_sys"; - # TODO: this should be available via `pkgs.defaultCrateOverrides`, - # I thought that was included by default? - nativeBuildInputs = [ pkg-config ]; - buildInputs = [ pkgs.zlib pkgs.libgit2 ]; - buildDependencies = [ - cc - pkg-config - ]; - env.LIBGIT2_NO_VENDOR = "1"; - }; - - matches = buildRustCrate { - pname = "matches"; - version = "0.1.8"; - sha256 = "03hl636fg6xggy0a26200xs74amk3k9n0908rga2szn68agyz3cv"; - libPath = "lib.rs"; - }; - - percent-encoding = buildRustCrate { - pname = "percent-encoding"; - version = "2.1.0"; - sha256 = "0i838f2nr81585ckmfymf8l1x1vdmx6n8xqvli0lgcy60yl2axy3"; - libPath = "lib.rs"; - }; - - form_urlencoded = buildRustCrate { - pname = "form_urlencoded"; - version = "1.0.1"; - sha256 = "0rhv2hfrzk2smdh27walkm66zlvccnnwrbd47fmf8jh6m420dhj8"; - dependencies = [ - matches - percent-encoding - ]; - }; - - tinyvec_macros = buildRustCrate { - pname = "tinyvec_macros"; - version = "0.1.0"; - sha256 = "0aim73hyq5g8b2hs9gjq2sv0xm4xzfbwp5fdyg1frljqzkapq682"; - }; - - tinyvec = buildRustCrate { - pname = "tinyvec"; - version = "1.2.0"; - sha256 = "1c95nma20kiyrjwfsk7hzd5ir6yy4bm63fmfbfb4dm9ahnlvdp3y"; - features = [ "alloc" ]; - dependencies = [ - tinyvec_macros - ]; - }; - - unicode-normalization = buildRustCrate { - pname = "unicode-normalization"; - version = "0.1.17"; - sha256 = "0w4s0avzlf7pzcclhhih93aap613398sshm6jrxcwq0f9lhis11c"; - dependencies = [ - tinyvec - ]; - }; - - unicode-bidi = buildRustCrate { - pname = "unicode-bidi"; - version = "0.3.5"; - sha256 = "193jzlxj1dfcms2381lyd45zh4ywlicj9lzcfpid1zbkmfarymkz"; - dependencies = [ - matches - ]; - }; - - idna = buildRustCrate { - pname = "idna"; - version = "0.2.3"; - sha256 = "0hwypd0fpym9lmd4bbqpwyr5lhrlvmvzhi1vy9asc5wxwkzrh299"; - dependencies = [ - matches - unicode-normalization - unicode-bidi - ]; - }; - - url = buildRustCrate { - pname = "url"; - version = "2.2.1"; - sha256 = "1ci1djafh83qhpzbmxnr9w5gcrjs3ghf8rrxdy4vklqyji6fvn5v"; - dependencies = [ - form_urlencoded - idna - matches - percent-encoding - ]; - }; - - - git2 = buildRustCrate { - pname = "git2"; - edition = "2018"; - version = "0.18.1"; - sha256 = "1d1wm8cn37svyxgvzfapwilkkc9d2x7fcrgciwn8b2pv9aqz102k"; - dependencies = [ - bitflags - libc - libgit2-sys - log - url - ]; - }; } diff --git a/third_party/sources/sources.json b/third_party/sources/sources.json index 109451ff510e..eef1ffee9c98 100644 --- a/third_party/sources/sources.json +++ b/third_party/sources/sources.json @@ -5,10 +5,22 @@ "homepage": "https://matrix.to/#/#agenix:nixos.org", "owner": "ryantm", "repo": "agenix", - "rev": "0.15.0", - "sha256": "01dhrghwa7zw93cybvx4gnrskqk97b004nfxgsys0736823956la", + "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "sha256": "1x8nd8hvsq6mvzig122vprwigsr3z2skanig65haqswn7z7amsvg", "type": "tarball", - "url": "https://github.com/ryantm/agenix/archive/0.15.0.tar.gz", + "url": "https://github.com/ryantm/agenix/archive/f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41.tar.gz", + "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" + }, + "gitignore.nix": { + "branch": "master", + "description": "Nix functions for filtering local git sources", + "homepage": "", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "sha256": "02wxkdpbhlm3yk5mhkhsp3kwakc16xpmsf2baw57nz1dg459qv8w", + "type": "tarball", + "url": "https://github.com/hercules-ci/gitignore.nix/archive/637db329424fd7e46cf4185293b9cc8c88c95394.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "home-manager": { @@ -17,10 +29,10 @@ "homepage": "https://nix-community.github.io/home-manager/", "owner": "nix-community", "repo": "home-manager", - "rev": "c1609d584a6b5e9e6a02010f51bd368cb4782f8e", - "sha256": "112r86p3iah1xahwlp82yd3gvh10wkf271za5h7v3jsqv08c6gkr", + "rev": "93435d27d250fa986bfec6b2ff263161ff8288cb", + "sha256": "0vf36nfm1l77493jsyc3xzjndd79ayrvzkpc7yzvgzirs766ggww", "type": "tarball", - "url": "https://github.com/nix-community/home-manager/archive/c1609d584a6b5e9e6a02010f51bd368cb4782f8e.tar.gz", + "url": "https://github.com/nix-community/home-manager/archive/93435d27d250fa986bfec6b2ff263161ff8288cb.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "impermanence": { @@ -29,10 +41,10 @@ "homepage": "", "owner": "nix-community", "repo": "impermanence", - "rev": "a33ef102a02ce77d3e39c25197664b7a636f9c30", - "sha256": "1mig6ns8l5iynsm6pfbnx2b9hmr592s1kqbw6gq1n25czdlcniam", + "rev": "e337457502571b23e449bf42153d7faa10c0a562", + "sha256": "0l242sa21jv53lkjh180dp5x9ip1blrz3gbks9m604kmk520csqb", "type": "tarball", - "url": "https://github.com/nix-community/impermanence/archive/a33ef102a02ce77d3e39c25197664b7a636f9c30.tar.gz", + "url": "https://github.com/nix-community/impermanence/archive/e337457502571b23e449bf42153d7faa10c0a562.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "naersk": { @@ -41,10 +53,10 @@ "homepage": "", "owner": "nmattia", "repo": "naersk", - "rev": "c5037590290c6c7dae2e42e7da1e247e54ed2d49", - "sha256": "1ql5ziwfrpmc8cxhgflmdy2z06z4dsdfzjwb2vv9bag6a2chrvq8", + "rev": "3fb418eaf352498f6b6c30592e3beb63df42ef11", + "sha256": "0v6ncaqm8q2mdv1jhkjjwi1sx4firlhjxpw4wachkwkriyjnkz5g", "type": "tarball", - "url": "https://github.com/nmattia/naersk/archive/c5037590290c6c7dae2e42e7da1e247e54ed2d49.tar.gz", + "url": "https://github.com/nmattia/naersk/archive/3fb418eaf352498f6b6c30592e3beb63df42ef11.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "napalm": { @@ -53,10 +65,10 @@ "homepage": "", "owner": "nix-community", "repo": "napalm", - "rev": "edcb26c266ca37c9521f6a97f33234633cbec186", - "sha256": "0ai1ax380nnpz0mbgbc5vdzafyjilcmdj7kgv087x2vagpprb4yy", + "rev": "e1babff744cd278b56abe8478008b4a9e23036cf", + "sha256": "04h62p4hxw7fhclki7hcn739hhig3rh9q4njp24j7bm0dk2kj8h6", "type": "tarball", - "url": "https://github.com/nix-community/napalm/archive/edcb26c266ca37c9521f6a97f33234633cbec186.tar.gz", + "url": "https://github.com/nix-community/napalm/archive/e1babff744cd278b56abe8478008b4a9e23036cf.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "nixpkgs": { @@ -65,10 +77,10 @@ "homepage": "", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7bb2ccd8cdc44c91edba16c48d2c8f331fb3d856", - "sha256": "0ijqx995jw9i16f28whyjdll9b0nydmyl4n91bci2cgryxms7f8f", + "rev": "2768c7d042a37de65bb1b5b3268fc987e534c49d", + "sha256": "17pikpqk1icgy4anadd9yg3plwfrsmfwv1frwm78jg2rf84jcmq2", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/7bb2ccd8cdc44c91edba16c48d2c8f331fb3d856.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/2768c7d042a37de65bb1b5b3268fc987e534c49d.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "nixpkgs-stable": { @@ -77,10 +89,10 @@ "homepage": "", "owner": "NixOS", "repo": "nixpkgs", - "rev": "dd37924974b9202f8226ed5d74a252a9785aedf8", - "sha256": "1nxd4dqci8rs94a7cypx30axgj778p2wydkx16q298n29crkflbw", + "rev": "205fd4226592cc83fd4c0885a3e4c9c400efabb5", + "sha256": "1f5d2g1p6nfwycpmrnnmc2xmcszp804adp16knjvdkj8nz36y1fg", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/dd37924974b9202f8226ed5d74a252a9785aedf8.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/205fd4226592cc83fd4c0885a3e4c9c400efabb5.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "rust-overlay": { @@ -89,10 +101,10 @@ "homepage": "", "owner": "oxalica", "repo": "rust-overlay", - "rev": "2a42c742ab04b61d9b2f1edf392842cf9f27ebfd", - "sha256": "1wpkca75ysb2ssycc0dshd1m76q8iqhzrrbr6xmfmkkcj1p333nk", + "rev": "17cadbc36da05e75197d082decb382a5f4208e30", + "sha256": "0vh5nlmvig418d15w7yz3ls0x56jdwlvbs9kgr7ri0lsng2v2ykr", "type": "tarball", - "url": "https://github.com/oxalica/rust-overlay/archive/2a42c742ab04b61d9b2f1edf392842cf9f27ebfd.tar.gz", + "url": "https://github.com/oxalica/rust-overlay/archive/17cadbc36da05e75197d082decb382a5f4208e30.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "rustsec-advisory-db": { @@ -101,10 +113,10 @@ "homepage": "https://rustsec.org", "owner": "RustSec", "repo": "advisory-db", - "rev": "35e7459a331d3e0c585e56dabd03006b9b354088", - "sha256": "1j8c0vzwg6b9lxmdy2a40pvwsy2kncv455spbjbxsj10p2vmy5fl", + "rev": "c586bd65ec3543e2fe2f21e358f0645220822325", + "sha256": "17my60z1yg5yn9l4wp8a0gqwfyx2njai2nhghj3dkljhvkgsn30n", "type": "tarball", - "url": "https://github.com/RustSec/advisory-db/archive/35e7459a331d3e0c585e56dabd03006b9b354088.tar.gz", + "url": "https://github.com/RustSec/advisory-db/archive/c586bd65ec3543e2fe2f21e358f0645220822325.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" } } diff --git a/third_party/teleirc/default.nix b/third_party/teleirc/default.nix new file mode 100644 index 000000000000..87915110024f --- /dev/null +++ b/third_party/teleirc/default.nix @@ -0,0 +1,23 @@ +{ pkgs, lib, ... }: + +pkgs.buildGoModule rec { + name = "teleirc"; + version = "2.3.0-4"; + + src = pkgs.fetchFromGitHub { + owner = "tvlfyi"; + repo = "teleirc"; + rev = "356ed1450840822172e7dff57965cc5371f63454"; + sha256 = "0s6rlixks7lar9js4q1drg742cy2p4n8l4pmlzjmskl5d04c15gq"; + }; + + vendorHash = "sha256:06f2wyxbphj73wknpp6dsn7rb4yhvdl6x0gj729cns7r4bsviscs"; + ldflags = [ "-s" "-w" "-X" "main.version=${version}" ]; + postInstall = "mv $out/bin/cmd $out/bin/teleirc"; + + meta = with lib; { + description = "IRC/Telegram bridge"; + homepage = "https://docs.teleirc.com/en/latest/"; + license = licenses.gpl3; + }; +} diff --git a/tools/cheddar/Cargo.lock b/tools/cheddar/Cargo.lock index 41632ea15927..c88cba580a08 100644 --- a/tools/cheddar/Cargo.lock +++ b/tools/cheddar/Cargo.lock @@ -3,10 +3,10 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "adler32" @@ -16,9 +16,9 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -64,50 +64,51 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -129,9 +130,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "base64" @@ -141,9 +142,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bincode" @@ -177,9 +178,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -192,9 +193,9 @@ dependencies = [ [[package]] name = "brotli" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -223,17 +224,23 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.84" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f8e7c90afad890484a21653d08b6e209ae34770fb5ee298f9c699fcc1e5c856" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ - "libc", + "shlex", ] [[package]] @@ -258,21 +265,21 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] name = "chunked_transfer" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cca491388666e04d7248af3f60f0c40cfb0991c72205595d7c396e3510207d1a" +checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" [[package]] name = "clap" @@ -291,9 +298,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.8" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -301,22 +308,22 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.8" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.10.0", + "strsim 0.11.1", "terminal_size", ] [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck", "proc-macro2", @@ -326,15 +333,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "comrak" @@ -342,7 +349,7 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c11e55664fcff7f4d37cc2adf3a1996913692f037312f4ab0909047fdd2bf962" dependencies = [ - "clap 4.4.8", + "clap 4.5.16", "entities", "memchr", "once_cell", @@ -358,24 +365,24 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -402,9 +409,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -433,12 +440,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -453,27 +460,27 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", - "windows-sys", + "libredox", + "windows-sys 0.59.0", ] [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", "miniz_oxide", @@ -487,9 +494,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -506,9 +513,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -526,15 +533,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" @@ -547,15 +554,15 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -565,9 +572,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -588,9 +595,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -598,48 +605,56 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", ] [[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] -name = "line-wrap" -version = "0.1.1" +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "safemem", + "bitflags 2.6.0", + "libc", + "redox_syscall", ] [[package]] @@ -650,21 +665,21 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -674,9 +689,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -684,11 +699,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -710,10 +725,16 @@ dependencies = [ ] [[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -724,24 +745,24 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.9", "libc", ] [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "onig" @@ -767,15 +788,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.5" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -784,9 +805,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.5" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -794,9 +815,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.5" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", @@ -807,9 +828,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.5" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -818,19 +839,18 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plist" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ - "base64 0.21.5", + "base64 0.22.1", "indexmap", - "line-wrap", "quick-xml", "serde", "time", @@ -844,15 +864,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -865,18 +888,18 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quick-xml" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -913,56 +936,41 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" - -[[package]] -name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rouille" @@ -990,22 +998,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safemem" @@ -1024,18 +1032,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.192" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", @@ -1044,20 +1052,21 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "sha1_smol" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" @@ -1077,6 +1086,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1084,15 +1099,15 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.39" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -1101,9 +1116,9 @@ dependencies = [ [[package]] name = "syntect" -version = "5.1.0" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02b4b303bf8d08bfeb0445cba5068a3d306b6baece1d5582171a9bf49188f91" +checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1" dependencies = [ "bincode", "bitflags 1.3.2", @@ -1113,8 +1128,9 @@ dependencies = [ "once_cell", "onig", "plist", - "regex-syntax 0.7.5", + "regex-syntax", "serde", + "serde_derive", "serde_json", "thiserror", "walkdir", @@ -1123,15 +1139,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "once_cell", "rustix", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1141,7 +1157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1155,18 +1171,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -1184,13 +1200,14 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", "libc", + "num-conv", "num_threads", "powerfmt", "serde", @@ -1206,10 +1223,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -1227,9 +1245,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -1278,9 +1296,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -1290,18 +1308,18 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode_categories" @@ -1311,9 +1329,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "url" -version = "2.4.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -1322,9 +1340,9 @@ dependencies = [ [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "vec_map" @@ -1334,15 +1352,15 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -1356,19 +1374,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -1381,9 +1400,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1391,9 +1410,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -1404,9 +1423,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "winapi" @@ -1426,11 +1445,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -1441,11 +1460,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1454,7 +1473,25 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -1463,13 +1500,29 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -1479,42 +1532,90 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] name = "xdg" version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1528,3 +1629,24 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/tools/depot-deps.nix b/tools/depot-deps.nix index c2f1cd302ce8..5fa1fe23be20 100644 --- a/tools/depot-deps.nix +++ b/tools/depot-deps.nix @@ -8,6 +8,7 @@ depot.nix.lazy-deps { depotfmt.attr = "tools.depotfmt"; fetch-depot-inbox.attr = "tools.fetch-depot-inbox"; git-r.attr = "tools.git-r"; + git-review.attr = "third_party.nixpkgs.git-review"; gerrit-update.attr = "tools.gerrit-update"; gerrit.attr = "tools.gerrit-cli"; hash-password.attr = "tools.hash-password"; diff --git a/tools/depotfmt.nix b/tools/depotfmt.nix index 706b7c05a5a4..7c45f8be44b4 100644 --- a/tools/depotfmt.nix +++ b/tools/depotfmt.nix @@ -1,24 +1,14 @@ # Builds treefmt for depot, with a hardcoded configuration that # includes the right paths to formatters. -{ depot, pkgs, ... }: +{ pkgs, ... }: let - # terraform fmt can't handle multiple paths at once, but treefmt - # expects this - terraformat = pkgs.writeShellScript "terraformat" '' - echo "$@" | xargs -n1 ${pkgs.terraform}/bin/terraform fmt - ''; - config = pkgs.writeText "depot-treefmt-config" '' [formatter.go] - command = "${depot.nix.buildGo.go}/bin/gofmt" + command = "${pkgs.go}/bin/gofmt" options = [ "-w" ] includes = ["*.go"] - [formatter.tf] - command = "${terraformat}" - includes = [ "*.tf" ] - [formatter.nix] command = "${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt" includes = [ "*.nix" ] @@ -28,8 +18,10 @@ let [formatter.rust] command = "${pkgs.rustfmt}/bin/rustfmt" + options = ["--edition", "2021"] includes = [ "*.rs" ] excludes = [ + "users/emery/*", "users/tazjin/*", ] ''; @@ -37,23 +29,28 @@ let # helper tool for formatting the depot interactively depotfmt = pkgs.writeShellScriptBin "depotfmt" '' exec ${pkgs.treefmt}/bin/treefmt ''${@} \ - --config-file ${config} \ + --on-unmatched=debug \ + --config-file=${config} \ --tree-root $(${pkgs.git}/bin/git rev-parse --show-toplevel) ''; # wrapper script for running formatting checks in CI check = pkgs.writeShellScript "depotfmt-check" '' ${pkgs.treefmt}/bin/treefmt \ - --clear-cache \ + --no-cache \ + --on-unmatched=debug \ --fail-on-change \ - --config-file ${config} \ - --tree-root . + --config-file=${config} \ + --tree-root=. ''; in depotfmt.overrideAttrs (_: { - passthru.meta.ci.extraSteps.check = { - label = "depot formatting check"; - command = check; - alwaysRun = true; + passthru = { + inherit config check; + meta.ci.extraSteps.check = { + label = "depot formatting check"; + command = check; + alwaysRun = true; + }; }; }) diff --git a/tools/eaglemode/commands/B.nix b/tools/eaglemode/commands/B.nix new file mode 100644 index 000000000000..bca3d3a87a87 --- /dev/null +++ b/tools/eaglemode/commands/B.nix @@ -0,0 +1,23 @@ +{ depot, pkgs, ... }: + +let + em = depot.tools.eaglemode; +in +em.mkCommand { + name = "9 B"; + hotkey = "Ctrl+E"; + icon = "${./plan9.tga}"; + + description = '' + Plumb target to Sam or Acme + ''; + + code = '' + ErrorIfNotSingleTarget(); + + my @tgt=GetTgt(); + my $dir=$tgt[0]; + + ExecOrError('${pkgs.plan9port}/bin/9', 'B', $dir); + ''; +} diff --git a/tools/eaglemode/commands/emacsclient.nix b/tools/eaglemode/commands/emacsclient.nix new file mode 100644 index 000000000000..bac3674120ee --- /dev/null +++ b/tools/eaglemode/commands/emacsclient.nix @@ -0,0 +1,26 @@ +{ depot, pkgs, ... }: + +let + em = depot.tools.eaglemode; + icon = em.mkTGA "emacs" "${pkgs.emacs}/share/icons/hicolor/128x128/apps/emacs.png"; +in +em.mkCommand { + name = "Emacsclient"; + hotkey = "Ctrl+E"; + icon = "${icon}"; + + description = '' + Open target in Emacsclient. + + Emacs server must be running already for this to have any effect. + ''; + + code = '' + ErrorIfNotSingleTarget(); + + my @tgt=GetTgt(); + my $dir=$tgt[0]; + + ExecOrError('${pkgs.emacs}/bin/emacsclient', '-n', $dir); + ''; +} diff --git a/tools/eaglemode/commands/plan9.tga b/tools/eaglemode/commands/plan9.tga new file mode 100644 index 000000000000..55d002221a9b --- /dev/null +++ b/tools/eaglemode/commands/plan9.tga Binary files differdiff --git a/tools/eaglemode/default.nix b/tools/eaglemode/default.nix new file mode 100644 index 000000000000..30983f5d5018 --- /dev/null +++ b/tools/eaglemode/default.nix @@ -0,0 +1,146 @@ +# Helper functions for extending Eagle Mode with useful stuff. +# +# Eagle Mode's customisation usually expects people to copy the entire +# configuration into their user folder, which we can automate fairly easily +# using Nix, letting users choose whether to keep upstream config or not. +{ depot, lib, pkgs, ... }: + +let + mkDesc = d: lib.concatMapStringsSep "\n" + (x: "# Descr =${x}") + (builtins.filter (s: s != "") (lib.splitString "\n" d)); + + configWrapper = pkgs.runCommand "eaglemode-config-wrapper" { } '' + cp ${./wrapper.go} wrapper.go + export HOME=$PWD + ${pkgs.go}/bin/go build wrapper.go + install -Dm755 wrapper $out/bin/wrapper + ''; +in +rec { + # mkCommand creates an Eagle Mode command for the file browser. + # + # Commands are basically little Perl scripts with a command standard library + # available. They receive the user's selected target from Eagle Mode. + mkCommand = lib.makeOverridable ( + { + # Name of the command. + name + , # User-facing description, displayed in Eagle Mode UI. Can be multi-line. + description + , # Verbatim Perl code of the command. Command library is already available. + code + , # Caption for the UI button (defaults to name). + caption ? name + , icon ? "terminal.tga" + , # TODO: what's a good default? + hotkey ? "" + , order ? 1.0 + }: pkgs.writeTextDir "emFileMan/Commands/${name}.pl" ('' + #!${pkgs.perl}/bin/perl + #[[BEGIN PROPERTIES]] + # Type = Command + # Interpreter = perl + # DefaultFor = directory + # Caption = ${caption} + # Order = ${toString order} + # Icon = ${icon} + '' + + (lib.optionalString (description != "") "${mkDesc description}\n") + + (lib.optionalString (hotkey != "") "# Hotkey = ${hotkey}\n") + + '' + #[[END PROPERTIES]] + + use strict; + use warnings; + BEGIN { require "$ENV{'EM_DIR'}/res/emFileMan/scripts/cmd-util.pl"; } + + ${if builtins.isString code + then code + else (if builtins.isPath code + then builtins.readFile code + else throw "code must be a string (literal code) or path to file")} + '') + ); + + # mkTGA converts the given image to a TGA image. + mkTGA = name: path: pkgs.runCommand "${name}.tga" { } '' + ${pkgs.imagemagick}/bin/convert ${path} $out + ''; + + buildPlugin = lib.makeOverridable ( + { name + , src + , version + , eaglemode ? pkgs.eaglemode + , target ? name + , extraNativeBuildInputs ? [ ] + , extraBuildInputs ? [ ] + }: + pkgs.stdenv.mkDerivation { + pname = "eaglemode-plugin-${name}"; + inherit src version; + # inherit (eaglemode.drvAttrs) dontPatchELF; + + nativeBuildInputs = eaglemode.drvAttrs.nativeBuildInputs ++ extraNativeBuildInputs; + buildInputs = eaglemode.drvAttrs.buildInputs ++ extraBuildInputs ++ [ eaglemode ]; + + buildPhase = '' + runHook preBuild + + # merge eaglemode & plugin folders + cp -r ${pkgs.srcOnly eaglemode} merged-src && chmod -R u+rw merged-src + cp -r $src/* merged-src && chmod -R u+rw merged-src + cd merged-src + + export NIX_LDFLAGS="$NIX_LDFLAGS -lXxf86vm -lXext -lXinerama" + perl make.pl build projects=${target} continue=no + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/lib + cp -r lib/lib${target}.so $out/lib + + if [ -d "$src/etc" ]; then + cp -r $src/etc/* $out + fi + + runHook postInstall + ''; + } + ); + + # etcDir creates a directory layout suitable for use in the EM_USER_CONFIG_DIR + # environment variable. + # + # Note that Eagle Mode requires the value of that variable to be mutable at + # runtime (it is the same place where it persists all of its user-controlled + # state), so the results of this function can not be used directly. + etcDir = + { eaglemode ? pkgs.eaglemode + , extraPaths ? [ ] + }: pkgs.runCommand "eaglemode-config" { } '' + mkdir $out + + ${ + lib.concatMapStringsSep "\n" (s: "cp -rT ${s} $out/\nchmod -R u+rw $out/\n") ([ "${eaglemode}/etc"] ++ extraPaths) + } + ''; + + # withConfig creates an Eagle Mode wrapper that runs it with the given + # configuration. + withConfig = { eaglemode ? pkgs.eaglemode, config }: pkgs.writeShellScriptBin "eaglemode" '' + ${configWrapper}/bin/wrapper --em-config "${config}" + + if [ -d "${config}/lib" ]; then + export LD_LIBRARY_PATH="${config}/lib:$LD_LIBRARY_PATH" + exec ${eaglemode}/bin/eaglemode "$@" + fi + + exec ${eaglemode}/bin/eaglemode "$@" + ''; +} diff --git a/tools/eaglemode/plugins/avif/default.nix b/tools/eaglemode/plugins/avif/default.nix new file mode 100644 index 000000000000..07577c685cc7 --- /dev/null +++ b/tools/eaglemode/plugins/avif/default.nix @@ -0,0 +1,10 @@ +{ depot, pkgs, ... }: + +depot.tools.eaglemode.buildPlugin { + name = "avif"; + version = "canon"; + src = ./.; + target = "PlAvif"; + extraBuildInputs = [ pkgs.libavif ]; + extraNativeBuildInputs = [ pkgs.pkg-config ]; +} diff --git a/tools/eaglemode/plugins/avif/etc/emCore/FpPlugins/PlAvif.emFpPlugin b/tools/eaglemode/plugins/avif/etc/emCore/FpPlugins/PlAvif.emFpPlugin new file mode 100644 index 000000000000..61615f9fd391 --- /dev/null +++ b/tools/eaglemode/plugins/avif/etc/emCore/FpPlugins/PlAvif.emFpPlugin @@ -0,0 +1,6 @@ +#%rec:emFpPlugin%# + +FileTypes = { ".avif" } +Priority = 1.0 +Library = "PlAvif" +Function = "PlAvifFpPluginFunc" diff --git a/tools/eaglemode/plugins/avif/makers/PlAvif.maker.pm b/tools/eaglemode/plugins/avif/makers/PlAvif.maker.pm new file mode 100644 index 000000000000..00b927805a72 --- /dev/null +++ b/tools/eaglemode/plugins/avif/makers/PlAvif.maker.pm @@ -0,0 +1,64 @@ +package PlAvif; + +use strict; +use warnings; + +sub GetDependencies +{ + return ('emCore'); +} + +sub IsEssential +{ + return 0; +} + +sub GetFileHandlingrules +{ + return (); +} + +sub GetExtraBuildOptions +{ + return (); +} + +sub Build +{ + shift; + my %options=@_; + + my @libAvifFlags=(); + if ($options{'avif-inc-dir'} eq '' && $options{'avif-lib-dir'} eq '') { + @libAvifFlags=split("\n",readpipe( + "perl \"".$options{'utils'}."/PkgConfig.pl\" libavif" + )); + } + if (!@libAvifFlags) { + if ($options{'avif-inc-dir'} ne '') { + push(@libAvifFlags, "--inc-search-dir", $options{'avif-inc-dir'}); + } + if ($options{'avif-lib-dir'} ne '') { + push(@libAvifFlags, "--lib-search-dir", $options{'avif-lib-dir'}); + } + push(@libAvifFlags, "--link", "avif"); + } + + system( + @{$options{'unicc_call'}}, + "--math", + "--rtti", + "--exceptions", + "--bin-dir" , "bin", + "--lib-dir" , "lib", + "--obj-dir" , "obj", + "--inc-search-dir", "include", + @libAvifFlags, + "--link" , "emCore", + "--type" , "dynlib", + "--name" , "PlAvif", + "src/PlAvif.cpp" + )==0 or return 0; + + return 1; +} diff --git a/tools/eaglemode/plugins/avif/src/PlAvif.cpp b/tools/eaglemode/plugins/avif/src/PlAvif.cpp new file mode 100644 index 000000000000..e4807bacd49a --- /dev/null +++ b/tools/eaglemode/plugins/avif/src/PlAvif.cpp @@ -0,0 +1,190 @@ +#include <emCore/emFpPlugin.h> +#include <emCore/emImageFile.h> + +#include "avif/avif.h" + +class PlAvifImageFileModel : public emImageFileModel +{ +public: + + static emRef<PlAvifImageFileModel> Acquire( + emContext & context, const emString & name, bool common=true + ); + +protected: + PlAvifImageFileModel(emContext & context, const emString & name); + virtual ~PlAvifImageFileModel(); + virtual void TryStartLoading(); + virtual bool TryContinueLoading(); + virtual void QuitLoading(); + virtual void TryStartSaving(); + virtual bool TryContinueSaving(); + virtual void QuitSaving(); + virtual emUInt64 CalcMemoryNeed(); + virtual double CalcFileProgress(); + +private: + struct LoadingState; + LoadingState * L = NULL; +}; + + +struct PlAvifImageFileModel::LoadingState { + avifRGBImage rgb; + avifDecoder * decoder; +}; + + +emRef<PlAvifImageFileModel> PlAvifImageFileModel::Acquire( + emContext & context, const emString & name, bool common +) +{ + EM_IMPL_ACQUIRE(PlAvifImageFileModel, context, name, common) +} + + +PlAvifImageFileModel::PlAvifImageFileModel( + emContext & context, const emString & name +) + : emImageFileModel(context, name) +{ +} + + +PlAvifImageFileModel::~PlAvifImageFileModel() +{ + PlAvifImageFileModel::QuitLoading(); + PlAvifImageFileModel::QuitSaving(); +} + + +void PlAvifImageFileModel::TryStartLoading() +{ + avifResult result; + + L = new LoadingState; + memset(L, 0, sizeof(LoadingState)); + + L->decoder = avifDecoderCreate(); + if (L->decoder == NULL) { + throw emException("failed to create AVIF decoder"); + } + + result = avifDecoderSetIOFile(L->decoder, GetFilePath()); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + result = avifDecoderParse(L->decoder); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + FileFormatInfo = emString::Format( + "AVIF %s %ubpc", + avifPixelFormatToString(L->decoder->image->yuvFormat), + L->decoder->image->depth + ); + + + Signal(ChangeSignal); +} + + +bool PlAvifImageFileModel::TryContinueLoading() +{ + avifResult result; + + if (!Image.GetHeight()) { + Image.Setup( + L->decoder->image->width, + L->decoder->image->height, + L->decoder->alphaPresent ? 4 : 3 + ); + } + + result = avifDecoderNextImage(L->decoder); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + avifRGBImageSetDefaults(&L->rgb, L->decoder->image); + L->rgb.format = L->decoder->alphaPresent ? + AVIF_RGB_FORMAT_RGBA : AVIF_RGB_FORMAT_RGB; + L->rgb.pixels = Image.GetWritableMap(); + L->rgb.width = Image.GetWidth(); + L->rgb.height = Image.GetHeight(); + L->rgb.depth = 8; + L->rgb.rowBytes = Image.GetWidth() * Image.GetChannelCount(); + + result = avifImageYUVToRGB(L->decoder->image, &L->rgb); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + Signal(ChangeSignal); + return true; +} + + +void PlAvifImageFileModel::QuitLoading() +{ + if (L) { + if (L->decoder) avifDecoderDestroy(L->decoder); + delete L; + L = NULL; + } +} + + +void PlAvifImageFileModel::TryStartSaving() +{ + throw emException("PlAvifImageFileModel: Saving not implemented."); +} + + +bool PlAvifImageFileModel::TryContinueSaving() +{ + return false; +} + + +void PlAvifImageFileModel::QuitSaving() +{ +} + + +emUInt64 PlAvifImageFileModel::CalcMemoryNeed() +{ + return + (emUInt64) + L->decoder->image->width * + L->decoder->image->height * + (L->decoder->alphaPresent ? 4 : 3); +} + + +double PlAvifImageFileModel::CalcFileProgress() +{ + return 0.0; +} + +extern "C" { + emPanel * PlAvifFpPluginFunc( + emPanel::ParentArg parent, const emString & name, + const emString & path, emFpPlugin * plugin, + emString * errorBuf + ) + { + if (plugin->Properties.GetCount()) { + *errorBuf="PlAvifFpPlugin: No properties allowed."; + return NULL; + } + return new emImageFilePanel( + parent, name, + PlAvifImageFileModel::Acquire( + parent.GetRootContext(), path + ) + ); + } +} diff --git a/tools/eaglemode/plugins/example.nix b/tools/eaglemode/plugins/example.nix new file mode 100644 index 000000000000..b361971cc57e --- /dev/null +++ b/tools/eaglemode/plugins/example.nix @@ -0,0 +1,17 @@ +{ depot, pkgs, ... }: + +let + em = depot.tools.eaglemode; + emSrc = with pkgs; srcOnly eaglemode; +in +em.buildPlugin { + name = "example"; + version = "canon"; + + src = pkgs.runCommand "em-plugin-example-src" { } '' + set -ux + cp -r ${emSrc}/doc/examples/CppApiExamples/PluginExample $out + ''; + + target = "PlEx"; +} diff --git a/tools/eaglemode/plugins/qoi/default.nix b/tools/eaglemode/plugins/qoi/default.nix new file mode 100644 index 000000000000..8764ac39e88d --- /dev/null +++ b/tools/eaglemode/plugins/qoi/default.nix @@ -0,0 +1,12 @@ +{ depot, pkgs, ... }: + +let + em = depot.tools.eaglemode; + emSrc = pkgs.srcOnly pkgs.em; +in +em.buildPlugin { + name = "qoi"; + version = "canon"; + src = ./.; + target = "PlQoi"; +} diff --git a/tools/eaglemode/plugins/qoi/etc/emCore/FpPlugins/PlQoi.emFpPlugin b/tools/eaglemode/plugins/qoi/etc/emCore/FpPlugins/PlQoi.emFpPlugin new file mode 100644 index 000000000000..e27f37261d77 --- /dev/null +++ b/tools/eaglemode/plugins/qoi/etc/emCore/FpPlugins/PlQoi.emFpPlugin @@ -0,0 +1,6 @@ +#%rec:emFpPlugin%# + +FileTypes = { ".qoi" } +Priority = 1.0 +Library = "PlQoi" +Function = "PlQoiFpPluginFunc" diff --git a/tools/eaglemode/plugins/qoi/makers/PlQoi.maker.pm b/tools/eaglemode/plugins/qoi/makers/PlQoi.maker.pm new file mode 100644 index 000000000000..c68b9bc6324b --- /dev/null +++ b/tools/eaglemode/plugins/qoi/makers/PlQoi.maker.pm @@ -0,0 +1,47 @@ +package PlQoi; + +use strict; +use warnings; + +sub GetDependencies +{ + return ('emCore'); +} + +sub IsEssential +{ + return 0; +} + +sub GetFileHandlingrules +{ + return (); +} + +sub GetExtraBuildOptions +{ + return (); +} + +sub Build +{ + shift; + my %options=@_; + + system( + @{$options{'unicc_call'}}, + "--math", + "--rtti", + "--exceptions", + "--bin-dir" , "bin", + "--lib-dir" , "lib", + "--obj-dir" , "obj", + "--inc-search-dir", "include", + "--link" , "emCore", + "--type" , "dynlib", + "--name" , "PlQoi", + "src/PlQoi.cpp" + )==0 or return 0; + + return 1; +} diff --git a/tools/eaglemode/plugins/qoi/src/PlQoi.cpp b/tools/eaglemode/plugins/qoi/src/PlQoi.cpp new file mode 100644 index 000000000000..1455712eff3a --- /dev/null +++ b/tools/eaglemode/plugins/qoi/src/PlQoi.cpp @@ -0,0 +1,273 @@ +#include <emCore/emFpPlugin.h> +#include <emCore/emImageFile.h> + +/* +QOI Utilities + +Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org +SPDX-License-Identifier: MIT +*/ + +#define QOI_OP_INDEX 0x00 /* 00xxxxxx */ +#define QOI_OP_DIFF 0x40 /* 01xxxxxx */ +#define QOI_OP_LUMA 0x80 /* 10xxxxxx */ +#define QOI_OP_RUN 0xc0 /* 11xxxxxx */ +#define QOI_OP_RGB 0xfe /* 11111110 */ +#define QOI_OP_RGBA 0xff /* 11111111 */ + +#define QOI_MASK_2 0xc0 /* 11000000 */ + +#define QOI_COLOR_HASH(C) (C.GetRed()*3 + C.GetGreen()*5 + C.GetBlue()*7 + C.GetAlpha()*11) + +#define QOI_MAGIC \ + (((unsigned int)'q') << 24 | ((unsigned int)'o') << 16 | \ + ((unsigned int)'i') << 8 | ((unsigned int)'f')) + +#define QOI_HEADER_SIZE 14 + +static unsigned int qoi_read_32(const unsigned char *bytes, int *p) { + unsigned int a = bytes[(*p)++]; + unsigned int b = bytes[(*p)++]; + unsigned int c = bytes[(*p)++]; + unsigned int d = bytes[(*p)++]; + return a << 24 | b << 16 | c << 8 | d; +} + + +class PlQoiImageFileModel : public emImageFileModel +{ +public: + + static emRef<PlQoiImageFileModel> Acquire( + emContext & context, const emString & name, bool common=true + ); + +protected: + PlQoiImageFileModel(emContext & context, const emString & name); + virtual ~PlQoiImageFileModel(); + virtual void TryStartLoading(); + virtual bool TryContinueLoading(); + virtual void QuitLoading(); + virtual void TryStartSaving(); + virtual bool TryContinueSaving(); + virtual void QuitSaving(); + virtual emUInt64 CalcMemoryNeed(); + virtual double CalcFileProgress(); + +private: + struct LoadingState; + LoadingState * L = NULL; +}; + + +struct PlQoiImageFileModel::LoadingState { + FILE * file; + unsigned int width, height, channels; + size_t file_len; +}; + + +emRef<PlQoiImageFileModel> PlQoiImageFileModel::Acquire( + emContext & context, const emString & name, bool common +) +{ + EM_IMPL_ACQUIRE(PlQoiImageFileModel, context, name, common) +} + + +PlQoiImageFileModel::PlQoiImageFileModel( + emContext & context, const emString & name +) + : emImageFileModel(context, name) +{ +} + + +PlQoiImageFileModel::~PlQoiImageFileModel() +{ + PlQoiImageFileModel::QuitLoading(); + PlQoiImageFileModel::QuitSaving(); +} + + +void PlQoiImageFileModel::TryStartLoading() +{ + unsigned char header[QOI_HEADER_SIZE]; + unsigned int header_magic, colorspace; + int pos = 0; + + L = new LoadingState; + memset(L, 0, sizeof(LoadingState)); + L->file = fopen(GetFilePath(),"rb"); + if (!L->file) throw emException("%s",emGetErrorText(errno).Get()); + + if (fread(header, 1, sizeof(header), L->file) != sizeof(header)) { + if (ferror(L->file)) { + throw emException("%s",emGetErrorText(errno).Get()); + } + else { + throw emException("QOI header not found"); + } + } + + header_magic = qoi_read_32(header, &pos); + L->width = qoi_read_32(header, &pos); + L->height = qoi_read_32(header, &pos); + L->channels = header[pos++]; + colorspace = header[pos++]; + + if ( + L->width == 0 || L->height == 0 || + L->channels < 3 || L->channels > 4 || + colorspace > 1 || + header_magic != QOI_MAGIC + ) { + throw emException("QOI header not valid"); + } + + fseek(L->file, 0, SEEK_END); + L->file_len = ftell(L->file); + + if (L->file_len <= QOI_HEADER_SIZE || fseek(L->file, 0, SEEK_SET) != 0) { + throw emException("QOI data incomplete"); + } + + FileFormatInfo = "QOI "; + FileFormatInfo += ( + colorspace ? "all channels linear" : "sRGB with linear alpha" + ); + + Signal(ChangeSignal); +} + + +bool PlQoiImageFileModel::TryContinueLoading() +{ + emArray<unsigned char> data; + emColor index[64]; + emColor px { 0, 0, 0, 255 }; + int pos = QOI_HEADER_SIZE; + int run = 0; + + if (!Image.GetHeight()) { + Image.Setup(L->width, L->height, L->channels); + } + + data.SetCount(L->file_len); + if (fread(data.GetWritable(), 1, L->file_len, L->file) < L->file_len) { + if (ferror(L->file)) { + throw emException("%s",emGetErrorText(errno).Get()); + } + else { + throw emException("QOI data incomplete"); + } + } + + memset(index, 0, sizeof(index)); + + for (int px_y = 0; px_y < L->height; px_y++) { + for (int px_x = 0; px_x < L->width; px_x++) { + if (run > 0) { + run--; + } else if (pos < data.GetCount()) { + int b1 = data.Get(pos++); + + if (b1 == QOI_OP_RGB) { + px.SetRed( data.Get(pos++)); + px.SetGreen( data.Get(pos++)); + px.SetBlue( data.Get(pos++)); + } else if (b1 == QOI_OP_RGBA) { + px.SetRed( data.Get(pos++)); + px.SetGreen( data.Get(pos++)); + px.SetBlue( data.Get(pos++)); + px.SetAlpha( data.Get(pos++)); + } else if ((b1 & QOI_MASK_2) == QOI_OP_INDEX) { + px = index[b1]; + } else if ((b1 & QOI_MASK_2) == QOI_OP_DIFF) { + px.SetRed( + px.GetRed() + ((b1 >> 4) & 0x03) - 2); + px.SetGreen( + px.GetGreen() + ((b1 >> 2) & 0x03) - 2); + px.SetBlue( + px.GetBlue() + ( b1 & 0x03) - 2); + } else if ((b1 & QOI_MASK_2) == QOI_OP_LUMA) { + int b2 = data.Get(pos++); + int vg = (b1 & 0x3f) - 32; + px.SetRed( + px.GetRed() + vg - 8 + ((b2 >> 4) & 0x0f)); + px.SetGreen( + px.GetGreen() + vg); + px.SetBlue( + px.GetBlue() + vg - 8 + (b2 & 0x0f)); + } else if ((b1 & QOI_MASK_2) == QOI_OP_RUN) { + run = (b1 & 0x3f); + } + index[QOI_COLOR_HASH(px) % 64] = px; + } + Image.SetPixel(px_x, px_y, px); + } + } + + Signal(ChangeSignal); + return true; +} + + +void PlQoiImageFileModel::QuitLoading() +{ + if (L) { + if (L->file) fclose(L->file); + delete L; + L = NULL; + } +} + + +void PlQoiImageFileModel::TryStartSaving() +{ + throw emException("PlQoiImageFileModel: Saving not implemented."); +} + + +bool PlQoiImageFileModel::TryContinueSaving() +{ + return false; +} + + +void PlQoiImageFileModel::QuitSaving() +{ +} + + +emUInt64 PlQoiImageFileModel::CalcMemoryNeed() +{ + return + (emUInt64)L->width * L->height * L->channels + L->file_len; +} + + +double PlQoiImageFileModel::CalcFileProgress() +{ + return 0.0; +} + +extern "C" { + emPanel * PlQoiFpPluginFunc( + emPanel::ParentArg parent, const emString & name, + const emString & path, emFpPlugin * plugin, + emString * errorBuf + ) + { + if (plugin->Properties.GetCount()) { + *errorBuf="PlQoiFpPlugin: No properties allowed."; + return NULL; + } + return new emImageFilePanel( + parent, name, + PlQoiImageFileModel::Acquire( + parent.GetRootContext(), path + ) + ); + } +} diff --git a/tools/eaglemode/plugins/yatracker/default.nix b/tools/eaglemode/plugins/yatracker/default.nix new file mode 100644 index 000000000000..3ffc42029a03 --- /dev/null +++ b/tools/eaglemode/plugins/yatracker/default.nix @@ -0,0 +1,18 @@ +{ depot, pkgs, ... }: + +let + em = depot.tools.eaglemode; + emSrc = with pkgs; srcOnly eaglemode; +in +(em.buildPlugin { + name = "yatracker"; + version = "canon"; + src = ./.; + target = "PlYaTracker"; +}).overrideAttrs (_: { + postInstall = '' + mkdir -p $out/icons + ${pkgs.imagemagick}/bin/convert $src/logo.webp $out/icons/yandex-tracker.tga + ''; +}) + diff --git a/tools/eaglemode/plugins/yatracker/etc/emCore/FpPlugins/PlYaTracker.emFpPlugin b/tools/eaglemode/plugins/yatracker/etc/emCore/FpPlugins/PlYaTracker.emFpPlugin new file mode 100644 index 000000000000..637878844709 --- /dev/null +++ b/tools/eaglemode/plugins/yatracker/etc/emCore/FpPlugins/PlYaTracker.emFpPlugin @@ -0,0 +1,6 @@ +#%rec:emFpPlugin%# + +FileTypes = { ".YaTracker" } +Priority = 1.0 +Library = "PlYaTracker" +Function = "PlYaTrackerPluginFunc" diff --git a/tools/eaglemode/plugins/yatracker/logo.webp b/tools/eaglemode/plugins/yatracker/logo.webp new file mode 100644 index 000000000000..460d57d72c33 --- /dev/null +++ b/tools/eaglemode/plugins/yatracker/logo.webp Binary files differdiff --git a/tools/eaglemode/plugins/yatracker/makers/PlYaTracker.maker.pm b/tools/eaglemode/plugins/yatracker/makers/PlYaTracker.maker.pm new file mode 100644 index 000000000000..ae954260a2d1 --- /dev/null +++ b/tools/eaglemode/plugins/yatracker/makers/PlYaTracker.maker.pm @@ -0,0 +1,47 @@ +package PlYaTracker; + +use strict; +use warnings; + +sub GetDependencies +{ + return ('emCore'); +} + +sub IsEssential +{ + return 0; +} + +sub GetFileHandlingRules +{ + return (); +} + +sub GetExtraBuildOptions +{ + return (); +} + +sub Build +{ + shift; + my %options=@_; + + system( + @{$options{'unicc_call'}}, + "--math", + "--rtti", + "--exceptions", + "--bin-dir" , "bin", + "--lib-dir" , "lib", + "--obj-dir" , "obj", + "--inc-search-dir", "include", + "--link" , "emCore", + "--type" , "dynlib", + "--name" , "PlYaTracker", + "src/PlYaTracker/PlYaTracker.cpp" + )==0 or return 0; + + return 1; +} diff --git a/tools/eaglemode/plugins/yatracker/src/PlYaTracker/PlYaTracker.cpp b/tools/eaglemode/plugins/yatracker/src/PlYaTracker/PlYaTracker.cpp new file mode 100644 index 000000000000..9bf05a17179f --- /dev/null +++ b/tools/eaglemode/plugins/yatracker/src/PlYaTracker/PlYaTracker.cpp @@ -0,0 +1,58 @@ +#include <emCore/emFilePanel.h> +#include <emCore/emFpPlugin.h> +#include <emCore/emRecFileModel.h> +#include <emCore/emToolkit.h> + +class PlYaTrackerConfig final : public emRecFileModel, public emStructRec { + public: + static emRef<PlYaTrackerConfig> Acquire(emContext& context, + const emString& name, + bool common = true); + + virtual const char* GetFormatName() const; + + emStringRec URL; + emStringRec Token; + + protected: + PlYaTrackerConfig(emContext& context, const emString& name); +}; + +emRef<PlYaTrackerConfig> PlYaTrackerConfig::Acquire(emContext& context, + const emString& name, + bool common) { + EM_IMPL_ACQUIRE(PlYaTrackerConfig, context, name, common) +} + +const char* PlYaTrackerConfig::GetFormatName() const { return "PlYaTracker"; } + +PlYaTrackerConfig::PlYaTrackerConfig(emContext& context, const emString& name) + : emRecFileModel(context, name), + emStructRec(), + URL(this, "URL"), + Token(this, "Token") { + PostConstruct(*this); +} + +class PlYaTrackerFilePanel : public emFilePanel { + public: + PlYaTrackerFilePanel(ParentArg parent, const emString& name, + emRef<PlYaTrackerConfig> config); + + private: + emRef<PlYaTrackerConfig> Config; +}; + +PlYaTrackerFilePanel::PlYaTrackerFilePanel(ParentArg parent, + const emString& name, + emRef<PlYaTrackerConfig> config) + : emFilePanel(parent, name, config), Config(config) {} + +extern "C" { +emPanel* PlYaTrackerPluginFunc(emPanel::ParentArg parent, const emString& name, + const emString& path, emFpPlugin* plugin, + emString* errorBuf) { + return new PlYaTrackerFilePanel( + parent, name, PlYaTrackerConfig::Acquire(parent.GetRootContext(), path)); +} +} diff --git a/tools/eaglemode/wrapper.go b/tools/eaglemode/wrapper.go new file mode 100644 index 000000000000..841642b6d93f --- /dev/null +++ b/tools/eaglemode/wrapper.go @@ -0,0 +1,156 @@ +// Eagle Mode configuration wrapper that recreates the required directory +// structure for Eagle Mode based on the output of depot.tools.eaglemode.etcDir +// +// This will replace *all* symlinks in the Eagle Mode configuration directory, +// but it will not touch actual files. Missing folders will be created. +package main + +import ( + "flag" + "fmt" + "io/fs" + "log" + "os" + "os/user" + "path" + "path/filepath" + "strings" +) + +func configDir() (string, error) { + v := os.Getenv("EM_USER_CONFIG_DIR") + if v != "" { + return v, nil + } + + usr, err := user.Current() + if err != nil { + return "", fmt.Errorf("failed to get current user: %w", err) + } + + return path.Join(usr.HomeDir, ".eaglemode"), nil +} + +// cleanupConfig removes *all* existing symlinks in the configuration which do +// not point into the right Nix store path. +func cleanupConfig(conf string, dir string) (map[string]bool, error) { + // In case of first launch, we might have to create the directory. + _ = os.MkdirAll(dir, 0755) + c := 0 + + currentFiles := map[string]bool{} + + walker := func(p string, d fs.DirEntry, e error) error { + if e != nil { + return fmt.Errorf("could not walk %s in config directory: %w", p, e) + } + + if d.Type()&fs.ModeSymlink != 0 { + target, err := os.Readlink(p) + if err != nil { + return fmt.Errorf("could not read link for %s: %w", p, err) + } + + if !strings.HasPrefix(target, conf) { + err = os.Remove(p) + c++ + if err != nil { + return fmt.Errorf("could not remove stale link %q: %w", p, err) + } + log.Printf("removed stale symlink %q", p) + } else { + currentFiles[p] = false + } + } + + if d.Type().IsRegular() { + currentFiles[p] = true + } + + return nil + } + + err := filepath.WalkDir(dir, walker) + if err != nil { + return nil, err + } + + if c > 0 { + log.Printf("removed %v stale symlinks", c) + } + + return currentFiles, nil +} + +// linkConfig traverses the given Eagle Mode configuration and links everything +// to the expected location in the user's configuration directory. +// +// If the user placed actual files in the configuration directory at paths that +// would be overwritten, they will not be touched. +func linkConfig(conf string, dir string, existing map[string]bool) error { + walker := func(p string, d fs.DirEntry, e error) error { + if e != nil { + return fmt.Errorf("could not walk %s in config directory: %w", p, e) + } + + target := path.Join(dir, strings.TrimPrefix(p, conf)) + + if d.Type().IsDir() { + err := os.MkdirAll(target, 0755) + if err != nil { + return fmt.Errorf("could not create directory %q: %w", target, err) + } + + return nil + } + + if shadow, exists := existing[target]; exists { + if shadow { + log.Printf("WARN: file %q already exists and shadows a file from configuration", target) + } + + return nil + } + + err := os.Symlink(p, target) + if err != nil { + return fmt.Errorf("failed to link %q: %w", target, err) + } + + return nil + } + + return filepath.WalkDir(conf, walker) +} + +func main() { + emConfig := flag.String("em-config", "", "path to em-config dir") + + flag.Parse() + log.Println("verifying current Eagle Mode configuration") + + if *emConfig == "" { + log.Fatalf("Eagle Mode configuration must be given") + } + + if !strings.HasPrefix(*emConfig, "/nix/store/") { + log.Fatalf("Eagle Mode configuration must be in Nix store") + } + + dir, err := configDir() + if err != nil { + log.Fatalf("could not determine Eagle Mode config dir: %v", err) + } + + currentFiles, err := cleanupConfig(*emConfig, dir) + if err != nil { + log.Fatalf("failed to remove stale symlinks: %v", err) + } + + err = linkConfig(*emConfig, dir, currentFiles) + if err != nil { + log.Fatalf("failed to link new configuration: %v", err) + } + + log.Println("Eagle Mode configuration updated") +} diff --git a/tools/emacs-pkgs/niri/default.nix b/tools/emacs-pkgs/niri/default.nix new file mode 100644 index 000000000000..995b1b6208ad --- /dev/null +++ b/tools/emacs-pkgs/niri/default.nix @@ -0,0 +1,7 @@ +{ depot, ... }: + +depot.tools.emacs-pkgs.buildEmacsPackage rec { + pname = "niri"; + version = "1.0"; + src = ./niri.el; +} diff --git a/tools/emacs-pkgs/niri/niri.el b/tools/emacs-pkgs/niri/niri.el new file mode 100644 index 000000000000..32b65efdfcaa --- /dev/null +++ b/tools/emacs-pkgs/niri/niri.el @@ -0,0 +1,181 @@ +;;; niri.el --- seamless niri/emacs integration. -*- lexical-binding: t; -*- +;; +;; Copyright (C) 2024 The TVL Contributors +;; +;; Author: Vincent Ambo <tazjin@tvl.su> +;; Version: 1.0 +;; Package-Requires: ((emacs "27.1")) +;; +;;; Commentary: +;; +;; After having used EXWM for many years (7 or so?) it's become second nature +;; that there is no difference between windows and Emacs buffers. This means +;; that from any Emacs buffer (or, in the case of EXWM, from any X window) it's +;; possible to switch to any of the others. +;; +;; This implements similar logic for Emacs running in Niri, consisting of two +;; sides of the integration: +;; +;; # In Emacs +;; +;; Inside of Emacs, when switching buffers, populate the buffer-switching menu +;; additionally with all open Niri windows. Selecting a Niri window moves the +;; screen to that window. +;; +;; # Outside of Emacs +;; +;; Provides an interface for the same core functionality that can be used from +;; shell scripts, and bound to selectors like dmenu or rofi. +;; +;; # Switching to Emacs buffers +;; +;; Some special logic exists for handling the case of switching to an Emacs +;; buffer. There are several conditions that we can be in, that each have a +;; predictable result: +;; +;; In a non-Emacs window, selecting an Emacs buffer will either switch to an +;; Emacs frame already displaying this buffer, or launch a new frame for it. +;; +;; Inside of Emacs, if *another* frame is already displaying the buffer, switch +;; to it. Otherwise the behaviour is the same as standard buffer switching. + +(require 'seq) +(require 'map) + +(defun niri-list-windows () + "List all currently open Niri windows." + (json-parse-string + (shell-command-to-string "niri msg -j windows") + :false-object nil)) + +(defun niri--window-is-emacs (window) + (equal (map-elt window "app_id") "emacs")) + +(defun niri--list-selectables () + "Lists all currently selectable things in a format that can work +with completing-read. Selectable means all open Niri +windows (except Emacs windows) and all Emacs buffers. + +Emacs windows are returned separately, as they are required for +frame navigation." + (let* (;; all niri windows, with emacs/non-emacs windows split up + (all-windows (niri-list-windows)) + (windows (seq-filter (lambda (w) (not (niri--window-is-emacs w))) + all-windows)) + (emacs-windows (seq-filter #'niri--window-is-emacs all-windows)) + + ;; all non-hidden buffers + (buffers (seq-filter (lambda (b) (not (string-prefix-p " " (buffer-name b)))) + (buffer-list))) + (selectables (make-hash-table :test 'equal :size (+ (length windows) + (length buffers))))) + (seq-do (lambda (window) + (map-put! selectables (map-elt window "title") + (cons :niri window))) + windows) + + (seq-do (lambda (buf) + (map-put! selectables (buffer-name buf) + (cons :emacs buf))) + buffers) + (cons selectables emacs-windows))) + +(defun niri--focus-window (window) + (shell-command (format "niri msg action focus-window --id %d" + (map-elt window "id")))) + +(defun niri--target-action-internal (target) + "Focus the given TARGET (a Niri window or Emacs buffer). This is +used when called from inside of Emacs. It will NOT correctly +switch Niri windows when called from outside of Emacs." + (pcase (car target) + (:emacs (pop-to-buffer (cdr target) '((display-buffer-reuse-window + display-buffer-same-window) + (reusable-frames . 0)))) + (:niri (niri--focus-window (cdr target))))) + +(defun niri-go-anywhere () + "Interactively select and switch to an open Niri window, or an + Emacs buffer." + (interactive) + (let* ((selectables (car (niri--list-selectables))) + ;; Annotate buffers that display remote files. I frequently + ;; want to see it, because I might have identically named + ;; files open locally and remotely at the same time, and it + ;; helps with differentiating them. + (completion-extra-properties + '(:annotation-function + (lambda (name) + (let ((elt (map-elt selectables name))) + (pcase (car elt) + (:emacs + (if-let* ((file (buffer-file-name (cdr elt))) + (remote (file-remote-p file))) + (format " [%s]" remote))) + (:niri (format " [%s]" (map-elt (cdr elt) "app_id")))))))) + + (target-key (completing-read "Switch to: " (map-keys selectables))) + (target (map-elt selectables target-key))) + (if target + (niri--target-action-internal target) + (switch-to-buffer target-key nil t)))) + + +(defun niri--target-action-external (target frames) + "Focus the given TARGET (a Niri window or Emacs buffer). This +always behaves correctly, but does more work than the -internal +variant. It should only be called when invoking the switcher from +outside of Emacs (i.e. through `emacsclient'). + +FRAMES is the exact list of Emacs frames that existed at the time +the switcher was invoked." + (pcase (car target) + (:niri (niri--focus-window (cdr target))) + + ;; When switching to an Emacs buffer from outside of Emacs, we run into the + ;; additional complication that Wayland does not allow arbitrary + ;; applications to change the focused window. Calling e.g. + ;; `select-frame-set-input-focus' has no effect on Wayland when not called + ;; from within a focused Emacs frame. + ;; + ;; However, due to concurrency, frames may change between the moment when we + ;; start the switcher (and potentially wait for user input), and when the + ;; final selection happens. + ;; + ;; To get around this we try to match the target Emacs frame (if present) to + ;; a Niri window, switch to it optimistically, and *then* execute the final + ;; buffer switching command. + (:emacs + (if-let ((window (get-buffer-window (cdr target) t)) + (frame (window-frame window)) + (frame-name (frame-parameter frame 'name)) + (niri-window (seq-find (lambda (w) + (equal (map-elt w "title") frame-name)) + frames))) + ;; Target frame found and could be matched to a Niri window: Go there! + (progn (select-window window) ;; ensure the right window in the frame has focus + (niri--focus-window niri-window) + (message "Switched to existing window for \"%s\"" (buffer-name (cdr target)))) + + ;; Target frame not found; is Emacs the focused program? + (if (seq-find (lambda (w) (map-elt w "is_focused")) frames) + (switch-to-buffer (cdr target)) + ;; if not, just make a new frame + (display-buffer (cdr target) '(display-buffer-pop-up-frame))))))) + +(defun niri-go-anywhere-external () + "Use a dmenu-compatible launcher like `fuzzel' to achieve the same +effect as `niri-go-anywhere', but from outside of Emacs through +Emacsclient." + (interactive) ;; TODO no? + (let* ((all (niri--list-selectables)) + (selectables (car all)) + (target (with-temp-buffer + (dolist (key (map-keys selectables)) + (insert key "\n")) + (call-process-region nil nil "fuzzel" t t nil "-d") + (string-trim (buffer-string))))) + (when-let ((selectable (map-elt selectables target))) + (niri--target-action-external selectable (cdr all))))) + +(provide 'niri) diff --git a/tools/when/default.nix b/tools/when/default.nix new file mode 100644 index 000000000000..1aee5e1ea8e5 --- /dev/null +++ b/tools/when/default.nix @@ -0,0 +1,6 @@ +{ depot, ... }: + +depot.nix.buildGo.program { + name = "when"; + srcs = [ ./when.go ]; +} diff --git a/tools/when/when.go b/tools/when/when.go new file mode 100644 index 000000000000..a2ac494e8c64 --- /dev/null +++ b/tools/when/when.go @@ -0,0 +1,206 @@ +package main + +import ( + "fmt" + "os" + "strconv" + "strings" + "time" +) + +const usage = `usage: when <time> + +This program converts the given time into various formats (currently a local +timestamp, UTC timestamp, and UNIX epoch). It tries to guess what the input is. + +Some valid queries: + + 2024-01-05 + 1715079241 + tomorrow 5PM + -22h + -7h10m + Mar 15 + Sep 3 18:00 + +For now a single timestamp and a single duration (which is added either to the +current time, or the given time) is supported.` + +func printTime(t time.Time) { + fmt.Println("Local:", t.Format("Mon 02 January 2006 at 15:04:05 MST")) + fmt.Println("UTC: ", t.UTC().Format(time.RFC3339)) + fmt.Println("UNIX: ", t.Unix()) +} + +type FieldSet uint8 + +const ( + SetYear FieldSet = 1 << iota + SetDay + SetMonth + SetHour + SetMinute + SetSecond + SetLocation +) + +const ( + SetDate = SetYear | SetDay | SetMonth + SetClock = SetHour | SetMinute | SetSecond +) + +// mergeTimes returns a new time.Time with all fields in this overridden with the +// specified fields from that. +func mergeTimes(this time.Time, that time.Time, set FieldSet) time.Time { + year, month, day := this.Date() + hour, min, sec := this.Clock() + loc := this.Location() + + if set&SetYear == SetYear { + year = that.Year() + } + if set&SetMonth == SetMonth { + month = that.Month() + } + if set&SetDay == SetDay { + day = that.Day() + } + if set&SetHour == SetHour { + hour = that.Hour() + } + if set&SetMinute == SetMinute { + min = that.Minute() + } + if set&SetSecond == SetSecond { + sec = that.Second() + } + if set&SetLocation == SetLocation { + loc = that.Location() + } + + return time.Date(year, month, day, hour, min, sec, 0, loc) +} + +func parseTime(input string) (time.Time, error) { + // try unix times + if i, err := strconv.ParseInt(input, 10, 64); err == nil { + if i < 9999999999 { + return time.Unix(i, 0), nil + } + if i < 9999999999999 { + return time.UnixMilli(i), nil + } + } + + // try simple date/time formats + if t, err := time.Parse(time.DateOnly, input); err == nil { + return t, nil + } + + if t, err := time.Parse(time.Kitchen, input); err == nil { + now := time.Now() + return mergeTimes(now, t, SetClock), nil + } + + if t, err := time.Parse(time.TimeOnly, input); err == nil { + now := time.Now() + return mergeTimes(now, t, SetClock), nil + } + + if t, err := time.Parse("15:04", input); err == nil { + now := time.Now() + return mergeTimes(now, t, SetClock), nil + } + + if t, err := time.Parse("3PM", input); err == nil { + now := time.Now() + return mergeTimes(now, t, SetClock), nil + } + + if t, err := time.Parse(time.DateTime, input); err == nil { + return t, nil + } + + if t, err := time.Parse(time.Stamp, input); err == nil { + now := time.Now() + return mergeTimes(t, now, SetYear|SetLocation), nil + } + + if t, err := time.Parse("Jan _2 15:04", input); err == nil { + now := time.Now() + return mergeTimes(t, now, SetYear|SetLocation), nil + } + + if t, err := time.Parse("Jan _2", input); err == nil { + now := time.Now() + return mergeTimes(t, now, SetYear|SetLocation), nil + } + + return time.Time{}, fmt.Errorf("could not parse time: %q", input) +} + +func parseDuration(input string) (time.Duration, error) { + // some simple rewriting + switch input { + case "yesterday": + input = "-24h" + case "tomorrow": + input = "24h" + case "today", "now": + return time.Duration(0), nil + } + + // TODO: days, months, weeks, ... + return time.ParseDuration(input) +} + +func main() { + if len(os.Args) < 2 { + fmt.Fprintln(os.Stderr, usage) + os.Exit(1) + } + + var d time.Duration + var t time.Time + var err error + var haveTime, haveDuration bool + + // Try to parse entire input as one full thing, before getting more + // clever. + if t, err = parseTime(strings.Join(os.Args[1:], " ")); err == nil { + printTime(t) + return + } + + for _, arg := range os.Args[1:] { + if !haveTime { + if t, err = parseTime(arg); err == nil { + haveTime = true + continue + } + } + + if !haveDuration { + if d, err = parseDuration(arg); err == nil { + haveDuration = true + continue + } + } + } + + if err != nil { + fmt.Fprintln(os.Stderr, "Not sure what you want, try another time.") + os.Exit(1) + } + + if haveTime && haveDuration { + printTime(t.Add(d)) + } else if haveTime { + printTime(t) + } else if haveDuration { + printTime(time.Now().Add(d)) + } else { + fmt.Fprintln(os.Stderr, "Not sure what you want, try another time.") + os.Exit(1) + } +} diff --git a/tvix/Cargo.lock b/tvix/Cargo.lock index 334b69b7f580..2984479c18ef 100644 --- a/tvix/Cargo.lock +++ b/tvix/Cargo.lock @@ -4,29 +4,35 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -49,47 +55,48 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.11" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -97,46 +104,45 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "arc-swap" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-channel" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" dependencies = [ "concurrent-queue", - "event-listener 5.2.0", - "event-listener-strategy 0.5.0", + "event-listener-strategy", "futures-core", "pin-project-lite", ] [[package]] name = "async-compression" -version = "0.4.6" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a116f46a969224200a0a97f29cfd4c50e7534e4b4826bd23ea2c3c533039c82c" +checksum = "998282f8f49ccd6116b0ed8a4de0fbd3151697920e7c7533416d6e25e76434a7" dependencies = [ "bzip2", "flate2", @@ -145,15 +151,17 @@ dependencies = [ "pin-project-lite", "tokio", "xz2", + "zstd", + "zstd-safe", ] [[package]] name = "async-io" -version = "2.3.2" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ - "async-lock 3.3.0", + "async-lock", "cfg-if", "concurrent-queue", "futures-io", @@ -163,66 +171,47 @@ dependencies = [ "rustix", "slab", "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", + "windows-sys 0.59.0", ] [[package]] name = "async-lock" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy 0.4.0", + "event-listener", + "event-listener-strategy", "pin-project-lite", ] [[package]] name = "async-process" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451e3cf68011bd56771c79db04a9e333095ab6349f7e47592b788e9b98720cc8" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ "async-channel", "async-io", - "async-lock 3.3.0", + "async-lock", "async-signal", + "async-task", "blocking", "cfg-if", - "event-listener 5.2.0", + "event-listener", "futures-lite", "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "async-recursion" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", + "tracing", ] [[package]] name = "async-signal" -version = "0.2.5" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ "async-io", - "async-lock 2.8.0", + "async-lock", "atomic-waker", "cfg-if", "futures-core", @@ -230,14 +219,14 @@ dependencies = [ "rustix", "signal-hook-registry", "slab", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -246,20 +235,20 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "async-task" -version = "4.7.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-tempfile" @@ -273,13 +262,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] @@ -289,56 +278,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] -name = "autocfg" -version = "1.1.0" +name = "auto_impl" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] [[package]] -name = "axum" -version = "0.6.20" +name = "autocfg" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" -dependencies = [ - "async-trait", - "axum-core 0.3.4", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http 0.2.11", - "http-body 0.4.6", - "hyper 0.14.28", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper", - "tower", - "tower-layer", - "tower-service", -] +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", - "axum-core 0.4.3", + "axum-core", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", - "hyper 1.2.0", + "hyper", "hyper-util", "itoa", - "matchit", + "matchit 0.7.3", "memchr", "mime", "percent-encoding", @@ -348,9 +320,9 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "tokio", - "tower", + "tower 0.5.1", "tower-layer", "tower-service", "tracing", @@ -358,55 +330,76 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.3.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", "futures-util", - "http 0.2.11", - "http-body 0.4.6", + "http", + "http-body", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", + "tracing", ] [[package]] -name = "axum-core" -version = "0.4.3" +name = "axum-extra" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "73c3220b188aea709cf1b6c5f9b01c3bd936bb08bd2b5184a12b35ac8131b1f9" dependencies = [ - "async-trait", + "axum", + "axum-core", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "headers", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", - "rustversion", - "sync_wrapper", + "serde", + "tower 0.5.1", "tower-layer", "tower-service", "tracing", ] [[package]] +name = "axum-range" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c30398a7f716ebdd7f3c8a4f7a7a6df48a30e002007fd57b2a7a00fac864bd" +dependencies = [ + "axum", + "axum-extra", + "bytes", + "futures", + "http-body", + "pin-project", + "tokio", +] + +[[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -416,6 +409,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] name = "base64ct" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -423,43 +422,28 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bigtable_rs" -version = "0.2.9" -source = "git+https://github.com/flokli/bigtable_rs?rev=0af404741dfc40eb9fa99cf4d4140a09c5c20df7#0af404741dfc40eb9fa99cf4d4140a09c5c20df7" +version = "0.2.10" +source = "git+https://github.com/liufuyang/bigtable_rs?rev=1818355a5373a5bc2c84287e3a4e3807154ac8ef#1818355a5373a5bc2c84287e3a4e3807154ac8ef" dependencies = [ "gcp_auth", - "http 0.2.11", + "http", + "hyper-util", "log", - "prost 0.12.3", + "prost", "prost-build", "prost-types", "prost-wkt", - "prost-wkt-build", "prost-wkt-types", "serde", "serde_with", "thiserror", "tokio", - "tonic 0.11.0", + "tonic", "tonic-build", - "tower", + "tower 0.4.13", ] [[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -467,21 +451,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" - -[[package]] -name = "bitmaps" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703642b98a00b3b90513279a8ede3fcfa479c126c5fb46e78f3051522f021403" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "blake3" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" dependencies = [ "arrayref", "arrayvec", @@ -489,7 +467,7 @@ dependencies = [ "cfg-if", "constant_time_eq", "digest", - "rayon", + "rayon-core", ] [[package]] @@ -503,36 +481,33 @@ dependencies = [ [[package]] name = "blocking" -version = "1.5.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ "async-channel", - "async-lock 3.3.0", "async-task", - "fastrand", "futures-io", "futures-lite", "piper", - "tracing", ] [[package]] name = "bstr" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.8", "serde", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" @@ -542,9 +517,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "bzip2" @@ -585,12 +560,13 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.83" +version = "1.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "58e804ac3194a48bb129643eb1d62fcc20d18c6b8c181704489353d13120bcd1" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -601,9 +577,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.34" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -611,14 +587,14 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -627,15 +603,15 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", @@ -643,9 +619,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.18" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -653,9 +629,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -665,21 +641,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clipboard-win" @@ -710,20 +686,33 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] [[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + +[[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -731,9 +720,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "core-foundation" @@ -747,9 +736,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "count-write" @@ -765,18 +754,18 @@ checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -819,9 +808,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -847,9 +836,15 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" @@ -863,16 +858,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -886,14 +880,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "darling" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -901,40 +895,40 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", @@ -951,6 +945,37 @@ dependencies = [ ] [[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.79", +] + +[[package]] name = "diff" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1009,6 +1034,12 @@ dependencies = [ ] [[package]] +name = "dissimilar" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d" + +[[package]] name = "doc-comment" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1016,9 +1047,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "document-features" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" dependencies = [ "litrs", ] @@ -1035,9 +1066,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", @@ -1049,18 +1080,15 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] -name = "encoding_rs" -version = "0.8.33" +name = "encode_unicode" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" -dependencies = [ - "cfg-if", -] +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "endian-type" @@ -1076,7 +1104,7 @@ checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c" dependencies = [ "num-traits", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] @@ -1087,18 +1115,19 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erased-serde" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b73807008a3c7f171cc40312f37d95ef0396e048b5848d775f54b1a4dd4a0d3" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" dependencies = [ "serde", + "typeid", ] [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1116,26 +1145,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.3" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", @@ -1144,22 +1156,22 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 4.0.3", + "event-listener", "pin-project-lite", ] [[package]] -name = "event-listener-strategy" -version = "0.5.0" +name = "expect-test" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +checksum = "9e0be0a561335815e06dab7c62e50353134c796e7a6155402a64bcff66b6a5e0" dependencies = [ - "event-listener 5.2.0", - "pin-project-lite", + "dissimilar", + "once_cell", ] [[package]] @@ -1175,9 +1187,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fd-lock" @@ -1192,20 +1204,20 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.5" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] @@ -1216,9 +1228,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -1231,6 +1243,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + +[[package]] name = "form_urlencoded" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1240,20 +1258,10 @@ dependencies = [ ] [[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - -[[package]] name = "fuse-backend-rs" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5a63a89f40ec26a0a1434e89de3f4ee939a920eae15d641053ee09ee6ed44b" +checksum = "e1663480cae165243a6c7f75abecfb868c16d17346afc74faf61a2febcadd11b" dependencies = [ "arc-swap", "bitflags 1.3.2", @@ -1262,8 +1270,9 @@ dependencies = [ "lazy_static", "libc", "log", - "mio", + "mio 0.8.11", "nix 0.24.3", + "radix_trie", "vhost", "virtio-queue", "vm-memory", @@ -1272,9 +1281,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1287,9 +1296,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1297,15 +1306,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1314,9 +1323,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -1333,38 +1342,38 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-timer" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1379,29 +1388,23 @@ dependencies = [ ] [[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] name = "gcp_auth" -version = "0.10.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de2c71ea685b88a1aa50e9fb66fe0e1cb29d755f58cca41fb8c91ef604d4f4d4" +checksum = "536c79e79dde296a800738474691e97031769bed9b54e6dd0401b169d35d693d" dependencies = [ "async-trait", - "base64", + "base64 0.22.1", + "bytes", "chrono", "home", - "hyper 0.14.28", + "http", + "http-body-util", + "hyper", "hyper-rustls", + "hyper-util", "ring", - "rustls 0.21.10", - "rustls-pemfile 1.0.4", + "rustls-pemfile", "serde", "serde_json", "thiserror", @@ -1409,7 +1412,6 @@ dependencies = [ "tracing", "tracing-futures", "url", - "which 5.0.0", ] [[package]] @@ -1428,6 +1430,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" [[package]] +name = "generator" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb949699c3e4df3a183b1d2142cb24277057055ed23c68ed58894f76c517223" +dependencies = [ + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + +[[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1439,20 +1454,34 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getset" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f636605b743120a8d32ed92fc27b6cde1a769f8f936c065151eb66f88ded513c" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.79", ] [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -1462,17 +1491,17 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.24" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", - "http 0.2.11", - "indexmap 2.1.0", + "http", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -1480,41 +1509,61 @@ dependencies = [ ] [[package]] -name = "h2" -version = "0.4.3" +name = "half" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 1.1.0", - "indexmap 2.1.0", - "slab", - "tokio", - "tokio-util", - "tracing", + "cfg-if", + "crunchy", ] [[package]] -name = "half" -version = "1.8.2" +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "headers" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" +dependencies = [ + "base64 0.21.7", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http", +] [[package]] name = "heck" @@ -1523,10 +1572,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] name = "hermit-abi" -version = "0.3.4" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "hex" @@ -1551,17 +1612,6 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" @@ -1573,43 +1623,32 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.11", - "pin-project-lite", -] - -[[package]] -name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http", ] [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", - "http 1.1.0", - "http-body 1.0.0", + "futures-util", + "http", + "http-body", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1625,103 +1664,87 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.24", - "http 0.2.11", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.3", - "http 1.1.0", - "http-body 1.0.0", + "h2", + "http", + "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", "smallvec", "tokio", + "want", ] [[package]] name = "hyper-rustls" -version = "0.24.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", - "http 0.2.11", - "hyper 0.14.28", - "rustls 0.21.10", - "rustls-native-certs 0.6.3", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-native-certs", + "rustls-pki-types", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls", + "tower-service", ] [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper 0.14.28", + "hyper", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", + "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "hyper 1.2.0", + "http", + "http-body", + "hyper", "pin-project-lite", "socket2", "tokio", + "tower-service", + "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -1750,30 +1773,6 @@ dependencies = [ ] [[package]] -name = "imbl" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978d142c8028edf52095703af2fad11d6f611af1246685725d6b850634647085" -dependencies = [ - "bitmaps", - "imbl-sized-chunks", - "proptest", - "rand_core", - "rand_xoshiro", - "serde", - "version_check", -] - -[[package]] -name = "imbl-sized-chunks" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "144006fb58ed787dcae3f54575ff4349755b00ccc99f4b4873860b654be1ed63" -dependencies = [ - "bitmaps", -] - -[[package]] name = "indexmap" version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1786,20 +1785,34 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.15.0", "serde", ] [[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", + "vt100", +] + +[[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -1812,22 +1825,28 @@ checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-terminal" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi", - "rustix", + "hermit-abi 0.4.0", + "libc", "windows-sys 0.52.0", ] [[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] name = "itertools" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1838,51 +1857,51 @@ dependencies = [ [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itertools" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lexical-core" @@ -1950,9 +1969,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.152" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libm" @@ -1961,21 +1980,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] +name = "libmimalloc-sys" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] + +[[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.7", ] [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litrs" @@ -1985,9 +2014,9 @@ checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1995,9 +2024,31 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.0", +] [[package]] name = "lzma-sys" @@ -2016,7 +2067,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a200ae03df8c3dce7a963f6eeaac8feb41bf9001cb7e5ab22e3205aec2f0373d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "libc", "magic-sys", "thiserror", @@ -2048,6 +2099,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] name = "md-5" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2059,9 +2116,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -2073,12 +2130,12 @@ dependencies = [ ] [[package]] -name = "memoffset" -version = "0.9.0" +name = "mimalloc" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" dependencies = [ - "autocfg", + "libmimalloc-sys", ] [[package]] @@ -2095,18 +2152,18 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", @@ -2115,10 +2172,59 @@ dependencies = [ ] [[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] name = "multimap" -version = "0.8.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" + +[[package]] +name = "nar-bridge" +version = "0.1.0" +dependencies = [ + "axum", + "axum-extra", + "axum-range", + "bytes", + "clap", + "data-encoding", + "futures", + "hex-literal", + "itertools 0.12.1", + "lru", + "mimalloc", + "nix-compat", + "parking_lot", + "prost", + "prost-build", + "rstest", + "serde", + "thiserror", + "tokio", + "tokio-listener", + "tokio-util", + "tonic", + "tonic-build", + "tower 0.4.13", + "tower-http", + "tracing", + "tracing-subscriber", + "tvix-castore", + "tvix-store", + "tvix-tracing", + "url", +] [[package]] name = "nibble_vec" @@ -2138,7 +2244,7 @@ dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", - "memoffset 0.6.5", + "memoffset", ] [[package]] @@ -2170,7 +2276,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "cfg-if", "libc", ] @@ -2179,8 +2285,9 @@ dependencies = [ name = "nix-compat" version = "0.1.0" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "bstr", + "bytes", "criterion", "data-encoding", "ed25519", @@ -2189,7 +2296,8 @@ dependencies = [ "futures", "glob", "hex-literal", - "lazy_static", + "mimalloc", + "nix-compat-derive", "nom", "num-traits", "pin-project-lite", @@ -2198,13 +2306,67 @@ dependencies = [ "serde", "serde_json", "sha2", + "smol_str", "thiserror", "tokio", "tokio-test", + "tracing", "zstd", ] [[package]] +name = "nix-compat-derive" +version = "0.1.0" +dependencies = [ + "hex-literal", + "nix-compat", + "pretty_assertions", + "proc-macro2", + "quote", + "rstest", + "syn 2.0.79", + "tokio", + "tokio-test", +] + +[[package]] +name = "nix-compat-derive-tests" +version = "0.1.0" +dependencies = [ + "hex-literal", + "nix-compat", + "nix-compat-derive", + "pretty_assertions", + "rstest", + "tokio", + "tokio-test", + "trybuild", +] + +[[package]] +name = "nix-daemon" +version = "0.1.0" +dependencies = [ + "async-trait", + "clap", + "futures", + "mimalloc", + "nix-compat", + "tokio", + "tokio-listener", + "tracing", + "tvix-castore", + "tvix-store", + "tvix-tracing", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2241,9 +2403,9 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -2255,41 +2417,47 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] [[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] name = "object" -version = "0.32.2" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "object_store" -version = "0.9.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8718f8b65fdf67a45108d1548347d4af7d71fb81ce727bbf9e3b2535e079db3" +checksum = "e6da452820c715ce78221e8202ccc599b4a52f3e1eb3eedb487b680c81a8e3f3" dependencies = [ "async-trait", - "base64", + "base64 0.22.1", "bytes", "chrono", "futures", "humantime", - "hyper 0.14.28", - "itertools 0.12.0", + "hyper", + "itertools 0.13.0", "md-5", - "parking_lot 0.12.1", + "parking_lot", "percent-encoding", "quick-xml", "rand", "reqwest", "ring", - "rustls-pemfile 2.1.0", + "rustls-pemfile", "serde", "serde_json", "snafu", @@ -2300,16 +2468,32 @@ dependencies = [ ] [[package]] +name = "oci-spec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cee185ce7cf1cce45e194e34cd87c0bad7ff0aa2e8917009a2da4f7b31fb363" +dependencies = [ + "derive_builder", + "getset", + "regex", + "serde", + "serde_json", + "strum", + "strum_macros", + "thiserror", +] + +[[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "openssl-probe" @@ -2319,13 +2503,12 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "opentelemetry" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" +checksum = "900d57987be3f2aeb70d385fff9b27fb74c5723cc9a52d904d4f9c807a0667bf" dependencies = [ "futures-core", "futures-sink", - "indexmap 2.1.0", "js-sys", "once_cell", "pin-project-lite", @@ -2334,62 +2517,97 @@ dependencies = [ ] [[package]] +name = "opentelemetry" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c365a63eec4f55b7efeceb724f1336f26a9cf3427b70e59e2cd2a5b947fba96" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", +] + +[[package]] +name = "opentelemetry-http" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad31e9de44ee3538fb9d64fe3376c1362f406162434609e79aea2a41a0af78ab" +dependencies = [ + "async-trait", + "bytes", + "http", + "opentelemetry 0.24.0", +] + +[[package]] name = "opentelemetry-otlp" -version = "0.14.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f24cda83b20ed2433c68241f918d0f6fdec8b1d43b7a9590ab4420c5095ca930" +checksum = "6b925a602ffb916fb7421276b86756027b37ee708f9dce2dbdcc51739f07e727" dependencies = [ "async-trait", "futures-core", - "http 0.2.11", - "opentelemetry", + "http", + "opentelemetry 0.24.0", "opentelemetry-proto", - "opentelemetry-semantic-conventions", - "opentelemetry_sdk", - "prost 0.11.9", + "opentelemetry_sdk 0.24.1", + "prost", "thiserror", "tokio", - "tonic 0.9.2", + "tonic", ] [[package]] name = "opentelemetry-proto" -version = "0.4.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2e155ce5cc812ea3d1dffbd1539aed653de4bf4882d60e6e04dcf0901d674e1" +checksum = "30ee9f20bff9c984511a02f082dc8ede839e4a9bf15cc2487c8d6fea5ad850d9" dependencies = [ - "opentelemetry", - "opentelemetry_sdk", - "prost 0.11.9", - "tonic 0.9.2", + "opentelemetry 0.24.0", + "opentelemetry_sdk 0.24.1", + "prost", + "tonic", ] [[package]] -name = "opentelemetry-semantic-conventions" -version = "0.13.0" +name = "opentelemetry_sdk" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5774f1ef1f982ef2a447f6ee04ec383981a3ab99c8e77a1a7b30182e65bbc84" +checksum = "9e90c7113be649e31e9a0f8b5ee24ed7a16923b322c3c5ab6367469c049d6b7e" dependencies = [ - "opentelemetry", + "async-trait", + "crossbeam-channel", + "futures-channel", + "futures-executor", + "futures-util", + "glob", + "once_cell", + "opentelemetry 0.22.0", + "ordered-float", + "percent-encoding", + "rand", + "thiserror", ] [[package]] name = "opentelemetry_sdk" -version = "0.21.2" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f16aec8a98a457a52664d69e0091bac3a0abd18ead9b641cb00202ba4e0efe4" +checksum = "692eac490ec80f24a17828d49b40b60f5aeaccdfe6a503f939713afd22bc28df" dependencies = [ "async-trait", - "crossbeam-channel", "futures-channel", "futures-executor", "futures-util", "glob", "once_cell", - "opentelemetry", - "ordered-float", + "opentelemetry 0.24.0", "percent-encoding", "rand", + "serde_json", "thiserror", "tokio", "tokio-stream", @@ -2397,9 +2615,9 @@ dependencies = [ [[package]] name = "ordered-float" -version = "4.2.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" +checksum = "44d501f1a72f71d3c063a6bbc8f7271fa73aa09fe5d6283b6571e2ed176a2537" dependencies = [ "num-traits", ] @@ -2421,56 +2639,31 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.9", + "parking_lot_core", ] [[package]] name = "parking_lot_core" -version = "0.8.6" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", - "instant", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.5.7", "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.4.1", - "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2487,39 +2680,39 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.1.0", + "indexmap 2.6.0", ] [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2529,9 +2722,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", "fastrand", @@ -2550,21 +2743,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" - -[[package]] -name = "platforms" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -2575,34 +2762,41 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] [[package]] name = "polling" -version = "3.4.0" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30054e72317ab98eddd8561db0f6524df3367636884b7b21b703e4b280a84a14" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if", "concurrent-queue", + "hermit-abi 0.4.0", "pin-project-lite", "rustix", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + +[[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2610,15 +2804,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", @@ -2626,131 +2823,126 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.16" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +dependencies = [ + "proc-macro2", + "syn 2.0.79", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ + "proc-macro-error-attr2", "proc-macro2", - "syn 2.0.48", + "quote", + "syn 2.0.79", ] [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ - "bit-set", - "bit-vec", - "bitflags 2.4.2", + "bitflags 2.6.0", "lazy_static", "num-traits", "rand", "rand_chacha", "rand_xorshift", - "regex-syntax 0.8.2", - "rusty-fork", + "regex-syntax 0.8.5", "tempfile", "unarray", ] [[package]] name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive 0.11.9", -] - -[[package]] -name = "prost" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", - "prost-derive 0.12.3", + "prost-derive", ] [[package]] name = "prost-build" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" +checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" dependencies = [ "bytes", - "heck", - "itertools 0.11.0", + "heck 0.5.0", + "itertools 0.13.0", "log", "multimap", "once_cell", "petgraph", "prettyplease", - "prost 0.12.3", + "prost", "prost-types", "pulldown-cmark", "pulldown-cmark-to-cmark", "regex", - "syn 2.0.48", + "syn 2.0.79", "tempfile", - "which 4.4.2", ] [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", - "syn 1.0.109", -] - -[[package]] -name = "prost-derive" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" -dependencies = [ - "anyhow", - "itertools 0.11.0", - "proc-macro2", - "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "prost-types" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" dependencies = [ - "prost 0.12.3", + "prost", ] [[package]] name = "prost-wkt" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d8ef9c3f0f1dab910d2b7e2c24a8e4322e122eba6d7a1921eeebcebbc046c40" +checksum = "a8d84e2bee181b04c2bac339f2bfe818c46a99750488cc6728ce4181d5aa8299" dependencies = [ "chrono", "inventory", - "prost 0.12.3", + "prost", "serde", "serde_derive", "serde_json", @@ -2759,12 +2951,12 @@ dependencies = [ [[package]] name = "prost-wkt-build" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b31cae9a54ca84fee1504740a82eebf2479532905e106f63ca0c3bc8d780321" +checksum = "8a669d5acbe719010c6f62a64e6d7d88fdedc1fe46e419747949ecb6312e9b14" dependencies = [ - "heck", - "prost 0.12.3", + "heck 0.5.0", + "prost", "prost-build", "prost-types", "quote", @@ -2772,12 +2964,12 @@ dependencies = [ [[package]] name = "prost-wkt-types" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435be4a8704091b4c5fb1d79799de7f2dbff53af05edf29385237f8cf7ab37ee" +checksum = "01ef068e9b82e654614b22e6b13699bd545b6c0e2e721736008b00b38aeb4f64" dependencies = [ "chrono", - "prost 0.12.3", + "prost", "prost-build", "prost-types", "prost-wkt", @@ -2790,45 +2982,87 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.9.6" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +checksum = "666f0f59e259aea2d72e6012290c09877a780935cc3c18b1ceded41f3890d59c" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "memchr", "unicase", ] [[package]] name = "pulldown-cmark-to-cmark" -version = "10.0.4" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0194e6e1966c23cc5fd988714f85b18d548d773e81965413555d96569931833d" +checksum = "41b27c0d365d60ff3e085007911d73419e5664de48155d558ebfa84d117a5109" dependencies = [ "pulldown-cmark", ] [[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] name = "quick-xml" -version = "0.31.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", "serde", ] [[package]] +name = "quinn" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.0.0", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash 2.0.0", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2883,19 +3117,10 @@ dependencies = [ ] [[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core", -] - -[[package]] name = "rayon" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -2912,12 +3137,13 @@ dependencies = [ ] [[package]] -name = "redox_syscall" -version = "0.2.16" +name = "redb" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "074373f3e7e5d27d8741d19512232adb47be8622d3daef3a45bcae72050c3d2a" dependencies = [ - "bitflags 1.3.2", + "libc", + "log", ] [[package]] @@ -2931,18 +3157,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -2951,14 +3177,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -2972,13 +3198,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", ] [[package]] @@ -2989,32 +3215,33 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "relative-path" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "reqwest" -version = "0.11.23" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ - "base64", + "base64 0.22.1", "bytes", - "encoding_rs", "futures-core", "futures-util", - "h2 0.3.24", - "http 0.2.11", - "http-body 0.4.6", - "hyper 0.14.28", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", "hyper-rustls", + "hyper-util", "ipnet", "js-sys", "log", @@ -3022,15 +3249,17 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.10", - "rustls-native-certs 0.6.3", - "rustls-pemfile 1.0.4", + "quinn", + "rustls", + "rustls-native-certs", + "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "system-configuration", + "sync_wrapper 1.0.1", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3038,21 +3267,55 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "winreg", + "windows-registry", +] + +[[package]] +name = "reqwest-middleware" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562ceb5a604d3f7c885a792d42c199fd8af239d0a51b2fa6a78aafa092452b04" +dependencies = [ + "anyhow", + "async-trait", + "http", + "reqwest", + "serde", + "thiserror", + "tower-service", +] + +[[package]] +name = "reqwest-tracing" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfdd9bfa64c72233d8dd99ab7883efcdefe9e16d46488ecb9228b71a2e2ceb45" +dependencies = [ + "anyhow", + "async-trait", + "getrandom", + "http", + "matchit 0.8.4", + "opentelemetry 0.22.0", + "reqwest", + "reqwest-middleware", + "tracing", + "tracing-opentelemetry 0.23.0", ] [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3066,14 +3329,13 @@ dependencies = [ [[package]] name = "rowan" -version = "0.15.15" +version = "0.15.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a58fa8a7ccff2aec4f39cc45bf5f985cec7125ab271cf681c279fd00192b49" +checksum = "0a542b0253fa46e632d27a1dc5cf7b930de4df8659dc6e720b647fc72147ae3d" dependencies = [ "countme", - "hashbrown 0.14.3", - "memoffset 0.9.0", - "rustc-hash", + "hashbrown 0.14.5", + "rustc-hash 1.1.0", "text-size", ] @@ -3102,7 +3364,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.48", + "syn 2.0.79", "unicode-ident", ] @@ -3115,14 +3377,14 @@ dependencies = [ "quote", "rand", "rustc_version", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -3131,21 +3393,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + +[[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.30" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -3154,50 +3422,27 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" -dependencies = [ - "log", - "ring", - "rustls-webpki 0.101.7", - "sct", -] - -[[package]] -name = "rustls" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" dependencies = [ "log", + "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile 1.0.4", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-native-certs" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.0", + "rustls-pemfile", "rustls-pki-types", "schannel", "security-framework", @@ -3205,44 +3450,24 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64", -] - -[[package]] -name = "rustls-pemfile" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c333bb734fcdedcea57de1602543590f545f127dc8b533324318fd492c5c70b" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" - -[[package]] -name = "rustls-webpki" -version = "0.101.7" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -3251,21 +3476,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "rustyline" @@ -3292,9 +3505,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -3307,36 +3520,32 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] -name = "scopeguard" -version = "1.2.0" +name = "scoped-tls" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] -name = "sct" -version = "0.7.1" +name = "scopeguard" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -3345,9 +3554,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -3355,37 +3564,38 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -3413,14 +3623,24 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] [[package]] +name = "serde_tagged" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cd248df2ce32924bfc2273e1af035ff3092b73253fe0567230b5c4154a99e9" +dependencies = [ + "erased-serde", + "serde", +] + +[[package]] name = "serde_urlencoded" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3434,15 +3654,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.7.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ - "base64", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.1.0", + "indexmap 2.6.0", "serde", "serde_derive", "serde_json", @@ -3452,14 +3672,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.7.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] @@ -3494,10 +3714,16 @@ dependencies = [ ] [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -3521,32 +3747,16 @@ dependencies = [ ] [[package]] -name = "sled" -version = "0.34.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" -dependencies = [ - "crc32fast", - "crossbeam-epoch", - "crossbeam-utils", - "fs2", - "fxhash", - "libc", - "log", - "parking_lot 0.11.2", -] - -[[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smol_str" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" dependencies = [ "serde", ] @@ -3567,7 +3777,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "syn 1.0.109", @@ -3575,12 +3785,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3613,9 +3823,9 @@ checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "structmeta" @@ -3641,10 +3851,29 @@ dependencies = [ ] [[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.79", +] + +[[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -3659,9 +3888,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -3675,24 +3904,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" +name = "sync_wrapper" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" dependencies = [ - "core-foundation-sys", - "libc", + "futures-core", ] [[package]] @@ -3706,15 +3923,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.9.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3746,39 +3963,48 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", ] [[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -3797,9 +4023,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -3817,9 +4043,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -3832,60 +4058,54 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", + "mio 1.0.2", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", + "windows-sys 0.52.0", ] [[package]] name = "tokio-listener" -version = "0.3.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96367e127b4cf47b92592a5154a563435fe28fe3fccf25917d4a34ee59c87303" +checksum = "914a439d123292125bc806649c396d23e1aac5da4052f0d97b23137b38782f46" dependencies = [ - "axum 0.7.4", + "axum", + "clap", "document-features", "futures-core", "futures-util", + "hyper", + "hyper-util", "nix 0.26.4", "pin-project", "socket2", "tokio", "tokio-util", - "tonic 0.11.0", + "tonic", + "tower 0.4.13", + "tower-service", "tracing", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] @@ -3901,30 +4121,20 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.21.10", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls 0.22.2", + "rustls", "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -3948,9 +4158,9 @@ dependencies = [ [[package]] name = "tokio-test" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b3cbabd3ae862100094ae433e1def582cf86451b4e9bf83aa7ac1d8a7d719" +checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" dependencies = [ "async-stream", "bytes", @@ -3961,9 +4171,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -3971,7 +4181,6 @@ dependencies = [ "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -3982,8 +4191,20 @@ checksum = "4fb9d890e4dc9298b70f740f615f2e05b9db37dce531f6b24fb77ac993f9f217" dependencies = [ "serde", "serde_spanned", - "toml_datetime", - "toml_edit", + "toml_datetime 0.5.1", + "toml_edit 0.18.1", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.8", + "toml_edit 0.22.22", ] [[package]] @@ -3996,6 +4217,15 @@ dependencies = [ ] [[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] name = "toml_edit" version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4005,63 +4235,50 @@ dependencies = [ "nom8", "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.5.1", ] [[package]] -name = "tonic" -version = "0.9.2" +name = "toml_edit" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "async-trait", - "axum 0.6.20", - "base64", - "bytes", - "futures-core", - "futures-util", - "h2 0.3.24", - "http 0.2.11", - "http-body 0.4.6", - "hyper 0.14.28", - "hyper-timeout", - "percent-encoding", - "pin-project", - "prost 0.11.9", - "tokio", - "tokio-stream", - "tower", - "tower-layer", - "tower-service", - "tracing", + "indexmap 2.6.0", + "serde", + "serde_spanned", + "toml_datetime 0.6.8", + "winnow", ] [[package]] name = "tonic" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ "async-stream", "async-trait", - "axum 0.6.20", - "base64", + "axum", + "base64 0.22.1", "bytes", - "h2 0.3.24", - "http 0.2.11", - "http-body 0.4.6", - "hyper 0.14.28", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", - "prost 0.12.3", - "rustls-native-certs 0.7.0", - "rustls-pemfile 2.1.0", - "rustls-pki-types", + "prost", + "rustls-native-certs", + "rustls-pemfile", + "socket2", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -4069,28 +4286,42 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4ef6dd70a610078cb4e338a0f79d06bc759ff1b22d2120c2ff02ae264ba9c2" +checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" dependencies = [ "prettyplease", "proc-macro2", "prost-build", + "prost-types", "quote", - "syn 2.0.48", + "syn 2.0.79", +] + +[[package]] +name = "tonic-health" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1eaf34ddb812120f5c601162d5429933c9b527d901ab0e7f930d3147e33a09b2" +dependencies = [ + "async-stream", + "prost", + "tokio", + "tokio-stream", + "tonic", ] [[package]] name = "tonic-reflection" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "548c227bd5c0fae5925812c4ec6c66ffcfced23ea370cb823f4d18f0fc1cb6a7" +checksum = "878d81f52e7fcfd80026b7fdb6a9b578b3c3653ba987f87f0dce4b64043cba27" dependencies = [ - "prost 0.12.3", + "prost", "prost-types", "tokio", "tokio-stream", - "tonic 0.11.0", + "tonic", ] [[package]] @@ -4114,16 +4345,49 @@ dependencies = [ ] [[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +dependencies = [ + "bitflags 2.6.0", + "bytes", + "http", + "http-body", + "http-body-util", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -4145,7 +4409,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] @@ -4169,6 +4433,18 @@ dependencies = [ ] [[package]] +name = "tracing-indicatif" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069580424efe11d97c3fef4197fa98c004fa26672cc71ad8770d224e23b1951d" +dependencies = [ + "indicatif", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] name = "tracing-log" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4181,14 +4457,14 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c67ac25c5407e7b961fafc6f7e9aa5958fd297aada2d20fa2ae1737357e55596" +checksum = "a9be14ba1bbe4ab79e9229f7f89fab8d120b865859f10527f31c033e599d2284" dependencies = [ "js-sys", "once_cell", - "opentelemetry", - "opentelemetry_sdk", + "opentelemetry 0.22.0", + "opentelemetry_sdk 0.22.1", "smallvec", "tracing", "tracing-core", @@ -4198,13 +4474,21 @@ dependencies = [ ] [[package]] -name = "tracing-serde" -version = "0.1.3" +name = "tracing-opentelemetry" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +checksum = "a9784ed4da7d921bc8df6963f8c80a0e4ce34ba6ba76668acadd3edbd985ff3b" dependencies = [ - "serde", + "js-sys", + "once_cell", + "opentelemetry 0.24.0", + "opentelemetry_sdk 0.24.1", + "smallvec", + "tracing", "tracing-core", + "tracing-log", + "tracing-subscriber", + "web-time", ] [[package]] @@ -4217,15 +4501,43 @@ dependencies = [ "nu-ansi-term", "once_cell", "regex", - "serde", - "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", - "tracing-serde", +] + +[[package]] +name = "tracing-tracy" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc775fdaf33c3dfd19dc354729e65e87914bc67dcdc390ca1210807b8bee5902" +dependencies = [ + "tracing-core", + "tracing-subscriber", + "tracy-client", +] + +[[package]] +name = "tracy-client" +version = "0.17.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "746b078c6a09ebfd5594609049e07116735c304671eaab06ce749854d23435bc" +dependencies = [ + "loom", + "once_cell", + "tracy-client-sys", +] + +[[package]] +name = "tracy-client-sys" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68613466112302fdbeabc5fa55f7d57462a0b247d5a6b7d7e09401fb471a144d" +dependencies = [ + "cc", ] [[package]] @@ -4235,78 +4547,113 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] +name = "trybuild" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "207aa50d36c4be8d8c6ea829478be44a372c6a77669937bb39c698e52f1491e8" +dependencies = [ + "glob", + "serde", + "serde_derive", + "serde_json", + "termcolor", + "toml 0.8.19", +] + +[[package]] name = "tvix-build" version = "0.1.0" dependencies = [ + "anyhow", + "blake3", + "bstr", "bytes", "clap", - "itertools 0.12.0", - "prost 0.12.3", + "data-encoding", + "futures", + "itertools 0.12.1", + "mimalloc", + "oci-spec", + "prost", "prost-build", "rstest", + "serde_json", + "tempfile", "thiserror", "tokio", "tokio-listener", - "tonic 0.11.0", + "tonic", "tonic-build", "tonic-reflection", "tracing", - "tracing-subscriber", "tvix-castore", + "tvix-tracing", "url", + "uuid", ] [[package]] name = "tvix-castore" version = "0.1.0" dependencies = [ + "async-compression", "async-process", "async-stream", "async-tempfile", + "auto_impl", "bigtable_rs", "blake3", "bstr", "bytes", "data-encoding", "digest", + "erased-serde", "fastcdc", "fuse-backend-rs", "futures", "hex-literal", - "lazy_static", + "hyper-util", "libc", "object_store", - "parking_lot 0.12.1", + "parking_lot", "petgraph", + "pin-project", "pin-project-lite", - "prost 0.12.3", + "prost", "prost-build", + "redb", "rstest", "rstest_reuse", "serde", + "serde_json", "serde_qs", + "serde_tagged", "serde_with", - "sled", "tempfile", "thiserror", + "threadpool", "tokio", "tokio-retry", "tokio-stream", "tokio-tar", + "tokio-test", "tokio-util", - "tonic 0.11.0", + "tonic", "tonic-build", "tonic-reflection", - "tower", + "tower 0.4.13", "tracing", + "tracing-indicatif", + "tvix-tracing", "url", "vhost", "vhost-user-backend", - "virtio-bindings 0.2.2", + "virtio-bindings 0.2.3", "virtio-queue", "vm-memory", "vmm-sys-util", "walkdir", + "wu-manber", "xattr", "zstd", ] @@ -4318,17 +4665,22 @@ dependencies = [ "bytes", "clap", "dirs", - "nix-compat", + "expect-test", + "mimalloc", + "rnix", + "rowan", + "rustc-hash 2.0.0", "rustyline", + "smol_str", "thiserror", "tokio", "tracing", - "tracing-subscriber", + "tracing-indicatif", "tvix-build", - "tvix-castore", "tvix-eval", "tvix-glue", "tvix-store", + "tvix-tracing", "wu-manber", ] @@ -4344,11 +4696,11 @@ dependencies = [ "data-encoding", "dirs", "genawaiter", - "imbl", - "itertools 0.12.0", - "lazy_static", + "itertools 0.12.1", "lexical-core", "md-5", + "mimalloc", + "nohash-hasher", "os_str_bytes", "path-clean", "pretty_assertions", @@ -4357,6 +4709,7 @@ dependencies = [ "rnix", "rowan", "rstest", + "rustc-hash 2.0.0", "serde", "serde_json", "sha1", @@ -4365,9 +4718,10 @@ dependencies = [ "tabwriter", "tempfile", "test-strategy", - "toml", + "thiserror", + "toml 0.6.0", "tvix-eval-builtin-macros", - "xml-rs", + "vu128", ] [[package]] @@ -4385,16 +4739,16 @@ name = "tvix-glue" version = "0.1.0" dependencies = [ "async-compression", - "async-recursion", "bstr", "bytes", + "clap", "criterion", "data-encoding", "futures", "hex-literal", - "lazy_static", "magic", "md-5", + "mimalloc", "nix 0.27.1", "nix-compat", "pin-project", @@ -4411,13 +4765,14 @@ dependencies = [ "tokio-tar", "tokio-util", "tracing", + "tracing-indicatif", "tvix-build", "tvix-castore", "tvix-eval", "tvix-store", + "tvix-tracing", "url", "walkdir", - "wu-manber", ] [[package]] @@ -4434,9 +4789,10 @@ name = "tvix-store" version = "0.1.0" dependencies = [ "anyhow", + "async-compression", "async-process", - "async-recursion", "async-stream", + "auto_impl", "bigtable_rs", "blake3", "bstr", @@ -4444,16 +4800,20 @@ dependencies = [ "clap", "count-write", "data-encoding", + "ed25519", + "ed25519-dalek", "futures", - "lazy_static", + "hyper-util", + "lru", + "mimalloc", "nix-compat", - "opentelemetry", - "opentelemetry-otlp", - "opentelemetry_sdk", + "parking_lot", "pin-project-lite", - "prost 0.12.3", + "prost", "prost-build", + "redb", "reqwest", + "reqwest-middleware", "rstest", "rstest_reuse", "serde", @@ -4461,7 +4821,6 @@ dependencies = [ "serde_qs", "serde_with", "sha2", - "sled", "tempfile", "thiserror", "tokio", @@ -4469,20 +4828,50 @@ dependencies = [ "tokio-retry", "tokio-stream", "tokio-util", - "tonic 0.11.0", + "toml 0.8.19", + "tonic", "tonic-build", + "tonic-health", "tonic-reflection", - "tower", + "tower 0.4.13", + "tower-http", "tracing", - "tracing-opentelemetry", - "tracing-subscriber", + "tracing-indicatif", "tvix-castore", + "tvix-tracing", "url", "walkdir", - "xz2", ] [[package]] +name = "tvix-tracing" +version = "0.1.0" +dependencies = [ + "axum", + "http", + "indicatif", + "opentelemetry 0.24.0", + "opentelemetry-http", + "opentelemetry-otlp", + "opentelemetry_sdk 0.24.1", + "reqwest-tracing", + "thiserror", + "tokio", + "tonic", + "tracing", + "tracing-indicatif", + "tracing-opentelemetry 0.25.0", + "tracing-subscriber", + "tracing-tracy", +] + +[[package]] +name = "typeid" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" + +[[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4490,9 +4879,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "typetag" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "661d18414ec032a49ece2d56eee03636e43c4e8d577047ab334c0ba892e29aaf" +checksum = "52ba3b6e86ffe0054b2c44f2d86407388b933b16cb0a70eea3929420db1d9bbe" dependencies = [ "erased-serde", "inventory", @@ -4503,13 +4892,13 @@ dependencies = [ [[package]] name = "typetag-impl" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac73887f47b9312552aa90ef477927ff014d63d1920ca8037c6c1951eab64bb1" +checksum = "70b20a22c42c8f1cd23ce5e34f165d4d37038f5b663ad20fb6adbdf029172483" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] @@ -4529,36 +4918,36 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "untrusted" @@ -4568,9 +4957,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -4585,15 +4974,15 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", ] @@ -4612,9 +5001,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vhost" @@ -4651,9 +5040,9 @@ checksum = "3ff512178285488516ed85f15b5d0113a7cdb89e9e8a760b269ae4f02b84bd6b" [[package]] name = "virtio-bindings" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "878bcb1b2812a10c30d53b0ed054999de3d98f25ece91fc173973f9c57aaae86" +checksum = "68d0df4f5ad79b1dc81b5913ac737e24a84dcd5100f36ed953a1faec18aba241" [[package]] name = "virtio-queue" @@ -4689,19 +5078,49 @@ dependencies = [ ] [[package]] -name = "wait-timeout" -version = "0.2.0" +name = "vt100" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +checksum = "84cd863bf0db7e392ba3bd04994be3473491b31e66340672af5d11943c6274de" dependencies = [ - "libc", + "itoa", + "log", + "unicode-width", + "vte", +] + +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "arrayvec", + "utf8parse", + "vte_generate_state_changes", ] [[package]] +name = "vte_generate_state_changes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "vu128" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b18da3bd753c6f4373511e5f025423986560dfe4a5e7d642cc9a0266847f9fdd" + +[[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -4724,34 +5143,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.40" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -4761,9 +5181,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4771,28 +5191,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-streams" -version = "0.3.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" dependencies = [ "futures-util", "js-sys", @@ -4803,9 +5223,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -4813,40 +5233,15 @@ dependencies = [ [[package]] name = "web-time" -version = "0.2.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "which" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bf3ea8596f3a0dd5980b46430f2058dfe2c36a27ccfbb1845d6fbfcd9ba6e14" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", - "windows-sys 0.48.0", -] - -[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4864,11 +5259,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -4878,12 +5273,87 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -4901,7 +5371,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -4921,17 +5400,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -4942,9 +5422,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -4954,9 +5434,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -4966,9 +5446,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -4978,9 +5464,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -4990,9 +5476,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -5002,9 +5488,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -5014,18 +5500,17 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "winreg" -version = "0.50.0" +name = "winnow" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ - "cfg-if", - "windows-sys 0.48.0", + "memchr", ] [[package]] @@ -5045,12 +5530,6 @@ dependencies = [ ] [[package]] -name = "xml-rs" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" - -[[package]] name = "xz2" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5061,39 +5540,60 @@ dependencies = [ [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zstd" -version = "0.13.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.0.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/tvix/Cargo.nix b/tvix/Cargo.nix index 51d47b05e34f..749f39fb93cc 100644 --- a/tvix/Cargo.nix +++ b/tvix/Cargo.nix @@ -1,4 +1,4 @@ -# This file was @generated by crate2nix 0.13.0 with the command: +# This file was @generated by crate2nix 0.14.1 with the command: # "generate" "--all-features" # See https://github.com/kolloch/crate2nix for more info. @@ -13,6 +13,8 @@ , rootFeatures ? [ "default" ] # If true, throw errors instead of issueing deprecation warnings. , strictDeprecation ? false + # Elements to add to the `-C target-feature=` argument passed to `rustc` + # (separated by `,`, prefixed with `+`). # Used for conditional compilation based on CPU feature detection. , targetFeatures ? [ ] # Whether to perform release builds: longer compile times, faster binaries. @@ -33,6 +35,16 @@ rec { # You can override the features with # workspaceMembers."${crateName}".build.override { features = [ "default" "feature1" ... ]; }. workspaceMembers = { + "nar-bridge" = rec { + packageId = "nar-bridge"; + build = internal.buildRustCrateWithFeatures { + packageId = "nar-bridge"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; "nix-compat" = rec { packageId = "nix-compat"; build = internal.buildRustCrateWithFeatures { @@ -43,6 +55,36 @@ rec { # File a bug if you depend on any for non-debug work! debug = internal.debugCrate { inherit packageId; }; }; + "nix-compat-derive" = rec { + packageId = "nix-compat-derive"; + build = internal.buildRustCrateWithFeatures { + packageId = "nix-compat-derive"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + "nix-compat-derive-tests" = rec { + packageId = "nix-compat-derive-tests"; + build = internal.buildRustCrateWithFeatures { + packageId = "nix-compat-derive-tests"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + "nix-daemon" = rec { + packageId = "nix-daemon"; + build = internal.buildRustCrateWithFeatures { + packageId = "nix-daemon"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; "tvix-build" = rec { packageId = "tvix-build"; build = internal.buildRustCrateWithFeatures { @@ -123,6 +165,16 @@ rec { # File a bug if you depend on any for non-debug work! debug = internal.debugCrate { inherit packageId; }; }; + "tvix-tracing" = rec { + packageId = "tvix-tracing"; + build = internal.buildRustCrateWithFeatures { + packageId = "tvix-tracing"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; }; # A derivation that joins the outputs of all workspace members together. @@ -151,9 +203,10 @@ rec { crates = { "addr2line" = rec { crateName = "addr2line"; - version = "0.21.0"; + version = "0.24.2"; edition = "2018"; - sha256 = "1jx0k3iwyqr8klqbzk6kjvr496yd94aspis10vwsj5wy7gib4c4a"; + crateBin = [ ]; + sha256 = "1hd1i57zxgz08j6h5qrhsnm2fi0bcqvsh389fw400xm3arz2ggnz"; dependencies = [ { name = "gimli"; @@ -163,28 +216,29 @@ rec { } ]; features = { + "all" = [ "bin" ]; "alloc" = [ "dep:alloc" ]; + "bin" = [ "loader" "rustc-demangle" "cpp_demangle" "fallible-iterator" "smallvec" "dep:clap" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; "cpp_demangle" = [ "dep:cpp_demangle" ]; - "default" = [ "rustc-demangle" "cpp_demangle" "std-object" "fallible-iterator" "smallvec" "memmap2" ]; + "default" = [ "rustc-demangle" "cpp_demangle" "loader" "fallible-iterator" "smallvec" ]; "fallible-iterator" = [ "dep:fallible-iterator" ]; - "memmap2" = [ "dep:memmap2" ]; - "object" = [ "dep:object" ]; + "loader" = [ "std" "dep:object" "dep:memmap2" "dep:typed-arena" ]; "rustc-demangle" = [ "dep:rustc-demangle" ]; "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "gimli/rustc-dep-of-std" ]; "smallvec" = [ "dep:smallvec" ]; "std" = [ "gimli/std" ]; - "std-object" = [ "std" "object" "object/std" "object/compression" "gimli/endian-reader" ]; }; }; - "adler" = rec { - crateName = "adler"; - version = "1.0.2"; - edition = "2015"; - sha256 = "1zim79cvzd5yrkzl3nyfx0avijwgk9fqv3yrscdy1cc79ih02qpj"; + "adler2" = rec { + crateName = "adler2"; + version = "2.0.0"; + edition = "2021"; + sha256 = "09r6drylvgy8vv8k20lnbvwq8gp09h7smfn6h1rxsy15pgh629si"; authors = [ "Jonas Schievink <jonasschievink@gmail.com>" + "oyvindln <oyvindln@users.noreply.github.com>" ]; features = { "compiler_builtins" = [ "dep:compiler_builtins" ]; @@ -195,9 +249,9 @@ rec { }; "aho-corasick" = rec { crateName = "aho-corasick"; - version = "1.1.2"; + version = "1.1.3"; edition = "2021"; - sha256 = "1w510wnixvlgimkx1zjbvlxh6xps2vjgfqgwf5a6adlbjp5rv5mj"; + sha256 = "05mrpkvdgp5d20y2p989f187ry9diliijgwrs254fs9s1m1x6q4f"; libName = "aho_corasick"; authors = [ "Andrew Gallant <jamslam@gmail.com>" @@ -216,13 +270,30 @@ rec { "perf-literal" = [ "dep:memchr" ]; "std" = [ "memchr?/std" ]; }; - resolvedDefaultFeatures = [ "default" "perf-literal" "std" ]; + resolvedDefaultFeatures = [ "perf-literal" "std" ]; + }; + "allocator-api2" = rec { + crateName = "allocator-api2"; + version = "0.2.18"; + edition = "2018"; + sha256 = "0kr6lfnxvnj164j1x38g97qjlhb7akppqzvgfs0697140ixbav2w"; + libName = "allocator_api2"; + authors = [ + "Zakarum <zaq.dev@icloud.com>" + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" ]; }; "android-tzdata" = rec { crateName = "android-tzdata"; version = "0.1.1"; edition = "2018"; sha256 = "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9"; + libName = "android_tzdata"; authors = [ "RumovZ" ]; @@ -260,9 +331,9 @@ rec { }; "anstream" = rec { crateName = "anstream"; - version = "0.6.11"; + version = "0.6.15"; edition = "2021"; - sha256 = "19dndamalavhjwp4i74k8hdijcixb7gsfa6ycwyc1r8xn6y1wbkf"; + sha256 = "09nm4qj34kiwgzczdvj14x7hgsb235g4sqsay3xsz7zqn4d5rqb4"; dependencies = [ { name = "anstyle"; @@ -288,6 +359,10 @@ rec { packageId = "colorchoice"; } { + name = "is_terminal_polyfill"; + packageId = "is_terminal_polyfill"; + } + { name = "utf8parse"; packageId = "utf8parse"; } @@ -301,9 +376,9 @@ rec { }; "anstyle" = rec { crateName = "anstyle"; - version = "1.0.4"; + version = "1.0.8"; edition = "2021"; - sha256 = "11yxw02b6parn29s757z96rgiqbn8qy0fk9a3p3bhczm85dhfybh"; + sha256 = "1cfmkza63xpn1kkz844mgjwm9miaiz4jkyczmwxzivcsypk1vv0v"; features = { "default" = [ "std" ]; }; @@ -311,9 +386,10 @@ rec { }; "anstyle-parse" = rec { crateName = "anstyle-parse"; - version = "0.2.3"; + version = "0.2.5"; edition = "2021"; - sha256 = "134jhzrz89labrdwxxnjxqjdg06qvaflj1wkfnmyapwyldfwcnn7"; + sha256 = "1jy12rvgbldflnb2x7mcww9dcffw1mx22nyv6p3n7d62h0gdwizb"; + libName = "anstyle_parse"; dependencies = [ { name = "utf8parse"; @@ -330,9 +406,10 @@ rec { }; "anstyle-query" = rec { crateName = "anstyle-query"; - version = "1.0.2"; + version = "1.1.1"; edition = "2021"; - sha256 = "0j3na4b1nma39g4x7cwvj009awxckjf3z2vkwhldgka44hqj72g2"; + sha256 = "0aj22iy4pzk6mz745sfrm1ym14r0y892jhcrbs8nkj7nqx9gqdkd"; + libName = "anstyle_query"; dependencies = [ { name = "windows-sys"; @@ -345,9 +422,10 @@ rec { }; "anstyle-wincon" = rec { crateName = "anstyle-wincon"; - version = "3.0.2"; + version = "3.0.4"; edition = "2021"; - sha256 = "19v0fv400bmp4niqpzxnhg83vz12mmqv7l2l8vi80qcdxj0lpm8w"; + sha256 = "1y2pkvsrdxbcwircahb4wimans2pzmwwxad7ikdhj5lpdqdlxxsv"; + libName = "anstyle_wincon"; dependencies = [ { name = "anstyle"; @@ -364,9 +442,9 @@ rec { }; "anyhow" = rec { crateName = "anyhow"; - version = "1.0.79"; + version = "1.0.89"; edition = "2018"; - sha256 = "1ji5irqiwr8yprgqj8zvnli7zd7fz9kzaiddq44jnrl2l289h3h8"; + sha256 = "1xh1vg89n56h6nqikcmgbpmkixjds33492klrp9m96xrbmhgizc6"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -378,9 +456,10 @@ rec { }; "arc-swap" = rec { crateName = "arc-swap"; - version = "1.6.0"; + version = "1.7.1"; edition = "2018"; - sha256 = "19n9j146bpxs9phyh48gmlh9jjsdijr9p9br04qms0g9ypfsvp5x"; + sha256 = "0mrl9a9r9p9bln74q6aszvf22q1ijiw089jkrmabfqkbj31zixv9"; + libName = "arc_swap"; authors = [ "Michal 'vorner' Vaner <vorner@vorner.cz>" ]; @@ -390,9 +469,9 @@ rec { }; "arrayref" = rec { crateName = "arrayref"; - version = "0.3.7"; + version = "0.3.9"; edition = "2015"; - sha256 = "0ia5ndyxqkzdymqr4ls53jdmajf09adjimg5kvw65kkprg930jbb"; + sha256 = "1jzyp0nvp10dmahaq9a2rnxqdd5wxgbvp8xaibps3zai8c9fi8kn"; authors = [ "David Roundy <roundyd@physics.oregonstate.edu>" ]; @@ -400,13 +479,14 @@ rec { }; "arrayvec" = rec { crateName = "arrayvec"; - version = "0.7.4"; + version = "0.7.6"; edition = "2018"; - sha256 = "04b7n722jij0v3fnm3qk072d5ysc2q30rl9fz33zpfhzah30mlwn"; + sha256 = "0l1fz4ccgv6pm609rif37sl5nv5k6lbzi7kkppgzqzh1vwix20kw"; authors = [ "bluss" ]; features = { + "borsh" = [ "dep:borsh" ]; "default" = [ "std" ]; "serde" = [ "dep:serde" ]; "zeroize" = [ "dep:zeroize" ]; @@ -414,9 +494,10 @@ rec { }; "async-channel" = rec { crateName = "async-channel"; - version = "2.2.0"; + version = "2.3.1"; edition = "2021"; - sha256 = "1hzhkbrlmgbrrwb1d5aba5f03p42s6z80g5p38s127c27nj470pj"; + sha256 = "0skvwxj6ysfc6d7bhczz9a2550260g62bm5gl0nmjxxyn007id49"; + libName = "async_channel"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -427,13 +508,8 @@ rec { usesDefaultFeatures = false; } { - name = "event-listener"; - packageId = "event-listener 5.2.0"; - usesDefaultFeatures = false; - } - { name = "event-listener-strategy"; - packageId = "event-listener-strategy 0.5.0"; + packageId = "event-listener-strategy"; usesDefaultFeatures = false; } { @@ -448,15 +524,16 @@ rec { ]; features = { "default" = [ "std" ]; - "std" = [ "concurrent-queue/std" "event-listener/std" "event-listener-strategy/std" ]; + "std" = [ "concurrent-queue/std" "event-listener-strategy/std" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; "async-compression" = rec { crateName = "async-compression"; - version = "0.4.6"; + version = "0.4.14"; edition = "2018"; - sha256 = "0b6874q56g1cx8ivs9j89d757rsh9kyrrwlp1852094jjrmg85m1"; + sha256 = "19rlckkjavkd84rpaz0fjabic5fkzgh4v2pdn0b63kcwykw850lr"; + libName = "async_compression"; authors = [ "Wim Looman <wim@nemo157.com>" "Allen Bui <fairingrey@gmail.com>" @@ -496,6 +573,27 @@ rec { packageId = "xz2"; optional = true; } + { + name = "zstd"; + packageId = "zstd"; + rename = "libzstd"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "zstd-safe"; + packageId = "zstd-safe"; + optional = true; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "tokio"; + packageId = "tokio"; + usesDefaultFeatures = false; + features = [ "io-util" "macros" "rt-multi-thread" "io-std" ]; + } ]; features = { "all" = [ "all-implementations" "all-algorithms" ]; @@ -518,20 +616,21 @@ rec { "zstd-safe" = [ "dep:zstd-safe" ]; "zstdmt" = [ "zstd" "zstd-safe/zstdmt" ]; }; - resolvedDefaultFeatures = [ "bzip2" "flate2" "gzip" "tokio" "xz" "xz2" ]; + resolvedDefaultFeatures = [ "bzip2" "flate2" "gzip" "libzstd" "tokio" "xz" "xz2" "zstd" "zstd-safe" ]; }; "async-io" = rec { crateName = "async-io"; - version = "2.3.2"; + version = "2.3.4"; edition = "2021"; - sha256 = "110847w0ycfhklm3i928avd28x7lf9amblr2wjngi8ngk7sv1k6w"; + sha256 = "1s679l7x6ijh8zcxqn5pqgdiyshpy4xwklv86ldm1rhfjll04js4"; + libName = "async_io"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; dependencies = [ { name = "async-lock"; - packageId = "async-lock 3.3.0"; + packageId = "async-lock"; } { name = "cfg-if"; @@ -577,46 +676,31 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; + packageId = "windows-sys 0.59.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" ]; } ]; }; - "async-lock 2.8.0" = rec { + "async-lock" = rec { crateName = "async-lock"; - version = "2.8.0"; - edition = "2018"; - sha256 = "0asq5xdzgp3d5m82y5rg7a0k9q0g95jy6mgc7ivl334x7qlp4wi8"; - authors = [ - "Stjepan Glavina <stjepang@gmail.com>" - ]; - dependencies = [ - { - name = "event-listener"; - packageId = "event-listener 2.5.3"; - } - ]; - - }; - "async-lock 3.3.0" = rec { - crateName = "async-lock"; - version = "3.3.0"; + version = "3.4.0"; edition = "2021"; - sha256 = "0yxflkfw46rad4lv86f59b5z555dlfmg1riz1n8830rgi0qb8d6h"; + sha256 = "060vh45i809wcqyxzs5g69nqiqah7ydz0hpkcjys9258vqn4fvpz"; + libName = "async_lock"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; dependencies = [ { name = "event-listener"; - packageId = "event-listener 4.0.3"; + packageId = "event-listener"; usesDefaultFeatures = false; } { name = "event-listener-strategy"; - packageId = "event-listener-strategy 0.4.0"; + packageId = "event-listener-strategy"; usesDefaultFeatures = false; } { @@ -626,15 +710,17 @@ rec { ]; features = { "default" = [ "std" ]; + "loom" = [ "event-listener/loom" "dep:loom" ]; "std" = [ "event-listener/std" "event-listener-strategy/std" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; "async-process" = rec { crateName = "async-process"; - version = "2.1.0"; + version = "2.3.0"; edition = "2021"; - sha256 = "1j0cfac9p3kq5dclfzlz6jv5l29kwflh9nvr3ivmdg8ih3v3q7j5"; + sha256 = "1fr6cpqdw7hrmzns1983lgx86cg8vyz7nlrn0h0125iqq8fmy9b3"; + libName = "async_process"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -642,16 +728,15 @@ rec { { name = "async-channel"; packageId = "async-channel"; - target = { target, features }: (target."windows" or false); + target = { target, features }: ((target."windows" or false) || ("linux" == target."os" or null)); } { name = "async-io"; packageId = "async-io"; - target = { target, features }: (target."unix" or false); } { name = "async-lock"; - packageId = "async-lock 3.3.0"; + packageId = "async-lock"; } { name = "async-signal"; @@ -659,6 +744,11 @@ rec { target = { target, features }: (target."unix" or false); } { + name = "async-task"; + packageId = "async-task"; + target = { target, features }: ((target."windows" or false) || ("linux" == target."os" or null)); + } + { name = "blocking"; packageId = "blocking"; target = { target, features }: (target."windows" or false); @@ -669,7 +759,7 @@ rec { } { name = "event-listener"; - packageId = "event-listener 5.2.0"; + packageId = "event-listener"; } { name = "futures-lite"; @@ -679,59 +769,30 @@ rec { name = "rustix"; packageId = "rustix"; usesDefaultFeatures = false; - target = { target, features }: (target."unix" or false); - features = [ "std" "fs" ]; - } - { - name = "windows-sys"; - packageId = "windows-sys 0.52.0"; - usesDefaultFeatures = false; - target = { target, features }: (target."windows" or false); - features = [ "Win32_Foundation" "Win32_System_Threading" ]; - } - ]; - devDependencies = [ - { - name = "async-io"; - packageId = "async-io"; + target = { target, features }: ((target."unix" or false) && (!("linux" == target."os" or null))); + features = [ "std" "fs" "process" ]; } - ]; - - }; - "async-recursion" = rec { - crateName = "async-recursion"; - version = "1.0.5"; - edition = "2018"; - sha256 = "1l2vlgyaa9a2dd0y1vbqyppzsvpdr1y4rar4gn1qi68pl5dmmmaz"; - procMacro = true; - authors = [ - "Robert Usher <266585+dcchut@users.noreply.github.com>" - ]; - dependencies = [ { - name = "proc-macro2"; - packageId = "proc-macro2"; - usesDefaultFeatures = false; - } - { - name = "quote"; - packageId = "quote"; + name = "rustix"; + packageId = "rustix"; usesDefaultFeatures = false; + target = { target, features }: (target."unix" or false); + features = [ "std" "fs" ]; } { - name = "syn"; - packageId = "syn 2.0.48"; + name = "tracing"; + packageId = "tracing"; usesDefaultFeatures = false; - features = [ "full" "parsing" "printing" "proc-macro" "clone-impls" ]; } ]; }; "async-signal" = rec { crateName = "async-signal"; - version = "0.2.5"; + version = "0.2.10"; edition = "2018"; - sha256 = "1i9466hiqghhmljjnn83a8vnxi8z013xga03f59c89d2cl7xjiwy"; + sha256 = "1wxrq3871l00mil43nmh0akvwjjjnv0bn7n2pzwbvh00k0s00zk3"; + libName = "async_signal"; authors = [ "John Nunley <dev@notgull.net>" ]; @@ -743,7 +804,7 @@ rec { } { name = "async-lock"; - packageId = "async-lock 2.8.0"; + packageId = "async-lock"; target = { target, features }: (target."windows" or false); } { @@ -783,7 +844,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.59.0"; usesDefaultFeatures = false; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_System_Console" ]; @@ -799,9 +860,10 @@ rec { }; "async-stream" = rec { crateName = "async-stream"; - version = "0.3.5"; - edition = "2018"; - sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + version = "0.3.6"; + edition = "2021"; + sha256 = "0xl4zqncrdmw2g6241wgr11dxdg4h7byy6bz3l6si03qyfk72nhb"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -823,10 +885,11 @@ rec { }; "async-stream-impl" = rec { crateName = "async-stream-impl"; - version = "0.3.5"; - edition = "2018"; - sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; + version = "0.3.6"; + edition = "2021"; + sha256 = "0kaplfb5axsvf1gfs2gk6c4zx6zcsns0yf3ssk7iwni7bphlvhn7"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -841,7 +904,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" "visit-mut" ]; } ]; @@ -849,9 +912,10 @@ rec { }; "async-task" = rec { crateName = "async-task"; - version = "4.7.0"; - edition = "2018"; - sha256 = "16975vx6aqy5yf16fs9xz5vx1zq8mwkzfmykvcilc1j7b6c6xczv"; + version = "4.7.1"; + edition = "2021"; + sha256 = "1pp3avr4ri2nbh7s6y9ws0397nkx1zymmcr14sq761ljarh3axcb"; + libName = "async_task"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -866,6 +930,7 @@ rec { version = "0.4.0"; edition = "2021"; sha256 = "16zx4qcwzq94n13pp6xwa4589apm5y8j20jb7lk4yzn42fqlnzdk"; + libName = "async_tempfile"; authors = [ "Markus Mayer" ]; @@ -897,10 +962,11 @@ rec { }; "async-trait" = rec { crateName = "async-trait"; - version = "0.1.77"; + version = "0.1.83"; edition = "2021"; - sha256 = "1adf1jh2yg39rkpmqjqyr9xyd6849p0d95425i6imgbhx0syx069"; + sha256 = "1p8q8gm4fv2fdka8hwy2w3f8df7p5inixqi7rlmbnky3wmysw73j"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -915,8 +981,9 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; - features = [ "full" "visit-mut" ]; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "proc-macro" "visit-mut" ]; } ]; @@ -926,6 +993,7 @@ rec { version = "1.1.2"; edition = "2018"; sha256 = "1h5av1lw56m0jf0fd3bchxq8a30xv0b4wv8s4zkp4s0i7mfvs18m"; + libName = "atomic_waker"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" "Contributors to futures-rs" @@ -934,149 +1002,48 @@ rec { "portable-atomic" = [ "dep:portable-atomic" ]; }; }; - "autocfg" = rec { - crateName = "autocfg"; - version = "1.1.0"; - edition = "2015"; - sha256 = "1ylp3cb47ylzabimazvbz9ms6ap784zhb6syaz6c1jqpmcmq0s6l"; + "auto_impl" = rec { + crateName = "auto_impl"; + version = "1.2.0"; + edition = "2021"; + sha256 = "0hmfcahj0vrnzq7rayk7r428zp54x9a8awgw6wil753pbvqz71rw"; + procMacro = true; authors = [ - "Josh Stone <cuviper@gmail.com>" + "Ashley Mannix <ashleymannix@live.com.au>" + "Lukas Kalbertodt <lukas.kalbertodt@gmail.com>" ]; - - }; - "axum 0.6.20" = rec { - crateName = "axum"; - version = "0.6.20"; - edition = "2021"; - sha256 = "1gynqkg3dcy1zd7il69h8a3zax86v6qq5zpawqyn87mr6979x0iv"; dependencies = [ { - name = "async-trait"; - packageId = "async-trait"; - } - { - name = "axum-core"; - packageId = "axum-core 0.3.4"; - } - { - name = "bitflags"; - packageId = "bitflags 1.3.2"; - } - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - features = [ "alloc" ]; - } - { - name = "http"; - packageId = "http 0.2.11"; - } - { - name = "http-body"; - packageId = "http-body 0.4.6"; - } - { - name = "hyper"; - packageId = "hyper 0.14.28"; - features = [ "stream" ]; - } - { - name = "itoa"; - packageId = "itoa"; - } - { - name = "matchit"; - packageId = "matchit"; - } - { - name = "memchr"; - packageId = "memchr"; - } - { - name = "mime"; - packageId = "mime"; - } - { - name = "percent-encoding"; - packageId = "percent-encoding"; - } - { - name = "pin-project-lite"; - packageId = "pin-project-lite"; - } - { - name = "serde"; - packageId = "serde"; - } - { - name = "sync_wrapper"; - packageId = "sync_wrapper"; - } - { - name = "tower"; - packageId = "tower"; - usesDefaultFeatures = false; - features = [ "util" ]; - } - { - name = "tower-layer"; - packageId = "tower-layer"; + name = "proc-macro2"; + packageId = "proc-macro2"; } { - name = "tower-service"; - packageId = "tower-service"; + name = "quote"; + packageId = "quote"; } - ]; - buildDependencies = [ { - name = "rustversion"; - packageId = "rustversion"; + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" "visit" "visit-mut" ]; } ]; - devDependencies = [ - { - name = "rustversion"; - packageId = "rustversion"; - } - { - name = "serde"; - packageId = "serde"; - features = [ "derive" ]; - } - { - name = "tower"; - packageId = "tower"; - rename = "tower"; - features = [ "util" "timeout" "limit" "load-shed" "steer" "filter" ]; - } + + }; + "autocfg" = rec { + crateName = "autocfg"; + version = "1.4.0"; + edition = "2015"; + sha256 = "09lz3by90d2hphbq56znag9v87gfpd9gb8nr82hll8z6x2nhprdc"; + authors = [ + "Josh Stone <cuviper@gmail.com>" ]; - features = { - "__private_docs" = [ "tower/full" "dep:tower-http" ]; - "default" = [ "form" "http1" "json" "matched-path" "original-uri" "query" "tokio" "tower-log" ]; - "form" = [ "dep:serde_urlencoded" ]; - "headers" = [ "dep:headers" ]; - "http1" = [ "hyper/http1" ]; - "http2" = [ "hyper/http2" ]; - "json" = [ "dep:serde_json" "dep:serde_path_to_error" ]; - "macros" = [ "dep:axum-macros" ]; - "multipart" = [ "dep:multer" ]; - "query" = [ "dep:serde_urlencoded" ]; - "tokio" = [ "dep:tokio" "hyper/server" "hyper/tcp" "hyper/runtime" "tower/make" ]; - "tower-log" = [ "tower/log" ]; - "tracing" = [ "dep:tracing" "axum-core/tracing" ]; - "ws" = [ "tokio" "dep:tokio-tungstenite" "dep:sha1" "dep:base64" ]; - }; + }; - "axum 0.7.4" = rec { + "axum" = rec { crateName = "axum"; - version = "0.7.4"; + version = "0.7.7"; edition = "2021"; - sha256 = "17kv7v8m981cqmfbv5m538fzxhw51l9bajv06kfddi7njarb8dhj"; + sha256 = "1bkhgnj7rk1aih1c1ylqkmn72mjbgi8lql1paim35j3s613kjkjh"; dependencies = [ { name = "async-trait"; @@ -1084,7 +1051,7 @@ rec { } { name = "axum-core"; - packageId = "axum-core 0.4.3"; + packageId = "axum-core"; } { name = "bytes"; @@ -1098,11 +1065,11 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "http-body-util"; @@ -1110,14 +1077,14 @@ rec { } { name = "hyper"; - packageId = "hyper 1.2.0"; + packageId = "hyper"; optional = true; } { name = "hyper-util"; packageId = "hyper-util"; optional = true; - features = [ "tokio" "server" "server-auto" ]; + features = [ "tokio" "server" "service" ]; } { name = "itoa"; @@ -1125,7 +1092,7 @@ rec { } { name = "matchit"; - packageId = "matchit"; + packageId = "matchit 0.7.3"; } { name = "memchr"; @@ -1144,6 +1111,10 @@ rec { packageId = "pin-project-lite"; } { + name = "rustversion"; + packageId = "rustversion"; + } + { name = "serde"; packageId = "serde"; } @@ -1165,7 +1136,7 @@ rec { } { name = "sync_wrapper"; - packageId = "sync_wrapper"; + packageId = "sync_wrapper 1.0.1"; } { name = "tokio"; @@ -1176,7 +1147,7 @@ rec { } { name = "tower"; - packageId = "tower"; + packageId = "tower 0.5.1"; usesDefaultFeatures = false; features = [ "util" ]; } @@ -1195,18 +1166,8 @@ rec { usesDefaultFeatures = false; } ]; - buildDependencies = [ - { - name = "rustversion"; - packageId = "rustversion"; - } - ]; devDependencies = [ { - name = "rustversion"; - packageId = "rustversion"; - } - { name = "serde"; packageId = "serde"; features = [ "derive" ]; @@ -1223,7 +1184,7 @@ rec { } { name = "tower"; - packageId = "tower"; + packageId = "tower 0.5.1"; rename = "tower"; features = [ "util" "timeout" "limit" "load-shed" "steer" "filter" ]; } @@ -1236,8 +1197,8 @@ rec { "__private_docs" = [ "tower/full" "dep:tower-http" ]; "default" = [ "form" "http1" "json" "matched-path" "original-uri" "query" "tokio" "tower-log" "tracing" ]; "form" = [ "dep:serde_urlencoded" ]; - "http1" = [ "dep:hyper" "hyper?/http1" ]; - "http2" = [ "dep:hyper" "hyper?/http2" ]; + "http1" = [ "dep:hyper" "hyper?/http1" "hyper-util?/http1" ]; + "http2" = [ "dep:hyper" "hyper?/http2" "hyper-util?/http2" ]; "json" = [ "dep:serde_json" "dep:serde_path_to_error" ]; "macros" = [ "dep:axum-macros" ]; "multipart" = [ "dep:multer" ]; @@ -1247,13 +1208,14 @@ rec { "tracing" = [ "dep:tracing" "axum-core/tracing" ]; "ws" = [ "dep:hyper" "tokio" "dep:tokio-tungstenite" "dep:sha1" "dep:base64" ]; }; - resolvedDefaultFeatures = [ "default" "form" "http1" "json" "matched-path" "original-uri" "query" "tokio" "tower-log" "tracing" ]; + resolvedDefaultFeatures = [ "default" "form" "http1" "http2" "json" "matched-path" "original-uri" "query" "tokio" "tower-log" "tracing" ]; }; - "axum-core 0.3.4" = rec { + "axum-core" = rec { crateName = "axum-core"; - version = "0.3.4"; + version = "0.4.5"; edition = "2021"; - sha256 = "0b1d9nkqb8znaba4qqzxzc968qwj4ybn4vgpyz9lz4a7l9vsb7vm"; + sha256 = "16b1496c4gm387q20hkv5ic3k5bd6xmnvk50kwsy6ymr8rhvvwh9"; + libName = "axum_core"; dependencies = [ { name = "async-trait"; @@ -1271,17 +1233,33 @@ rec { } { name = "http"; - packageId = "http 0.2.11"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 0.4.6"; + packageId = "http-body"; + } + { + name = "http-body-util"; + packageId = "http-body-util"; } { name = "mime"; packageId = "mime"; } { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "rustversion"; + packageId = "rustversion"; + } + { + name = "sync_wrapper"; + packageId = "sync_wrapper 1.0.1"; + } + { name = "tower-layer"; packageId = "tower-layer"; } @@ -1289,11 +1267,11 @@ rec { name = "tower-service"; packageId = "tower-service"; } - ]; - buildDependencies = [ { - name = "rustversion"; - packageId = "rustversion"; + name = "tracing"; + packageId = "tracing"; + optional = true; + usesDefaultFeatures = false; } ]; devDependencies = [ @@ -1308,16 +1286,23 @@ rec { "__private_docs" = [ "dep:tower-http" ]; "tracing" = [ "dep:tracing" ]; }; + resolvedDefaultFeatures = [ "tracing" ]; }; - "axum-core 0.4.3" = rec { - crateName = "axum-core"; - version = "0.4.3"; + "axum-extra" = rec { + crateName = "axum-extra"; + version = "0.9.4"; edition = "2021"; - sha256 = "1qx28wg4j6qdcdrisqwyaavlzc0zvbsrcwa99zf9456lfbyn6p51"; + sha256 = "1ydi660sqd9bl6252axx12xkdn9v3jqgkidny6f71sla305j5hvk"; + libName = "axum_extra"; dependencies = [ { - name = "async-trait"; - packageId = "async-trait"; + name = "axum"; + packageId = "axum"; + usesDefaultFeatures = false; + } + { + name = "axum-core"; + packageId = "axum-core"; } { name = "bytes"; @@ -1330,12 +1315,17 @@ rec { features = [ "alloc" ]; } { + name = "headers"; + packageId = "headers"; + optional = true; + } + { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "http-body-util"; @@ -1350,8 +1340,14 @@ rec { packageId = "pin-project-lite"; } { - name = "sync_wrapper"; - packageId = "sync_wrapper"; + name = "serde"; + packageId = "serde"; + } + { + name = "tower"; + packageId = "tower 0.5.1"; + usesDefaultFeatures = false; + features = [ "util" ]; } { name = "tower-layer"; @@ -1368,31 +1364,103 @@ rec { usesDefaultFeatures = false; } ]; - buildDependencies = [ + devDependencies = [ { - name = "rustversion"; - packageId = "rustversion"; + name = "axum"; + packageId = "axum"; } - ]; - devDependencies = [ { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - features = [ "alloc" ]; + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "tower"; + packageId = "tower 0.5.1"; + features = [ "util" ]; } ]; features = { - "__private_docs" = [ "dep:tower-http" ]; - "tracing" = [ "dep:tracing" ]; + "async-read-body" = [ "dep:tokio-util" "tokio-util?/io" "dep:tokio" ]; + "attachment" = [ "dep:tracing" ]; + "cookie" = [ "dep:cookie" ]; + "cookie-key-expansion" = [ "cookie" "cookie?/key-expansion" ]; + "cookie-private" = [ "cookie" "cookie?/private" ]; + "cookie-signed" = [ "cookie" "cookie?/signed" ]; + "default" = [ "tracing" ]; + "erased-json" = [ "dep:serde_json" ]; + "form" = [ "dep:serde_html_form" ]; + "json-deserializer" = [ "dep:serde_json" "dep:serde_path_to_error" ]; + "json-lines" = [ "dep:serde_json" "dep:tokio-util" "dep:tokio-stream" "tokio-util?/io" "tokio-stream?/io-util" "dep:tokio" ]; + "multipart" = [ "dep:multer" ]; + "protobuf" = [ "dep:prost" ]; + "query" = [ "dep:serde_html_form" ]; + "tracing" = [ "dep:tracing" "axum-core/tracing" "axum/tracing" ]; + "typed-header" = [ "dep:headers" ]; + "typed-routing" = [ "dep:axum-macros" "dep:percent-encoding" "dep:serde_html_form" "dep:form_urlencoded" ]; }; - resolvedDefaultFeatures = [ "tracing" ]; + resolvedDefaultFeatures = [ "default" "tracing" "typed-header" ]; + }; + "axum-range" = rec { + crateName = "axum-range"; + version = "0.4.0"; + edition = "2021"; + sha256 = "1gb4r3x00yiaggapy002w0q8mx3dg9x4z2iwgzfyn5pplyc07hxi"; + libName = "axum_range"; + dependencies = [ + { + name = "axum"; + packageId = "axum"; + usesDefaultFeatures = false; + } + { + name = "axum-extra"; + packageId = "axum-extra"; + features = [ "typed-header" ]; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "futures"; + packageId = "futures"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "http-body"; + packageId = "http-body"; + } + { + name = "pin-project"; + packageId = "pin-project"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "fs" "io-util" ]; + } + ]; + devDependencies = [ + { + name = "axum"; + packageId = "axum"; + features = [ "macros" ]; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "rt" "rt-multi-thread" "macros" ]; + } + ]; + features = { }; }; "backtrace" = rec { crateName = "backtrace"; - version = "0.3.69"; - edition = "2018"; - sha256 = "0dsq23dhw4pfndkx2nsa1ml2g31idm7ss7ljxp8d57avygivg290"; + version = "0.3.74"; + edition = "2021"; + sha256 = "06pfif7nwx66qf2zaanc2fcq7m64i91ki9imw9xd3bnz5hrwp0ld"; authors = [ "The Rust Project Developers" ]; @@ -1424,32 +1492,27 @@ rec { packageId = "object"; usesDefaultFeatures = false; target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); - features = [ "read_core" "elf" "macho" "pe" "unaligned" "archive" ]; + features = [ "read_core" "elf" "macho" "pe" "xcoff" "unaligned" "archive" ]; } { name = "rustc-demangle"; packageId = "rustc-demangle"; } - ]; - buildDependencies = [ { - name = "cc"; - packageId = "cc"; + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + target = { target, features }: (target."windows" or false); } ]; features = { "cpp_demangle" = [ "dep:cpp_demangle" ]; "default" = [ "std" ]; - "rustc-serialize" = [ "dep:rustc-serialize" ]; "serde" = [ "dep:serde" ]; - "serialize-rustc" = [ "rustc-serialize" ]; "serialize-serde" = [ "serde" ]; - "verify-winapi" = [ "winapi/dbghelp" "winapi/handleapi" "winapi/libloaderapi" "winapi/memoryapi" "winapi/minwindef" "winapi/processthreadsapi" "winapi/synchapi" "winapi/tlhelp32" "winapi/winbase" "winapi/winnt" ]; - "winapi" = [ "dep:winapi" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "base64" = rec { + "base64 0.21.7" = rec { crateName = "base64"; version = "0.21.7"; edition = "2018"; @@ -1464,6 +1527,20 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; + "base64 0.22.1" = rec { + crateName = "base64"; + version = "0.22.1"; + edition = "2018"; + sha256 = "1imqzgh7bxcikp5vx3shqvw9j09g9ly0xr0jma0q66i52r7jbcvj"; + authors = [ + "Marshall Pierce <marshall@mpierce.org>" + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; "base64ct" = rec { crateName = "base64ct"; version = "1.6.0"; @@ -1479,13 +1556,13 @@ rec { }; "bigtable_rs" = rec { crateName = "bigtable_rs"; - version = "0.2.9"; + version = "0.2.10"; edition = "2021"; workspace_member = null; src = pkgs.fetchgit { - url = "https://github.com/flokli/bigtable_rs"; - rev = "0af404741dfc40eb9fa99cf4d4140a09c5c20df7"; - sha256 = "1njjam1lx2xlnm7a41lga8601vmjgqz0fvc77x24gd04pc7avxll"; + url = "https://github.com/liufuyang/bigtable_rs"; + rev = "1818355a5373a5bc2c84287e3a4e3807154ac8ef"; + sha256 = "0mn6iw1z7gdxbarsqiwscbdr25nplwlvzs0rs51vgnnjfsnbgl6q"; }; authors = [ "Fuyang Liu <liufuyang@users.noreply.github.com>" @@ -1497,7 +1574,12 @@ rec { } { name = "http"; - packageId = "http 0.2.11"; + packageId = "http"; + } + { + name = "hyper-util"; + packageId = "hyper-util"; + features = [ "tokio" ]; } { name = "log"; @@ -1505,7 +1587,7 @@ rec { } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; } { name = "prost-types"; @@ -1540,12 +1622,12 @@ rec { } { name = "tonic"; - packageId = "tonic 0.11.0"; + packageId = "tonic"; features = [ "tls" "transport" ]; } { name = "tower"; - packageId = "tower"; + packageId = "tower 0.4.13"; } ]; buildDependencies = [ @@ -1554,8 +1636,8 @@ rec { packageId = "prost-build"; } { - name = "prost-wkt-build"; - packageId = "prost-wkt-build"; + name = "prost-wkt-types"; + packageId = "prost-wkt-types"; } { name = "tonic-build"; @@ -1565,43 +1647,6 @@ rec { ]; }; - "bit-set" = rec { - crateName = "bit-set"; - version = "0.5.3"; - edition = "2015"; - sha256 = "1wcm9vxi00ma4rcxkl3pzzjli6ihrpn9cfdi0c5b4cvga2mxs007"; - authors = [ - "Alexis Beingessner <a.beingessner@gmail.com>" - ]; - dependencies = [ - { - name = "bit-vec"; - packageId = "bit-vec"; - usesDefaultFeatures = false; - } - ]; - features = { - "default" = [ "std" ]; - "std" = [ "bit-vec/std" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; - "bit-vec" = rec { - crateName = "bit-vec"; - version = "0.6.3"; - edition = "2015"; - sha256 = "1ywqjnv60cdh1slhz67psnp422md6jdliji6alq0gmly2xm9p7rl"; - authors = [ - "Alexis Beingessner <a.beingessner@gmail.com>" - ]; - features = { - "default" = [ "std" ]; - "serde" = [ "dep:serde" ]; - "serde_no_std" = [ "serde/alloc" ]; - "serde_std" = [ "std" "serde/std" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "bitflags 1.3.2" = rec { crateName = "bitflags"; version = "1.3.2"; @@ -1617,11 +1662,11 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "bitflags 2.4.2" = rec { + "bitflags 2.6.0" = rec { crateName = "bitflags"; - version = "2.4.2"; + version = "2.6.0"; edition = "2021"; - sha256 = "1pqd142hyqlzr7p9djxq2ff0jx07a2sb2xp9lhw69cbf80s0jmzd"; + sha256 = "1pkidwzn3hnxlsl8zizh0bncgbjnw7c41cx7bby26ncbzmiznj5h"; authors = [ "The Rust Project Developers" ]; @@ -1635,24 +1680,11 @@ rec { }; resolvedDefaultFeatures = [ "std" ]; }; - "bitmaps" = rec { - crateName = "bitmaps"; - version = "3.2.0"; - edition = "2021"; - sha256 = "00ql08pm4l9hizkldyy54v0pk96g7zg8x6i72c2vkcq0iawl4dkh"; - authors = [ - "Bodil Stokke <bodil@bodil.org>" - ]; - features = { - "default" = [ "std" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "blake3" = rec { crateName = "blake3"; - version = "1.5.0"; + version = "1.5.4"; edition = "2021"; - sha256 = "11ysh12zcqq6xkjxh5cbrmnwzalprm3z552i5ff7wm5za9hz0c82"; + sha256 = "1xy6gp8yfcpvzwrhbx5iksxxwf6hsix403klizgr1s6qgwj3686q"; authors = [ "Jack O'Connor <oconnor663@gmail.com>" "Samuel Neves" @@ -1682,8 +1714,8 @@ rec { features = [ "mac" ]; } { - name = "rayon"; - packageId = "rayon"; + name = "rayon-core"; + packageId = "rayon-core"; optional = true; } ]; @@ -1695,20 +1727,20 @@ rec { ]; features = { "default" = [ "std" ]; - "digest" = [ "dep:digest" ]; "mmap" = [ "std" "dep:memmap2" ]; - "rayon" = [ "dep:rayon" "std" ]; + "rayon" = [ "dep:rayon-core" "std" ]; "serde" = [ "dep:serde" ]; - "traits-preview" = [ "digest" ]; + "traits-preview" = [ "dep:digest" ]; "zeroize" = [ "dep:zeroize" "arrayvec/zeroize" ]; }; - resolvedDefaultFeatures = [ "default" "digest" "rayon" "std" "traits-preview" ]; + resolvedDefaultFeatures = [ "default" "rayon" "std" "traits-preview" ]; }; "block-buffer" = rec { crateName = "block-buffer"; version = "0.10.4"; edition = "2018"; sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -1722,9 +1754,9 @@ rec { }; "blocking" = rec { crateName = "blocking"; - version = "1.5.1"; - edition = "2018"; - sha256 = "064i3d6b8ln34fgdw49nmx9m36bwi3r3nv8c9xhcrpf4ilz92dva"; + version = "1.6.1"; + edition = "2021"; + sha256 = "1si99l8zp7c4zq87y35ayjgc5c9b60jb8h0k14zfcs679z2l2gvh"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -1734,19 +1766,10 @@ rec { packageId = "async-channel"; } { - name = "async-lock"; - packageId = "async-lock 3.3.0"; - target = { target, features }: (!(builtins.elem "wasm" target."family")); - } - { name = "async-task"; packageId = "async-task"; } { - name = "fastrand"; - packageId = "fastrand"; - } - { name = "futures-io"; packageId = "futures-io"; usesDefaultFeatures = false; @@ -1761,11 +1784,6 @@ rec { name = "piper"; packageId = "piper"; } - { - name = "tracing"; - packageId = "tracing"; - usesDefaultFeatures = false; - } ]; devDependencies = [ { @@ -1773,13 +1791,15 @@ rec { packageId = "futures-lite"; } ]; - + features = { + "tracing" = [ "dep:tracing" ]; + }; }; "bstr" = rec { crateName = "bstr"; - version = "1.9.0"; + version = "1.10.0"; edition = "2021"; - sha256 = "1p6hzf3wqwwynv6w4pn17jg21amfafph9kb5sfvf1idlli8h13y4"; + sha256 = "036wwrchd5gq3q4k6w1j2bfl2bk2ff8c0dsa9y7w7aw7nf7knwj0"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -1791,7 +1811,7 @@ rec { } { name = "regex-automata"; - packageId = "regex-automata 0.4.3"; + packageId = "regex-automata 0.4.8"; optional = true; usesDefaultFeatures = false; features = [ "dfa-search" ]; @@ -1814,14 +1834,15 @@ rec { }; "bumpalo" = rec { crateName = "bumpalo"; - version = "3.14.0"; + version = "3.16.0"; edition = "2021"; - sha256 = "1v4arnv9kwk54v5d0qqpv4vyw2sgr660nk0w3apzixi1cm3yfc3z"; + sha256 = "0b015qb4knwanbdlp1x48pkb4pm57b8gidbhhhxr900q2wb6fabr"; authors = [ "Nick Fitzgerald <fitzgen@gmail.com>" ]; features = { "allocator-api2" = [ "dep:allocator-api2" ]; + "serde" = [ "dep:serde" ]; }; resolvedDefaultFeatures = [ "default" ]; }; @@ -1836,13 +1857,12 @@ rec { features = { "default" = [ "std" ]; }; - resolvedDefaultFeatures = [ "default" "std" ]; }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.7.2"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "1wzs7l57iwqmrszdpr2mmqf1b1hgvpxafc30imxhnry0zfl9m3a2"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -1942,10 +1962,9 @@ rec { }; "cc" = rec { crateName = "cc"; - version = "1.0.83"; + version = "1.1.29"; edition = "2018"; - crateBin = [ ]; - sha256 = "1l643zidlb5iy1dskc5ggqs4wqa29a02f44piczqc8zcnsq4y5zi"; + sha256 = "1ldw40qx2lwk9021f64cdf6d286c5zbb2gk456qqp94l66n09s2q"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -1954,25 +1973,31 @@ rec { name = "jobserver"; packageId = "jobserver"; optional = true; + usesDefaultFeatures = false; } { name = "libc"; packageId = "libc"; + optional = true; usesDefaultFeatures = false; target = { target, features }: (target."unix" or false); } + { + name = "shlex"; + packageId = "shlex"; + } ]; features = { - "jobserver" = [ "dep:jobserver" ]; - "parallel" = [ "jobserver" ]; + "parallel" = [ "dep:libc" "dep:jobserver" ]; }; - resolvedDefaultFeatures = [ "jobserver" "parallel" ]; + resolvedDefaultFeatures = [ "parallel" ]; }; "cfg-if" = rec { crateName = "cfg-if"; version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -1984,9 +2009,9 @@ rec { }; "chrono" = rec { crateName = "chrono"; - version = "0.4.34"; + version = "0.4.38"; edition = "2021"; - sha256 = "12zk0ja924f55va2fs0qj34xaygq46fy92blmc7qkmcj9dj1bh2v"; + sha256 = "009l8vc5p8750vn02z30mblg4pv2qhkbfizhfwmzc6vpy5nr67x2"; dependencies = [ { name = "android-tzdata"; @@ -2026,7 +2051,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets 0.52.0"; + packageId = "windows-targets 0.52.6"; optional = true; target = { target, features }: (target."windows" or false); } @@ -2045,7 +2070,6 @@ rec { "rkyv-32" = [ "dep:rkyv" "rkyv?/size_32" ]; "rkyv-64" = [ "dep:rkyv" "rkyv?/size_64" ]; "rkyv-validation" = [ "rkyv?/validation" ]; - "rustc-serialize" = [ "dep:rustc-serialize" ]; "serde" = [ "dep:serde" ]; "std" = [ "alloc" ]; "unstable-locales" = [ "pure-rust-locales" ]; @@ -2058,9 +2082,9 @@ rec { }; "ciborium" = rec { crateName = "ciborium"; - version = "0.2.1"; + version = "0.2.2"; edition = "2021"; - sha256 = "09p9gr3jxys51v0fzwsmxym2p7pcz9mhng2xib74lnlfqzv93zgg"; + sha256 = "03hgfw4674im1pdqblcp77m7rc8x2v828si5570ga5q9dzyrzrj2"; authors = [ "Nathaniel McCallum <npmccallum@profian.com>" ]; @@ -2089,9 +2113,10 @@ rec { }; "ciborium-io" = rec { crateName = "ciborium-io"; - version = "0.2.1"; + version = "0.2.2"; edition = "2021"; - sha256 = "0mi6ci27lpz3azksxrvgzl9jc4a3dfr20pjx7y2nkcrjalbikyfd"; + sha256 = "0my7s5g24hvp1rs1zd1cxapz94inrvqpdf1rslrvxj8618gfmbq5"; + libName = "ciborium_io"; authors = [ "Nathaniel McCallum <npmccallum@profian.com>" ]; @@ -2102,9 +2127,10 @@ rec { }; "ciborium-ll" = rec { crateName = "ciborium-ll"; - version = "0.2.1"; + version = "0.2.2"; edition = "2021"; - sha256 = "0az2vabamfk75m74ylgf6nzqgqgma5yf25bc1ripfg09ri7a5yny"; + sha256 = "1n8g4j5rwkfs3rzfi6g1p7ngmz6m5yxsksryzf5k72ll7mjknrjp"; + libName = "ciborium_ll"; authors = [ "Nathaniel McCallum <npmccallum@profian.com>" ]; @@ -2116,18 +2142,19 @@ rec { { name = "half"; packageId = "half"; + usesDefaultFeatures = false; } ]; features = { - "std" = [ "alloc" ]; + "std" = [ "alloc" "half/std" ]; }; }; "clap" = rec { crateName = "clap"; - version = "4.4.18"; + version = "4.5.20"; edition = "2021"; crateBin = [ ]; - sha256 = "0p46h346y8nval6gwzh27if3icbi9dwl95fg5ir36ihrqip8smqy"; + sha256 = "1s37v23gcxkjy4800qgnkxkpliz68vslpr5sgn1xar56hmnkfzxr"; dependencies = [ { name = "clap_builder"; @@ -2155,6 +2182,7 @@ rec { "suggestions" = [ "clap_builder/suggestions" ]; "unicode" = [ "clap_builder/unicode" ]; "unstable-doc" = [ "clap_builder/unstable-doc" "derive" ]; + "unstable-ext" = [ "clap_builder/unstable-ext" ]; "unstable-styles" = [ "clap_builder/unstable-styles" ]; "unstable-v5" = [ "clap_builder/unstable-v5" "clap_derive?/unstable-v5" "deprecated" ]; "usage" = [ "clap_builder/usage" ]; @@ -2164,9 +2192,9 @@ rec { }; "clap_builder" = rec { crateName = "clap_builder"; - version = "4.4.18"; + version = "4.5.20"; edition = "2021"; - sha256 = "1iyif47075caa4x1p3ygk18b07lb4xl4k48w4c061i2hxi0dzx2d"; + sha256 = "0m6w10l2f65h3ch0d53lql6p26xxrh20ffipra9ysjsfsjmq1g0r"; dependencies = [ { name = "anstream"; @@ -2194,7 +2222,7 @@ rec { "std" = [ "anstyle/std" ]; "suggestions" = [ "dep:strsim" "error-context" ]; "unicode" = [ "dep:unicode-width" "dep:unicase" ]; - "unstable-doc" = [ "cargo" "wrap_help" "env" "unicode" "string" ]; + "unstable-doc" = [ "cargo" "wrap_help" "env" "unicode" "string" "unstable-ext" ]; "unstable-styles" = [ "color" ]; "unstable-v5" = [ "deprecated" ]; "wrap_help" = [ "help" "dep:terminal_size" ]; @@ -2203,14 +2231,14 @@ rec { }; "clap_derive" = rec { crateName = "clap_derive"; - version = "4.4.7"; + version = "4.5.18"; edition = "2021"; - sha256 = "0hk4hcxl56qwqsf4hmf7c0gr19r9fbxk0ah2bgkr36pmmaph966g"; + sha256 = "1ardb26bvcpg72q9myr7yir3a8c83gx7vxk1cccabsd9n73s1ija"; procMacro = true; dependencies = [ { name = "heck"; - packageId = "heck"; + packageId = "heck 0.5.0"; } { name = "proc-macro2"; @@ -2222,7 +2250,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -2234,9 +2262,9 @@ rec { }; "clap_lex" = rec { crateName = "clap_lex"; - version = "0.6.0"; + version = "0.7.2"; edition = "2021"; - sha256 = "1l8bragdvim7mva9flvd159dskn2bdkpl0jqrr41wnjfn8pcfbvh"; + sha256 = "15zcrc2fa6ycdzaihxghf48180bnvzsivhf0fmah24bnnaf76qhl"; }; "clipboard-win" = rec { @@ -2244,6 +2272,7 @@ rec { version = "4.5.0"; edition = "2018"; sha256 = "0qh3rypkf1lazniq4nr04hxsck0d55rigb5sjvpvgnap4dyc54bi"; + libName = "clipboard_win"; authors = [ "Douman <douman@gmx.se>" ]; @@ -2285,6 +2314,7 @@ rec { version = "0.1.2"; edition = "2015"; sha256 = "08l1b84bn8r8a72rbvyi2v8a5i0j0kk0a5gr7fb6lmjvw05pf86c"; + libName = "codemap_diagnostic"; authors = [ "Kevin Mehall <km@kevinmehall.net>" "The Rust Project Developers" @@ -2303,20 +2333,21 @@ rec { }; "colorchoice" = rec { crateName = "colorchoice"; - version = "1.0.0"; + version = "1.0.2"; edition = "2021"; - sha256 = "1ix7w85kwvyybwi2jdkl3yva2r2bvdcc3ka2grjfzfgrapqimgxc"; + sha256 = "1h18ph538y8yjmbpaf8li98l0ifms2xmh3rax9666c5qfjfi3zfk"; }; "concurrent-queue" = rec { crateName = "concurrent-queue"; - version = "2.4.0"; - edition = "2018"; - sha256 = "0qvk23ynj311adb4z7v89wk3bs65blps4n24q8rgl23vjk6lhq6i"; + version = "2.5.0"; + edition = "2021"; + sha256 = "0wrr3mzq2ijdkxwndhf79k952cp4zkz35ray8hvsxl96xrx1k82c"; + libName = "concurrent_queue"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" "Taiki Endo <te316e89@gmail.com>" - "John Nunley <jtnunley01@gmail.com>" + "John Nunley <dev@notgull.net>" ]; dependencies = [ { @@ -2332,11 +2363,53 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; + "console" = rec { + crateName = "console"; + version = "0.15.8"; + edition = "2018"; + sha256 = "1sz4nl9nz8pkmapqni6py7jxzi7nzqjxzb3ya4kxvmkb0zy867qf"; + authors = [ + "Armin Ronacher <armin.ronacher@active-4.com>" + ]; + dependencies = [ + { + name = "encode_unicode"; + packageId = "encode_unicode"; + target = { target, features }: (target."windows" or false); + } + { + name = "lazy_static"; + packageId = "lazy_static"; + } + { + name = "libc"; + packageId = "libc"; + } + { + name = "unicode-width"; + packageId = "unicode-width"; + optional = true; + } + { + name = "windows-sys"; + packageId = "windows-sys 0.52.0"; + target = { target, features }: (target."windows" or false); + features = [ "Win32_Foundation" "Win32_System_Console" "Win32_Storage_FileSystem" "Win32_UI_Input_KeyboardAndMouse" ]; + } + ]; + features = { + "default" = [ "unicode-width" "ansi-parsing" ]; + "unicode-width" = [ "dep:unicode-width" ]; + "windows-console-colors" = [ "ansi-parsing" ]; + }; + resolvedDefaultFeatures = [ "ansi-parsing" "unicode-width" ]; + }; "const-oid" = rec { crateName = "const-oid"; version = "0.9.6"; edition = "2021"; sha256 = "1y0jnqaq7p2wvspnx7qj76m7hjcqpz73qzvr9l2p9n2s51vr6if2"; + libName = "const_oid"; authors = [ "RustCrypto Developers" ]; @@ -2346,9 +2419,9 @@ rec { }; "constant_time_eq" = rec { crateName = "constant_time_eq"; - version = "0.3.0"; + version = "0.3.1"; edition = "2021"; - sha256 = "1hl0y8frzlhpr58rh8rlg4bm53ax09ikj2i5fk7gpyphvhq4s57p"; + sha256 = "19nwwczii762pwlsm7bpizgjg8hkg1kqi32b2g4rglijklsbhx3w"; authors = [ "Cesar Eduardo Barros <cesarb@cesarb.eti.br>" ]; @@ -2359,6 +2432,7 @@ rec { version = "0.9.4"; edition = "2018"; sha256 = "13zvbbj07yk3b61b8fhwfzhy35535a583irf23vlcg59j7h9bqci"; + libName = "core_foundation"; authors = [ "The Servo Project Developers" ]; @@ -2387,9 +2461,10 @@ rec { }; "core-foundation-sys" = rec { crateName = "core-foundation-sys"; - version = "0.8.6"; + version = "0.8.7"; edition = "2018"; - sha256 = "13w6sdf06r0hn7bx2b45zxsg1mm2phz34jikm6xc5qrbr6djpsh6"; + sha256 = "12w8j73lazxmr1z0h98hf3z623kl8ms7g07jch7n4p8f9nwlhdkp"; + libName = "core_foundation_sys"; authors = [ "The Servo Project Developers" ]; @@ -2403,6 +2478,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "11bswmgr81s3jagdci1pr6qh9vnz9zsbbf2dqpi260daa2mhgmff"; + libName = "count_write"; authors = [ "SOFe <sofe2038@gmail.com>" ]; @@ -2431,9 +2507,9 @@ rec { }; "cpufeatures" = rec { crateName = "cpufeatures"; - version = "0.2.12"; + version = "0.2.14"; edition = "2018"; - sha256 = "012m7rrak4girqlii3jnqwrr73gv1i980q4wra5yyyhvzwk5xzjk"; + sha256 = "1q3qd9qkw94vs7n5i0y3zz2cqgzcxvdgyb54ryngwmjhfbgrg1k0"; authors = [ "RustCrypto Developers" ]; @@ -2441,7 +2517,7 @@ rec { { name = "libc"; packageId = "libc"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-linux-android"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-linux-android"); } { name = "libc"; @@ -2463,9 +2539,9 @@ rec { }; "crc32fast" = rec { crateName = "crc32fast"; - version = "1.3.2"; + version = "1.4.2"; edition = "2015"; - sha256 = "03c8f29yx293yf43xar946xbls1g60c207m9drf8ilqhr25vsh5m"; + sha256 = "1czp7vif73b8xslr3c9yxysmh9ws2r8824qda7j47ffs9pcnjxx9"; authors = [ "Sam Rijs <srijs@airpost.net>" "Alex Crichton <alex@alexcrichton.com>" @@ -2598,6 +2674,7 @@ rec { version = "0.5.0"; edition = "2018"; sha256 = "1c866xkjqqhzg4cjvg01f8w6xc1j3j7s58rdksl52skq89iq4l3b"; + libName = "criterion_plot"; authors = [ "Jorge Aparicio <japaricious@gmail.com>" "Brook Heisler <brookheisler@gmail.com>" @@ -2616,9 +2693,10 @@ rec { }; "crossbeam-channel" = rec { crateName = "crossbeam-channel"; - version = "0.5.11"; + version = "0.5.13"; edition = "2021"; - sha256 = "16v48qdflpw3hgdik70bhsj7hympna79q7ci47rw0mlgnxsw2v8p"; + sha256 = "1wkx45r34v7g3wyi3lg2wz536lrrrab4h4hh741shfhr8rlhsj1k"; + libName = "crossbeam_channel"; dependencies = [ { name = "crossbeam-utils"; @@ -2637,6 +2715,7 @@ rec { version = "0.8.5"; edition = "2021"; sha256 = "03bp38ljx4wj6vvy4fbhx41q8f585zyqix6pncz1mkz93z08qgv1"; + libName = "crossbeam_deque"; dependencies = [ { name = "crossbeam-epoch"; @@ -2660,6 +2739,7 @@ rec { version = "0.9.18"; edition = "2021"; sha256 = "03j2np8llwf376m3fxqx859mgp9f83hj1w34153c7a9c7i5ar0jv"; + libName = "crossbeam_epoch"; dependencies = [ { name = "crossbeam-utils"; @@ -2674,24 +2754,39 @@ rec { "nightly" = [ "crossbeam-utils/nightly" ]; "std" = [ "alloc" "crossbeam-utils/std" ]; }; - resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + resolvedDefaultFeatures = [ "alloc" "std" ]; }; "crossbeam-utils" = rec { crateName = "crossbeam-utils"; - version = "0.8.19"; + version = "0.8.20"; edition = "2021"; - sha256 = "0iakrb1b8fjqrag7wphl94d10irhbh2fw1g444xslsywqyn3p3i4"; + sha256 = "100fksq5mm1n7zj242cclkw6yf7a4a8ix3lvpfkhxvdhbda9kv12"; + libName = "crossbeam_utils"; features = { "default" = [ "std" ]; "loom" = [ "dep:loom" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; + "crunchy" = rec { + crateName = "crunchy"; + version = "0.2.2"; + edition = "2015"; + sha256 = "1dx9mypwd5mpfbbajm78xcrg5lirqk7934ik980mmaffg3hdm0bs"; + authors = [ + "Vurich <jackefransham@hotmail.co.uk>" + ]; + features = { + "default" = [ "limit_128" ]; + }; + resolvedDefaultFeatures = [ "default" "limit_128" ]; + }; "crypto-common" = rec { crateName = "crypto-common"; version = "0.1.6"; edition = "2018"; sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; authors = [ "RustCrypto Developers" ]; @@ -2714,9 +2809,10 @@ rec { }; "curve25519-dalek" = rec { crateName = "curve25519-dalek"; - version = "4.1.1"; + version = "4.1.3"; edition = "2021"; - sha256 = "0p7ns5917k6369gajrsbfj24llc5zfm635yh3abla7sb5rm8r6z8"; + sha256 = "1gmjb9dsknrr8lypmhkyjd67p1arb8mbfamlwxm7vph38my8pywp"; + libName = "curve25519_dalek"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -2762,10 +2858,6 @@ rec { ]; buildDependencies = [ { - name = "platforms"; - packageId = "platforms"; - } - { name = "rustc_version"; packageId = "rustc_version"; } @@ -2789,6 +2881,7 @@ rec { edition = "2021"; sha256 = "1cry71xxrr0mcy5my3fb502cwfxy6822k4pm19cwrilrg7hq4s7l"; procMacro = true; + libName = "curve25519_dalek_derive"; dependencies = [ { name = "proc-macro2"; @@ -2800,7 +2893,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -2808,9 +2901,9 @@ rec { }; "darling" = rec { crateName = "darling"; - version = "0.20.8"; - edition = "2018"; - sha256 = "14a38qsi9104kvk1z11rqj0bnz1866dyhnvgvbgzz17d2g6nzqsl"; + version = "0.20.10"; + edition = "2021"; + sha256 = "1299h2z88qn71mizhh05j26yr3ik0wnqmw11ijds89l8i9nbhqvg"; authors = [ "Ted Driggs <ted.driggs@outlook.com>" ]; @@ -2833,9 +2926,9 @@ rec { }; "darling_core" = rec { crateName = "darling_core"; - version = "0.20.8"; - edition = "2018"; - sha256 = "03x7s149p06xfwcq0lgkk4yxh6jf7jckny18nzp1yyk87b1g2b4w"; + version = "0.20.10"; + edition = "2021"; + sha256 = "1rgr9nci61ahnim93yh3xy6fkfayh7sk4447hahawah3m1hkh4wm"; authors = [ "Ted Driggs <ted.driggs@outlook.com>" ]; @@ -2863,7 +2956,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" "extra-traits" ]; } ]; @@ -2875,9 +2968,9 @@ rec { }; "darling_macro" = rec { crateName = "darling_macro"; - version = "0.20.8"; - edition = "2018"; - sha256 = "0gwkz0cjfy3fgcc1zmm7azzhj5qpja34s0cklcria4l38sjyss56"; + version = "0.20.10"; + edition = "2021"; + sha256 = "01kq3ibbn47czijj39h3vxyw0c2ksd0jvc097smcrk7n2jjs4dnk"; procMacro = true; authors = [ "Ted Driggs <ted.driggs@outlook.com>" @@ -2893,16 +2986,17 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; } ]; }; "data-encoding" = rec { crateName = "data-encoding"; - version = "2.5.0"; + version = "2.6.0"; edition = "2018"; - sha256 = "1rcbnwfmfxhlshzbn3r7srm3azqha3mn33yxyqxkzz2wpqcjm5ky"; + sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -2914,9 +3008,9 @@ rec { }; "der" = rec { crateName = "der"; - version = "0.7.8"; + version = "0.7.9"; edition = "2021"; - sha256 = "070bwiyr80800h31c5zd96ckkgagfjgnrrdmz3dzg2lccsd3dypz"; + sha256 = "1h4vzjfa1lczxdf8avfj9qlwh1qianqlxdy1g5rn762qnvkzhnzm"; authors = [ "RustCrypto Developers" ]; @@ -2980,6 +3074,94 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "powerfmt" "serde" "std" ]; }; + "derive_builder" = rec { + crateName = "derive_builder"; + version = "0.20.2"; + edition = "2018"; + sha256 = "0is9z7v3kznziqsxa5jqji3ja6ay9wzravppzhcaczwbx84znzah"; + authors = [ + "Colin Kiegel <kiegel@gmx.de>" + "Pascal Hertleif <killercup@gmail.com>" + "Jan-Erik Rediger <janerik@fnordig.de>" + "Ted Driggs <ted.driggs@outlook.com>" + ]; + dependencies = [ + { + name = "derive_builder_macro"; + packageId = "derive_builder_macro"; + } + ]; + features = { + "alloc" = [ "derive_builder_macro/alloc" ]; + "clippy" = [ "derive_builder_macro/clippy" ]; + "default" = [ "std" ]; + "std" = [ "derive_builder_macro/lib_has_std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "derive_builder_core" = rec { + crateName = "derive_builder_core"; + version = "0.20.2"; + edition = "2018"; + sha256 = "1s640r6q46c2iiz25sgvxw3lk6b6v5y8hwylng7kas2d09xwynrd"; + authors = [ + "Colin Kiegel <kiegel@gmx.de>" + "Pascal Hertleif <killercup@gmail.com>" + "Jan-Erik Rediger <janerik@fnordig.de>" + "Ted Driggs <ted.driggs@outlook.com>" + ]; + dependencies = [ + { + name = "darling"; + packageId = "darling"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" "extra-traits" ]; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "lib_has_std" ]; + }; + "derive_builder_macro" = rec { + crateName = "derive_builder_macro"; + version = "0.20.2"; + edition = "2018"; + sha256 = "0g1zznpqrmvjlp2w7p0jzsjvpmw5rvdag0rfyypjhnadpzib0qxb"; + procMacro = true; + authors = [ + "Colin Kiegel <kiegel@gmx.de>" + "Pascal Hertleif <killercup@gmail.com>" + "Jan-Erik Rediger <janerik@fnordig.de>" + "Ted Driggs <ted.driggs@outlook.com>" + ]; + dependencies = [ + { + name = "derive_builder_core"; + packageId = "derive_builder_core"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" "extra-traits" ]; + } + ]; + features = { + "alloc" = [ "derive_builder_core/alloc" ]; + "clippy" = [ "derive_builder_core/clippy" ]; + "lib_has_std" = [ "derive_builder_core/lib_has_std" ]; + }; + resolvedDefaultFeatures = [ "lib_has_std" ]; + }; "diff" = rec { crateName = "diff"; version = "0.1.13"; @@ -3051,6 +3233,7 @@ rec { version = "2.0.0"; edition = "2018"; sha256 = "1q9kr151h9681wwp6is18750ssghz6j9j7qm7qi1ngcwy7mzi35r"; + libName = "dirs_next"; authors = [ "The @xdg-rs members" ]; @@ -3071,6 +3254,7 @@ rec { version = "0.3.7"; edition = "2015"; sha256 = "19md1cnkazham8a6kh22v12d8hh3raqahfk6yb043vrjr68is78v"; + libName = "dirs_sys"; authors = [ "Simon Ochsenreither <simon@ochsenreither.de>" ]; @@ -3100,6 +3284,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "0kavhavdxv4phzj4l0psvh55hszwnr0rcz8sxbvx20pyqi2a3gaf"; + libName = "dirs_sys_next"; authors = [ "The @xdg-rs members" ]; @@ -3124,6 +3309,16 @@ rec { ]; }; + "dissimilar" = rec { + crateName = "dissimilar"; + version = "1.0.9"; + edition = "2018"; + sha256 = "0bcn4s99ghigd3yadpd7i3gljv5z2hkr07ijvvxvsxmz3yfygy2r"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + + }; "doc-comment" = rec { crateName = "doc-comment"; version = "0.3.3"; @@ -3137,13 +3332,14 @@ rec { }; "document-features" = rec { crateName = "document-features"; - version = "0.2.8"; + version = "0.2.10"; edition = "2018"; - sha256 = "15cvgxqngxslgllz15m8aban6wqfgsi6nlhr0g25yfsnd6nq4lpg"; + sha256 = "182h528pjyv4ppil2pd2nir46qrb393x5kvm4y51yhnjmgm6jsfb"; procMacro = true; + libName = "document_features"; libPath = "lib.rs"; authors = [ - "Slint Developers <info@slint-ui.com>" + "Slint Developers <info@slint.dev>" ]; dependencies = [ { @@ -3189,9 +3385,10 @@ rec { }; "ed25519-dalek" = rec { crateName = "ed25519-dalek"; - version = "2.1.0"; + version = "2.1.1"; edition = "2021"; - sha256 = "1h13qm789m9gdjl6jazss80hqi8ll37m0afwcnw23zcbqjp8wqhz"; + sha256 = "0w88cafwglg9hjizldbmlza0ns3hls81zk1bcih3m5m3h67algaa"; + libName = "ed25519_dalek"; authors = [ "isis lovecruft <isis@patternsinthevoid.net>" "Tony Arcieri <bascule@gmail.com>" @@ -3266,9 +3463,9 @@ rec { }; "either" = rec { crateName = "either"; - version = "1.9.0"; + version = "1.13.0"; edition = "2018"; - sha256 = "01qy3anr7jal5lpc20791vxrw0nl6vksb5j7x56q2fycgcyy8sm2"; + sha256 = "1w2c1mybrd7vljyxk77y9f4w9dyjrmp3yp82mk7bcm8848fazcb0"; authors = [ "bluss" ]; @@ -3276,36 +3473,29 @@ rec { "default" = [ "use_std" ]; "serde" = [ "dep:serde" ]; }; - resolvedDefaultFeatures = [ "default" "use_std" ]; + resolvedDefaultFeatures = [ "use_std" ]; }; - "encoding_rs" = rec { - crateName = "encoding_rs"; - version = "0.8.33"; - edition = "2018"; - sha256 = "1qa5k4a0ipdrxq4xg9amms9r9pnnfn7nfh2i9m3mw0ka563b6s3j"; + "encode_unicode" = rec { + crateName = "encode_unicode"; + version = "0.3.6"; + edition = "2015"; + sha256 = "07w3vzrhxh9lpjgsg2y5bwzfar2aq35mdznvcp3zjl0ssj7d4mx3"; authors = [ - "Henri Sivonen <hsivonen@hsivonen.fi>" - ]; - dependencies = [ - { - name = "cfg-if"; - packageId = "cfg-if"; - } + "Torbjørn Birch Moltu <t.b.moltu@lyse.net>" ]; features = { - "default" = [ "alloc" ]; - "fast-legacy-encode" = [ "fast-hangul-encode" "fast-hanja-encode" "fast-kanji-encode" "fast-gb-hanzi-encode" "fast-big5-hanzi-encode" ]; - "packed_simd" = [ "dep:packed_simd" ]; - "serde" = [ "dep:serde" ]; - "simd-accel" = [ "packed_simd" "packed_simd/into_bits" ]; + "ascii" = [ "dep:ascii" ]; + "clippy" = [ "dep:clippy" ]; + "default" = [ "std" ]; }; - resolvedDefaultFeatures = [ "alloc" "default" ]; + resolvedDefaultFeatures = [ "default" "std" ]; }; "endian-type" = rec { crateName = "endian-type"; version = "0.1.2"; edition = "2015"; sha256 = "0bbh88zaig1jfqrm7w3gx0pz81kw2jakk3055vbgapw3dmk08ky3"; + libName = "endian_type"; authors = [ "Lolirofle <lolipopple@hotmail.com>" ]; @@ -3317,6 +3507,7 @@ rec { edition = "2018"; sha256 = "0k6wcf58h5kh64yq5nfq71va53kaya0kzxwsjwbgwm2n2zd9axxs"; procMacro = true; + libName = "enum_primitive_derive"; authors = [ "Doug Goldstein <cardoe@cardoe.com>" ]; @@ -3332,7 +3523,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; } ]; @@ -3346,9 +3537,10 @@ rec { }; "erased-serde" = rec { crateName = "erased-serde"; - version = "0.4.4"; + version = "0.4.5"; edition = "2021"; - sha256 = "1lx0si6iljzmfpblhn4b0ip3kw2yv4vjyca0riqz3ix311q80wrb"; + sha256 = "13dirfj9972nvk05b20w3xyn3xp1j6qyfp9avhksnkxbcnfkiqi4"; + libName = "erased_serde"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3358,19 +3550,23 @@ rec { packageId = "serde"; usesDefaultFeatures = false; } + { + name = "typeid"; + packageId = "typeid"; + } ]; features = { "alloc" = [ "serde/alloc" ]; "default" = [ "std" ]; "std" = [ "alloc" "serde/std" ]; }; - resolvedDefaultFeatures = [ "alloc" ]; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; "errno" = rec { crateName = "errno"; - version = "0.3.8"; + version = "0.3.9"; edition = "2018"; - sha256 = "0ia28ylfsp36i27g1qih875cyyy4by2grf80ki8vhgh6vinf8n52"; + sha256 = "1fi0m0493maq1jygcf1bya9cymz2pc1mqxj26bdv7yjd37v5qk2k"; authors = [ "Chris Wong <lambda.fairy@gmail.com>" ]; @@ -3411,6 +3607,7 @@ rec { version = "2.3.1"; edition = "2018"; sha256 = "08baxlf8qz01lgjsdbfhs193r9y1nlc566s5xvzyf4dzwy8qkwb4"; + libName = "error_code"; authors = [ "Douman <douman@gmx.se>" ]; @@ -3427,58 +3624,15 @@ rec { ]; features = { }; }; - "event-listener 2.5.3" = rec { + "event-listener" = rec { crateName = "event-listener"; - version = "2.5.3"; - edition = "2018"; - sha256 = "1q4w3pndc518crld6zsqvvpy9lkzwahp2zgza9kbzmmqh9gif1h2"; - authors = [ - "Stjepan Glavina <stjepang@gmail.com>" - ]; - - }; - "event-listener 4.0.3" = rec { - crateName = "event-listener"; - version = "4.0.3"; + version = "5.3.1"; edition = "2021"; - sha256 = "0vk4smw1vf871vi76af1zn7w69jg3zmpjddpby2qq91bkg21bck7"; - authors = [ - "Stjepan Glavina <stjepang@gmail.com>" - ]; - dependencies = [ - { - name = "concurrent-queue"; - packageId = "concurrent-queue"; - usesDefaultFeatures = false; - } - { - name = "parking"; - packageId = "parking"; - optional = true; - target = { target, features }: (!(builtins.elem "wasm" target."family")); - } - { - name = "pin-project-lite"; - packageId = "pin-project-lite"; - } - ]; - features = { - "default" = [ "std" ]; - "parking" = [ "dep:parking" ]; - "portable-atomic" = [ "portable-atomic-util" "portable_atomic_crate" ]; - "portable-atomic-util" = [ "dep:portable-atomic-util" ]; - "portable_atomic_crate" = [ "dep:portable_atomic_crate" ]; - "std" = [ "concurrent-queue/std" "parking" ]; - }; - resolvedDefaultFeatures = [ "parking" "std" ]; - }; - "event-listener 5.2.0" = rec { - crateName = "event-listener"; - version = "5.2.0"; - edition = "2021"; - sha256 = "14fcnjgpfl22645nhc3hzkdq3a1v0srqacc3kfassg7sjj8vhprb"; + sha256 = "1fkm6q4hjn61wl52xyqyyxai0x9w0ngrzi0wf1qsf8vhsadvwck0"; + libName = "event_listener"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" + "John Nunley <dev@notgull.net>" ]; dependencies = [ { @@ -3499,26 +3653,28 @@ rec { ]; features = { "default" = [ "std" ]; + "loom" = [ "concurrent-queue/loom" "parking?/loom" "dep:loom" ]; "parking" = [ "dep:parking" ]; - "portable-atomic" = [ "portable-atomic-util" "portable_atomic_crate" ]; + "portable-atomic" = [ "portable-atomic-util" "portable_atomic_crate" "concurrent-queue/portable-atomic" ]; "portable-atomic-util" = [ "dep:portable-atomic-util" ]; "portable_atomic_crate" = [ "dep:portable_atomic_crate" ]; "std" = [ "concurrent-queue/std" "parking" ]; }; resolvedDefaultFeatures = [ "default" "parking" "std" ]; }; - "event-listener-strategy 0.4.0" = rec { + "event-listener-strategy" = rec { crateName = "event-listener-strategy"; - version = "0.4.0"; - edition = "2018"; - sha256 = "1lwprdjqp2ibbxhgm9khw7s7y7k4xiqj5i5yprqiks6mnrq4v3lm"; + version = "0.5.2"; + edition = "2021"; + sha256 = "18f5ri227khkayhv3ndv7yl4rnasgwksl2jhwgafcxzr7324s88g"; + libName = "event_listener_strategy"; authors = [ "John Nunley <dev@notgull.net>" ]; dependencies = [ { name = "event-listener"; - packageId = "event-listener 4.0.3"; + packageId = "event-listener"; usesDefaultFeatures = false; } { @@ -3532,30 +3688,26 @@ rec { }; resolvedDefaultFeatures = [ "std" ]; }; - "event-listener-strategy 0.5.0" = rec { - crateName = "event-listener-strategy"; - version = "0.5.0"; - edition = "2021"; - sha256 = "148jflvjrq0zrr3dx3srv88jksj1klm4amy3b9fifjdpm75azvgy"; + "expect-test" = rec { + crateName = "expect-test"; + version = "1.5.0"; + edition = "2018"; + sha256 = "1q55nrkgzg345905aqbsdrwlq4sk0gjn4z5bdph1an1kc6jy02wy"; + libName = "expect_test"; authors = [ - "John Nunley <dev@notgull.net>" + "rust-analyzer developers" ]; dependencies = [ { - name = "event-listener"; - packageId = "event-listener 5.2.0"; - usesDefaultFeatures = false; + name = "dissimilar"; + packageId = "dissimilar"; } { - name = "pin-project-lite"; - packageId = "pin-project-lite"; + name = "once_cell"; + packageId = "once_cell"; } ]; - features = { - "default" = [ "std" ]; - "std" = [ "event-listener/std" ]; - }; - resolvedDefaultFeatures = [ "std" ]; + }; "fastcdc" = rec { crateName = "fastcdc"; @@ -3600,9 +3752,9 @@ rec { }; "fastrand" = rec { crateName = "fastrand"; - version = "2.0.1"; + version = "2.1.1"; edition = "2018"; - sha256 = "19flpv5zbzpf0rk4x77z4zf25in0brg8l7m304d3yrf47qvwxjr5"; + sha256 = "19nyzdq3ha4g173364y2wijmd6jlyms8qx40daqkxsnl458jmh78"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -3619,6 +3771,7 @@ rec { version = "3.0.13"; edition = "2018"; sha256 = "1df1jdncda67g65hrnmd2zsl7q5hdn8cm84chdalxndsx7akw0zg"; + libName = "fd_lock"; authors = [ "Yoshua Wuyts <yoshuawuyts@gmail.com>" ]; @@ -3644,9 +3797,10 @@ rec { }; "fiat-crypto" = rec { crateName = "fiat-crypto"; - version = "0.2.5"; + version = "0.2.9"; edition = "2018"; - sha256 = "1dxn0g50pv0ppal779vi7k40fr55pbhkyv4in7i13pgl4sn3wmr7"; + sha256 = "07c1vknddv3ak7w89n85ik0g34nzzpms6yb845vrjnv9m4csbpi8"; + libName = "fiat_crypto"; authors = [ "Fiat Crypto library authors <jgross@mit.edu>" ]; @@ -3656,9 +3810,9 @@ rec { }; "filetime" = rec { crateName = "filetime"; - version = "0.2.23"; + version = "0.2.25"; edition = "2018"; - sha256 = "1za0sbq7fqidk8aaq9v7m9ms0sv8mmi49g6p5cphpan819q4gr0y"; + sha256 = "11l5zr86n5sr6g6k6sqldswk0jzklm0q95rzikxcns0yk0p55h1m"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -3673,13 +3827,13 @@ rec { target = { target, features }: (target."unix" or false); } { - name = "redox_syscall"; - packageId = "redox_syscall 0.4.1"; + name = "libredox"; + packageId = "libredox"; target = { target, features }: ("redox" == target."os" or null); } { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; + packageId = "windows-sys 0.59.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Storage_FileSystem" ]; } @@ -3701,9 +3855,9 @@ rec { }; "flate2" = rec { crateName = "flate2"; - version = "1.0.28"; + version = "1.0.34"; edition = "2018"; - sha256 = "03llhsh4gqdirnfxxb9g2w9n0721dyn4yjir3pz7z4vjaxb3yc26"; + sha256 = "1w1nf2ap4q1sq1v6v951011wcvljk449ap7q7jnnjf8hvjs8kdd1"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Josh Triplett <josh@joshtriplett.org>" @@ -3734,6 +3888,7 @@ rec { "cloudflare_zlib" = [ "any_zlib" "cloudflare-zlib-sys" ]; "default" = [ "rust_backend" ]; "libz-ng-sys" = [ "dep:libz-ng-sys" ]; + "libz-rs-sys" = [ "dep:libz-rs-sys" ]; "libz-sys" = [ "dep:libz-sys" ]; "miniz-sys" = [ "rust_backend" ]; "miniz_oxide" = [ "dep:miniz_oxide" ]; @@ -3742,6 +3897,7 @@ rec { "zlib-default" = [ "any_zlib" "libz-sys/default" ]; "zlib-ng" = [ "any_zlib" "libz-ng-sys" ]; "zlib-ng-compat" = [ "zlib" "libz-sys/zlib-ng" ]; + "zlib-rs" = [ "any_zlib" "libz-rs-sys" ]; }; resolvedDefaultFeatures = [ "any_impl" "default" "miniz_oxide" "rust_backend" ]; }; @@ -3759,6 +3915,18 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; + "foldhash" = rec { + crateName = "foldhash"; + version = "0.1.3"; + edition = "2021"; + sha256 = "18in1a8mjcg43pfrdkhwzr0w988zb2bmb6sqwi07snjlkhvcc7pq"; + authors = [ + "Orson Peters <orsonpeters@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + }; + }; "form_urlencoded" = rec { crateName = "form_urlencoded"; version = "1.2.1"; @@ -3781,34 +3949,12 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; - "fs2" = rec { - crateName = "fs2"; - version = "0.4.3"; - edition = "2015"; - sha256 = "04v2hwk7035c088f19mfl5b1lz84gnvv2hv6m935n0hmirszqr4m"; - authors = [ - "Dan Burkert <dan@danburkert.com>" - ]; - dependencies = [ - { - name = "libc"; - packageId = "libc"; - target = { target, features }: (target."unix" or false); - } - { - name = "winapi"; - packageId = "winapi"; - target = { target, features }: (target."windows" or false); - features = [ "handleapi" "processthreadsapi" "winerror" "fileapi" "winbase" "std" ]; - } - ]; - - }; "fuse-backend-rs" = rec { crateName = "fuse-backend-rs"; - version = "0.11.0"; + version = "0.12.0"; edition = "2018"; - sha256 = "0jyldvp0kvjk21j5vqga42lkksaf7zg8jkj3l6h2dv20kyl66nif"; + sha256 = "06yimnygx8k1mx7wgbs6fg8id346zgnanxbzdhx28rg1ra038rp1"; + libName = "fuse_backend_rs"; authors = [ "Liu Bo <bo.liu@linux.alibaba.com>" "Liu Jiang <gerry@linux.alibaba.com>" @@ -3849,7 +3995,7 @@ rec { } { name = "mio"; - packageId = "mio"; + packageId = "mio 0.8.11"; features = [ "os-poll" "os-ext" ]; } { @@ -3857,6 +4003,10 @@ rec { packageId = "nix 0.24.3"; } { + name = "radix_trie"; + packageId = "radix_trie"; + } + { name = "vhost"; packageId = "vhost"; optional = true; @@ -3913,9 +4063,9 @@ rec { }; "futures" = rec { crateName = "futures"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1c04g14bccmprwsvx2j9m2blhwrynq7vhl151lsvcv4gi0b6jp34"; + sha256 = "0xh8ddbkm9jy8kc5gbvjp9a4b6rqqxvc8471yb2qaz5wm2qhgg35"; dependencies = [ { name = "futures-channel"; @@ -3974,9 +4124,10 @@ rec { }; "futures-channel" = rec { crateName = "futures-channel"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "0y6b7xxqdjm9hlcjpakcg41qfl7lihf6gavk8fyqijsxhvbzgj7a"; + sha256 = "040vpqpqlbk099razq8lyn74m0f161zd0rp36hciqrwcg2zibzrd"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -4001,9 +4152,10 @@ rec { }; "futures-core" = rec { crateName = "futures-core"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "07aslayrn3lbggj54kci0ishmd1pr367fp7iks7adia1p05miinz"; + sha256 = "0gk6yrxgi5ihfanm2y431jadrll00n5ifhnpx090c2f2q1cr1wh5"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -4013,9 +4165,10 @@ rec { }; "futures-executor" = rec { crateName = "futures-executor"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "07dh08gs9vfll2h36kq32q9xd86xm6lyl9xikmmwlkqnmrrgqxm5"; + sha256 = "17vcci6mdfzx4gbk0wx64chr2f13wwwpvyf3xd5fb1gmjzcx2a0y"; + libName = "futures_executor"; dependencies = [ { name = "futures-core"; @@ -4043,9 +4196,10 @@ rec { }; "futures-io" = rec { crateName = "futures-io"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1hgh25isvsr4ybibywhr4dpys8mjnscw4wfxxwca70cn1gi26im4"; + sha256 = "1ikmw1yfbgvsychmsihdkwa8a1knank2d9a8dk01mbjar9w1np4y"; + libName = "futures_io"; features = { "default" = [ "std" ]; }; @@ -4056,6 +4210,7 @@ rec { version = "2.3.0"; edition = "2021"; sha256 = "19gk4my8zhfym6gwnpdjiyv2hw8cc098skkbkhryjdaf0yspwljj"; + libName = "futures_lite"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" "Contributors to futures-rs" @@ -4100,10 +4255,11 @@ rec { }; "futures-macro" = rec { crateName = "futures-macro"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1b49qh9d402y8nka4q6wvvj0c88qq91wbr192mdn5h54nzs0qxc7"; + sha256 = "0l1n7kqzwwmgiznn0ywdc5i24z72zvh9q1dwps54mimppi7f6bhn"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -4115,7 +4271,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -4123,9 +4279,10 @@ rec { }; "futures-sink" = rec { crateName = "futures-sink"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1dag8xyyaya8n8mh8smx7x6w2dpmafg2din145v973a3hw7f1f4z"; + sha256 = "1xyly6naq6aqm52d5rh236snm08kw8zadydwqz8bip70s6vzlxg5"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -4134,9 +4291,10 @@ rec { }; "futures-task" = rec { crateName = "futures-task"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "013h1724454hj8qczp8vvs10qfiqrxr937qsrv6rhii68ahlzn1q"; + sha256 = "124rv4n90f5xwfsm9qw6y99755y021cmi5dhzh253s920z77s3zr"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -4145,9 +4303,10 @@ rec { }; "futures-timer" = rec { crateName = "futures-timer"; - version = "3.0.2"; + version = "3.0.3"; edition = "2018"; - sha256 = "0b5v7lk9838ix6jdcrainsyrh7xrf24pwm61dp13907qkn806jz6"; + sha256 = "094vw8k37djpbwv74bwf2qb7n6v6ghif4myss6smd6hgyajb127j"; + libName = "futures_timer"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -4159,9 +4318,10 @@ rec { }; "futures-util" = rec { crateName = "futures-util"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "0j0xqhcir1zf2dcbpd421kgw6wvsk0rpxflylcysn1rlp3g02r1x"; + sha256 = "10aa1ar8bgkgbr4wzxlidkqkcxf77gffyj8j7768h831pcaq784z"; + libName = "futures_util"; dependencies = [ { name = "futures-channel"; @@ -4242,28 +4402,11 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "async-await" "async-await-macro" "channel" "default" "futures-channel" "futures-io" "futures-macro" "futures-sink" "io" "memchr" "sink" "slab" "std" ]; }; - "fxhash" = rec { - crateName = "fxhash"; - version = "0.2.1"; - edition = "2015"; - sha256 = "037mb9ichariqi45xm6mz0b11pa92gj38ba0409z3iz239sns6y3"; - libPath = "lib.rs"; - authors = [ - "cbreeden <github@u.breeden.cc>" - ]; - dependencies = [ - { - name = "byteorder"; - packageId = "byteorder"; - } - ]; - - }; "gcp_auth" = rec { crateName = "gcp_auth"; - version = "0.10.0"; + version = "0.12.2"; edition = "2021"; - sha256 = "1m7lsh2gc7n9p0gs9k2qbxsrvchw1vz6dyz9a2ma322vd3m72b6y"; + sha256 = "0gb9bp9nkc810kfycm4vxndpccbhx68lcirq0y06lafykpkpjv2k"; dependencies = [ { name = "async-trait"; @@ -4271,7 +4414,11 @@ rec { } { name = "base64"; - packageId = "base64"; + packageId = "base64 0.22.1"; + } + { + name = "bytes"; + packageId = "bytes"; } { name = "chrono"; @@ -4283,27 +4430,37 @@ rec { packageId = "home"; } { + name = "http"; + packageId = "http"; + } + { + name = "http-body-util"; + packageId = "http-body-util"; + } + { name = "hyper"; - packageId = "hyper 0.14.28"; - features = [ "client" "runtime" "http2" ]; + packageId = "hyper"; + usesDefaultFeatures = false; + features = [ "client" "http1" "http2" ]; } { name = "hyper-rustls"; packageId = "hyper-rustls"; usesDefaultFeatures = false; - features = [ "tokio-runtime" "http1" "http2" ]; + features = [ "http1" "http2" ]; } { - name = "ring"; - packageId = "ring"; + name = "hyper-util"; + packageId = "hyper-util"; + features = [ "client-legacy" ]; } { - name = "rustls"; - packageId = "rustls 0.21.10"; + name = "ring"; + packageId = "ring"; } { name = "rustls-pemfile"; - packageId = "rustls-pemfile 1.0.4"; + packageId = "rustls-pemfile"; } { name = "serde"; @@ -4335,10 +4492,6 @@ rec { name = "url"; packageId = "url"; } - { - name = "which"; - packageId = "which 5.0.0"; - } ]; devDependencies = [ { @@ -4348,7 +4501,7 @@ rec { } ]; features = { - "default" = [ "hyper-rustls/rustls-native-certs" ]; + "default" = [ "hyper-rustls/rustls-native-certs" "hyper-rustls/ring" ]; "webpki-roots" = [ "hyper-rustls/webpki-roots" ]; }; resolvedDefaultFeatures = [ "default" ]; @@ -4381,11 +4534,49 @@ rec { version = "0.99.1"; edition = "2018"; sha256 = "1g6zmr88fk48f1ksz9ik1i2mwjsiam9s4p9aybhvs2zwzphxychb"; + libName = "genawaiter_macro"; authors = [ "Devin R <devin.ragotzy@gmail.com>" ]; features = { }; }; + "generator" = rec { + crateName = "generator"; + version = "0.8.3"; + edition = "2021"; + sha256 = "08vja5ngg548sn7cc8zdamq0axs2n8n19lmihfhz6k9ykillkffv"; + authors = [ + "Xudong Huang <huangxu008@hotmail.com>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "log"; + packageId = "log"; + } + { + name = "windows"; + packageId = "windows"; + target = { target, features }: (target."windows" or false); + features = [ "Win32_System_Memory" "Win32_System_Kernel" "Win32_Foundation" "Win32_System_SystemInformation" "Win32_System_Diagnostics_Debug" ]; + } + ]; + buildDependencies = [ + { + name = "rustversion"; + packageId = "rustversion"; + } + ]; + + }; "generic-array" = rec { crateName = "generic-array"; version = "0.14.7"; @@ -4416,9 +4607,9 @@ rec { }; "getrandom" = rec { crateName = "getrandom"; - version = "0.2.12"; + version = "0.2.15"; edition = "2018"; - sha256 = "1d8jb9bv38nkwlqqdjcav6gxckgwc9g30pm3qq506rvncpm9400r"; + sha256 = "1mzlnrb3dgyd1fb84gvw10pyr8wdqdl4ry4sr64i1s8an66pqmn4"; authors = [ "The Rand Project Developers" ]; @@ -4428,6 +4619,12 @@ rec { packageId = "cfg-if"; } { + name = "js-sys"; + packageId = "js-sys"; + optional = true; + target = { target, features }: ((("wasm32" == target."arch" or null) || ("wasm64" == target."arch" or null)) && ("unknown" == target."os" or null)); + } + { name = "libc"; packageId = "libc"; usesDefaultFeatures = false; @@ -4439,6 +4636,13 @@ rec { usesDefaultFeatures = false; target = { target, features }: ("wasi" == target."os" or null); } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: ((("wasm32" == target."arch" or null) || ("wasm64" == target."arch" or null)) && ("unknown" == target."os" or null)); + } ]; features = { "compiler_builtins" = [ "dep:compiler_builtins" ]; @@ -4448,13 +4652,44 @@ rec { "rustc-dep-of-std" = [ "compiler_builtins" "core" "libc/rustc-dep-of-std" "wasi/rustc-dep-of-std" ]; "wasm-bindgen" = [ "dep:wasm-bindgen" ]; }; - resolvedDefaultFeatures = [ "std" ]; + resolvedDefaultFeatures = [ "js" "js-sys" "std" "wasm-bindgen" ]; + }; + "getset" = rec { + crateName = "getset"; + version = "0.1.3"; + edition = "2018"; + sha256 = "0g2ixn6zhrpba58hcv4kiygpc6nydixw4byr5v9sh81ifidn0dpn"; + procMacro = true; + authors = [ + "Ana Hobden <ana@hoverbear.org>" + "John Baublitz <john.m.baublitz@gmail.com" + ]; + dependencies = [ + { + name = "proc-macro-error2"; + packageId = "proc-macro-error2"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + } + ]; + }; "gimli" = rec { crateName = "gimli"; - version = "0.28.1"; + version = "0.31.1"; edition = "2018"; - sha256 = "0lv23wc8rxvmjia3mcxc6hj9vkqnv1bqq0h8nzjcgf71mrxx6wa2"; + sha256 = "0gvqc0ramx8szv76jhfd4dms0zyamvlg4whhiz11j34hh3dqxqh7"; features = { "default" = [ "read-all" "write" ]; "endian-reader" = [ "read" "dep:stable_deref_trait" ]; @@ -4477,17 +4712,21 @@ rec { ]; }; - "h2 0.3.24" = rec { + "h2" = rec { crateName = "h2"; - version = "0.3.24"; - edition = "2018"; - sha256 = "1jf9488b66nayxzp3iw3b2rb64y49hdbbywnv9wfwrsv14i48b5v"; + version = "0.4.6"; + edition = "2021"; + sha256 = "01cjblya9zxyadvxcmgcv2bk9r9pyc8l8bbchjdg88clk738lkjj"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" ]; dependencies = [ { + name = "atomic-waker"; + packageId = "atomic-waker"; + } + { name = "bytes"; packageId = "bytes"; } @@ -4506,17 +4745,12 @@ rec { usesDefaultFeatures = false; } { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - } - { name = "http"; - packageId = "http 0.2.11"; + packageId = "http"; } { name = "indexmap"; - packageId = "indexmap 2.1.0"; + packageId = "indexmap 2.6.0"; features = [ "std" ]; } { @@ -4549,91 +4783,38 @@ rec { ]; features = { }; }; - "h2 0.4.3" = rec { - crateName = "h2"; - version = "0.4.3"; + "half" = rec { + crateName = "half"; + version = "2.4.1"; edition = "2021"; - sha256 = "1m4rj76zl77jany6p10k4mm1cqwsrlc1dmgmxwp3jy7kwk92vvji"; + sha256 = "123q4zzw1x4309961i69igzd1wb7pj04aaii3kwasrz3599qrl3d"; authors = [ - "Carl Lerche <me@carllerche.com>" - "Sean McArthur <sean@seanmonstar.com>" + "Kathryn Long <squeeself@gmail.com>" ]; dependencies = [ { - name = "bytes"; - packageId = "bytes"; - } - { - name = "fnv"; - packageId = "fnv"; - } - { - name = "futures-core"; - packageId = "futures-core"; - usesDefaultFeatures = false; - } - { - name = "futures-sink"; - packageId = "futures-sink"; - usesDefaultFeatures = false; - } - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - } - { - name = "http"; - packageId = "http 1.1.0"; - } - { - name = "indexmap"; - packageId = "indexmap 2.1.0"; - features = [ "std" ]; - } - { - name = "slab"; - packageId = "slab"; - } - { - name = "tokio"; - packageId = "tokio"; - features = [ "io-util" ]; + name = "cfg-if"; + packageId = "cfg-if"; } { - name = "tokio-util"; - packageId = "tokio-util"; - features = [ "codec" "io" ]; - } - { - name = "tracing"; - packageId = "tracing"; - usesDefaultFeatures = false; - features = [ "std" ]; + name = "crunchy"; + packageId = "crunchy"; + target = { target, features }: ("spirv" == target."arch" or null); } ]; devDependencies = [ { - name = "tokio"; - packageId = "tokio"; - features = [ "rt-multi-thread" "macros" "sync" "net" ]; + name = "crunchy"; + packageId = "crunchy"; } ]; - features = { }; - }; - "half" = rec { - crateName = "half"; - version = "1.8.2"; - edition = "2018"; - sha256 = "1mqbmx2m9qd4lslkb42fzgldsklhv9c4bxsc8j82r80d8m24mfza"; - authors = [ - "Kathryn Long <squeeself@gmail.com>" - ]; features = { "bytemuck" = [ "dep:bytemuck" ]; + "default" = [ "std" ]; "num-traits" = [ "dep:num-traits" ]; + "rand_distr" = [ "dep:rand" "dep:rand_distr" ]; + "rkyv" = [ "dep:rkyv" ]; "serde" = [ "dep:serde" ]; - "serialize" = [ "serde" ]; "std" = [ "alloc" ]; "zerocopy" = [ "dep:zerocopy" ]; }; @@ -4660,11 +4841,11 @@ rec { }; resolvedDefaultFeatures = [ "raw" ]; }; - "hashbrown 0.14.3" = rec { + "hashbrown 0.14.5" = rec { crateName = "hashbrown"; - version = "0.14.3"; + version = "0.14.5"; edition = "2021"; - sha256 = "012nywlg0lj9kwanh69my5x67vjlfmzfi9a0rq4qvis2j8fil3r9"; + sha256 = "1wa1vy1xs3mp11bn3z9dv0jricgr6a2j0zkf1g19yz3vw4il89z5"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -4682,9 +4863,111 @@ rec { "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" ]; "serde" = [ "dep:serde" ]; }; - resolvedDefaultFeatures = [ "inline-more" "raw" ]; + resolvedDefaultFeatures = [ "inline-more" ]; + }; + "hashbrown 0.15.0" = rec { + crateName = "hashbrown"; + version = "0.15.0"; + edition = "2021"; + sha256 = "1yx4xq091s7i6mw6bn77k8cp4jrpcac149xr32rg8szqsj27y20y"; + authors = [ + "Amanieu d'Antras <amanieu@gmail.com>" + ]; + dependencies = [ + { + name = "allocator-api2"; + packageId = "allocator-api2"; + optional = true; + usesDefaultFeatures = false; + features = [ "alloc" ]; + } + { + name = "equivalent"; + packageId = "equivalent"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "foldhash"; + packageId = "foldhash"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "dep:alloc" ]; + "allocator-api2" = [ "dep:allocator-api2" ]; + "borsh" = [ "dep:borsh" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "default-hasher" "inline-more" "allocator-api2" "equivalent" "raw-entry" ]; + "default-hasher" = [ "dep:foldhash" ]; + "equivalent" = [ "dep:equivalent" ]; + "nightly" = [ "allocator-api2?/nightly" "bumpalo/allocator_api" ]; + "rayon" = [ "dep:rayon" ]; + "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" "raw-entry" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "allocator-api2" "default" "default-hasher" "equivalent" "inline-more" "raw-entry" ]; + }; + "headers" = rec { + crateName = "headers"; + version = "0.4.0"; + edition = "2015"; + sha256 = "1abari69kjl2yv2dg06g2x17qgd1a20xp7aqmmg2vfhcppk0c89j"; + authors = [ + "Sean McArthur <sean@seanmonstar.com>" + ]; + dependencies = [ + { + name = "base64"; + packageId = "base64 0.21.7"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "headers-core"; + packageId = "headers-core"; + } + { + name = "http"; + packageId = "http"; + } + { + name = "httpdate"; + packageId = "httpdate"; + } + { + name = "mime"; + packageId = "mime"; + } + { + name = "sha1"; + packageId = "sha1"; + } + ]; + features = { }; + }; + "headers-core" = rec { + crateName = "headers-core"; + version = "0.3.0"; + edition = "2015"; + sha256 = "1r1w80i2bhmyh8s5mjr2dz6baqlrm6cak6yvzm4jq96lacjs5d2l"; + libName = "headers_core"; + authors = [ + "Sean McArthur <sean@seanmonstar.com>" + ]; + dependencies = [ + { + name = "http"; + packageId = "http"; + } + ]; + }; - "heck" = rec { + "heck 0.4.1" = rec { crateName = "heck"; version = "0.4.1"; edition = "2018"; @@ -4698,11 +4981,36 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "hermit-abi" = rec { + "heck 0.5.0" = rec { + crateName = "heck"; + version = "0.5.0"; + edition = "2021"; + sha256 = "1sjmpsdl8czyh9ywl3qcsfsq9a307dg4ni2vnlwgnzzqhc4y0113"; + + }; + "hermit-abi 0.3.9" = rec { crateName = "hermit-abi"; - version = "0.3.4"; + version = "0.3.9"; edition = "2021"; - sha256 = "07v5vbwb9kx0yxgdpx15h38ynpzhaqx5ncriryipypi5707hwgax"; + sha256 = "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj"; + libName = "hermit_abi"; + authors = [ + "Stefan Lankes" + ]; + features = { + "alloc" = [ "dep:alloc" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins/rustc-dep-of-std" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "hermit-abi 0.4.0" = rec { + crateName = "hermit-abi"; + version = "0.4.0"; + edition = "2021"; + sha256 = "1k1zwllx6nfq417hy38x4akw1ivlv68ymvnzyxs76ffgsqcskxpv"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -4734,6 +5042,7 @@ rec { version = "0.4.1"; edition = "2021"; sha256 = "0iny5inkixsdr41pm2vkqh3fl66752z5j5c0cdxw16yl9ryjdqkg"; + libName = "hex_literal"; authors = [ "RustCrypto Developers" ]; @@ -4757,33 +5066,7 @@ rec { ]; }; - "http 0.2.11" = rec { - crateName = "http"; - version = "0.2.11"; - edition = "2018"; - sha256 = "1fwz3mhh86h5kfnr5767jlx9agpdggclq7xsqx930fflzakb2iw9"; - authors = [ - "Alex Crichton <alex@alexcrichton.com>" - "Carl Lerche <me@carllerche.com>" - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "fnv"; - packageId = "fnv"; - } - { - name = "itoa"; - packageId = "itoa"; - } - ]; - - }; - "http 1.1.0" = rec { + "http" = rec { crateName = "http"; version = "1.1.0"; edition = "2018"; @@ -4812,37 +5095,12 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "http-body 0.4.6" = rec { + "http-body" = rec { crateName = "http-body"; - version = "0.4.6"; - edition = "2018"; - sha256 = "1lmyjfk6bqk6k9gkn1dxq770sb78pqbqshga241hr5p995bb5skw"; - authors = [ - "Carl Lerche <me@carllerche.com>" - "Lucio Franco <luciofranco14@gmail.com>" - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "http"; - packageId = "http 0.2.11"; - } - { - name = "pin-project-lite"; - packageId = "pin-project-lite"; - } - ]; - - }; - "http-body 1.0.0" = rec { - crateName = "http-body"; - version = "1.0.0"; + version = "1.0.1"; edition = "2018"; - sha256 = "0hyn8n3iadrbwq8y0p1rl1275s4nm49bllw5wji29g4aa3dqbb0w"; + sha256 = "111ir5k2b9ihz5nr9cz7cwm7fnydca7dx4hc7vr16scfzghxrzhy"; + libName = "http_body"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -4855,16 +5113,17 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } ]; }; "http-body-util" = rec { crateName = "http-body-util"; - version = "0.1.1"; + version = "0.1.2"; edition = "2018"; - sha256 = "07agldas2qgcfc05ckiarlmf9vzragbda823nqhrqrc6mjrghx84"; + sha256 = "0kslwazg4400qnc2azkrgqqci0fppv12waicnsy5d8hncvbjjd3r"; + libName = "http_body_util"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -4876,16 +5135,17 @@ rec { packageId = "bytes"; } { - name = "futures-core"; - packageId = "futures-core"; + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "pin-project-lite"; @@ -4896,9 +5156,9 @@ rec { }; "httparse" = rec { crateName = "httparse"; - version = "1.8.0"; + version = "1.9.5"; edition = "2018"; - sha256 = "010rrfahm1jss3p022fqf3j3jmm72vhn4iqhykahb9ynpaag75yq"; + sha256 = "0ip9v8m9lvgvq1lznl31wvn0ch1v254na7lhid9p29yx9rbx6wbx"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -4927,118 +5187,11 @@ rec { ]; }; - "hyper 0.14.28" = rec { + "hyper" = rec { crateName = "hyper"; - version = "0.14.28"; - edition = "2018"; - sha256 = "107gkvqx4h9bl17d602zkm2dgpfq86l2dr36yzfsi8l3xcsy35mz"; - authors = [ - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "futures-channel"; - packageId = "futures-channel"; - } - { - name = "futures-core"; - packageId = "futures-core"; - usesDefaultFeatures = false; - } - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - } - { - name = "h2"; - packageId = "h2 0.3.24"; - optional = true; - } - { - name = "http"; - packageId = "http 0.2.11"; - } - { - name = "http-body"; - packageId = "http-body 0.4.6"; - } - { - name = "httparse"; - packageId = "httparse"; - } - { - name = "httpdate"; - packageId = "httpdate"; - } - { - name = "itoa"; - packageId = "itoa"; - } - { - name = "pin-project-lite"; - packageId = "pin-project-lite"; - } - { - name = "socket2"; - packageId = "socket2"; - optional = true; - features = [ "all" ]; - } - { - name = "tokio"; - packageId = "tokio"; - features = [ "sync" ]; - } - { - name = "tower-service"; - packageId = "tower-service"; - } - { - name = "tracing"; - packageId = "tracing"; - usesDefaultFeatures = false; - features = [ "std" ]; - } - { - name = "want"; - packageId = "want"; - } - ]; - devDependencies = [ - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - features = [ "alloc" ]; - } - { - name = "tokio"; - packageId = "tokio"; - features = [ "fs" "macros" "io-std" "io-util" "rt" "rt-multi-thread" "sync" "time" "test-util" ]; - } - ]; - features = { - "ffi" = [ "libc" ]; - "full" = [ "client" "http1" "http2" "server" "stream" "runtime" ]; - "h2" = [ "dep:h2" ]; - "http2" = [ "h2" ]; - "libc" = [ "dep:libc" ]; - "runtime" = [ "tcp" "tokio/rt" "tokio/time" ]; - "socket2" = [ "dep:socket2" ]; - "tcp" = [ "socket2" "tokio/net" "tokio/rt" "tokio/time" ]; - }; - resolvedDefaultFeatures = [ "client" "default" "full" "h2" "http1" "http2" "runtime" "server" "socket2" "stream" "tcp" ]; - }; - "hyper 1.2.0" = rec { - crateName = "hyper"; - version = "1.2.0"; + version = "1.4.1"; edition = "2021"; - sha256 = "0fi6k7hz5fmdph0a5r8hw50d7h2n9zxkizmafcmb65f67bblhr8q"; + sha256 = "01ds8i3q6hw5kw56mavy544m11gkr87zi999siigdl3n1qpd5psh"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -5060,16 +5213,16 @@ rec { } { name = "h2"; - packageId = "h2 0.4.3"; + packageId = "h2"; optional = true; } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "httparse"; @@ -5102,6 +5255,11 @@ rec { packageId = "tokio"; features = [ "sync" ]; } + { + name = "want"; + packageId = "want"; + optional = true; + } ]; devDependencies = [ { @@ -5113,7 +5271,7 @@ rec { name = "futures-util"; packageId = "futures-util"; usesDefaultFeatures = false; - features = [ "sink" ]; + features = [ "alloc" "sink" ]; } { name = "tokio"; @@ -5123,20 +5281,21 @@ rec { ]; features = { "client" = [ "dep:want" "dep:pin-project-lite" "dep:smallvec" ]; - "ffi" = [ "dep:libc" "dep:http-body-util" ]; + "ffi" = [ "dep:libc" "dep:http-body-util" "futures-util?/alloc" ]; "full" = [ "client" "http1" "http2" "server" ]; "http1" = [ "dep:futures-channel" "dep:futures-util" "dep:httparse" "dep:itoa" ]; "http2" = [ "dep:futures-channel" "dep:futures-util" "dep:h2" ]; "server" = [ "dep:httpdate" "dep:pin-project-lite" "dep:smallvec" ]; "tracing" = [ "dep:tracing" ]; }; - resolvedDefaultFeatures = [ "default" "http1" "http2" "server" ]; + resolvedDefaultFeatures = [ "client" "default" "http1" "http2" "server" ]; }; "hyper-rustls" = rec { crateName = "hyper-rustls"; - version = "0.24.2"; + version = "0.27.3"; edition = "2021"; - sha256 = "1475j4a2nczz4aajzzsq3hpwg1zacmzbqg393a14j80ff8izsgpc"; + sha256 = "0cxkph8hsmbz693a8ih2ciy7h0xbac844rpm981y6c0iqfsxpbq8"; + libName = "hyper_rustls"; dependencies = [ { name = "futures-util"; @@ -5145,43 +5304,58 @@ rec { } { name = "http"; - packageId = "http 0.2.11"; + packageId = "http"; } { name = "hyper"; - packageId = "hyper 0.14.28"; + packageId = "hyper"; usesDefaultFeatures = false; - features = [ "client" ]; + } + { + name = "hyper-util"; + packageId = "hyper-util"; + usesDefaultFeatures = false; + features = [ "client-legacy" "tokio" ]; } { name = "rustls"; - packageId = "rustls 0.21.10"; + packageId = "rustls"; usesDefaultFeatures = false; } { name = "rustls-native-certs"; - packageId = "rustls-native-certs 0.6.3"; + packageId = "rustls-native-certs"; optional = true; } { + name = "rustls-pki-types"; + packageId = "rustls-pki-types"; + rename = "pki-types"; + } + { name = "tokio"; packageId = "tokio"; } { name = "tokio-rustls"; - packageId = "tokio-rustls 0.24.1"; + packageId = "tokio-rustls"; usesDefaultFeatures = false; } + { + name = "tower-service"; + packageId = "tower-service"; + } ]; devDependencies = [ { - name = "hyper"; - packageId = "hyper 0.14.28"; - features = [ "full" ]; + name = "hyper-util"; + packageId = "hyper-util"; + usesDefaultFeatures = false; + features = [ "server-auto" ]; } { name = "rustls"; - packageId = "rustls 0.21.10"; + packageId = "rustls"; usesDefaultFeatures = false; features = [ "tls12" ]; } @@ -5192,34 +5366,41 @@ rec { } ]; features = { - "acceptor" = [ "hyper/server" "tokio-runtime" ]; - "default" = [ "native-tokio" "http1" "tls12" "logging" "acceptor" ]; - "http1" = [ "hyper/http1" ]; - "http2" = [ "hyper/http2" ]; + "aws-lc-rs" = [ "rustls/aws_lc_rs" ]; + "default" = [ "native-tokio" "http1" "tls12" "logging" "aws-lc-rs" ]; + "fips" = [ "aws-lc-rs" "rustls/fips" ]; + "http1" = [ "hyper-util/http1" ]; + "http2" = [ "hyper-util/http2" ]; "log" = [ "dep:log" ]; "logging" = [ "log" "tokio-rustls/logging" "rustls/logging" ]; - "native-tokio" = [ "tokio-runtime" "rustls-native-certs" ]; + "native-tokio" = [ "rustls-native-certs" ]; + "ring" = [ "rustls/ring" ]; "rustls-native-certs" = [ "dep:rustls-native-certs" ]; + "rustls-platform-verifier" = [ "dep:rustls-platform-verifier" ]; "tls12" = [ "tokio-rustls/tls12" "rustls/tls12" ]; - "tokio-runtime" = [ "hyper/runtime" ]; "webpki-roots" = [ "dep:webpki-roots" ]; - "webpki-tokio" = [ "tokio-runtime" "webpki-roots" ]; + "webpki-tokio" = [ "webpki-roots" ]; }; - resolvedDefaultFeatures = [ "http1" "http2" "rustls-native-certs" "tokio-runtime" ]; + resolvedDefaultFeatures = [ "http1" "http2" "native-tokio" "ring" "rustls-native-certs" "tls12" ]; }; "hyper-timeout" = rec { crateName = "hyper-timeout"; - version = "0.4.1"; + version = "0.5.1"; edition = "2018"; - sha256 = "1c8k3g8k2yh1gxvsx9p7amkimgxhl9kafwpj7jyf8ywc5r45ifdv"; + sha256 = "14rpyv9zz0ncadn9qgmnjz0hiqk3nav7hglkk1a6yfy8wmhsj0rj"; + libName = "hyper_timeout"; authors = [ "Herman J. Radtke III <herman@hermanradtke.com>" ]; dependencies = [ { name = "hyper"; - packageId = "hyper 0.14.28"; - features = [ "client" ]; + packageId = "hyper"; + } + { + name = "hyper-util"; + packageId = "hyper-util"; + features = [ "client-legacy" "http1" ]; } { name = "pin-project-lite"; @@ -5230,15 +5411,15 @@ rec { packageId = "tokio"; } { - name = "tokio-io-timeout"; - packageId = "tokio-io-timeout"; + name = "tower-service"; + packageId = "tower-service"; } ]; devDependencies = [ { name = "hyper"; - packageId = "hyper 0.14.28"; - features = [ "client" "http1" "tcp" ]; + packageId = "hyper"; + features = [ "http1" ]; } { name = "tokio"; @@ -5250,9 +5431,10 @@ rec { }; "hyper-util" = rec { crateName = "hyper-util"; - version = "0.1.3"; + version = "0.1.9"; edition = "2021"; - sha256 = "1akngan7j0n2n0wd25c6952mvqbkj9gp1lcwzyxjc0d37l8yyf6a"; + sha256 = "12yhradh0bpwa9jjyyq6shrrcx9fxbdkrq06xj7ccfhqkyq6waa1"; + libName = "hyper_util"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -5262,21 +5444,26 @@ rec { packageId = "bytes"; } { + name = "futures-channel"; + packageId = "futures-channel"; + optional = true; + } + { name = "futures-util"; packageId = "futures-util"; usesDefaultFeatures = false; } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "hyper"; - packageId = "hyper 1.2.0"; + packageId = "hyper"; } { name = "pin-project-lite"; @@ -5292,7 +5479,19 @@ rec { name = "tokio"; packageId = "tokio"; optional = true; - features = [ "net" "rt" "time" ]; + usesDefaultFeatures = false; + } + { + name = "tower-service"; + packageId = "tower-service"; + optional = true; + } + { + name = "tracing"; + packageId = "tracing"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" ]; } ]; devDependencies = [ @@ -5302,33 +5501,35 @@ rec { } { name = "hyper"; - packageId = "hyper 1.2.0"; + packageId = "hyper"; features = [ "full" ]; } { name = "tokio"; packageId = "tokio"; - features = [ "macros" "test-util" ]; + features = [ "macros" "test-util" "signal" ]; } ]; features = { - "client" = [ "hyper/client" "dep:tracing" "dep:futures-channel" "dep:tower" "dep:tower-service" ]; - "client-legacy" = [ "client" ]; - "full" = [ "client" "client-legacy" "server" "server-auto" "service" "http1" "http2" "tokio" ]; + "client" = [ "hyper/client" "dep:tracing" "dep:futures-channel" "dep:tower-service" ]; + "client-legacy" = [ "client" "dep:socket2" "tokio/sync" ]; + "full" = [ "client" "client-legacy" "server" "server-auto" "server-graceful" "service" "http1" "http2" "tokio" ]; "http1" = [ "hyper/http1" ]; "http2" = [ "hyper/http2" ]; "server" = [ "hyper/server" ]; "server-auto" = [ "server" "http1" "http2" ]; - "service" = [ "dep:tower" "dep:tower-service" ]; - "tokio" = [ "dep:tokio" "dep:socket2" ]; + "server-graceful" = [ "server" "tokio/sync" "futures-util/alloc" ]; + "service" = [ "dep:tower-service" ]; + "tokio" = [ "dep:tokio" "tokio/net" "tokio/rt" "tokio/time" ]; }; - resolvedDefaultFeatures = [ "default" "http1" "http2" "server" "server-auto" "tokio" ]; + resolvedDefaultFeatures = [ "client" "client-legacy" "default" "http1" "http2" "server" "server-auto" "service" "tokio" ]; }; "iana-time-zone" = rec { crateName = "iana-time-zone"; - version = "0.1.60"; + version = "0.1.61"; edition = "2018"; - sha256 = "0hdid5xz3jznm04lysjm3vi93h3c523w0hcc3xba47jl3ddbpzz7"; + sha256 = "085jjsls330yj1fnwykfzmb2f10zp6l7w4fhq81ng81574ghhpi3"; + libName = "iana_time_zone"; authors = [ "Andrew Straw <strawman@astraw.com>" "René Kijewski <rene.kijewski@fu-berlin.de>" @@ -5353,16 +5554,16 @@ rec { { name = "js-sys"; packageId = "js-sys"; - target = { target, features }: ("wasm32" == target."arch" or null); + target = { target, features }: (("wasm32" == target."arch" or null) && ("unknown" == target."os" or null)); } { name = "wasm-bindgen"; packageId = "wasm-bindgen"; - target = { target, features }: ("wasm32" == target."arch" or null); + target = { target, features }: (("wasm32" == target."arch" or null) && ("unknown" == target."os" or null)); } { name = "windows-core"; - packageId = "windows-core"; + packageId = "windows-core 0.52.0"; target = { target, features }: ("windows" == target."os" or null); } ]; @@ -5374,6 +5575,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k"; + libName = "iana_time_zone_haiku"; authors = [ "René Kijewski <crates.io@k6i.de>" ]; @@ -5422,94 +5624,6 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; - "imbl" = rec { - crateName = "imbl"; - version = "2.0.3"; - edition = "2018"; - sha256 = "11bhchs0d1bbbmr8ari4y4d62vqxs7xg4fkhjlhgbv98h0n193cp"; - authors = [ - "Bodil Stokke <bodil@bodil.org>" - "Joe Neeman <joeneeman@gmail.com>" - ]; - dependencies = [ - { - name = "bitmaps"; - packageId = "bitmaps"; - } - { - name = "imbl-sized-chunks"; - packageId = "imbl-sized-chunks"; - } - { - name = "proptest"; - packageId = "proptest"; - optional = true; - } - { - name = "rand_core"; - packageId = "rand_core"; - } - { - name = "rand_xoshiro"; - packageId = "rand_xoshiro"; - } - { - name = "serde"; - packageId = "serde"; - optional = true; - } - ]; - buildDependencies = [ - { - name = "version_check"; - packageId = "version_check"; - } - ]; - devDependencies = [ - { - name = "proptest"; - packageId = "proptest"; - } - { - name = "serde"; - packageId = "serde"; - } - ]; - features = { - "arbitrary" = [ "dep:arbitrary" ]; - "proptest" = [ "dep:proptest" ]; - "quickcheck" = [ "dep:quickcheck" ]; - "rayon" = [ "dep:rayon" ]; - "refpool" = [ "dep:refpool" ]; - "serde" = [ "dep:serde" ]; - }; - resolvedDefaultFeatures = [ "proptest" "serde" ]; - }; - "imbl-sized-chunks" = rec { - crateName = "imbl-sized-chunks"; - version = "0.1.2"; - edition = "2021"; - sha256 = "0qzdw55na2w6fd44p7y9rh05nxa98gzpaigmwg57sy7db3xhch0l"; - authors = [ - "Bodil Stokke <bodil@bodil.org>" - "Joe Neeman <joeneeman@gmail.com>" - ]; - dependencies = [ - { - name = "bitmaps"; - packageId = "bitmaps"; - usesDefaultFeatures = false; - } - ]; - features = { - "arbitrary" = [ "dep:arbitrary" ]; - "array-ops" = [ "dep:array-ops" ]; - "default" = [ "std" ]; - "refpool" = [ "dep:refpool" ]; - "ringbuffer" = [ "array-ops" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "indexmap 1.9.3" = rec { crateName = "indexmap"; version = "1.9.3"; @@ -5545,11 +5659,11 @@ rec { }; resolvedDefaultFeatures = [ "serde" "serde-1" "std" ]; }; - "indexmap 2.1.0" = rec { + "indexmap 2.6.0" = rec { crateName = "indexmap"; - version = "2.1.0"; + version = "2.6.0"; edition = "2021"; - sha256 = "07rxrqmryr1xfnmhrjlz8ic6jw28v6h5cig3ws2c9d0wifhy2c6m"; + sha256 = "1nmrwn8lbs19gkvhxaawffzbvrpyrb5y3drcrr645x957kz0fybh"; dependencies = [ { name = "equivalent"; @@ -5558,9 +5672,8 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown 0.14.3"; + packageId = "hashbrown 0.15.0"; usesDefaultFeatures = false; - features = [ "raw" ]; } { name = "serde"; @@ -5571,6 +5684,7 @@ rec { ]; features = { "arbitrary" = [ "dep:arbitrary" ]; + "borsh" = [ "dep:borsh" ]; "default" = [ "std" ]; "quickcheck" = [ "dep:quickcheck" ]; "rayon" = [ "dep:rayon" ]; @@ -5579,11 +5693,60 @@ rec { }; resolvedDefaultFeatures = [ "default" "serde" "std" ]; }; + "indicatif" = rec { + crateName = "indicatif"; + version = "0.17.8"; + edition = "2021"; + sha256 = "18xyqxw9i5x4sbpzckhfz3nm984iq9r7nbi2lk76nz888n7mlfkn"; + dependencies = [ + { + name = "console"; + packageId = "console"; + usesDefaultFeatures = false; + features = [ "ansi-parsing" ]; + } + { + name = "instant"; + packageId = "instant"; + target = { target, features }: ("wasm32" == target."arch" or null); + } + { + name = "number_prefix"; + packageId = "number_prefix"; + } + { + name = "portable-atomic"; + packageId = "portable-atomic"; + } + { + name = "unicode-width"; + packageId = "unicode-width"; + optional = true; + } + { + name = "vt100"; + packageId = "vt100"; + optional = true; + } + ]; + features = { + "default" = [ "unicode-width" "console/unicode-width" ]; + "futures" = [ "dep:futures-core" ]; + "improved_unicode" = [ "unicode-segmentation" "unicode-width" "console/unicode-width" ]; + "in_memory" = [ "vt100" ]; + "rayon" = [ "dep:rayon" ]; + "tokio" = [ "dep:tokio" ]; + "unicode-segmentation" = [ "dep:unicode-segmentation" ]; + "unicode-width" = [ "dep:unicode-width" ]; + "vt100" = [ "dep:vt100" ]; + }; + resolvedDefaultFeatures = [ "default" "in_memory" "unicode-width" "vt100" ]; + }; "instant" = rec { crateName = "instant"; - version = "0.1.12"; + version = "0.1.13"; edition = "2018"; - sha256 = "0b2bx5qdlwayriidhrag8vhy10kdfimfhmb3jnjmsz2h9j1bwnvs"; + sha256 = "08h27kzvb5jw74mh0ajv0nv9ggwvgqm8ynjsn2sa9jsks4cjh970"; authors = [ "sebcrozet <developer@crozet.re>" ]; @@ -5613,9 +5776,9 @@ rec { }; "ipnet" = rec { crateName = "ipnet"; - version = "2.9.0"; + version = "2.10.1"; edition = "2018"; - sha256 = "1hzrcysgwf0knf83ahb3535hrkw63mil88iqc6kjaryfblrqylcg"; + sha256 = "025p9wm94q1w2l13hbbr4cbmfygly3a2ag8g5s618l2jhq4l3hnx"; authors = [ "Kris Price <kris@krisprice.nz>" ]; @@ -5631,9 +5794,10 @@ rec { }; "is-terminal" = rec { crateName = "is-terminal"; - version = "0.4.10"; + version = "0.4.13"; edition = "2018"; - sha256 = "0m9la3f7cs77y85nkbcjsxkb7k861fc6bdhahyfidgh7gljh1b8b"; + sha256 = "0jwgjjz33kkmnwai3nsdk1pz9vb6gkqvw1d1vq7bs3q48kinh7r6"; + libName = "is_terminal"; authors = [ "softprops <d.tangren@gmail.com>" "Dan Gohman <dev@sunfishcode.online>" @@ -5641,14 +5805,13 @@ rec { dependencies = [ { name = "hermit-abi"; - packageId = "hermit-abi"; + packageId = "hermit-abi 0.4.0"; target = { target, features }: ("hermit" == target."os" or null); } { - name = "rustix"; - packageId = "rustix"; - target = { target, features }: (!((target."windows" or false) || ("hermit" == target."os" or null) || ("unknown" == target."os" or null))); - features = [ "termios" ]; + name = "libc"; + packageId = "libc"; + target = { target, features }: ((target."unix" or false) || ("wasi" == target."os" or null)); } { name = "windows-sys"; @@ -5659,14 +5822,21 @@ rec { ]; devDependencies = [ { - name = "rustix"; - packageId = "rustix"; - target = { target, features }: (!((target."windows" or false) || ("hermit" == target."os" or null) || ("unknown" == target."os" or null))); - features = [ "stdio" ]; + name = "libc"; + packageId = "libc"; + target = { target, features }: ((target."unix" or false) || ("wasi" == target."os" or null)); } ]; }; + "is_terminal_polyfill" = rec { + crateName = "is_terminal_polyfill"; + version = "1.70.1"; + edition = "2021"; + sha256 = "1kwfgglh91z33kl0w5i338mfpa3zs0hidq5j4ny4rmjwrikchhvr"; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; "itertools 0.10.5" = rec { crateName = "itertools"; version = "0.10.5"; @@ -5688,11 +5858,11 @@ rec { }; resolvedDefaultFeatures = [ "default" "use_alloc" "use_std" ]; }; - "itertools 0.11.0" = rec { + "itertools 0.12.1" = rec { crateName = "itertools"; - version = "0.11.0"; + version = "0.12.1"; edition = "2018"; - sha256 = "0mzyqcc59azx9g5cg6fs8k529gvh4463smmka6jvzs3cd2jp7hdi"; + sha256 = "0s95jbb3ndj1lvfxyq5wanc0fm0r6hg6q4ngb92qlfdxvci10ads"; authors = [ "bluss" ]; @@ -5707,13 +5877,13 @@ rec { "default" = [ "use_std" ]; "use_std" = [ "use_alloc" "either/use_std" ]; }; - resolvedDefaultFeatures = [ "use_alloc" ]; + resolvedDefaultFeatures = [ "default" "use_alloc" "use_std" ]; }; - "itertools 0.12.0" = rec { + "itertools 0.13.0" = rec { crateName = "itertools"; - version = "0.12.0"; + version = "0.13.0"; edition = "2018"; - sha256 = "1c07gzdlc6a1c8p8jrvvw3gs52bss3y58cs2s21d9i978l36pnr5"; + sha256 = "11hiy3qzl643zcigknclh446qb9zlg4dpdzfkjaa9q9fqpgyfgj1"; authors = [ "bluss" ]; @@ -5732,9 +5902,9 @@ rec { }; "itoa" = rec { crateName = "itoa"; - version = "1.0.10"; + version = "1.0.11"; edition = "2018"; - sha256 = "0k7xjfki7mnv6yzjrbnbnjllg86acmbnk4izz2jmm1hx2wd6v95i"; + sha256 = "0nv9cqjwzr3q58qz84dcz63ggc54yhf1yqar1m858m1kfd4g3wa9"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5744,9 +5914,9 @@ rec { }; "jobserver" = rec { crateName = "jobserver"; - version = "0.1.27"; - edition = "2018"; - sha256 = "0z9w6vfqwbr6hfk9yaw7kydlh6f7k39xdlszxlh39in4acwzcdwc"; + version = "0.1.32"; + edition = "2021"; + sha256 = "1l2k50qmj84x9mn39ivjz76alqmx72jhm12rw33zx9xnpv5xpla8"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -5761,9 +5931,10 @@ rec { }; "js-sys" = rec { crateName = "js-sys"; - version = "0.3.67"; - edition = "2018"; - sha256 = "1lar78p13w781b4zf44a0sk26i461fczbdrhpan6kjav4gqkc7cs"; + version = "0.3.72"; + edition = "2021"; + sha256 = "1a8r61hbgw5kmscgj3g5pzg2ywlnswvljy0l592v0xdxlayz323a"; + libName = "js_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -5777,9 +5948,9 @@ rec { }; "lazy_static" = rec { crateName = "lazy_static"; - version = "1.4.0"; + version = "1.5.0"; edition = "2015"; - sha256 = "0in6ikhw8mgl33wjv6q6xfrb5b9jr16q8ygjy803fay4zcisvaz2"; + sha256 = "1zk6dqqni0193xg6iijh7i3i44sryglwgvx20spdvwk3r6sbrlmv"; authors = [ "Marvin Löbel <loebel.marvin@gmail.com>" ]; @@ -5793,6 +5964,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0ihf0x3vrk25fq3bv9q35m0xax0wmvwkh0j0pjm2yk4ddvh5vpic"; + libName = "lexical_core"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -5855,6 +6027,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0py0gp8hlzcrlvjqmqlpl2v1as65iiqxq2xsabxvhc01pmg3lfv8"; + libName = "lexical_parse_float"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -5895,6 +6068,7 @@ rec { version = "0.8.6"; edition = "2018"; sha256 = "1sayji3mpvb2xsjq56qcq3whfz8px9a6fxk5v7v15hyhbr4982bd"; + libName = "lexical_parse_integer"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -5926,6 +6100,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "1z73qkv7yxhsbc4aiginn1dqmsj8jarkrdlyxc88g2gz2vzvjmaj"; + libName = "lexical_util"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -5952,6 +6127,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0qk825l0csvnksh9sywb51996cjc2bylq6rxjaiha7sqqjhvmjmc"; + libName = "lexical_write_float"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -5992,6 +6168,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0ii4hmvqrg6pd4j9y1pkhkp0nw2wpivjzmljh6v6ca22yk8z7dp1"; + libName = "lexical_write_integer"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -6020,9 +6197,9 @@ rec { }; "libc" = rec { crateName = "libc"; - version = "0.2.152"; + version = "0.2.159"; edition = "2015"; - sha256 = "1rsnma7hnw22w7jh9yqg43slddvfbnfzrvm3s7s4kinbj1jvzqqk"; + sha256 = "1i9xpia0hn1y8dws7all8rqng6h3lc8ymlgslnljcvm376jrf7an"; authors = [ "The Rust Project Developers" ]; @@ -6048,18 +6225,45 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; + "libmimalloc-sys" = rec { + crateName = "libmimalloc-sys"; + version = "0.1.39"; + edition = "2018"; + links = "mimalloc"; + sha256 = "0i3b0dzz7cp0ik7ys66q92r16va78gwlbrnxhj5fnkdxsc8niai3"; + libName = "libmimalloc_sys"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cty" = [ "dep:cty" ]; + "extended" = [ "cty" ]; + }; + }; "libredox" = rec { crateName = "libredox"; - version = "0.0.1"; + version = "0.1.3"; edition = "2021"; - sha256 = "1s2fh4ikpp9xl0lsl01pi0n8pw1q9s3ld452vd8qh1v63v537j45"; + sha256 = "139602gzgs0k91zb7dvgj1qh4ynb8g1lbxsswdim18hcb6ykgzy0"; authors = [ "4lDO2 <4lDO2@protonmail.com>" ]; dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "libc"; @@ -6067,20 +6271,24 @@ rec { } { name = "redox_syscall"; - packageId = "redox_syscall 0.4.1"; + packageId = "redox_syscall 0.5.7"; + optional = true; } ]; features = { - "default" = [ "scheme" "call" ]; - "scheme" = [ "call" ]; + "default" = [ "call" "std" "redox_syscall" ]; + "ioslice" = [ "dep:ioslice" ]; + "mkns" = [ "ioslice" ]; + "redox_syscall" = [ "dep:redox_syscall" ]; }; - resolvedDefaultFeatures = [ "call" ]; + resolvedDefaultFeatures = [ "call" "default" "redox_syscall" "std" ]; }; "linux-raw-sys" = rec { crateName = "linux-raw-sys"; - version = "0.4.13"; + version = "0.4.14"; edition = "2021"; - sha256 = "172k2c6422gsc914ig8rh99mb9yc7siw6ikc3d9xw1k7vx0s3k81"; + sha256 = "12gsjgbhhjwywpqcrizv80vrp7p7grsz5laqq773i33wphjsxcvq"; + libName = "linux_raw_sys"; authors = [ "Dan Gohman <dev@sunfishcode.online>" ]; @@ -6109,9 +6317,9 @@ rec { }; "lock_api" = rec { crateName = "lock_api"; - version = "0.4.11"; - edition = "2018"; - sha256 = "0iggx0h4jx63xm35861106af3jkxq06fpqhpkhgw0axi2n38y5iw"; + version = "0.4.12"; + edition = "2021"; + sha256 = "05qvxa6g27yyva25a5ghsg85apdxkvr77yhkyhapj6r8vnf8pbq7"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -6137,17 +6345,20 @@ rec { }; "log" = rec { crateName = "log"; - version = "0.4.20"; - edition = "2015"; - sha256 = "13rf7wphnwd61vazpxr7fiycin6cb1g8fmvgqg18i464p0y1drmm"; + version = "0.4.22"; + edition = "2021"; + sha256 = "093vs0wkm1rgyykk7fjbqp2lwizbixac1w52gv109p5r4jh0p9x7"; authors = [ "The Rust Project Developers" ]; features = { - "kv_unstable" = [ "value-bag" ]; - "kv_unstable_serde" = [ "kv_unstable_std" "value-bag/serde" "serde" ]; - "kv_unstable_std" = [ "std" "kv_unstable" "value-bag/error" ]; - "kv_unstable_sval" = [ "kv_unstable" "value-bag/sval" "sval" "sval_ref" ]; + "kv_serde" = [ "kv_std" "value-bag/serde" "serde" ]; + "kv_std" = [ "std" "kv" "value-bag/error" ]; + "kv_sval" = [ "kv" "value-bag/sval" "sval" "sval_ref" ]; + "kv_unstable" = [ "kv" "value-bag" ]; + "kv_unstable_serde" = [ "kv_serde" "kv_unstable_std" ]; + "kv_unstable_std" = [ "kv_std" "kv_unstable" ]; + "kv_unstable_sval" = [ "kv_sval" "kv_unstable" ]; "serde" = [ "dep:serde" ]; "sval" = [ "dep:sval" ]; "sval_ref" = [ "dep:sval_ref" ]; @@ -6155,12 +6366,77 @@ rec { }; resolvedDefaultFeatures = [ "std" ]; }; + "loom" = rec { + crateName = "loom"; + version = "0.7.2"; + edition = "2018"; + sha256 = "1jpszf9qxv8ydpsm2h9vcyvxvyxcfkhmmfbylzd4gfbc0k40v7j1"; + authors = [ + "Carl Lerche <me@carllerche.com>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "generator"; + packageId = "generator"; + } + { + name = "scoped-tls"; + packageId = "scoped-tls"; + } + { + name = "tracing"; + packageId = "tracing"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "tracing-subscriber"; + packageId = "tracing-subscriber"; + features = [ "env-filter" ]; + } + ]; + features = { + "checkpoint" = [ "serde" "serde_json" ]; + "futures" = [ "pin-utils" ]; + "pin-utils" = [ "dep:pin-utils" ]; + "serde" = [ "dep:serde" ]; + "serde_json" = [ "dep:serde_json" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "lru" = rec { + crateName = "lru"; + version = "0.12.5"; + edition = "2015"; + sha256 = "0f1a7cgqxbyhrmgaqqa11m3azwhcc36w0v5r4izgbhadl3sg8k13"; + authors = [ + "Jerome Froelich <jeromefroelic@hotmail.com>" + ]; + dependencies = [ + { + name = "hashbrown"; + packageId = "hashbrown 0.15.0"; + optional = true; + } + ]; + features = { + "default" = [ "hashbrown" ]; + "hashbrown" = [ "dep:hashbrown" ]; + "nightly" = [ "hashbrown" "hashbrown/nightly" ]; + }; + resolvedDefaultFeatures = [ "default" "hashbrown" ]; + }; "lzma-sys" = rec { crateName = "lzma-sys"; version = "0.1.20"; edition = "2018"; links = "lzma"; sha256 = "09sxp20waxyglgn3cjz8qjkspb3ryz2fwx4rigkwvrk46ymh9njz"; + libName = "lzma_sys"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -6198,7 +6474,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "libc"; @@ -6222,6 +6498,7 @@ rec { edition = "2015"; links = "magic"; sha256 = "1g5k9d9igxv4h23nbhp8bqa5gdpkd3ahgm0rh5i0s54mi3h6my7g"; + libName = "magic_sys"; authors = [ "robo9k <robo9k@symlink.io>" ]; @@ -6272,7 +6549,7 @@ rec { ]; }; - "matchit" = rec { + "matchit 0.7.3" = rec { crateName = "matchit"; version = "0.7.3"; edition = "2021"; @@ -6283,6 +6560,17 @@ rec { features = { }; resolvedDefaultFeatures = [ "default" ]; }; + "matchit 0.8.4" = rec { + crateName = "matchit"; + version = "0.8.4"; + edition = "2021"; + sha256 = "1hzl48fwq1cn5dvshfly6vzkzqhfihya65zpj7nz7lfx82mgzqa7"; + authors = [ + "Ibraheem Ahmed <ibraheem@ibraheem.ca>" + ]; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; "md-5" = rec { crateName = "md-5"; version = "0.10.6"; @@ -6320,9 +6608,9 @@ rec { }; "memchr" = rec { crateName = "memchr"; - version = "2.7.1"; + version = "2.7.4"; edition = "2021"; - sha256 = "0jf1kicqa4vs9lyzj4v4y1p90q0dh87hvhsdd5xvhnp527sw8gaj"; + sha256 = "18z32bhxrax0fnjikv475z7ii718hq457qwmaryixfxsl2qrmjkq"; authors = [ "Andrew Gallant <jamslam@gmail.com>" "bluss" @@ -6338,7 +6626,7 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; - "memoffset 0.6.5" = rec { + "memoffset" = rec { crateName = "memoffset"; version = "0.6.5"; edition = "2015"; @@ -6355,21 +6643,32 @@ rec { features = { }; resolvedDefaultFeatures = [ "default" ]; }; - "memoffset 0.9.0" = rec { - crateName = "memoffset"; - version = "0.9.0"; - edition = "2015"; - sha256 = "0v20ihhdzkfw1jx00a7zjpk2dcp5qjq6lz302nyqamd9c4f4nqss"; + "mimalloc" = rec { + crateName = "mimalloc"; + version = "0.1.43"; + edition = "2018"; + sha256 = "0csnyrxc16i592gm5ffham07jyj2w98qsh9jyy1rv59lmr8474b8"; authors = [ - "Gilad Naaman <gilad.naaman@gmail.com>" + "Octavian Oncescu <octavonce@gmail.com>" + "Vincent Rouillé <vincent@speedy37.fr>" + "Thom Chiovoloni <chiovolonit@gmail.com>" ]; - buildDependencies = [ + dependencies = [ { - name = "autocfg"; - packageId = "autocfg"; + name = "libmimalloc-sys"; + packageId = "libmimalloc-sys"; + usesDefaultFeatures = false; } ]; - features = { }; + features = { + "debug" = [ "libmimalloc-sys/debug" ]; + "debug_in_debug" = [ "libmimalloc-sys/debug_in_debug" ]; + "extended" = [ "libmimalloc-sys/extended" ]; + "local_dynamic_tls" = [ "libmimalloc-sys/local_dynamic_tls" ]; + "no_thp" = [ "libmimalloc-sys/no_thp" ]; + "override" = [ "libmimalloc-sys/override" ]; + "secure" = [ "libmimalloc-sys/secure" ]; + }; resolvedDefaultFeatures = [ "default" ]; }; "mime" = rec { @@ -6387,6 +6686,7 @@ rec { version = "0.2.1"; edition = "2018"; sha256 = "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8"; + libName = "minimal_lexical"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -6397,17 +6697,17 @@ rec { }; "miniz_oxide" = rec { crateName = "miniz_oxide"; - version = "0.7.1"; - edition = "2018"; - sha256 = "1ivl3rbbdm53bzscrd01g60l46lz5krl270487d8lhjvwl5hx0g7"; + version = "0.8.0"; + edition = "2021"; + sha256 = "1wadxkg6a6z4lr7kskapj5d8pxlx7cp1ifw4daqnkzqjxych5n72"; authors = [ "Frommi <daniil.liferenko@gmail.com>" "oyvindln <oyvindln@users.noreply.github.com>" ]; dependencies = [ { - name = "adler"; - packageId = "adler"; + name = "adler2"; + packageId = "adler2"; usesDefaultFeatures = false; } ]; @@ -6416,17 +6716,17 @@ rec { "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; "default" = [ "with-alloc" ]; - "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler/rustc-dep-of-std" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler2/rustc-dep-of-std" ]; "simd" = [ "simd-adler32" ]; "simd-adler32" = [ "dep:simd-adler32" ]; }; resolvedDefaultFeatures = [ "with-alloc" ]; }; - "mio" = rec { + "mio 0.8.11" = rec { crateName = "mio"; - version = "0.8.10"; + version = "0.8.11"; edition = "2018"; - sha256 = "02gyaxvaia9zzi4drrw59k9s0j6pa5d1y2kv7iplwjipdqlhngcg"; + sha256 = "034byyl0ardml5yliy1hmvx8arkmn9rv479pid794sm07ia519m4"; authors = [ "Carl Lerche <me@carllerche.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -6465,13 +6765,59 @@ rec { "log" = [ "dep:log" ]; "os-ext" = [ "os-poll" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_Security" ]; }; - resolvedDefaultFeatures = [ "default" "log" "net" "os-ext" "os-poll" ]; + resolvedDefaultFeatures = [ "default" "log" "os-ext" "os-poll" ]; + }; + "mio 1.0.2" = rec { + crateName = "mio"; + version = "1.0.2"; + edition = "2021"; + sha256 = "1v1cnnn44awxbcfm4zlavwgkvbyg7gp5zzjm8mqf1apkrwflvq40"; + authors = [ + "Carl Lerche <me@carllerche.com>" + "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "hermit-abi"; + packageId = "hermit-abi 0.3.9"; + rename = "libc"; + target = { target, features }: ("hermit" == target."os" or null); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: ("wasi" == target."os" or null); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "wasi"; + packageId = "wasi"; + target = { target, features }: ("wasi" == target."os" or null); + } + { + name = "windows-sys"; + packageId = "windows-sys 0.52.0"; + target = { target, features }: (target."windows" or false); + features = [ "Wdk_Foundation" "Wdk_Storage_FileSystem" "Wdk_System_IO" "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; + } + ]; + features = { + "default" = [ "log" ]; + "log" = [ "dep:log" ]; + "os-ext" = [ "os-poll" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_Security" ]; + }; + resolvedDefaultFeatures = [ "net" "os-ext" "os-poll" ]; }; "multimap" = rec { crateName = "multimap"; - version = "0.8.3"; + version = "0.10.0"; edition = "2015"; - sha256 = "0sicyz4n500vdhgcxn4g8jz97cp1ijir1rnbgph3pmx9ckz4dkp5"; + sha256 = "00vs2frqdhrr8iqx4y3fbq73ax5l12837fvbjrpi729d85alrz6y"; authors = [ "HÃ¥var Nøvik <havar.novik@gmail.com>" ]; @@ -6481,6 +6827,164 @@ rec { "serde_impl" = [ "serde" ]; }; }; + "nar-bridge" = rec { + crateName = "nar-bridge"; + version = "0.1.0"; + edition = "2021"; + crateBin = [ + { + name = "nar-bridge"; + path = "src/bin/nar-bridge.rs"; + requiredFeatures = [ ]; + } + ]; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./nar-bridge; }; + libName = "nar_bridge"; + dependencies = [ + { + name = "axum"; + packageId = "axum"; + features = [ "http2" ]; + } + { + name = "axum-extra"; + packageId = "axum-extra"; + } + { + name = "axum-range"; + packageId = "axum-range"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "clap"; + packageId = "clap"; + features = [ "derive" "env" ]; + } + { + name = "data-encoding"; + packageId = "data-encoding"; + } + { + name = "futures"; + packageId = "futures"; + } + { + name = "itertools"; + packageId = "itertools 0.12.1"; + } + { + name = "lru"; + packageId = "lru"; + } + { + name = "mimalloc"; + packageId = "mimalloc"; + } + { + name = "nix-compat"; + packageId = "nix-compat"; + features = [ "async" ]; + } + { + name = "parking_lot"; + packageId = "parking_lot"; + } + { + name = "prost"; + packageId = "prost"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "tokio"; + packageId = "tokio"; + } + { + name = "tokio-listener"; + packageId = "tokio-listener"; + features = [ "axum07" "clap" "multi-listener" "sd_listen" ]; + } + { + name = "tokio-util"; + packageId = "tokio-util"; + features = [ "io" "io-util" "compat" ]; + } + { + name = "tonic"; + packageId = "tonic"; + features = [ "tls" "tls-roots" ]; + } + { + name = "tower"; + packageId = "tower 0.4.13"; + } + { + name = "tower-http"; + packageId = "tower-http"; + features = [ "trace" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "tracing-subscriber"; + packageId = "tracing-subscriber"; + } + { + name = "tvix-castore"; + packageId = "tvix-castore"; + } + { + name = "tvix-store"; + packageId = "tvix-store"; + } + { + name = "tvix-tracing"; + packageId = "tvix-tracing"; + features = [ "tonic" "axum" ]; + } + { + name = "url"; + packageId = "url"; + } + ]; + buildDependencies = [ + { + name = "prost-build"; + packageId = "prost-build"; + } + { + name = "tonic-build"; + packageId = "tonic-build"; + } + ]; + devDependencies = [ + { + name = "hex-literal"; + packageId = "hex-literal"; + } + { + name = "rstest"; + packageId = "rstest"; + } + ]; + features = { + "default" = [ "otlp" ]; + "otlp" = [ "tvix-tracing/otlp" ]; + }; + resolvedDefaultFeatures = [ "default" "otlp" ]; + }; "nibble_vec" = rec { crateName = "nibble_vec"; version = "0.1.0"; @@ -6521,7 +7025,7 @@ rec { } { name = "memoffset"; - packageId = "memoffset 0.6.5"; + packageId = "memoffset"; optional = true; target = { target, features }: (!("redox" == target."os" or null)); } @@ -6644,7 +7148,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "cfg-if"; @@ -6685,16 +7189,12 @@ rec { requiredFeatures = [ ]; } ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./nix-compat; } - else ./nix-compat; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./nix-compat; }; + libName = "nix_compat"; dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "bstr"; @@ -6702,6 +7202,11 @@ rec { features = [ "alloc" "unicode" "serde" ]; } { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { name = "data-encoding"; packageId = "data-encoding"; } @@ -6722,6 +7227,15 @@ rec { packageId = "glob"; } { + name = "mimalloc"; + packageId = "mimalloc"; + } + { + name = "nix-compat-derive"; + packageId = "nix-compat-derive"; + optional = true; + } + { name = "nom"; packageId = "nom"; } @@ -6757,6 +7271,10 @@ rec { optional = true; features = [ "io-util" "macros" ]; } + { + name = "tracing"; + packageId = "tracing"; + } ]; devDependencies = [ { @@ -6767,16 +7285,14 @@ rec { { name = "futures"; packageId = "futures"; - usesDefaultFeatures = false; - features = [ "executor" ]; } { name = "hex-literal"; packageId = "hex-literal"; } { - name = "lazy_static"; - packageId = "lazy_static"; + name = "mimalloc"; + packageId = "mimalloc"; } { name = "pretty_assertions"; @@ -6791,6 +7307,10 @@ rec { packageId = "serde_json"; } { + name = "smol_str"; + packageId = "smol_str"; + } + { name = "tokio-test"; packageId = "tokio-test"; } @@ -6801,12 +7321,193 @@ rec { ]; features = { "async" = [ "tokio" ]; - "default" = [ "async" "wire" ]; + "bytes" = [ "dep:bytes" ]; + "default" = [ "async" "wire" "nix-compat-derive" ]; + "nix-compat-derive" = [ "dep:nix-compat-derive" ]; "pin-project-lite" = [ "dep:pin-project-lite" ]; "tokio" = [ "dep:tokio" ]; - "wire" = [ "tokio" "pin-project-lite" ]; + "wire" = [ "tokio" "pin-project-lite" "bytes" ]; }; - resolvedDefaultFeatures = [ "async" "default" "pin-project-lite" "tokio" "wire" ]; + resolvedDefaultFeatures = [ "async" "bytes" "default" "nix-compat-derive" "pin-project-lite" "test" "tokio" "wire" ]; + }; + "nix-compat-derive" = rec { + crateName = "nix-compat-derive"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./nix-compat-derive; }; + procMacro = true; + libName = "nix_compat_derive"; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + features = [ "proc-macro" ]; + } + { + name = "quote"; + packageId = "quote"; + features = [ "proc-macro" ]; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" "extra-traits" ]; + } + ]; + devDependencies = [ + { + name = "hex-literal"; + packageId = "hex-literal"; + } + { + name = "nix-compat"; + packageId = "nix-compat"; + usesDefaultFeatures = false; + features = [ "async" "wire" "test" ]; + } + { + name = "pretty_assertions"; + packageId = "pretty_assertions"; + } + { + name = "rstest"; + packageId = "rstest"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "io-util" "macros" ]; + } + { + name = "tokio-test"; + packageId = "tokio-test"; + } + ]; + + }; + "nix-compat-derive-tests" = rec { + crateName = "nix-compat-derive-tests"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./nix-compat-derive-tests; }; + devDependencies = [ + { + name = "hex-literal"; + packageId = "hex-literal"; + } + { + name = "nix-compat"; + packageId = "nix-compat"; + features = [ "test" "wire" ]; + } + { + name = "nix-compat-derive"; + packageId = "nix-compat-derive"; + } + { + name = "pretty_assertions"; + packageId = "pretty_assertions"; + } + { + name = "rstest"; + packageId = "rstest"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "io-util" "macros" ]; + } + { + name = "tokio-test"; + packageId = "tokio-test"; + } + { + name = "trybuild"; + packageId = "trybuild"; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "compile-tests" ]; + }; + "nix-daemon" = rec { + crateName = "nix-daemon"; + version = "0.1.0"; + edition = "2021"; + crateBin = [ + { + name = "nix-daemon"; + path = "src/bin/nix-daemon.rs"; + requiredFeatures = [ ]; + } + ]; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./nix-daemon; }; + dependencies = [ + { + name = "async-trait"; + packageId = "async-trait"; + } + { + name = "clap"; + packageId = "clap"; + features = [ "derive" "env" ]; + } + { + name = "futures"; + packageId = "futures"; + } + { + name = "mimalloc"; + packageId = "mimalloc"; + } + { + name = "nix-compat"; + packageId = "nix-compat"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "fs" "macros" "net" "rt" "rt-multi-thread" "signal" ]; + } + { + name = "tokio-listener"; + packageId = "tokio-listener"; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "tvix-castore"; + packageId = "tvix-castore"; + } + { + name = "tvix-store"; + packageId = "tvix-store"; + } + { + name = "tvix-tracing"; + packageId = "tvix-tracing"; + } + ]; + features = { + "default" = [ "otlp" ]; + "otlp" = [ "tvix-tracing/otlp" ]; + }; + resolvedDefaultFeatures = [ "default" "otlp" ]; + }; + "nohash-hasher" = rec { + crateName = "nohash-hasher"; + version = "0.2.0"; + edition = "2018"; + sha256 = "0lf4p6k01w4wm7zn4grnihzj8s7zd5qczjmzng7wviwxawih5x9b"; + libName = "nohash_hasher"; + authors = [ + "Parity Technologies <admin@parity.io>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; }; "nom" = rec { crateName = "nom"; @@ -6858,6 +7559,7 @@ rec { version = "0.46.0"; edition = "2018"; sha256 = "115sywxh53p190lyw97alm14nc004qj5jm5lvdj608z84rbida3p"; + libName = "nu_ansi_term"; authors = [ "ogham@bsago.me" "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>" @@ -6886,6 +7588,7 @@ rec { version = "0.1.0"; edition = "2021"; sha256 = "1ndiyg82q73783jq18isi71a7mjh56wxrk52rlvyx0mi5z9ibmai"; + libName = "num_conv"; authors = [ "Jacob Pratt <jacob@jhpratt.dev>" ]; @@ -6893,9 +7596,10 @@ rec { }; "num-traits" = rec { crateName = "num-traits"; - version = "0.2.18"; - edition = "2018"; - sha256 = "0yjib8p2p9kzmaz48xwhs69w5dh1wipph9jgnillzd2x33jz03fs"; + version = "0.2.19"; + edition = "2021"; + sha256 = "0h984rhdkkqd4ny9cif7y2azl3xdfb7768hb9irhpsch4q3gq787"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -6929,7 +7633,7 @@ rec { dependencies = [ { name = "hermit-abi"; - packageId = "hermit-abi"; + packageId = "hermit-abi 0.3.9"; target = { target, features }: ("hermit" == target."os" or null); } { @@ -6940,11 +7644,24 @@ rec { ]; }; + "number_prefix" = rec { + crateName = "number_prefix"; + version = "0.4.0"; + edition = "2015"; + sha256 = "1wvh13wvlajqxkb1filsfzbrnq0vrmrw298v2j3sy82z1rm282w3"; + authors = [ + "Benjamin Sago <ogham@bsago.me>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; "object" = rec { crateName = "object"; - version = "0.32.2"; + version = "0.36.5"; edition = "2018"; - sha256 = "0hc4cjwyngiy6k51hlzrlsxgv5z25vv7c2cp0ky1lckfic0259m6"; + sha256 = "0gk8lhbs229c68lapq6w6qmnm4jkj48hrcw5ilfyswy514nhmpxf"; dependencies = [ { name = "memchr"; @@ -6953,13 +7670,15 @@ rec { } ]; features = { - "all" = [ "read" "write" "std" "compression" "wasm" ]; + "all" = [ "read" "write" "build" "std" "compression" "wasm" ]; "alloc" = [ "dep:alloc" ]; + "build" = [ "build_core" "write_std" "elf" ]; + "build_core" = [ "read_core" "write_core" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "compression" = [ "dep:flate2" "dep:ruzstd" "std" ]; "core" = [ "dep:core" ]; "default" = [ "read" "compression" ]; - "doc" = [ "read_core" "write_std" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; + "doc" = [ "read_core" "write_std" "build_core" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; "pe" = [ "coff" ]; "read" = [ "read_core" "archive" "coff" "elf" "macho" "pe" "xcoff" "unaligned" ]; "rustc-dep-of-std" = [ "core" "compiler_builtins" "alloc" "memchr/rustc-dep-of-std" ]; @@ -6970,13 +7689,13 @@ rec { "write_core" = [ "dep:crc32fast" "dep:indexmap" "dep:hashbrown" ]; "write_std" = [ "write_core" "std" "indexmap?/std" "crc32fast?/std" ]; }; - resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" ]; + resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" "xcoff" ]; }; "object_store" = rec { crateName = "object_store"; - version = "0.9.1"; + version = "0.10.2"; edition = "2021"; - sha256 = "1cwx0xg57cp3z6xjgrqwp0gxgxsagls4h5cd212pmxpxcn5qywdq"; + sha256 = "1wz3m20hqs3v93dyxcqy7qpsbd4rqp6050hy49wcw5f740l4bnp6"; dependencies = [ { name = "async-trait"; @@ -6984,7 +7703,7 @@ rec { } { name = "base64"; - packageId = "base64"; + packageId = "base64 0.22.1"; optional = true; usesDefaultFeatures = false; features = [ "std" ]; @@ -7009,13 +7728,13 @@ rec { } { name = "hyper"; - packageId = "hyper 0.14.28"; + packageId = "hyper"; optional = true; usesDefaultFeatures = false; } { name = "itertools"; - packageId = "itertools 0.12.0"; + packageId = "itertools 0.13.0"; } { name = "md-5"; @@ -7025,7 +7744,7 @@ rec { } { name = "parking_lot"; - packageId = "parking_lot 0.12.1"; + packageId = "parking_lot"; } { name = "percent-encoding"; @@ -7049,7 +7768,7 @@ rec { packageId = "reqwest"; optional = true; usesDefaultFeatures = false; - features = [ "rustls-tls-native-roots" ]; + features = [ "rustls-tls-native-roots" "http2" ]; } { name = "ring"; @@ -7060,7 +7779,7 @@ rec { } { name = "rustls-pemfile"; - packageId = "rustls-pemfile 2.1.0"; + packageId = "rustls-pemfile"; optional = true; usesDefaultFeatures = false; features = [ "std" ]; @@ -7103,7 +7822,7 @@ rec { devDependencies = [ { name = "hyper"; - packageId = "hyper 0.14.28"; + packageId = "hyper"; features = [ "server" ]; } { @@ -7131,11 +7850,71 @@ rec { }; resolvedDefaultFeatures = [ "aws" "azure" "base64" "cloud" "gcp" "http" "hyper" "md-5" "quick-xml" "rand" "reqwest" "ring" "rustls-pemfile" "serde" "serde_json" ]; }; + "oci-spec" = rec { + crateName = "oci-spec"; + version = "0.7.0"; + edition = "2021"; + sha256 = "0qxk3yrzg91dk801g29fmbq7zb8bgkc4rqwlw52ww76gwxf1ivjw"; + libName = "oci_spec"; + authors = [ + "Furisto" + "Sascha Grunert <sgrunert@redhat.com>" + "Toru Komatsu <k0ma@utam0k.jp>" + ]; + dependencies = [ + { + name = "derive_builder"; + packageId = "derive_builder"; + } + { + name = "getset"; + packageId = "getset"; + } + { + name = "regex"; + packageId = "regex"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "serde_json"; + packageId = "serde_json"; + } + { + name = "strum"; + packageId = "strum"; + } + { + name = "strum_macros"; + packageId = "strum_macros"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + ]; + devDependencies = [ + { + name = "serde_json"; + packageId = "serde_json"; + features = [ "preserve_order" ]; + } + ]; + features = { + "default" = [ "distribution" "image" "runtime" ]; + "proptests" = [ "quickcheck" ]; + "quickcheck" = [ "dep:quickcheck" ]; + }; + resolvedDefaultFeatures = [ "default" "distribution" "image" "runtime" ]; + }; "once_cell" = rec { crateName = "once_cell"; - version = "1.19.0"; + version = "1.20.2"; edition = "2021"; - sha256 = "14kvw7px5z96dk4dwdm1r9cqhhy2cyj1l5n5b29mynbb8yr15nrz"; + sha256 = "0xb7rw1aqr7pa4z3b00y7786gyf8awx2gca3md73afy76dzgwq8j"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" ]; @@ -7152,9 +7931,9 @@ rec { }; "oorandom" = rec { crateName = "oorandom"; - version = "11.1.3"; + version = "11.1.4"; edition = "2018"; - sha256 = "0xdm4vd89aiwnrk1xjwzklnchjqvib4klcihlc2bsd4x50mbrc8a"; + sha256 = "1sg4j19r5302a6jpn0kgfkbjnslrqr3ynxv8x2h2ddaaw7kvn45l"; authors = [ "Simon Heath <icefox@dreamquest.io>" ]; @@ -7165,16 +7944,17 @@ rec { version = "0.1.5"; edition = "2015"; sha256 = "1kq18qm48rvkwgcggfkqq6pm948190czqc94d6bm2sir5hq1l0gz"; + libName = "openssl_probe"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; }; - "opentelemetry" = rec { + "opentelemetry 0.22.0" = rec { crateName = "opentelemetry"; - version = "0.21.0"; + version = "0.22.0"; edition = "2021"; - sha256 = "12jfmyx8k9q2sjlx4wp76ddzaf94i7lnkliv1c9mj164bnd36chy"; + sha256 = "1gv70rx8172g9n82v9f97ircax7v4ydzyprq1nvsxwp3gfc5f3ch"; dependencies = [ { name = "futures-core"; @@ -7185,10 +7965,6 @@ rec { packageId = "futures-sink"; } { - name = "indexmap"; - packageId = "indexmap 2.1.0"; - } - { name = "js-sys"; packageId = "js-sys"; target = { target, features }: (("wasm32" == target."arch" or null) && (!("wasi" == target."os" or null))); @@ -7205,6 +7981,7 @@ rec { { name = "thiserror"; packageId = "thiserror"; + usesDefaultFeatures = false; } { name = "urlencoding"; @@ -7220,11 +7997,89 @@ rec { }; resolvedDefaultFeatures = [ "default" "metrics" "pin-project-lite" "trace" ]; }; + "opentelemetry 0.24.0" = rec { + crateName = "opentelemetry"; + version = "0.24.0"; + edition = "2021"; + sha256 = "15msgya5nandw9chxdr76k7sj9kg6gqj9dyfzrz5pxf4xrimldjc"; + dependencies = [ + { + name = "futures-core"; + packageId = "futures-core"; + } + { + name = "futures-sink"; + packageId = "futures-sink"; + } + { + name = "js-sys"; + packageId = "js-sys"; + target = { target, features }: (("wasm32" == target."arch" or null) && (!("wasi" == target."os" or null))); + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + optional = true; + } + { + name = "thiserror"; + packageId = "thiserror"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "trace" "metrics" "logs" ]; + "logs_level_enabled" = [ "logs" ]; + "pin-project-lite" = [ "dep:pin-project-lite" ]; + "testing" = [ "trace" "metrics" ]; + "trace" = [ "pin-project-lite" ]; + }; + resolvedDefaultFeatures = [ "default" "logs" "metrics" "pin-project-lite" "trace" ]; + }; + "opentelemetry-http" = rec { + crateName = "opentelemetry-http"; + version = "0.13.0"; + edition = "2021"; + sha256 = "1avqmyh42apakbkhjij3c9hl0brnq5v37zk4kpxkhdgf8kgfjcdd"; + libName = "opentelemetry_http"; + dependencies = [ + { + name = "async-trait"; + packageId = "async-trait"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "http"; + packageId = "http"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "opentelemetry"; + packageId = "opentelemetry 0.24.0"; + features = [ "trace" ]; + } + ]; + features = { + "hyper" = [ "dep:http-body-util" "dep:hyper" "dep:hyper-util" "dep:tokio" ]; + "reqwest" = [ "dep:reqwest" ]; + "reqwest-rustls" = [ "reqwest" "reqwest/rustls-tls-native-roots" ]; + "reqwest-rustls-webpki-roots" = [ "reqwest" "reqwest/rustls-tls-webpki-roots" ]; + }; + }; "opentelemetry-otlp" = rec { crateName = "opentelemetry-otlp"; - version = "0.14.0"; + version = "0.17.0"; edition = "2021"; - sha256 = "0c59bh4wa824mf89ayivsjqwipkg1y6r27r4d0y47lhfna1xlk7j"; + sha256 = "09z70ygp6lfcplnwx7cgf3p3fyq2arkvhxhj8avnz4gv5xh5m4kb"; + libName = "opentelemetry_otlp"; dependencies = [ { name = "async-trait"; @@ -7236,12 +8091,14 @@ rec { } { name = "http"; - packageId = "http 0.2.11"; + packageId = "http"; optional = true; + usesDefaultFeatures = false; + features = [ "std" ]; } { name = "opentelemetry"; - packageId = "opentelemetry"; + packageId = "opentelemetry 0.24.0"; usesDefaultFeatures = false; } { @@ -7250,138 +8107,133 @@ rec { usesDefaultFeatures = false; } { - name = "opentelemetry-semantic-conventions"; - packageId = "opentelemetry-semantic-conventions"; - } - { name = "opentelemetry_sdk"; - packageId = "opentelemetry_sdk"; + packageId = "opentelemetry_sdk 0.24.1"; usesDefaultFeatures = false; } { name = "prost"; - packageId = "prost 0.11.9"; + packageId = "prost"; optional = true; } { name = "thiserror"; packageId = "thiserror"; + usesDefaultFeatures = false; } { name = "tokio"; packageId = "tokio"; optional = true; + usesDefaultFeatures = false; features = [ "sync" "rt" ]; } { name = "tonic"; - packageId = "tonic 0.9.2"; + packageId = "tonic"; optional = true; + usesDefaultFeatures = false; } ]; devDependencies = [ { name = "tokio"; packageId = "tokio"; + usesDefaultFeatures = false; features = [ "macros" "rt-multi-thread" ]; } ]; features = { - "default" = [ "grpc-tonic" "trace" ]; - "grpc-sys" = [ "grpcio" "opentelemetry-proto/gen-grpcio" ]; + "default" = [ "grpc-tonic" "trace" "metrics" "logs" ]; "grpc-tonic" = [ "tonic" "prost" "http" "tokio" "opentelemetry-proto/gen-tonic" ]; - "grpcio" = [ "dep:grpcio" ]; "gzip-tonic" = [ "tonic/gzip" ]; "http" = [ "dep:http" ]; + "http-json" = [ "serde_json" "prost" "opentelemetry-http" "opentelemetry-proto/gen-tonic-messages" "opentelemetry-proto/with-serde" "http" "trace" "metrics" ]; "http-proto" = [ "prost" "opentelemetry-http" "opentelemetry-proto/gen-tonic-messages" "http" "trace" "metrics" ]; "integration-testing" = [ "tonic" "prost" "tokio/full" "trace" ]; "logs" = [ "opentelemetry/logs" "opentelemetry_sdk/logs" "opentelemetry-proto/logs" ]; "metrics" = [ "opentelemetry/metrics" "opentelemetry_sdk/metrics" "opentelemetry-proto/metrics" ]; - "openssl" = [ "grpcio/openssl" ]; - "openssl-vendored" = [ "grpcio/openssl-vendored" ]; "opentelemetry-http" = [ "dep:opentelemetry-http" ]; "prost" = [ "dep:prost" ]; "reqwest" = [ "dep:reqwest" ]; "reqwest-blocking-client" = [ "reqwest/blocking" "opentelemetry-http/reqwest" ]; "reqwest-client" = [ "reqwest" "opentelemetry-http/reqwest" ]; - "reqwest-rustls" = [ "reqwest" "reqwest/rustls-tls-native-roots" ]; + "reqwest-rustls" = [ "reqwest" "opentelemetry-http/reqwest-rustls" ]; + "reqwest-rustls-webpki-roots" = [ "reqwest" "opentelemetry-http/reqwest-rustls-webpki-roots" ]; "serde" = [ "dep:serde" ]; - "serialize" = [ "serde" ]; - "surf" = [ "dep:surf" ]; - "surf-client" = [ "surf" "opentelemetry-http/surf" ]; + "serde_json" = [ "dep:serde_json" ]; + "serialize" = [ "serde" "serde_json" ]; "tls" = [ "tonic/tls" ]; "tls-roots" = [ "tls" "tonic/tls-roots" ]; + "tls-webpki-roots" = [ "tls" "tonic/tls-webpki-roots" ]; "tokio" = [ "dep:tokio" ]; "tonic" = [ "dep:tonic" ]; "trace" = [ "opentelemetry/trace" "opentelemetry_sdk/trace" "opentelemetry-proto/trace" ]; }; - resolvedDefaultFeatures = [ "default" "grpc-tonic" "http" "prost" "tokio" "tonic" "trace" ]; + resolvedDefaultFeatures = [ "default" "grpc-tonic" "http" "logs" "metrics" "prost" "tokio" "tonic" "trace" ]; }; "opentelemetry-proto" = rec { crateName = "opentelemetry-proto"; - version = "0.4.0"; + version = "0.7.0"; edition = "2021"; - sha256 = "1qblsq0hkksdw3k60bc8yi5xwlynmqwibggz3lyyl4n8bk75bqd2"; + sha256 = "1nahv1dflvwdgi4c4p7ikd59x0yyivf85w02398q9jgrpwh9zvih"; + libName = "opentelemetry_proto"; dependencies = [ { name = "opentelemetry"; - packageId = "opentelemetry"; + packageId = "opentelemetry 0.24.0"; usesDefaultFeatures = false; } { name = "opentelemetry_sdk"; - packageId = "opentelemetry_sdk"; + packageId = "opentelemetry_sdk 0.24.1"; usesDefaultFeatures = false; } { name = "prost"; - packageId = "prost 0.11.9"; + packageId = "prost"; optional = true; } { name = "tonic"; - packageId = "tonic 0.9.2"; + packageId = "tonic"; optional = true; usesDefaultFeatures = false; features = [ "codegen" "prost" ]; } ]; + devDependencies = [ + { + name = "opentelemetry"; + packageId = "opentelemetry 0.24.0"; + features = [ "testing" ]; + } + ]; features = { - "full" = [ "gen-tonic" "gen-grpcio" "trace" "logs" "metrics" "zpages" "with-serde" ]; - "gen-grpcio" = [ "grpcio" "prost" ]; + "default" = [ "full" ]; + "full" = [ "gen-tonic" "trace" "logs" "metrics" "zpages" "with-serde" ]; "gen-tonic" = [ "gen-tonic-messages" "tonic/transport" ]; "gen-tonic-messages" = [ "tonic" "prost" ]; - "grpcio" = [ "dep:grpcio" ]; + "hex" = [ "dep:hex" ]; "logs" = [ "opentelemetry/logs" "opentelemetry_sdk/logs" ]; "metrics" = [ "opentelemetry/metrics" "opentelemetry_sdk/metrics" ]; "prost" = [ "dep:prost" ]; + "schemars" = [ "dep:schemars" ]; "serde" = [ "dep:serde" ]; + "testing" = [ "opentelemetry/testing" ]; "tonic" = [ "dep:tonic" ]; "trace" = [ "opentelemetry/trace" "opentelemetry_sdk/trace" ]; - "with-serde" = [ "serde" ]; + "with-schemars" = [ "schemars" ]; + "with-serde" = [ "serde" "hex" ]; "zpages" = [ "trace" ]; }; - resolvedDefaultFeatures = [ "gen-tonic" "gen-tonic-messages" "prost" "tonic" "trace" ]; + resolvedDefaultFeatures = [ "gen-tonic" "gen-tonic-messages" "logs" "metrics" "prost" "tonic" "trace" ]; }; - "opentelemetry-semantic-conventions" = rec { - crateName = "opentelemetry-semantic-conventions"; - version = "0.13.0"; - edition = "2021"; - sha256 = "115wbgk840dklyhpg3lwp4x1m643qd7f0vkz8hmfz0pry4g4yxzm"; - dependencies = [ - { - name = "opentelemetry"; - packageId = "opentelemetry"; - usesDefaultFeatures = false; - } - ]; - - }; - "opentelemetry_sdk" = rec { + "opentelemetry_sdk 0.22.1" = rec { crateName = "opentelemetry_sdk"; - version = "0.21.2"; + version = "0.22.1"; edition = "2021"; - sha256 = "1r7gw2j2n800rd0vdnga32yhlfmc3c4y0sadcr97licam74aw5ig"; + sha256 = "0zkbkl29qik7cfmwbhr2ncink8fp9vi5x2qgk8gf6jg67c8wg44y"; dependencies = [ { name = "async-trait"; @@ -7418,7 +8270,7 @@ rec { } { name = "opentelemetry"; - packageId = "opentelemetry"; + packageId = "opentelemetry 0.22.0"; } { name = "ordered-float"; @@ -7434,11 +8286,100 @@ rec { packageId = "rand"; optional = true; usesDefaultFeatures = false; - features = [ "std" "std_rng" ]; + features = [ "std" "std_rng" "small_rng" ]; } { name = "thiserror"; packageId = "thiserror"; + usesDefaultFeatures = false; + } + ]; + features = { + "async-std" = [ "dep:async-std" ]; + "async-trait" = [ "dep:async-trait" ]; + "crossbeam-channel" = [ "dep:crossbeam-channel" ]; + "default" = [ "trace" ]; + "glob" = [ "dep:glob" ]; + "http" = [ "dep:http" ]; + "jaeger_remote_sampler" = [ "trace" "opentelemetry-http" "http" "serde" "serde_json" "url" ]; + "logs" = [ "opentelemetry/logs" "crossbeam-channel" "async-trait" "serde_json" ]; + "logs_level_enabled" = [ "logs" "opentelemetry/logs_level_enabled" ]; + "metrics" = [ "opentelemetry/metrics" "glob" "async-trait" ]; + "opentelemetry-http" = [ "dep:opentelemetry-http" ]; + "percent-encoding" = [ "dep:percent-encoding" ]; + "rand" = [ "dep:rand" ]; + "rt-async-std" = [ "async-std" ]; + "rt-tokio" = [ "tokio" "tokio-stream" ]; + "rt-tokio-current-thread" = [ "tokio" "tokio-stream" ]; + "serde" = [ "dep:serde" ]; + "serde_json" = [ "dep:serde_json" ]; + "testing" = [ "opentelemetry/testing" "trace" "metrics" "logs" "rt-async-std" "rt-tokio" "rt-tokio-current-thread" "tokio/macros" "tokio/rt-multi-thread" ]; + "tokio" = [ "dep:tokio" ]; + "tokio-stream" = [ "dep:tokio-stream" ]; + "trace" = [ "opentelemetry/trace" "crossbeam-channel" "rand" "async-trait" "percent-encoding" ]; + "url" = [ "dep:url" ]; + }; + resolvedDefaultFeatures = [ "async-trait" "crossbeam-channel" "glob" "metrics" "percent-encoding" "rand" "trace" ]; + }; + "opentelemetry_sdk 0.24.1" = rec { + crateName = "opentelemetry_sdk"; + version = "0.24.1"; + edition = "2021"; + sha256 = "1pr8phigsfki77wh79g6vz6flnhgnr09pm18g2hj83y81r4sqbk9"; + dependencies = [ + { + name = "async-trait"; + packageId = "async-trait"; + optional = true; + } + { + name = "futures-channel"; + packageId = "futures-channel"; + } + { + name = "futures-executor"; + packageId = "futures-executor"; + } + { + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; + features = [ "std" "sink" "async-await-macro" ]; + } + { + name = "glob"; + packageId = "glob"; + optional = true; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "opentelemetry"; + packageId = "opentelemetry 0.24.0"; + } + { + name = "percent-encoding"; + packageId = "percent-encoding"; + optional = true; + } + { + name = "rand"; + packageId = "rand"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" "std_rng" "small_rng" ]; + } + { + name = "serde_json"; + packageId = "serde_json"; + optional = true; + } + { + name = "thiserror"; + packageId = "thiserror"; + usesDefaultFeatures = false; } { name = "tokio"; @@ -7456,12 +8397,11 @@ rec { features = { "async-std" = [ "dep:async-std" ]; "async-trait" = [ "dep:async-trait" ]; - "crossbeam-channel" = [ "dep:crossbeam-channel" ]; - "default" = [ "trace" ]; + "default" = [ "trace" "metrics" "logs" ]; "glob" = [ "dep:glob" ]; "http" = [ "dep:http" ]; "jaeger_remote_sampler" = [ "trace" "opentelemetry-http" "http" "serde" "serde_json" "url" ]; - "logs" = [ "opentelemetry/logs" "crossbeam-channel" "async-trait" "serde_json" ]; + "logs" = [ "opentelemetry/logs" "async-trait" "serde_json" ]; "logs_level_enabled" = [ "logs" "opentelemetry/logs_level_enabled" ]; "metrics" = [ "opentelemetry/metrics" "glob" "async-trait" ]; "opentelemetry-http" = [ "dep:opentelemetry-http" ]; @@ -7475,16 +8415,17 @@ rec { "testing" = [ "opentelemetry/testing" "trace" "metrics" "logs" "rt-async-std" "rt-tokio" "rt-tokio-current-thread" "tokio/macros" "tokio/rt-multi-thread" ]; "tokio" = [ "dep:tokio" ]; "tokio-stream" = [ "dep:tokio-stream" ]; - "trace" = [ "opentelemetry/trace" "crossbeam-channel" "rand" "async-trait" "percent-encoding" ]; + "trace" = [ "opentelemetry/trace" "rand" "async-trait" "percent-encoding" ]; "url" = [ "dep:url" ]; }; - resolvedDefaultFeatures = [ "async-trait" "crossbeam-channel" "default" "glob" "metrics" "percent-encoding" "rand" "rt-tokio" "tokio" "tokio-stream" "trace" ]; + resolvedDefaultFeatures = [ "async-trait" "default" "glob" "logs" "metrics" "percent-encoding" "rand" "rt-tokio" "serde_json" "tokio" "tokio-stream" "trace" ]; }; "ordered-float" = rec { crateName = "ordered-float"; - version = "4.2.0"; + version = "4.3.0"; edition = "2021"; - sha256 = "0kjqcvvbcsibbx3hnj7ag06bd9gv2zfi5ja6rgyh2kbxbh3zfvd7"; + sha256 = "0dr5d8byvqkiclxjimp5kyh3m9qz4zvwifx6cg0d6w9glzqh3ma4"; + libName = "ordered_float"; authors = [ "Jonathan Reem <jonathan.reem@gmail.com>" "Matt Brubeck <mbrubeck@limpet.net>" @@ -7501,6 +8442,7 @@ rec { "borsh" = [ "dep:borsh" ]; "bytemuck" = [ "dep:bytemuck" ]; "default" = [ "std" ]; + "num-cmp" = [ "dep:num-cmp" ]; "proptest" = [ "dep:proptest" ]; "rand" = [ "dep:rand" ]; "randtest" = [ "rand/std" "rand/std_rng" ]; @@ -7552,9 +8494,9 @@ rec { }; "parking" = rec { crateName = "parking"; - version = "2.2.0"; + version = "2.2.1"; edition = "2018"; - sha256 = "1blwbkq6im1hfxp5wlbr475mw98rsyc0bbr2d5n16m38z253p0dv"; + sha256 = "1fnfgmzkfpjd69v4j9x737b1k8pnn054bvzcn5dm3pkgq595d3gk"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" "The Rust Project Developers" @@ -7563,44 +8505,11 @@ rec { "loom" = [ "dep:loom" ]; }; }; - "parking_lot 0.11.2" = rec { - crateName = "parking_lot"; - version = "0.11.2"; - edition = "2018"; - sha256 = "16gzf41bxmm10x82bla8d6wfppy9ym3fxsmdjyvn61m66s0bf5vx"; - authors = [ - "Amanieu d'Antras <amanieu@gmail.com>" - ]; - dependencies = [ - { - name = "instant"; - packageId = "instant"; - } - { - name = "lock_api"; - packageId = "lock_api"; - } - { - name = "parking_lot_core"; - packageId = "parking_lot_core 0.8.6"; - } - ]; - features = { - "arc_lock" = [ "lock_api/arc_lock" ]; - "deadlock_detection" = [ "parking_lot_core/deadlock_detection" ]; - "nightly" = [ "parking_lot_core/nightly" "lock_api/nightly" ]; - "owning_ref" = [ "lock_api/owning_ref" ]; - "serde" = [ "lock_api/serde" ]; - "stdweb" = [ "instant/stdweb" ]; - "wasm-bindgen" = [ "instant/wasm-bindgen" ]; - }; - resolvedDefaultFeatures = [ "default" ]; - }; - "parking_lot 0.12.1" = rec { + "parking_lot" = rec { crateName = "parking_lot"; - version = "0.12.1"; - edition = "2018"; - sha256 = "13r2xk7mnxfc5g0g6dkdxqdqad99j7s7z8zhzz4npw5r0g0v4hip"; + version = "0.12.3"; + edition = "2021"; + sha256 = "09ws9g6245iiq8z975h8ycf818a66q3c6zv4b5h8skpm7hc1igzi"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -7611,7 +8520,7 @@ rec { } { name = "parking_lot_core"; - packageId = "parking_lot_core 0.9.9"; + packageId = "parking_lot_core"; } ]; features = { @@ -7623,56 +8532,11 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "parking_lot_core 0.8.6" = rec { + "parking_lot_core" = rec { crateName = "parking_lot_core"; - version = "0.8.6"; - edition = "2018"; - sha256 = "1p2nfcbr0b9lm9rglgm28k6mwyjwgm4knipsmqbgqaxdy3kcz8k0"; - authors = [ - "Amanieu d'Antras <amanieu@gmail.com>" - ]; - dependencies = [ - { - name = "cfg-if"; - packageId = "cfg-if"; - } - { - name = "instant"; - packageId = "instant"; - } - { - name = "libc"; - packageId = "libc"; - target = { target, features }: (target."unix" or false); - } - { - name = "redox_syscall"; - packageId = "redox_syscall 0.2.16"; - target = { target, features }: ("redox" == target."os" or null); - } - { - name = "smallvec"; - packageId = "smallvec"; - } - { - name = "winapi"; - packageId = "winapi"; - target = { target, features }: (target."windows" or false); - features = [ "winnt" "ntstatus" "minwindef" "winerror" "winbase" "errhandlingapi" "handleapi" ]; - } - ]; - features = { - "backtrace" = [ "dep:backtrace" ]; - "deadlock_detection" = [ "petgraph" "thread-id" "backtrace" ]; - "petgraph" = [ "dep:petgraph" ]; - "thread-id" = [ "dep:thread-id" ]; - }; - }; - "parking_lot_core 0.9.9" = rec { - crateName = "parking_lot_core"; - version = "0.9.9"; - edition = "2018"; - sha256 = "13h0imw1aq86wj28gxkblhkzx6z1gk8q18n0v76qmmj6cliajhjc"; + version = "0.9.10"; + edition = "2021"; + sha256 = "1y3cf9ld9ijf7i4igwzffcn0xl16dxyn4c5bwgjck1dkgabiyh0y"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -7688,7 +8552,7 @@ rec { } { name = "redox_syscall"; - packageId = "redox_syscall 0.4.1"; + packageId = "redox_syscall 0.5.7"; target = { target, features }: ("redox" == target."os" or null); } { @@ -7697,7 +8561,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets 0.48.5"; + packageId = "windows-targets 0.52.6"; target = { target, features }: (target."windows" or false); } ]; @@ -7713,6 +8577,7 @@ rec { version = "0.1.0"; edition = "2015"; sha256 = "1pcgqxw0mgg3ha5hi5xkjhyjf488bw5rw1g3qlr9awbq4szh3fpc"; + libName = "path_clean"; authors = [ "Dan Reeves <hey@danreev.es>" ]; @@ -7723,6 +8588,7 @@ rec { version = "2.3.1"; edition = "2018"; sha256 = "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -7734,9 +8600,9 @@ rec { }; "petgraph" = rec { crateName = "petgraph"; - version = "0.6.4"; + version = "0.6.5"; edition = "2018"; - sha256 = "1ac6wfq5f5pzcv0nvzzfgjbwg2kwslpnzsw5wcmxlscfcb9azlz1"; + sha256 = "1ns7mbxidnn2pqahbbjccxkrqkrll2i5rbxx43ns6rh6fn3cridl"; authors = [ "bluss" "mitchmindtree" @@ -7749,13 +8615,14 @@ rec { } { name = "indexmap"; - packageId = "indexmap 2.1.0"; + packageId = "indexmap 2.6.0"; } ]; features = { - "all" = [ "unstable" "quickcheck" "matrix_graph" "stable_graph" "graphmap" ]; + "all" = [ "unstable" "quickcheck" "matrix_graph" "stable_graph" "graphmap" "rayon" ]; "default" = [ "graphmap" "stable_graph" "matrix_graph" ]; "quickcheck" = [ "dep:quickcheck" ]; + "rayon" = [ "dep:rayon" "indexmap/rayon" ]; "serde" = [ "dep:serde" ]; "serde-1" = [ "serde" "serde_derive" ]; "serde_derive" = [ "dep:serde_derive" ]; @@ -7765,9 +8632,10 @@ rec { }; "pin-project" = rec { crateName = "pin-project"; - version = "1.1.3"; + version = "1.1.6"; edition = "2021"; - sha256 = "08k4cpy8q3j93qqgnrbzkcgpn7g0a88l4a9nm33kyghpdhffv97x"; + sha256 = "1v4924b870bss0x5ahww9a164d4dbny90vzkmljfbqfxc6hj7wds"; + libName = "pin_project"; dependencies = [ { name = "pin-project-internal"; @@ -7778,10 +8646,11 @@ rec { }; "pin-project-internal" = rec { crateName = "pin-project-internal"; - version = "1.1.3"; + version = "1.1.6"; edition = "2021"; - sha256 = "01a4l3vb84brv9v7wl71chzxra2kynm6yvcjca66xv3ij6fgsna3"; + sha256 = "1y2pjavbcq40njylbnw3929i8nnrcdzrhgalzgqk57ya2n2jsl54"; procMacro = true; + libName = "pin_project_internal"; dependencies = [ { name = "proc-macro2"; @@ -7793,17 +8662,19 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; - features = [ "full" "visit-mut" ]; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "parsing" "printing" "clone-impls" "proc-macro" "full" "visit-mut" ]; } ]; }; "pin-project-lite" = rec { crateName = "pin-project-lite"; - version = "0.2.13"; + version = "0.2.14"; edition = "2018"; - sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + sha256 = "00nx3f04agwjlsmd3mc5rx5haibj2v8q9b52b0kwn63wcv4nz9mx"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -7811,6 +8682,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -7818,9 +8690,9 @@ rec { }; "piper" = rec { crateName = "piper"; - version = "0.2.1"; + version = "0.2.4"; edition = "2018"; - sha256 = "1m45fkdq7q5l9mv3b0ra10qwm0kb67rjp2q8y91958gbqjqk33b6"; + sha256 = "0rn0mjjm0cwagdkay77wgmz3sqf8fqmv9d9czm79mvr2yj8c9j4n"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" "John Nunley <dev@notgull.net>" @@ -7887,34 +8759,20 @@ rec { }; "pkg-config" = rec { crateName = "pkg-config"; - version = "0.3.29"; - edition = "2015"; - sha256 = "1jy6158v1316khkpmq2sjj1vgbnbnw51wffx7p0k0l9h9vlys019"; + version = "0.3.31"; + edition = "2018"; + sha256 = "1wk6yp2phl91795ia0lwkr3wl4a9xkrympvhqq8cxk4d75hwhglm"; + libName = "pkg_config"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; }; - "platforms" = rec { - crateName = "platforms"; - version = "3.3.0"; - edition = "2018"; - sha256 = "0k7q6pigmnvgpfasvssb12m2pv3pc94zrhrfg9by3h3wmhyfqvb2"; - authors = [ - "Tony Arcieri <bascule@gmail.com>" - "Sergey \"Shnatsel\" Davidoff <shnatsel@gmail.com>" - ]; - features = { - "default" = [ "std" ]; - "serde" = [ "dep:serde" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "plotters" = rec { crateName = "plotters"; - version = "0.3.5"; + version = "0.3.7"; edition = "2018"; - sha256 = "0igxq58bx96gz58pqls6g3h80plf17rfl3b6bi6xvjnp02x29hnj"; + sha256 = "0ixpy9svpmr2rkzkxvvdpysjjky4gw104d73n7pi2jbs7m06zsss"; authors = [ "Hao Hou <haohou302@gmail.com>" ]; @@ -7972,9 +8830,10 @@ rec { }; "plotters-backend" = rec { crateName = "plotters-backend"; - version = "0.3.5"; + version = "0.3.7"; edition = "2018"; - sha256 = "02cn98gsj2i1bwrfsymifmyas1wn2gibdm9mk8w82x9s9n5n4xly"; + sha256 = "0ahpliim4hrrf7d4ispc2hwr7rzkn6d6nf7lyyrid2lm28yf2hnz"; + libName = "plotters_backend"; authors = [ "Hao Hou <haohou302@gmail.com>" ]; @@ -7982,9 +8841,10 @@ rec { }; "plotters-svg" = rec { crateName = "plotters-svg"; - version = "0.3.5"; + version = "0.3.7"; edition = "2018"; - sha256 = "1axbw82frs5di4drbyzihr5j35wpy2a75hp3f49p186cjfcd7xiq"; + sha256 = "0w56sxaa2crpasa1zj0bhxzihlapqfkncggavyngg0w86anf5fji"; + libName = "plotters_svg"; authors = [ "Hao Hou <haohou302@gmail.com>" ]; @@ -8001,9 +8861,9 @@ rec { }; "polling" = rec { crateName = "polling"; - version = "3.4.0"; + version = "3.7.3"; edition = "2021"; - sha256 = "052am20b5r03nwhpnjw86rv3dwsdabvb07anv3fqxfbs65r4w19h"; + sha256 = "04b5zdgz0m9ydbzcr3f9a55749gqbj0y89d0nz9nrv0x636r09yc"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" "John Nunley <dev@notgull.net>" @@ -8019,6 +8879,11 @@ rec { target = { target, features }: (target."windows" or false); } { + name = "hermit-abi"; + packageId = "hermit-abi 0.4.0"; + target = { target, features }: ("hermit" == target."os" or null); + } + { name = "pin-project-lite"; packageId = "pin-project-lite"; target = { target, features }: (target."windows" or false); @@ -8037,13 +8902,26 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; + packageId = "windows-sys 0.59.0"; target = { target, features }: (target."windows" or false); features = [ "Wdk_Foundation" "Wdk_Storage_FileSystem" "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_LibraryLoader" "Win32_System_Threading" "Win32_System_WindowsProgramming" ]; } ]; }; + "portable-atomic" = rec { + crateName = "portable-atomic"; + version = "1.9.0"; + edition = "2018"; + sha256 = "1cmd87qj90panwsi350djb8lsxdryqkkxmimjcz7a1nsysini76c"; + libName = "portable_atomic"; + features = { + "critical-section" = [ "dep:critical-section" ]; + "default" = [ "fallback" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "fallback" ]; + }; "powerfmt" = rec { crateName = "powerfmt"; version = "0.2.0"; @@ -8060,12 +8938,20 @@ rec { }; "ppv-lite86" = rec { crateName = "ppv-lite86"; - version = "0.2.17"; - edition = "2018"; - sha256 = "1pp6g52aw970adv3x2310n7glqnji96z0a9wiamzw89ibf0ayh2v"; + version = "0.2.20"; + edition = "2021"; + sha256 = "017ax9ssdnpww7nrl1hvqh2lzncpv04nnsibmnw9nxjnaqlpp5bp"; + libName = "ppv_lite86"; authors = [ "The CryptoCorrosion Contributors" ]; + dependencies = [ + { + name = "zerocopy"; + packageId = "zerocopy"; + features = [ "simd" "derive" ]; + } + ]; features = { "default" = [ "std" ]; }; @@ -8073,9 +8959,9 @@ rec { }; "pretty_assertions" = rec { crateName = "pretty_assertions"; - version = "1.4.0"; + version = "1.4.1"; edition = "2018"; - sha256 = "0rmsnqlpmpfjp5gyi31xgc48kdhc1kqn246bnc494nwadhdfwz5g"; + sha256 = "0v8iq35ca4rw3rza5is3wjxwsf88303ivys07anc5yviybi31q9s"; authors = [ "Colin Kiegel <kiegel@gmx.de>" "Florent Fayolle <florent.fayolle69@gmail.com>" @@ -8098,10 +8984,10 @@ rec { }; "prettyplease" = rec { crateName = "prettyplease"; - version = "0.2.16"; + version = "0.2.22"; edition = "2021"; links = "prettyplease02"; - sha256 = "1dfbq98rkq86l9g8w1l81bdvrz4spcfl48929n0pyz79clhzc754"; + sha256 = "1fpsyn4x1scbp8ik8xw4pfh4jxfm5bv7clax5k1jcd5vzd0gk727"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -8113,7 +8999,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; usesDefaultFeatures = false; features = [ "full" ]; } @@ -8126,7 +9012,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; usesDefaultFeatures = false; features = [ "parsing" ]; } @@ -8135,11 +9021,78 @@ rec { "verbatim" = [ "syn/parsing" ]; }; }; + "proc-macro-error-attr2" = rec { + crateName = "proc-macro-error-attr2"; + version = "2.0.0"; + edition = "2021"; + sha256 = "1ifzi763l7swl258d8ar4wbpxj4c9c2im7zy89avm6xv6vgl5pln"; + procMacro = true; + libName = "proc_macro_error_attr2"; + authors = [ + "CreepySkeleton <creepy-skeleton@yandex.ru>" + "GnomedDev <david2005thomas@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + ]; + + }; + "proc-macro-error2" = rec { + crateName = "proc-macro-error2"; + version = "2.0.1"; + edition = "2021"; + sha256 = "00lq21vgh7mvyx51nwxwf822w2fpww1x0z8z0q47p8705g2hbv0i"; + libName = "proc_macro_error2"; + authors = [ + "CreepySkeleton <creepy-skeleton@yandex.ru>" + "GnomedDev <david2005thomas@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro-error-attr2"; + packageId = "proc-macro-error-attr2"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + optional = true; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" ]; + } + ]; + features = { + "default" = [ "syn-error" ]; + "syn-error" = [ "dep:syn" ]; + }; + resolvedDefaultFeatures = [ "default" "syn-error" ]; + }; "proc-macro2" = rec { crateName = "proc-macro2"; - version = "1.0.76"; + version = "1.0.87"; edition = "2021"; - sha256 = "136cp0fgl6rg5ljm3b1xpc0bn0lyvagzzmxvbxgk5hxml36mdz4m"; + sha256 = "16mifsq1nqzk81qm82aszib44jsd23gpqic5z4kbmzpnvjhdmr5k"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -8157,26 +9110,16 @@ rec { }; "proptest" = rec { crateName = "proptest"; - version = "1.4.0"; + version = "1.5.0"; edition = "2018"; - sha256 = "1gzmw40pgmwzb7x6jsyr88z5w151snv5rp1g0dlcp1iw3h9pdd1i"; + sha256 = "13gm7mphs95cw4gbgk5qiczkmr68dvcwhp58gmiz33dq2ccm3hml"; authors = [ "Jason Lingle" ]; dependencies = [ { - name = "bit-set"; - packageId = "bit-set"; - optional = true; - } - { - name = "bit-vec"; - packageId = "bit-vec"; - optional = true; - } - { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "lazy_static"; @@ -8206,16 +9149,10 @@ rec { } { name = "regex-syntax"; - packageId = "regex-syntax 0.8.2"; + packageId = "regex-syntax 0.8.5"; optional = true; } { - name = "rusty-fork"; - packageId = "rusty-fork"; - optional = true; - usesDefaultFeatures = false; - } - { name = "tempfile"; packageId = "tempfile"; optional = true; @@ -8226,12 +9163,14 @@ rec { } ]; features = { + "attr-macro" = [ "proptest-macro" ]; "bit-set" = [ "dep:bit-set" "dep:bit-vec" ]; "default" = [ "std" "fork" "timeout" "bit-set" ]; "default-code-coverage" = [ "std" "fork" "timeout" "bit-set" ]; "fork" = [ "std" "rusty-fork" "tempfile" ]; "hardware-rng" = [ "x86" ]; "lazy_static" = [ "dep:lazy_static" ]; + "proptest-macro" = [ "dep:proptest-macro" ]; "regex-syntax" = [ "dep:regex-syntax" ]; "rusty-fork" = [ "dep:rusty-fork" ]; "std" = [ "rand/std" "lazy_static" "regex-syntax" "num-traits/std" ]; @@ -8239,44 +9178,17 @@ rec { "timeout" = [ "fork" "rusty-fork/timeout" ]; "x86" = [ "dep:x86" ]; }; - resolvedDefaultFeatures = [ "alloc" "bit-set" "default" "fork" "lazy_static" "regex-syntax" "rusty-fork" "std" "tempfile" "timeout" ]; - }; - "prost 0.11.9" = rec { - crateName = "prost"; - version = "0.11.9"; - edition = "2021"; - sha256 = "1kc1hva2h894hc0zf6r4r8fsxfpazf7xn5rj3jya9sbrsyhym0hb"; - authors = [ - "Dan Burkert <dan@danburkert.com>" - "Lucio Franco <luciofranco14@gmail.com" - "Tokio Contributors <team@tokio.rs>" - ]; - dependencies = [ - { - name = "bytes"; - packageId = "bytes"; - usesDefaultFeatures = false; - } - { - name = "prost-derive"; - packageId = "prost-derive 0.11.9"; - optional = true; - } - ]; - features = { - "default" = [ "prost-derive" "std" ]; - "prost-derive" = [ "dep:prost-derive" ]; - }; - resolvedDefaultFeatures = [ "default" "prost-derive" "std" ]; + resolvedDefaultFeatures = [ "alloc" "lazy_static" "regex-syntax" "std" "tempfile" ]; }; - "prost 0.12.3" = rec { + "prost" = rec { crateName = "prost"; - version = "0.12.3"; + version = "0.13.3"; edition = "2021"; - sha256 = "0jmrhlb4jkiylz72xb14vlkfbmlq0jwv7j20ini9harhvaf2hv0l"; + sha256 = "0gx1kbvgnws59ggv1mda15bc00f6hlxp24s9k1zyhz841vcqf13v"; authors = [ "Dan Burkert <dan@danburkert.com>" - "Lucio Franco <luciofranco14@gmail.com" + "Lucio Franco <luciofranco14@gmail.com>" + "Casper Meijn <casper@meijn.net>" "Tokio Contributors <team@tokio.rs>" ]; dependencies = [ @@ -8287,24 +9199,27 @@ rec { } { name = "prost-derive"; - packageId = "prost-derive 0.12.3"; + packageId = "prost-derive"; optional = true; } ]; features = { - "default" = [ "prost-derive" "std" ]; - "prost-derive" = [ "dep:prost-derive" ]; + "default" = [ "derive" "std" ]; + "derive" = [ "dep:prost-derive" ]; + "prost-derive" = [ "derive" ]; }; - resolvedDefaultFeatures = [ "default" "prost-derive" "std" ]; + resolvedDefaultFeatures = [ "default" "derive" "prost-derive" "std" ]; }; "prost-build" = rec { crateName = "prost-build"; - version = "0.12.3"; + version = "0.13.3"; edition = "2021"; - sha256 = "1lp2l1l65l163yggk9nw5mjb2fqwzz12693af5phn1v0abih4pn5"; + sha256 = "05dyk9fzyl05p2chjb88kj7qbxxvadc469k9060qdw45j2qih4qc"; + libName = "prost_build"; authors = [ "Dan Burkert <dan@danburkert.com>" "Lucio Franco <luciofranco14@gmail.com>" + "Casper Meijn <casper@meijn.net>" "Tokio Contributors <team@tokio.rs>" ]; dependencies = [ @@ -8315,11 +9230,11 @@ rec { } { name = "heck"; - packageId = "heck"; + packageId = "heck 0.5.0"; } { name = "itertools"; - packageId = "itertools 0.11.0"; + packageId = "itertools 0.13.0"; usesDefaultFeatures = false; features = [ "use_alloc" ]; } @@ -8348,7 +9263,7 @@ rec { } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; usesDefaultFeatures = false; } { @@ -8375,7 +9290,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; optional = true; features = [ "full" ]; } @@ -8383,69 +9298,25 @@ rec { name = "tempfile"; packageId = "tempfile"; } - { - name = "which"; - packageId = "which 4.4.2"; - } ]; features = { - "cleanup-markdown" = [ "pulldown-cmark" "pulldown-cmark-to-cmark" ]; + "cleanup-markdown" = [ "dep:pulldown-cmark" "dep:pulldown-cmark-to-cmark" ]; "default" = [ "format" ]; - "format" = [ "prettyplease" "syn" ]; - "prettyplease" = [ "dep:prettyplease" ]; - "pulldown-cmark" = [ "dep:pulldown-cmark" ]; - "pulldown-cmark-to-cmark" = [ "dep:pulldown-cmark-to-cmark" ]; - "syn" = [ "dep:syn" ]; + "format" = [ "dep:prettyplease" "dep:syn" ]; }; - resolvedDefaultFeatures = [ "cleanup-markdown" "default" "format" "prettyplease" "pulldown-cmark" "pulldown-cmark-to-cmark" "syn" ]; - }; - "prost-derive 0.11.9" = rec { - crateName = "prost-derive"; - version = "0.11.9"; - edition = "2021"; - sha256 = "1d3mw2s2jba1f7wcjmjd6ha2a255p2rmynxhm1nysv9w1z8xilp5"; - procMacro = true; - authors = [ - "Dan Burkert <dan@danburkert.com>" - "Lucio Franco <luciofranco14@gmail.com>" - "Tokio Contributors <team@tokio.rs>" - ]; - dependencies = [ - { - name = "anyhow"; - packageId = "anyhow"; - } - { - name = "itertools"; - packageId = "itertools 0.10.5"; - usesDefaultFeatures = false; - features = [ "use_alloc" ]; - } - { - name = "proc-macro2"; - packageId = "proc-macro2"; - } - { - name = "quote"; - packageId = "quote"; - } - { - name = "syn"; - packageId = "syn 1.0.109"; - features = [ "extra-traits" ]; - } - ]; - + resolvedDefaultFeatures = [ "cleanup-markdown" "default" "format" ]; }; - "prost-derive 0.12.3" = rec { + "prost-derive" = rec { crateName = "prost-derive"; - version = "0.12.3"; + version = "0.13.3"; edition = "2021"; - sha256 = "03l4yf6pdjvc4sgbvln2srq1avzm1ai86zni4hhqxvqxvnhwkdpg"; + sha256 = "1i9wh2q5rly0lwsmxq5svwyk4adcb5j31gyhwjj682az1n2jymg9"; procMacro = true; + libName = "prost_derive"; authors = [ "Dan Burkert <dan@danburkert.com>" "Lucio Franco <luciofranco14@gmail.com>" + "Casper Meijn <casper@meijn.net>" "Tokio Contributors <team@tokio.rs>" ]; dependencies = [ @@ -8455,9 +9326,7 @@ rec { } { name = "itertools"; - packageId = "itertools 0.11.0"; - usesDefaultFeatures = false; - features = [ "use_alloc" ]; + packageId = "itertools 0.13.0"; } { name = "proc-macro2"; @@ -8469,7 +9338,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "extra-traits" ]; } ]; @@ -8477,18 +9346,20 @@ rec { }; "prost-types" = rec { crateName = "prost-types"; - version = "0.12.3"; + version = "0.13.3"; edition = "2021"; - sha256 = "03j73llzljdxv9cdxp4m3vb9j3gh4y24rkbx48k3rx6wkvsrhf0r"; + sha256 = "0w6n122pi7fsfvnwfcm9mil7q1105kg62yxrpn6znck2786slna7"; + libName = "prost_types"; authors = [ "Dan Burkert <dan@danburkert.com>" - "Lucio Franco <luciofranco14@gmail.com" + "Lucio Franco <luciofranco14@gmail.com>" + "Casper Meijn <casper@meijn.net>" "Tokio Contributors <team@tokio.rs>" ]; dependencies = [ { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; usesDefaultFeatures = false; features = [ "prost-derive" ]; } @@ -8501,9 +9372,10 @@ rec { }; "prost-wkt" = rec { crateName = "prost-wkt"; - version = "0.5.0"; + version = "0.6.0"; edition = "2021"; - sha256 = "0h3c0jyfpg7f3s9a3mx6xcif28j3ir5c5qmps88bknpiy31zk3jd"; + sha256 = "16c2mbaq2hff51kwr204fncnmi0qx2zz4ff3pb1086qqxqmlxn58"; + libName = "prost_wkt"; authors = [ "fdeantoni <fdeantoni@gmail.com>" ]; @@ -8520,7 +9392,7 @@ rec { } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; } { name = "serde"; @@ -8543,20 +9415,21 @@ rec { }; "prost-wkt-build" = rec { crateName = "prost-wkt-build"; - version = "0.5.0"; + version = "0.6.0"; edition = "2021"; - sha256 = "0883g26vrhx07kv0dq85559pj95zxs10lx042pp4za2clplwlcav"; + sha256 = "054v5qqvdv29g5s1kr26zv0yvzc8gmnlx9k2dw6026g7rdd9srla"; + libName = "prost_wkt_build"; authors = [ "fdeantoni <fdeantoni@gmail.com>" ]; dependencies = [ { name = "heck"; - packageId = "heck"; + packageId = "heck 0.5.0"; } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; } { name = "prost-build"; @@ -8575,9 +9448,10 @@ rec { }; "prost-wkt-types" = rec { crateName = "prost-wkt-types"; - version = "0.5.0"; + version = "0.6.0"; edition = "2021"; - sha256 = "1vipmgvqqzr3hn9z5v85mx9zznzjwyfpjy8xzg2v94a0f2lf8ns3"; + sha256 = "0r2gxf5b604b00v1fwif1rn5nm5xk4vb3ri29dhm9rl2kf70dvq1"; + libName = "prost_wkt_types"; authors = [ "fdeantoni <fdeantoni@gmail.com>" ]; @@ -8590,7 +9464,7 @@ rec { } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; } { name = "prost-wkt"; @@ -8612,7 +9486,7 @@ rec { buildDependencies = [ { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; } { name = "prost-build"; @@ -8642,10 +9516,11 @@ rec { }; "pulldown-cmark" = rec { crateName = "pulldown-cmark"; - version = "0.9.6"; + version = "0.12.1"; edition = "2021"; crateBin = [ ]; - sha256 = "0av876a31qvqhy7gzdg134zn4s10smlyi744mz9vrllkf906n82p"; + sha256 = "176mj0w1zm6yrsqihg6c6l4phyl71462j4k05vbs5bjrw9chyvv6"; + libName = "pulldown_cmark"; authors = [ "Raph Levien <raph.levien@gmail.com>" "Marcus Klaas de Vries <mail@marcusklaas.nl>" @@ -8653,7 +9528,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "memchr"; @@ -8665,16 +9540,20 @@ rec { } ]; features = { - "default" = [ "getopts" ]; + "default" = [ "getopts" "html" ]; "getopts" = [ "dep:getopts" ]; + "html" = [ "pulldown-cmark-escape" ]; + "pulldown-cmark-escape" = [ "dep:pulldown-cmark-escape" ]; "serde" = [ "dep:serde" ]; + "simd" = [ "pulldown-cmark-escape?/simd" ]; }; }; "pulldown-cmark-to-cmark" = rec { crateName = "pulldown-cmark-to-cmark"; - version = "10.0.4"; + version = "17.0.0"; edition = "2018"; - sha256 = "0gc366cmd5jxal9m95l17rvqsm4dn62lywc8v5gwq8vcjvhyd501"; + sha256 = "02aig88lva5zirams5a8vrj5d7j1fcfr21sh10zgyq2x6q6prcj1"; + libName = "pulldown_cmark_to_cmark"; authors = [ "Sebastian Thiel <byronimo@gmail.com>" "Dylan Owen <dyltotheo@gmail.com>" @@ -8690,22 +9569,12 @@ rec { ]; }; - "quick-error" = rec { - crateName = "quick-error"; - version = "1.2.3"; - edition = "2015"; - sha256 = "1q6za3v78hsspisc197bg3g7rpc989qycy8ypr8ap8igv10ikl51"; - authors = [ - "Paul Colomiets <paul@colomiets.name>" - "Colin Kiegel <kiegel@gmx.de>" - ]; - - }; "quick-xml" = rec { crateName = "quick-xml"; - version = "0.31.0"; + version = "0.36.2"; edition = "2021"; - sha256 = "0cravqanylzh5cq2v6hzlfqgxcid5nrp2snnb3pf4m0and2a610h"; + sha256 = "1zj3sjcjk6sn544wb2wvhr1km5f9cy664vzclygfsnph9mxrlr7p"; + libName = "quick_xml"; dependencies = [ { name = "memchr"; @@ -8730,11 +9599,195 @@ rec { }; resolvedDefaultFeatures = [ "default" "overlapped-lists" "serde" "serialize" ]; }; + "quinn" = rec { + crateName = "quinn"; + version = "0.11.5"; + edition = "2021"; + sha256 = "1146h9wkn5bb8l1mllnw7s1hkvg0iykg1i3x881p5bndwgfmyz4c"; + dependencies = [ + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "quinn-proto"; + packageId = "quinn-proto"; + rename = "proto"; + usesDefaultFeatures = false; + } + { + name = "quinn-udp"; + packageId = "quinn-udp"; + rename = "udp"; + usesDefaultFeatures = false; + features = [ "tracing" ]; + } + { + name = "rustc-hash"; + packageId = "rustc-hash 2.0.0"; + } + { + name = "rustls"; + packageId = "rustls"; + optional = true; + usesDefaultFeatures = false; + features = [ "ring" "std" ]; + } + { + name = "socket2"; + packageId = "socket2"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "sync" ]; + } + { + name = "tracing"; + packageId = "tracing"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + ]; + devDependencies = [ + { + name = "tokio"; + packageId = "tokio"; + features = [ "sync" "rt" "rt-multi-thread" "time" "macros" ]; + } + ]; + features = { + "async-io" = [ "dep:async-io" ]; + "async-std" = [ "dep:async-std" ]; + "default" = [ "log" "platform-verifier" "ring" "runtime-tokio" "rustls" ]; + "futures-io" = [ "dep:futures-io" ]; + "log" = [ "tracing/log" "proto/log" "udp/log" ]; + "platform-verifier" = [ "proto/platform-verifier" ]; + "ring" = [ "proto/ring" ]; + "runtime-async-std" = [ "async-io" "async-std" ]; + "runtime-smol" = [ "async-io" "smol" ]; + "runtime-tokio" = [ "tokio/time" "tokio/rt" "tokio/net" ]; + "rustls" = [ "dep:rustls" "proto/rustls" "proto/ring" ]; + "smol" = [ "dep:smol" ]; + }; + resolvedDefaultFeatures = [ "ring" "runtime-tokio" "rustls" ]; + }; + "quinn-proto" = rec { + crateName = "quinn-proto"; + version = "0.11.8"; + edition = "2021"; + sha256 = "19m4219ybsma7kkz79j721lzhy3vgfqfwwxvc40rsf3zrp9axpzs"; + libName = "quinn_proto"; + dependencies = [ + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "rand"; + packageId = "rand"; + } + { + name = "ring"; + packageId = "ring"; + optional = true; + } + { + name = "rustc-hash"; + packageId = "rustc-hash 2.0.0"; + } + { + name = "rustls"; + packageId = "rustls"; + optional = true; + usesDefaultFeatures = false; + features = [ "ring" "std" ]; + } + { + name = "slab"; + packageId = "slab"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "tinyvec"; + packageId = "tinyvec"; + features = [ "alloc" "alloc" ]; + } + { + name = "tracing"; + packageId = "tracing"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "default" = [ "rustls" "log" ]; + "log" = [ "tracing/log" ]; + "platform-verifier" = [ "dep:rustls-platform-verifier" ]; + "ring" = [ "dep:ring" ]; + "rustls" = [ "dep:rustls" "ring" ]; + }; + resolvedDefaultFeatures = [ "ring" "rustls" ]; + }; + "quinn-udp" = rec { + crateName = "quinn-udp"; + version = "0.5.5"; + edition = "2021"; + sha256 = "02qlqjsbmfgwin9jpb652d0hkjyzz7wvsgb833i384hskqp8rrjg"; + libName = "quinn_udp"; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + { + name = "once_cell"; + packageId = "once_cell"; + target = { target, features }: (target."windows" or false); + } + { + name = "socket2"; + packageId = "socket2"; + } + { + name = "tracing"; + packageId = "tracing"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "windows-sys"; + packageId = "windows-sys 0.59.0"; + target = { target, features }: (target."windows" or false); + features = [ "Win32_Foundation" "Win32_System_IO" "Win32_Networking_WinSock" ]; + } + ]; + features = { + "default" = [ "tracing" "log" ]; + "direct-log" = [ "dep:log" ]; + "log" = [ "tracing/log" ]; + "tracing" = [ "dep:tracing" ]; + }; + resolvedDefaultFeatures = [ "tracing" ]; + }; "quote" = rec { crateName = "quote"; - version = "1.0.35"; + version = "1.0.37"; edition = "2018"; - sha256 = "1vv8r2ncaz4pqdr78x7f138ka595sp2ncr1sa2plm4zxbsmwj7i9"; + sha256 = "1brklraw2g34bxy9y4q1nbrccn7bv36ylihv12c9vlcii55x7fdm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -8891,30 +9944,11 @@ rec { "serde1" = [ "serde" ]; }; }; - "rand_xoshiro" = rec { - crateName = "rand_xoshiro"; - version = "0.6.0"; - edition = "2018"; - sha256 = "1ajsic84rzwz5qr0mzlay8vi17swqi684bqvwqyiim3flfrcv5vg"; - authors = [ - "The Rand Project Developers" - ]; - dependencies = [ - { - name = "rand_core"; - packageId = "rand_core"; - } - ]; - features = { - "serde" = [ "dep:serde" ]; - "serde1" = [ "serde" ]; - }; - }; "rayon" = rec { crateName = "rayon"; - version = "1.8.1"; + version = "1.10.0"; edition = "2021"; - sha256 = "0lg0488xwpj5jsfz2gfczcrpclbjl8221mj5vdrhg8bp3883fwps"; + sha256 = "1ylgnzwgllajalr4v00y4kj22klq2jbwllm70aha232iah0sc65l"; authors = [ "Niko Matsakis <niko@alum.mit.edu>" "Josh Stone <cuviper@gmail.com>" @@ -8940,6 +9974,7 @@ rec { edition = "2021"; links = "rayon-core"; sha256 = "1qpwim68ai5h0j7axa8ai8z0payaawv3id0lrgkqmapx7lx8fr8l"; + libName = "rayon_core"; authors = [ "Niko Matsakis <niko@alum.mit.edu>" "Josh Stone <cuviper@gmail.com>" @@ -8958,22 +9993,38 @@ rec { "web_spin_lock" = [ "dep:wasm_sync" ]; }; }; - "redox_syscall 0.2.16" = rec { - crateName = "redox_syscall"; - version = "0.2.16"; - edition = "2018"; - sha256 = "16jicm96kjyzm802cxdd1k9jmcph0db1a4lhslcnhjsvhp0mhnpv"; - libName = "syscall"; + "redb" = rec { + crateName = "redb"; + version = "2.1.4"; + edition = "2021"; + sha256 = "0aix1h2p5bmw8lxfznnk4a3bwiyv58ii55fi863pvlp5wzrp6hq7"; + type = [ "cdylib" "rlib" ]; authors = [ - "Jeremy Soller <jackpot51@gmail.com>" + "Christopher Berner <me@cberner.com>" ]; dependencies = [ { - name = "bitflags"; - packageId = "bitflags 1.3.2"; + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "log"; + packageId = "log"; + optional = true; } ]; - + devDependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + features = { + "logging" = [ "dep:log" ]; + "python" = [ "dep:pyo3" "dep:pyo3-build-config" ]; + }; + resolvedDefaultFeatures = [ "logging" ]; }; "redox_syscall 0.3.5" = rec { crateName = "redox_syscall"; @@ -8995,11 +10046,11 @@ rec { "rustc-dep-of-std" = [ "core" "bitflags/rustc-dep-of-std" ]; }; }; - "redox_syscall 0.4.1" = rec { + "redox_syscall 0.5.7" = rec { crateName = "redox_syscall"; - version = "0.4.1"; - edition = "2018"; - sha256 = "1aiifyz5dnybfvkk4cdab9p2kmphag1yad6iknc7aszlxxldf8j7"; + version = "0.5.7"; + edition = "2021"; + sha256 = "07vpgfr6a04k0x19zqr1xdlqm6fncik3zydbdi3f5g3l5k7zwvcv"; libName = "syscall"; authors = [ "Jeremy Soller <jackpot51@gmail.com>" @@ -9007,19 +10058,21 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 1.3.2"; + packageId = "bitflags 2.6.0"; } ]; features = { "core" = [ "dep:core" ]; + "default" = [ "userspace" ]; "rustc-dep-of-std" = [ "core" "bitflags/rustc-dep-of-std" ]; }; + resolvedDefaultFeatures = [ "default" "userspace" ]; }; "redox_users" = rec { crateName = "redox_users"; - version = "0.4.4"; + version = "0.4.6"; edition = "2021"; - sha256 = "1d1c7dhbb62sh8jrq9dhvqcyxqsh3wg8qknsi94iwq3r0wh7k151"; + sha256 = "0hya2cxx6hxmjfxzv9n8rjl5igpychav7zfi1f81pz6i4krry05s"; authors = [ "Jose Narvaez <goyox86@gmail.com>" "Wesley Hershberger <mggmugginsmc@gmail.com>" @@ -9034,7 +10087,7 @@ rec { name = "libredox"; packageId = "libredox"; usesDefaultFeatures = false; - features = [ "call" ]; + features = [ "std" "call" ]; } { name = "thiserror"; @@ -9050,9 +10103,9 @@ rec { }; "regex" = rec { crateName = "regex"; - version = "1.10.2"; + version = "1.10.6"; edition = "2021"; - sha256 = "0hxkd814n4irind8im5c9am221ri6bprx49nc7yxv02ykhd9a2rq"; + sha256 = "06cnlxwzyqfbw1za1i7ks89ns4i2kr0lpg5ykx56b8v7dd6df6a2"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -9062,21 +10115,23 @@ rec { name = "aho-corasick"; packageId = "aho-corasick"; optional = true; + usesDefaultFeatures = false; } { name = "memchr"; packageId = "memchr"; optional = true; + usesDefaultFeatures = false; } { name = "regex-automata"; - packageId = "regex-automata 0.4.3"; + packageId = "regex-automata 0.4.8"; usesDefaultFeatures = false; features = [ "alloc" "syntax" "meta" "nfa-pikevm" ]; } { name = "regex-syntax"; - packageId = "regex-syntax 0.8.2"; + packageId = "regex-syntax 0.8.5"; usesDefaultFeatures = false; } ]; @@ -9109,6 +10164,7 @@ rec { version = "0.1.10"; edition = "2015"; sha256 = "0ci1hvbzhrfby5fdpf4ganhf7kla58acad9i1ff1p34dzdrhs8vc"; + libName = "regex_automata"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -9128,11 +10184,12 @@ rec { }; resolvedDefaultFeatures = [ "default" "regex-syntax" "std" ]; }; - "regex-automata 0.4.3" = rec { + "regex-automata 0.4.8" = rec { crateName = "regex-automata"; - version = "0.4.3"; + version = "0.4.8"; edition = "2021"; - sha256 = "0gs8q9yhd3kcg4pr00ag4viqxnh5l7jpyb9fsfr8hzh451w4r02z"; + sha256 = "18wd530ndrmygi6xnz3sp345qi0hy2kdbsa89182nwbl6br5i1rn"; + libName = "regex_automata"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -9152,7 +10209,7 @@ rec { } { name = "regex-syntax"; - packageId = "regex-syntax 0.8.2"; + packageId = "regex-syntax 0.8.5"; optional = true; usesDefaultFeatures = false; } @@ -9193,6 +10250,7 @@ rec { version = "0.6.29"; edition = "2018"; sha256 = "1qgj49vm6y3zn1hi09x91jvgkl2b1fiaq402skj83280ggfwcqpi"; + libName = "regex_syntax"; authors = [ "The Rust Project Developers" ]; @@ -9202,11 +10260,12 @@ rec { }; resolvedDefaultFeatures = [ "default" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; }; - "regex-syntax 0.8.2" = rec { + "regex-syntax 0.8.5" = rec { crateName = "regex-syntax"; - version = "0.8.2"; + version = "0.8.5"; edition = "2021"; - sha256 = "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360"; + sha256 = "0p41p3hj9ww7blnbwbj9h7rwxzxg0c1hvrdycgys8rxyhqqw859b"; + libName = "regex_syntax"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -9220,9 +10279,10 @@ rec { }; "relative-path" = rec { crateName = "relative-path"; - version = "1.9.2"; + version = "1.9.3"; edition = "2021"; - sha256 = "1g0gc604zwm73gvpcicn8si25j9j5agqz50r0x1bkmgx6f7mi678"; + sha256 = "1limlh8fzwi21g0473fqzd6fln9iqkwvzp3816bxi31pkilz6fds"; + libName = "relative_path"; authors = [ "John-John Tedro <udoprog@tedro.se>" ]; @@ -9233,27 +10293,22 @@ rec { }; "reqwest" = rec { crateName = "reqwest"; - version = "0.11.23"; - edition = "2018"; - sha256 = "0hgvzb7r46656r9vqhl5qk1kbr2xzjb91yr2cb321160ka6sxc9p"; + version = "0.12.8"; + edition = "2021"; + sha256 = "0yra0j7fa0f99psrx5nfbdicc14cwk4vhwrc7591wdljprzi84zp"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; dependencies = [ { name = "base64"; - packageId = "base64"; + packageId = "base64 0.22.1"; } { name = "bytes"; packageId = "bytes"; } { - name = "encoding_rs"; - packageId = "encoding_rs"; - target = { target, features }: (!("wasm32" == target."arch" or null)); - } - { name = "futures-core"; packageId = "futures-core"; usesDefaultFeatures = false; @@ -9265,24 +10320,29 @@ rec { } { name = "h2"; - packageId = "h2 0.3.24"; + packageId = "h2"; + optional = true; target = { target, features }: (!("wasm32" == target."arch" or null)); } { name = "http"; - packageId = "http 0.2.11"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 0.4.6"; + packageId = "http-body"; + target = { target, features }: (!("wasm32" == target."arch" or null)); + } + { + name = "http-body-util"; + packageId = "http-body-util"; target = { target, features }: (!("wasm32" == target."arch" or null)); } { name = "hyper"; - packageId = "hyper 0.14.28"; - usesDefaultFeatures = false; + packageId = "hyper"; target = { target, features }: (!("wasm32" == target."arch" or null)); - features = [ "tcp" "http1" "http2" "client" "runtime" ]; + features = [ "http1" "client" ]; } { name = "hyper-rustls"; @@ -9290,6 +10350,13 @@ rec { optional = true; usesDefaultFeatures = false; target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "http1" "tls12" ]; + } + { + name = "hyper-util"; + packageId = "hyper-util"; + target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "http1" "client" "client-legacy" "tokio" ]; } { name = "ipnet"; @@ -9327,23 +10394,39 @@ rec { target = { target, features }: (!("wasm32" == target."arch" or null)); } { + name = "quinn"; + packageId = "quinn"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "rustls" "runtime-tokio" ]; + } + { name = "rustls"; - packageId = "rustls 0.21.10"; + packageId = "rustls"; optional = true; + usesDefaultFeatures = false; target = { target, features }: (!("wasm32" == target."arch" or null)); - features = [ "dangerous_configuration" ]; + features = [ "std" "tls12" ]; } { name = "rustls-native-certs"; - packageId = "rustls-native-certs 0.6.3"; + packageId = "rustls-native-certs"; optional = true; target = { target, features }: (!("wasm32" == target."arch" or null)); } { name = "rustls-pemfile"; - packageId = "rustls-pemfile 1.0.4"; + packageId = "rustls-pemfile"; + optional = true; + target = { target, features }: (!("wasm32" == target."arch" or null)); + } + { + name = "rustls-pki-types"; + packageId = "rustls-pki-types"; optional = true; target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "alloc" ]; } { name = "serde"; @@ -9364,9 +10447,9 @@ rec { packageId = "serde_urlencoded"; } { - name = "system-configuration"; - packageId = "system-configuration"; - target = { target, features }: ("macos" == target."os" or null); + name = "sync_wrapper"; + packageId = "sync_wrapper 1.0.1"; + features = [ "futures" ]; } { name = "tokio"; @@ -9377,9 +10460,11 @@ rec { } { name = "tokio-rustls"; - packageId = "tokio-rustls 0.24.1"; + packageId = "tokio-rustls"; optional = true; + usesDefaultFeatures = false; target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "tls12" ]; } { name = "tokio-util"; @@ -9420,18 +10505,38 @@ rec { features = [ "AbortController" "AbortSignal" "Headers" "Request" "RequestInit" "RequestMode" "Response" "Window" "FormData" "Blob" "BlobPropertyBag" "ServiceWorkerGlobalScope" "RequestCredentials" "File" "ReadableStream" ]; } { - name = "winreg"; - packageId = "winreg"; + name = "windows-registry"; + packageId = "windows-registry"; target = { target, features }: (target."windows" or false); } ]; devDependencies = [ { + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; + target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "std" "alloc" ]; + } + { name = "hyper"; - packageId = "hyper 0.14.28"; + packageId = "hyper"; usesDefaultFeatures = false; target = { target, features }: (!("wasm32" == target."arch" or null)); - features = [ "tcp" "stream" "http1" "http2" "client" "server" "runtime" ]; + features = [ "http1" "http2" "client" "server" ]; + } + { + name = "hyper-util"; + packageId = "hyper-util"; + target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "http1" "http2" "client" "client-legacy" "server-auto" "tokio" ]; + } + { + name = "rustls"; + packageId = "rustls"; + usesDefaultFeatures = false; + target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "ring" ]; } { name = "serde"; @@ -9454,63 +10559,194 @@ rec { } ]; features = { - "__rustls" = [ "hyper-rustls" "tokio-rustls" "rustls" "__tls" "rustls-pemfile" ]; - "async-compression" = [ "dep:async-compression" ]; - "blocking" = [ "futures-util/io" "tokio/rt-multi-thread" "tokio/sync" ]; - "brotli" = [ "async-compression" "async-compression/brotli" "tokio-util" ]; - "cookie_crate" = [ "dep:cookie_crate" ]; - "cookie_store" = [ "dep:cookie_store" ]; - "cookies" = [ "cookie_crate" "cookie_store" ]; - "default" = [ "default-tls" ]; - "default-tls" = [ "hyper-tls" "native-tls-crate" "__tls" "tokio-native-tls" ]; - "deflate" = [ "async-compression" "async-compression/zlib" "tokio-util" ]; - "futures-channel" = [ "dep:futures-channel" ]; - "gzip" = [ "async-compression" "async-compression/gzip" "tokio-util" ]; - "h3" = [ "dep:h3" ]; - "h3-quinn" = [ "dep:h3-quinn" ]; - "http3" = [ "rustls-tls-manual-roots" "h3" "h3-quinn" "quinn" "futures-channel" ]; - "hyper-rustls" = [ "dep:hyper-rustls" ]; - "hyper-tls" = [ "dep:hyper-tls" ]; - "json" = [ "serde_json" ]; - "mime_guess" = [ "dep:mime_guess" ]; - "multipart" = [ "mime_guess" ]; + "__rustls" = [ "dep:hyper-rustls" "dep:tokio-rustls" "dep:rustls" "__tls" "dep:rustls-pemfile" "dep:rustls-pki-types" ]; + "__rustls-ring" = [ "hyper-rustls?/ring" "tokio-rustls?/ring" "rustls?/ring" "quinn?/ring" ]; + "__tls" = [ "dep:rustls-pemfile" "tokio/io-util" ]; + "blocking" = [ "dep:futures-channel" "futures-channel?/sink" "futures-util/io" "futures-util/sink" "tokio/sync" ]; + "brotli" = [ "dep:async-compression" "async-compression?/brotli" "dep:tokio-util" ]; + "charset" = [ "dep:encoding_rs" ]; + "cookies" = [ "dep:cookie_crate" "dep:cookie_store" ]; + "default" = [ "default-tls" "charset" "http2" "macos-system-configuration" ]; + "default-tls" = [ "dep:hyper-tls" "dep:native-tls-crate" "__tls" "dep:tokio-native-tls" ]; + "deflate" = [ "dep:async-compression" "async-compression?/zlib" "dep:tokio-util" ]; + "gzip" = [ "dep:async-compression" "async-compression?/gzip" "dep:tokio-util" ]; + "h2" = [ "dep:h2" ]; + "hickory-dns" = [ "dep:hickory-resolver" ]; + "http2" = [ "h2" "hyper/http2" "hyper-util/http2" "hyper-rustls?/http2" ]; + "http3" = [ "rustls-tls-manual-roots" "dep:h3" "dep:h3-quinn" "dep:quinn" "dep:slab" "dep:futures-channel" ]; + "json" = [ "dep:serde_json" ]; + "macos-system-configuration" = [ "dep:system-configuration" ]; + "multipart" = [ "dep:mime_guess" ]; "native-tls" = [ "default-tls" ]; - "native-tls-alpn" = [ "native-tls" "native-tls-crate/alpn" ]; - "native-tls-crate" = [ "dep:native-tls-crate" ]; - "native-tls-vendored" = [ "native-tls" "native-tls-crate/vendored" ]; - "quinn" = [ "dep:quinn" ]; - "rustls" = [ "dep:rustls" ]; - "rustls-native-certs" = [ "dep:rustls-native-certs" ]; - "rustls-pemfile" = [ "dep:rustls-pemfile" ]; + "native-tls-alpn" = [ "native-tls" "native-tls-crate?/alpn" "hyper-tls?/alpn" ]; + "native-tls-vendored" = [ "native-tls" "native-tls-crate?/vendored" ]; "rustls-tls" = [ "rustls-tls-webpki-roots" ]; - "rustls-tls-manual-roots" = [ "__rustls" ]; - "rustls-tls-native-roots" = [ "rustls-native-certs" "__rustls" ]; - "rustls-tls-webpki-roots" = [ "webpki-roots" "__rustls" ]; - "serde_json" = [ "dep:serde_json" ]; - "socks" = [ "tokio-socks" ]; - "stream" = [ "tokio/fs" "tokio-util" "wasm-streams" ]; - "tokio-native-tls" = [ "dep:tokio-native-tls" ]; - "tokio-rustls" = [ "dep:tokio-rustls" ]; - "tokio-socks" = [ "dep:tokio-socks" ]; - "tokio-util" = [ "dep:tokio-util" ]; - "trust-dns" = [ "trust-dns-resolver" ]; - "trust-dns-resolver" = [ "dep:trust-dns-resolver" ]; - "wasm-streams" = [ "dep:wasm-streams" ]; - "webpki-roots" = [ "dep:webpki-roots" ]; + "rustls-tls-manual-roots" = [ "__rustls" "__rustls-ring" ]; + "rustls-tls-manual-roots-no-provider" = [ "__rustls" ]; + "rustls-tls-native-roots" = [ "dep:rustls-native-certs" "hyper-rustls?/native-tokio" "__rustls" "__rustls-ring" ]; + "rustls-tls-no-provider" = [ "rustls-tls-manual-roots-no-provider" ]; + "rustls-tls-webpki-roots" = [ "dep:webpki-roots" "hyper-rustls?/webpki-tokio" "__rustls" "__rustls-ring" ]; + "socks" = [ "dep:tokio-socks" ]; + "stream" = [ "tokio/fs" "dep:tokio-util" "dep:wasm-streams" ]; + "zstd" = [ "dep:async-compression" "async-compression?/zstd" "dep:tokio-util" ]; + }; + resolvedDefaultFeatures = [ "__rustls" "__rustls-ring" "__tls" "h2" "http2" "json" "rustls-tls-native-roots" "stream" ]; + }; + "reqwest-middleware" = rec { + crateName = "reqwest-middleware"; + version = "0.3.3"; + edition = "2018"; + sha256 = "011b8n9a1bwalyk2y6x5s0wz52pxk70l4bbrba47qgsdc1dfnb2n"; + libName = "reqwest_middleware"; + authors = [ + "Rodrigo Gryzinski <rodrigo.gryzinski@truelayer.com>" + ]; + dependencies = [ + { + name = "anyhow"; + packageId = "anyhow"; + } + { + name = "async-trait"; + packageId = "async-trait"; + } + { + name = "http"; + packageId = "http"; + } + { + name = "reqwest"; + packageId = "reqwest"; + usesDefaultFeatures = false; + } + { + name = "serde"; + packageId = "serde"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "tower-service"; + packageId = "tower-service"; + } + ]; + devDependencies = [ + { + name = "reqwest"; + packageId = "reqwest"; + features = [ "rustls-tls" ]; + } + ]; + features = { + "charset" = [ "reqwest/charset" ]; + "http2" = [ "reqwest/http2" ]; + "json" = [ "reqwest/json" ]; + "multipart" = [ "reqwest/multipart" ]; + "rustls-tls" = [ "reqwest/rustls-tls" ]; + }; + }; + "reqwest-tracing" = rec { + crateName = "reqwest-tracing"; + version = "0.5.3"; + edition = "2018"; + sha256 = "0igb5hp1mdr8jb5qwj26dphykvydxy1piawrvpc368n7ckx9ppdz"; + libName = "reqwest_tracing"; + authors = [ + "Rodrigo Gryzinski <rodrigo.gryzinski@truelayer.com>" + ]; + dependencies = [ + { + name = "anyhow"; + packageId = "anyhow"; + } + { + name = "async-trait"; + packageId = "async-trait"; + } + { + name = "getrandom"; + packageId = "getrandom"; + target = { target, features }: ("wasm32" == target."arch" or null); + features = [ "js" ]; + } + { + name = "http"; + packageId = "http"; + } + { + name = "matchit"; + packageId = "matchit 0.8.4"; + } + { + name = "opentelemetry"; + packageId = "opentelemetry 0.22.0"; + rename = "opentelemetry_0_22_pkg"; + optional = true; + } + { + name = "reqwest"; + packageId = "reqwest"; + usesDefaultFeatures = false; + } + { + name = "reqwest-middleware"; + packageId = "reqwest-middleware"; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "tracing-opentelemetry"; + packageId = "tracing-opentelemetry 0.23.0"; + rename = "tracing-opentelemetry_0_23_pkg"; + optional = true; + } + ]; + devDependencies = [ + { + name = "reqwest"; + packageId = "reqwest"; + features = [ "rustls-tls" ]; + } + ]; + features = { + "opentelemetry_0_20" = [ "opentelemetry_0_20_pkg" "tracing-opentelemetry_0_21_pkg" ]; + "opentelemetry_0_20_pkg" = [ "dep:opentelemetry_0_20_pkg" ]; + "opentelemetry_0_21" = [ "opentelemetry_0_21_pkg" "tracing-opentelemetry_0_22_pkg" ]; + "opentelemetry_0_21_pkg" = [ "dep:opentelemetry_0_21_pkg" ]; + "opentelemetry_0_22" = [ "opentelemetry_0_22_pkg" "tracing-opentelemetry_0_23_pkg" ]; + "opentelemetry_0_22_pkg" = [ "dep:opentelemetry_0_22_pkg" ]; + "opentelemetry_0_23" = [ "opentelemetry_0_23_pkg" "tracing-opentelemetry_0_24_pkg" ]; + "opentelemetry_0_23_pkg" = [ "dep:opentelemetry_0_23_pkg" ]; + "opentelemetry_0_24" = [ "opentelemetry_0_24_pkg" "tracing-opentelemetry_0_25_pkg" ]; + "opentelemetry_0_24_pkg" = [ "dep:opentelemetry_0_24_pkg" ]; + "tracing-opentelemetry_0_21_pkg" = [ "dep:tracing-opentelemetry_0_21_pkg" ]; + "tracing-opentelemetry_0_22_pkg" = [ "dep:tracing-opentelemetry_0_22_pkg" ]; + "tracing-opentelemetry_0_23_pkg" = [ "dep:tracing-opentelemetry_0_23_pkg" ]; + "tracing-opentelemetry_0_24_pkg" = [ "dep:tracing-opentelemetry_0_24_pkg" ]; + "tracing-opentelemetry_0_25_pkg" = [ "dep:tracing-opentelemetry_0_25_pkg" ]; }; - resolvedDefaultFeatures = [ "__rustls" "__tls" "hyper-rustls" "json" "rustls" "rustls-native-certs" "rustls-pemfile" "rustls-tls-native-roots" "serde_json" "stream" "tokio-rustls" "tokio-util" "wasm-streams" ]; + resolvedDefaultFeatures = [ "opentelemetry_0_22" "opentelemetry_0_22_pkg" "tracing-opentelemetry_0_23_pkg" ]; }; "ring" = rec { crateName = "ring"; - version = "0.17.7"; + version = "0.17.8"; edition = "2021"; - links = "ring_core_0_17_7"; - sha256 = "0x5vvsp2424vll571xx085qf4hzljmwpz4x8n9l0j1c3akb67338"; + links = "ring_core_0_17_8"; + sha256 = "03fwlb1ssrmfxdckvqv033pfmk01rhx9ynwi7r186dcfcp5s8zy1"; authors = [ "Brian Smith <brian@briansmith.org>" ]; dependencies = [ { + name = "cfg-if"; + packageId = "cfg-if"; + usesDefaultFeatures = false; + } + { name = "getrandom"; packageId = "getrandom"; } @@ -9533,7 +10769,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (("aarch64" == target."arch" or null) && ("windows" == target."os" or null)); features = [ "Win32_Foundation" "Win32_System_Threading" ]; } @@ -9578,9 +10814,9 @@ rec { }; "rowan" = rec { crateName = "rowan"; - version = "0.15.15"; + version = "0.15.16"; edition = "2021"; - sha256 = "0j9b340gsyf2h7v1q9xb4mqyqp4qbyzlbk1r9zn2mzyclyl8z99j"; + sha256 = "0gdf8whwfzv41dr6xp2rhvgy83ckgg7wa7bss8rfcipsac12nm0a"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" ]; @@ -9591,17 +10827,13 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown 0.14.3"; + packageId = "hashbrown 0.14.5"; usesDefaultFeatures = false; features = [ "inline-more" ]; } { - name = "memoffset"; - packageId = "memoffset 0.9.0"; - } - { name = "rustc-hash"; - packageId = "rustc-hash"; + packageId = "rustc-hash 1.1.0"; } { name = "text-size"; @@ -9686,7 +10918,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" "parsing" "extra-traits" "visit" "visit-mut" ]; } { @@ -9725,7 +10957,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" "extra-traits" ]; } ]; @@ -9739,9 +10971,10 @@ rec { }; "rustc-demangle" = rec { crateName = "rustc-demangle"; - version = "0.1.23"; + version = "0.1.24"; edition = "2015"; - sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + sha256 = "07zysaafgrkzy2rjgwqdj2a8qdpsm6zv6f5pgpk9x0lm40z9b6vi"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -9751,28 +10984,40 @@ rec { "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; }; }; - "rustc-hash" = rec { + "rustc-hash 1.1.0" = rec { crateName = "rustc-hash"; version = "1.1.0"; edition = "2015"; sha256 = "1qkc5khrmv5pqi5l5ca9p5nl5hs742cagrndhbrlk3dhlrx3zm08"; + libName = "rustc_hash"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "rustc-hash 2.0.0" = rec { + crateName = "rustc-hash"; + version = "2.0.0"; + edition = "2021"; + sha256 = "0lni0lf846bzrf3jvci6jaf4142n1mdqxvcpczk5ch9pfgyk8c2q"; + libName = "rustc_hash"; authors = [ "The Rust Project Developers" ]; features = { "default" = [ "std" ]; + "rand" = [ "dep:rand" "std" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; "rustc_version" = rec { crateName = "rustc_version"; - version = "0.4.0"; + version = "0.4.1"; edition = "2018"; - sha256 = "0rpk9rcdk405xhbmgclsh4pai0svn49x35aggl4nhbkd4a2zb85z"; - authors = [ - "Dirkjan Ochtman <dirkjan@ochtman.nl>" - "Marvin Löbel <loebel.marvin@gmail.com>" - ]; + sha256 = "14lvdsmr5si5qbqzrajgb6vfn69k0sfygrvfvr2mps26xwi3mjyg"; dependencies = [ { name = "semver"; @@ -9783,9 +11028,9 @@ rec { }; "rustix" = rec { crateName = "rustix"; - version = "0.38.30"; + version = "0.38.37"; edition = "2021"; - sha256 = "1jkb6bzrj2w9ffy35aw4q04mqk1yxqw35fz80x0c4cxgi9c988rj"; + sha256 = "04b8f99c2g36gyggf4aphw8742k2b1vls3364n2z493whj5pijwa"; authors = [ "Dan Gohman <dev@sunfishcode.online>" "Jakub Konka <kubkon@jakubkonka.com>" @@ -9793,7 +11038,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; usesDefaultFeatures = false; } { @@ -9824,14 +11069,12 @@ rec { optional = true; usesDefaultFeatures = false; target = { target, features }: ((!(target."rustix_use_libc" or false)) && (!(target."miri" or false)) && ("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null)))); - features = [ "extra_traits" ]; } { name = "libc"; packageId = "libc"; usesDefaultFeatures = false; target = { target, features }: ((!(target."windows" or false)) && ((target."rustix_use_libc" or false) || (target."miri" or false) || (!(("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null))))))); - features = [ "extra_traits" ]; } { name = "linux-raw-sys"; @@ -9868,10 +11111,13 @@ rec { ]; features = { "all-apis" = [ "event" "fs" "io_uring" "mm" "mount" "net" "param" "pipe" "process" "procfs" "pty" "rand" "runtime" "shm" "stdio" "system" "termios" "thread" "time" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; "default" = [ "std" "use-libc-auxv" ]; "io_uring" = [ "event" "fs" "net" "linux-raw-sys/io_uring" ]; "itoa" = [ "dep:itoa" ]; "libc" = [ "dep:libc" ]; + "libc-extra-traits" = [ "libc?/extra_traits" ]; "libc_errno" = [ "dep:libc_errno" ]; "linux_latest" = [ "linux_4_11" ]; "net" = [ "linux-raw-sys/net" "linux-raw-sys/netlink" "linux-raw-sys/if_ether" "linux-raw-sys/xdp" ]; @@ -9881,20 +11127,21 @@ rec { "procfs" = [ "once_cell" "itoa" "fs" ]; "pty" = [ "itoa" "fs" ]; "runtime" = [ "linux-raw-sys/prctl" ]; - "rustc-dep-of-std" = [ "dep:core" "dep:alloc" "dep:compiler_builtins" "linux-raw-sys/rustc-dep-of-std" "bitflags/rustc-dep-of-std" "compiler_builtins?/rustc-dep-of-std" ]; + "rustc-dep-of-std" = [ "core" "rustc-std-workspace-alloc" "compiler_builtins" "linux-raw-sys/rustc-dep-of-std" "bitflags/rustc-dep-of-std" "compiler_builtins?/rustc-dep-of-std" ]; + "rustc-std-workspace-alloc" = [ "dep:rustc-std-workspace-alloc" ]; "shm" = [ "fs" ]; - "std" = [ "bitflags/std" "alloc" "libc?/std" "libc_errno?/std" ]; + "std" = [ "bitflags/std" "alloc" "libc?/std" "libc_errno?/std" "libc-extra-traits" ]; "system" = [ "linux-raw-sys/system" ]; "thread" = [ "linux-raw-sys/prctl" ]; - "use-libc" = [ "libc_errno" "libc" ]; + "use-libc" = [ "libc_errno" "libc" "libc-extra-traits" ]; }; - resolvedDefaultFeatures = [ "alloc" "default" "event" "fs" "net" "pipe" "process" "std" "termios" "time" "use-libc-auxv" ]; + resolvedDefaultFeatures = [ "alloc" "default" "event" "fs" "libc-extra-traits" "net" "pipe" "process" "std" "time" "use-libc-auxv" ]; }; - "rustls 0.21.10" = rec { + "rustls" = rec { crateName = "rustls"; - version = "0.21.10"; + version = "0.23.14"; edition = "2021"; - sha256 = "1fmpzk3axnhkd99saqkvraifdfms4pkyi56lkihf8n877j0sdmgr"; + sha256 = "1a0b2sdvq69vqrz08wvjmlqafzh7pfgzhn9j0n107f9wd529jpa1"; dependencies = [ { name = "log"; @@ -9902,45 +11149,10 @@ rec { optional = true; } { - name = "ring"; - packageId = "ring"; - } - { - name = "rustls-webpki"; - packageId = "rustls-webpki 0.101.7"; - rename = "webpki"; - features = [ "alloc" "std" ]; - } - { - name = "sct"; - packageId = "sct"; - } - ]; - devDependencies = [ - { - name = "log"; - packageId = "log"; - } - ]; - features = { - "default" = [ "logging" "tls12" ]; - "log" = [ "dep:log" ]; - "logging" = [ "log" ]; - "read_buf" = [ "rustversion" ]; - "rustversion" = [ "dep:rustversion" ]; - }; - resolvedDefaultFeatures = [ "dangerous_configuration" "default" "log" "logging" "tls12" ]; - }; - "rustls 0.22.2" = rec { - crateName = "rustls"; - version = "0.22.2"; - edition = "2021"; - sha256 = "0hcxyhq6ynvws9v5b2h81s1nwmijmya7a3vyyyhsy1wqpmb9jz78"; - dependencies = [ - { - name = "log"; - packageId = "log"; - optional = true; + name = "once_cell"; + packageId = "once_cell"; + usesDefaultFeatures = false; + features = [ "alloc" "race" ]; } { name = "ring"; @@ -9951,14 +11163,14 @@ rec { name = "rustls-pki-types"; packageId = "rustls-pki-types"; rename = "pki-types"; - features = [ "std" ]; + features = [ "alloc" ]; } { name = "rustls-webpki"; - packageId = "rustls-webpki 0.102.2"; + packageId = "rustls-webpki"; rename = "webpki"; usesDefaultFeatures = false; - features = [ "std" ]; + features = [ "alloc" ]; } { name = "subtle"; @@ -9977,49 +11189,28 @@ rec { } ]; features = { + "aws-lc-rs" = [ "aws_lc_rs" ]; "aws_lc_rs" = [ "dep:aws-lc-rs" "webpki/aws_lc_rs" ]; - "default" = [ "logging" "ring" "tls12" ]; + "brotli" = [ "dep:brotli" "dep:brotli-decompressor" "std" ]; + "default" = [ "aws_lc_rs" "logging" "std" "tls12" ]; + "fips" = [ "aws_lc_rs" "aws-lc-rs?/fips" ]; + "hashbrown" = [ "dep:hashbrown" ]; "log" = [ "dep:log" ]; "logging" = [ "log" ]; - "read_buf" = [ "rustversion" ]; + "read_buf" = [ "rustversion" "std" ]; "ring" = [ "dep:ring" "webpki/ring" ]; "rustversion" = [ "dep:rustversion" ]; + "std" = [ "webpki/std" "pki-types/std" "once_cell/std" ]; + "zlib" = [ "dep:zlib-rs" ]; }; - resolvedDefaultFeatures = [ "log" "logging" "ring" "tls12" ]; + resolvedDefaultFeatures = [ "log" "logging" "ring" "std" "tls12" ]; }; - "rustls-native-certs 0.6.3" = rec { + "rustls-native-certs" = rec { crateName = "rustls-native-certs"; - version = "0.6.3"; - edition = "2021"; - sha256 = "007zind70rd5rfsrkdcfm8vn09j8sg02phg9334kark6rdscxam9"; - dependencies = [ - { - name = "openssl-probe"; - packageId = "openssl-probe"; - target = { target, features }: ((target."unix" or false) && (!("macos" == target."os" or null))); - } - { - name = "rustls-pemfile"; - packageId = "rustls-pemfile 1.0.4"; - } - { - name = "schannel"; - packageId = "schannel"; - target = { target, features }: (target."windows" or false); - } - { - name = "security-framework"; - packageId = "security-framework"; - target = { target, features }: ("macos" == target."os" or null); - } - ]; - - }; - "rustls-native-certs 0.7.0" = rec { - crateName = "rustls-native-certs"; - version = "0.7.0"; + version = "0.8.0"; edition = "2021"; - sha256 = "14ip15dcr6fmjzi12lla9cpln7mmkdid4a7wsp344v4kz9gbh7wg"; + sha256 = "12izz1ahwj3yr9fkd39q1w535577z9wsapsahz6jcwxyyaj1ibzw"; + libName = "rustls_native_certs"; dependencies = [ { name = "openssl-probe"; @@ -10028,7 +11219,7 @@ rec { } { name = "rustls-pemfile"; - packageId = "rustls-pemfile 2.1.0"; + packageId = "rustls-pemfile"; } { name = "rustls-pki-types"; @@ -10048,32 +11239,14 @@ rec { ]; }; - "rustls-pemfile 1.0.4" = rec { - crateName = "rustls-pemfile"; - version = "1.0.4"; - edition = "2018"; - sha256 = "1324n5bcns0rnw6vywr5agff3rwfvzphi7rmbyzwnv6glkhclx0w"; - dependencies = [ - { - name = "base64"; - packageId = "base64"; - } - ]; - - }; - "rustls-pemfile 2.1.0" = rec { + "rustls-pemfile" = rec { crateName = "rustls-pemfile"; - version = "2.1.0"; + version = "2.2.0"; edition = "2018"; - sha256 = "02y7qn9d93ri4hrm72yw4zqlbxch6ma045nyazmdrppw6jvkncrw"; + sha256 = "0l3f3mrfkgdjrava7ibwzgwc4h3dljw3pdkbsi9rkwz3zvji9qyw"; + libName = "rustls_pemfile"; dependencies = [ { - name = "base64"; - packageId = "base64"; - usesDefaultFeatures = false; - features = [ "alloc" ]; - } - { name = "rustls-pki-types"; packageId = "rustls-pki-types"; rename = "pki-types"; @@ -10081,50 +11254,29 @@ rec { ]; features = { "default" = [ "std" ]; - "std" = [ "base64/std" ]; + "std" = [ "pki-types/std" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; "rustls-pki-types" = rec { crateName = "rustls-pki-types"; - version = "1.3.1"; + version = "1.9.0"; edition = "2021"; - sha256 = "1a0g7453h07701vyxjj05gv903a0shi43mf7hl3cdd08hsr6gpjy"; + sha256 = "0mcc901b4hm2ql2qwpf2gzqhqn6d7iag92hr872wjr8c6wsnws8f"; + libName = "rustls_pki_types"; features = { "default" = [ "alloc" ]; "std" = [ "alloc" ]; + "web" = [ "web-time" ]; + "web-time" = [ "dep:web-time" ]; }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; - "rustls-webpki 0.101.7" = rec { + "rustls-webpki" = rec { crateName = "rustls-webpki"; - version = "0.101.7"; + version = "0.102.8"; edition = "2021"; - sha256 = "0rapfhpkqp75552i8r0y7f4vq7csb4k7gjjans0df73sxv8paqlb"; - libName = "webpki"; - dependencies = [ - { - name = "ring"; - packageId = "ring"; - usesDefaultFeatures = false; - } - { - name = "untrusted"; - packageId = "untrusted"; - } - ]; - features = { - "alloc" = [ "ring/alloc" ]; - "default" = [ "std" ]; - "std" = [ "alloc" ]; - }; - resolvedDefaultFeatures = [ "alloc" "default" "std" ]; - }; - "rustls-webpki 0.102.2" = rec { - crateName = "rustls-webpki"; - version = "0.102.2"; - edition = "2021"; - sha256 = "041ncshpw8wsvi8p74a3yw9c0r17lhyk1yjsxyrbkv8bfii0maps"; + sha256 = "1sdy8ks86b7jpabpnb2px2s7f1sq8v0nqf6fnlvwzm4vfk41pjk4"; libName = "webpki"; dependencies = [ { @@ -10155,9 +11307,9 @@ rec { }; "rustversion" = rec { crateName = "rustversion"; - version = "1.0.14"; + version = "1.0.17"; edition = "2018"; - sha256 = "1x1pz1yynk5xzzrazk2svmidj69jhz89dz5vrc28sixl20x1iz3z"; + sha256 = "1mm3fckyvb0l2209in1n2k05sws5d9mpkszbnwhq3pkq8apjhpcm"; procMacro = true; build = "build/build.rs"; authors = [ @@ -10165,40 +11317,6 @@ rec { ]; }; - "rusty-fork" = rec { - crateName = "rusty-fork"; - version = "0.3.0"; - edition = "2018"; - sha256 = "0kxwq5c480gg6q0j3bg4zzyfh2kwmc3v2ba94jw8ncjc8mpcqgfb"; - authors = [ - "Jason Lingle" - ]; - dependencies = [ - { - name = "fnv"; - packageId = "fnv"; - } - { - name = "quick-error"; - packageId = "quick-error"; - } - { - name = "tempfile"; - packageId = "tempfile"; - } - { - name = "wait-timeout"; - packageId = "wait-timeout"; - optional = true; - } - ]; - features = { - "default" = [ "timeout" ]; - "timeout" = [ "wait-timeout" ]; - "wait-timeout" = [ "dep:wait-timeout" ]; - }; - resolvedDefaultFeatures = [ "timeout" "wait-timeout" ]; - }; "rustyline" = rec { crateName = "rustyline"; version = "10.1.1"; @@ -10295,9 +11413,9 @@ rec { }; "ryu" = rec { crateName = "ryu"; - version = "1.0.16"; + version = "1.0.18"; edition = "2018"; - sha256 = "0k7b90xr48ag5bzmfjp82rljasw2fx28xr3bg1lrpx7b5sljm3gr"; + sha256 = "17xx2s8j1lln7iackzd9p0sv546vjq71i779gphjq923vjh5pjzk"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -10310,6 +11428,7 @@ rec { version = "1.0.6"; edition = "2018"; sha256 = "00h5j1w87dmhnvbv9l8bic3y7xxsnjmssvifw2ayvgx9mb1ivz4k"; + libName = "same_file"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -10324,9 +11443,9 @@ rec { }; "schannel" = rec { crateName = "schannel"; - version = "0.1.23"; + version = "0.1.26"; edition = "2018"; - sha256 = "0d1m156bsjrws6xzzr1wyfyih9i22mb2csb5pc5kmkrvci2ibjgv"; + sha256 = "1hfip5mdwqcfnmrnkrq9d8zwy6bssmf6rfm2441nk83ghbjpn8h1"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Steffen Butzer <steffen.butzer@outlook.com>" @@ -10334,19 +11453,30 @@ rec { dependencies = [ { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; - features = [ "Win32_Foundation" "Win32_Security_Cryptography" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_System_Memory" ]; + packageId = "windows-sys 0.59.0"; + features = [ "Win32_Foundation" "Win32_Security_Cryptography" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_System_LibraryLoader" "Win32_System_Memory" "Win32_System_SystemInformation" ]; } ]; devDependencies = [ { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; + packageId = "windows-sys 0.59.0"; features = [ "Win32_System_SystemInformation" "Win32_System_Time" ]; } ]; }; + "scoped-tls" = rec { + crateName = "scoped-tls"; + version = "1.0.1"; + edition = "2015"; + sha256 = "15524h04mafihcvfpgxd8f4bgc3k95aclz8grjkg9a0rxcvn9kz1"; + libName = "scoped_tls"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + + }; "scopeguard" = rec { crateName = "scopeguard"; version = "1.2.0"; @@ -10360,31 +11490,12 @@ rec { }; resolvedDefaultFeatures = [ "default" "use_std" ]; }; - "sct" = rec { - crateName = "sct"; - version = "0.7.1"; - edition = "2021"; - sha256 = "056lmi2xkzdg1dbai6ha3n57s18cbip4pnmpdhyljli3m99n216s"; - authors = [ - "Joseph Birr-Pixton <jpixton@gmail.com>" - ]; - dependencies = [ - { - name = "ring"; - packageId = "ring"; - } - { - name = "untrusted"; - packageId = "untrusted"; - } - ]; - - }; "security-framework" = rec { crateName = "security-framework"; - version = "2.9.2"; + version = "2.11.1"; edition = "2021"; - sha256 = "1pplxk15s5yxvi2m1sz5xfmjibp96cscdcl432w9jzbk0frlzdh5"; + sha256 = "00ldclwx78dm61v7wkach9lcx76awlrv0fdgjdwch4dmy12j4yw9"; + libName = "security_framework"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -10392,7 +11503,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 1.3.2"; + packageId = "bitflags 2.6.0"; } { name = "core-foundation"; @@ -10420,17 +11531,18 @@ rec { "OSX_10_14" = [ "OSX_10_13" "security-framework-sys/OSX_10_14" ]; "OSX_10_15" = [ "OSX_10_14" "security-framework-sys/OSX_10_15" ]; "OSX_10_9" = [ "security-framework-sys/OSX_10_9" ]; - "default" = [ "OSX_10_9" ]; + "default" = [ "OSX_10_12" ]; "log" = [ "dep:log" ]; "serial-number-bigint" = [ "dep:num-bigint" ]; }; - resolvedDefaultFeatures = [ "OSX_10_9" "default" ]; + resolvedDefaultFeatures = [ "OSX_10_10" "OSX_10_11" "OSX_10_12" "OSX_10_9" "default" ]; }; "security-framework-sys" = rec { crateName = "security-framework-sys"; - version = "2.9.1"; + version = "2.12.0"; edition = "2021"; - sha256 = "0yhciwlsy9dh0ps1gw3197kvyqx1bvc4knrhiznhid6kax196cp9"; + sha256 = "1dml0lp9lrvvi01s011lyss5kzzsmakaamdwsxr0431jd4l2jjpa"; + libName = "security_framework_sys"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -10452,15 +11564,15 @@ rec { "OSX_10_13" = [ "OSX_10_12" ]; "OSX_10_14" = [ "OSX_10_13" ]; "OSX_10_15" = [ "OSX_10_14" ]; - "default" = [ "OSX_10_9" ]; + "default" = [ "OSX_10_12" ]; }; - resolvedDefaultFeatures = [ "OSX_10_9" ]; + resolvedDefaultFeatures = [ "OSX_10_10" "OSX_10_11" "OSX_10_12" "OSX_10_9" ]; }; "semver" = rec { crateName = "semver"; - version = "1.0.21"; + version = "1.0.23"; edition = "2018"; - sha256 = "1c49snqlfcx93xym1cgwx8zcspmyyxm37xa2fyfgjx1vhalxfzmr"; + sha256 = "12wqpxfflclbq4dv8sa6gchdh92ahhwn4ci1ls22wlby3h57wsb1"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -10472,9 +11584,9 @@ rec { }; "serde" = rec { crateName = "serde"; - version = "1.0.197"; + version = "1.0.210"; edition = "2018"; - sha256 = "1qjcxqd3p4yh5cmmax9q4ics1zy34j5ij32cvjj5dc5rw5rwic9z"; + sha256 = "0flc0z8wgax1k4j5bf2zyq48bgzyv425jkd5w0i6wbh7f8j5kqy8"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -10506,9 +11618,9 @@ rec { }; "serde_derive" = rec { crateName = "serde_derive"; - version = "1.0.197"; + version = "1.0.210"; edition = "2015"; - sha256 = "02v1x0sdv8qy06lpr6by4ar1n3jz3hmab15cgimpzhgd895v7c3y"; + sha256 = "07yzy4wafk79ps0hmbqmsqh5xjna4pm4q57wc847bb8gl3nh4f94"; procMacro = true; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" @@ -10529,7 +11641,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; usesDefaultFeatures = false; features = [ "clone-impls" "derive" "parsing" "printing" "proc-macro" ]; } @@ -10539,9 +11651,9 @@ rec { }; "serde_json" = rec { crateName = "serde_json"; - version = "1.0.111"; + version = "1.0.128"; edition = "2021"; - sha256 = "1x441azvvdy6x8am4bvkxhswhzw5cr8ml0cqspnihvri8bx4cvhp"; + sha256 = "1n43nia50ybpcfmh3gcw4lcc627qsg9nyakzwgkk9pm10xklbxbg"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -10552,6 +11664,11 @@ rec { packageId = "itoa"; } { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + { name = "ryu"; packageId = "ryu"; } @@ -10573,7 +11690,7 @@ rec { "default" = [ "std" ]; "indexmap" = [ "dep:indexmap" ]; "preserve_order" = [ "indexmap" "std" ]; - "std" = [ "serde/std" ]; + "std" = [ "memchr/std" "serde/std" ]; }; resolvedDefaultFeatures = [ "alloc" "default" "raw_value" "std" ]; }; @@ -10637,9 +11754,9 @@ rec { }; "serde_spanned" = rec { crateName = "serde_spanned"; - version = "0.6.5"; + version = "0.6.8"; edition = "2021"; - sha256 = "1hgh6s3jjwyzhfk3xwb6pnnr1misq9nflwq0f026jafi37s24dpb"; + sha256 = "1q89g70azwi4ybilz5jb8prfpa575165lmrffd49vmcf76qpqq47"; dependencies = [ { name = "serde"; @@ -10658,6 +11775,32 @@ rec { }; resolvedDefaultFeatures = [ "serde" ]; }; + "serde_tagged" = rec { + crateName = "serde_tagged"; + version = "0.3.0"; + edition = "2015"; + sha256 = "1scr98aw9d9hf9bf0gr5fcmhkwsz0fpy2wr2zi5r4cnfya6j9kbn"; + authors = [ + "qzed <qzed@users.noreply.github.com>" + ]; + dependencies = [ + { + name = "erased-serde"; + packageId = "erased-serde"; + optional = true; + } + { + name = "serde"; + packageId = "serde"; + } + ]; + features = { + "default" = [ "erased" ]; + "erased" = [ "erased-serde" ]; + "erased-serde" = [ "dep:erased-serde" ]; + }; + resolvedDefaultFeatures = [ "default" "erased" "erased-serde" ]; + }; "serde_urlencoded" = rec { crateName = "serde_urlencoded"; version = "0.7.1"; @@ -10688,9 +11831,9 @@ rec { }; "serde_with" = rec { crateName = "serde_with"; - version = "3.7.0"; + version = "3.11.0"; edition = "2021"; - sha256 = "16jn72cij27fxjafcsma1z5p587xkk8wqhp2yv98zy5vc7iv107f"; + sha256 = "05z83zkx9q8k4yw3z7isb3l95c5k43q0hwcz8h739f5jdnnvsa4f"; authors = [ "Jonas Bushart" "Marcin Kaźmierczak" @@ -10698,7 +11841,7 @@ rec { dependencies = [ { name = "base64"; - packageId = "base64"; + packageId = "base64 0.22.1"; optional = true; usesDefaultFeatures = false; } @@ -10726,7 +11869,7 @@ rec { } { name = "indexmap"; - packageId = "indexmap 2.1.0"; + packageId = "indexmap 2.6.0"; rename = "indexmap_2"; optional = true; usesDefaultFeatures = false; @@ -10781,6 +11924,7 @@ rec { "default" = [ "std" "macros" ]; "guide" = [ "dep:doc-comment" "dep:document-features" "macros" "std" ]; "hashbrown_0_14" = [ "dep:hashbrown_0_14" "alloc" ]; + "hashbrown_0_15" = [ "dep:hashbrown_0_15" "alloc" ]; "hex" = [ "dep:hex" "alloc" ]; "indexmap" = [ "indexmap_1" ]; "indexmap_1" = [ "dep:indexmap_1" "alloc" ]; @@ -10795,9 +11939,9 @@ rec { }; "serde_with_macros" = rec { crateName = "serde_with_macros"; - version = "3.7.0"; + version = "3.11.0"; edition = "2021"; - sha256 = "0mbnika5bw1mvgnl50rs7wfzj7dwxzgwqxnq6656694j38bdqqb5"; + sha256 = "17d7viab3z0ypf4jzpn73xydxn22c911n5nsycjgfkl5m4a6514x"; procMacro = true; authors = [ "Jonas Bushart" @@ -10817,7 +11961,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "extra-traits" "full" "parsing" ]; } ]; @@ -10907,6 +12051,7 @@ rec { version = "0.1.7"; edition = "2018"; sha256 = "1xipjr4nqsgw34k7a2cgj9zaasl2ds6jwn89886kww93d32a637l"; + libName = "sharded_slab"; authors = [ "Eliza Weisman <eliza@buoyant.io>" ]; @@ -10920,11 +12065,30 @@ rec { "loom" = [ "dep:loom" ]; }; }; + "shlex" = rec { + crateName = "shlex"; + version = "1.3.0"; + edition = "2015"; + sha256 = "0r1y6bv26c1scpxvhg2cabimrmwgbp4p3wy6syj9n0c4s3q2znhg"; + authors = [ + "comex <comexk@gmail.com>" + "Fenhl <fenhl@fenhl.net>" + "Adrian Taylor <adetaylor@chromium.org>" + "Alex Touchet <alextouchet@outlook.com>" + "Daniel Parks <dp+git@oxidized.org>" + "Garrett Berg <googberg@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; "signal-hook-registry" = rec { crateName = "signal-hook-registry"; - version = "1.4.1"; + version = "1.4.2"; edition = "2015"; - sha256 = "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq"; + sha256 = "1cb5akgq8ajnd5spyn587srvs4n26ryq0p78nswffwhv46sf1sd9"; + libName = "signal_hook_registry"; authors = [ "Michal 'vorner' Vaner <vorner@vorner.cz>" "Masaki Hara <ackie.h.gmai@gmail.com>" @@ -10981,74 +12145,11 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "sled" = rec { - crateName = "sled"; - version = "0.34.7"; - edition = "2018"; - sha256 = "0dcr2s7cylj5mb33ci3kpx7fz797jwvysnl5airrir9cgirv95kz"; - authors = [ - "Tyler Neely <t@jujit.su>" - ]; - dependencies = [ - { - name = "crc32fast"; - packageId = "crc32fast"; - } - { - name = "crossbeam-epoch"; - packageId = "crossbeam-epoch"; - } - { - name = "crossbeam-utils"; - packageId = "crossbeam-utils"; - } - { - name = "fs2"; - packageId = "fs2"; - target = { target, features }: (("linux" == target."os" or null) || ("macos" == target."os" or null) || ("windows" == target."os" or null)); - } - { - name = "fxhash"; - packageId = "fxhash"; - } - { - name = "libc"; - packageId = "libc"; - } - { - name = "log"; - packageId = "log"; - } - { - name = "parking_lot"; - packageId = "parking_lot 0.11.2"; - } - ]; - devDependencies = [ - { - name = "log"; - packageId = "log"; - } - ]; - features = { - "backtrace" = [ "dep:backtrace" ]; - "color-backtrace" = [ "dep:color-backtrace" ]; - "compression" = [ "zstd" ]; - "default" = [ "no_metrics" ]; - "io_uring" = [ "rio" ]; - "no_logs" = [ "log/max_level_off" ]; - "pretty_backtrace" = [ "color-backtrace" ]; - "rio" = [ "dep:rio" ]; - "testing" = [ "event_log" "lock_free_delays" "compression" "failpoints" "backtrace" ]; - "zstd" = [ "dep:zstd" ]; - }; - resolvedDefaultFeatures = [ "default" "no_metrics" ]; - }; "smallvec" = rec { crateName = "smallvec"; - version = "1.13.1"; + version = "1.13.2"; edition = "2018"; - sha256 = "1mzk9j117pn3k1gabys0b7nz8cdjsx5xc6q7fwnm8r0an62d7v76"; + sha256 = "0rsw5samawl3wsw6glrsb127rx6sh89a8wyikicw6dkdcjd1lpiw"; authors = [ "The Servo Project Developers" ]; @@ -11062,9 +12163,9 @@ rec { }; "smol_str" = rec { crateName = "smol_str"; - version = "0.2.1"; + version = "0.2.2"; edition = "2018"; - sha256 = "0jca0hyrwnv428q5gxhn2s8jsvrrkyrb0fyla9x37056mmimb176"; + sha256 = "1bfylqf2vnqaglw58930vpxm2rfzji5gjp15a2c0kh8aj6v8ylyx"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" ]; @@ -11134,13 +12235,14 @@ rec { edition = "2018"; sha256 = "1gzy9rzggs090zf7hfvgp4lm1glrmg9qzh796686jnq7bxk7j04r"; procMacro = true; + libName = "snafu_derive"; authors = [ "Jake Goulding <jake.goulding@gmail.com>" ]; dependencies = [ { name = "heck"; - packageId = "heck"; + packageId = "heck 0.4.1"; } { name = "proc-macro2"; @@ -11161,9 +12263,9 @@ rec { }; "socket2" = rec { crateName = "socket2"; - version = "0.5.5"; + version = "0.5.7"; edition = "2021"; - sha256 = "1sgq315f1njky114ip7wcy83qlphv9qclprfjwvxcpfblmcsqpvv"; + sha256 = "070r941wbq76xpy039an4pyiy3rfj7mp7pvibf1rcri9njq5wc6f"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -11176,7 +12278,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_System_IO" "Win32_System_Threading" "Win32_System_WindowsProgramming" ]; } @@ -11256,6 +12358,7 @@ rec { version = "1.0.6"; edition = "2018"; sha256 = "1l7q4nha7wpsr0970bfqm773vhmpwr9l6rr8r4gwgrh46wvdh24y"; + libName = "str_buf"; authors = [ "Douman <douman@gmx.se>" ]; @@ -11265,11 +12368,12 @@ rec { }; "strsim" = rec { crateName = "strsim"; - version = "0.10.0"; + version = "0.11.1"; edition = "2015"; - sha256 = "08s69r4rcrahwnickvi0kq49z524ci50capybln83mg6b473qivk"; + sha256 = "0kzvqlw8hxqb7y598w1s0hxlnmi84sg5vsipp3yg5na5d1rvba3x"; authors = [ "Danny Guo <danny@dannyguo.com>" + "maxbachmann <oss@maxbachmann.de>" ]; }; @@ -11314,6 +12418,7 @@ rec { edition = "2021"; sha256 = "14vxik2m3dm7bwx016qfz062fwznkbq02fyq8vby545m0pj0nhi4"; procMacro = true; + libName = "structmeta_derive"; authors = [ "frozenlib" ]; @@ -11340,11 +12445,61 @@ rec { ]; }; + "strum" = rec { + crateName = "strum"; + version = "0.26.3"; + edition = "2018"; + sha256 = "01lgl6jvrf4j28v5kmx9bp480ygf1nhvac8b4p7rcj9hxw50zv4g"; + authors = [ + "Peter Glotfelty <peter.glotfelty@microsoft.com>" + ]; + features = { + "default" = [ "std" ]; + "derive" = [ "strum_macros" ]; + "phf" = [ "dep:phf" ]; + "strum_macros" = [ "dep:strum_macros" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "strum_macros" = rec { + crateName = "strum_macros"; + version = "0.26.4"; + edition = "2018"; + sha256 = "1gl1wmq24b8md527cpyd5bw9rkbqldd7k1h38kf5ajd2ln2ywssc"; + procMacro = true; + authors = [ + "Peter Glotfelty <peter.glotfelty@microsoft.com>" + ]; + dependencies = [ + { + name = "heck"; + packageId = "heck 0.5.0"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "rustversion"; + packageId = "rustversion"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "parsing" "extra-traits" ]; + } + ]; + + }; "subtle" = rec { crateName = "subtle"; - version = "2.5.0"; + version = "2.6.1"; edition = "2018"; - sha256 = "1g2yjs7gffgmdvkkq0wrrh0pxds3q0dv6dhkw9cdpbib656xdkc1"; + sha256 = "14ijxaymghbl1p0wql9cib5zlwiina7kall6w7g89csprkgbvhhk"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -11387,11 +12542,11 @@ rec { }; resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit" "visit-mut" ]; }; - "syn 2.0.48" = rec { + "syn 2.0.79" = rec { crateName = "syn"; - version = "2.0.48"; + version = "2.0.79"; edition = "2021"; - sha256 = "0gqgfygmrxmp8q32lia9p294kdd501ybn6kn2h4gqza0irik2d8g"; + sha256 = "147mk4sgigmvsb9l8qzj199ygf0fgb0bphwdsghn8205pz82q4w9"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -11414,14 +12569,13 @@ rec { ]; features = { "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; - "printing" = [ "quote" ]; - "proc-macro" = [ "proc-macro2/proc-macro" "quote/proc-macro" ]; - "quote" = [ "dep:quote" ]; + "printing" = [ "dep:quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; "test" = [ "syn-test-suite/all-features" ]; }; - resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit" "visit-mut" ]; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; }; - "sync_wrapper" = rec { + "sync_wrapper 0.1.2" = rec { crateName = "sync_wrapper"; version = "0.1.2"; edition = "2018"; @@ -11434,49 +12588,27 @@ rec { "futures-core" = [ "dep:futures-core" ]; }; }; - "system-configuration" = rec { - crateName = "system-configuration"; - version = "0.5.1"; - edition = "2021"; - sha256 = "1rz0r30xn7fiyqay2dvzfy56cvaa3km74hnbz2d72p97bkf3lfms"; - authors = [ - "Mullvad VPN" - ]; - dependencies = [ - { - name = "bitflags"; - packageId = "bitflags 1.3.2"; - } - { - name = "core-foundation"; - packageId = "core-foundation"; - } - { - name = "system-configuration-sys"; - packageId = "system-configuration-sys"; - } - ]; - - }; - "system-configuration-sys" = rec { - crateName = "system-configuration-sys"; - version = "0.5.0"; - edition = "2021"; - sha256 = "1jckxvdr37bay3i9v52izgy52dg690x5xfg3hd394sv2xf4b2px7"; + "sync_wrapper 1.0.1" = rec { + crateName = "sync_wrapper"; + version = "1.0.1"; + edition = "2018"; + sha256 = "150k6lwvr4nl237ngsz8fj5j78k712m4bggrfyjsidllraz5l1m7"; authors = [ - "Mullvad VPN" + "Actyx AG <developer@actyx.io>" ]; dependencies = [ { - name = "core-foundation-sys"; - packageId = "core-foundation-sys"; - } - { - name = "libc"; - packageId = "libc"; + name = "futures-core"; + packageId = "futures-core"; + optional = true; + usesDefaultFeatures = false; } ]; - + features = { + "futures" = [ "futures-core" ]; + "futures-core" = [ "dep:futures-core" ]; + }; + resolvedDefaultFeatures = [ "futures" "futures-core" ]; }; "tabwriter" = rec { crateName = "tabwriter"; @@ -11497,9 +12629,9 @@ rec { }; "tempfile" = rec { crateName = "tempfile"; - version = "3.9.0"; - edition = "2018"; - sha256 = "1ypkl7rvv57n16q28psxpb61rnyhmfaif12ascdnsyljm90l3kh1"; + version = "3.13.0"; + edition = "2021"; + sha256 = "0nyagmbd4v5g6nzfydiihcn6l9j1w9bxgzyca5lyzgnhcbyckwph"; authors = [ "Steven Allen <steven@stebalien.com>" "The Rust Project Developers" @@ -11516,9 +12648,10 @@ rec { packageId = "fastrand"; } { - name = "redox_syscall"; - packageId = "redox_syscall 0.4.1"; - target = { target, features }: ("redox" == target."os" or null); + name = "once_cell"; + packageId = "once_cell"; + usesDefaultFeatures = false; + features = [ "std" ]; } { name = "rustix"; @@ -11528,7 +12661,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; + packageId = "windows-sys 0.59.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Storage_FileSystem" "Win32_Foundation" ]; } @@ -11558,6 +12691,7 @@ rec { edition = "2021"; sha256 = "105lxqs0vnqff5821sgns8q1scvrwfx1yw6iz7i7nr862j6l1mk2"; procMacro = true; + libName = "test_strategy"; authors = [ "frozenlib" ]; @@ -11587,6 +12721,7 @@ rec { version = "1.1.1"; edition = "2018"; sha256 = "0cwjbkl7w3xc8mnkhg1nwij6p5y2qkcfldgss8ddnawvhf3s32pi"; + libName = "text_size"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" "Christopher Durham (CAD97) <cad97@cad97.com>" @@ -11597,9 +12732,9 @@ rec { }; "thiserror" = rec { crateName = "thiserror"; - version = "1.0.56"; + version = "1.0.64"; edition = "2021"; - sha256 = "1b9hnzngjan4d89zjs16i01bcpcnvdwklyh73lj16xk28p37hhym"; + sha256 = "114s8lmssxl0c2480s671am88vzlasbaikxbvfv8pyqrq6mzh2nm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -11613,10 +12748,11 @@ rec { }; "thiserror-impl" = rec { crateName = "thiserror-impl"; - version = "1.0.56"; + version = "1.0.64"; edition = "2021"; - sha256 = "0w9ldp8fa574ilz4dn7y7scpcq66vdjy59qal8qdpwsh7faal3zs"; + sha256 = "1hvzmjx9iamln854l74qyhs0jl2pg3hhqzpqm9p8gszmf9v4x408"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -11631,16 +12767,16 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; } ]; }; "thread_local" = rec { crateName = "thread_local"; - version = "1.1.7"; + version = "1.1.8"; edition = "2021"; - sha256 = "0lp19jdgvp5m4l60cgxdnl00yw1hlqy8gcywg9bddwng9h36zp9z"; + sha256 = "173i5lyjh011gsimk21np9jn8al18rxsrkjli20a7b8ks2xgk7lb"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -11656,11 +12792,29 @@ rec { ]; features = { }; }; + "threadpool" = rec { + crateName = "threadpool"; + version = "1.8.1"; + edition = "2015"; + sha256 = "1amgfyzvynbm8pacniivzq9r0fh3chhs7kijic81j76l6c5ycl6h"; + authors = [ + "The Rust Project Developers" + "Corey Farwell <coreyf@rwell.org>" + "Stefan Schindler <dns2utf8@estada.ch>" + ]; + dependencies = [ + { + name = "num_cpus"; + packageId = "num_cpus"; + } + ]; + + }; "time" = rec { crateName = "time"; - version = "0.3.34"; + version = "0.3.36"; edition = "2021"; - sha256 = "0jc7wgprzqjhzd0nqkbmdlnjwyddnswmjw86ni2vq55v45jqn968"; + sha256 = "11g8hdpahgrf1wwl2rpsg5nxq3aj7ri6xr672v4qcij6cgjqizax"; authors = [ "Jacob Pratt <open-source@jhpratt.dev>" "Time contributors" @@ -11741,6 +12895,7 @@ rec { version = "0.1.2"; edition = "2021"; sha256 = "1wx3qizcihw6z151hywfzzyd1y5dl804ydyxci6qm07vbakpr4pg"; + libName = "time_core"; authors = [ "Jacob Pratt <open-source@jhpratt.dev>" "Time contributors" @@ -11749,10 +12904,11 @@ rec { }; "time-macros" = rec { crateName = "time-macros"; - version = "0.2.17"; + version = "0.2.18"; edition = "2021"; - sha256 = "0x3pahhk2751c6kqqq9dk6lz0gydbnxr44q01wpjlrz687ps78vv"; + sha256 = "1kqwxvfh2jkpg38fy673d6danh1bhcmmbsmffww3mphgail2l99z"; procMacro = true; + libName = "time_macros"; authors = [ "Jacob Pratt <open-source@jhpratt.dev>" "Time contributors" @@ -11792,9 +12948,9 @@ rec { }; "tinyvec" = rec { crateName = "tinyvec"; - version = "1.6.0"; + version = "1.8.0"; edition = "2018"; - sha256 = "0l6bl2h62a5m44jdnpn7lmj14rd44via8180i7121fvm73mmrk47"; + sha256 = "0f5rf6a2wzyv6w4jmfga9iw7rp9fp5gf4d604xgjsf3d9wgqhpj4"; authors = [ "Lokathor <zefria@gmail.com>" ]; @@ -11809,7 +12965,6 @@ rec { "alloc" = [ "tinyvec_macros" ]; "arbitrary" = [ "dep:arbitrary" ]; "real_blackbox" = [ "criterion/real_blackbox" ]; - "rustc_1_55" = [ "rustc_1_40" ]; "rustc_1_57" = [ "rustc_1_55" ]; "serde" = [ "dep:serde" ]; "std" = [ "alloc" ]; @@ -11829,9 +12984,9 @@ rec { }; "tokio" = rec { crateName = "tokio"; - version = "1.35.1"; + version = "1.40.0"; edition = "2021"; - sha256 = "01613rkziqp812a288ga65aqygs254wgajdi57v8brivjkx4x6y8"; + sha256 = "166rllhfkyqp0fs7sxn6crv74iizi4wzd3cvxkcpmlk52qip1c72"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -11854,16 +13009,11 @@ rec { } { name = "mio"; - packageId = "mio"; + packageId = "mio 1.0.2"; optional = true; usesDefaultFeatures = false; } { - name = "num_cpus"; - packageId = "num_cpus"; - optional = true; - } - { name = "pin-project-lite"; packageId = "pin-project-lite"; } @@ -11887,7 +13037,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; optional = true; target = { target, features }: (target."windows" or false); } @@ -11905,7 +13055,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Security_Authorization" ]; } @@ -11918,10 +13068,9 @@ rec { "macros" = [ "tokio-macros" ]; "mio" = [ "dep:mio" ]; "net" = [ "libc" "mio/os-poll" "mio/os-ext" "mio/net" "socket2" "windows-sys/Win32_Foundation" "windows-sys/Win32_Security" "windows-sys/Win32_Storage_FileSystem" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_System_SystemServices" ]; - "num_cpus" = [ "dep:num_cpus" ]; "parking_lot" = [ "dep:parking_lot" ]; "process" = [ "bytes" "libc" "mio/os-poll" "mio/os-ext" "mio/net" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Threading" "windows-sys/Win32_System_WindowsProgramming" ]; - "rt-multi-thread" = [ "num_cpus" "rt" ]; + "rt-multi-thread" = [ "rt" ]; "signal" = [ "libc" "mio/os-poll" "mio/net" "mio/os-ext" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Console" ]; "signal-hook-registry" = [ "dep:signal-hook-registry" ]; "socket2" = [ "dep:socket2" ]; @@ -11930,46 +13079,27 @@ rec { "tracing" = [ "dep:tracing" ]; "windows-sys" = [ "dep:windows-sys" ]; }; - resolvedDefaultFeatures = [ "bytes" "default" "fs" "io-std" "io-util" "libc" "macros" "mio" "net" "num_cpus" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "test-util" "time" "tokio-macros" "windows-sys" ]; - }; - "tokio-io-timeout" = rec { - crateName = "tokio-io-timeout"; - version = "1.2.0"; - edition = "2018"; - sha256 = "1gx84f92q1491vj4pkn81j8pz1s3pgwnbrsdhfsa2556mli41drh"; - authors = [ - "Steven Fackler <sfackler@gmail.com>" - ]; - dependencies = [ - { - name = "pin-project-lite"; - packageId = "pin-project-lite"; - } - { - name = "tokio"; - packageId = "tokio"; - features = [ "time" ]; - } - ]; - devDependencies = [ - { - name = "tokio"; - packageId = "tokio"; - features = [ "full" ]; - } - ]; - + resolvedDefaultFeatures = [ "bytes" "default" "fs" "io-std" "io-util" "libc" "macros" "mio" "net" "process" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "test-util" "time" "tokio-macros" "windows-sys" ]; }; "tokio-listener" = rec { crateName = "tokio-listener"; - version = "0.3.2"; + version = "0.4.3"; edition = "2021"; - sha256 = "00vkr1cywd2agn8jbkzwwf7y4ps3cfjm8l9ab697px2cgc97wdln"; + sha256 = "0iigg0w7n4r3ggcz0lj0vb2smq93dlwrqr06r1di54ij2afl6jli"; + libName = "tokio_listener"; dependencies = [ { name = "axum"; - packageId = "axum 0.7.4"; + packageId = "axum"; rename = "axum07"; + optional = true; + } + { + name = "clap"; + packageId = "clap"; + optional = true; + usesDefaultFeatures = false; + features = [ "derive" "std" ]; } { name = "document-features"; @@ -11985,6 +13115,19 @@ rec { optional = true; } { + name = "hyper"; + packageId = "hyper"; + rename = "hyper1"; + optional = true; + features = [ "server" ]; + } + { + name = "hyper-util"; + packageId = "hyper-util"; + optional = true; + features = [ "server" "server-auto" ]; + } + { name = "nix"; packageId = "nix 0.26.4"; optional = true; @@ -12015,8 +13158,19 @@ rec { } { name = "tonic"; - packageId = "tonic 0.11.0"; - rename = "tonic"; + packageId = "tonic"; + rename = "tonic_012"; + optional = true; + } + { + name = "tower"; + packageId = "tower 0.4.13"; + optional = true; + features = [ "util" ]; + } + { + name = "tower-service"; + packageId = "tower-service"; optional = true; } { @@ -12026,36 +13180,45 @@ rec { ]; devDependencies = [ { + name = "clap"; + packageId = "clap"; + features = [ "help" ]; + } + { name = "tokio"; packageId = "tokio"; features = [ "macros" "rt" "io-util" ]; } ]; features = { - "axum07" = [ "dep:hyper1" "dep:hyper-util" "dep:futures-util" "dep:tower-service" "dep:tower" ]; + "axum07" = [ "dep:hyper1" "dep:hyper-util" "dep:futures-util" "dep:tower-service" "dep:tower" "dep:axum07" ]; "clap" = [ "dep:clap" ]; "default" = [ "user_facing_default" "tokio-util" ]; "hyper014" = [ "dep:hyper014" ]; "inetd" = [ "dep:futures-util" ]; + "multi-listener" = [ "dep:futures-util" ]; "nix" = [ "dep:nix" ]; + "sd_listen" = [ "socket2" ]; "serde" = [ "dep:serde" "serde_with" ]; "serde_with" = [ "dep:serde_with" ]; "socket2" = [ "dep:socket2" ]; "socket_options" = [ "socket2" ]; "tokio-util" = [ "dep:tokio-util" ]; "tonic010" = [ "dep:tonic_010" ]; - "tonic011" = [ "dep:tonic" ]; + "tonic011" = [ "dep:tonic_011" ]; + "tonic012" = [ "dep:tonic_012" ]; "unix_path_tools" = [ "nix" ]; "user_facing_default" = [ "inetd" "unix" "unix_path_tools" "sd_listen" "socket_options" ]; }; - resolvedDefaultFeatures = [ "default" "inetd" "nix" "sd_listen" "socket2" "socket_options" "tokio-util" "tonic011" "unix" "unix_path_tools" "user_facing_default" ]; + resolvedDefaultFeatures = [ "axum07" "clap" "default" "inetd" "multi-listener" "nix" "sd_listen" "socket2" "socket_options" "tokio-util" "tonic012" "unix" "unix_path_tools" "user_facing_default" ]; }; "tokio-macros" = rec { crateName = "tokio-macros"; - version = "2.2.0"; + version = "2.4.0"; edition = "2021"; - sha256 = "0fwjy4vdx1h9pi4g2nml72wi0fr27b5m954p13ji9anyy8l1x2jv"; + sha256 = "0lnpg14h1v3fh2jvnc8cz7cjf0m7z1xgkwfpcyy632g829imjgb9"; procMacro = true; + libName = "tokio_macros"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -12070,7 +13233,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -12081,6 +13244,7 @@ rec { version = "0.3.0"; edition = "2018"; sha256 = "0kr1hnm5dmb9gfkby88yg2xj8g6x4i4gipva0c8ca3xyxhvfnmvz"; + libName = "tokio_retry"; authors = [ "Sam Rijs <srijs@airpost.net>" ]; @@ -12108,48 +13272,18 @@ rec { ]; }; - "tokio-rustls 0.24.1" = rec { + "tokio-rustls" = rec { crateName = "tokio-rustls"; - version = "0.24.1"; - edition = "2018"; - sha256 = "10bhibg57mqir7xjhb2xmf24xgfpx6fzpyw720a4ih8a737jg0y2"; - dependencies = [ - { - name = "rustls"; - packageId = "rustls 0.21.10"; - usesDefaultFeatures = false; - } - { - name = "tokio"; - packageId = "tokio"; - } - ]; - devDependencies = [ - { - name = "tokio"; - packageId = "tokio"; - features = [ "full" ]; - } - ]; - features = { - "dangerous_configuration" = [ "rustls/dangerous_configuration" ]; - "default" = [ "logging" "tls12" ]; - "logging" = [ "rustls/logging" ]; - "secret_extraction" = [ "rustls/secret_extraction" ]; - "tls12" = [ "rustls/tls12" ]; - }; - resolvedDefaultFeatures = [ "default" "logging" "tls12" ]; - }; - "tokio-rustls 0.25.0" = rec { - crateName = "tokio-rustls"; - version = "0.25.0"; + version = "0.26.0"; edition = "2021"; - sha256 = "03w6d5aqqf084rmcmrsyq5grhydl53blaiqcl0i2yfnv187hqpkp"; + sha256 = "1m00czrmk8x7pdjnz10a3da3i1d0sdf9j9vfp5dnk5ss1q6w8yqc"; + libName = "tokio_rustls"; dependencies = [ { name = "rustls"; - packageId = "rustls 0.22.2"; + packageId = "rustls"; usesDefaultFeatures = false; + features = [ "std" ]; } { name = "rustls-pki-types"; @@ -12169,18 +13303,22 @@ rec { } ]; features = { - "default" = [ "logging" "tls12" "ring" ]; + "aws-lc-rs" = [ "aws_lc_rs" ]; + "aws_lc_rs" = [ "rustls/aws_lc_rs" ]; + "default" = [ "logging" "tls12" "aws_lc_rs" ]; + "fips" = [ "rustls/fips" ]; "logging" = [ "rustls/logging" ]; "ring" = [ "rustls/ring" ]; "tls12" = [ "rustls/tls12" ]; }; - resolvedDefaultFeatures = [ "default" "logging" "ring" "tls12" ]; + resolvedDefaultFeatures = [ "logging" "ring" "tls12" ]; }; "tokio-stream" = rec { crateName = "tokio-stream"; - version = "0.1.14"; + version = "0.1.16"; edition = "2021"; - sha256 = "0hi8hcwavh5sdi1ivc9qc4yvyr32f153c212dpd7sb366y6rhz1r"; + sha256 = "1wc65gprcsyzqlr0k091glswy96kph90i32gffi4ksyh03hnqkjg"; + libName = "tokio_stream"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -12224,6 +13362,7 @@ rec { version = "0.3.1"; edition = "2018"; sha256 = "0xffvap4g7hlswk5daklk3jaqha6s6wxw72c24kmqgna23018mwx"; + libName = "tokio_tar"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "dignifiedquire <me@dignifiequire.com>" @@ -12280,9 +13419,10 @@ rec { }; "tokio-test" = rec { crateName = "tokio-test"; - version = "0.4.3"; + version = "0.4.4"; edition = "2021"; - sha256 = "06fplzcc2ymahfzykd2ickw2qn7g3lz47bll00865s1spnx3r6z8"; + sha256 = "1xzri2m3dg8nzdyznm77nymvil9cyh1gfdfrbnska51iqfmvls14"; + libName = "tokio_test"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -12320,9 +13460,10 @@ rec { }; "tokio-util" = rec { crateName = "tokio-util"; - version = "0.7.10"; + version = "0.7.12"; edition = "2021"; - sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + sha256 = "0spc0g4irbnf2flgag22gfii87avqzibwfm0si0d1g0k9ijw7rv1"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -12353,13 +13494,6 @@ rec { packageId = "tokio"; features = [ "sync" ]; } - { - name = "tracing"; - packageId = "tracing"; - optional = true; - usesDefaultFeatures = false; - features = [ "std" ]; - } ]; devDependencies = [ { @@ -12370,7 +13504,6 @@ rec { ]; features = { "__docs_rs" = [ "futures-util" ]; - "codec" = [ "tracing" ]; "compat" = [ "futures-io" ]; "full" = [ "codec" "compat" "io-util" "time" "net" "rt" ]; "futures-io" = [ "dep:futures-io" ]; @@ -12383,9 +13516,9 @@ rec { "time" = [ "tokio/time" "slab" ]; "tracing" = [ "dep:tracing" ]; }; - resolvedDefaultFeatures = [ "codec" "compat" "default" "futures-io" "io" "io-util" "net" "tracing" ]; + resolvedDefaultFeatures = [ "codec" "compat" "default" "futures-io" "io" "io-util" "net" ]; }; - "toml" = rec { + "toml 0.6.0" = rec { crateName = "toml"; version = "0.6.0"; edition = "2021"; @@ -12405,12 +13538,12 @@ rec { } { name = "toml_datetime"; - packageId = "toml_datetime"; + packageId = "toml_datetime 0.5.1"; features = [ "serde" ]; } { name = "toml_edit"; - packageId = "toml_edit"; + packageId = "toml_edit 0.18.1"; optional = true; features = [ "serde" ]; } @@ -12431,7 +13564,54 @@ rec { }; resolvedDefaultFeatures = [ "default" "display" "parse" ]; }; - "toml_datetime" = rec { + "toml 0.8.19" = rec { + crateName = "toml"; + version = "0.8.19"; + edition = "2021"; + sha256 = "0knjd3mkxyb87qcs2dark3qkpadidap3frqfj5nqvhpxwfc1zvd1"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "serde"; + packageId = "serde"; + } + { + name = "serde_spanned"; + packageId = "serde_spanned"; + features = [ "serde" ]; + } + { + name = "toml_datetime"; + packageId = "toml_datetime 0.6.8"; + features = [ "serde" ]; + } + { + name = "toml_edit"; + packageId = "toml_edit 0.22.22"; + optional = true; + usesDefaultFeatures = false; + features = [ "serde" ]; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + ]; + features = { + "default" = [ "parse" "display" ]; + "display" = [ "dep:toml_edit" "toml_edit?/display" ]; + "indexmap" = [ "dep:indexmap" ]; + "parse" = [ "dep:toml_edit" "toml_edit?/parse" ]; + "preserve_order" = [ "indexmap" ]; + }; + resolvedDefaultFeatures = [ "default" "display" "parse" ]; + }; + "toml_datetime 0.5.1" = rec { crateName = "toml_datetime"; version = "0.5.1"; edition = "2021"; @@ -12451,7 +13631,27 @@ rec { }; resolvedDefaultFeatures = [ "serde" ]; }; - "toml_edit" = rec { + "toml_datetime 0.6.8" = rec { + crateName = "toml_datetime"; + version = "0.6.8"; + edition = "2021"; + sha256 = "0hgv7v9g35d7y9r2afic58jvlwnf73vgd1mz2k8gihlgrf73bmqd"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "serde"; + packageId = "serde"; + optional = true; + } + ]; + features = { + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "serde" ]; + }; + "toml_edit 0.18.1" = rec { crateName = "toml_edit"; version = "0.18.1"; edition = "2021"; @@ -12482,7 +13682,7 @@ rec { } { name = "toml_datetime"; - packageId = "toml_datetime"; + packageId = "toml_datetime 0.5.1"; } ]; features = { @@ -12492,11 +13692,55 @@ rec { }; resolvedDefaultFeatures = [ "default" "serde" ]; }; - "tonic 0.11.0" = rec { + "toml_edit 0.22.22" = rec { + crateName = "toml_edit"; + version = "0.22.22"; + edition = "2021"; + sha256 = "1xf7sxfzmnc45f75x302qrn5aph52vc8w226v59yhrm211i8vr2a"; + authors = [ + "Andronik Ordian <write@reusable.software>" + "Ed Page <eopage@gmail.com>" + ]; + dependencies = [ + { + name = "indexmap"; + packageId = "indexmap 2.6.0"; + features = [ "std" ]; + } + { + name = "serde"; + packageId = "serde"; + optional = true; + } + { + name = "serde_spanned"; + packageId = "serde_spanned"; + optional = true; + features = [ "serde" ]; + } + { + name = "toml_datetime"; + packageId = "toml_datetime 0.6.8"; + } + { + name = "winnow"; + packageId = "winnow"; + optional = true; + } + ]; + features = { + "default" = [ "parse" "display" ]; + "parse" = [ "dep:winnow" ]; + "perf" = [ "dep:kstring" ]; + "serde" = [ "dep:serde" "toml_datetime/serde" "dep:serde_spanned" ]; + }; + resolvedDefaultFeatures = [ "display" "parse" "serde" ]; + }; + "tonic" = rec { crateName = "tonic"; - version = "0.11.0"; + version = "0.12.3"; edition = "2021"; - sha256 = "04qsr527i256i3dk9dp1g2jr42q7yl91y5h06rvd9ycy9rxfpi3n"; + sha256 = "0ljd1lfjpw0vrm5wbv15x6nq2i38llsanls5rkzmdn2n0wrmnz47"; authors = [ "Lucio Franco <luciofranco14@gmail.com>" ]; @@ -12513,13 +13757,13 @@ rec { } { name = "axum"; - packageId = "axum 0.6.20"; + packageId = "axum"; optional = true; usesDefaultFeatures = false; } { name = "base64"; - packageId = "base64"; + packageId = "base64 0.22.1"; } { name = "bytes"; @@ -12527,22 +13771,26 @@ rec { } { name = "h2"; - packageId = "h2 0.3.24"; + packageId = "h2"; optional = true; } { name = "http"; - packageId = "http 0.2.11"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 0.4.6"; + packageId = "http-body"; + } + { + name = "http-body-util"; + packageId = "http-body-util"; } { name = "hyper"; - packageId = "hyper 0.14.28"; + packageId = "hyper"; optional = true; - features = [ "full" ]; + features = [ "http1" "http2" ]; } { name = "hyper-timeout"; @@ -12550,6 +13798,12 @@ rec { optional = true; } { + name = "hyper-util"; + packageId = "hyper-util"; + optional = true; + features = [ "tokio" ]; + } + { name = "percent-encoding"; packageId = "percent-encoding"; } @@ -12559,45 +13813,50 @@ rec { } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; optional = true; usesDefaultFeatures = false; features = [ "std" ]; } { name = "rustls-native-certs"; - packageId = "rustls-native-certs 0.7.0"; + packageId = "rustls-native-certs"; optional = true; } { name = "rustls-pemfile"; - packageId = "rustls-pemfile 2.1.0"; + packageId = "rustls-pemfile"; optional = true; } { - name = "rustls-pki-types"; - packageId = "rustls-pki-types"; + name = "socket2"; + packageId = "socket2"; optional = true; + features = [ "all" ]; } { name = "tokio"; packageId = "tokio"; + optional = true; + usesDefaultFeatures = false; } { name = "tokio-rustls"; - packageId = "tokio-rustls 0.25.0"; + packageId = "tokio-rustls"; optional = true; + usesDefaultFeatures = false; + features = [ "logging" "tls12" "ring" ]; } { name = "tokio-stream"; packageId = "tokio-stream"; + usesDefaultFeatures = false; } { name = "tower"; - packageId = "tower"; + packageId = "tower 0.4.13"; optional = true; usesDefaultFeatures = false; - features = [ "balance" "buffer" "discover" "limit" "load" "make" "timeout" "util" ]; } { name = "tower-layer"; @@ -12620,201 +13879,127 @@ rec { } { name = "tower"; - packageId = "tower"; + packageId = "tower 0.4.13"; features = [ "full" ]; } ]; features = { + "channel" = [ "dep:hyper" "hyper?/client" "dep:hyper-util" "hyper-util?/client-legacy" "dep:tower" "tower?/balance" "tower?/buffer" "tower?/discover" "tower?/limit" "tower?/util" "dep:tokio" "tokio?/time" "dep:hyper-timeout" ]; "codegen" = [ "dep:async-trait" ]; "default" = [ "transport" "codegen" "prost" ]; "gzip" = [ "dep:flate2" ]; "prost" = [ "dep:prost" ]; - "tls" = [ "dep:rustls-pki-types" "dep:rustls-pemfile" "transport" "dep:tokio-rustls" "tokio/rt" "tokio/macros" ]; - "tls-roots" = [ "tls-roots-common" "dep:rustls-native-certs" ]; - "tls-roots-common" = [ "tls" ]; - "tls-webpki-roots" = [ "tls-roots-common" "dep:webpki-roots" ]; - "transport" = [ "dep:async-stream" "dep:axum" "channel" "dep:h2" "dep:hyper" "tokio/net" "tokio/time" "dep:tower" "dep:hyper-timeout" ]; + "router" = [ "dep:axum" "dep:tower" "tower?/util" ]; + "server" = [ "router" "dep:async-stream" "dep:h2" "dep:hyper" "hyper?/server" "dep:hyper-util" "hyper-util?/service" "hyper-util?/server-auto" "dep:socket2" "dep:tokio" "tokio?/macros" "tokio?/net" "tokio?/time" "tokio-stream/net" "dep:tower" "tower?/util" "tower?/limit" ]; + "tls" = [ "dep:rustls-pemfile" "dep:tokio-rustls" "dep:tokio" "tokio?/rt" "tokio?/macros" ]; + "tls-native-roots" = [ "tls" "channel" "dep:rustls-native-certs" ]; + "tls-roots" = [ "tls-native-roots" ]; + "tls-webpki-roots" = [ "tls" "channel" "dep:webpki-roots" ]; + "transport" = [ "server" "channel" ]; "zstd" = [ "dep:zstd" ]; }; - resolvedDefaultFeatures = [ "channel" "codegen" "default" "prost" "tls" "tls-roots" "tls-roots-common" "transport" ]; + resolvedDefaultFeatures = [ "channel" "codegen" "default" "prost" "router" "server" "tls" "tls-native-roots" "tls-roots" "transport" ]; }; - "tonic 0.9.2" = rec { - crateName = "tonic"; - version = "0.9.2"; + "tonic-build" = rec { + crateName = "tonic-build"; + version = "0.12.3"; edition = "2021"; - sha256 = "0nlx35lvah5hdcp6lg1d6dlprq0zz8ijj6f727szfcv479m6d0ih"; + sha256 = "04baqblgrlc0g8scnhpky5s0n4cljaixrrdrr6cv6wx7kq8cwmwm"; + libName = "tonic_build"; authors = [ "Lucio Franco <luciofranco14@gmail.com>" ]; dependencies = [ { - name = "async-trait"; - packageId = "async-trait"; - optional = true; - } - { - name = "axum"; - packageId = "axum 0.6.20"; - optional = true; - usesDefaultFeatures = false; - } - { - name = "base64"; - packageId = "base64"; - } - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "futures-core"; - packageId = "futures-core"; - usesDefaultFeatures = false; + name = "prettyplease"; + packageId = "prettyplease"; } { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; + name = "proc-macro2"; + packageId = "proc-macro2"; } { - name = "h2"; - packageId = "h2 0.3.24"; + name = "prost-build"; + packageId = "prost-build"; optional = true; } { - name = "http"; - packageId = "http 0.2.11"; - } - { - name = "http-body"; - packageId = "http-body 0.4.6"; - } - { - name = "hyper"; - packageId = "hyper 0.14.28"; + name = "prost-types"; + packageId = "prost-types"; optional = true; - features = [ "full" ]; } { - name = "hyper-timeout"; - packageId = "hyper-timeout"; - optional = true; + name = "quote"; + packageId = "quote"; } { - name = "percent-encoding"; - packageId = "percent-encoding"; + name = "syn"; + packageId = "syn 2.0.79"; } + ]; + features = { + "cleanup-markdown" = [ "prost" "prost-build/cleanup-markdown" ]; + "default" = [ "transport" "prost" ]; + "prost" = [ "prost-build" "dep:prost-types" ]; + "prost-build" = [ "dep:prost-build" ]; + }; + resolvedDefaultFeatures = [ "cleanup-markdown" "default" "prost" "prost-build" "transport" ]; + }; + "tonic-health" = rec { + crateName = "tonic-health"; + version = "0.12.3"; + edition = "2021"; + sha256 = "1ch97bilfc8djdzhxaq1v4kvbj9kk51daqhic1f0y4hjp3fk9bqy"; + libName = "tonic_health"; + authors = [ + "James Nugent <james@jen20.com>" + ]; + dependencies = [ { - name = "pin-project"; - packageId = "pin-project"; + name = "async-stream"; + packageId = "async-stream"; } { name = "prost"; - packageId = "prost 0.11.9"; - optional = true; - usesDefaultFeatures = false; - features = [ "std" ]; + packageId = "prost"; } { name = "tokio"; packageId = "tokio"; - optional = true; - features = [ "net" "time" "macros" ]; + features = [ "sync" ]; } { name = "tokio-stream"; packageId = "tokio-stream"; } { - name = "tower"; - packageId = "tower"; - optional = true; + name = "tonic"; + packageId = "tonic"; usesDefaultFeatures = false; - features = [ "balance" "buffer" "discover" "limit" "load" "make" "timeout" "util" ]; - } - { - name = "tower-layer"; - packageId = "tower-layer"; - } - { - name = "tower-service"; - packageId = "tower-service"; - } - { - name = "tracing"; - packageId = "tracing"; + features = [ "codegen" "prost" ]; } ]; devDependencies = [ { name = "tokio"; packageId = "tokio"; - features = [ "rt" "macros" ]; - } - { - name = "tower"; - packageId = "tower"; - features = [ "full" ]; - } - ]; - features = { - "channel" = [ "dep:h2" "dep:hyper" "dep:tokio" "dep:tower" "dep:hyper-timeout" ]; - "codegen" = [ "dep:async-trait" ]; - "default" = [ "transport" "codegen" "prost" ]; - "gzip" = [ "dep:flate2" ]; - "prost" = [ "dep:prost" ]; - "tls" = [ "dep:rustls-pemfile" "transport" "dep:tokio-rustls" "dep:async-stream" ]; - "tls-roots" = [ "tls-roots-common" "dep:rustls-native-certs" ]; - "tls-roots-common" = [ "tls" ]; - "tls-webpki-roots" = [ "tls-roots-common" "dep:webpki-roots" ]; - "transport" = [ "dep:axum" "channel" ]; - }; - resolvedDefaultFeatures = [ "channel" "codegen" "default" "prost" "transport" ]; - }; - "tonic-build" = rec { - crateName = "tonic-build"; - version = "0.11.0"; - edition = "2021"; - sha256 = "1hm99ckaw0pzq8h22bdjy6gpbg06kpvs0f73nj60f456f3fzckmy"; - authors = [ - "Lucio Franco <luciofranco14@gmail.com>" - ]; - dependencies = [ - { - name = "prettyplease"; - packageId = "prettyplease"; - } - { - name = "proc-macro2"; - packageId = "proc-macro2"; - } - { - name = "prost-build"; - packageId = "prost-build"; - optional = true; - } - { - name = "quote"; - packageId = "quote"; + features = [ "rt-multi-thread" "macros" ]; } { - name = "syn"; - packageId = "syn 2.0.48"; + name = "tokio-stream"; + packageId = "tokio-stream"; } ]; features = { - "cleanup-markdown" = [ "prost" "prost-build/cleanup-markdown" ]; - "default" = [ "transport" "prost" ]; - "prost" = [ "prost-build" ]; - "prost-build" = [ "dep:prost-build" ]; + "default" = [ "transport" ]; }; - resolvedDefaultFeatures = [ "cleanup-markdown" "default" "prost" "prost-build" "transport" ]; }; "tonic-reflection" = rec { crateName = "tonic-reflection"; - version = "0.11.0"; + version = "0.12.3"; edition = "2021"; - sha256 = "19xn3kyg062d7y1cnw537v9cxkzzcrnfri0jb29fbyn0smxj532l"; + sha256 = "09xs7h268jyf1mzzi1x97djw7cvqnnlvdzdp4q0dikvz5vsq33c7"; + libName = "tonic_reflection"; authors = [ "James Nugent <james@jen20.com>" "Samani G. Gikandi <samani@gojulas.com>" @@ -12822,7 +14007,7 @@ rec { dependencies = [ { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; } { name = "prost-types"; @@ -12843,7 +14028,7 @@ rec { } { name = "tonic"; - packageId = "tonic 0.11.0"; + packageId = "tonic"; usesDefaultFeatures = false; features = [ "codegen" "prost" ]; } @@ -12851,7 +14036,7 @@ rec { devDependencies = [ { name = "tonic"; - packageId = "tonic 0.11.0"; + packageId = "tonic"; usesDefaultFeatures = false; features = [ "transport" ]; } @@ -12863,7 +14048,7 @@ rec { }; resolvedDefaultFeatures = [ "default" "prost-types" "server" ]; }; - "tower" = rec { + "tower 0.4.13" = rec { crateName = "tower"; version = "0.4.13"; edition = "2018"; @@ -12982,13 +14167,211 @@ rec { "tracing" = [ "dep:tracing" ]; "util" = [ "__common" "futures-util" "pin-project" ]; }; - resolvedDefaultFeatures = [ "__common" "balance" "buffer" "default" "discover" "futures-core" "futures-util" "indexmap" "limit" "load" "log" "make" "pin-project" "pin-project-lite" "rand" "ready-cache" "slab" "timeout" "tokio" "tokio-util" "tracing" "util" ]; + resolvedDefaultFeatures = [ "__common" "balance" "buffer" "default" "discover" "futures-core" "futures-util" "indexmap" "limit" "load" "log" "make" "pin-project" "pin-project-lite" "rand" "ready-cache" "slab" "tokio" "tokio-util" "tracing" "util" ]; + }; + "tower 0.5.1" = rec { + crateName = "tower"; + version = "0.5.1"; + edition = "2018"; + sha256 = "0kvbp97bhb4sk24vhihcz74ngn0i4ygxqikmxndgng3w926r6wr8"; + authors = [ + "Tower Maintainers <team@tower-rs.com>" + ]; + dependencies = [ + { + name = "futures-core"; + packageId = "futures-core"; + optional = true; + } + { + name = "futures-util"; + packageId = "futures-util"; + optional = true; + usesDefaultFeatures = false; + features = [ "alloc" ]; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + optional = true; + } + { + name = "sync_wrapper"; + packageId = "sync_wrapper 0.1.2"; + optional = true; + } + { + name = "tokio"; + packageId = "tokio"; + optional = true; + features = [ "sync" ]; + } + { + name = "tower-layer"; + packageId = "tower-layer"; + } + { + name = "tower-service"; + packageId = "tower-service"; + } + { + name = "tracing"; + packageId = "tracing"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" ]; + } + ]; + devDependencies = [ + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "macros" "sync" "test-util" "rt-multi-thread" ]; + } + { + name = "tracing"; + packageId = "tracing"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + ]; + features = { + "__common" = [ "futures-core" "pin-project-lite" ]; + "balance" = [ "discover" "load" "ready-cache" "make" "slab" "util" ]; + "buffer" = [ "__common" "tokio/sync" "tokio/rt" "tokio-util" "tracing" ]; + "discover" = [ "__common" ]; + "filter" = [ "__common" "futures-util" ]; + "full" = [ "balance" "buffer" "discover" "filter" "hedge" "limit" "load" "load-shed" "make" "ready-cache" "reconnect" "retry" "spawn-ready" "steer" "timeout" "util" ]; + "futures-core" = [ "dep:futures-core" ]; + "futures-util" = [ "dep:futures-util" ]; + "hdrhistogram" = [ "dep:hdrhistogram" ]; + "hedge" = [ "util" "filter" "futures-util" "hdrhistogram" "tokio/time" "tracing" ]; + "indexmap" = [ "dep:indexmap" ]; + "limit" = [ "__common" "tokio/time" "tokio/sync" "tokio-util" "tracing" ]; + "load" = [ "__common" "tokio/time" "tracing" ]; + "load-shed" = [ "__common" ]; + "log" = [ "tracing/log" ]; + "make" = [ "futures-util" "pin-project-lite" "tokio/io-std" ]; + "pin-project-lite" = [ "dep:pin-project-lite" ]; + "ready-cache" = [ "futures-core" "futures-util" "indexmap" "tokio/sync" "tracing" "pin-project-lite" ]; + "reconnect" = [ "make" "tokio/io-std" "tracing" ]; + "retry" = [ "__common" "tokio/time" "util" ]; + "slab" = [ "dep:slab" ]; + "spawn-ready" = [ "__common" "futures-util" "tokio/sync" "tokio/rt" "util" "tracing" ]; + "sync_wrapper" = [ "dep:sync_wrapper" ]; + "timeout" = [ "pin-project-lite" "tokio/time" ]; + "tokio" = [ "dep:tokio" ]; + "tokio-stream" = [ "dep:tokio-stream" ]; + "tokio-util" = [ "dep:tokio-util" ]; + "tracing" = [ "dep:tracing" ]; + "util" = [ "__common" "futures-util" "pin-project-lite" "sync_wrapper" ]; + }; + resolvedDefaultFeatures = [ "__common" "futures-core" "futures-util" "log" "make" "pin-project-lite" "sync_wrapper" "tokio" "tracing" "util" ]; + }; + "tower-http" = rec { + crateName = "tower-http"; + version = "0.5.2"; + edition = "2018"; + sha256 = "1xakj3x0anp55gjqibiwvzma5iz0w9pcjsr7qk97sx4qm4sd970y"; + libName = "tower_http"; + authors = [ + "Tower Maintainers <team@tower-rs.com>" + ]; + dependencies = [ + { + name = "bitflags"; + packageId = "bitflags 2.6.0"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "http"; + packageId = "http"; + } + { + name = "http-body"; + packageId = "http-body"; + } + { + name = "http-body-util"; + packageId = "http-body-util"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tower-layer"; + packageId = "tower-layer"; + } + { + name = "tower-service"; + packageId = "tower-service"; + } + { + name = "tracing"; + packageId = "tracing"; + optional = true; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "bytes"; + packageId = "bytes"; + } + ]; + features = { + "async-compression" = [ "dep:async-compression" ]; + "auth" = [ "base64" "validate-request" ]; + "base64" = [ "dep:base64" ]; + "catch-panic" = [ "tracing" "futures-util/std" ]; + "compression-br" = [ "async-compression/brotli" "futures-core" "tokio-util" "tokio" ]; + "compression-deflate" = [ "async-compression/zlib" "futures-core" "tokio-util" "tokio" ]; + "compression-full" = [ "compression-br" "compression-deflate" "compression-gzip" "compression-zstd" ]; + "compression-gzip" = [ "async-compression/gzip" "futures-core" "tokio-util" "tokio" ]; + "compression-zstd" = [ "async-compression/zstd" "futures-core" "tokio-util" "tokio" ]; + "decompression-br" = [ "async-compression/brotli" "futures-core" "tokio-util" "tokio" ]; + "decompression-deflate" = [ "async-compression/zlib" "futures-core" "tokio-util" "tokio" ]; + "decompression-full" = [ "decompression-br" "decompression-deflate" "decompression-gzip" "decompression-zstd" ]; + "decompression-gzip" = [ "async-compression/gzip" "futures-core" "tokio-util" "tokio" ]; + "decompression-zstd" = [ "async-compression/zstd" "futures-core" "tokio-util" "tokio" ]; + "follow-redirect" = [ "futures-util" "iri-string" "tower/util" ]; + "fs" = [ "futures-util" "tokio/fs" "tokio-util/io" "tokio/io-util" "dep:http-range-header" "mime_guess" "mime" "percent-encoding" "httpdate" "set-status" "futures-util/alloc" "tracing" ]; + "full" = [ "add-extension" "auth" "catch-panic" "compression-full" "cors" "decompression-full" "follow-redirect" "fs" "limit" "map-request-body" "map-response-body" "metrics" "normalize-path" "propagate-header" "redirect" "request-id" "sensitive-headers" "set-header" "set-status" "timeout" "trace" "util" "validate-request" ]; + "futures-core" = [ "dep:futures-core" ]; + "futures-util" = [ "dep:futures-util" ]; + "httpdate" = [ "dep:httpdate" ]; + "iri-string" = [ "dep:iri-string" ]; + "metrics" = [ "tokio/time" ]; + "mime" = [ "dep:mime" ]; + "mime_guess" = [ "dep:mime_guess" ]; + "percent-encoding" = [ "dep:percent-encoding" ]; + "request-id" = [ "uuid" ]; + "timeout" = [ "tokio/time" ]; + "tokio" = [ "dep:tokio" ]; + "tokio-util" = [ "dep:tokio-util" ]; + "tower" = [ "dep:tower" ]; + "trace" = [ "tracing" ]; + "tracing" = [ "dep:tracing" ]; + "util" = [ "tower" ]; + "uuid" = [ "dep:uuid" ]; + "validate-request" = [ "mime" ]; + }; + resolvedDefaultFeatures = [ "default" "trace" "tracing" ]; }; "tower-layer" = rec { crateName = "tower-layer"; - version = "0.3.2"; + version = "0.3.3"; edition = "2018"; - sha256 = "1l7i17k9vlssrdg4s3b0ia5jjkmmxsvv8s9y9ih0jfi8ssz8s362"; + sha256 = "03kq92fdzxin51w8iqix06dcfgydyvx7yr6izjq0p626v9n2l70j"; + libName = "tower_layer"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -12996,9 +14379,10 @@ rec { }; "tower-service" = rec { crateName = "tower-service"; - version = "0.3.2"; + version = "0.3.3"; edition = "2018"; - sha256 = "0lmfzmmvid2yp2l36mbavhmqgsvzqf7r2wiwz73ml4xmwaf1rg5n"; + sha256 = "1hzfkvkci33ra94xjx64vv3pp0sq346w06fpkcdwjcid7zhvdycd"; + libName = "tower_service"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -13049,7 +14433,7 @@ rec { "tracing-attributes" = [ "dep:tracing-attributes" ]; "valuable" = [ "tracing-core/valuable" ]; }; - resolvedDefaultFeatures = [ "attributes" "default" "log" "max_level_trace" "release_max_level_info" "std" "tracing-attributes" ]; + resolvedDefaultFeatures = [ "attributes" "default" "log" "max_level_trace" "release_max_level_debug" "std" "tracing-attributes" ]; }; "tracing-attributes" = rec { crateName = "tracing-attributes"; @@ -13057,6 +14441,7 @@ rec { edition = "2018"; sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; procMacro = true; + libName = "tracing_attributes"; authors = [ "Tokio Contributors <team@tokio.rs>" "Eliza Weisman <eliza@buoyant.io>" @@ -13073,7 +14458,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; usesDefaultFeatures = false; features = [ "full" "parsing" "printing" "visit-mut" "clone-impls" "extra-traits" "proc-macro" ]; } @@ -13085,6 +14470,7 @@ rec { version = "0.1.32"; edition = "2018"; sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -13115,6 +14501,7 @@ rec { version = "0.2.5"; edition = "2018"; sha256 = "1wimg0iwa2ldq7xv98lvivvf3q9ykfminig8r1bs0ig22np9bl4p"; + libName = "tracing_futures"; authors = [ "Eliza Weisman <eliza@buoyant.io>" "Tokio Contributors <team@tokio.rs>" @@ -13146,11 +14533,39 @@ rec { }; resolvedDefaultFeatures = [ "default" "pin-project" "std" "std-future" ]; }; + "tracing-indicatif" = rec { + crateName = "tracing-indicatif"; + version = "0.3.6"; + edition = "2021"; + sha256 = "07cmn4ilw8hdfzc1mirccwkgl160k3x9fhgg7xydj4gy9r181586"; + libName = "tracing_indicatif"; + dependencies = [ + { + name = "indicatif"; + packageId = "indicatif"; + features = [ "in_memory" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "tracing-core"; + packageId = "tracing-core"; + } + { + name = "tracing-subscriber"; + packageId = "tracing-subscriber"; + } + ]; + + }; "tracing-log" = rec { crateName = "tracing-log"; version = "0.2.0"; edition = "2018"; sha256 = "1hs77z026k730ij1a9dhahzrl0s073gfa2hm5p0fbl0b80gmz1gf"; + libName = "tracing_log"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -13177,11 +14592,12 @@ rec { }; resolvedDefaultFeatures = [ "log-tracer" "std" ]; }; - "tracing-opentelemetry" = rec { + "tracing-opentelemetry 0.23.0" = rec { crateName = "tracing-opentelemetry"; - version = "0.22.0"; + version = "0.23.0"; edition = "2018"; - sha256 = "15jmwmbp6wz15bx20bfsmabx53wmlnd7wvzwz9hvkrq7aifc4yn6"; + sha256 = "1112kmckw0qwyckhbwarb230n4ldmfgzixr9jagbfjmy3fx19gm9"; + libName = "tracing_opentelemetry"; authors = [ "Julian Tescher <julian@tescher.me>" "Tokio Contributors <team@tokio.rs>" @@ -13198,13 +14614,13 @@ rec { } { name = "opentelemetry"; - packageId = "opentelemetry"; + packageId = "opentelemetry 0.22.0"; usesDefaultFeatures = false; features = [ "trace" ]; } { name = "opentelemetry_sdk"; - packageId = "opentelemetry_sdk"; + packageId = "opentelemetry_sdk 0.22.1"; usesDefaultFeatures = false; features = [ "trace" ]; } @@ -13244,12 +14660,12 @@ rec { devDependencies = [ { name = "opentelemetry"; - packageId = "opentelemetry"; + packageId = "opentelemetry 0.22.0"; features = [ "trace" "metrics" ]; } { name = "opentelemetry_sdk"; - packageId = "opentelemetry_sdk"; + packageId = "opentelemetry_sdk 0.22.1"; usesDefaultFeatures = false; features = [ "trace" "rt-tokio" ]; } @@ -13269,6 +14685,7 @@ rec { features = { "async-trait" = [ "dep:async-trait" ]; "default" = [ "tracing-log" "metrics" ]; + "futures-util" = [ "dep:futures-util" ]; "metrics" = [ "opentelemetry/metrics" "opentelemetry_sdk/metrics" "smallvec" ]; "smallvec" = [ "dep:smallvec" ]; "thiserror" = [ "dep:thiserror" ]; @@ -13276,35 +14693,111 @@ rec { }; resolvedDefaultFeatures = [ "default" "metrics" "smallvec" "tracing-log" ]; }; - "tracing-serde" = rec { - crateName = "tracing-serde"; - version = "0.1.3"; - edition = "2018"; - sha256 = "1qfr0va69djvxqvjrx4vqq7p6myy414lx4w1f6amcn0hfwqj2sxw"; - authors = [ - "Tokio Contributors <team@tokio.rs>" - ]; + "tracing-opentelemetry 0.25.0" = rec { + crateName = "tracing-opentelemetry"; + version = "0.25.0"; + edition = "2021"; + sha256 = "0fzzhpcxngnxra56cxmslr5y6k0f1b4ghqv9vz41p4kxvba4wy59"; + libName = "tracing_opentelemetry"; dependencies = [ { - name = "serde"; - packageId = "serde"; + name = "js-sys"; + packageId = "js-sys"; + target = { target, features }: (("wasm32" == target."arch" or null) && (!("wasi" == target."os" or null))); + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "opentelemetry"; + packageId = "opentelemetry 0.24.0"; + usesDefaultFeatures = false; + features = [ "trace" ]; + } + { + name = "opentelemetry_sdk"; + packageId = "opentelemetry_sdk 0.24.1"; + usesDefaultFeatures = false; + features = [ "trace" ]; + } + { + name = "smallvec"; + packageId = "smallvec"; + optional = true; + } + { + name = "tracing"; + packageId = "tracing"; + usesDefaultFeatures = false; + features = [ "std" ]; } { name = "tracing-core"; packageId = "tracing-core"; } + { + name = "tracing-log"; + packageId = "tracing-log"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "tracing-subscriber"; + packageId = "tracing-subscriber"; + usesDefaultFeatures = false; + features = [ "registry" "std" ]; + } + { + name = "web-time"; + packageId = "web-time"; + target = { target, features }: (("wasm32" == target."arch" or null) && (!("wasi" == target."os" or null))); + } + ]; + devDependencies = [ + { + name = "opentelemetry"; + packageId = "opentelemetry 0.24.0"; + features = [ "trace" "metrics" ]; + } + { + name = "opentelemetry_sdk"; + packageId = "opentelemetry_sdk 0.24.1"; + usesDefaultFeatures = false; + features = [ "trace" "rt-tokio" ]; + } + { + name = "tracing"; + packageId = "tracing"; + usesDefaultFeatures = false; + features = [ "std" "attributes" ]; + } + { + name = "tracing-subscriber"; + packageId = "tracing-subscriber"; + usesDefaultFeatures = false; + features = [ "registry" "std" "fmt" ]; + } ]; features = { - "valuable" = [ "valuable_crate" "valuable-serde" "tracing-core/valuable" ]; - "valuable-serde" = [ "dep:valuable-serde" ]; - "valuable_crate" = [ "dep:valuable_crate" ]; + "async-trait" = [ "dep:async-trait" ]; + "default" = [ "tracing-log" "metrics" ]; + "futures-util" = [ "dep:futures-util" ]; + "lazy_static" = [ "dep:lazy_static" ]; + "metrics" = [ "opentelemetry/metrics" "opentelemetry_sdk/metrics" "smallvec" ]; + "metrics_gauge_unstable" = [ "opentelemetry/otel_unstable" ]; + "smallvec" = [ "dep:smallvec" ]; + "thiserror" = [ "dep:thiserror" ]; + "tracing-log" = [ "dep:tracing-log" ]; }; + resolvedDefaultFeatures = [ "default" "metrics" "smallvec" "tracing-log" ]; }; "tracing-subscriber" = rec { crateName = "tracing-subscriber"; version = "0.3.18"; edition = "2018"; sha256 = "12vs1bwk4kig1l2qqjbbn2nm5amwiqmkcmnznylzmnfvjy6083xd"; + libName = "tracing_subscriber"; authors = [ "Eliza Weisman <eliza@buoyant.io>" "David Barsky <me@davidbarsky.com>" @@ -13334,16 +14827,6 @@ rec { features = [ "std" "unicode-case" "unicode-perl" ]; } { - name = "serde"; - packageId = "serde"; - optional = true; - } - { - name = "serde_json"; - packageId = "serde_json"; - optional = true; - } - { name = "sharded-slab"; packageId = "sharded-slab"; optional = true; @@ -13376,11 +14859,6 @@ rec { usesDefaultFeatures = false; features = [ "log-tracer" "std" ]; } - { - name = "tracing-serde"; - packageId = "tracing-serde"; - optional = true; - } ]; devDependencies = [ { @@ -13426,18 +14904,181 @@ rec { "valuable-serde" = [ "dep:valuable-serde" ]; "valuable_crate" = [ "dep:valuable_crate" ]; }; - resolvedDefaultFeatures = [ "alloc" "ansi" "default" "env-filter" "fmt" "json" "matchers" "nu-ansi-term" "once_cell" "regex" "registry" "serde" "serde_json" "sharded-slab" "smallvec" "std" "thread_local" "tracing" "tracing-log" "tracing-serde" ]; + resolvedDefaultFeatures = [ "alloc" "ansi" "default" "env-filter" "fmt" "matchers" "nu-ansi-term" "once_cell" "regex" "registry" "sharded-slab" "smallvec" "std" "thread_local" "tracing" "tracing-log" ]; + }; + "tracing-tracy" = rec { + crateName = "tracing-tracy"; + version = "0.11.3"; + edition = "2021"; + sha256 = "00jrxs5pp00h2b591hydgp34p4c7bvk2jirmvhczsg9wygd5yxyw"; + libName = "tracing_tracy"; + authors = [ + "Simonas Kazlauskas <tracing-tracy@kazlauskas.me>" + ]; + dependencies = [ + { + name = "tracing-core"; + packageId = "tracing-core"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "tracing-subscriber"; + packageId = "tracing-subscriber"; + usesDefaultFeatures = false; + features = [ "fmt" "registry" ]; + } + { + name = "tracy-client"; + packageId = "tracy-client"; + rename = "client"; + usesDefaultFeatures = false; + } + ]; + features = { + "broadcast" = [ "client/broadcast" ]; + "callstack-inlines" = [ "client/callstack-inlines" ]; + "code-transfer" = [ "client/code-transfer" ]; + "context-switch-tracing" = [ "client/context-switch-tracing" ]; + "debuginfod" = [ "client/debuginfod" ]; + "default" = [ "enable" "system-tracing" "context-switch-tracing" "sampling" "code-transfer" "broadcast" "callstack-inlines" ]; + "delayed-init" = [ "client/delayed-init" ]; + "demangle" = [ "client/demangle" ]; + "enable" = [ "client/enable" ]; + "fibers" = [ "client/fibers" ]; + "flush-on-exit" = [ "client/flush-on-exit" ]; + "manual-lifetime" = [ "client/manual-lifetime" ]; + "ondemand" = [ "client/ondemand" ]; + "only-ipv4" = [ "client/only-ipv4" ]; + "only-localhost" = [ "client/only-localhost" ]; + "sampling" = [ "client/sampling" ]; + "system-tracing" = [ "client/system-tracing" ]; + "timer-fallback" = [ "client/timer-fallback" ]; + "verify" = [ "client/verify" ]; + }; + resolvedDefaultFeatures = [ "broadcast" "callstack-inlines" "code-transfer" "context-switch-tracing" "default" "enable" "flush-on-exit" "sampling" "system-tracing" ]; + }; + "tracy-client" = rec { + crateName = "tracy-client"; + version = "0.17.4"; + edition = "2021"; + sha256 = "1g1m6k95963lrq3apski8qq5qwqnf7h4k430jiazvsq9da60fsvl"; + libName = "tracy_client"; + authors = [ + "Simonas Kazlauskas <tracy-client@kazlauskas.me>" + ]; + dependencies = [ + { + name = "loom"; + packageId = "loom"; + target = { target, features }: (target."loom" or false); + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "tracy-client-sys"; + packageId = "tracy-client-sys"; + rename = "sys"; + usesDefaultFeatures = false; + } + ]; + features = { + "broadcast" = [ "sys/broadcast" ]; + "callstack-inlines" = [ "sys/callstack-inlines" ]; + "code-transfer" = [ "sys/code-transfer" ]; + "context-switch-tracing" = [ "sys/context-switch-tracing" ]; + "debuginfod" = [ "sys/debuginfod" ]; + "default" = [ "enable" "system-tracing" "context-switch-tracing" "sampling" "code-transfer" "broadcast" "callstack-inlines" ]; + "delayed-init" = [ "sys/delayed-init" ]; + "demangle" = [ "sys/demangle" "dep:rustc-demangle" ]; + "enable" = [ "sys/enable" ]; + "fibers" = [ "sys/fibers" ]; + "flush-on-exit" = [ "sys/flush-on-exit" ]; + "manual-lifetime" = [ "sys/manual-lifetime" ]; + "ondemand" = [ "sys/ondemand" ]; + "only-ipv4" = [ "sys/only-ipv4" ]; + "only-localhost" = [ "sys/only-localhost" ]; + "sampling" = [ "sys/sampling" ]; + "system-tracing" = [ "sys/system-tracing" ]; + "timer-fallback" = [ "sys/timer-fallback" ]; + "verify" = [ "sys/verify" ]; + }; + resolvedDefaultFeatures = [ "broadcast" "callstack-inlines" "code-transfer" "context-switch-tracing" "enable" "flush-on-exit" "sampling" "system-tracing" ]; + }; + "tracy-client-sys" = rec { + crateName = "tracy-client-sys"; + version = "0.24.1"; + edition = "2021"; + sha256 = "0k8l393zn0clw3bvg9nm8yra0qklspvmbyn5mfzgs0i325k38qb8"; + libName = "tracy_client_sys"; + authors = [ + "Simonas Kazlauskas <tracy-client-sys@kazlauskas.me>" + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "enable" "system-tracing" "context-switch-tracing" "sampling" "code-transfer" "broadcast" "callstack-inlines" ]; + "manual-lifetime" = [ "delayed-init" ]; + }; + resolvedDefaultFeatures = [ "broadcast" "callstack-inlines" "code-transfer" "context-switch-tracing" "enable" "flush-on-exit" "sampling" "system-tracing" ]; }; "try-lock" = rec { crateName = "try-lock"; version = "0.2.5"; edition = "2015"; sha256 = "0jqijrrvm1pyq34zn1jmy2vihd4jcrjlvsh4alkjahhssjnsn8g4"; + libName = "try_lock"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; }; + "trybuild" = rec { + crateName = "trybuild"; + version = "1.0.99"; + edition = "2021"; + sha256 = "1s4i2hpyb66676xkg6b6fxm2qdsawj5lfad8ds68vgn46q6sayi0"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "glob"; + packageId = "glob"; + } + { + name = "serde"; + packageId = "serde"; + } + { + name = "serde_derive"; + packageId = "serde_derive"; + } + { + name = "serde_json"; + packageId = "serde_json"; + } + { + name = "termcolor"; + packageId = "termcolor"; + } + { + name = "toml"; + packageId = "toml 0.8.19"; + } + ]; + features = { + "diff" = [ "dissimilar" ]; + "dissimilar" = [ "dep:dissimilar" ]; + }; + }; "tvix-build" = rec { crateName = "tvix-build"; version = "0.1.0"; @@ -13449,14 +15090,22 @@ rec { requiredFeatures = [ ]; } ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./build; } - else ./build; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./build; }; + libName = "tvix_build"; dependencies = [ { + name = "anyhow"; + packageId = "anyhow"; + } + { + name = "blake3"; + packageId = "blake3"; + } + { + name = "bstr"; + packageId = "bstr"; + } + { name = "bytes"; packageId = "bytes"; } @@ -13466,12 +15115,32 @@ rec { features = [ "derive" "env" ]; } { + name = "data-encoding"; + packageId = "data-encoding"; + } + { + name = "futures"; + packageId = "futures"; + } + { name = "itertools"; - packageId = "itertools 0.12.0"; + packageId = "itertools 0.12.1"; + } + { + name = "mimalloc"; + packageId = "mimalloc"; + } + { + name = "oci-spec"; + packageId = "oci-spec"; } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; + } + { + name = "serde_json"; + packageId = "serde_json"; } { name = "thiserror"; @@ -13480,15 +15149,16 @@ rec { { name = "tokio"; packageId = "tokio"; + features = [ "process" ]; } { name = "tokio-listener"; packageId = "tokio-listener"; - features = [ "tonic011" ]; + features = [ "tonic012" ]; } { name = "tonic"; - packageId = "tonic 0.11.0"; + packageId = "tonic"; features = [ "tls" "tls-roots" ]; } { @@ -13501,18 +15171,23 @@ rec { packageId = "tracing"; } { - name = "tracing-subscriber"; - packageId = "tracing-subscriber"; - features = [ "json" ]; - } - { name = "tvix-castore"; packageId = "tvix-castore"; + features = [ "fuse" ]; + } + { + name = "tvix-tracing"; + packageId = "tvix-tracing"; } { name = "url"; packageId = "url"; } + { + name = "uuid"; + packageId = "uuid"; + features = [ "v4" ]; + } ]; buildDependencies = [ { @@ -13529,9 +15204,13 @@ rec { name = "rstest"; packageId = "rstest"; } + { + name = "tempfile"; + packageId = "tempfile"; + } ]; features = { - "tonic-reflection" = [ "dep:tonic-reflection" ]; + "tonic-reflection" = [ "dep:tonic-reflection" "tvix-castore/tonic-reflection" ]; }; resolvedDefaultFeatures = [ "default" "tonic-reflection" ]; }; @@ -13539,14 +15218,15 @@ rec { crateName = "tvix-castore"; version = "0.1.0"; edition = "2021"; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./castore; } - else ./castore; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./castore; }; + libName = "tvix_castore"; dependencies = [ { + name = "async-compression"; + packageId = "async-compression"; + features = [ "tokio" "zstd" ]; + } + { name = "async-stream"; packageId = "async-stream"; } @@ -13555,6 +15235,10 @@ rec { packageId = "async-tempfile"; } { + name = "auto_impl"; + packageId = "auto_impl"; + } + { name = "bigtable_rs"; packageId = "bigtable_rs"; optional = true; @@ -13581,6 +15265,10 @@ rec { packageId = "digest"; } { + name = "erased-serde"; + packageId = "erased-serde"; + } + { name = "fastcdc"; packageId = "fastcdc"; features = [ "tokio" ]; @@ -13595,8 +15283,8 @@ rec { packageId = "futures"; } { - name = "lazy_static"; - packageId = "lazy_static"; + name = "hyper-util"; + packageId = "hyper-util"; } { name = "libc"; @@ -13610,19 +15298,28 @@ rec { } { name = "parking_lot"; - packageId = "parking_lot 0.12.1"; + packageId = "parking_lot"; } { name = "petgraph"; packageId = "petgraph"; } { + name = "pin-project"; + packageId = "pin-project"; + } + { name = "pin-project-lite"; packageId = "pin-project-lite"; } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; + } + { + name = "redb"; + packageId = "redb"; + features = [ "logging" ]; } { name = "serde"; @@ -13634,18 +15331,23 @@ rec { packageId = "serde_qs"; } { - name = "serde_with"; - packageId = "serde_with"; + name = "serde_tagged"; + packageId = "serde_tagged"; } { - name = "sled"; - packageId = "sled"; + name = "serde_with"; + packageId = "serde_with"; } { name = "thiserror"; packageId = "thiserror"; } { + name = "threadpool"; + packageId = "threadpool"; + optional = true; + } + { name = "tokio"; packageId = "tokio"; features = [ "fs" "macros" "net" "rt" "rt-multi-thread" "signal" ]; @@ -13662,11 +15364,11 @@ rec { { name = "tokio-util"; packageId = "tokio-util"; - features = [ "io" "io-util" ]; + features = [ "io" "io-util" "codec" ]; } { name = "tonic"; - packageId = "tonic 0.11.0"; + packageId = "tonic"; } { name = "tonic-reflection"; @@ -13675,13 +15377,22 @@ rec { } { name = "tower"; - packageId = "tower"; + packageId = "tower 0.4.13"; } { name = "tracing"; packageId = "tracing"; } { + name = "tracing-indicatif"; + packageId = "tracing-indicatif"; + } + { + name = "tvix-tracing"; + packageId = "tvix-tracing"; + features = [ "tonic" ]; + } + { name = "url"; packageId = "url"; } @@ -13697,7 +15408,7 @@ rec { } { name = "virtio-bindings"; - packageId = "virtio-bindings 0.2.2"; + packageId = "virtio-bindings 0.2.3"; optional = true; } { @@ -13720,6 +15431,10 @@ rec { packageId = "walkdir"; } { + name = "wu-manber"; + packageId = "wu-manber"; + } + { name = "zstd"; packageId = "zstd"; } @@ -13752,6 +15467,10 @@ rec { packageId = "rstest_reuse"; } { + name = "serde_json"; + packageId = "serde_json"; + } + { name = "tempfile"; packageId = "tempfile"; } @@ -13760,18 +15479,23 @@ rec { packageId = "tokio-retry"; } { + name = "tokio-test"; + packageId = "tokio-test"; + } + { name = "xattr"; packageId = "xattr"; } ]; features = { "cloud" = [ "dep:bigtable_rs" "object_store/aws" "object_store/azure" "object_store/gcp" ]; - "fs" = [ "dep:libc" "dep:fuse-backend-rs" ]; + "default" = [ "cloud" ]; + "fs" = [ "dep:fuse-backend-rs" "dep:threadpool" "dep:libc" ]; "fuse" = [ "fs" ]; "tonic-reflection" = [ "dep:tonic-reflection" ]; "virtiofs" = [ "fs" "dep:vhost" "dep:vhost-user-backend" "dep:virtio-queue" "dep:vm-memory" "dep:vmm-sys-util" "dep:virtio-bindings" "fuse-backend-rs?/vhost-user-fs" "fuse-backend-rs?/virtiofs" ]; }; - resolvedDefaultFeatures = [ "cloud" "default" "fs" "fuse" "tonic-reflection" "virtiofs" ]; + resolvedDefaultFeatures = [ "cloud" "default" "fs" "fuse" "integration" "tonic-reflection" "virtiofs" "xp-store-composition" ]; }; "tvix-cli" = rec { crateName = "tvix-cli"; @@ -13784,12 +15508,8 @@ rec { requiredFeatures = [ ]; } ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./cli; } - else ./cli; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./cli; }; + libName = "tvix_cli"; dependencies = [ { name = "bytes"; @@ -13805,14 +15525,30 @@ rec { packageId = "dirs"; } { - name = "nix-compat"; - packageId = "nix-compat"; + name = "mimalloc"; + packageId = "mimalloc"; + } + { + name = "rnix"; + packageId = "rnix"; + } + { + name = "rowan"; + packageId = "rowan"; + } + { + name = "rustc-hash"; + packageId = "rustc-hash 2.0.0"; } { name = "rustyline"; packageId = "rustyline"; } { + name = "smol_str"; + packageId = "smol_str"; + } + { name = "thiserror"; packageId = "thiserror"; } @@ -13823,22 +15559,16 @@ rec { { name = "tracing"; packageId = "tracing"; - features = [ "max_level_trace" "release_max_level_info" ]; } { - name = "tracing-subscriber"; - packageId = "tracing-subscriber"; - features = [ "json" ]; + name = "tracing-indicatif"; + packageId = "tracing-indicatif"; } { name = "tvix-build"; packageId = "tvix-build"; } { - name = "tvix-castore"; - packageId = "tvix-castore"; - } - { name = "tvix-eval"; packageId = "tvix-eval"; } @@ -13852,22 +15582,30 @@ rec { usesDefaultFeatures = false; } { + name = "tvix-tracing"; + packageId = "tvix-tracing"; + } + { name = "wu-manber"; packageId = "wu-manber"; } ]; - + devDependencies = [ + { + name = "expect-test"; + packageId = "expect-test"; + } + ]; + features = { + "tracy" = [ "tvix-tracing/tracy" ]; + }; + resolvedDefaultFeatures = [ "default" "tracy" ]; }; "tvix-eval" = rec { crateName = "tvix-eval"; version = "0.1.0"; edition = "2021"; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./eval; } - else ./eval; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./eval; }; libName = "tvix_eval"; dependencies = [ { @@ -13901,17 +15639,8 @@ rec { usesDefaultFeatures = false; } { - name = "imbl"; - packageId = "imbl"; - features = [ "serde" ]; - } - { name = "itertools"; - packageId = "itertools 0.12.0"; - } - { - name = "lazy_static"; - packageId = "lazy_static"; + packageId = "itertools 0.12.1"; } { name = "lexical-core"; @@ -13923,6 +15652,10 @@ rec { packageId = "md-5"; } { + name = "nohash-hasher"; + packageId = "nohash-hasher"; + } + { name = "os_str_bytes"; packageId = "os_str_bytes"; features = [ "conversions" ]; @@ -13951,6 +15684,10 @@ rec { packageId = "rowan"; } { + name = "rustc-hash"; + packageId = "rustc-hash 2.0.0"; + } + { name = "serde"; packageId = "serde"; features = [ "rc" "derive" ]; @@ -13981,8 +15718,12 @@ rec { optional = true; } { + name = "thiserror"; + packageId = "thiserror"; + } + { name = "toml"; - packageId = "toml"; + packageId = "toml 0.6.0"; } { name = "tvix-eval-builtin-macros"; @@ -13990,8 +15731,8 @@ rec { rename = "builtin-macros"; } { - name = "xml-rs"; - packageId = "xml-rs"; + name = "vu128"; + packageId = "vu128"; } ]; devDependencies = [ @@ -14001,7 +15742,11 @@ rec { } { name = "itertools"; - packageId = "itertools 0.12.0"; + packageId = "itertools 0.12.1"; + } + { + name = "mimalloc"; + packageId = "mimalloc"; } { name = "pretty_assertions"; @@ -14017,24 +15762,20 @@ rec { } ]; features = { - "arbitrary" = [ "proptest" "test-strategy" "imbl/proptest" ]; + "arbitrary" = [ "proptest" "test-strategy" ]; "default" = [ "impure" "arbitrary" "nix_tests" ]; "proptest" = [ "dep:proptest" ]; "test-strategy" = [ "dep:test-strategy" ]; }; - resolvedDefaultFeatures = [ "arbitrary" "default" "impure" "nix_tests" "proptest" "test-strategy" ]; + resolvedDefaultFeatures = [ "arbitrary" "default" "impure" "nix_tests" "no_leak" "proptest" "test-strategy" ]; }; "tvix-eval-builtin-macros" = rec { crateName = "tvix-eval-builtin-macros"; version = "0.0.1"; edition = "2021"; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./eval/builtin-macros; } - else ./eval/builtin-macros; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./eval/builtin-macros; }; procMacro = true; + libName = "tvix_eval_builtin_macros"; authors = [ "Griffin Smith <root@gws.fyi>" ]; @@ -14065,12 +15806,8 @@ rec { crateName = "tvix-glue"; version = "0.1.0"; edition = "2021"; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./glue; } - else ./glue; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./glue; }; + libName = "tvix_glue"; dependencies = [ { name = "async-compression"; @@ -14078,10 +15815,6 @@ rec { features = [ "tokio" "gzip" "bzip2" "xz" ]; } { - name = "async-recursion"; - packageId = "async-recursion"; - } - { name = "bstr"; packageId = "bstr"; } @@ -14090,6 +15823,10 @@ rec { packageId = "bytes"; } { + name = "clap"; + packageId = "clap"; + } + { name = "data-encoding"; packageId = "data-encoding"; } @@ -14157,6 +15894,10 @@ rec { packageId = "tracing"; } { + name = "tracing-indicatif"; + packageId = "tracing-indicatif"; + } + { name = "tvix-build"; packageId = "tvix-build"; usesDefaultFeatures = false; @@ -14175,6 +15916,10 @@ rec { usesDefaultFeatures = false; } { + name = "tvix-tracing"; + packageId = "tvix-tracing"; + } + { name = "url"; packageId = "url"; } @@ -14182,10 +15927,6 @@ rec { name = "walkdir"; packageId = "walkdir"; } - { - name = "wu-manber"; - packageId = "wu-manber"; - } ]; devDependencies = [ { @@ -14198,8 +15939,8 @@ rec { packageId = "hex-literal"; } { - name = "lazy_static"; - packageId = "lazy_static"; + name = "mimalloc"; + packageId = "mimalloc"; } { name = "nix"; @@ -14228,12 +15969,8 @@ rec { crateName = "tvix-serde"; version = "0.1.0"; edition = "2021"; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./serde; } - else ./serde; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./serde; }; + libName = "tvix_serde"; dependencies = [ { name = "bstr"; @@ -14263,26 +16000,27 @@ rec { requiredFeatures = [ ]; } ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./store; } - else ./store; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./store; }; + libName = "tvix_store"; dependencies = [ { name = "anyhow"; packageId = "anyhow"; } { - name = "async-recursion"; - packageId = "async-recursion"; + name = "async-compression"; + packageId = "async-compression"; + features = [ "tokio" "bzip2" "gzip" "xz" "zstd" ]; } { name = "async-stream"; packageId = "async-stream"; } { + name = "auto_impl"; + packageId = "auto_impl"; + } + { name = "bigtable_rs"; packageId = "bigtable_rs"; optional = true; @@ -14314,33 +16052,37 @@ rec { packageId = "data-encoding"; } { + name = "ed25519"; + packageId = "ed25519"; + } + { + name = "ed25519-dalek"; + packageId = "ed25519-dalek"; + } + { name = "futures"; packageId = "futures"; } { - name = "lazy_static"; - packageId = "lazy_static"; + name = "hyper-util"; + packageId = "hyper-util"; } { - name = "nix-compat"; - packageId = "nix-compat"; - features = [ "async" ]; + name = "lru"; + packageId = "lru"; } { - name = "opentelemetry"; - packageId = "opentelemetry"; - optional = true; + name = "mimalloc"; + packageId = "mimalloc"; } { - name = "opentelemetry-otlp"; - packageId = "opentelemetry-otlp"; - optional = true; + name = "nix-compat"; + packageId = "nix-compat"; + features = [ "async" ]; } { - name = "opentelemetry_sdk"; - packageId = "opentelemetry_sdk"; - optional = true; - features = [ "rt-tokio" ]; + name = "parking_lot"; + packageId = "parking_lot"; } { name = "pin-project-lite"; @@ -14348,7 +16090,12 @@ rec { } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; + } + { + name = "redb"; + packageId = "redb"; + features = [ "logging" ]; } { name = "reqwest"; @@ -14357,6 +16104,10 @@ rec { features = [ "rustls-tls-native-roots" "stream" ]; } { + name = "reqwest-middleware"; + packageId = "reqwest-middleware"; + } + { name = "serde"; packageId = "serde"; features = [ "derive" ]; @@ -14378,10 +16129,6 @@ rec { packageId = "sha2"; } { - name = "sled"; - packageId = "sled"; - } - { name = "thiserror"; packageId = "thiserror"; } @@ -14393,7 +16140,7 @@ rec { { name = "tokio-listener"; packageId = "tokio-listener"; - features = [ "tonic011" ]; + features = [ "clap" "multi-listener" "sd_listen" "tonic012" ]; } { name = "tokio-stream"; @@ -14406,37 +16153,52 @@ rec { features = [ "io" "io-util" "compat" ]; } { + name = "toml"; + packageId = "toml 0.8.19"; + optional = true; + } + { name = "tonic"; - packageId = "tonic 0.11.0"; + packageId = "tonic"; features = [ "tls" "tls-roots" ]; } { + name = "tonic-health"; + packageId = "tonic-health"; + usesDefaultFeatures = false; + } + { name = "tonic-reflection"; packageId = "tonic-reflection"; optional = true; } { name = "tower"; - packageId = "tower"; + packageId = "tower 0.4.13"; } { - name = "tracing"; - packageId = "tracing"; + name = "tower-http"; + packageId = "tower-http"; + features = [ "trace" ]; } { - name = "tracing-opentelemetry"; - packageId = "tracing-opentelemetry"; + name = "tracing"; + packageId = "tracing"; } { - name = "tracing-subscriber"; - packageId = "tracing-subscriber"; - features = [ "env-filter" "json" ]; + name = "tracing-indicatif"; + packageId = "tracing-indicatif"; } { name = "tvix-castore"; packageId = "tvix-castore"; } { + name = "tvix-tracing"; + packageId = "tvix-tracing"; + features = [ "tonic" "reqwest" ]; + } + { name = "url"; packageId = "url"; } @@ -14444,10 +16206,6 @@ rec { name = "walkdir"; packageId = "walkdir"; } - { - name = "xz2"; - packageId = "xz2"; - } ]; buildDependencies = [ { @@ -14485,11 +16243,121 @@ rec { "cloud" = [ "dep:bigtable_rs" "tvix-castore/cloud" ]; "default" = [ "cloud" "fuse" "otlp" "tonic-reflection" ]; "fuse" = [ "tvix-castore/fuse" ]; - "otlp" = [ "dep:opentelemetry" "dep:opentelemetry-otlp" "dep:opentelemetry_sdk" ]; + "otlp" = [ "tvix-tracing/otlp" ]; + "toml" = [ "dep:toml" ]; "tonic-reflection" = [ "dep:tonic-reflection" "tvix-castore/tonic-reflection" ]; + "tracy" = [ "tvix-tracing/tracy" ]; "virtiofs" = [ "tvix-castore/virtiofs" ]; + "xp-store-composition" = [ "toml" "tvix-castore/xp-store-composition" ]; }; - resolvedDefaultFeatures = [ "cloud" "default" "fuse" "otlp" "tonic-reflection" "virtiofs" ]; + resolvedDefaultFeatures = [ "cloud" "default" "fuse" "integration" "otlp" "toml" "tonic-reflection" "tracy" "virtiofs" "xp-store-composition" ]; + }; + "tvix-tracing" = rec { + crateName = "tvix-tracing"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./tracing; }; + libName = "tvix_tracing"; + dependencies = [ + { + name = "axum"; + packageId = "axum"; + optional = true; + } + { + name = "http"; + packageId = "http"; + optional = true; + } + { + name = "indicatif"; + packageId = "indicatif"; + } + { + name = "opentelemetry"; + packageId = "opentelemetry 0.24.0"; + optional = true; + } + { + name = "opentelemetry-http"; + packageId = "opentelemetry-http"; + optional = true; + } + { + name = "opentelemetry-otlp"; + packageId = "opentelemetry-otlp"; + optional = true; + } + { + name = "opentelemetry_sdk"; + packageId = "opentelemetry_sdk 0.24.1"; + optional = true; + features = [ "rt-tokio" ]; + } + { + name = "reqwest-tracing"; + packageId = "reqwest-tracing"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "sync" "rt" ]; + } + { + name = "tonic"; + packageId = "tonic"; + optional = true; + } + { + name = "tracing"; + packageId = "tracing"; + features = [ "max_level_trace" "release_max_level_debug" ]; + } + { + name = "tracing-indicatif"; + packageId = "tracing-indicatif"; + } + { + name = "tracing-opentelemetry"; + packageId = "tracing-opentelemetry 0.25.0"; + optional = true; + } + { + name = "tracing-subscriber"; + packageId = "tracing-subscriber"; + features = [ "env-filter" ]; + } + { + name = "tracing-tracy"; + packageId = "tracing-tracy"; + optional = true; + features = [ "flush-on-exit" ]; + } + ]; + features = { + "axum" = [ "dep:axum" ]; + "otlp" = [ "dep:tracing-opentelemetry" "dep:opentelemetry" "dep:opentelemetry-otlp" "dep:opentelemetry_sdk" "dep:opentelemetry-http" "reqwest-tracing?/opentelemetry_0_22" ]; + "reqwest" = [ "dep:reqwest-tracing" ]; + "tonic" = [ "dep:tonic" "dep:http" ]; + "tracy" = [ "dep:tracing-tracy" ]; + }; + resolvedDefaultFeatures = [ "axum" "default" "otlp" "reqwest" "tonic" "tracy" ]; + }; + "typeid" = rec { + crateName = "typeid"; + version = "1.0.2"; + edition = "2018"; + sha256 = "0vi32jv3s3nbybbl4r317wi2bk8j4fx4d8p88jji8pnd1hpdn4qf"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + }; "typenum" = rec { crateName = "typenum"; @@ -14508,9 +16376,9 @@ rec { }; "typetag" = rec { crateName = "typetag"; - version = "0.2.16"; + version = "0.2.18"; edition = "2021"; - sha256 = "1bwswa9ah2sc6fmlfw2pim73rr1n6vhfwmidrsga8cn09r0ih7b6"; + sha256 = "1glv3pdj154jlgp702nb2qxr72rq0xjdiwj45i5hbq7zhrp3pfjj"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -14546,10 +16414,11 @@ rec { }; "typetag-impl" = rec { crateName = "typetag-impl"; - version = "0.2.16"; + version = "0.2.18"; edition = "2021"; - sha256 = "1cabnvm526bcgh1sh34js5ils0gz4xwlgvwhm992acdr8xzqhwxc"; + sha256 = "10r42wlz1gddnq7x4fk6bf7h6dsdblb4zqz57k91r3rcqhi0mckh"; procMacro = true; + libName = "typetag_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -14564,7 +16433,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -14595,9 +16464,9 @@ rec { }; "unicode-bidi" = rec { crateName = "unicode-bidi"; - version = "0.3.15"; + version = "0.3.17"; edition = "2018"; - sha256 = "0xcdxm7h0ydyprwpcbh436rbs6s6lph7f3gr527lzgv6lw053y88"; + sha256 = "14vqdsnrm3y5anj6h5zz5s32w88crraycblb88d9k23k9ns7vcas"; libName = "unicode_bidi"; authors = [ "The Servo Project Developers" @@ -14608,15 +16477,17 @@ rec { "flame_it" = [ "flame" "flamer" ]; "flamer" = [ "dep:flamer" ]; "serde" = [ "dep:serde" ]; + "smallvec" = [ "dep:smallvec" ]; "with_serde" = [ "serde" ]; }; resolvedDefaultFeatures = [ "hardcoded-data" "std" ]; }; "unicode-ident" = rec { crateName = "unicode-ident"; - version = "1.0.12"; + version = "1.0.13"; edition = "2018"; - sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + sha256 = "1zm1xylzsdfvm2a5ib9li3g5pp7qnkv4amhspydvgbmd9k6mc6z9"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -14624,9 +16495,10 @@ rec { }; "unicode-normalization" = rec { crateName = "unicode-normalization"; - version = "0.1.22"; + version = "0.1.24"; edition = "2018"; - sha256 = "08d95g7b1irc578b2iyhzv4xhsa4pfvwsqxcl9lbcpabzkq16msw"; + sha256 = "0mnrk809z3ix1wspcqy97ld5wxdb31f3xz6nsvg5qcv289ycjcsh"; + libName = "unicode_normalization"; authors = [ "kwantam <kwantam@gmail.com>" "Manish Goregaokar <manishsmail@gmail.com>" @@ -14645,9 +16517,10 @@ rec { }; "unicode-segmentation" = rec { crateName = "unicode-segmentation"; - version = "1.10.1"; + version = "1.12.0"; edition = "2018"; - sha256 = "0dky2hm5k51xy11hc3nk85p533rvghd462b6i0c532b7hl4j9mhx"; + sha256 = "14qla2jfx74yyb9ds3d2mpwpa4l4lzb9z57c6d2ba511458z5k7n"; + libName = "unicode_segmentation"; authors = [ "kwantam <kwantam@gmail.com>" "Manish Goregaokar <manishsmail@gmail.com>" @@ -14656,9 +16529,10 @@ rec { }; "unicode-width" = rec { crateName = "unicode-width"; - version = "0.1.11"; - edition = "2015"; - sha256 = "11ds4ydhg8g7l06rlmh712q41qsrd0j0h00n1jm74kww3kqk65z5"; + version = "0.1.14"; + edition = "2021"; + sha256 = "1bzn2zv0gp8xxbxbhifw778a7fc93pa6a1kj24jgg9msj07f7mkx"; + libName = "unicode_width"; authors = [ "kwantam <kwantam@gmail.com>" "Manish Goregaokar <manishsmail@gmail.com>" @@ -14666,10 +16540,11 @@ rec { features = { "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; + "default" = [ "cjk" ]; "rustc-dep-of-std" = [ "std" "core" "compiler_builtins" ]; "std" = [ "dep:std" ]; }; - resolvedDefaultFeatures = [ "default" ]; + resolvedDefaultFeatures = [ "cjk" "default" ]; }; "untrusted" = rec { crateName = "untrusted"; @@ -14683,9 +16558,9 @@ rec { }; "url" = rec { crateName = "url"; - version = "2.5.0"; + version = "2.5.2"; edition = "2018"; - sha256 = "0cs65961miawncdg2z20171w0vqrmraswv2ihdpd8lxp7cp31rii"; + sha256 = "0v2dx50mx7xzl9454cl5qmpjnhkbahmn59gd3apyipbgyyylsy12"; authors = [ "The rust-url developers" ]; @@ -14721,9 +16596,9 @@ rec { }; "utf8parse" = rec { crateName = "utf8parse"; - version = "0.2.1"; + version = "0.2.2"; edition = "2018"; - sha256 = "02ip1a0az0qmc2786vxk2nqwsgcwf17d3a38fkf0q7hrmwh9c6vi"; + sha256 = "088807qwjq46azicqwbhlmzwrbkz7l4hpw43sdkdyyk524vdxaq6"; authors = [ "Joe Wilm <joe@jwilm.com>" "Christian Duerr <contact@christianduerr.com>" @@ -14733,12 +16608,11 @@ rec { }; "uuid" = rec { crateName = "uuid"; - version = "1.7.0"; + version = "1.10.0"; edition = "2018"; - sha256 = "0aivp5ys7sg2izlj2sn6rr8p43vdcwg64naj8n0kqbd15iqcj37h"; + sha256 = "0503gvp08dh5mnm3f0ffqgisj6x3mbs53dmnn1lm19pga43a1pw1"; authors = [ "Ashley Mannix<ashleymannix@live.com.au>" - "Christopher Armstrong" "Dylan DPC<dylan.dpc@gmail.com>" "Hunar Roop Kahlon<hunar.roop@gmail.com>" ]; @@ -14768,7 +16642,7 @@ rec { "v4" = [ "rng" ]; "v5" = [ "sha1" ]; "v6" = [ "atomic" ]; - "v7" = [ "atomic" "rng" ]; + "v7" = [ "rng" ]; "zerocopy" = [ "dep:zerocopy" ]; }; resolvedDefaultFeatures = [ "default" "rng" "std" "v4" ]; @@ -14798,9 +16672,9 @@ rec { }; "version_check" = rec { crateName = "version_check"; - version = "0.9.4"; + version = "0.9.5"; edition = "2015"; - sha256 = "0gs8grwdlgh0xq660d7wr80x14vxbizmd8dbp29p2pdncx8lp1s9"; + sha256 = "0nhhi4i5x89gm911azqbn7avs9mdacw2i3vcz3cnmz3mv4rqz4hb"; authors = [ "Sergio Benitez <sb@sergio.bz>" ]; @@ -14852,6 +16726,7 @@ rec { version = "0.8.0"; edition = "2018"; sha256 = "00s33wy8cj2i8b4hlxn7wd8zm1fpaa5kjhzv77b3khsavf8pn8wz"; + libName = "vhost_user_backend"; authors = [ "The Cloud Hypervisor Authors" ]; @@ -14906,16 +16781,18 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "0sxxhhmz1r4s4q5pd2lykswcv9qk05fmpwc5xlb8aj45h8bi5x9z"; + libName = "virtio_bindings"; authors = [ "Sergio Lopez <slp@redhat.com>" ]; features = { }; }; - "virtio-bindings 0.2.2" = rec { + "virtio-bindings 0.2.3" = rec { crateName = "virtio-bindings"; - version = "0.2.2"; + version = "0.2.3"; edition = "2021"; - sha256 = "11mfm9brqgwpfg0izsgc4n7xkqwxk5ad03ivslq0r88j50dwp2w7"; + sha256 = "0hd2mccfrym1agcnxwq0a76lva14grrsq4sr3g41v6ypb97xzl38"; + libName = "virtio_bindings"; authors = [ "Sergio Lopez <slp@redhat.com>" ]; @@ -14926,6 +16803,7 @@ rec { version = "0.7.1"; edition = "2021"; sha256 = "1gbppbapj7c0vyca88vl34cx4sp2cy9yg0v6bvyd5h11rhmixa1v"; + libName = "virtio_queue"; authors = [ "The Chromium OS Authors" ]; @@ -14961,6 +16839,7 @@ rec { version = "0.10.0"; edition = "2021"; sha256 = "0z423a8i4s3addq4yjad4ar5l6qwarjwdn94lismbd0mcqv712k8"; + libName = "vm_memory"; authors = [ "Liu Jiang <gerry@linux.alibaba.com>" ]; @@ -14992,6 +16871,7 @@ rec { version = "0.11.2"; edition = "2021"; sha256 = "0a9azxk6wsahwkggshbdga4jdryzfw6j5r21f11gf50j4f2b1ds8"; + libName = "vmm_sys_util"; authors = [ "Intel Virtualization Team <vmm-maintainers@intel.com>" ]; @@ -15012,29 +16892,113 @@ rec { "with-serde" = [ "serde" "serde_derive" ]; }; }; - "wait-timeout" = rec { - crateName = "wait-timeout"; - version = "0.2.0"; - edition = "2015"; - crateBin = [ ]; - sha256 = "1xpkk0j5l9pfmjfh1pi0i89invlavfrd9av5xp0zhxgb29dhy84z"; + "vt100" = rec { + crateName = "vt100"; + version = "0.15.2"; + edition = "2021"; + sha256 = "1pklc8y984axmxr0cd363srr2d27wd5rj15xlcmkjznvy0xqdkc4"; authors = [ - "Alex Crichton <alex@alexcrichton.com>" + "Jesse Luehrs <doy@tozt.net>" ]; dependencies = [ { - name = "libc"; - packageId = "libc"; - target = { target, features }: (target."unix" or false); + name = "itoa"; + packageId = "itoa"; + } + { + name = "log"; + packageId = "log"; + } + { + name = "unicode-width"; + packageId = "unicode-width"; + } + { + name = "vte"; + packageId = "vte"; + } + ]; + devDependencies = [ + { + name = "vte"; + packageId = "vte"; + } + ]; + + }; + "vte" = rec { + crateName = "vte"; + version = "0.11.1"; + edition = "2021"; + sha256 = "15r1ff4j8ndqj9vsyil3wqwxhhl7jsz5g58f31n0h1wlpxgjn0pm"; + authors = [ + "Joe Wilm <joe@jwilm.com>" + "Christian Duerr <contact@christianduerr.com>" + ]; + dependencies = [ + { + name = "arrayvec"; + packageId = "arrayvec"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "utf8parse"; + packageId = "utf8parse"; + } + { + name = "vte_generate_state_changes"; + packageId = "vte_generate_state_changes"; + } + ]; + features = { + "ansi" = [ "log" ]; + "arrayvec" = [ "dep:arrayvec" ]; + "default" = [ "no_std" ]; + "log" = [ "dep:log" ]; + "nightly" = [ "utf8parse/nightly" ]; + "no_std" = [ "arrayvec" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "arrayvec" "default" "no_std" ]; + }; + "vte_generate_state_changes" = rec { + crateName = "vte_generate_state_changes"; + version = "0.1.2"; + edition = "2018"; + sha256 = "0biwgpcji3w4llz7h4bi8c2rwqchm9gmyr7dnjki1m853gp9ndif"; + procMacro = true; + authors = [ + "Christian Duerr <contact@christianduerr.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; } ]; }; + "vu128" = rec { + crateName = "vu128"; + version = "1.1.0"; + edition = "2018"; + sha256 = "1pczgy26c0lsri1ddrx5wkgn0rcq4da04pqya5rl6vrwfnys73di"; + libPath = "vu128/vu128.rs"; + authors = [ + "John Millikin <john@john-millikin.com>" + ]; + + }; "walkdir" = rec { crateName = "walkdir"; - version = "2.4.0"; + version = "2.5.0"; edition = "2018"; - sha256 = "1vjl9fmfc4v8k9ald23qrpcbyb8dl1ynyq8d516cm537r1yqa7fp"; + sha256 = "0jsy7a710qv8gld5957ybrnc07gavppp963gs32xk4ag8130jy99"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -15086,9 +17050,10 @@ rec { }; "wasm-bindgen" = rec { crateName = "wasm-bindgen"; - version = "0.2.90"; - edition = "2018"; - sha256 = "01jlal3mynqwvqx4acrdnr9bvsdczaz2sy8lmmzmqh81lab348mi"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0bpbvmxhil380gpv53smaypl8wc7sy7rq8apxfw349pn78v1x38j"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -15098,6 +17063,10 @@ rec { packageId = "cfg-if"; } { + name = "once_cell"; + packageId = "once_cell"; + } + { name = "wasm-bindgen-macro"; packageId = "wasm-bindgen-macro"; } @@ -15105,7 +17074,6 @@ rec { features = { "default" = [ "spans" "std" ]; "enable-interning" = [ "std" ]; - "gg-alloc" = [ "wasm-bindgen-test/gg-alloc" ]; "serde" = [ "dep:serde" ]; "serde-serialize" = [ "serde" "serde_json" "std" ]; "serde_json" = [ "dep:serde_json" ]; @@ -15117,9 +17085,10 @@ rec { }; "wasm-bindgen-backend" = rec { crateName = "wasm-bindgen-backend"; - version = "0.2.90"; - edition = "2018"; - sha256 = "1kcxml9762zjdrn0h0n0qxfg1n7z1f577jcc5yimi3a0cddr7p7w"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0n53wgy78bgzgjwk0z69zbspzhv8p2a4zh69s4fzvpqdrb9x8vfb"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -15146,7 +17115,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" ]; } { @@ -15161,9 +17130,10 @@ rec { }; "wasm-bindgen-futures" = rec { crateName = "wasm-bindgen-futures"; - version = "0.4.40"; - edition = "2018"; - sha256 = "0qf4bzlinyg0s4b38fhzdi1cqdd7rgrywqdjr3ngmgc6xcm07qmx"; + version = "0.4.45"; + edition = "2021"; + sha256 = "0fznn43frhq72ci41lgybahv6assvfmqfgnvfiimhwbshbwc8znc"; + libName = "wasm_bindgen_futures"; authors = [ "The wasm-bindgen Developers" ]; @@ -15194,10 +17164,11 @@ rec { }; "wasm-bindgen-macro" = rec { crateName = "wasm-bindgen-macro"; - version = "0.2.90"; - edition = "2018"; - sha256 = "16d980bql7y5krfqlmcr8mk1q4mrm0rmb0a99j92im5jc62j6k1y"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0mic8b2vab1a91m6x3hjxkwz23094bq1cwhnszarsnlggyz894z7"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -15219,9 +17190,10 @@ rec { }; "wasm-bindgen-macro-support" = rec { crateName = "wasm-bindgen-macro-support"; - version = "0.2.90"; - edition = "2018"; - sha256 = "19r5bsyjw0fvim7dsj8pbwrq8v0ggh845lhfasgavhbdh2vapqds"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0s7g6glb85lyx2pj83shbmg4d50mvqhb2c2qk2j28yigaxbspii6"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -15236,8 +17208,8 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; - features = [ "visit" "full" ]; + packageId = "syn 2.0.79"; + features = [ "visit" "visit-mut" "full" ]; } { name = "wasm-bindgen-backend"; @@ -15256,10 +17228,11 @@ rec { }; "wasm-bindgen-shared" = rec { crateName = "wasm-bindgen-shared"; - version = "0.2.90"; - edition = "2018"; + version = "0.2.95"; + edition = "2021"; links = "wasm_bindgen"; - sha256 = "0av0m0shdg1jxhf66ymjbq03m0qb7ypm297glndm7mri3hxl34ad"; + sha256 = "1386q7mvv5ky003hcc6yyxpid3y1m7fy0l920i3z3ab60vqhkz35"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -15267,9 +17240,10 @@ rec { }; "wasm-streams" = rec { crateName = "wasm-streams"; - version = "0.3.0"; + version = "0.4.1"; edition = "2021"; - sha256 = "1iqa4kmhbsjj8k4q15i1x0x4p3xda0dhbg7zw51mydr4g129sq5l"; + sha256 = "1kdy5crbsahavcy9010ixwz03pqmjfir9znq8csgn07pf972s1sf"; + libName = "wasm_streams"; type = [ "cdylib" "rlib" ]; authors = [ "Mattias Buelens <mattias@buelens.com>" @@ -15295,23 +17269,24 @@ rec { { name = "web-sys"; packageId = "web-sys"; - features = [ "AbortSignal" ]; + features = [ "AbortSignal" "QueuingStrategy" "ReadableStream" "ReadableStreamType" "ReadableWritablePair" "ReadableStreamByobReader" "ReadableStreamReaderMode" "ReadableStreamReadResult" "ReadableStreamByobRequest" "ReadableStreamDefaultReader" "ReadableByteStreamController" "ReadableStreamGetReaderOptions" "ReadableStreamDefaultController" "StreamPipeOptions" "TransformStream" "TransformStreamDefaultController" "Transformer" "UnderlyingSink" "UnderlyingSource" "WritableStream" "WritableStreamDefaultController" "WritableStreamDefaultWriter" ]; } ]; devDependencies = [ { name = "web-sys"; packageId = "web-sys"; - features = [ "console" "AbortSignal" "Response" "ReadableStream" "Window" ]; + features = [ "console" "AbortSignal" "ErrorEvent" "PromiseRejectionEvent" "Response" "ReadableStream" "Window" ]; } ]; }; "web-sys" = rec { crateName = "web-sys"; - version = "0.3.67"; - edition = "2018"; - sha256 = "1vfjjj3i49gy8bh8znnqhak1hx7xj9c2a3jzc0wpmgp0nqrj7kaq"; + version = "0.3.72"; + edition = "2021"; + sha256 = "04k19hilj9r8sx6q20fz853149gfpmf83yk2zvq0s14c2288nj7n"; + libName = "web_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -15422,8 +17397,6 @@ rec { "FontFaceSet" = [ "EventTarget" ]; "FontFaceSetLoadEvent" = [ "Event" ]; "GainNode" = [ "AudioNode" "EventTarget" ]; - "GamepadAxisMoveEvent" = [ "Event" "GamepadEvent" ]; - "GamepadButtonEvent" = [ "Event" "GamepadEvent" ]; "GamepadEvent" = [ "Event" ]; "GpuDevice" = [ "EventTarget" ]; "GpuInternalError" = [ "GpuError" ]; @@ -15523,7 +17496,9 @@ rec { "IirFilterNode" = [ "AudioNode" "EventTarget" ]; "ImageCaptureErrorEvent" = [ "Event" ]; "ImageTrack" = [ "EventTarget" ]; + "InputDeviceInfo" = [ "MediaDeviceInfo" ]; "InputEvent" = [ "Event" "UiEvent" ]; + "KeyFrameRequestEvent" = [ "Event" ]; "KeyboardEvent" = [ "Event" "UiEvent" ]; "KeyframeEffect" = [ "AnimationEffect" ]; "LocalMediaStream" = [ "EventTarget" "MediaStream" ]; @@ -15594,10 +17569,15 @@ rec { "RtcDataChannel" = [ "EventTarget" ]; "RtcDataChannelEvent" = [ "Event" ]; "RtcPeerConnection" = [ "EventTarget" ]; + "RtcPeerConnectionIceErrorEvent" = [ "Event" ]; "RtcPeerConnectionIceEvent" = [ "Event" ]; + "RtcRtpScriptTransformer" = [ "EventTarget" ]; "RtcTrackEvent" = [ "Event" ]; + "RtcTransformEvent" = [ "Event" ]; "RtcdtmfSender" = [ "EventTarget" ]; "RtcdtmfToneChangeEvent" = [ "Event" ]; + "SFrameTransform" = [ "EventTarget" ]; + "SFrameTransformErrorEvent" = [ "Event" ]; "Screen" = [ "EventTarget" ]; "ScreenOrientation" = [ "EventTarget" ]; "ScriptProcessorNode" = [ "AudioNode" "EventTarget" ]; @@ -15727,6 +17707,7 @@ rec { "TextTrackCue" = [ "EventTarget" ]; "TextTrackList" = [ "EventTarget" ]; "TimeEvent" = [ "Event" ]; + "ToggleEvent" = [ "Event" ]; "TouchEvent" = [ "Event" "UiEvent" ]; "TrackEvent" = [ "Event" ]; "TransitionEvent" = [ "Event" ]; @@ -15738,6 +17719,7 @@ rec { "ValueEvent" = [ "Event" ]; "VideoStreamTrack" = [ "EventTarget" "MediaStreamTrack" ]; "VideoTrackList" = [ "EventTarget" ]; + "VisualViewport" = [ "EventTarget" ]; "VrDisplay" = [ "EventTarget" ]; "VttCue" = [ "EventTarget" "TextTrackCue" ]; "WakeLockSentinel" = [ "EventTarget" ]; @@ -15774,100 +17756,29 @@ rec { "XrViewerPose" = [ "XrPose" ]; "XrWebGlLayer" = [ "EventTarget" "XrLayer" ]; }; - resolvedDefaultFeatures = [ "AbortController" "AbortSignal" "Blob" "BlobPropertyBag" "CanvasRenderingContext2d" "Document" "DomRect" "DomRectReadOnly" "Element" "Event" "EventTarget" "File" "FormData" "Headers" "HtmlCanvasElement" "HtmlElement" "MessageEvent" "Node" "ReadableStream" "Request" "RequestCredentials" "RequestInit" "RequestMode" "Response" "ServiceWorkerGlobalScope" "Window" "Worker" "WorkerGlobalScope" ]; + resolvedDefaultFeatures = [ "AbortController" "AbortSignal" "Blob" "BlobPropertyBag" "CanvasRenderingContext2d" "Document" "DomRect" "DomRectReadOnly" "Element" "Event" "EventTarget" "File" "FormData" "Headers" "HtmlCanvasElement" "HtmlElement" "MessageEvent" "Node" "QueuingStrategy" "ReadableByteStreamController" "ReadableStream" "ReadableStreamByobReader" "ReadableStreamByobRequest" "ReadableStreamDefaultController" "ReadableStreamDefaultReader" "ReadableStreamGetReaderOptions" "ReadableStreamReadResult" "ReadableStreamReaderMode" "ReadableStreamType" "ReadableWritablePair" "Request" "RequestCredentials" "RequestInit" "RequestMode" "Response" "ServiceWorkerGlobalScope" "StreamPipeOptions" "TransformStream" "TransformStreamDefaultController" "Transformer" "UnderlyingSink" "UnderlyingSource" "Window" "Worker" "WorkerGlobalScope" "WritableStream" "WritableStreamDefaultController" "WritableStreamDefaultWriter" ]; }; "web-time" = rec { crateName = "web-time"; - version = "0.2.4"; + version = "1.1.0"; edition = "2021"; - sha256 = "1q6gk0nkwbfz30g1pz8g52mq00zjx7m5im36k3474aw73jdh8c5a"; + sha256 = "1fx05yqx83dhx628wb70fyy10yjfq1jpl20qfqhdkymi13rq0ras"; + libName = "web_time"; dependencies = [ { name = "js-sys"; packageId = "js-sys"; - target = { target, features }: ((builtins.elem "wasm" target."family") && (!(("emscripten" == target."os" or null) || ("wasi" == target."os" or null)))); + target = { target, features }: ((builtins.elem "wasm" target."family") && ("unknown" == target."os" or null)); } { name = "wasm-bindgen"; packageId = "wasm-bindgen"; usesDefaultFeatures = false; - target = { target, features }: ((builtins.elem "wasm" target."family") && (!(("emscripten" == target."os" or null) || ("wasi" == target."os" or null)))); - } - ]; - - }; - "which 4.4.2" = rec { - crateName = "which"; - version = "4.4.2"; - edition = "2021"; - sha256 = "1ixzmx3svsv5hbdvd8vdhd3qwvf6ns8jdpif1wmwsy10k90j9fl7"; - authors = [ - "Harry Fei <tiziyuanfang@gmail.com>" - ]; - dependencies = [ - { - name = "either"; - packageId = "either"; - } - { - name = "home"; - packageId = "home"; - target = { target, features }: ((target."windows" or false) || (target."unix" or false) || ("redox" == target."os" or null)); - } - { - name = "once_cell"; - packageId = "once_cell"; - target = { target, features }: (target."windows" or false); - } - { - name = "rustix"; - packageId = "rustix"; - usesDefaultFeatures = false; - features = [ "fs" "std" ]; + target = { target, features }: ((builtins.elem "wasm" target."family") && ("unknown" == target."os" or null)); } ]; features = { - "regex" = [ "dep:regex" ]; - }; - }; - "which 5.0.0" = rec { - crateName = "which"; - version = "5.0.0"; - edition = "2021"; - sha256 = "053fpbczryyn8lcbpkvwl8v2rzld0pr30r5lh1cxv87kjs2ymwwv"; - authors = [ - "Harry Fei <tiziyuanfang@gmail.com>" - ]; - dependencies = [ - { - name = "either"; - packageId = "either"; - } - { - name = "home"; - packageId = "home"; - target = { target, features }: ((target."windows" or false) || (target."unix" or false) || ("redox" == target."os" or null)); - } - { - name = "once_cell"; - packageId = "once_cell"; - target = { target, features }: (target."windows" or false); - } - { - name = "rustix"; - packageId = "rustix"; - usesDefaultFeatures = false; - features = [ "fs" "std" ]; - } - { - name = "windows-sys"; - packageId = "windows-sys 0.48.0"; - target = { target, features }: (target."windows" or false); - features = [ "Win32_Storage_FileSystem" "Win32_Foundation" ]; - } - ]; - features = { - "regex" = [ "dep:regex" ]; + "serde" = [ "dep:serde" ]; }; }; "winapi" = rec { @@ -15882,24 +17793,25 @@ rec { { name = "winapi-i686-pc-windows-gnu"; packageId = "winapi-i686-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "i686-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnu"); } { name = "winapi-x86_64-pc-windows-gnu"; packageId = "winapi-x86_64-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnu"); } ]; features = { "debug" = [ "impl-debug" ]; }; - resolvedDefaultFeatures = [ "basetsd" "consoleapi" "errhandlingapi" "fileapi" "handleapi" "knownfolders" "minwindef" "ntstatus" "objbase" "processenv" "processthreadsapi" "shellapi" "shlobj" "std" "stringapiset" "synchapi" "sysinfoapi" "winbase" "wincon" "winerror" "winnt" "winuser" ]; + resolvedDefaultFeatures = [ "basetsd" "consoleapi" "errhandlingapi" "fileapi" "handleapi" "knownfolders" "minwindef" "objbase" "processenv" "shellapi" "shlobj" "std" "stringapiset" "synchapi" "sysinfoapi" "winbase" "wincon" "winerror" "winuser" ]; }; "winapi-i686-pc-windows-gnu" = rec { crateName = "winapi-i686-pc-windows-gnu"; version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -15907,18 +17819,19 @@ rec { }; "winapi-util" = rec { crateName = "winapi-util"; - version = "0.1.6"; + version = "0.1.9"; edition = "2021"; - sha256 = "15i5lm39wd44004i9d5qspry2cynkrpvwzghr6s2c3dsk28nz7pj"; + sha256 = "1fqhkcl9scd230cnfj8apfficpf5c9vhwnk4yy9xfc1sw69iq8ng"; + libName = "winapi_util"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; dependencies = [ { - name = "winapi"; - packageId = "winapi"; + name = "windows-sys"; + packageId = "windows-sys 0.59.0"; target = { target, features }: (target."windows" or false); - features = [ "std" "consoleapi" "errhandlingapi" "fileapi" "minwindef" "processenv" "sysinfoapi" "winbase" "wincon" "winerror" "winnt" ]; + features = [ "Win32_Foundation" "Win32_Storage_FileSystem" "Win32_System_Console" "Win32_System_SystemInformation" ]; } ]; @@ -15928,33 +17841,907 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; }; - "windows-core" = rec { + "windows" = rec { + crateName = "windows"; + version = "0.58.0"; + edition = "2021"; + sha256 = "1dkjj94b0gn91nn1n22cvm4afsj98f5qrhcl3112v6f4jcfx816x"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-core"; + packageId = "windows-core 0.58.0"; + } + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + } + ]; + features = { + "AI" = [ "Foundation" ]; + "AI_MachineLearning" = [ "AI" ]; + "ApplicationModel" = [ "Foundation" ]; + "ApplicationModel_Activation" = [ "ApplicationModel" ]; + "ApplicationModel_AppExtensions" = [ "ApplicationModel" ]; + "ApplicationModel_AppService" = [ "ApplicationModel" ]; + "ApplicationModel_Appointments" = [ "ApplicationModel" ]; + "ApplicationModel_Appointments_AppointmentsProvider" = [ "ApplicationModel_Appointments" ]; + "ApplicationModel_Appointments_DataProvider" = [ "ApplicationModel_Appointments" ]; + "ApplicationModel_Background" = [ "ApplicationModel" ]; + "ApplicationModel_Calls" = [ "ApplicationModel" ]; + "ApplicationModel_Calls_Background" = [ "ApplicationModel_Calls" ]; + "ApplicationModel_Calls_Provider" = [ "ApplicationModel_Calls" ]; + "ApplicationModel_Chat" = [ "ApplicationModel" ]; + "ApplicationModel_CommunicationBlocking" = [ "ApplicationModel" ]; + "ApplicationModel_Contacts" = [ "ApplicationModel" ]; + "ApplicationModel_Contacts_DataProvider" = [ "ApplicationModel_Contacts" ]; + "ApplicationModel_Contacts_Provider" = [ "ApplicationModel_Contacts" ]; + "ApplicationModel_ConversationalAgent" = [ "ApplicationModel" ]; + "ApplicationModel_Core" = [ "ApplicationModel" ]; + "ApplicationModel_DataTransfer" = [ "ApplicationModel" ]; + "ApplicationModel_DataTransfer_DragDrop" = [ "ApplicationModel_DataTransfer" ]; + "ApplicationModel_DataTransfer_DragDrop_Core" = [ "ApplicationModel_DataTransfer_DragDrop" ]; + "ApplicationModel_DataTransfer_ShareTarget" = [ "ApplicationModel_DataTransfer" ]; + "ApplicationModel_Email" = [ "ApplicationModel" ]; + "ApplicationModel_Email_DataProvider" = [ "ApplicationModel_Email" ]; + "ApplicationModel_ExtendedExecution" = [ "ApplicationModel" ]; + "ApplicationModel_ExtendedExecution_Foreground" = [ "ApplicationModel_ExtendedExecution" ]; + "ApplicationModel_Holographic" = [ "ApplicationModel" ]; + "ApplicationModel_LockScreen" = [ "ApplicationModel" ]; + "ApplicationModel_PackageExtensions" = [ "ApplicationModel" ]; + "ApplicationModel_Payments" = [ "ApplicationModel" ]; + "ApplicationModel_Payments_Provider" = [ "ApplicationModel_Payments" ]; + "ApplicationModel_Preview" = [ "ApplicationModel" ]; + "ApplicationModel_Preview_Holographic" = [ "ApplicationModel_Preview" ]; + "ApplicationModel_Preview_InkWorkspace" = [ "ApplicationModel_Preview" ]; + "ApplicationModel_Preview_Notes" = [ "ApplicationModel_Preview" ]; + "ApplicationModel_Resources" = [ "ApplicationModel" ]; + "ApplicationModel_Resources_Core" = [ "ApplicationModel_Resources" ]; + "ApplicationModel_Resources_Management" = [ "ApplicationModel_Resources" ]; + "ApplicationModel_Search" = [ "ApplicationModel" ]; + "ApplicationModel_Search_Core" = [ "ApplicationModel_Search" ]; + "ApplicationModel_UserActivities" = [ "ApplicationModel" ]; + "ApplicationModel_UserActivities_Core" = [ "ApplicationModel_UserActivities" ]; + "ApplicationModel_UserDataAccounts" = [ "ApplicationModel" ]; + "ApplicationModel_UserDataAccounts_Provider" = [ "ApplicationModel_UserDataAccounts" ]; + "ApplicationModel_UserDataAccounts_SystemAccess" = [ "ApplicationModel_UserDataAccounts" ]; + "ApplicationModel_UserDataTasks" = [ "ApplicationModel" ]; + "ApplicationModel_UserDataTasks_DataProvider" = [ "ApplicationModel_UserDataTasks" ]; + "ApplicationModel_VoiceCommands" = [ "ApplicationModel" ]; + "ApplicationModel_Wallet" = [ "ApplicationModel" ]; + "ApplicationModel_Wallet_System" = [ "ApplicationModel_Wallet" ]; + "Data" = [ "Foundation" ]; + "Data_Html" = [ "Data" ]; + "Data_Json" = [ "Data" ]; + "Data_Pdf" = [ "Data" ]; + "Data_Text" = [ "Data" ]; + "Data_Xml" = [ "Data" ]; + "Data_Xml_Dom" = [ "Data_Xml" ]; + "Data_Xml_Xsl" = [ "Data_Xml" ]; + "Devices" = [ "Foundation" ]; + "Devices_Adc" = [ "Devices" ]; + "Devices_Adc_Provider" = [ "Devices_Adc" ]; + "Devices_Background" = [ "Devices" ]; + "Devices_Bluetooth" = [ "Devices" ]; + "Devices_Bluetooth_Advertisement" = [ "Devices_Bluetooth" ]; + "Devices_Bluetooth_Background" = [ "Devices_Bluetooth" ]; + "Devices_Bluetooth_GenericAttributeProfile" = [ "Devices_Bluetooth" ]; + "Devices_Bluetooth_Rfcomm" = [ "Devices_Bluetooth" ]; + "Devices_Custom" = [ "Devices" ]; + "Devices_Display" = [ "Devices" ]; + "Devices_Display_Core" = [ "Devices_Display" ]; + "Devices_Enumeration" = [ "Devices" ]; + "Devices_Enumeration_Pnp" = [ "Devices_Enumeration" ]; + "Devices_Geolocation" = [ "Devices" ]; + "Devices_Geolocation_Geofencing" = [ "Devices_Geolocation" ]; + "Devices_Geolocation_Provider" = [ "Devices_Geolocation" ]; + "Devices_Gpio" = [ "Devices" ]; + "Devices_Gpio_Provider" = [ "Devices_Gpio" ]; + "Devices_Haptics" = [ "Devices" ]; + "Devices_HumanInterfaceDevice" = [ "Devices" ]; + "Devices_I2c" = [ "Devices" ]; + "Devices_I2c_Provider" = [ "Devices_I2c" ]; + "Devices_Input" = [ "Devices" ]; + "Devices_Input_Preview" = [ "Devices_Input" ]; + "Devices_Lights" = [ "Devices" ]; + "Devices_Lights_Effects" = [ "Devices_Lights" ]; + "Devices_Midi" = [ "Devices" ]; + "Devices_PointOfService" = [ "Devices" ]; + "Devices_PointOfService_Provider" = [ "Devices_PointOfService" ]; + "Devices_Portable" = [ "Devices" ]; + "Devices_Power" = [ "Devices" ]; + "Devices_Printers" = [ "Devices" ]; + "Devices_Printers_Extensions" = [ "Devices_Printers" ]; + "Devices_Pwm" = [ "Devices" ]; + "Devices_Pwm_Provider" = [ "Devices_Pwm" ]; + "Devices_Radios" = [ "Devices" ]; + "Devices_Scanners" = [ "Devices" ]; + "Devices_Sensors" = [ "Devices" ]; + "Devices_Sensors_Custom" = [ "Devices_Sensors" ]; + "Devices_SerialCommunication" = [ "Devices" ]; + "Devices_SmartCards" = [ "Devices" ]; + "Devices_Sms" = [ "Devices" ]; + "Devices_Spi" = [ "Devices" ]; + "Devices_Spi_Provider" = [ "Devices_Spi" ]; + "Devices_Usb" = [ "Devices" ]; + "Devices_WiFi" = [ "Devices" ]; + "Devices_WiFiDirect" = [ "Devices" ]; + "Devices_WiFiDirect_Services" = [ "Devices_WiFiDirect" ]; + "Embedded" = [ "Foundation" ]; + "Embedded_DeviceLockdown" = [ "Embedded" ]; + "Foundation_Collections" = [ "Foundation" ]; + "Foundation_Diagnostics" = [ "Foundation" ]; + "Foundation_Metadata" = [ "Foundation" ]; + "Foundation_Numerics" = [ "Foundation" ]; + "Gaming" = [ "Foundation" ]; + "Gaming_Input" = [ "Gaming" ]; + "Gaming_Input_Custom" = [ "Gaming_Input" ]; + "Gaming_Input_ForceFeedback" = [ "Gaming_Input" ]; + "Gaming_Input_Preview" = [ "Gaming_Input" ]; + "Gaming_Preview" = [ "Gaming" ]; + "Gaming_Preview_GamesEnumeration" = [ "Gaming_Preview" ]; + "Gaming_UI" = [ "Gaming" ]; + "Gaming_XboxLive" = [ "Gaming" ]; + "Gaming_XboxLive_Storage" = [ "Gaming_XboxLive" ]; + "Globalization" = [ "Foundation" ]; + "Globalization_Collation" = [ "Globalization" ]; + "Globalization_DateTimeFormatting" = [ "Globalization" ]; + "Globalization_Fonts" = [ "Globalization" ]; + "Globalization_NumberFormatting" = [ "Globalization" ]; + "Globalization_PhoneNumberFormatting" = [ "Globalization" ]; + "Graphics" = [ "Foundation" ]; + "Graphics_Capture" = [ "Graphics" ]; + "Graphics_DirectX" = [ "Graphics" ]; + "Graphics_DirectX_Direct3D11" = [ "Graphics_DirectX" ]; + "Graphics_Display" = [ "Graphics" ]; + "Graphics_Display_Core" = [ "Graphics_Display" ]; + "Graphics_Effects" = [ "Graphics" ]; + "Graphics_Holographic" = [ "Graphics" ]; + "Graphics_Imaging" = [ "Graphics" ]; + "Graphics_Printing" = [ "Graphics" ]; + "Graphics_Printing3D" = [ "Graphics" ]; + "Graphics_Printing_OptionDetails" = [ "Graphics_Printing" ]; + "Graphics_Printing_PrintSupport" = [ "Graphics_Printing" ]; + "Graphics_Printing_PrintTicket" = [ "Graphics_Printing" ]; + "Graphics_Printing_Workflow" = [ "Graphics_Printing" ]; + "Management" = [ "Foundation" ]; + "Management_Core" = [ "Management" ]; + "Management_Deployment" = [ "Management" ]; + "Management_Deployment_Preview" = [ "Management_Deployment" ]; + "Management_Policies" = [ "Management" ]; + "Management_Setup" = [ "Management" ]; + "Management_Update" = [ "Management" ]; + "Management_Workplace" = [ "Management" ]; + "Media" = [ "Foundation" ]; + "Media_AppBroadcasting" = [ "Media" ]; + "Media_AppRecording" = [ "Media" ]; + "Media_Audio" = [ "Media" ]; + "Media_Capture" = [ "Media" ]; + "Media_Capture_Core" = [ "Media_Capture" ]; + "Media_Capture_Frames" = [ "Media_Capture" ]; + "Media_Casting" = [ "Media" ]; + "Media_ClosedCaptioning" = [ "Media" ]; + "Media_ContentRestrictions" = [ "Media" ]; + "Media_Control" = [ "Media" ]; + "Media_Core" = [ "Media" ]; + "Media_Core_Preview" = [ "Media_Core" ]; + "Media_Devices" = [ "Media" ]; + "Media_Devices_Core" = [ "Media_Devices" ]; + "Media_DialProtocol" = [ "Media" ]; + "Media_Editing" = [ "Media" ]; + "Media_Effects" = [ "Media" ]; + "Media_FaceAnalysis" = [ "Media" ]; + "Media_Import" = [ "Media" ]; + "Media_MediaProperties" = [ "Media" ]; + "Media_Miracast" = [ "Media" ]; + "Media_Ocr" = [ "Media" ]; + "Media_PlayTo" = [ "Media" ]; + "Media_Playback" = [ "Media" ]; + "Media_Playlists" = [ "Media" ]; + "Media_Protection" = [ "Media" ]; + "Media_Protection_PlayReady" = [ "Media_Protection" ]; + "Media_Render" = [ "Media" ]; + "Media_SpeechRecognition" = [ "Media" ]; + "Media_SpeechSynthesis" = [ "Media" ]; + "Media_Streaming" = [ "Media" ]; + "Media_Streaming_Adaptive" = [ "Media_Streaming" ]; + "Media_Transcoding" = [ "Media" ]; + "Networking" = [ "Foundation" ]; + "Networking_BackgroundTransfer" = [ "Networking" ]; + "Networking_Connectivity" = [ "Networking" ]; + "Networking_NetworkOperators" = [ "Networking" ]; + "Networking_Proximity" = [ "Networking" ]; + "Networking_PushNotifications" = [ "Networking" ]; + "Networking_ServiceDiscovery" = [ "Networking" ]; + "Networking_ServiceDiscovery_Dnssd" = [ "Networking_ServiceDiscovery" ]; + "Networking_Sockets" = [ "Networking" ]; + "Networking_Vpn" = [ "Networking" ]; + "Networking_XboxLive" = [ "Networking" ]; + "Perception" = [ "Foundation" ]; + "Perception_Automation" = [ "Perception" ]; + "Perception_Automation_Core" = [ "Perception_Automation" ]; + "Perception_People" = [ "Perception" ]; + "Perception_Spatial" = [ "Perception" ]; + "Perception_Spatial_Preview" = [ "Perception_Spatial" ]; + "Perception_Spatial_Surfaces" = [ "Perception_Spatial" ]; + "Phone" = [ "Foundation" ]; + "Phone_ApplicationModel" = [ "Phone" ]; + "Phone_Devices" = [ "Phone" ]; + "Phone_Devices_Notification" = [ "Phone_Devices" ]; + "Phone_Devices_Power" = [ "Phone_Devices" ]; + "Phone_Management" = [ "Phone" ]; + "Phone_Management_Deployment" = [ "Phone_Management" ]; + "Phone_Media" = [ "Phone" ]; + "Phone_Media_Devices" = [ "Phone_Media" ]; + "Phone_Notification" = [ "Phone" ]; + "Phone_Notification_Management" = [ "Phone_Notification" ]; + "Phone_PersonalInformation" = [ "Phone" ]; + "Phone_PersonalInformation_Provisioning" = [ "Phone_PersonalInformation" ]; + "Phone_Speech" = [ "Phone" ]; + "Phone_Speech_Recognition" = [ "Phone_Speech" ]; + "Phone_StartScreen" = [ "Phone" ]; + "Phone_System" = [ "Phone" ]; + "Phone_System_Power" = [ "Phone_System" ]; + "Phone_System_Profile" = [ "Phone_System" ]; + "Phone_System_UserProfile" = [ "Phone_System" ]; + "Phone_System_UserProfile_GameServices" = [ "Phone_System_UserProfile" ]; + "Phone_System_UserProfile_GameServices_Core" = [ "Phone_System_UserProfile_GameServices" ]; + "Phone_UI" = [ "Phone" ]; + "Phone_UI_Input" = [ "Phone_UI" ]; + "Security" = [ "Foundation" ]; + "Security_Authentication" = [ "Security" ]; + "Security_Authentication_Identity" = [ "Security_Authentication" ]; + "Security_Authentication_Identity_Core" = [ "Security_Authentication_Identity" ]; + "Security_Authentication_OnlineId" = [ "Security_Authentication" ]; + "Security_Authentication_Web" = [ "Security_Authentication" ]; + "Security_Authentication_Web_Core" = [ "Security_Authentication_Web" ]; + "Security_Authentication_Web_Provider" = [ "Security_Authentication_Web" ]; + "Security_Authorization" = [ "Security" ]; + "Security_Authorization_AppCapabilityAccess" = [ "Security_Authorization" ]; + "Security_Credentials" = [ "Security" ]; + "Security_Credentials_UI" = [ "Security_Credentials" ]; + "Security_Cryptography" = [ "Security" ]; + "Security_Cryptography_Certificates" = [ "Security_Cryptography" ]; + "Security_Cryptography_Core" = [ "Security_Cryptography" ]; + "Security_Cryptography_DataProtection" = [ "Security_Cryptography" ]; + "Security_DataProtection" = [ "Security" ]; + "Security_EnterpriseData" = [ "Security" ]; + "Security_ExchangeActiveSyncProvisioning" = [ "Security" ]; + "Security_Isolation" = [ "Security" ]; + "Services" = [ "Foundation" ]; + "Services_Maps" = [ "Services" ]; + "Services_Maps_Guidance" = [ "Services_Maps" ]; + "Services_Maps_LocalSearch" = [ "Services_Maps" ]; + "Services_Maps_OfflineMaps" = [ "Services_Maps" ]; + "Services_Store" = [ "Services" ]; + "Services_TargetedContent" = [ "Services" ]; + "Storage" = [ "Foundation" ]; + "Storage_AccessCache" = [ "Storage" ]; + "Storage_BulkAccess" = [ "Storage" ]; + "Storage_Compression" = [ "Storage" ]; + "Storage_FileProperties" = [ "Storage" ]; + "Storage_Pickers" = [ "Storage" ]; + "Storage_Pickers_Provider" = [ "Storage_Pickers" ]; + "Storage_Provider" = [ "Storage" ]; + "Storage_Search" = [ "Storage" ]; + "Storage_Streams" = [ "Storage" ]; + "System" = [ "Foundation" ]; + "System_Diagnostics" = [ "System" ]; + "System_Diagnostics_DevicePortal" = [ "System_Diagnostics" ]; + "System_Diagnostics_Telemetry" = [ "System_Diagnostics" ]; + "System_Diagnostics_TraceReporting" = [ "System_Diagnostics" ]; + "System_Display" = [ "System" ]; + "System_Implementation" = [ "System" ]; + "System_Implementation_FileExplorer" = [ "System_Implementation" ]; + "System_Inventory" = [ "System" ]; + "System_Power" = [ "System" ]; + "System_Profile" = [ "System" ]; + "System_Profile_SystemManufacturers" = [ "System_Profile" ]; + "System_RemoteDesktop" = [ "System" ]; + "System_RemoteDesktop_Input" = [ "System_RemoteDesktop" ]; + "System_RemoteDesktop_Provider" = [ "System_RemoteDesktop" ]; + "System_RemoteSystems" = [ "System" ]; + "System_Threading" = [ "System" ]; + "System_Threading_Core" = [ "System_Threading" ]; + "System_Update" = [ "System" ]; + "System_UserProfile" = [ "System" ]; + "UI" = [ "Foundation" ]; + "UI_Accessibility" = [ "UI" ]; + "UI_ApplicationSettings" = [ "UI" ]; + "UI_Composition" = [ "UI" ]; + "UI_Composition_Core" = [ "UI_Composition" ]; + "UI_Composition_Desktop" = [ "UI_Composition" ]; + "UI_Composition_Diagnostics" = [ "UI_Composition" ]; + "UI_Composition_Effects" = [ "UI_Composition" ]; + "UI_Composition_Interactions" = [ "UI_Composition" ]; + "UI_Composition_Scenes" = [ "UI_Composition" ]; + "UI_Core" = [ "UI" ]; + "UI_Core_AnimationMetrics" = [ "UI_Core" ]; + "UI_Core_Preview" = [ "UI_Core" ]; + "UI_Input" = [ "UI" ]; + "UI_Input_Core" = [ "UI_Input" ]; + "UI_Input_Inking" = [ "UI_Input" ]; + "UI_Input_Inking_Analysis" = [ "UI_Input_Inking" ]; + "UI_Input_Inking_Core" = [ "UI_Input_Inking" ]; + "UI_Input_Inking_Preview" = [ "UI_Input_Inking" ]; + "UI_Input_Preview" = [ "UI_Input" ]; + "UI_Input_Preview_Injection" = [ "UI_Input_Preview" ]; + "UI_Input_Spatial" = [ "UI_Input" ]; + "UI_Notifications" = [ "UI" ]; + "UI_Notifications_Management" = [ "UI_Notifications" ]; + "UI_Notifications_Preview" = [ "UI_Notifications" ]; + "UI_Popups" = [ "UI" ]; + "UI_Shell" = [ "UI" ]; + "UI_StartScreen" = [ "UI" ]; + "UI_Text" = [ "UI" ]; + "UI_Text_Core" = [ "UI_Text" ]; + "UI_UIAutomation" = [ "UI" ]; + "UI_UIAutomation_Core" = [ "UI_UIAutomation" ]; + "UI_ViewManagement" = [ "UI" ]; + "UI_ViewManagement_Core" = [ "UI_ViewManagement" ]; + "UI_WebUI" = [ "UI" ]; + "UI_WebUI_Core" = [ "UI_WebUI" ]; + "UI_WindowManagement" = [ "UI" ]; + "UI_WindowManagement_Preview" = [ "UI_WindowManagement" ]; + "Wdk" = [ "Win32_Foundation" ]; + "Wdk_Devices" = [ "Wdk" ]; + "Wdk_Devices_Bluetooth" = [ "Wdk_Devices" ]; + "Wdk_Devices_HumanInterfaceDevice" = [ "Wdk_Devices" ]; + "Wdk_Foundation" = [ "Wdk" ]; + "Wdk_Graphics" = [ "Wdk" ]; + "Wdk_Graphics_Direct3D" = [ "Wdk_Graphics" ]; + "Wdk_NetworkManagement" = [ "Wdk" ]; + "Wdk_NetworkManagement_Ndis" = [ "Wdk_NetworkManagement" ]; + "Wdk_NetworkManagement_WindowsFilteringPlatform" = [ "Wdk_NetworkManagement" ]; + "Wdk_Storage" = [ "Wdk" ]; + "Wdk_Storage_FileSystem" = [ "Wdk_Storage" ]; + "Wdk_Storage_FileSystem_Minifilters" = [ "Wdk_Storage_FileSystem" ]; + "Wdk_System" = [ "Wdk" ]; + "Wdk_System_IO" = [ "Wdk_System" ]; + "Wdk_System_Memory" = [ "Wdk_System" ]; + "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; + "Wdk_System_Registry" = [ "Wdk_System" ]; + "Wdk_System_SystemInformation" = [ "Wdk_System" ]; + "Wdk_System_SystemServices" = [ "Wdk_System" ]; + "Wdk_System_Threading" = [ "Wdk_System" ]; + "Web" = [ "Foundation" ]; + "Web_AtomPub" = [ "Web" ]; + "Web_Http" = [ "Web" ]; + "Web_Http_Diagnostics" = [ "Web_Http" ]; + "Web_Http_Filters" = [ "Web_Http" ]; + "Web_Http_Headers" = [ "Web_Http" ]; + "Web_Syndication" = [ "Web" ]; + "Web_UI" = [ "Web" ]; + "Web_UI_Interop" = [ "Web_UI" ]; + "Win32" = [ "Win32_Foundation" ]; + "Win32_AI" = [ "Win32" ]; + "Win32_AI_MachineLearning" = [ "Win32_AI" ]; + "Win32_AI_MachineLearning_DirectML" = [ "Win32_AI_MachineLearning" ]; + "Win32_AI_MachineLearning_WinML" = [ "Win32_AI_MachineLearning" ]; + "Win32_Data" = [ "Win32" ]; + "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; + "Win32_Data_RightsManagement" = [ "Win32_Data" ]; + "Win32_Data_Xml" = [ "Win32_Data" ]; + "Win32_Data_Xml_MsXml" = [ "Win32_Data_Xml" ]; + "Win32_Data_Xml_XmlLite" = [ "Win32_Data_Xml" ]; + "Win32_Devices" = [ "Win32" ]; + "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; + "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; + "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; + "Win32_Devices_Communication" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceAccess" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; + "Win32_Devices_Display" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; + "Win32_Devices_Fax" = [ "Win32_Devices" ]; + "Win32_Devices_FunctionDiscovery" = [ "Win32_Devices" ]; + "Win32_Devices_Geolocation" = [ "Win32_Devices" ]; + "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; + "Win32_Devices_ImageAcquisition" = [ "Win32_Devices" ]; + "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; + "Win32_Devices_Properties" = [ "Win32_Devices" ]; + "Win32_Devices_Pwm" = [ "Win32_Devices" ]; + "Win32_Devices_Sensors" = [ "Win32_Devices" ]; + "Win32_Devices_SerialCommunication" = [ "Win32_Devices" ]; + "Win32_Devices_Tapi" = [ "Win32_Devices" ]; + "Win32_Devices_Usb" = [ "Win32_Devices" ]; + "Win32_Devices_WebServicesOnDevices" = [ "Win32_Devices" ]; + "Win32_Foundation" = [ "Win32" ]; + "Win32_Gaming" = [ "Win32" ]; + "Win32_Globalization" = [ "Win32" ]; + "Win32_Graphics" = [ "Win32" ]; + "Win32_Graphics_CompositionSwapchain" = [ "Win32_Graphics" ]; + "Win32_Graphics_DXCore" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct2D" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct2D_Common" = [ "Win32_Graphics_Direct2D" ]; + "Win32_Graphics_Direct3D" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D10" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D11" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D11on12" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D12" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D9" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D9on12" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D_Dxc" = [ "Win32_Graphics_Direct3D" ]; + "Win32_Graphics_Direct3D_Fxc" = [ "Win32_Graphics_Direct3D" ]; + "Win32_Graphics_DirectComposition" = [ "Win32_Graphics" ]; + "Win32_Graphics_DirectDraw" = [ "Win32_Graphics" ]; + "Win32_Graphics_DirectManipulation" = [ "Win32_Graphics" ]; + "Win32_Graphics_DirectWrite" = [ "Win32_Graphics" ]; + "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; + "Win32_Graphics_Dxgi" = [ "Win32_Graphics" ]; + "Win32_Graphics_Dxgi_Common" = [ "Win32_Graphics_Dxgi" ]; + "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; + "Win32_Graphics_GdiPlus" = [ "Win32_Graphics" ]; + "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; + "Win32_Graphics_Imaging" = [ "Win32_Graphics" ]; + "Win32_Graphics_Imaging_D2D" = [ "Win32_Graphics_Imaging" ]; + "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing_PrintTicket" = [ "Win32_Graphics_Printing" ]; + "Win32_Management" = [ "Win32" ]; + "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; + "Win32_Media" = [ "Win32" ]; + "Win32_Media_Audio" = [ "Win32_Media" ]; + "Win32_Media_Audio_Apo" = [ "Win32_Media_Audio" ]; + "Win32_Media_Audio_DirectMusic" = [ "Win32_Media_Audio" ]; + "Win32_Media_Audio_DirectSound" = [ "Win32_Media_Audio" ]; + "Win32_Media_Audio_Endpoints" = [ "Win32_Media_Audio" ]; + "Win32_Media_Audio_XAudio2" = [ "Win32_Media_Audio" ]; + "Win32_Media_DeviceManager" = [ "Win32_Media" ]; + "Win32_Media_DirectShow" = [ "Win32_Media" ]; + "Win32_Media_DirectShow_Tv" = [ "Win32_Media_DirectShow" ]; + "Win32_Media_DirectShow_Xml" = [ "Win32_Media_DirectShow" ]; + "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; + "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; + "Win32_Media_LibrarySharingServices" = [ "Win32_Media" ]; + "Win32_Media_MediaFoundation" = [ "Win32_Media" ]; + "Win32_Media_MediaPlayer" = [ "Win32_Media" ]; + "Win32_Media_Multimedia" = [ "Win32_Media" ]; + "Win32_Media_PictureAcquisition" = [ "Win32_Media" ]; + "Win32_Media_Speech" = [ "Win32_Media" ]; + "Win32_Media_Streaming" = [ "Win32_Media" ]; + "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; + "Win32_NetworkManagement" = [ "Win32" ]; + "Win32_NetworkManagement_Dhcp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_MobileBroadband" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetworkPolicyServer" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Snmp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsConnectNow" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; + "Win32_Networking" = [ "Win32" ]; + "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; + "Win32_Networking_BackgroundIntelligentTransferService" = [ "Win32_Networking" ]; + "Win32_Networking_Clustering" = [ "Win32_Networking" ]; + "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; + "Win32_Networking_Ldap" = [ "Win32_Networking" ]; + "Win32_Networking_NetworkListManager" = [ "Win32_Networking" ]; + "Win32_Networking_RemoteDifferentialCompression" = [ "Win32_Networking" ]; + "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; + "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; + "Win32_Networking_WinInet" = [ "Win32_Networking" ]; + "Win32_Networking_WinSock" = [ "Win32_Networking" ]; + "Win32_Networking_WindowsWebServices" = [ "Win32_Networking" ]; + "Win32_Security" = [ "Win32" ]; + "Win32_Security_AppLocker" = [ "Win32_Security" ]; + "Win32_Security_Authentication" = [ "Win32_Security" ]; + "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; + "Win32_Security_Authentication_Identity_Provider" = [ "Win32_Security_Authentication_Identity" ]; + "Win32_Security_Authorization" = [ "Win32_Security" ]; + "Win32_Security_Authorization_UI" = [ "Win32_Security_Authorization" ]; + "Win32_Security_ConfigurationSnapin" = [ "Win32_Security" ]; + "Win32_Security_Credentials" = [ "Win32_Security" ]; + "Win32_Security_Cryptography" = [ "Win32_Security" ]; + "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Certificates" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Sip" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_UI" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_DiagnosticDataQuery" = [ "Win32_Security" ]; + "Win32_Security_DirectoryServices" = [ "Win32_Security" ]; + "Win32_Security_EnterpriseData" = [ "Win32_Security" ]; + "Win32_Security_ExtensibleAuthenticationProtocol" = [ "Win32_Security" ]; + "Win32_Security_Isolation" = [ "Win32_Security" ]; + "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; + "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; + "Win32_Security_Tpm" = [ "Win32_Security" ]; + "Win32_Security_WinTrust" = [ "Win32_Security" ]; + "Win32_Security_WinWlx" = [ "Win32_Security" ]; + "Win32_Storage" = [ "Win32" ]; + "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; + "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; + "Win32_Storage_Compression" = [ "Win32_Storage" ]; + "Win32_Storage_DataDeduplication" = [ "Win32_Storage" ]; + "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_EnhancedStorage" = [ "Win32_Storage" ]; + "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; + "Win32_Storage_FileServerResourceManager" = [ "Win32_Storage" ]; + "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_Imapi" = [ "Win32_Storage" ]; + "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; + "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; + "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; + "Win32_Storage_Jet" = [ "Win32_Storage" ]; + "Win32_Storage_Nvme" = [ "Win32_Storage" ]; + "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; + "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; + "Win32_Storage_Packaging_Opc" = [ "Win32_Storage_Packaging" ]; + "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; + "Win32_Storage_Vhd" = [ "Win32_Storage" ]; + "Win32_Storage_VirtualDiskService" = [ "Win32_Storage" ]; + "Win32_Storage_Vss" = [ "Win32_Storage" ]; + "Win32_Storage_Xps" = [ "Win32_Storage" ]; + "Win32_Storage_Xps_Printing" = [ "Win32_Storage_Xps" ]; + "Win32_System" = [ "Win32" ]; + "Win32_System_AddressBook" = [ "Win32_System" ]; + "Win32_System_Antimalware" = [ "Win32_System" ]; + "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; + "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; + "Win32_System_AssessmentTool" = [ "Win32_System" ]; + "Win32_System_ClrHosting" = [ "Win32_System" ]; + "Win32_System_Com" = [ "Win32_System" ]; + "Win32_System_Com_CallObj" = [ "Win32_System_Com" ]; + "Win32_System_Com_ChannelCredentials" = [ "Win32_System_Com" ]; + "Win32_System_Com_Events" = [ "Win32_System_Com" ]; + "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; + "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; + "Win32_System_Com_UI" = [ "Win32_System_Com" ]; + "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; + "Win32_System_ComponentServices" = [ "Win32_System" ]; + "Win32_System_Console" = [ "Win32_System" ]; + "Win32_System_Contacts" = [ "Win32_System" ]; + "Win32_System_CorrelationVector" = [ "Win32_System" ]; + "Win32_System_DataExchange" = [ "Win32_System" ]; + "Win32_System_DeploymentServices" = [ "Win32_System" ]; + "Win32_System_DesktopSharing" = [ "Win32_System" ]; + "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; + "Win32_System_Diagnostics" = [ "Win32_System" ]; + "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ClrProfiling" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug_ActiveScript" = [ "Win32_System_Diagnostics_Debug" ]; + "Win32_System_Diagnostics_Debug_Extensions" = [ "Win32_System_Diagnostics_Debug" ]; + "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_TraceLogging" = [ "Win32_System_Diagnostics" ]; + "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; + "Win32_System_Environment" = [ "Win32_System" ]; + "Win32_System_ErrorReporting" = [ "Win32_System" ]; + "Win32_System_EventCollector" = [ "Win32_System" ]; + "Win32_System_EventLog" = [ "Win32_System" ]; + "Win32_System_EventNotificationService" = [ "Win32_System" ]; + "Win32_System_GroupPolicy" = [ "Win32_System" ]; + "Win32_System_HostCompute" = [ "Win32_System" ]; + "Win32_System_HostComputeNetwork" = [ "Win32_System" ]; + "Win32_System_HostComputeSystem" = [ "Win32_System" ]; + "Win32_System_Hypervisor" = [ "Win32_System" ]; + "Win32_System_IO" = [ "Win32_System" ]; + "Win32_System_Iis" = [ "Win32_System" ]; + "Win32_System_Ioctl" = [ "Win32_System" ]; + "Win32_System_JobObjects" = [ "Win32_System" ]; + "Win32_System_Js" = [ "Win32_System" ]; + "Win32_System_Kernel" = [ "Win32_System" ]; + "Win32_System_LibraryLoader" = [ "Win32_System" ]; + "Win32_System_Mailslots" = [ "Win32_System" ]; + "Win32_System_Mapi" = [ "Win32_System" ]; + "Win32_System_Memory" = [ "Win32_System" ]; + "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; + "Win32_System_MessageQueuing" = [ "Win32_System" ]; + "Win32_System_MixedReality" = [ "Win32_System" ]; + "Win32_System_Mmc" = [ "Win32_System" ]; + "Win32_System_Ole" = [ "Win32_System" ]; + "Win32_System_ParentalControls" = [ "Win32_System" ]; + "Win32_System_PasswordManagement" = [ "Win32_System" ]; + "Win32_System_Performance" = [ "Win32_System" ]; + "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; + "Win32_System_Pipes" = [ "Win32_System" ]; + "Win32_System_Power" = [ "Win32_System" ]; + "Win32_System_ProcessStatus" = [ "Win32_System" ]; + "Win32_System_RealTimeCommunications" = [ "Win32_System" ]; + "Win32_System_Recovery" = [ "Win32_System" ]; + "Win32_System_Registry" = [ "Win32_System" ]; + "Win32_System_RemoteAssistance" = [ "Win32_System" ]; + "Win32_System_RemoteDesktop" = [ "Win32_System" ]; + "Win32_System_RemoteManagement" = [ "Win32_System" ]; + "Win32_System_RestartManager" = [ "Win32_System" ]; + "Win32_System_Restore" = [ "Win32_System" ]; + "Win32_System_Rpc" = [ "Win32_System" ]; + "Win32_System_Search" = [ "Win32_System" ]; + "Win32_System_Search_Common" = [ "Win32_System_Search" ]; + "Win32_System_SecurityCenter" = [ "Win32_System" ]; + "Win32_System_ServerBackup" = [ "Win32_System" ]; + "Win32_System_Services" = [ "Win32_System" ]; + "Win32_System_SettingsManagementInfrastructure" = [ "Win32_System" ]; + "Win32_System_SetupAndMigration" = [ "Win32_System" ]; + "Win32_System_Shutdown" = [ "Win32_System" ]; + "Win32_System_SideShow" = [ "Win32_System" ]; + "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; + "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; + "Win32_System_SystemInformation" = [ "Win32_System" ]; + "Win32_System_SystemServices" = [ "Win32_System" ]; + "Win32_System_TaskScheduler" = [ "Win32_System" ]; + "Win32_System_Threading" = [ "Win32_System" ]; + "Win32_System_Time" = [ "Win32_System" ]; + "Win32_System_TpmBaseServices" = [ "Win32_System" ]; + "Win32_System_TransactionServer" = [ "Win32_System" ]; + "Win32_System_UpdateAgent" = [ "Win32_System" ]; + "Win32_System_UpdateAssessment" = [ "Win32_System" ]; + "Win32_System_UserAccessLogging" = [ "Win32_System" ]; + "Win32_System_Variant" = [ "Win32_System" ]; + "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; + "Win32_System_WinRT" = [ "Win32_System" ]; + "Win32_System_WinRT_AllJoyn" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Composition" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_CoreInputView" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Direct3D11" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Display" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Graphics" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Graphics_Capture" = [ "Win32_System_WinRT_Graphics" ]; + "Win32_System_WinRT_Graphics_Direct2D" = [ "Win32_System_WinRT_Graphics" ]; + "Win32_System_WinRT_Graphics_Imaging" = [ "Win32_System_WinRT_Graphics" ]; + "Win32_System_WinRT_Holographic" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Isolation" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_ML" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Media" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Metadata" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Pdf" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Printing" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Shell" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Storage" = [ "Win32_System_WinRT" ]; + "Win32_System_WindowsProgramming" = [ "Win32_System" ]; + "Win32_System_WindowsSync" = [ "Win32_System" ]; + "Win32_System_Wmi" = [ "Win32_System" ]; + "Win32_UI" = [ "Win32" ]; + "Win32_UI_Accessibility" = [ "Win32_UI" ]; + "Win32_UI_Animation" = [ "Win32_UI" ]; + "Win32_UI_ColorSystem" = [ "Win32_UI" ]; + "Win32_UI_Controls" = [ "Win32_UI" ]; + "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; + "Win32_UI_Controls_RichEdit" = [ "Win32_UI_Controls" ]; + "Win32_UI_HiDpi" = [ "Win32_UI" ]; + "Win32_UI_Input" = [ "Win32_UI" ]; + "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Ink" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Radial" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; + "Win32_UI_InteractionContext" = [ "Win32_UI" ]; + "Win32_UI_LegacyWindowsEnvironmentFeatures" = [ "Win32_UI" ]; + "Win32_UI_Magnification" = [ "Win32_UI" ]; + "Win32_UI_Notifications" = [ "Win32_UI" ]; + "Win32_UI_Ribbon" = [ "Win32_UI" ]; + "Win32_UI_Shell" = [ "Win32_UI" ]; + "Win32_UI_Shell_Common" = [ "Win32_UI_Shell" ]; + "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; + "Win32_UI_TabletPC" = [ "Win32_UI" ]; + "Win32_UI_TextServices" = [ "Win32_UI" ]; + "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; + "Win32_UI_Wpf" = [ "Win32_UI" ]; + "Win32_Web" = [ "Win32" ]; + "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; + "default" = [ "std" ]; + "std" = [ "windows-core/std" ]; + }; + resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_System" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_Kernel" "Win32_System_Memory" "Win32_System_SystemInformation" "default" "std" ]; + }; + "windows-core 0.52.0" = rec { crateName = "windows-core"; version = "0.52.0"; edition = "2021"; sha256 = "1nc3qv7sy24x0nlnb32f7alzpd6f72l4p24vl65vydbyil669ark"; + libName = "windows_core"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets 0.52.0"; + packageId = "windows-targets 0.52.6"; } ]; features = { }; resolvedDefaultFeatures = [ "default" ]; }; + "windows-core 0.58.0" = rec { + crateName = "windows-core"; + version = "0.58.0"; + edition = "2021"; + sha256 = "16czypy425jzmiys4yb3pwsh7cm6grxn9kjp889iqnf2r17d99kb"; + libName = "windows_core"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-implement"; + packageId = "windows-implement"; + } + { + name = "windows-interface"; + packageId = "windows-interface"; + } + { + name = "windows-result"; + packageId = "windows-result"; + } + { + name = "windows-strings"; + packageId = "windows-strings"; + } + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + } + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "windows-implement" = rec { + crateName = "windows-implement"; + version = "0.58.0"; + edition = "2021"; + sha256 = "16spr5z65z21qyv379rv2mb1s5q2i9ibd1p2pkn0dr9qr535pg9b"; + procMacro = true; + libName = "windows_implement"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "parsing" "proc-macro" "printing" "full" "derive" ]; + } + ]; + + }; + "windows-interface" = rec { + crateName = "windows-interface"; + version = "0.58.0"; + edition = "2021"; + sha256 = "059mxmfvx3x88q74ms0qlxmj2pnidmr5mzn60hakn7f95m34qg05"; + procMacro = true; + libName = "windows_interface"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "parsing" "proc-macro" "printing" "full" "derive" "clone-impls" ]; + } + ]; + + }; + "windows-registry" = rec { + crateName = "windows-registry"; + version = "0.2.0"; + edition = "2021"; + sha256 = "1c04923fq0rbvl3z0h67xr6rh2fgwkizhclhqv0j79i0nwdh0074"; + libName = "windows_registry"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-result"; + packageId = "windows-result"; + } + { + name = "windows-strings"; + packageId = "windows-strings"; + } + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + } + ]; + + }; + "windows-result" = rec { + crateName = "windows-result"; + version = "0.2.0"; + edition = "2021"; + sha256 = "03mf2z1xcy2slhhsm15z24p76qxgm2m74xdjp8bihyag47c4640x"; + libName = "windows_result"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + } + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "windows-strings" = rec { + crateName = "windows-strings"; + version = "0.1.0"; + edition = "2021"; + sha256 = "042dxvi3133f7dyi2pgcvknwkikk47k8bddwxbq5s0l6qhjv3nac"; + libName = "windows_strings"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-result"; + packageId = "windows-result"; + usesDefaultFeatures = false; + } + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + } + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; "windows-sys 0.48.0" = rec { crateName = "windows-sys"; version = "0.48.0"; edition = "2018"; sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -16241,36 +19028,294 @@ rec { "Win32_Web" = [ "Win32" ]; "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; }; - resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Console" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_Registry" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_Time" "Win32_System_WindowsProgramming" "default" ]; + resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_WindowsProgramming" "default" ]; }; "windows-sys 0.52.0" = rec { crateName = "windows-sys"; version = "0.52.0"; edition = "2021"; sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + libName = "windows_sys"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + } + ]; + features = { + "Wdk_Foundation" = [ "Wdk" ]; + "Wdk_Graphics" = [ "Wdk" ]; + "Wdk_Graphics_Direct3D" = [ "Wdk_Graphics" ]; + "Wdk_Storage" = [ "Wdk" ]; + "Wdk_Storage_FileSystem" = [ "Wdk_Storage" ]; + "Wdk_Storage_FileSystem_Minifilters" = [ "Wdk_Storage_FileSystem" ]; + "Wdk_System" = [ "Wdk" ]; + "Wdk_System_IO" = [ "Wdk_System" ]; + "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; + "Wdk_System_Registry" = [ "Wdk_System" ]; + "Wdk_System_SystemInformation" = [ "Wdk_System" ]; + "Wdk_System_SystemServices" = [ "Wdk_System" ]; + "Wdk_System_Threading" = [ "Wdk_System" ]; + "Win32_Data" = [ "Win32" ]; + "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; + "Win32_Data_RightsManagement" = [ "Win32_Data" ]; + "Win32_Devices" = [ "Win32" ]; + "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; + "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; + "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; + "Win32_Devices_Communication" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; + "Win32_Devices_Display" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; + "Win32_Devices_Fax" = [ "Win32_Devices" ]; + "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; + "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; + "Win32_Devices_Properties" = [ "Win32_Devices" ]; + "Win32_Devices_Pwm" = [ "Win32_Devices" ]; + "Win32_Devices_Sensors" = [ "Win32_Devices" ]; + "Win32_Devices_SerialCommunication" = [ "Win32_Devices" ]; + "Win32_Devices_Tapi" = [ "Win32_Devices" ]; + "Win32_Devices_Usb" = [ "Win32_Devices" ]; + "Win32_Devices_WebServicesOnDevices" = [ "Win32_Devices" ]; + "Win32_Foundation" = [ "Win32" ]; + "Win32_Gaming" = [ "Win32" ]; + "Win32_Globalization" = [ "Win32" ]; + "Win32_Graphics" = [ "Win32" ]; + "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; + "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; + "Win32_Graphics_GdiPlus" = [ "Win32_Graphics" ]; + "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; + "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing_PrintTicket" = [ "Win32_Graphics_Printing" ]; + "Win32_Management" = [ "Win32" ]; + "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; + "Win32_Media" = [ "Win32" ]; + "Win32_Media_Audio" = [ "Win32_Media" ]; + "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; + "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; + "Win32_Media_Multimedia" = [ "Win32_Media" ]; + "Win32_Media_Streaming" = [ "Win32_Media" ]; + "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; + "Win32_NetworkManagement" = [ "Win32" ]; + "Win32_NetworkManagement_Dhcp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Snmp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; + "Win32_Networking" = [ "Win32" ]; + "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; + "Win32_Networking_Clustering" = [ "Win32_Networking" ]; + "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; + "Win32_Networking_Ldap" = [ "Win32_Networking" ]; + "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; + "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; + "Win32_Networking_WinInet" = [ "Win32_Networking" ]; + "Win32_Networking_WinSock" = [ "Win32_Networking" ]; + "Win32_Networking_WindowsWebServices" = [ "Win32_Networking" ]; + "Win32_Security" = [ "Win32" ]; + "Win32_Security_AppLocker" = [ "Win32_Security" ]; + "Win32_Security_Authentication" = [ "Win32_Security" ]; + "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; + "Win32_Security_Authorization" = [ "Win32_Security" ]; + "Win32_Security_Credentials" = [ "Win32_Security" ]; + "Win32_Security_Cryptography" = [ "Win32_Security" ]; + "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Certificates" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Sip" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_UI" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_DiagnosticDataQuery" = [ "Win32_Security" ]; + "Win32_Security_DirectoryServices" = [ "Win32_Security" ]; + "Win32_Security_EnterpriseData" = [ "Win32_Security" ]; + "Win32_Security_ExtensibleAuthenticationProtocol" = [ "Win32_Security" ]; + "Win32_Security_Isolation" = [ "Win32_Security" ]; + "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; + "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; + "Win32_Security_WinTrust" = [ "Win32_Security" ]; + "Win32_Security_WinWlx" = [ "Win32_Security" ]; + "Win32_Storage" = [ "Win32" ]; + "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; + "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; + "Win32_Storage_Compression" = [ "Win32_Storage" ]; + "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; + "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_Imapi" = [ "Win32_Storage" ]; + "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; + "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; + "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; + "Win32_Storage_Jet" = [ "Win32_Storage" ]; + "Win32_Storage_Nvme" = [ "Win32_Storage" ]; + "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; + "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; + "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; + "Win32_Storage_Vhd" = [ "Win32_Storage" ]; + "Win32_Storage_Xps" = [ "Win32_Storage" ]; + "Win32_System" = [ "Win32" ]; + "Win32_System_AddressBook" = [ "Win32_System" ]; + "Win32_System_Antimalware" = [ "Win32_System" ]; + "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; + "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; + "Win32_System_ClrHosting" = [ "Win32_System" ]; + "Win32_System_Com" = [ "Win32_System" ]; + "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; + "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; + "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; + "Win32_System_ComponentServices" = [ "Win32_System" ]; + "Win32_System_Console" = [ "Win32_System" ]; + "Win32_System_CorrelationVector" = [ "Win32_System" ]; + "Win32_System_DataExchange" = [ "Win32_System" ]; + "Win32_System_DeploymentServices" = [ "Win32_System" ]; + "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; + "Win32_System_Diagnostics" = [ "Win32_System" ]; + "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug_Extensions" = [ "Win32_System_Diagnostics_Debug" ]; + "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; + "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; + "Win32_System_Environment" = [ "Win32_System" ]; + "Win32_System_ErrorReporting" = [ "Win32_System" ]; + "Win32_System_EventCollector" = [ "Win32_System" ]; + "Win32_System_EventLog" = [ "Win32_System" ]; + "Win32_System_EventNotificationService" = [ "Win32_System" ]; + "Win32_System_GroupPolicy" = [ "Win32_System" ]; + "Win32_System_HostCompute" = [ "Win32_System" ]; + "Win32_System_HostComputeNetwork" = [ "Win32_System" ]; + "Win32_System_HostComputeSystem" = [ "Win32_System" ]; + "Win32_System_Hypervisor" = [ "Win32_System" ]; + "Win32_System_IO" = [ "Win32_System" ]; + "Win32_System_Iis" = [ "Win32_System" ]; + "Win32_System_Ioctl" = [ "Win32_System" ]; + "Win32_System_JobObjects" = [ "Win32_System" ]; + "Win32_System_Js" = [ "Win32_System" ]; + "Win32_System_Kernel" = [ "Win32_System" ]; + "Win32_System_LibraryLoader" = [ "Win32_System" ]; + "Win32_System_Mailslots" = [ "Win32_System" ]; + "Win32_System_Mapi" = [ "Win32_System" ]; + "Win32_System_Memory" = [ "Win32_System" ]; + "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; + "Win32_System_MessageQueuing" = [ "Win32_System" ]; + "Win32_System_MixedReality" = [ "Win32_System" ]; + "Win32_System_Ole" = [ "Win32_System" ]; + "Win32_System_PasswordManagement" = [ "Win32_System" ]; + "Win32_System_Performance" = [ "Win32_System" ]; + "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; + "Win32_System_Pipes" = [ "Win32_System" ]; + "Win32_System_Power" = [ "Win32_System" ]; + "Win32_System_ProcessStatus" = [ "Win32_System" ]; + "Win32_System_Recovery" = [ "Win32_System" ]; + "Win32_System_Registry" = [ "Win32_System" ]; + "Win32_System_RemoteDesktop" = [ "Win32_System" ]; + "Win32_System_RemoteManagement" = [ "Win32_System" ]; + "Win32_System_RestartManager" = [ "Win32_System" ]; + "Win32_System_Restore" = [ "Win32_System" ]; + "Win32_System_Rpc" = [ "Win32_System" ]; + "Win32_System_Search" = [ "Win32_System" ]; + "Win32_System_Search_Common" = [ "Win32_System_Search" ]; + "Win32_System_SecurityCenter" = [ "Win32_System" ]; + "Win32_System_Services" = [ "Win32_System" ]; + "Win32_System_SetupAndMigration" = [ "Win32_System" ]; + "Win32_System_Shutdown" = [ "Win32_System" ]; + "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; + "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; + "Win32_System_SystemInformation" = [ "Win32_System" ]; + "Win32_System_SystemServices" = [ "Win32_System" ]; + "Win32_System_Threading" = [ "Win32_System" ]; + "Win32_System_Time" = [ "Win32_System" ]; + "Win32_System_TpmBaseServices" = [ "Win32_System" ]; + "Win32_System_UserAccessLogging" = [ "Win32_System" ]; + "Win32_System_Variant" = [ "Win32_System" ]; + "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; + "Win32_System_WindowsProgramming" = [ "Win32_System" ]; + "Win32_System_Wmi" = [ "Win32_System" ]; + "Win32_UI" = [ "Win32" ]; + "Win32_UI_Accessibility" = [ "Win32_UI" ]; + "Win32_UI_ColorSystem" = [ "Win32_UI" ]; + "Win32_UI_Controls" = [ "Win32_UI" ]; + "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; + "Win32_UI_HiDpi" = [ "Win32_UI" ]; + "Win32_UI_Input" = [ "Win32_UI" ]; + "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; + "Win32_UI_InteractionContext" = [ "Win32_UI" ]; + "Win32_UI_Magnification" = [ "Win32_UI" ]; + "Win32_UI_Shell" = [ "Win32_UI" ]; + "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; + "Win32_UI_TabletPC" = [ "Win32_UI" ]; + "Win32_UI_TextServices" = [ "Win32_UI" ]; + "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; + "Win32_Web" = [ "Win32" ]; + "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; + }; + resolvedDefaultFeatures = [ "Wdk" "Wdk_Foundation" "Wdk_Storage" "Wdk_Storage_FileSystem" "Wdk_System" "Wdk_System_IO" "Win32" "Win32_Foundation" "Win32_NetworkManagement" "Win32_NetworkManagement_IpHelper" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Com" "Win32_System_Console" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "Win32_UI" "Win32_UI_Input" "Win32_UI_Input_KeyboardAndMouse" "Win32_UI_Shell" "default" ]; + }; + "windows-sys 0.59.0" = rec { + crateName = "windows-sys"; + version = "0.59.0"; + edition = "2021"; + sha256 = "0fw5672ziw8b3zpmnbp9pdv1famk74f1l9fcbc3zsrzdg56vqf0y"; + libName = "windows_sys"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets 0.52.0"; + packageId = "windows-targets 0.52.6"; } ]; features = { + "Wdk" = [ "Win32_Foundation" ]; + "Wdk_Devices" = [ "Wdk" ]; + "Wdk_Devices_Bluetooth" = [ "Wdk_Devices" ]; + "Wdk_Devices_HumanInterfaceDevice" = [ "Wdk_Devices" ]; "Wdk_Foundation" = [ "Wdk" ]; "Wdk_Graphics" = [ "Wdk" ]; "Wdk_Graphics_Direct3D" = [ "Wdk_Graphics" ]; + "Wdk_NetworkManagement" = [ "Wdk" ]; + "Wdk_NetworkManagement_Ndis" = [ "Wdk_NetworkManagement" ]; + "Wdk_NetworkManagement_WindowsFilteringPlatform" = [ "Wdk_NetworkManagement" ]; "Wdk_Storage" = [ "Wdk" ]; "Wdk_Storage_FileSystem" = [ "Wdk_Storage" ]; "Wdk_Storage_FileSystem_Minifilters" = [ "Wdk_Storage_FileSystem" ]; "Wdk_System" = [ "Wdk" ]; "Wdk_System_IO" = [ "Wdk_System" ]; + "Wdk_System_Memory" = [ "Wdk_System" ]; "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; "Wdk_System_Registry" = [ "Wdk_System" ]; "Wdk_System_SystemInformation" = [ "Wdk_System" ]; "Wdk_System_SystemServices" = [ "Wdk_System" ]; "Wdk_System_Threading" = [ "Wdk_System" ]; + "Win32" = [ "Win32_Foundation" ]; "Win32_Data" = [ "Win32" ]; "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; "Win32_Data_RightsManagement" = [ "Win32_Data" ]; @@ -16410,6 +19455,7 @@ rec { "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_TraceLogging" = [ "Win32_System_Diagnostics" ]; "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; "Win32_System_Environment" = [ "Win32_System" ]; "Win32_System_ErrorReporting" = [ "Win32_System" ]; @@ -16481,6 +19527,7 @@ rec { "Win32_UI_InteractionContext" = [ "Win32_UI" ]; "Win32_UI_Magnification" = [ "Win32_UI" ]; "Win32_UI_Shell" = [ "Win32_UI" ]; + "Win32_UI_Shell_Common" = [ "Win32_UI_Shell" ]; "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; "Win32_UI_TabletPC" = [ "Win32_UI" ]; "Win32_UI_TextServices" = [ "Win32_UI" ]; @@ -16488,13 +19535,14 @@ rec { "Win32_Web" = [ "Win32" ]; "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; }; - resolvedDefaultFeatures = [ "Wdk" "Wdk_Foundation" "Wdk_Storage" "Wdk_Storage_FileSystem" "Win32" "Win32_Foundation" "Win32_NetworkManagement" "Win32_NetworkManagement_IpHelper" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Security_Authentication" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_Security_Cryptography" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Com" "Win32_System_Console" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_LibraryLoader" "Win32_System_Memory" "Win32_System_Threading" "Win32_System_WindowsProgramming" "Win32_UI" "Win32_UI_Shell" "default" ]; + resolvedDefaultFeatures = [ "Wdk" "Wdk_Foundation" "Wdk_Storage" "Wdk_Storage_FileSystem" "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Security_Authentication" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_Security_Cryptography" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Console" "Win32_System_IO" "Win32_System_LibraryLoader" "Win32_System_Memory" "Win32_System_SystemInformation" "Win32_System_Threading" "Win32_System_WindowsProgramming" "default" ]; }; "windows-targets 0.48.5" = rec { crateName = "windows-targets"; version = "0.48.5"; edition = "2018"; sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -16502,7 +19550,7 @@ rec { { name = "windows_aarch64_gnullvm"; packageId = "windows_aarch64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); } { name = "windows_aarch64_msvc"; @@ -16527,7 +19575,7 @@ rec { { name = "windows_x86_64_gnullvm"; packageId = "windows_x86_64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); } { name = "windows_x86_64_msvc"; @@ -16537,49 +19585,55 @@ rec { ]; }; - "windows-targets 0.52.0" = rec { + "windows-targets 0.52.6" = rec { crateName = "windows-targets"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "1kg7a27ynzw8zz3krdgy6w5gbqcji27j1sz4p7xk2j5j8082064a"; + sha256 = "0wwrx625nwlfp7k93r2rra568gad1mwd888h1jwnl0vfg5r4ywlv"; + libName = "windows_targets"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows_aarch64_gnullvm"; - packageId = "windows_aarch64_gnullvm 0.52.0"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + packageId = "windows_aarch64_gnullvm 0.52.6"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); } { name = "windows_aarch64_msvc"; - packageId = "windows_aarch64_msvc 0.52.0"; + packageId = "windows_aarch64_msvc 0.52.6"; target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_i686_gnu"; - packageId = "windows_i686_gnu 0.52.0"; - target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + packageId = "windows_i686_gnu 0.52.6"; + target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_i686_gnullvm"; + packageId = "windows_i686_gnullvm"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnullvm"); } { name = "windows_i686_msvc"; - packageId = "windows_i686_msvc 0.52.0"; + packageId = "windows_i686_msvc 0.52.6"; target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnu"; - packageId = "windows_x86_64_gnu 0.52.0"; + packageId = "windows_x86_64_gnu 0.52.6"; target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnullvm"; - packageId = "windows_x86_64_gnullvm 0.52.0"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); + packageId = "windows_x86_64_gnullvm 0.52.6"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); } { name = "windows_x86_64_msvc"; - packageId = "windows_x86_64_msvc 0.52.0"; - target = { target, features }: (("x86_64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + packageId = "windows_x86_64_msvc 0.52.6"; + target = { target, features }: ((("x86_64" == target."arch" or null) || ("arm64ec" == target."arch" or null)) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } ]; @@ -16594,11 +19648,11 @@ rec { ]; }; - "windows_aarch64_gnullvm 0.52.0" = rec { + "windows_aarch64_gnullvm 0.52.6" = rec { crateName = "windows_aarch64_gnullvm"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "1shmn1kbdc0bpphcxz0vlph96bxz0h1jlmh93s9agf2dbpin8xyb"; + sha256 = "1lrcq38cr2arvmz19v32qaggvj8bh1640mdm9c2fr877h0hn591j"; authors = [ "Microsoft" ]; @@ -16614,11 +19668,11 @@ rec { ]; }; - "windows_aarch64_msvc 0.52.0" = rec { + "windows_aarch64_msvc 0.52.6" = rec { crateName = "windows_aarch64_msvc"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "1vvmy1ypvzdvxn9yf0b8ygfl85gl2gpcyvsvqppsmlpisil07amv"; + sha256 = "0sfl0nysnz32yyfh773hpi49b1q700ah6y7sacmjbqjjn5xjmv09"; authors = [ "Microsoft" ]; @@ -16634,11 +19688,21 @@ rec { ]; }; - "windows_i686_gnu 0.52.0" = rec { + "windows_i686_gnu 0.52.6" = rec { crateName = "windows_i686_gnu"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "04zkglz4p3pjsns5gbz85v4s5aw102raz4spj4b0lmm33z5kg1m2"; + sha256 = "02zspglbykh1jh9pi7gn8g1f97jh1rrccni9ivmrfbl0mgamm6wf"; + authors = [ + "Microsoft" + ]; + + }; + "windows_i686_gnullvm" = rec { + crateName = "windows_i686_gnullvm"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0rpdx1537mw6slcpqa0rm3qixmsb79nbhqy5fsm3q2q9ik9m5vhf"; authors = [ "Microsoft" ]; @@ -16654,11 +19718,11 @@ rec { ]; }; - "windows_i686_msvc 0.52.0" = rec { + "windows_i686_msvc 0.52.6" = rec { crateName = "windows_i686_msvc"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "16kvmbvx0vr0zbgnaz6nsks9ycvfh5xp05bjrhq65kj623iyirgz"; + sha256 = "0rkcqmp4zzmfvrrrx01260q3xkpzi6fzi2x2pgdcdry50ny4h294"; authors = [ "Microsoft" ]; @@ -16674,11 +19738,11 @@ rec { ]; }; - "windows_x86_64_gnu 0.52.0" = rec { + "windows_x86_64_gnu 0.52.6" = rec { crateName = "windows_x86_64_gnu"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "1zdy4qn178sil5sdm63lm7f0kkcjg6gvdwmcprd2yjmwn8ns6vrx"; + sha256 = "0y0sifqcb56a56mvn7xjgs8g43p33mfqkd8wj1yhrgxzma05qyhl"; authors = [ "Microsoft" ]; @@ -16694,11 +19758,11 @@ rec { ]; }; - "windows_x86_64_gnullvm 0.52.0" = rec { + "windows_x86_64_gnullvm 0.52.6" = rec { crateName = "windows_x86_64_gnullvm"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "17lllq4l2k1lqgcnw1cccphxp9vs7inq99kjlm2lfl9zklg7wr8s"; + sha256 = "03gda7zjx1qh8k9nnlgb7m3w3s1xkysg55hkd1wjch8pqhyv5m94"; authors = [ "Microsoft" ]; @@ -16714,40 +19778,37 @@ rec { ]; }; - "windows_x86_64_msvc 0.52.0" = rec { + "windows_x86_64_msvc 0.52.6" = rec { crateName = "windows_x86_64_msvc"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "012wfq37f18c09ij5m6rniw7xxn5fcvrxbqd0wd8vgnl3hfn9yfz"; + sha256 = "1v7rb5cibyzx8vak29pdrk8nx9hycsjs4w0jgms08qk49jl6v7sq"; authors = [ "Microsoft" ]; }; - "winreg" = rec { - crateName = "winreg"; - version = "0.50.0"; - edition = "2018"; - sha256 = "1cddmp929k882mdh6i9f2as848f13qqna6czwsqzkh1pqnr5fkjj"; - authors = [ - "Igor Shaula <gentoo90@gmail.com>" - ]; + "winnow" = rec { + crateName = "winnow"; + version = "0.6.20"; + edition = "2021"; + sha256 = "16y4i8z9vh8hazjxg5mvmq0c5i35wlk8rxi5gkq6cn5vlb0zxh9n"; dependencies = [ { - name = "cfg-if"; - packageId = "cfg-if"; - } - { - name = "windows-sys"; - packageId = "windows-sys 0.48.0"; - features = [ "Win32_Foundation" "Win32_System_Time" "Win32_System_Registry" "Win32_Security" "Win32_Storage_FileSystem" "Win32_System_Diagnostics_Debug" ]; + name = "memchr"; + packageId = "memchr"; + optional = true; + usesDefaultFeatures = false; } ]; features = { - "chrono" = [ "dep:chrono" ]; - "serde" = [ "dep:serde" ]; - "serialization-serde" = [ "transactions" "serde" ]; + "debug" = [ "std" "dep:anstream" "dep:anstyle" "dep:is-terminal" "dep:terminal_size" ]; + "default" = [ "std" ]; + "simd" = [ "dep:memchr" ]; + "std" = [ "alloc" "memchr?/std" ]; + "unstable-doc" = [ "alloc" "std" "simd" "unstable-recover" ]; }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; "wu-manber" = rec { crateName = "wu-manber"; @@ -16759,6 +19820,7 @@ rec { rev = "0d5b22bea136659f7de60b102a7030e0daaa503d"; sha256 = "1zhk83lbq99xzyjwphv2qrb8f8qgfqwa5bbbvyzm0z0bljsjv0pd"; }; + libName = "wu_manber"; authors = [ "Joe Neeman <joeneeman@gmail.com>" ]; @@ -16805,18 +19867,6 @@ rec { }; resolvedDefaultFeatures = [ "default" "unsupported" ]; }; - "xml-rs" = rec { - crateName = "xml-rs"; - version = "0.8.19"; - edition = "2021"; - crateBin = [ ]; - sha256 = "0nnpvk3fv32hgh7vs9gbg2swmzxx5yz73f4b7rak7q39q2x9rjqg"; - libName = "xml"; - authors = [ - "Vladimir Matveev <vmatveev@citrine.cc>" - ]; - - }; "xz2" = rec { crateName = "xz2"; version = "0.1.7"; @@ -16840,19 +19890,95 @@ rec { }; "yansi" = rec { crateName = "yansi"; - version = "0.5.1"; - edition = "2015"; - sha256 = "1v4qljgzh73knr7291cgwrf56zrvhmpn837n5n5pypzq1kciq109"; + version = "1.0.1"; + edition = "2021"; + sha256 = "0jdh55jyv0dpd38ij4qh60zglbw9aa8wafqai6m0wa7xaxk3mrfg"; authors = [ "Sergio Benitez <sb@sergio.bz>" ]; + features = { + "default" = [ "std" ]; + "detect-env" = [ "std" ]; + "detect-tty" = [ "is-terminal" "std" ]; + "hyperlink" = [ "std" ]; + "is-terminal" = [ "dep:is-terminal" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "zerocopy" = rec { + crateName = "zerocopy"; + version = "0.7.35"; + edition = "2018"; + sha256 = "1w36q7b9il2flg0qskapgi9ymgg7p985vniqd09vi0mwib8lz6qv"; + authors = [ + "Joshua Liebow-Feeser <joshlf@google.com>" + ]; + dependencies = [ + { + name = "byteorder"; + packageId = "byteorder"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "zerocopy-derive"; + packageId = "zerocopy-derive"; + optional = true; + } + { + name = "zerocopy-derive"; + packageId = "zerocopy-derive"; + target = { target, features }: false; + } + ]; + devDependencies = [ + { + name = "zerocopy-derive"; + packageId = "zerocopy-derive"; + } + ]; + features = { + "__internal_use_only_features_that_work_on_stable" = [ "alloc" "derive" "simd" ]; + "byteorder" = [ "dep:byteorder" ]; + "default" = [ "byteorder" ]; + "derive" = [ "zerocopy-derive" ]; + "simd-nightly" = [ "simd" ]; + "zerocopy-derive" = [ "dep:zerocopy-derive" ]; + }; + resolvedDefaultFeatures = [ "byteorder" "default" "derive" "simd" "zerocopy-derive" ]; + }; + "zerocopy-derive" = rec { + crateName = "zerocopy-derive"; + version = "0.7.35"; + edition = "2018"; + sha256 = "0gnf2ap2y92nwdalzz3x7142f2b83sni66l39vxp2ijd6j080kzs"; + procMacro = true; + libName = "zerocopy_derive"; + authors = [ + "Joshua Liebow-Feeser <joshlf@google.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + } + ]; }; "zeroize" = rec { crateName = "zeroize"; - version = "1.7.0"; + version = "1.8.1"; edition = "2021"; - sha256 = "0bfvby7k9pdp6623p98yz2irqnamcyzpn7zh20nqmdn68b0lwnsj"; + sha256 = "1pjdrmjwmszpxfd7r860jx54cyk94qk59x13sc307cvr5256glyf"; authors = [ "The RustCrypto Project Developers" ]; @@ -16867,9 +19993,9 @@ rec { }; "zstd" = rec { crateName = "zstd"; - version = "0.13.0"; + version = "0.13.2"; edition = "2018"; - sha256 = "0401q54s9r35x2i7m1kwppgkj79g0pb6xz3xpby7qlkdb44k7yxz"; + sha256 = "1ygkr6wspm9clbp7ykyl0rv69cfsf9q4lic9wcqiwn34lrwbgwpw"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -16900,9 +20026,10 @@ rec { }; "zstd-safe" = rec { crateName = "zstd-safe"; - version = "7.0.0"; + version = "7.2.1"; edition = "2018"; - sha256 = "0gpav2lcibrpmyslmjkcn3w0w64qif3jjljd2h8lr4p249s7qx23"; + sha256 = "0nch85m5cr493y26yvndm6a8j6sd9mxpr2awrim3dslcnr6sp8sl"; + libName = "zstd_safe"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -16932,10 +20059,11 @@ rec { }; "zstd-sys" = rec { crateName = "zstd-sys"; - version = "2.0.9+zstd.1.5.5"; + version = "2.0.13+zstd.1.5.6"; edition = "2018"; links = "zstd"; - sha256 = "0mk6a2367swdi22zg03lcackpnvgq96d7120awd4i83lm2lfy5ly"; + sha256 = "1almbackh06am0d2kc4a089n3al91jg3ahgg9kcrg3zfrwhhzzrq"; + libName = "zstd_sys"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -16971,14 +20099,11 @@ rec { fuchsia = true; test = false; - /* We are choosing an arbitrary rust version to grab `lib` from, - which is unfortunate, but `lib` has been version-agnostic the - whole time so this is good enough for now. - */ - os = pkgs.rust.lib.toTargetOs platform; - arch = pkgs.rust.lib.toTargetArch platform; - family = pkgs.rust.lib.toTargetFamily platform; - vendor = pkgs.rust.lib.toTargetVendor platform; + inherit (platform.rust.platform) + arch + os + vendor; + family = platform.rust.platform.target-family; env = "gnu"; endian = if platform.parsed.cpu.significantByte.name == "littleEndian" @@ -17068,51 +20193,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; - export RUST_BACKTRACE=1 + inherit (crate) src; - # recreate a file hierarchy as when running tests with cargo + inherit testCrateFlags; - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # TODO(raitobezarius): I believe there could be more edge cases if `crate.sourceRoot` - # do exist but it's very hard to reason about them, so let's wait until the first bug report. - mkdir -p source/ - cd source/ + buildInputs = testInputs; - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + buildPhase = '' + set -e + export RUST_BACKTRACE=1 - # build outputs - testRoot=target/debug - mkdir -p $testRoot + # build outputs + testRoot=target/debug + mkdir -p $testRoot - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { @@ -17221,7 +20336,7 @@ rec { let self = { crates = lib.mapAttrs (packageId: value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs; - target = makeTarget pkgs.stdenv.hostPlatform; + target = makeTarget stdenv.hostPlatform; build = mkBuiltByPackageIdByPkgs pkgs.buildPackages; }; in @@ -17296,8 +20411,6 @@ rec { buildRustCrateForPkgsFunc pkgs ( crateConfig // { - # https://github.com/NixOS/nixpkgs/issues/218712 - dontStrip = stdenv.hostPlatform.isDarwin; src = crateConfig.src or ( pkgs.fetchurl rec { name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz"; diff --git a/tvix/Cargo.toml b/tvix/Cargo.toml index 6cd19831dc83..19f3a2b9c521 100644 --- a/tvix/Cargo.toml +++ b/tvix/Cargo.toml @@ -25,11 +25,143 @@ members = [ "eval", "eval/builtin-macros", "glue", + "nar-bridge", "nix-compat", + "nix-compat-derive", + "nix-compat-derive-tests", + "nix-daemon", "serde", "store", + "tracing", ] +[workspace.lints.clippy] +# Allow blocks_in_conditions due to false positives with #[tracing::instrument(…)]: +# https://github.com/rust-lang/rust-clippy/issues/12281 +blocks_in_conditions = "allow" + +[workspace.dependencies] +anyhow = "1.0.86" +async-compression = "0.4.12" +async-process = "2.2.4" +async-stream = "0.3.5" +async-tempfile = "0.4.0" +axum = "0.7.5" +axum-extra = "0.9.3" +axum-range = "0.4.0" +# https://github.com/liufuyang/bigtable_rs/pull/86 +bigtable_rs = { git = "https://github.com/liufuyang/bigtable_rs", rev = "1818355a5373a5bc2c84287e3a4e3807154ac8ef" } +bitflags = "2.6.0" +blake3 = "1.5.4" +bstr = "1.10.0" +bytes = "1.7.1" +clap = "4.5.16" +codemap = "0.1.3" +codemap-diagnostic = "0.1.2" +count-write = "0.1.0" +criterion = "0.5" +data-encoding = "2.6.0" +digest = "0.10.7" +dirs = "4.0.0" +ed25519 = "2.2.3" +ed25519-dalek = "2.1.1" +enum-primitive-derive = "0.3.0" +erased-serde = "0.4.5" +expect-test = "1.5.0" +fastcdc = "3.1.0" +fuse-backend-rs = "0.12.0" +futures = "0.3.30" +genawaiter = { version = "0.99.1", default-features = false } +glob = "0.3.1" +hex-literal = "0.4.1" +http = "1.1.0" +hyper-util = "0.1.7" +indicatif = "0.17.8" +itertools = "0.12.1" +lexical-core = "0.8.5" +libc = "0.2.158" +lru = "0.12.4" +magic = "0.16.2" +md-5 = "0.10.6" +mimalloc = "0.1.43" +nix = "0.27.1" +nohash-hasher = "0.2.0" +nom = "7.1.3" +num-traits = "0.2.19" +object_store = "0.10.2" +opentelemetry = "0.24.0" +opentelemetry-http = "0.13.0" +opentelemetry-otlp = "0.17.0" +opentelemetry_sdk = "0.24.1" +os_str_bytes = "6.6" +parking_lot = "0.12.3" +path-clean = "0.1" +petgraph = "0.6.5" +pin-project = "1.1" +pin-project-lite = "0.2.14" +pretty_assertions = "1.4.0" +proc-macro2 = "1.0.86" +proptest = { version = "1.5.0", default-features = false } +prost = "0.13.1" +prost-build = "0.13.1" +quote = "1.0.37" +redb = "2.1.2" +regex = "1.10.6" +reqwest = { version = "0.12.7", default-features = false } +reqwest-middleware = "0.3.3" +reqwest-tracing = { version = "0.5.3", default-features = false } +rnix = "0.11.0" +rowan = "*" +rstest = "0.19.0" +rstest_reuse = "0.6.0" +rustc-hash = "2.0.0" +rustyline = "10.1.1" +serde = "1.0.209" +serde_json = "1.0" +serde_qs = "0.12.0" +serde_tagged = "0.3.0" +serde_with = "3.9.0" +sha1 = "0.10.6" +sha2 = "0.10.8" +smol_str = "0.2.2" +tabwriter = "1.4" +tempfile = "3.12.0" +test-strategy = "0.2.1" +thiserror = "1.0.63" +threadpool = "1.8.1" +tokio = "1.39.3" +tokio-listener = "0.4.3" +tokio-retry = "0.3.0" +tokio-stream = "0.1.15" +tokio-tar = "0.3.1" +tokio-test = "0.4.4" +tokio-util = "0.7.11" +tonic = "0.12.2" +tonic-build = "0.12.2" +tonic-health = { version = "0.12.2", default-features = false } +tonic-reflection = "0.12.2" +tower = "0.4.13" +tower-http = "0.5.2" +tracing = "0.1.40" +tracing-indicatif = "0.3.6" +tracing-opentelemetry = "0.25.0" +tracing-subscriber = "0.3.18" +tracing-tracy = "0.11.2" +trybuild = "1.0.99" +url = "2.5.2" +vhost = "0.6" +vhost-user-backend = "0.8" +virtio-bindings = "0.2.2" +virtio-queue = "0.7" +vm-memory = "0.10" +vmm-sys-util = "0.11" +vu128 = "1.1.0" +walkdir = "2.5.0" +# https://github.com/jneem/wu-manber/pull/1 +wu-manber = { git = "https://github.com/tvlfyi/wu-manber.git" } +xattr = "1.3.1" +zstd = "0.13.2" + # Add a profile to all targets that enables release optimisations, but # retains debug symbols. This is great for use with # benchmarking/profiling tools. diff --git a/tvix/README.md b/tvix/README.md index bf96afa4ba3f..af12d6ff4b10 100644 --- a/tvix/README.md +++ b/tvix/README.md @@ -61,8 +61,7 @@ This folder contains the following components: * `//tvix/castore` - subtree storage/transfer in a content-addressed fashion * `//tvix/cli` - preliminary REPL & CLI implementation for Tvix * `//tvix/eval` - an implementation of the Nix programming language -* `//tvix/nar-bridge` - * `nar-bridge-http`: A HTTP webserver providing a Nix HTTP Binary Cache interface in front of a tvix-store +* `//tvix/nar-bridge` - a HTTP webserver providing a Nix HTTP Binary Cache interface in front of a tvix-store * `//tvix/nix-compat` - a Rust library for compatibility with C++ Nix, features like encodings and hashing schemes and formats * `//tvix/serde` - a Rust library for using the Nix language for app configuration * `//tvix/store` - a "filesystem" linking Nix store paths and metadata with the content-addressed layer @@ -105,6 +104,11 @@ Rust projects under `//tvix`, be sure to run `mg run //tools:crate2nix-generate` in `//tvix` itself and commit the changes to the generated `Cargo.nix` file. This only applies to the full TVL checkout. +When adding/removing a Cargo feature for a crate, you will want to add it to the +features power set that gets tested in CI. For each crate there's a default.nix with a +`mkFeaturePowerset` invocation, modify the list to include/remove the feature. +Note that you don't want to add "collection" features, such as `fs` for tvix-[ca]store or `default`. + ## License structure All code implemented for Tvix is licensed under the GPL-3.0, with the diff --git a/tvix/boot/README.md b/tvix/boot/README.md index 13a485506079..037a15852d06 100644 --- a/tvix/boot/README.md +++ b/tvix/boot/README.md @@ -31,21 +31,35 @@ the `tvix` directory: export PATH=$PATH:$PWD/target/release-with-debug ``` -Secondly, configure tvix to use the local backend: +Now, spin up tvix-daemon, connecting to some (local) backends: ``` -export BLOB_SERVICE_ADDR=sled://$PWD/blobs.sled -export DIRECTORY_SERVICE_ADDR=sled://$PWD/directories.sled -export PATH_INFO_SERVICE_ADDR=sled://$PWD/pathinfo.sled +tvix-store --otlp=false daemon \ + --blob-service-addr=objectstore+file://$PWD/blobs \ + --directory-service-addr=redb://$PWD/directories.redb \ + --path-info-service-addr=redb://$PWD/pathinfo.redb & ``` -Potentially copy some data into tvix-store (via nar-bridge): +Copy some data into tvix-store (we use `nar-bridge` for this for now): ``` -mg run //tvix:store -- daemon & -$(mg build //tvix:nar-bridge)/bin/nar-bridge-http & +mg run //tvix:nar-bridge -- --otlp=false & rm -Rf ~/.cache/nix; nix copy --to http://localhost:9000\?compression\=none $(mg build //third_party/nixpkgs:hello) -pkill nar-bridge-http; pkill tvix-store +pkill nar-bridge +``` + +By default, the `tvix-store virtiofs` command used in the `runVM` script +connects to a running `tvix-store daemon` via gRPC - in which case you want to +keep `tvix-store daemon` running. + +In case you want to have `tvix-store virtiofs` open the stores directly, kill +`tvix-store daemon` too, and export the addresses from above: + +``` +pkill tvix-store +export BLOB_SERVICE_ADDR=objectstore+file://$PWD/blobs +export DIRECTORY_SERVICE_ADDR=redb://$PWD/directories.redb +export PATH_INFO_SERVICE_ADDR=redb://$PWD/pathinfo.redb ``` #### Interactive shell @@ -100,9 +114,12 @@ Hello, world! [ 0.299422] reboot: Power down ``` -#### Execute a NixOS system closure -It's also possible to invoke a system closure. To do this, tvix-init honors the -init= cmdline option, and will switch_root to it. +#### Boot a NixOS system closure +It's also possible to boot a system closure. To do this, tvix-init honors the +init= cmdline option, and will `switch_root` to it. + +Make sure to first copy that system closure into tvix-store, +using a similar `nix copy` comamnd as above. ``` diff --git a/tvix/boot/default.nix b/tvix/boot/default.nix index 85995ffbf2c5..60eb2f1b7608 100644 --- a/tvix/boot/default.nix +++ b/tvix/boot/default.nix @@ -1,13 +1,16 @@ -{ depot, pkgs, ... }: +{ lib, pkgs, ... }: rec { # A binary that sets up /nix/store from virtiofs, lists all store paths, and # powers off the machine. - tvix-init = depot.nix.buildGo.program { + tvix-init = pkgs.buildGoModule rec { name = "tvix-init"; - srcs = [ - ./tvix-init.go - ]; + src = lib.fileset.toSource { + root = ./.; + fileset = ./tvix-init.go; + }; + vendorHash = null; + postPatch = "go mod init ${name}"; }; # A kernel with virtiofs support baked in @@ -99,7 +102,7 @@ rec { --memory mergeable=on,shared=on,size=$CH_MEM_SIZE \ --console null \ --serial tty \ - --kernel ${kernel.dev}/vmlinux \ + --kernel ${kernel}/${pkgs.stdenv.hostPlatform.linux-kernel.target} \ --initramfs ${initrd} \ --cmdline "console=ttyS0 $CH_CMDLINE" \ --fs tag=tvix,socket=$tempdir/tvix.sock,num_queues=''${CH_NUM_CPU},queue_size=512 diff --git a/tvix/boot/tests/default.nix b/tvix/boot/tests/default.nix index d16dba79f140..97477572078e 100644 --- a/tvix/boot/tests/default.nix +++ b/tvix/boot/tests/default.nix @@ -16,8 +16,17 @@ let # Whether the path should be imported as a closure. # If false, importPathName must be specified. , isClosure ? false + # Whether to use nar-bridge to upload, rather than tvix-store copy. + # using nar-bridge currently is "slower", as the `pkgs.mkBinaryCache` build + # takes quite some time. + , useNarBridge ? false + , importPathName ? null + # Commands to run before starting the tvix-daemon. Useful to provide + # auxillary mock services. + , preStart ? "" + # The cmdline to pass to the VM. # Defaults to tvix.find, which lists all files in the store. , vmCmdline ? "tvix.find" @@ -29,29 +38,35 @@ let assert isClosure -> importPathName == null; assert (!isClosure) -> importPathName != null; - pkgs.stdenv.mkDerivation { + pkgs.stdenv.mkDerivation ({ name = "run-vm"; - __structuredAttrs = true; - exportReferencesGraph.closure = [ path ]; - nativeBuildInputs = [ depot.tvix.store depot.tvix.boot.runVM + ] ++ lib.optionals (isClosure && useNarBridge) [ + depot.tvix.nar-bridge + pkgs.curl + pkgs.parallel + pkgs.xz.bin ]; buildCommand = '' touch $out + # Ensure we can construct http clients. + export SSL_CERT_FILE=/dev/null + + ${preStart} # Start the tvix daemon, listening on a unix socket. - BLOB_SERVICE_ADDR=${blobServiceAddr} \ - DIRECTORY_SERVICE_ADDR=${directoryServiceAddr} \ - PATH_INFO_SERVICE_ADDR=${pathInfoServiceAddr} \ + BLOB_SERVICE_ADDR=${lib.escapeShellArg blobServiceAddr} \ + DIRECTORY_SERVICE_ADDR=${lib.escapeShellArg directoryServiceAddr} \ + PATH_INFO_SERVICE_ADDR=${lib.escapeShellArg pathInfoServiceAddr} \ tvix-store \ --otlp=false \ daemon -l $PWD/tvix-store.sock & - # Wait for the socket to be created. - while [ ! -e $PWD/tvix-store.sock ]; do sleep 1; done + # Wait for the service to report healthy. + timeout 22 sh -c "until ${pkgs.ip2unix}/bin/ip2unix -r out,path=$PWD/tvix-store.sock ${pkgs.grpc-health-check}/bin/grpc-health-check --address 127.0.0.1 --port 8080; do sleep 1; done" # Export env vars so that subsequent tvix-store commands will talk to # our tvix-store daemon over the unix socket. @@ -64,10 +79,38 @@ let outpath=$(tvix-store import ${importPathName}) echo "imported to $outpath" - '' + lib.optionalString (isClosure) '' + '' + lib.optionalString (isClosure && !useNarBridge) '' echo "Copying closure ${path}…" # This picks up the `closure` key in `$NIX_ATTRS_JSON_FILE` automatically. tvix-store --otlp=false copy + '' + lib.optionalString (isClosure && useNarBridge) '' + echo "Starting nar-bridge…" + nar-bridge \ + --otlp=false \ + -l $PWD/nar-bridge.sock & + + # Wait for nar-bridge to report healthy. + timeout 22 sh -c "until ${pkgs.curl}/bin/curl -s --unix-socket $PWD/nar-bridge.sock http:///nix-binary-cache; do sleep 1; done" + + # Upload. We can't use nix copy --to http://…, as it wants access to the nix db. + # However, we can use mkBinaryCache to assemble .narinfo and .nar.xz to upload, + # and then drive a HTTP client ourselves. + to_upload=${pkgs.mkBinaryCache { rootPaths = [path];}} + + # Upload all NAR files (with some parallelism). + # As mkBinaryCache produces them xz-compressed, unpack them on the fly. + # nar-bridge doesn't care about the path we upload *to*, but a + # subsequent .narinfo upload need to refer to its contents (by narhash). + echo -e "Uploading NARs… " + ls -d $to_upload/nar/*.nar.xz | parallel 'xz -d < {} | curl -s -T - --unix-socket $PWD/nar-bridge.sock http://localhost:9000/nar/$(basename {} | cut -d "." -f 1).nar' + echo "Done." + + # Upload all NARInfo files. + # FUTUREWORK: This doesn't upload them in order, and currently relies + # on PathInfoService not doing any checking. + # In the future, we might want to make this behaviour configurable, + # and disable checking here, to keep the logic simple. + ls -d $to_upload/*.narinfo | parallel 'curl -s -T - --unix-socket $PWD/nar-bridge.sock http://localhost:9000/$(basename {}) < {}' '' + '' # Invoke a VM using tvix as the backing store, ensure the outpath appears in its listing. echo "Starting VM…" @@ -76,11 +119,20 @@ let grep "${assertVMOutput}" output.txt ''; requiredSystemFeatures = [ "kvm" ]; - }; - - systemFor = sys: (depot.ops.nixos.nixosFor sys).system; + # HACK: The boot tests are sometimes flaky, and we don't want them to + # periodically fail other build. Have Buildkite auto-retry them 2 times + # on failure. + # Logs for individual failures are still available, so it won't hinder + # flakiness debuggability. + meta.ci.buildkiteExtraStepArgs = { + retry.automatic = true; + }; + } // lib.optionalAttrs (isClosure && !useNarBridge) { + __structuredAttrs = true; + exportReferencesGraph.closure = [ path ]; + }); - testSystem = systemFor ({ modulesPath, pkgs, ... }: { + testSystem = (pkgs.nixos { # Set some options necessary to evaluate. boot.loader.systemd-boot.enable = true; # TODO: figure out how to disable this without causing eval to fail @@ -100,7 +152,10 @@ let # Don't warn about stateVersion. system.stateVersion = "24.05"; - }); + + # Speed-up evaluation and building. + documentation.enable = lib.mkForce false; + }).config.system.build.toplevel; in depot.nix.readTree.drvTargets @@ -109,28 +164,75 @@ depot.nix.readTree.drvTargets path = ../../docs; importPathName = "docs"; }); - docs-sled = (mkBootTest { - blobServiceAddr = "sled://$PWD/blobs.sled"; - directoryServiceAddr = "sled://$PWD/directories.sled"; - pathInfoServiceAddr = "sled://$PWD/pathinfo.sled"; - path = ../../docs; - importPathName = "docs"; - }); - docs-objectstore-local = (mkBootTest { - blobServiceAddr = "objectstore+file://$PWD/blobs"; + docs-persistent = (mkBootTest { + blobServiceAddr = "objectstore+file:///build/blobs"; + directoryServiceAddr = "redb:///build/directories.redb"; + pathInfoServiceAddr = "redb:///build/pathinfo.redb"; path = ../../docs; importPathName = "docs"; }); closure-tvix = (mkBootTest { - blobServiceAddr = "objectstore+file://$PWD/blobs"; + blobServiceAddr = "objectstore+file:///build/blobs"; path = depot.tvix.store; isClosure = true; }); closure-nixos = (mkBootTest { - blobServiceAddr = "objectstore+file://$PWD/blobs"; + blobServiceAddr = "objectstore+file:///build/blobs"; + pathInfoServiceAddr = "redb:///build/pathinfo.redb"; + directoryServiceAddr = "redb:///build/directories.redb"; + path = testSystem; + isClosure = true; + vmCmdline = "init=${testSystem}/init panic=-1"; # reboot immediately on panic + assertVMOutput = "Onwards and upwards."; + }); + + closure-nixos-bigtable = (mkBootTest { + blobServiceAddr = "objectstore+file:///build/blobs"; + directoryServiceAddr = "bigtable://instance-1?project_id=project-1&table_name=directories&family_name=cf1"; + pathInfoServiceAddr = "bigtable://instance-1?project_id=project-1&table_name=pathinfos&family_name=cf1"; + path = testSystem; + useNarBridge = true; + preStart = '' + ${pkgs.cbtemulator}/bin/cbtemulator -address $PWD/cbtemulator.sock & + timeout 22 sh -c 'until [ -e $PWD/cbtemulator.sock ]; do sleep 1; done' + + export BIGTABLE_EMULATOR_HOST=unix://$PWD/cbtemulator.sock + ${pkgs.google-cloud-bigtable-tool}/bin/cbt -instance instance-1 -project project-1 createtable directories + ${pkgs.google-cloud-bigtable-tool}/bin/cbt -instance instance-1 -project project-1 createfamily directories cf1 + ${pkgs.google-cloud-bigtable-tool}/bin/cbt -instance instance-1 -project project-1 createtable pathinfos + ${pkgs.google-cloud-bigtable-tool}/bin/cbt -instance instance-1 -project project-1 createfamily pathinfos cf1 + ''; + isClosure = true; + vmCmdline = "init=${testSystem}/init panic=-1"; # reboot immediately on panic + assertVMOutput = "Onwards and upwards."; + }); + + closure-nixos-s3 = (mkBootTest { + blobServiceAddr = "objectstore+s3://mybucket/blobs?aws_access_key_id=myaccesskey&aws_secret_access_key=supersecret&aws_endpoint_url=http%3A%2F%2Flocalhost%3A9000&aws_allow_http=1"; + # we cannot use s3 here yet without any caching layer, as we don't allow "deeper" access to directories (non-root nodes) + # directoryServiceAddr = "objectstore+s3://mybucket/directories?aws_access_key_id=myaccesskey&aws_secret_access_key=supersecret&endpoint=http%3A%2F%2Flocalhost%3A9000&aws_allow_http=1"; + directoryServiceAddr = "memory://"; + pathInfoServiceAddr = "memory://"; + path = testSystem; + useNarBridge = true; + preStart = '' + MINIO_ACCESS_KEY=myaccesskey MINIO_SECRET_KEY=supersecret MINIO_ADDRESS=127.0.0.1:9000 ${pkgs.minio}/bin/minio server $(mktemp -d) & + timeout 22 sh -c 'until ${pkgs.netcat}/bin/nc -z $0 $1; do sleep 1; done' localhost 9000 + mc_config_dir=$(mktemp -d) + ${pkgs.minio-client}/bin/mc --config-dir $mc_config_dir alias set 'myminio' 'http://127.0.0.1:9000' 'myaccesskey' 'supersecret' + ${pkgs.minio-client}/bin/mc --config-dir $mc_config_dir mb myminio/mybucket + ''; + isClosure = true; + vmCmdline = "init=${testSystem}/init panic=-1"; # reboot immediately on panic + assertVMOutput = "Onwards and upwards."; + }); + + closure-nixos-nar-bridge = (mkBootTest { + blobServiceAddr = "objectstore+file:///build/blobs"; path = testSystem; + useNarBridge = true; isClosure = true; vmCmdline = "init=${testSystem}/init panic=-1"; # reboot immediately on panic assertVMOutput = "Onwards and upwards."; diff --git a/tvix/build-go/build.pb.go b/tvix/build-go/build.pb.go index 9c6bd5f24883..b7adc024cc75 100644 --- a/tvix/build-go/build.pb.go +++ b/tvix/build-go/build.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.35.1 // protoc (unknown) // source: tvix/build/protos/build.proto @@ -66,8 +66,8 @@ type BuildRequest struct { // The list of all root nodes that should be visible in `inputs_dir` at the // time of the build. - // As root nodes are content-addressed, no additional signatures are needed - // to substitute / make these available in the build environment. + // As all references are content-addressed, no additional signatures are + // needed to substitute / make these available in the build environment. // Inputs MUST be sorted by their names. Inputs []*castore_go.Node `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs,omitempty"` // The command (and its args) executed as the build script. @@ -115,15 +115,18 @@ type BuildRequest struct { // build environment, but outside inputs_dir. // Used for passAsFile and structuredAttrs in Nix. AdditionalFiles []*BuildRequest_AdditionalFile `protobuf:"bytes,9,rep,name=additional_files,json=additionalFiles,proto3" json:"additional_files,omitempty"` + // If this is an non-empty list, all paths in `outputs` are scanned for these. + // For Nix, `refscan_needles` would be populated with the nixbase32 hash parts of + // every input store path and output store path. The latter is necessary to scan + // for references between multi-output derivations. + RefscanNeedles []string `protobuf:"bytes,10,rep,name=refscan_needles,json=refscanNeedles,proto3" json:"refscan_needles,omitempty"` } func (x *BuildRequest) Reset() { *x = BuildRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_build_protos_build_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_build_protos_build_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *BuildRequest) String() string { @@ -134,7 +137,7 @@ func (*BuildRequest) ProtoMessage() {} func (x *BuildRequest) ProtoReflect() protoreflect.Message { mi := &file_tvix_build_protos_build_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -212,6 +215,13 @@ func (x *BuildRequest) GetAdditionalFiles() []*BuildRequest_AdditionalFile { return nil } +func (x *BuildRequest) GetRefscanNeedles() []string { + if x != nil { + return x.RefscanNeedles + } + return nil +} + // A Build is (one possible) outcome of executing a [BuildRequest]. type Build struct { state protoimpl.MessageState @@ -223,15 +233,15 @@ type Build struct { // The outputs that were produced after successfully building. // They are sorted by their names. Outputs []*castore_go.Node `protobuf:"bytes,2,rep,name=outputs,proto3" json:"outputs,omitempty"` + // Contains the same number of elements as the `outputs` field. + OutputsNeedles []*Build_OutputNeedles `protobuf:"bytes,3,rep,name=outputs_needles,json=outputsNeedles,proto3" json:"outputs_needles,omitempty"` } func (x *Build) Reset() { *x = Build{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_build_protos_build_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_build_protos_build_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Build) String() string { @@ -242,7 +252,7 @@ func (*Build) ProtoMessage() {} func (x *Build) ProtoReflect() protoreflect.Message { mi := &file_tvix_build_protos_build_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -271,6 +281,13 @@ func (x *Build) GetOutputs() []*castore_go.Node { return nil } +func (x *Build) GetOutputsNeedles() []*Build_OutputNeedles { + if x != nil { + return x.OutputsNeedles + } + return nil +} + type BuildRequest_EnvVar struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -283,11 +300,9 @@ type BuildRequest_EnvVar struct { func (x *BuildRequest_EnvVar) Reset() { *x = BuildRequest_EnvVar{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_build_protos_build_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_build_protos_build_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *BuildRequest_EnvVar) String() string { @@ -298,7 +313,7 @@ func (*BuildRequest_EnvVar) ProtoMessage() {} func (x *BuildRequest_EnvVar) ProtoReflect() protoreflect.Message { mi := &file_tvix_build_protos_build_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -357,11 +372,9 @@ type BuildRequest_BuildConstraints struct { func (x *BuildRequest_BuildConstraints) Reset() { *x = BuildRequest_BuildConstraints{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_build_protos_build_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_build_protos_build_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *BuildRequest_BuildConstraints) String() string { @@ -372,7 +385,7 @@ func (*BuildRequest_BuildConstraints) ProtoMessage() {} func (x *BuildRequest_BuildConstraints) ProtoReflect() protoreflect.Message { mi := &file_tvix_build_protos_build_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -433,11 +446,9 @@ type BuildRequest_AdditionalFile struct { func (x *BuildRequest_AdditionalFile) Reset() { *x = BuildRequest_AdditionalFile{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_build_protos_build_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_build_protos_build_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *BuildRequest_AdditionalFile) String() string { @@ -448,7 +459,7 @@ func (*BuildRequest_AdditionalFile) ProtoMessage() {} func (x *BuildRequest_AdditionalFile) ProtoReflect() protoreflect.Message { mi := &file_tvix_build_protos_build_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -477,6 +488,52 @@ func (x *BuildRequest_AdditionalFile) GetContents() []byte { return nil } +type Build_OutputNeedles struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The numbers are indexing into `refscan_needles` originally specified in the BuildRequest. + Needles []uint64 `protobuf:"varint,1,rep,packed,name=needles,proto3" json:"needles,omitempty"` +} + +func (x *Build_OutputNeedles) Reset() { + *x = Build_OutputNeedles{} + mi := &file_tvix_build_protos_build_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Build_OutputNeedles) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Build_OutputNeedles) ProtoMessage() {} + +func (x *Build_OutputNeedles) ProtoReflect() protoreflect.Message { + mi := &file_tvix_build_protos_build_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Build_OutputNeedles.ProtoReflect.Descriptor instead. +func (*Build_OutputNeedles) Descriptor() ([]byte, []int) { + return file_tvix_build_protos_build_proto_rawDescGZIP(), []int{1, 0} +} + +func (x *Build_OutputNeedles) GetNeedles() []uint64 { + if x != nil { + return x.Needles + } + return nil +} + var File_tvix_build_protos_build_proto protoreflect.FileDescriptor var file_tvix_build_protos_build_proto_rawDesc = []byte{ @@ -485,7 +542,7 @@ var file_tvix_build_protos_build_proto_rawDesc = []byte{ 0x0d, 0x74, 0x76, 0x69, 0x78, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x2e, 0x76, 0x31, 0x1a, 0x21, 0x74, 0x76, 0x69, 0x78, 0x2f, 0x63, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x63, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0x90, 0x06, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x6f, 0x22, 0xb9, 0x06, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x76, 0x69, 0x78, 0x2e, 0x63, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, @@ -514,37 +571,47 @@ var file_tvix_build_protos_build_proto_rawDesc = []byte{ 0x76, 0x69, 0x78, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x0f, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x1a, 0x30, 0x0a, 0x06, 0x45, 0x6e, 0x76, - 0x56, 0x61, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0xc4, 0x01, 0x0a, 0x10, - 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, - 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x69, 0x6e, 0x5f, - 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x69, - 0x6e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x6f, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, - 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x24, 0x0a, 0x0e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x5f, 0x62, 0x69, 0x6e, 0x5f, 0x73, 0x68, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x42, 0x69, 0x6e, - 0x53, 0x68, 0x1a, 0x40, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7a, 0x0a, 0x05, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x40, 0x0a, - 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x76, 0x69, 0x78, 0x2e, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x2f, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x74, 0x76, 0x69, 0x78, 0x2e, 0x63, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, - 0x42, 0x24, 0x5a, 0x22, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x74, 0x76, 0x6c, 0x2e, 0x66, 0x79, 0x69, - 0x2f, 0x74, 0x76, 0x69, 0x78, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x2d, 0x67, 0x6f, 0x3b, 0x62, - 0x75, 0x69, 0x6c, 0x64, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x66, + 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x66, 0x73, 0x63, 0x61, 0x6e, 0x4e, 0x65, 0x65, 0x64, 0x6c, + 0x65, 0x73, 0x1a, 0x30, 0x0a, 0x06, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x1a, 0xc4, 0x01, 0x0a, 0x10, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, + 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x69, 0x6e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, + 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x6f, + 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x76, + 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x6f, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x25, + 0x0a, 0x0e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x5f, 0x62, 0x69, 0x6e, 0x5f, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x42, 0x69, 0x6e, 0x53, 0x68, 0x1a, 0x40, 0x0a, 0x0e, 0x41, + 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xf2, 0x01, + 0x0a, 0x05, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x40, 0x0a, 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x74, 0x76, 0x69, 0x78, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x42, + 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0c, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x6f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x76, 0x69, + 0x78, 0x2e, 0x63, 0x61, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x0f, 0x6f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x73, 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x76, 0x69, 0x78, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x4e, 0x65, 0x65, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, + 0x4e, 0x65, 0x65, 0x64, 0x6c, 0x65, 0x73, 0x1a, 0x29, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x4e, 0x65, 0x65, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x65, 0x64, + 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52, 0x07, 0x6e, 0x65, 0x65, 0x64, 0x6c, + 0x65, 0x73, 0x42, 0x24, 0x5a, 0x22, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x74, 0x76, 0x6c, 0x2e, 0x66, + 0x79, 0x69, 0x2f, 0x74, 0x76, 0x69, 0x78, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x2d, 0x67, 0x6f, + 0x3b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -559,27 +626,29 @@ func file_tvix_build_protos_build_proto_rawDescGZIP() []byte { return file_tvix_build_protos_build_proto_rawDescData } -var file_tvix_build_protos_build_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_tvix_build_protos_build_proto_goTypes = []interface{}{ +var file_tvix_build_protos_build_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_tvix_build_protos_build_proto_goTypes = []any{ (*BuildRequest)(nil), // 0: tvix.build.v1.BuildRequest (*Build)(nil), // 1: tvix.build.v1.Build (*BuildRequest_EnvVar)(nil), // 2: tvix.build.v1.BuildRequest.EnvVar (*BuildRequest_BuildConstraints)(nil), // 3: tvix.build.v1.BuildRequest.BuildConstraints (*BuildRequest_AdditionalFile)(nil), // 4: tvix.build.v1.BuildRequest.AdditionalFile - (*castore_go.Node)(nil), // 5: tvix.castore.v1.Node + (*Build_OutputNeedles)(nil), // 5: tvix.build.v1.Build.OutputNeedles + (*castore_go.Node)(nil), // 6: tvix.castore.v1.Node } var file_tvix_build_protos_build_proto_depIdxs = []int32{ - 5, // 0: tvix.build.v1.BuildRequest.inputs:type_name -> tvix.castore.v1.Node + 6, // 0: tvix.build.v1.BuildRequest.inputs:type_name -> tvix.castore.v1.Node 2, // 1: tvix.build.v1.BuildRequest.environment_vars:type_name -> tvix.build.v1.BuildRequest.EnvVar 3, // 2: tvix.build.v1.BuildRequest.constraints:type_name -> tvix.build.v1.BuildRequest.BuildConstraints 4, // 3: tvix.build.v1.BuildRequest.additional_files:type_name -> tvix.build.v1.BuildRequest.AdditionalFile 0, // 4: tvix.build.v1.Build.build_request:type_name -> tvix.build.v1.BuildRequest - 5, // 5: tvix.build.v1.Build.outputs:type_name -> tvix.castore.v1.Node - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 6, // 5: tvix.build.v1.Build.outputs:type_name -> tvix.castore.v1.Node + 5, // 6: tvix.build.v1.Build.outputs_needles:type_name -> tvix.build.v1.Build.OutputNeedles + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_tvix_build_protos_build_proto_init() } @@ -587,75 +656,13 @@ func file_tvix_build_protos_build_proto_init() { if File_tvix_build_protos_build_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_tvix_build_protos_build_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BuildRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_build_protos_build_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Build); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_build_protos_build_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BuildRequest_EnvVar); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_build_protos_build_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BuildRequest_BuildConstraints); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_build_protos_build_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BuildRequest_AdditionalFile); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_tvix_build_protos_build_proto_rawDesc, NumEnums: 0, - NumMessages: 5, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, diff --git a/tvix/build-go/rpc_build.pb.go b/tvix/build-go/rpc_build.pb.go index aae0cd9d4776..e6cdb84f1669 100644 --- a/tvix/build-go/rpc_build.pb.go +++ b/tvix/build-go/rpc_build.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.35.1 // protoc (unknown) // source: tvix/build/protos/rpc_build.proto @@ -40,7 +40,7 @@ var file_tvix_build_protos_rpc_build_proto_rawDesc = []byte{ 0x69, 0x6c, 0x64, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } -var file_tvix_build_protos_rpc_build_proto_goTypes = []interface{}{ +var file_tvix_build_protos_rpc_build_proto_goTypes = []any{ (*BuildRequest)(nil), // 0: tvix.build.v1.BuildRequest (*Build)(nil), // 1: tvix.build.v1.Build } diff --git a/tvix/build/Cargo.toml b/tvix/build/Cargo.toml index 626fd35d7713..86f3fe4ac1f8 100644 --- a/tvix/build/Cargo.toml +++ b/tvix/build/Cargo.toml @@ -4,30 +4,42 @@ version = "0.1.0" edition = "2021" [dependencies] -bytes = "1.4.0" -clap = { version = "4.0", features = ["derive", "env"] } -itertools = "0.12.0" -prost = "0.12.1" -thiserror = "1.0.56" -tokio = { version = "1.32.0" } -tokio-listener = { version = "0.3.2", features = [ "tonic011" ] } -tonic = { version = "0.11.0", features = ["tls", "tls-roots"] } -tvix-castore = { path = "../castore" } -tracing = "0.1.37" -tracing-subscriber = { version = "0.3.16", features = ["json"] } -url = "2.4.0" +bytes = { workspace = true } +clap = { workspace = true, features = ["derive", "env"] } +itertools = { workspace = true } +prost = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true, features = ["process"] } +tokio-listener = { workspace = true, features = ["tonic012"] } +tonic = { workspace = true, features = ["tls", "tls-roots"] } +# TODO: put the fuse dep behind a feature flag? +tvix-castore = { path = "../castore", features = ["fuse"]} +tracing = { workspace = true } +url = { workspace = true } +mimalloc = { workspace = true } +tonic-reflection = { workspace = true, optional = true } -[dependencies.tonic-reflection] -optional = true -version = "0.11.0" +anyhow = "1.0.79" +blake3 = "1.5.0" +bstr = "1.6.0" +data-encoding = "2.5.0" +futures = "0.3.30" +oci-spec = "0.7.0" +serde_json = "1.0.111" +tvix-tracing = { path = "../tracing" } +uuid = { version = "1.7.0", features = ["v4"] } [build-dependencies] -prost-build = "0.12.1" -tonic-build = "0.11.0" +prost-build = { workspace = true } +tonic-build = { workspace = true } [features] default = [] -tonic-reflection = ["dep:tonic-reflection"] +tonic-reflection = ["dep:tonic-reflection", "tvix-castore/tonic-reflection"] [dev-dependencies] -rstest = "0.19.0" +rstest = { workspace = true } +tempfile = "3.3.0" + +[lints] +workspace = true diff --git a/tvix/build/build.rs b/tvix/build/build.rs index c3518ea8772b..2fb8d86ee15f 100644 --- a/tvix/build/build.rs +++ b/tvix/build/build.rs @@ -12,27 +12,25 @@ fn main() -> Result<()> { builder = builder.file_descriptor_set_path(descriptor_path); }; - // https://github.com/hyperium/tonic/issues/908 - let mut config = prost_build::Config::new(); - config.bytes(["."]); - config.extern_path(".tvix.castore.v1", "::tvix_castore::proto"); - builder .build_server(true) .build_client(true) .emit_rerun_if_changed(false) - .compile_with_config( - config, + .bytes(["."]) + .extern_path(".tvix.castore.v1", "::tvix_castore::proto") + .compile_protos( &[ "tvix/build/protos/build.proto", "tvix/build/protos/rpc_build.proto", ], // If we are in running `cargo build` manually, using `../..` works fine, // but in case we run inside a nix build, we need to instead point PROTO_ROOT - // to a sparseTree containing that structure. + // to a custom tree containing that structure. &[match std::env::var_os("PROTO_ROOT") { Some(proto_root) => proto_root.to_str().unwrap().to_owned(), None => "../..".to_string(), }], - ) + )?; + + Ok(()) } diff --git a/tvix/build/default.nix b/tvix/build/default.nix index a2a3bea0c5a5..17b52354bbeb 100644 --- a/tvix/build/default.nix +++ b/tvix/build/default.nix @@ -1,5 +1,11 @@ -{ depot, pkgs, ... }: +{ depot, lib, ... }: -depot.tvix.crates.workspaceMembers.tvix-build.build.override { +(depot.tvix.crates.workspaceMembers.tvix-build.build.override { runTests = true; -} +}).overrideAttrs (old: rec { + meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { + inherit (old) crateName; + features = [ "tonic-reflection" ]; + }); +}) diff --git a/tvix/build/protos/build.proto b/tvix/build/protos/build.proto index f1f6bf0b05d8..1d6f8690c58c 100644 --- a/tvix/build/protos/build.proto +++ b/tvix/build/protos/build.proto @@ -47,8 +47,8 @@ option go_package = "code.tvl.fyi/tvix/build-go;buildv1"; message BuildRequest { // The list of all root nodes that should be visible in `inputs_dir` at the // time of the build. - // As root nodes are content-addressed, no additional signatures are needed - // to substitute / make these available in the build environment. + // As all references are content-addressed, no additional signatures are + // needed to substitute / make these available in the build environment. // Inputs MUST be sorted by their names. repeated tvix.castore.v1.Node inputs = 1; @@ -144,6 +144,12 @@ message BuildRequest { bytes contents = 2; } + // If this is an non-empty list, all paths in `outputs` are scanned for these. + // For Nix, `refscan_needles` would be populated with the nixbase32 hash parts of + // every input store path and output store path. The latter is necessary to scan + // for references between multi-output derivations. + repeated string refscan_needles = 10; + // TODO: allow describing something like "preferLocal", to influence composition? } @@ -156,6 +162,14 @@ message Build { // They are sorted by their names. repeated tvix.castore.v1.Node outputs = 2; + message OutputNeedles { + // The numbers are indexing into `refscan_needles` originally specified in the BuildRequest. + repeated uint64 needles = 1; + } + + // Contains the same number of elements as the `outputs` field. + repeated OutputNeedles outputs_needles = 3; + // TODO: where did this run, how long, logs, … } diff --git a/tvix/build/protos/default.nix b/tvix/build/protos/default.nix index 790655ac7522..287b513136c9 100644 --- a/tvix/build/protos/default.nix +++ b/tvix/build/protos/default.nix @@ -1,17 +1,12 @@ -{ depot, pkgs, ... }: +{ depot, pkgs, lib, ... }: let - protos = depot.nix.sparseTree { - name = "build-protos"; - root = depot.path.origSrc; - paths = [ - # We need to include castore.proto (only), as it's referred. - ../../castore/protos/castore.proto - ./build.proto - ./rpc_build.proto - ../../../buf.yaml - ../../../buf.gen.yaml - ]; - }; + protos = lib.sourceByRegex depot.path.origSrc [ + "buf.yaml" + "buf.gen.yaml" + # We need to include castore.proto (only), as it's referred. + "^tvix(/castore(/protos(/castore\.proto)?)?)?$" + "^tvix(/build(/protos(/.*\.proto)?)?)?$" + ]; in depot.nix.readTree.drvTargets { inherit protos; diff --git a/tvix/build/src/bin/tvix-build.rs b/tvix/build/src/bin/tvix-build.rs index ed36c8933cae..cb92f333effb 100644 --- a/tvix/build/src/bin/tvix-build.rs +++ b/tvix/build/src/bin/tvix-build.rs @@ -1,13 +1,10 @@ -use std::sync::Arc; - use clap::Parser; use clap::Subcommand; use tokio_listener::Listener; use tokio_listener::SystemOptions; use tokio_listener::UserOptions; use tonic::{self, transport::Server}; -use tracing::{info, Level}; -use tracing_subscriber::prelude::*; +use tracing::info; use tvix_build::{ buildservice, proto::{build_service_server::BuildServiceServer, GRPCBuildServiceWrapper}, @@ -20,16 +17,14 @@ use tvix_build::proto::FILE_DESCRIPTOR_SET; #[cfg(feature = "tonic-reflection")] use tvix_castore::proto::FILE_DESCRIPTOR_SET as CASTORE_FILE_DESCRIPTOR_SET; +use mimalloc::MiMalloc; + +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; + #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Cli { - /// Whether to log in JSON - #[arg(long)] - json: bool, - - #[arg(long)] - log_level: Option<Level>, - #[command(subcommand)] command: Commands, } @@ -52,29 +47,10 @@ enum Commands { } #[tokio::main] -async fn main() -> Result<(), Box<dyn std::error::Error>> { +async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { let cli = Cli::parse(); - // configure log settings - let level = cli.log_level.unwrap_or(Level::INFO); - - let subscriber = tracing_subscriber::registry() - .with( - cli.json.then_some( - tracing_subscriber::fmt::Layer::new() - .with_writer(std::io::stderr.with_max_level(level)) - .json(), - ), - ) - .with( - (!cli.json).then_some( - tracing_subscriber::fmt::Layer::new() - .with_writer(std::io::stderr.with_max_level(level)) - .pretty(), - ), - ); - - tracing::subscriber::set_global_default(subscriber).expect("Unable to set global subscriber"); + let _ = tvix_tracing::TracingBuilder::default().enable_progressbar(); match cli.command { Commands::Daemon { @@ -87,12 +63,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { let blob_service = blobservice::from_addr(&blob_service_addr).await?; let directory_service = directoryservice::from_addr(&directory_service_addr).await?; - let build_service = buildservice::from_addr( - &build_service_addr, - Arc::from(blob_service), - Arc::from(directory_service), - ) - .await?; + let build_service = + buildservice::from_addr(&build_service_addr, blob_service, directory_service) + .await?; let listen_address = listen_address .unwrap_or_else(|| "[::]:8000".to_string()) @@ -108,11 +81,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { #[cfg(feature = "tonic-reflection")] { - let reflection_svc = tonic_reflection::server::Builder::configure() - .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) - .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) - .build()?; - router = router.add_service(reflection_svc); + router = router.add_service( + tonic_reflection::server::Builder::configure() + .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) + .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) + .build_v1alpha()?, + ); + router = router.add_service( + tonic_reflection::server::Builder::configure() + .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) + .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) + .build_v1()?, + ); } info!(listen_address=%listen_address, "listening"); diff --git a/tvix/build/src/buildservice/build_request.rs b/tvix/build/src/buildservice/build_request.rs new file mode 100644 index 000000000000..4d53ee55096c --- /dev/null +++ b/tvix/build/src/buildservice/build_request.rs @@ -0,0 +1,131 @@ +use std::collections::{BTreeMap, HashSet}; +use std::path::PathBuf; + +use bytes::Bytes; +use tvix_castore::{Node, PathComponent}; +/// A BuildRequest describes the request of something to be run on the builder. +/// It is distinct from an actual \[Build\] that has already happened, or might be +/// currently ongoing. +/// +/// A BuildRequest can be seen as a more normalized version of a Derivation +/// (parsed from A-Term), "writing out" some of the Nix-internal details about +/// how e.g. environment variables in the build are set. +/// +/// Nix has some impurities when building a Derivation, for example the --cores option +/// ends up as an environment variable in the build, that's not part of the ATerm. +/// +/// As of now, we serialize this into the BuildRequest, so builders can stay dumb. +/// This might change in the future. +/// +/// There's also a big difference when it comes to how inputs are modelled: +/// +/// * Nix only uses store path (strings) to describe the inputs. +/// As store paths can be input-addressed, a certain store path can contain +/// different contents (as not all store paths are binary reproducible). +/// This requires that for every input-addressed input, the builder has access +/// to either the input's deriver (and needs to build it) or else a trusted +/// source for the built input. +/// to upload input-addressed paths, requiring the trusted users concept. +/// * tvix-build records a list of tvix.castore.v1.Node as inputs. +/// These map from the store path base name to their contents, relieving the +/// builder from having to "trust" any input-addressed paths, contrary to Nix. +/// +/// While this approach gives a better hermeticity, it has one downside: +/// A BuildRequest can only be sent once the contents of all its inputs are known. +/// +/// As of now, we're okay to accept this, but it prevents uploading an +/// entirely-non-IFD subgraph of BuildRequests eagerly. +#[derive(Default, Debug, Clone, PartialEq)] +pub struct BuildRequest { + /// The list of all root nodes that should be visible in `inputs_dir` at the + /// time of the build. + /// As all references are content-addressed, no additional signatures are + /// needed to substitute / make these available in the build environment. + pub inputs: BTreeMap<PathComponent, Node>, + /// The command (and its args) executed as the build script. + /// In the case of a Nix derivation, this is usually + /// \["/path/to/some-bash/bin/bash", "-e", "/path/to/some/builder.sh"\]. + pub command_args: Vec<String>, + /// The working dir of the command, relative to the build root. + /// "build", in the case of Nix. + /// This MUST be a clean relative path, without any ".", "..", or superfluous + /// slashes. + pub working_dir: PathBuf, + /// A list of "scratch" paths, relative to the build root. + /// These will be write-able during the build. + /// \[build, nix/store\] in the case of Nix. + /// These MUST be clean relative paths, without any ".", "..", or superfluous + /// slashes, and sorted. + pub scratch_paths: Vec<PathBuf>, + /// The path where the castore input nodes will be located at, + /// "nix/store" in case of Nix. + /// Builds might also write into here (Nix builds do that). + /// This MUST be a clean relative path, without any ".", "..", or superfluous + /// slashes. + pub inputs_dir: PathBuf, + /// The list of output paths the build is expected to produce, + /// relative to the root. + /// If the path is not produced, the build is considered to have failed. + /// These MUST be clean relative paths, without any ".", "..", or superfluous + /// slashes, and sorted. + pub outputs: Vec<PathBuf>, + /// The list of environment variables and their values that should be set + /// inside the build environment. + /// This includes both environment vars set inside the derivation, as well as + /// more "ephemeral" ones like NIX_BUILD_CORES, controlled by the `--cores` + /// CLI option of `nix-build`. + /// For now, we consume this as an option when turning a Derivation into a BuildRequest, + /// similar to how Nix has a `--cores` option. + /// We don't want to bleed these very nix-specific sandbox impl details into + /// (dumber) builders if we don't have to. + /// Environment variables are sorted by their keys. + pub environment_vars: Vec<EnvVar>, + /// A set of constraints that need to be satisfied on a build host before a + /// Build can be started. + pub constraints: HashSet<BuildConstraints>, + /// Additional (small) files and their contents that should be placed into the + /// build environment, but outside inputs_dir. + /// Used for passAsFile and structuredAttrs in Nix. + pub additional_files: Vec<AdditionalFile>, + /// If this is an non-empty list, all paths in `outputs` are scanned for these. + /// For Nix, `refscan_needles` would be populated with the nixbase32 hash parts of + /// every input store path and output store path. The latter is necessary to scan + /// for references between multi-output derivations. + pub refscan_needles: Vec<String>, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct EnvVar { + /// name of the environment variable. Must not contain =. + pub key: String, + pub value: Bytes, +} +/// BuildConstraints represents certain conditions that must be fulfilled +/// inside the build environment to be able to build this. +/// Constraints can be things like required architecture and minimum amount of memory. +/// The required input paths are *not* represented in here, because it +/// wouldn't be hermetic enough - see the comment around inputs too. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum BuildConstraints { + /// The system that's needed to execute the build. + /// Must not be empty. + System(String), + /// The amount of memory required to be available for the build, in bytes. + MinMemory(u64), + /// An absolute path that need to be available in the build + /// environment, like `/dev/kvm`. + /// This is distinct from the castore nodes in inputs. + /// These MUST be clean absolute paths, without any ".", "..", or superfluous + /// slashes, and sorted. + AvailableReadOnlyPath(PathBuf), + /// Whether the build should be able to access the network. + NetworkAccess, + /// Whether to provide a /bin/sh inside the build environment, usually a static bash. + ProvideBinSh, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct AdditionalFile { + pub path: PathBuf, + pub contents: Bytes, +} diff --git a/tvix/build/src/buildservice/dummy.rs b/tvix/build/src/buildservice/dummy.rs index d20444755e73..3368201376ed 100644 --- a/tvix/build/src/buildservice/dummy.rs +++ b/tvix/build/src/buildservice/dummy.rs @@ -2,7 +2,8 @@ use tonic::async_trait; use tracing::instrument; use super::BuildService; -use crate::proto::{Build, BuildRequest}; +use crate::buildservice::BuildRequest; +use crate::proto; #[derive(Default)] pub struct DummyBuildService {} @@ -10,7 +11,7 @@ pub struct DummyBuildService {} #[async_trait] impl BuildService for DummyBuildService { #[instrument(skip(self), ret, err)] - async fn do_build(&self, _request: BuildRequest) -> std::io::Result<Build> { + async fn do_build(&self, _request: BuildRequest) -> std::io::Result<proto::Build> { Err(std::io::Error::new( std::io::ErrorKind::Other, "builds are not supported with DummyBuildService", diff --git a/tvix/build/src/buildservice/from_addr.rs b/tvix/build/src/buildservice/from_addr.rs index cc5403edefff..ba185bb25514 100644 --- a/tvix/build/src/buildservice/from_addr.rs +++ b/tvix/build/src/buildservice/from_addr.rs @@ -2,22 +2,26 @@ use super::{grpc::GRPCBuildService, BuildService, DummyBuildService}; use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService}; use url::Url; +#[cfg(target_os = "linux")] +use super::oci::OCIBuildService; + /// Constructs a new instance of a [BuildService] from an URI. /// /// The following schemes are supported by the following services: /// - `dummy://` ([DummyBuildService]) +/// - `oci://` ([OCIBuildService]) /// - `grpc+*://` ([GRPCBuildService]) /// /// As some of these [BuildService] need to talk to a [BlobService] and /// [DirectoryService], these also need to be passed in. pub async fn from_addr<BS, DS>( uri: &str, - _blob_service: BS, - _directory_service: DS, + blob_service: BS, + directory_service: DS, ) -> std::io::Result<Box<dyn BuildService>> where - BS: AsRef<dyn BlobService> + Send + Sync + Clone + 'static, - DS: AsRef<dyn DirectoryService> + Send + Sync + Clone + 'static, + BS: BlobService + Send + Sync + Clone + 'static, + DS: DirectoryService + Send + Sync + Clone + 'static, { let url = Url::parse(uri) .map_err(|e| std::io::Error::other(format!("unable to parse url: {}", e)))?; @@ -25,6 +29,21 @@ where Ok(match url.scheme() { // dummy doesn't care about parameters. "dummy" => Box::<DummyBuildService>::default(), + #[cfg(target_os = "linux")] + "oci" => { + // oci wants a path in which it creates bundles. + if url.path().is_empty() { + Err(std::io::Error::other("oci needs a bundle dir as path"))? + } + + // TODO: make sandbox shell and rootless_uid_gid + + Box::new(OCIBuildService::new( + url.path().into(), + blob_service, + directory_service, + )) + } scheme => { if scheme.starts_with("grpc+") { let client = crate::proto::build_service_client::BuildServiceClient::new( @@ -47,15 +66,17 @@ where #[cfg(test)] mod tests { - use std::sync::Arc; - use super::from_addr; use rstest::rstest; + use std::sync::{Arc, LazyLock}; + use tempfile::TempDir; use tvix_castore::{ blobservice::{BlobService, MemoryBlobService}, directoryservice::{DirectoryService, MemoryDirectoryService}, }; + static TMPDIR_OCI_1: LazyLock<TempDir> = LazyLock::new(|| TempDir::new().unwrap()); + #[rstest] /// This uses an unsupported scheme. #[case::unsupported_scheme("http://foo.example/test", false)] @@ -73,6 +94,10 @@ mod tests { #[case::grpc_valid_https_host_without_port("grpc+https://localhost", true)] /// Correct scheme to connect to localhost over http, but with additional path, which is invalid. #[case::grpc_invalid_host_and_path("grpc+http://localhost/some-path", false)] + /// This configures OCI, but doesn't specify the bundle path + #[case::oci_missing_bundle_dir("oci://", false)] + /// This configures OCI, specifying the bundle path + #[case::oci_bundle_path(&format!("oci://{}", TMPDIR_OCI_1.path().to_str().unwrap()), true)] #[tokio::test] async fn test_from_addr(#[case] uri_str: &str, #[case] exp_succeed: bool) { let blob_service: Arc<dyn BlobService> = Arc::from(MemoryBlobService::default()); diff --git a/tvix/build/src/buildservice/grpc.rs b/tvix/build/src/buildservice/grpc.rs index 9d22d8397abf..14f06f0ee3e6 100644 --- a/tvix/build/src/buildservice/grpc.rs +++ b/tvix/build/src/buildservice/grpc.rs @@ -1,6 +1,7 @@ use tonic::{async_trait, transport::Channel}; -use crate::proto::{build_service_client::BuildServiceClient, Build, BuildRequest}; +use crate::buildservice::BuildRequest; +use crate::proto::{self, build_service_client::BuildServiceClient}; use super::BuildService; @@ -17,10 +18,10 @@ impl GRPCBuildService { #[async_trait] impl BuildService for GRPCBuildService { - async fn do_build(&self, request: BuildRequest) -> std::io::Result<Build> { + async fn do_build(&self, request: BuildRequest) -> std::io::Result<proto::Build> { let mut client = self.client.clone(); client - .do_build(request) + .do_build(Into::<proto::BuildRequest>::into(request)) .await .map(|resp| resp.into_inner()) .map_err(std::io::Error::other) diff --git a/tvix/build/src/buildservice/mod.rs b/tvix/build/src/buildservice/mod.rs index a61d782919b9..b12db6b95d13 100644 --- a/tvix/build/src/buildservice/mod.rs +++ b/tvix/build/src/buildservice/mod.rs @@ -1,16 +1,21 @@ use tonic::async_trait; -use crate::proto::{Build, BuildRequest}; +use crate::proto; +pub mod build_request; +pub use crate::buildservice::build_request::*; mod dummy; mod from_addr; mod grpc; +#[cfg(target_os = "linux")] +mod oci; + pub use dummy::DummyBuildService; pub use from_addr::from_addr; #[async_trait] pub trait BuildService: Send + Sync { /// TODO: document - async fn do_build(&self, request: BuildRequest) -> std::io::Result<Build>; + async fn do_build(&self, request: BuildRequest) -> std::io::Result<proto::Build>; } diff --git a/tvix/build/src/buildservice/oci.rs b/tvix/build/src/buildservice/oci.rs new file mode 100644 index 000000000000..52efede6597b --- /dev/null +++ b/tvix/build/src/buildservice/oci.rs @@ -0,0 +1,266 @@ +use anyhow::Context; +use bstr::BStr; +use oci_spec::runtime::{LinuxIdMapping, LinuxIdMappingBuilder}; +use tokio::process::{Child, Command}; +use tonic::async_trait; +use tracing::{debug, instrument, warn, Span}; +use tvix_castore::{ + blobservice::BlobService, + directoryservice::DirectoryService, + fs::fuse::FuseDaemon, + import::fs::ingest_path, + refscan::{ReferencePattern, ReferenceScanner}, +}; +use uuid::Uuid; + +use crate::buildservice::BuildRequest; +use crate::{ + oci::{get_host_output_paths, make_bundle, make_spec}, + proto::{self, build::OutputNeedles}, +}; +use std::{ffi::OsStr, path::PathBuf, process::Stdio}; + +use super::BuildService; + +const SANDBOX_SHELL: &str = env!("TVIX_BUILD_SANDBOX_SHELL"); +const MAX_CONCURRENT_BUILDS: usize = 2; // TODO: make configurable + +pub struct OCIBuildService<BS, DS> { + /// Root path in which all bundles are created in + bundle_root: PathBuf, + + /// uid mappings to set up for the workloads + uid_mappings: Vec<LinuxIdMapping>, + /// uid mappings to set up for the workloads + gid_mappings: Vec<LinuxIdMapping>, + + /// Handle to a [BlobService], used by filesystems spawned during builds. + blob_service: BS, + /// Handle to a [DirectoryService], used by filesystems spawned during builds. + directory_service: DS, + + // semaphore to track number of concurrently running builds. + // this is necessary, as otherwise we very quickly run out of open file handles. + concurrent_builds: tokio::sync::Semaphore, +} + +impl<BS, DS> OCIBuildService<BS, DS> { + pub fn new(bundle_root: PathBuf, blob_service: BS, directory_service: DS) -> Self { + // We map root inside the container to the uid/gid this is running at, + // and allocate one for uid 1000 into the container from the range we + // got in /etc/sub{u,g}id. + // TODO: actually read uid, and /etc/subuid. Maybe only when we try to build? + // FUTUREWORK: use different uids? + Self { + bundle_root, + blob_service, + directory_service, + uid_mappings: vec![ + LinuxIdMappingBuilder::default() + .host_id(1000_u32) + .container_id(0_u32) + .size(1_u32) + .build() + .unwrap(), + LinuxIdMappingBuilder::default() + .host_id(100000_u32) + .container_id(1000_u32) + .size(1_u32) + .build() + .unwrap(), + ], + gid_mappings: vec![ + LinuxIdMappingBuilder::default() + .host_id(100_u32) + .container_id(0_u32) + .size(1_u32) + .build() + .unwrap(), + LinuxIdMappingBuilder::default() + .host_id(100000_u32) + .container_id(100_u32) + .size(1_u32) + .build() + .unwrap(), + ], + concurrent_builds: tokio::sync::Semaphore::new(MAX_CONCURRENT_BUILDS), + } + } +} + +#[async_trait] +impl<BS, DS> BuildService for OCIBuildService<BS, DS> +where + BS: BlobService + Clone + 'static, + DS: DirectoryService + Clone + 'static, +{ + #[instrument(skip_all, err)] + async fn do_build(&self, request: BuildRequest) -> std::io::Result<proto::Build> { + let _permit = self.concurrent_builds.acquire().await.unwrap(); + + let bundle_name = Uuid::new_v4(); + let bundle_path = self.bundle_root.join(bundle_name.to_string()); + + let span = Span::current(); + span.record("bundle_name", bundle_name.to_string()); + + let mut runtime_spec = make_spec(&request, true, SANDBOX_SHELL) + .context("failed to create spec") + .map_err(std::io::Error::other)?; + + let mut linux = runtime_spec.linux().clone().unwrap(); + + // edit the spec, we need to setup uid/gid mappings. + linux.set_uid_mappings(Some(self.uid_mappings.clone())); + linux.set_gid_mappings(Some(self.gid_mappings.clone())); + + runtime_spec.set_linux(Some(linux)); + + make_bundle(&request, &runtime_spec, &bundle_path) + .context("failed to produce bundle") + .map_err(std::io::Error::other)?; + + // pre-calculate the locations we want to later ingest, in the order of + // the original outputs. + // If we can't find calculate that path, don't start the build in first place. + let host_output_paths = get_host_output_paths(&request, &bundle_path) + .context("failed to calculate host output paths") + .map_err(std::io::Error::other)?; + + // assemble a BTreeMap of Nodes to pass into TvixStoreFs. + let patterns = ReferencePattern::new(request.refscan_needles.clone()); + // NOTE: impl Drop for FuseDaemon unmounts, so if the call is cancelled, umount. + let _fuse_daemon = tokio::task::spawn_blocking({ + let blob_service = self.blob_service.clone(); + let directory_service = self.directory_service.clone(); + + let dest = bundle_path.join("inputs"); + + let root_nodes = Box::new(request.inputs.clone()); + move || { + let fs = tvix_castore::fs::TvixStoreFs::new( + blob_service, + directory_service, + root_nodes, + true, + false, + ); + // mount the filesystem and wait for it to be unmounted. + // FUTUREWORK: make fuse daemon threads configurable? + FuseDaemon::new(fs, dest, 4, true).context("failed to start fuse daemon") + } + }) + .await? + .context("mounting") + .map_err(std::io::Error::other)?; + + debug!(bundle.path=?bundle_path, bundle.name=%bundle_name, "about to spawn bundle"); + + // start the bundle as another process. + let child = spawn_bundle(bundle_path, &bundle_name.to_string())?; + + // wait for the process to exit + // FUTUREWORK: change the trait to allow reporting progress / logs… + let child_output = child + .wait_with_output() + .await + .context("failed to run process") + .map_err(std::io::Error::other)?; + + // Check the exit code + if !child_output.status.success() { + let stdout = BStr::new(&child_output.stdout); + let stderr = BStr::new(&child_output.stderr); + + warn!(stdout=%stdout, stderr=%stderr, exit_code=%child_output.status, "build failed"); + + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + "nonzero exit code".to_string(), + )); + } + + // Ingest build outputs into the castore. + // We use try_join_all here. No need to spawn new tasks, as this is + // mostly IO bound. + let (outputs, outputs_needles) = futures::future::try_join_all( + host_output_paths.into_iter().enumerate().map(|(i, p)| { + let output_path = request.outputs[i].clone(); + let patterns = patterns.clone(); + async move { + debug!(host.path=?p, output.path=?output_path, "ingesting path"); + + let scanner = ReferenceScanner::new(patterns); + let output_node = ingest_path( + self.blob_service.clone(), + &self.directory_service, + p, + Some(&scanner), + ) + .await + .map_err(|e| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("Unable to ingest output: {}", e), + ) + })?; + + let needles = OutputNeedles { + needles: scanner + .matches() + .into_iter() + .enumerate() + .filter(|(_, val)| *val) + .map(|(idx, _)| idx as u64) + .collect(), + }; + + Ok::<_, std::io::Error>(( + tvix_castore::proto::Node::from_name_and_node( + output_path + .file_name() + .and_then(|s| s.to_str()) + .map(|s| s.to_string()) + .unwrap_or("".into()) + .into(), + output_node, + ), + needles, + )) + } + }), + ) + .await? + .into_iter() + .unzip(); + + Ok(proto::Build { + build_request: Some(request.into()), + outputs, + outputs_needles, + }) + } +} + +/// Spawns runc with the bundle at bundle_path. +/// On success, returns the child. +#[instrument(err)] +fn spawn_bundle( + bundle_path: impl AsRef<OsStr> + std::fmt::Debug, + bundle_name: &str, +) -> std::io::Result<Child> { + let mut command = Command::new("runc"); + + command + .args(&[ + "run".into(), + "--bundle".into(), + bundle_path.as_ref().to_os_string(), + bundle_name.into(), + ]) + .stderr(Stdio::piped()) + .stdout(Stdio::piped()) + .stdin(Stdio::null()); + + command.spawn() +} diff --git a/tvix/build/src/lib.rs b/tvix/build/src/lib.rs index b173657e431c..86c1862d629e 100644 --- a/tvix/build/src/lib.rs +++ b/tvix/build/src/lib.rs @@ -1,2 +1,4 @@ pub mod buildservice; +#[cfg(target_os = "linux")] +mod oci; pub mod proto; diff --git a/tvix/build/src/oci/bundle.rs b/tvix/build/src/oci/bundle.rs new file mode 100644 index 000000000000..52789362a58d --- /dev/null +++ b/tvix/build/src/oci/bundle.rs @@ -0,0 +1,144 @@ +//! Module to create an OCI runtime bundle for a given [BuildRequest]. +use std::{ + fs, + path::{Path, PathBuf}, +}; + +use super::scratch_name; +use crate::buildservice::BuildRequest; +use anyhow::{bail, Context}; +use tracing::{debug, instrument}; + +/// Produce an OCI bundle in a given path. +/// Check [make_spec] for a description about the paths produced. +#[instrument(err)] +pub(crate) fn make_bundle<'a>( + request: &BuildRequest, + runtime_spec: &oci_spec::runtime::Spec, + path: &Path, +) -> anyhow::Result<()> { + fs::create_dir_all(path).context("failed to create bundle path")?; + + let spec_json = serde_json::to_string(runtime_spec).context("failed to render spec to json")?; + fs::write(path.join("config.json"), spec_json).context("failed to write config.json")?; + + fs::create_dir_all(path.join("inputs")).context("failed to create inputs dir")?; + + let root_path = path.join("root"); + + fs::create_dir_all(&root_path).context("failed to create root path dir")?; + fs::create_dir_all(root_path.join("etc")).context("failed to create root/etc dir")?; + + // TODO: populate /etc/{group,passwd}. It's a mess? + + let scratch_root = path.join("scratch"); + fs::create_dir_all(&scratch_root).context("failed to create scratch/ dir")?; + + // for each scratch path, calculate its name inside scratch, and ensure the + // directory exists. + for p in request.scratch_paths.iter() { + let scratch_path = scratch_root.join(scratch_name(p)); + debug!(scratch_path=?scratch_path, path=?p, "about to create scratch dir"); + fs::create_dir_all(scratch_path).context("Unable to create scratch dir")?; + } + + Ok(()) +} + +/// Determine the path of all outputs specified in a [BuildRequest] +/// as seen from the host, for post-build ingestion. +/// This lookup needs to take scratch paths into consideration, as the build +/// root is not writable on its own. +/// If a path can't be determined, an error is returned. +pub(crate) fn get_host_output_paths( + request: &BuildRequest, + bundle_path: &Path, +) -> anyhow::Result<Vec<PathBuf>> { + let scratch_root = bundle_path.join("scratch"); + + let mut host_output_paths: Vec<PathBuf> = Vec::with_capacity(request.outputs.len()); + + for output_path in request.outputs.iter() { + // calculate the location of the path. + if let Some((mp, relpath)) = find_path_in_scratchs(output_path, &request.scratch_paths) { + host_output_paths.push(scratch_root.join(scratch_name(mp)).join(relpath)); + } else { + bail!("unable to find path {output_path:?}"); + } + } + + Ok(host_output_paths) +} + +/// For a given list of mountpoints (sorted) and a search_path, find the +/// specific mountpoint parenting that search_path and return it, as well as the +/// relative path from there to the search_path. +/// mountpoints must be sorted, so we can iterate over the list from the back +/// and match on the prefix. +fn find_path_in_scratchs<'a, 'b, I>( + search_path: &'a Path, + mountpoints: I, +) -> Option<(&'b Path, &'a Path)> +where + I: IntoIterator<Item = &'b PathBuf>, + I::IntoIter: DoubleEndedIterator, +{ + mountpoints + .into_iter() + .rev() + .find_map(|mp| Some((mp.as_path(), search_path.strip_prefix(mp).ok()?))) +} + +#[cfg(test)] +mod tests { + use std::path::{Path, PathBuf}; + + use rstest::rstest; + + use crate::{buildservice::BuildRequest, oci::scratch_name}; + + use super::{find_path_in_scratchs, get_host_output_paths}; + + #[rstest] + #[case::simple("nix/store/aaaa", &["nix/store".into()], Some(("nix/store", "aaaa")))] + #[case::prefix_no_sep("nix/store/aaaa", &["nix/sto".into()], None)] + #[case::not_found("nix/store/aaaa", &["build".into()], None)] + fn test_test_find_path_in_scratchs( + #[case] search_path: &str, + #[case] mountpoints: &[String], + #[case] expected: Option<(&str, &str)>, + ) { + let expected = expected.map(|e| (Path::new(e.0), Path::new(e.1))); + assert_eq!( + find_path_in_scratchs( + Path::new(search_path), + mountpoints + .iter() + .map(PathBuf::from) + .collect::<Vec<_>>() + .as_slice() + ), + expected + ); + } + + #[test] + fn test_get_host_output_paths_simple() { + let request = BuildRequest { + outputs: vec!["nix/store/fhaj6gmwns62s6ypkcldbaj2ybvkhx3p-foo".into()], + scratch_paths: vec!["build".into(), "nix/store".into()], + ..Default::default() + }; + + let paths = + get_host_output_paths(&request, Path::new("bundle-root")).expect("must succeed"); + + let mut expected_path = PathBuf::new(); + expected_path.push("bundle-root"); + expected_path.push("scratch"); + expected_path.push(scratch_name(Path::new("nix/store"))); + expected_path.push("fhaj6gmwns62s6ypkcldbaj2ybvkhx3p-foo"); + + assert_eq!(vec![expected_path], paths) + } +} diff --git a/tvix/build/src/oci/mod.rs b/tvix/build/src/oci/mod.rs new file mode 100644 index 000000000000..a2400c4a6eba --- /dev/null +++ b/tvix/build/src/oci/mod.rs @@ -0,0 +1,16 @@ +mod bundle; +mod spec; + +pub(crate) use bundle::get_host_output_paths; +pub(crate) use bundle::make_bundle; +pub(crate) use spec::make_spec; + +use std::path::Path; + +/// For a given scratch path, return the scratch_name that's allocated. +// We currently use use lower hex encoding of the b3 digest of the scratch +// path, so we don't need to globally allocate and pass down some uuids. +pub(crate) fn scratch_name(scratch_path: &Path) -> String { + data_encoding::BASE32 + .encode(blake3::hash(scratch_path.as_os_str().as_encoded_bytes()).as_bytes()) +} diff --git a/tvix/build/src/oci/spec.rs b/tvix/build/src/oci/spec.rs new file mode 100644 index 000000000000..e3b6172def8a --- /dev/null +++ b/tvix/build/src/oci/spec.rs @@ -0,0 +1,307 @@ +//! Module to create a OCI runtime spec for a given [BuildRequest]. +use crate::buildservice::{BuildConstraints, BuildRequest}; +use oci_spec::{ + runtime::{Capability, LinuxNamespace, LinuxNamespaceBuilder, LinuxNamespaceType}, + OciSpecError, +}; +use std::{collections::HashSet, path::Path}; + +use super::scratch_name; + +/// For a given [BuildRequest], return an OCI runtime spec. +/// +/// While there's no IO occuring in this function, the generated spec contains +/// path references relative to the "bundle location". +/// Due to overlayfs requiring its layers to be absolute paths, we also need a +/// [bundle_dir] parameter, pointing to the location of the bundle dir itself. +/// +/// The paths used in the spec are the following (relative to a "bundle root"): +/// +/// - `inputs`, a directory where the castore nodes specified the build request +/// inputs are supposed to be populated. +/// - `outputs`, a directory where all writes to the store_dir during the build +/// are directed to. +/// - `root`, a minimal skeleton of files that'll be present at /. +/// - `scratch`, a directory containing other directories which will be +/// bind-mounted read-write into the container and used as scratch space +/// during the build. +/// No assumptions should be made about what's inside this directory. +/// +/// Generating these paths, and populating contents, like a skeleton root +/// is up to another function, this function doesn't do filesystem IO. +pub(crate) fn make_spec( + request: &BuildRequest, + rootless: bool, + sandbox_shell: &str, +) -> Result<oci_spec::runtime::Spec, oci_spec::OciSpecError> { + let allow_network = request + .constraints + .contains(&BuildConstraints::NetworkAccess); + + // Assemble ro_host_mounts. Start with constraints.available_ro_paths. + let mut ro_host_mounts: Vec<_> = request + .constraints + .iter() + .filter_map(|constraint| match constraint { + BuildConstraints::AvailableReadOnlyPath(path) => Some((path.as_path(), path.as_path())), + _ => None, + }) + .collect(); + + // If provide_bin_sh is set, mount sandbox_shell to /bin/sh + if request + .constraints + .contains(&BuildConstraints::ProvideBinSh) + { + ro_host_mounts.push((Path::new(sandbox_shell), Path::new("/bin/sh"))) + } + + oci_spec::runtime::SpecBuilder::default() + .process(configure_process( + &request.command_args, + &request.working_dir, + request + .environment_vars + .iter() + .map(|e| { + ( + e.key.as_str(), + // TODO: decide what to do with non-bytes env values + String::from_utf8(e.value.to_vec()).expect("invalid string in env"), + ) + }) + .collect::<Vec<_>>(), + rootless, + )?) + .linux(configure_linux(allow_network, rootless)?) + .root( + oci_spec::runtime::RootBuilder::default() + .path("root") + .readonly(true) + .build()?, + ) + .hostname("localhost") + .mounts(configure_mounts( + rootless, + allow_network, + request.scratch_paths.iter().map(|e| e.as_path()), + request.inputs.iter(), + &request.inputs_dir, + ro_host_mounts, + )?) + .build() +} + +/// Return the Process part of the OCI Runtime spec. +/// This configures the command, it's working dir, env and terminal setup. +/// It also takes care of setting rlimits and capabilities. +/// Capabilities are a bit more complicated in case rootless building is requested. +fn configure_process<'a>( + command_args: &[String], + cwd: &Path, + env: impl IntoIterator<Item = (&'a str, String)>, + rootless: bool, +) -> Result<oci_spec::runtime::Process, oci_spec::OciSpecError> { + let spec_builder = oci_spec::runtime::ProcessBuilder::default() + .args(command_args) + .env( + env.into_iter() + .map(|(k, v)| format!("{}={}", k, v)) + .collect::<Vec<_>>(), + ) + .terminal(true) + .user( + oci_spec::runtime::UserBuilder::default() + .uid(1000u32) + .gid(100u32) + .build()?, + ) + .cwd(Path::new("/").join(cwd)) // relative to the bundle root, but at least runc wants it to also be absolute. + .capabilities({ + let caps: HashSet<Capability> = if !rootless { + HashSet::from([Capability::AuditWrite, Capability::Kill]) + } else { + HashSet::from([ + Capability::AuditWrite, + Capability::Chown, + Capability::DacOverride, + Capability::Fowner, + Capability::Fsetid, + Capability::Kill, + Capability::Mknod, + Capability::NetBindService, + Capability::NetRaw, + Capability::Setfcap, + Capability::Setgid, + Capability::Setpcap, + Capability::Setuid, + Capability::SysChroot, + ]) + }; + + oci_spec::runtime::LinuxCapabilitiesBuilder::default() + .bounding(caps.clone()) + .effective(caps.clone()) + .inheritable(caps.clone()) + .permitted(caps.clone()) + .ambient(caps) + .build()? + }) + .rlimits([oci_spec::runtime::PosixRlimitBuilder::default() + .typ(oci_spec::runtime::PosixRlimitType::RlimitNofile) + .hard(1024_u64) + .soft(1024_u64) + .build()?]) + .no_new_privileges(true); + + spec_builder.build() +} + +/// Return the Linux part of the OCI Runtime spec. +/// This configures various namespaces, masked and read-only paths. +fn configure_linux( + allow_network: bool, + rootless: bool, +) -> Result<oci_spec::runtime::Linux, OciSpecError> { + let mut linux = oci_spec::runtime::Linux::default(); + + // explicitly set namespaces, depending on allow_network. + linux.set_namespaces(Some({ + let mut namespace_types = vec![ + LinuxNamespaceType::Pid, + LinuxNamespaceType::Ipc, + LinuxNamespaceType::Uts, + LinuxNamespaceType::Mount, + LinuxNamespaceType::Cgroup, + ]; + if !allow_network { + namespace_types.push(LinuxNamespaceType::Network) + } + if rootless { + namespace_types.push(LinuxNamespaceType::User) + } + + namespace_types + .into_iter() + .map(|e| LinuxNamespaceBuilder::default().typ(e).build()) + .collect::<Result<Vec<LinuxNamespace>, _>>()? + })); + + linux.set_masked_paths(Some( + [ + "/proc/kcore", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/sys/firmware", + ] + .into_iter() + .map(|e| e.to_string()) + .collect::<Vec<_>>(), + )); + + linux.set_readonly_paths(Some( + [ + "/proc/asound", + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger", + ] + .into_iter() + .map(|e| e.to_string()) + .collect::<Vec<_>>(), + )); + + Ok(linux) +} + +/// Return the Mounts part of the OCI Runtime spec. +/// It first sets up the standard mounts, then scratch paths, bind mounts for +/// all inputs, and finally read-only paths from the hosts. +fn configure_mounts<'a>( + rootless: bool, + allow_network: bool, + scratch_paths: impl IntoIterator<Item = &'a Path>, + inputs: impl Iterator<Item = (&'a tvix_castore::PathComponent, &'a tvix_castore::Node)>, + + inputs_dir: &Path, + ro_host_mounts: impl IntoIterator<Item = (&'a Path, &'a Path)>, +) -> Result<Vec<oci_spec::runtime::Mount>, oci_spec::OciSpecError> { + let mut mounts: Vec<_> = if rootless { + oci_spec::runtime::get_rootless_mounts() + } else { + oci_spec::runtime::get_default_mounts() + }; + + mounts.push(configure_mount( + Path::new("tmpfs"), + Path::new("/tmp"), + "tmpfs", + &["nosuid", "noatime", "mode=700"], + )?); + + // For each scratch path, create a bind mount entry. + let scratch_root = Path::new("scratch"); // relative path + for scratch_path in scratch_paths.into_iter() { + let src = scratch_root.join(scratch_name(scratch_path)); + mounts.push(configure_mount( + &src, + &Path::new("/").join(scratch_path), + "none", + &["rbind", "rw"], + )?); + } + + // For each input, create a bind mount from inputs/$name into $inputs_dir/$name. + for (input_name, _input) in inputs { + let input_name = std::str::from_utf8(input_name.as_ref()).expect("invalid input name"); + mounts.push(configure_mount( + &Path::new("inputs").join(input_name), + &Path::new("/").join(inputs_dir).join(input_name), + "none", + &[ + "rbind", "ro", + // "nosuid" is required, otherwise mounting will just fail with + // a generic permission error. + // See https://github.com/wllenyj/containerd/commit/42a386c8164bef16d59590c61ab00806f854d8fd + "nosuid", "nodev", + ], + )?); + } + + // Process ro_host_mounts + for (src, dst) in ro_host_mounts.into_iter() { + mounts.push(configure_mount(src, dst, "none", &["rbind", "ro"])?); + } + + // In case network is enabled, also mount in /etc/{resolv.conf,services,hosts} + if allow_network { + for p in [ + Path::new("/etc/resolv.conf"), + Path::new("/etc/services"), + Path::new("/etc/hosts"), + ] { + mounts.push(configure_mount(p, p, "none", &["rbind", "ro"])?); + } + } + + Ok(mounts) +} + +/// Helper function to produce a mount. +fn configure_mount( + source: &Path, + destination: &Path, + typ: &str, + options: &[&str], +) -> Result<oci_spec::runtime::Mount, oci_spec::OciSpecError> { + oci_spec::runtime::MountBuilder::default() + .destination(destination) + .typ(typ.to_string()) + .source(source) + .options(options.iter().map(|e| e.to_string()).collect::<Vec<_>>()) + .build() +} diff --git a/tvix/build/src/proto/grpc_buildservice_wrapper.rs b/tvix/build/src/proto/grpc_buildservice_wrapper.rs index 024f075de9ad..8a2d36ac569f 100644 --- a/tvix/build/src/proto/grpc_buildservice_wrapper.rs +++ b/tvix/build/src/proto/grpc_buildservice_wrapper.rs @@ -27,7 +27,9 @@ where &self, request: tonic::Request<BuildRequest>, ) -> Result<tonic::Response<Build>, tonic::Status> { - match self.inner.do_build(request.into_inner()).await { + let request = TryInto::<crate::buildservice::BuildRequest>::try_into(request.into_inner()) + .map_err(|err| tonic::Status::new(tonic::Code::InvalidArgument, err.to_string()))?; + match self.inner.do_build(request).await { Ok(resp) => Ok(tonic::Response::new(resp)), Err(e) => Err(tonic::Status::internal(e.to_string())), } diff --git a/tvix/build/src/proto/mod.rs b/tvix/build/src/proto/mod.rs index e359b5b5b70e..be757bb56272 100644 --- a/tvix/build/src/proto/mod.rs +++ b/tvix/build/src/proto/mod.rs @@ -1,7 +1,8 @@ +use std::collections::{BTreeMap, HashSet}; use std::path::{Path, PathBuf}; use itertools::Itertools; -use tvix_castore::proto::{NamedNode, ValidateNodeError}; +use tvix_castore::{DirectoryError, Node, PathComponent}; mod grpc_buildservice_wrapper; @@ -19,7 +20,7 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("tvix #[derive(Debug, thiserror::Error)] pub enum ValidateBuildRequestError { #[error("invalid input node at position {0}: {1}")] - InvalidInputNode(usize, ValidateNodeError), + InvalidInputNode(usize, DirectoryError), #[error("input nodes are not sorted by name")] InputNodesNotSorted, @@ -117,86 +118,149 @@ where data.tuple_windows().all(|(a, b)| a <= b) } -impl BuildRequest { - /// Ensures the build request is valid. - /// This means, all input nodes need to be valid, paths in lists need to be sorted, - /// and all restrictions around paths themselves (relative, clean, …) need - // to be fulfilled. - pub fn validate(&self) -> Result<(), ValidateBuildRequestError> { - // validate all input nodes - for (i, n) in self.inputs.iter().enumerate() { - // ensure the input node itself is valid - n.validate() - .map_err(|e| ValidateBuildRequestError::InvalidInputNode(i, e))?; - } +fn path_to_string(path: &Path) -> String { + path.to_str() + .expect("Tvix Bug: unable to convert Path to String") + .to_string() +} - // now we can look at the names, and make sure they're sorted. - if !is_sorted( - self.inputs +impl From<crate::buildservice::BuildRequest> for BuildRequest { + fn from(value: crate::buildservice::BuildRequest) -> Self { + let constraints = if value.constraints.is_empty() { + None + } else { + let mut constraints = build_request::BuildConstraints::default(); + for constraint in value.constraints { + use crate::buildservice::BuildConstraints; + match constraint { + BuildConstraints::System(system) => constraints.system = system, + BuildConstraints::MinMemory(min_memory) => constraints.min_memory = min_memory, + BuildConstraints::AvailableReadOnlyPath(path) => { + constraints.available_ro_paths.push(path_to_string(&path)) + } + BuildConstraints::ProvideBinSh => constraints.provide_bin_sh = true, + BuildConstraints::NetworkAccess => constraints.network_access = true, + } + } + Some(constraints) + }; + Self { + inputs: value + .inputs + .into_iter() + .map(|(name, node)| { + tvix_castore::proto::Node::from_name_and_node(name.into(), node) + }) + .collect(), + command_args: value.command_args, + working_dir: path_to_string(&value.working_dir), + scratch_paths: value + .scratch_paths .iter() - .map(|e| e.node.as_ref().unwrap().get_name()), - ) { - Err(ValidateBuildRequestError::InputNodesNotSorted)? + .map(|p| path_to_string(p)) + .collect(), + inputs_dir: path_to_string(&value.inputs_dir), + outputs: value.outputs.iter().map(|p| path_to_string(p)).collect(), + environment_vars: value.environment_vars.into_iter().map(Into::into).collect(), + constraints, + additional_files: value.additional_files.into_iter().map(Into::into).collect(), + refscan_needles: value.refscan_needles, + } + } +} + +impl TryFrom<BuildRequest> for crate::buildservice::BuildRequest { + type Error = ValidateBuildRequestError; + fn try_from(value: BuildRequest) -> Result<Self, Self::Error> { + // validate input names. Make sure they're sorted + + let mut last_name: bytes::Bytes = "".into(); + let mut inputs: BTreeMap<PathComponent, Node> = BTreeMap::new(); + for (i, node) in value.inputs.iter().enumerate() { + let (name, node) = node + .clone() + .try_into_name_and_node() + .map_err(|e| ValidateBuildRequestError::InvalidInputNode(i, e))?; + + if name.as_ref() <= last_name.as_ref() { + return Err(ValidateBuildRequestError::InputNodesNotSorted); + } else { + inputs.insert(name.clone(), node); + last_name = name.into(); + } } // validate working_dir - if !is_clean_relative_path(&self.working_dir) { + if !is_clean_relative_path(&value.working_dir) { Err(ValidateBuildRequestError::InvalidWorkingDir)?; } // validate scratch paths - for (i, p) in self.scratch_paths.iter().enumerate() { + for (i, p) in value.scratch_paths.iter().enumerate() { if !is_clean_relative_path(p) { Err(ValidateBuildRequestError::InvalidScratchPath(i))? } } - if !is_sorted(self.scratch_paths.iter().map(|e| e.as_bytes())) { + if !is_sorted(value.scratch_paths.iter().map(|e| e.as_bytes())) { Err(ValidateBuildRequestError::ScratchPathsNotSorted)?; } // validate inputs_dir - if !is_clean_relative_path(&self.inputs_dir) { + if !is_clean_relative_path(&value.inputs_dir) { Err(ValidateBuildRequestError::InvalidInputsDir)?; } // validate outputs - for (i, p) in self.outputs.iter().enumerate() { + for (i, p) in value.outputs.iter().enumerate() { if !is_clean_relative_path(p) { Err(ValidateBuildRequestError::InvalidOutputPath(i))? } } - if !is_sorted(self.outputs.iter().map(|e| e.as_bytes())) { + if !is_sorted(value.outputs.iter().map(|e| e.as_bytes())) { Err(ValidateBuildRequestError::OutputsNotSorted)?; } // validate environment_vars. - for (i, e) in self.environment_vars.iter().enumerate() { + for (i, e) in value.environment_vars.iter().enumerate() { if e.key.is_empty() || e.key.contains('=') { Err(ValidateBuildRequestError::InvalidEnvVar(i))? } } - if !is_sorted(self.environment_vars.iter().map(|e| e.key.as_bytes())) { + if !is_sorted(value.environment_vars.iter().map(|e| e.key.as_bytes())) { Err(ValidateBuildRequestError::EnvVarNotSorted)?; } // validate build constraints - if let Some(constraints) = self.constraints.as_ref() { - constraints - .validate() - .map_err(ValidateBuildRequestError::InvalidBuildConstraints)?; - } + let constraints = value + .constraints + .map_or(Ok(HashSet::new()), |constraints| { + constraints + .try_into() + .map_err(ValidateBuildRequestError::InvalidBuildConstraints) + })?; // validate additional_files - for (i, additional_file) in self.additional_files.iter().enumerate() { + for (i, additional_file) in value.additional_files.iter().enumerate() { if !is_clean_relative_path(&additional_file.path) { Err(ValidateBuildRequestError::InvalidAdditionalFilePath(i))? } } - if !is_sorted(self.additional_files.iter().map(|e| e.path.as_bytes())) { + if !is_sorted(value.additional_files.iter().map(|e| e.path.as_bytes())) { Err(ValidateBuildRequestError::AdditionalFilesNotSorted)?; } - Ok(()) + Ok(Self { + inputs, + command_args: value.command_args, + working_dir: PathBuf::from(value.working_dir), + scratch_paths: value.scratch_paths.iter().map(PathBuf::from).collect(), + inputs_dir: PathBuf::from(value.inputs_dir), + outputs: value.outputs.iter().map(PathBuf::from).collect(), + environment_vars: value.environment_vars.into_iter().map(Into::into).collect(), + constraints, + additional_files: value.additional_files.into_iter().map(Into::into).collect(), + refscan_needles: value.refscan_needles, + }) } } @@ -214,27 +278,90 @@ pub enum ValidateBuildConstraintsError { AvailableRoPathsNotSorted, } -impl build_request::BuildConstraints { - pub fn validate(&self) -> Result<(), ValidateBuildConstraintsError> { +impl From<build_request::EnvVar> for crate::buildservice::EnvVar { + fn from(value: build_request::EnvVar) -> Self { + Self { + key: value.key, + value: value.value, + } + } +} + +impl From<crate::buildservice::EnvVar> for build_request::EnvVar { + fn from(value: crate::buildservice::EnvVar) -> Self { + Self { + key: value.key, + value: value.value, + } + } +} + +impl From<build_request::AdditionalFile> for crate::buildservice::AdditionalFile { + fn from(value: build_request::AdditionalFile) -> Self { + Self { + path: PathBuf::from(value.path), + contents: value.contents, + } + } +} + +impl From<crate::buildservice::AdditionalFile> for build_request::AdditionalFile { + fn from(value: crate::buildservice::AdditionalFile) -> Self { + Self { + path: value + .path + .to_str() + .expect("Tvix bug: expected a valid path") + .to_string(), + contents: value.contents, + } + } +} + +impl TryFrom<build_request::BuildConstraints> for HashSet<crate::buildservice::BuildConstraints> { + type Error = ValidateBuildConstraintsError; + fn try_from(value: build_request::BuildConstraints) -> Result<Self, Self::Error> { + use crate::buildservice::BuildConstraints; + // validate system - if self.system.is_empty() { + if value.system.is_empty() { Err(ValidateBuildConstraintsError::InvalidSystem)?; } + + let mut build_constraints = HashSet::from([ + BuildConstraints::System(value.system), + BuildConstraints::MinMemory(value.min_memory), + ]); + // validate available_ro_paths - for (i, p) in self.available_ro_paths.iter().enumerate() { + for (i, p) in value.available_ro_paths.iter().enumerate() { if !is_clean_absolute_path(p) { Err(ValidateBuildConstraintsError::InvalidAvailableRoPaths(i))? + } else { + build_constraints.insert(BuildConstraints::AvailableReadOnlyPath(PathBuf::from(p))); } } - if !is_sorted(self.available_ro_paths.iter().map(|e| e.as_bytes())) { + if !is_sorted(value.available_ro_paths.iter().map(|e| e.as_bytes())) { Err(ValidateBuildConstraintsError::AvailableRoPathsNotSorted)?; } - Ok(()) + if value.network_access { + build_constraints.insert(BuildConstraints::NetworkAccess); + } + if value.provide_bin_sh { + build_constraints.insert(BuildConstraints::ProvideBinSh); + } + + Ok(build_constraints) } } #[cfg(test)] +// TODO: add testcases for constraints special cases. The default cases in the protos +// should result in the constraints not being added. For example min_memory 0 can be omitted. +// Also interesting testcases are "merging semantics". MimMemory(1) and MinMemory(100) will +// result in mim_memory 100, multiple AvailableReadOnlyPaths need to be merged. Contradicting +// system constraints need to fail somewhere (maybe an assertion, as only buggy code can construct it) mod tests { use super::{is_clean_path, is_clean_relative_path}; use rstest::rstest; diff --git a/tvix/castore-go/castore.pb.go b/tvix/castore-go/castore.pb.go index 464f1d4a4183..9395a392be2e 100644 --- a/tvix/castore-go/castore.pb.go +++ b/tvix/castore-go/castore.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.35.1 // protoc (unknown) // source: tvix/castore/protos/castore.proto @@ -45,11 +45,9 @@ type Directory struct { func (x *Directory) Reset() { *x = Directory{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_castore_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_castore_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Directory) String() string { @@ -60,7 +58,7 @@ func (*Directory) ProtoMessage() {} func (x *Directory) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_castore_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -121,11 +119,9 @@ type DirectoryNode struct { func (x *DirectoryNode) Reset() { *x = DirectoryNode{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_castore_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_castore_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DirectoryNode) String() string { @@ -136,7 +132,7 @@ func (*DirectoryNode) ProtoMessage() {} func (x *DirectoryNode) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_castore_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -190,11 +186,9 @@ type FileNode struct { func (x *FileNode) Reset() { *x = FileNode{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_castore_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_castore_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FileNode) String() string { @@ -205,7 +199,7 @@ func (*FileNode) ProtoMessage() {} func (x *FileNode) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_castore_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -262,11 +256,9 @@ type SymlinkNode struct { func (x *SymlinkNode) Reset() { *x = SymlinkNode{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_castore_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_castore_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SymlinkNode) String() string { @@ -277,7 +269,7 @@ func (*SymlinkNode) ProtoMessage() {} func (x *SymlinkNode) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_castore_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -322,11 +314,9 @@ type Node struct { func (x *Node) Reset() { *x = Node{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_castore_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_castore_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Node) String() string { @@ -337,7 +327,7 @@ func (*Node) ProtoMessage() {} func (x *Node) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_castore_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -466,7 +456,7 @@ func file_tvix_castore_protos_castore_proto_rawDescGZIP() []byte { } var file_tvix_castore_protos_castore_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_tvix_castore_protos_castore_proto_goTypes = []interface{}{ +var file_tvix_castore_protos_castore_proto_goTypes = []any{ (*Directory)(nil), // 0: tvix.castore.v1.Directory (*DirectoryNode)(nil), // 1: tvix.castore.v1.DirectoryNode (*FileNode)(nil), // 2: tvix.castore.v1.FileNode @@ -492,69 +482,7 @@ func file_tvix_castore_protos_castore_proto_init() { if File_tvix_castore_protos_castore_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_tvix_castore_protos_castore_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Directory); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_castore_protos_castore_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DirectoryNode); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_castore_protos_castore_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FileNode); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_castore_protos_castore_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SymlinkNode); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_castore_protos_castore_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Node); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_tvix_castore_protos_castore_proto_msgTypes[4].OneofWrappers = []interface{}{ + file_tvix_castore_protos_castore_proto_msgTypes[4].OneofWrappers = []any{ (*Node_Directory)(nil), (*Node_File)(nil), (*Node_Symlink)(nil), diff --git a/tvix/castore-go/rpc_blobstore.pb.go b/tvix/castore-go/rpc_blobstore.pb.go index 3607a65bbe20..90b131bff921 100644 --- a/tvix/castore-go/rpc_blobstore.pb.go +++ b/tvix/castore-go/rpc_blobstore.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.35.1 // protoc (unknown) // source: tvix/castore/protos/rpc_blobstore.proto @@ -38,11 +38,9 @@ type StatBlobRequest struct { func (x *StatBlobRequest) Reset() { *x = StatBlobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *StatBlobRequest) String() string { @@ -53,7 +51,7 @@ func (*StatBlobRequest) ProtoMessage() {} func (x *StatBlobRequest) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -105,11 +103,9 @@ type StatBlobResponse struct { func (x *StatBlobResponse) Reset() { *x = StatBlobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *StatBlobResponse) String() string { @@ -120,7 +116,7 @@ func (*StatBlobResponse) ProtoMessage() {} func (x *StatBlobResponse) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -160,11 +156,9 @@ type ReadBlobRequest struct { func (x *ReadBlobRequest) Reset() { *x = ReadBlobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ReadBlobRequest) String() string { @@ -175,7 +169,7 @@ func (*ReadBlobRequest) ProtoMessage() {} func (x *ReadBlobRequest) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -209,11 +203,9 @@ type BlobChunk struct { func (x *BlobChunk) Reset() { *x = BlobChunk{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *BlobChunk) String() string { @@ -224,7 +216,7 @@ func (*BlobChunk) ProtoMessage() {} func (x *BlobChunk) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -257,11 +249,9 @@ type PutBlobResponse struct { func (x *PutBlobResponse) Reset() { *x = PutBlobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *PutBlobResponse) String() string { @@ -272,7 +262,7 @@ func (*PutBlobResponse) ProtoMessage() {} func (x *PutBlobResponse) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -307,11 +297,9 @@ type StatBlobResponse_ChunkMeta struct { func (x *StatBlobResponse_ChunkMeta) Reset() { *x = StatBlobResponse_ChunkMeta{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *StatBlobResponse_ChunkMeta) String() string { @@ -322,7 +310,7 @@ func (*StatBlobResponse_ChunkMeta) ProtoMessage() {} func (x *StatBlobResponse_ChunkMeta) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -415,7 +403,7 @@ func file_tvix_castore_protos_rpc_blobstore_proto_rawDescGZIP() []byte { } var file_tvix_castore_protos_rpc_blobstore_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_tvix_castore_protos_rpc_blobstore_proto_goTypes = []interface{}{ +var file_tvix_castore_protos_rpc_blobstore_proto_goTypes = []any{ (*StatBlobRequest)(nil), // 0: tvix.castore.v1.StatBlobRequest (*StatBlobResponse)(nil), // 1: tvix.castore.v1.StatBlobResponse (*ReadBlobRequest)(nil), // 2: tvix.castore.v1.ReadBlobRequest @@ -443,80 +431,6 @@ func file_tvix_castore_protos_rpc_blobstore_proto_init() { if File_tvix_castore_protos_rpc_blobstore_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StatBlobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StatBlobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReadBlobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlobChunk); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PutBlobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_castore_protos_rpc_blobstore_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StatBlobResponse_ChunkMeta); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/tvix/castore-go/rpc_directory.pb.go b/tvix/castore-go/rpc_directory.pb.go index 78c4a243e3ff..27a4e9423036 100644 --- a/tvix/castore-go/rpc_directory.pb.go +++ b/tvix/castore-go/rpc_directory.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.35.1 // protoc (unknown) // source: tvix/castore/protos/rpc_directory.proto @@ -41,11 +41,9 @@ type GetDirectoryRequest struct { func (x *GetDirectoryRequest) Reset() { *x = GetDirectoryRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_rpc_directory_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_rpc_directory_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GetDirectoryRequest) String() string { @@ -56,7 +54,7 @@ func (*GetDirectoryRequest) ProtoMessage() {} func (x *GetDirectoryRequest) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_rpc_directory_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -115,11 +113,9 @@ type PutDirectoryResponse struct { func (x *PutDirectoryResponse) Reset() { *x = PutDirectoryResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_castore_protos_rpc_directory_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_castore_protos_rpc_directory_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *PutDirectoryResponse) String() string { @@ -130,7 +126,7 @@ func (*PutDirectoryResponse) ProtoMessage() {} func (x *PutDirectoryResponse) ProtoReflect() protoreflect.Message { mi := &file_tvix_castore_protos_rpc_directory_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -199,7 +195,7 @@ func file_tvix_castore_protos_rpc_directory_proto_rawDescGZIP() []byte { } var file_tvix_castore_protos_rpc_directory_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_tvix_castore_protos_rpc_directory_proto_goTypes = []interface{}{ +var file_tvix_castore_protos_rpc_directory_proto_goTypes = []any{ (*GetDirectoryRequest)(nil), // 0: tvix.castore.v1.GetDirectoryRequest (*PutDirectoryResponse)(nil), // 1: tvix.castore.v1.PutDirectoryResponse (*Directory)(nil), // 2: tvix.castore.v1.Directory @@ -222,33 +218,7 @@ func file_tvix_castore_protos_rpc_directory_proto_init() { return } file_tvix_castore_protos_castore_proto_init() - if !protoimpl.UnsafeEnabled { - file_tvix_castore_protos_rpc_directory_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetDirectoryRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_castore_protos_rpc_directory_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PutDirectoryResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_tvix_castore_protos_rpc_directory_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_tvix_castore_protos_rpc_directory_proto_msgTypes[0].OneofWrappers = []any{ (*GetDirectoryRequest_Digest)(nil), } type x struct{} diff --git a/tvix/castore/Cargo.toml b/tvix/castore/Cargo.toml index f54bb2ddb5b4..aa44e2e8ee4b 100644 --- a/tvix/castore/Cargo.toml +++ b/tvix/castore/Cargo.toml @@ -4,101 +4,80 @@ version = "0.1.0" edition = "2021" [dependencies] -async-stream = "0.3.5" -async-tempfile = "0.4.0" -blake3 = { version = "1.3.1", features = ["rayon", "std", "traits-preview"] } -bstr = "1.6.0" -bytes = "1.4.0" -data-encoding = "2.3.3" -digest = "0.10.7" -fastcdc = { version = "3.1.0", features = ["tokio"] } -futures = "0.3.30" -lazy_static = "1.4.0" -object_store = { version = "0.9.1", features = ["http"] } -parking_lot = "0.12.1" -pin-project-lite = "0.2.13" -prost = "0.12.1" -sled = { version = "0.34.7" } -thiserror = "1.0.38" -tokio-stream = { version = "0.1.14", features = ["fs", "net"] } -tokio-util = { version = "0.7.9", features = ["io", "io-util"] } -tokio-tar = "0.3.1" -tokio = { version = "1.32.0", features = ["fs", "macros", "net", "rt", "rt-multi-thread", "signal"] } -tonic = "0.11.0" -tower = "0.4.13" -tracing = "0.1.37" -url = "2.4.0" -walkdir = "2.4.0" -zstd = "0.13.0" -serde = { version = "1.0.197", features = [ "derive" ] } -serde_with = "3.7.0" -serde_qs = "0.12.0" -petgraph = "0.6.4" - -[dependencies.bigtable_rs] -optional = true -# https://github.com/liufuyang/bigtable_rs/pull/72 -git = "https://github.com/flokli/bigtable_rs" -rev = "0af404741dfc40eb9fa99cf4d4140a09c5c20df7" - -[dependencies.fuse-backend-rs] -optional = true -version = "0.11.0" - -[dependencies.libc] -optional = true -version = "0.2.144" - -[dependencies.tonic-reflection] -optional = true -version = "0.11.0" - -[dependencies.vhost] -optional = true -version = "0.6" - -[dependencies.vhost-user-backend] -optional = true -version = "0.8" - -[dependencies.virtio-queue] -optional = true -version = "0.7" - -[dependencies.vm-memory] -optional = true -version = "0.10" - -[dependencies.vmm-sys-util] -optional = true -version = "0.11" - -[dependencies.virtio-bindings] -optional = true -version = "0.2.1" +async-compression = { workspace = true, features = ["tokio", "zstd"] } +async-stream = { workspace = true } +async-tempfile = { workspace = true } +blake3 = { workspace = true, features = ["rayon", "std", "traits-preview"] } +bstr = { workspace = true } +bytes = { workspace = true } +data-encoding = { workspace = true } +digest = { workspace = true } +fastcdc = { workspace = true, features = ["tokio"] } +futures = { workspace = true } +object_store = { workspace = true, features = ["http"] } +parking_lot = { workspace = true } +pin-project-lite = { workspace = true } +prost = { workspace = true } +thiserror = { workspace = true } +tokio-stream = { workspace = true, features = ["fs", "net"] } +tokio-util = { workspace = true, features = ["io", "io-util", "codec"] } +tokio-tar = { workspace = true } +tokio = { workspace = true, features = ["fs", "macros", "net", "rt", "rt-multi-thread", "signal"] } +tonic = { workspace = true } +tower = { workspace = true } +tracing = { workspace = true } +tracing-indicatif = { workspace = true } +tvix-tracing = { path = "../tracing", features = ["tonic"] } +url = { workspace = true } +walkdir = { workspace = true } +zstd = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_with = { workspace = true } +serde_qs = { workspace = true } +petgraph = { workspace = true } +pin-project = { workspace = true } +erased-serde = { workspace = true } +serde_tagged = { workspace = true } +hyper-util = { workspace = true } +redb = { workspace = true, features = ["logging"] } +bigtable_rs = { workspace = true, optional = true } +fuse-backend-rs = { workspace = true, optional = true } +libc = { workspace = true, optional = true } +threadpool = { workspace = true, optional = true } +tonic-reflection = { workspace = true, optional = true } +vhost = { workspace = true, optional = true } +vhost-user-backend = { workspace = true, optional = true } +virtio-queue = { workspace = true, optional = true } +vm-memory = { workspace = true, optional = true } +vmm-sys-util = { workspace = true, optional = true } +virtio-bindings = { workspace = true, optional = true } +wu-manber = { workspace = true } +auto_impl = "1.2.0" [build-dependencies] -prost-build = "0.12.1" -tonic-build = "0.11.0" +prost-build = { workspace = true } +tonic-build = { workspace = true } [dev-dependencies] -async-process = "2.1.0" -rstest = "0.19.0" -tempfile = "3.3.0" -tokio-retry = "0.3.0" -hex-literal = "0.4.1" -rstest_reuse = "0.6.0" -xattr = "1.3.1" +async-process = { workspace = true } +rstest = { workspace = true } +tempfile = { workspace = true } +tokio-retry = { workspace = true } +hex-literal = { workspace = true } +rstest_reuse = { workspace = true } +xattr = { workspace = true } +serde_json = { workspace = true } +tokio-test = { workspace = true } [features] -default = [] +default = ["cloud"] cloud = [ "dep:bigtable_rs", "object_store/aws", "object_store/azure", "object_store/gcp", ] -fs = ["dep:libc", "dep:fuse-backend-rs"] +fs = ["dep:fuse-backend-rs", "dep:threadpool", "dep:libc"] virtiofs = [ "fs", "dep:vhost", @@ -112,3 +91,15 @@ virtiofs = [ ] fuse = ["fs"] tonic-reflection = ["dep:tonic-reflection"] +# It's already possible for other crates to build a +# fully fledged store composition system based on castore composition. +# However, this feature enables anonymous url syntax which might +# inherently expose arbitrary composition possibilities to the user. +xp-store-composition = [] +# Whether to run the integration tests. +# Requires the following packages in $PATH: +# cbtemulator, google-cloud-bigtable-tool +integration = [] + +[lints] +workspace = true diff --git a/tvix/castore/build.rs b/tvix/castore/build.rs index 089c093e71b4..2250d4ebf0a2 100644 --- a/tvix/castore/build.rs +++ b/tvix/castore/build.rs @@ -12,17 +12,13 @@ fn main() -> Result<()> { builder = builder.file_descriptor_set_path(descriptor_path); }; - // https://github.com/hyperium/tonic/issues/908 - let mut config = prost_build::Config::new(); - config.bytes(["."]); - config.type_attribute(".", "#[derive(Eq, Hash)]"); - builder .build_server(true) .build_client(true) .emit_rerun_if_changed(false) - .compile_with_config( - config, + .bytes(["."]) + .type_attribute(".", "#[derive(Eq, Hash)]") + .compile_protos( &[ "tvix/castore/protos/castore.proto", "tvix/castore/protos/rpc_blobstore.proto", @@ -30,7 +26,7 @@ fn main() -> Result<()> { ], // If we are in running `cargo build` manually, using `../..` works fine, // but in case we run inside a nix build, we need to instead point PROTO_ROOT - // to a sparseTree containing that structure. + // to a custom tree containing that structure. &[match std::env::var_os("PROTO_ROOT") { Some(proto_root) => proto_root.to_str().unwrap().to_owned(), None => "../..".to_string(), diff --git a/tvix/castore/default.nix b/tvix/castore/default.nix index edc20ac79d5e..5314da9e0333 100644 --- a/tvix/castore/default.nix +++ b/tvix/castore/default.nix @@ -1,12 +1,28 @@ -{ depot, pkgs, ... }: +{ depot, pkgs, lib, ... }: -depot.tvix.crates.workspaceMembers.tvix-castore.build.override { +(depot.tvix.crates.workspaceMembers.tvix-castore.build.override { runTests = true; testPreRun = '' - export SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt; - export PATH="$PATH:${pkgs.lib.makeBinPath [pkgs.cbtemulator pkgs.google-cloud-bigtable-tool]}" + export SSL_CERT_FILE=/dev/null ''; - - # enable some optional features. - features = [ "default" "cloud" ]; -} +}).overrideAttrs (old: rec { + meta.ci.targets = [ "integration-tests" ] ++ lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); + passthru = (depot.tvix.utils.mkFeaturePowerset { + inherit (old) crateName; + features = ([ "cloud" "fuse" "tonic-reflection" "xp-store-composition" ] + # virtiofs feature currently fails to build on Darwin + ++ lib.optional pkgs.stdenv.isLinux "virtiofs"); + override.testPreRun = '' + export SSL_CERT_FILE=/dev/null + ''; + }) // { + integration-tests = depot.tvix.crates.workspaceMembers.${old.crateName}.build.override (old: { + runTests = true; + testPreRun = '' + export SSL_CERT_FILE=/dev/null + export PATH="$PATH:${pkgs.lib.makeBinPath [ pkgs.cbtemulator pkgs.google-cloud-bigtable-tool ]}" + ''; + features = old.features ++ [ "integration" ]; + }); + }; +}) diff --git a/tvix/castore/protos/default.nix b/tvix/castore/protos/default.nix index feef55690fb9..08bb8fcfeef1 100644 --- a/tvix/castore/protos/default.nix +++ b/tvix/castore/protos/default.nix @@ -1,16 +1,10 @@ -{ depot, pkgs, ... }: +{ depot, pkgs, lib, ... }: let - protos = depot.nix.sparseTree { - name = "castore-protos"; - root = depot.path.origSrc; - paths = [ - ./castore.proto - ./rpc_blobstore.proto - ./rpc_directory.proto - ../../../buf.yaml - ../../../buf.gen.yaml - ]; - }; + protos = lib.sourceByRegex depot.path.origSrc [ + "buf.yaml" + "buf.gen.yaml" + "^tvix(/castore(/protos(/.*\.proto)?)?)?$" + ]; in depot.nix.readTree.drvTargets { inherit protos; diff --git a/tvix/castore/src/blobservice/chunked_reader.rs b/tvix/castore/src/blobservice/chunked_reader.rs index 6e8355874bca..0e809b300485 100644 --- a/tvix/castore/src/blobservice/chunked_reader.rs +++ b/tvix/castore/src/blobservice/chunked_reader.rs @@ -253,14 +253,16 @@ where #[cfg(test)] mod test { - use std::{io::SeekFrom, sync::Arc}; + use std::{ + io::SeekFrom, + sync::{Arc, LazyLock}, + }; use crate::{ blobservice::{chunked_reader::ChunkedReader, BlobService, MemoryBlobService}, B3Digest, }; use hex_literal::hex; - use lazy_static::lazy_static; use tokio::io::{AsyncReadExt, AsyncSeekExt}; const CHUNK_1: [u8; 2] = hex!("0001"); @@ -269,21 +271,26 @@ mod test { const CHUNK_4: [u8; 2] = hex!("0708"); const CHUNK_5: [u8; 7] = hex!("090a0b0c0d0e0f"); - lazy_static! { - // `[ 0 1 ] [ 2 3 4 5 ] [ 6 ] [ 7 8 ] [ 9 10 11 12 13 14 15 ]` - pub static ref CHUNK_1_DIGEST: B3Digest = blake3::hash(&CHUNK_1).as_bytes().into(); - pub static ref CHUNK_2_DIGEST: B3Digest = blake3::hash(&CHUNK_2).as_bytes().into(); - pub static ref CHUNK_3_DIGEST: B3Digest = blake3::hash(&CHUNK_3).as_bytes().into(); - pub static ref CHUNK_4_DIGEST: B3Digest = blake3::hash(&CHUNK_4).as_bytes().into(); - pub static ref CHUNK_5_DIGEST: B3Digest = blake3::hash(&CHUNK_5).as_bytes().into(); - pub static ref BLOB_1_LIST: [(B3Digest, u64); 5] = [ + // `[ 0 1 ] [ 2 3 4 5 ] [ 6 ] [ 7 8 ] [ 9 10 11 12 13 14 15 ]` + pub static CHUNK_1_DIGEST: LazyLock<B3Digest> = + LazyLock::new(|| blake3::hash(&CHUNK_1).as_bytes().into()); + pub static CHUNK_2_DIGEST: LazyLock<B3Digest> = + LazyLock::new(|| blake3::hash(&CHUNK_2).as_bytes().into()); + pub static CHUNK_3_DIGEST: LazyLock<B3Digest> = + LazyLock::new(|| blake3::hash(&CHUNK_3).as_bytes().into()); + pub static CHUNK_4_DIGEST: LazyLock<B3Digest> = + LazyLock::new(|| blake3::hash(&CHUNK_4).as_bytes().into()); + pub static CHUNK_5_DIGEST: LazyLock<B3Digest> = + LazyLock::new(|| blake3::hash(&CHUNK_5).as_bytes().into()); + pub static BLOB_1_LIST: LazyLock<[(B3Digest, u64); 5]> = LazyLock::new(|| { + [ (CHUNK_1_DIGEST.clone(), 2), (CHUNK_2_DIGEST.clone(), 4), (CHUNK_3_DIGEST.clone(), 1), (CHUNK_4_DIGEST.clone(), 2), (CHUNK_5_DIGEST.clone(), 7), - ]; - } + ] + }); use super::ChunkedBlob; diff --git a/tvix/castore/src/blobservice/combinator.rs b/tvix/castore/src/blobservice/combinator.rs index 067eff96f488..6a964c8a8440 100644 --- a/tvix/castore/src/blobservice/combinator.rs +++ b/tvix/castore/src/blobservice/combinator.rs @@ -1,11 +1,12 @@ -use futures::{StreamExt, TryStreamExt}; -use tokio_util::io::{ReaderStream, StreamReader}; +use std::sync::Arc; + use tonic::async_trait; -use tracing::{instrument, warn}; +use tracing::instrument; -use crate::B3Digest; +use crate::composition::{CompositionContext, ServiceBuilder}; +use crate::{B3Digest, Error}; -use super::{naive_seeker::NaiveSeeker, BlobReader, BlobService, BlobWriter}; +use super::{BlobReader, BlobService, BlobWriter, ChunkedReader}; /// Combinator for a BlobService, using a "local" and "remote" blobservice. /// Requests are tried in (and returned from) the local store first, only if @@ -68,19 +69,16 @@ where // otherwise, a chunked reader, which will always try the // local backend first. - // map Vec<ChunkMeta> to Vec<(B3Digest, u64)> - let chunks: Vec<(B3Digest, u64)> = remote_chunks - .into_iter() - .map(|chunk_meta| { + let chunked_reader = ChunkedReader::from_chunks( + remote_chunks.into_iter().map(|chunk| { ( - B3Digest::try_from(chunk_meta.digest) - .expect("invalid chunk digest"), - chunk_meta.size, + chunk.digest.try_into().expect("invalid b3 digest"), + chunk.size, ) - }) - .collect(); - - Ok(Some(make_chunked_reader(self.clone(), chunks))) + }), + Arc::new(self.clone()) as Arc<dyn BlobService>, + ); + Ok(Some(Box::new(chunked_reader))) } } } @@ -93,40 +91,38 @@ where } } -fn make_chunked_reader<BS>( - // This must consume, as we can't retain references to blob_service, - // as it'd add a lifetime to BlobReader in general, which will get - // problematic in TvixStoreFs, which is using async move closures and cloning. - blob_service: BS, - // A list of b3 digests for individual chunks, and their sizes. - chunks: Vec<(B3Digest, u64)>, -) -> Box<dyn BlobReader> -where - BS: BlobService + Clone + 'static, -{ - // TODO: offset, verified streaming - - // construct readers for each chunk - let blob_service = blob_service.clone(); - let readers_stream = tokio_stream::iter(chunks).map(move |(digest, _)| { - let d = digest.to_owned(); - let blob_service = blob_service.clone(); - async move { - blob_service.open_read(&d.to_owned()).await?.ok_or_else(|| { - warn!(chunk.digest = %digest, "chunk not found"); - std::io::Error::new(std::io::ErrorKind::NotFound, "chunk not found") - }) - } - }); - - // convert the stream of readers to a stream of streams of byte chunks - let bytes_streams = readers_stream.then(|elem| async { elem.await.map(ReaderStream::new) }); - - // flatten into one stream of byte chunks - let bytes_stream = bytes_streams.try_flatten(); +#[derive(serde::Deserialize, Debug, Clone)] +#[serde(deny_unknown_fields)] +pub struct CombinedBlobServiceConfig { + local: String, + remote: String, +} - // convert into AsyncRead - let blob_reader = StreamReader::new(bytes_stream); +impl TryFrom<url::Url> for CombinedBlobServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(_url: url::Url) -> Result<Self, Self::Error> { + Err(Error::StorageError( + "Instantiating a CombinedBlobService from a url is not supported".into(), + ) + .into()) + } +} - Box::new(NaiveSeeker::new(Box::pin(blob_reader))) +#[async_trait] +impl ServiceBuilder for CombinedBlobServiceConfig { + type Output = dyn BlobService; + async fn build<'a>( + &'a self, + _instance_name: &str, + context: &CompositionContext, + ) -> Result<Arc<dyn BlobService>, Box<dyn std::error::Error + Send + Sync>> { + let (local, remote) = futures::join!( + context.resolve(self.local.clone()), + context.resolve(self.remote.clone()) + ); + Ok(Arc::new(CombinedBlobService { + local: local?, + remote: remote?, + })) + } } diff --git a/tvix/castore/src/blobservice/from_addr.rs b/tvix/castore/src/blobservice/from_addr.rs index 3e3f943e5931..803e7fa6a575 100644 --- a/tvix/castore/src/blobservice/from_addr.rs +++ b/tvix/castore/src/blobservice/from_addr.rs @@ -1,81 +1,34 @@ -use url::Url; +use std::sync::Arc; -use crate::{proto::blob_service_client::BlobServiceClient, Error}; +use url::Url; -use super::{ - BlobService, GRPCBlobService, MemoryBlobService, ObjectStoreBlobService, SledBlobService, +use crate::composition::{ + with_registry, CompositionContext, DeserializeWithRegistry, ServiceBuilder, REG, }; +use super::BlobService; + /// Constructs a new instance of a [BlobService] from an URI. /// /// The following schemes are supported by the following services: /// - `memory://` ([MemoryBlobService]) -/// - `sled://` ([SledBlobService]) /// - `grpc+*://` ([GRPCBlobService]) /// - `objectstore+*://` ([ObjectStoreBlobService]) /// /// See their `from_url` methods for more details about their syntax. -pub async fn from_addr(uri: &str) -> Result<Box<dyn BlobService>, crate::Error> { +pub async fn from_addr( + uri: &str, +) -> Result<Arc<dyn BlobService>, Box<dyn std::error::Error + Send + Sync>> { let url = Url::parse(uri) .map_err(|e| crate::Error::StorageError(format!("unable to parse url: {}", e)))?; - let blob_service: Box<dyn BlobService> = match url.scheme() { - "memory" => { - // memory doesn't support host or path in the URL. - if url.has_host() || !url.path().is_empty() { - return Err(Error::StorageError("invalid url".to_string())); - } - Box::<MemoryBlobService>::default() - } - "sled" => { - // sled doesn't support host, and a path can be provided (otherwise - // it'll live in memory only). - if url.has_host() { - return Err(Error::StorageError("no host allowed".to_string())); - } - - if url.path() == "/" { - return Err(Error::StorageError( - "cowardly refusing to open / with sled".to_string(), - )); - } - - // TODO: expose other parameters as URL parameters? - - Box::new(if url.path().is_empty() { - SledBlobService::new_temporary().map_err(|e| Error::StorageError(e.to_string()))? - } else { - SledBlobService::new(url.path()).map_err(|e| Error::StorageError(e.to_string()))? - }) - } - scheme if scheme.starts_with("grpc+") => { - // schemes starting with grpc+ go to the GRPCPathInfoService. - // That's normally grpc+unix for unix sockets, and grpc+http(s) for the HTTP counterparts. - // - In the case of unix sockets, there must be a path, but may not be a host. - // - In the case of non-unix sockets, there must be a host, but no path. - // Constructing the channel is handled by tvix_castore::channel::from_url. - let client = BlobServiceClient::new(crate::tonic::channel_from_url(&url).await?); - Box::new(GRPCBlobService::from_client(client)) - } - scheme if scheme.starts_with("objectstore+") => { - // We need to convert the URL to string, strip the prefix there, and then - // parse it back as url, as Url::set_scheme() rejects some of the transitions we want to do. - let trimmed_url = { - let s = url.to_string(); - Url::parse(s.strip_prefix("objectstore+").unwrap()).unwrap() - }; - Box::new( - ObjectStoreBlobService::parse_url(&trimmed_url) - .map_err(|e| Error::StorageError(e.to_string()))?, - ) - } - scheme => { - return Err(crate::Error::StorageError(format!( - "unknown scheme: {}", - scheme - ))) - } - }; + let blob_service_config = with_registry(®, || { + <DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = dyn BlobService>>>>::try_from(url) + })? + .0; + let blob_service = blob_service_config + .build("anonymous", &CompositionContext::blank(®)) + .await?; Ok(blob_service) } @@ -83,28 +36,11 @@ pub async fn from_addr(uri: &str) -> Result<Box<dyn BlobService>, crate::Error> #[cfg(test)] mod tests { use super::from_addr; - use lazy_static::lazy_static; use rstest::rstest; - use tempfile::TempDir; - - lazy_static! { - static ref TMPDIR_SLED_1: TempDir = TempDir::new().unwrap(); - static ref TMPDIR_SLED_2: TempDir = TempDir::new().unwrap(); - } #[rstest] /// This uses an unsupported scheme. #[case::unsupported_scheme("http://foo.example/test", false)] - /// This configures sled in temporary mode. - #[case::sled_temporary("sled://", true)] - /// This configures sled with /, which should fail. - #[case::sled_invalid_root("sled:///", false)] - /// This configures sled with a host, not path, which should fail. - #[case::sled_invalid_host("sled://foo.example", false)] - /// This configures sled with a valid path path, which should succeed. - #[case::sled_valid_path(&format!("sled://{}", &TMPDIR_SLED_1.path().to_str().unwrap()), true)] - /// This configures sled with a host, and a valid path path, which should fail. - #[case::sled_invalid_host_with_valid_path(&format!("sled://foo.example{}", &TMPDIR_SLED_2.path().to_str().unwrap()), false)] /// This correctly sets the scheme, and doesn't set a path. #[case::memory_valid("memory://", true)] /// This sets a memory url host to `foo` diff --git a/tvix/castore/src/blobservice/grpc.rs b/tvix/castore/src/blobservice/grpc.rs index 5663cd3838ec..0db3dfea4ad8 100644 --- a/tvix/castore/src/blobservice/grpc.rs +++ b/tvix/castore/src/blobservice/grpc.rs @@ -1,4 +1,5 @@ use super::{BlobReader, BlobService, BlobWriter, ChunkedReader}; +use crate::composition::{CompositionContext, ServiceBuilder}; use crate::{ proto::{self, stat_blob_response::ChunkMeta}, B3Digest, @@ -17,40 +18,43 @@ use tokio_util::{ io::{CopyToBytes, SinkWriter}, sync::PollSender, }; -use tonic::{async_trait, transport::Channel, Code, Status}; -use tracing::instrument; +use tonic::{async_trait, Code, Status}; +use tracing::{instrument, Instrument as _}; /// Connects to a (remote) tvix-store BlobService over gRPC. #[derive(Clone)] -pub struct GRPCBlobService { +pub struct GRPCBlobService<T> { /// The internal reference to a gRPC client. /// Cloning it is cheap, and it internally handles concurrent requests. - grpc_client: proto::blob_service_client::BlobServiceClient<Channel>, + grpc_client: proto::blob_service_client::BlobServiceClient<T>, } -impl GRPCBlobService { +impl<T> GRPCBlobService<T> { /// construct a [GRPCBlobService] from a [proto::blob_service_client::BlobServiceClient]. - /// panics if called outside the context of a tokio runtime. - pub fn from_client( - grpc_client: proto::blob_service_client::BlobServiceClient<Channel>, - ) -> Self { + pub fn from_client(grpc_client: proto::blob_service_client::BlobServiceClient<T>) -> Self { Self { grpc_client } } } #[async_trait] -impl BlobService for GRPCBlobService { +impl<T> BlobService for GRPCBlobService<T> +where + T: tonic::client::GrpcService<tonic::body::BoxBody> + Send + Sync + Clone + 'static, + T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static, + <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send, + T::Future: Send, +{ #[instrument(skip(self, digest), fields(blob.digest=%digest))] async fn has(&self, digest: &B3Digest) -> io::Result<bool> { - let mut grpc_client = self.grpc_client.clone(); - let resp = grpc_client + match self + .grpc_client + .clone() .stat(proto::StatBlobRequest { digest: digest.clone().into(), ..Default::default() }) - .await; - - match resp { + .await + { Ok(_blob_meta) => Ok(true), Err(e) if e.code() == Code::NotFound => Ok(false), Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)), @@ -133,6 +137,8 @@ impl BlobService for GRPCBlobService { let task = tokio::spawn({ let mut grpc_client = self.grpc_client.clone(); async move { Ok::<_, Status>(grpc_client.put(blobchunk_stream).await?.into_inner()) } + // instrument the task with the current span, this is not done by default + .in_current_span() }); // The tx part of the channel is converted to a sink of byte chunks. @@ -175,6 +181,40 @@ impl BlobService for GRPCBlobService { } } +#[derive(serde::Deserialize, Debug)] +#[serde(deny_unknown_fields)] +pub struct GRPCBlobServiceConfig { + url: String, +} + +impl TryFrom<url::Url> for GRPCBlobServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + // normally grpc+unix for unix sockets, and grpc+http(s) for the HTTP counterparts. + // - In the case of unix sockets, there must be a path, but may not be a host. + // - In the case of non-unix sockets, there must be a host, but no path. + // Constructing the channel is handled by tvix_castore::channel::from_url. + Ok(GRPCBlobServiceConfig { + url: url.to_string(), + }) + } +} + +#[async_trait] +impl ServiceBuilder for GRPCBlobServiceConfig { + type Output = dyn BlobService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn BlobService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + let client = proto::blob_service_client::BlobServiceClient::new( + crate::tonic::channel_from_url(&self.url.parse()?).await?, + ); + Ok(Arc::new(GRPCBlobService::from_client(client))) + } +} + pub struct GRPCBlobWriter<W: tokio::io::AsyncWrite> { /// The task containing the put request, and the inner writer, if we're still writing. task_and_writer: Option<(JoinHandle<Result<proto::PutBlobResponse, Status>>, W)>, @@ -335,7 +375,6 @@ mod tests { .await .expect("must succeed"), ); - GRPCBlobService::from_client(client) }; diff --git a/tvix/castore/src/blobservice/memory.rs b/tvix/castore/src/blobservice/memory.rs index 25eec334de60..3d733f950470 100644 --- a/tvix/castore/src/blobservice/memory.rs +++ b/tvix/castore/src/blobservice/memory.rs @@ -1,14 +1,13 @@ +use parking_lot::RwLock; use std::io::{self, Cursor, Write}; use std::task::Poll; -use std::{ - collections::HashMap, - sync::{Arc, RwLock}, -}; +use std::{collections::HashMap, sync::Arc}; use tonic::async_trait; use tracing::instrument; use super::{BlobReader, BlobService, BlobWriter}; -use crate::B3Digest; +use crate::composition::{CompositionContext, ServiceBuilder}; +use crate::{B3Digest, Error}; #[derive(Clone, Default)] pub struct MemoryBlobService { @@ -19,13 +18,13 @@ pub struct MemoryBlobService { impl BlobService for MemoryBlobService { #[instrument(skip_all, ret, err, fields(blob.digest=%digest))] async fn has(&self, digest: &B3Digest) -> io::Result<bool> { - let db = self.db.read().unwrap(); + let db = self.db.read(); Ok(db.contains_key(digest)) } #[instrument(skip_all, err, fields(blob.digest=%digest))] async fn open_read(&self, digest: &B3Digest) -> io::Result<Option<Box<dyn BlobReader>>> { - let db = self.db.read().unwrap(); + let db = self.db.read(); match db.get(digest).map(|x| Cursor::new(x.clone())) { Some(result) => Ok(Some(Box::new(result))), @@ -39,6 +38,33 @@ impl BlobService for MemoryBlobService { } } +#[derive(serde::Deserialize, Debug)] +#[serde(deny_unknown_fields)] +pub struct MemoryBlobServiceConfig {} + +impl TryFrom<url::Url> for MemoryBlobServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + // memory doesn't support host or path in the URL. + if url.has_host() || !url.path().is_empty() { + return Err(Error::StorageError("invalid url".to_string()).into()); + } + Ok(MemoryBlobServiceConfig {}) + } +} + +#[async_trait] +impl ServiceBuilder for MemoryBlobServiceConfig { + type Output = dyn BlobService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn BlobService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + Ok(Arc::new(MemoryBlobService::default())) + } +} + pub struct MemoryBlobWriter { db: Arc<RwLock<HashMap<B3Digest, Vec<u8>>>>, @@ -109,24 +135,16 @@ impl BlobWriter for MemoryBlobWriter { } else { let (buf, hasher) = self.writers.take().unwrap(); - // We know self.hasher is doing blake3 hashing, so this won't fail. let digest: B3Digest = hasher.finalize().as_bytes().into(); // Only insert if the blob doesn't already exist. - let db = self.db.read().map_err(|e| { - io::Error::new(io::ErrorKind::BrokenPipe, format!("RwLock poisoned: {}", e)) - })?; + let mut db = self.db.upgradable_read(); if !db.contains_key(&digest) { - // drop the read lock, so we can open for writing. - drop(db); - // open the database for writing. - let mut db = self.db.write().map_err(|e| { - io::Error::new(io::ErrorKind::BrokenPipe, format!("RwLock poisoned: {}", e)) - })?; - - // and put buf in there. This will move buf out. - db.insert(digest.clone(), buf); + db.with_upgraded(|db| { + // and put buf in there. This will move buf out. + db.insert(digest.clone(), buf); + }); } self.digest = Some(digest.clone()); diff --git a/tvix/castore/src/blobservice/mod.rs b/tvix/castore/src/blobservice/mod.rs index 4ba56a4af731..efba927b586b 100644 --- a/tvix/castore/src/blobservice/mod.rs +++ b/tvix/castore/src/blobservice/mod.rs @@ -1,6 +1,9 @@ use std::io; + +use auto_impl::auto_impl; use tonic::async_trait; +use crate::composition::{Registry, ServiceBuilder}; use crate::proto::stat_blob_response::ChunkMeta; use crate::B3Digest; @@ -9,20 +12,17 @@ mod combinator; mod from_addr; mod grpc; mod memory; -mod naive_seeker; mod object_store; -mod sled; #[cfg(test)] pub mod tests; pub use self::chunked_reader::ChunkedReader; -pub use self::combinator::CombinedBlobService; +pub use self::combinator::{CombinedBlobService, CombinedBlobServiceConfig}; pub use self::from_addr::from_addr; -pub use self::grpc::GRPCBlobService; -pub use self::memory::MemoryBlobService; -pub use self::object_store::ObjectStoreBlobService; -pub use self::sled::SledBlobService; +pub use self::grpc::{GRPCBlobService, GRPCBlobServiceConfig}; +pub use self::memory::{MemoryBlobService, MemoryBlobServiceConfig}; +pub use self::object_store::{ObjectStoreBlobService, ObjectStoreBlobServiceConfig}; /// The base trait all BlobService services need to implement. /// It provides functions to check whether a given blob exists, @@ -30,6 +30,7 @@ pub use self::sled::SledBlobService; /// which will implement a writer interface, and also provides a close funtion, /// to finalize a blob and get its digest. #[async_trait] +#[auto_impl(&, &mut, Arc, Box)] pub trait BlobService: Send + Sync { /// Check if the service has the blob, by its content hash. /// On implementations returning chunks, this must also work for chunks. @@ -61,28 +62,6 @@ pub trait BlobService: Send + Sync { } } -#[async_trait] -impl<A> BlobService for A -where - A: AsRef<dyn BlobService> + Send + Sync, -{ - async fn has(&self, digest: &B3Digest) -> io::Result<bool> { - self.as_ref().has(digest).await - } - - async fn open_read(&self, digest: &B3Digest) -> io::Result<Option<Box<dyn BlobReader>>> { - self.as_ref().open_read(digest).await - } - - async fn open_write(&self) -> Box<dyn BlobWriter> { - self.as_ref().open_write().await - } - - async fn chunks(&self, digest: &B3Digest) -> io::Result<Option<Vec<ChunkMeta>>> { - self.as_ref().chunks(digest).await - } -} - /// A [tokio::io::AsyncWrite] that the user needs to close() afterwards for persist. /// On success, it returns the digest of the written blob. #[async_trait] @@ -103,3 +82,11 @@ impl BlobReader for io::Cursor<&'static [u8; 0]> {} impl BlobReader for io::Cursor<Vec<u8>> {} impl BlobReader for io::Cursor<bytes::Bytes> {} impl BlobReader for tokio::fs::File {} + +/// Registers the builtin BlobService implementations with the registry +pub(crate) fn register_blob_services(reg: &mut Registry) { + reg.register::<Box<dyn ServiceBuilder<Output = dyn BlobService>>, super::blobservice::ObjectStoreBlobServiceConfig>("objectstore"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn BlobService>>, super::blobservice::MemoryBlobServiceConfig>("memory"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn BlobService>>, super::blobservice::CombinedBlobServiceConfig>("combined"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn BlobService>>, super::blobservice::GRPCBlobServiceConfig>("grpc"); +} diff --git a/tvix/castore/src/blobservice/naive_seeker.rs b/tvix/castore/src/blobservice/naive_seeker.rs deleted file mode 100644 index f5a530715093..000000000000 --- a/tvix/castore/src/blobservice/naive_seeker.rs +++ /dev/null @@ -1,265 +0,0 @@ -use super::BlobReader; -use futures::ready; -use pin_project_lite::pin_project; -use std::io; -use std::task::Poll; -use tokio::io::AsyncRead; -use tracing::{debug, instrument, trace, warn}; - -pin_project! { - /// This implements [tokio::io::AsyncSeek] for and [tokio::io::AsyncRead] by - /// simply skipping over some bytes, keeping track of the position. - /// It fails whenever you try to seek backwards. - /// - /// ## Pinning concerns: - /// - /// [NaiveSeeker] is itself pinned by callers, and we do not need to concern - /// ourselves regarding that. - /// - /// Though, its fields as per - /// <https://doc.rust-lang.org/std/pin/#pinning-is-not-structural-for-field> - /// can be pinned or unpinned. - /// - /// So we need to go over each field and choose our policy carefully. - /// - /// The obvious cases are the bookkeeping integers we keep in the structure, - /// those are private and not shared to anyone, we never build a - /// `Pin<&mut X>` out of them at any point, therefore, we can safely never - /// mark them as pinned. Of course, it is expected that no developer here - /// attempt to `pin!(self.pos)` to pin them because it makes no sense. If - /// they have to become pinned, they should be marked `#[pin]` and we need - /// to discuss it. - /// - /// So the bookkeeping integers are in the right state with respect to their - /// pinning status. The projection should offer direct access. - /// - /// On the `r` field, i.e. a `BufReader<R>`, given that - /// <https://docs.rs/tokio/latest/tokio/io/struct.BufReader.html#impl-Unpin-for-BufReader%3CR%3E> - /// is available, even a `Pin<&mut BufReader<R>>` can be safely moved. - /// - /// The only care we should have regards the internal reader itself, i.e. - /// the `R` instance, see that Tokio decided to `#[pin]` it too: - /// <https://docs.rs/tokio/latest/src/tokio/io/util/buf_reader.rs.html#29> - /// - /// In general, there's no `Unpin` instance for `R: tokio::io::AsyncRead` - /// (see <https://docs.rs/tokio/latest/tokio/io/trait.AsyncRead.html>). - /// - /// Therefore, we could keep it unpinned and pin it in every call site - /// whenever we need to call `poll_*` which can be confusing to the non- - /// expert developer and we have a fair share amount of situations where the - /// [BufReader] instance is naked, i.e. in its `&mut BufReader<R>` - /// form, this is annoying because it could lead to expose the naked `R` - /// internal instance somehow and would produce a risk of making it move - /// unexpectedly. - /// - /// We choose the path of the least resistance as we have no reason to have - /// access to the raw `BufReader<R>` instance, we just `#[pin]` it too and - /// enjoy its `poll_*` safe APIs and push the unpinning concerns to the - /// internal implementations themselves, which studied the question longer - /// than us. - pub struct NaiveSeeker<R: tokio::io::AsyncRead> { - #[pin] - r: tokio::io::BufReader<R>, - pos: u64, - bytes_to_skip: u64, - } -} - -/// The buffer size used to discard data. -const DISCARD_BUF_SIZE: usize = 4096; - -impl<R: tokio::io::AsyncRead> NaiveSeeker<R> { - pub fn new(r: R) -> Self { - NaiveSeeker { - r: tokio::io::BufReader::new(r), - pos: 0, - bytes_to_skip: 0, - } - } -} - -impl<R: tokio::io::AsyncRead> tokio::io::AsyncRead for NaiveSeeker<R> { - #[instrument(level = "trace", skip_all)] - fn poll_read( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - buf: &mut tokio::io::ReadBuf<'_>, - ) -> Poll<std::io::Result<()>> { - // The amount of data read can be determined by the increase - // in the length of the slice returned by `ReadBuf::filled`. - let filled_before = buf.filled().len(); - - let this = self.project(); - ready!(this.r.poll_read(cx, buf))?; - - let bytes_read = buf.filled().len() - filled_before; - *this.pos += bytes_read as u64; - - trace!(bytes_read = bytes_read, new_pos = this.pos, "poll_read"); - - Ok(()).into() - } -} - -impl<R: tokio::io::AsyncRead> tokio::io::AsyncBufRead for NaiveSeeker<R> { - fn poll_fill_buf( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> Poll<io::Result<&[u8]>> { - self.project().r.poll_fill_buf(cx) - } - - #[instrument(level = "trace", skip(self))] - fn consume(self: std::pin::Pin<&mut Self>, amt: usize) { - let this = self.project(); - this.r.consume(amt); - *this.pos += amt as u64; - - trace!(new_pos = this.pos, "consume"); - } -} - -impl<R: tokio::io::AsyncRead> tokio::io::AsyncSeek for NaiveSeeker<R> { - #[instrument(level="trace", skip(self), fields(inner_pos=%self.pos), err(Debug))] - fn start_seek( - self: std::pin::Pin<&mut Self>, - position: std::io::SeekFrom, - ) -> std::io::Result<()> { - let absolute_offset: u64 = match position { - io::SeekFrom::Start(start_offset) => { - if start_offset < self.pos { - return Err(io::Error::new( - io::ErrorKind::Unsupported, - format!("can't seek backwards ({} -> {})", self.pos, start_offset), - )); - } else { - start_offset - } - } - // we don't know the total size, can't support this. - io::SeekFrom::End(_end_offset) => { - return Err(io::Error::new( - io::ErrorKind::Unsupported, - "can't seek from end", - )); - } - io::SeekFrom::Current(relative_offset) => { - if relative_offset < 0 { - return Err(io::Error::new( - io::ErrorKind::Unsupported, - "can't seek backwards relative to current position", - )); - } else { - self.pos + relative_offset as u64 - } - } - }; - - // we already know absolute_offset is >= self.pos - debug_assert!( - absolute_offset >= self.pos, - "absolute_offset {} must be >= self.pos {}", - absolute_offset, - self.pos - ); - - // calculate bytes to skip - let this = self.project(); - *this.bytes_to_skip = absolute_offset - *this.pos; - - debug!(bytes_to_skip = *this.bytes_to_skip, "seek"); - - Ok(()) - } - - #[instrument(skip_all)] - fn poll_complete( - mut self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> Poll<std::io::Result<u64>> { - if self.bytes_to_skip == 0 { - // return the new position (from the start of the stream) - return Poll::Ready(Ok(self.pos)); - } - - // discard some bytes, until pos is where we want it to be. - // We create a buffer that we'll discard later on. - let mut discard_buf = [0; DISCARD_BUF_SIZE]; - - // Loop until we've reached the desired seek position. This is done by issuing repeated - // `poll_read` calls. - // If the data is not available yet, we will yield back to the executor - // and wait to be polled again. - loop { - if self.bytes_to_skip == 0 { - return Poll::Ready(Ok(self.pos)); - } - - // calculate the length we want to skip at most, which is either a max - // buffer size, or the number of remaining bytes to read, whatever is - // smaller. - let bytes_to_skip_now = std::cmp::min(self.bytes_to_skip as usize, discard_buf.len()); - let mut discard_buf = tokio::io::ReadBuf::new(&mut discard_buf[..bytes_to_skip_now]); - - ready!(self.as_mut().poll_read(cx, &mut discard_buf))?; - let bytes_skipped = discard_buf.filled().len(); - - if bytes_skipped == 0 { - return Poll::Ready(Err(io::Error::new( - io::ErrorKind::UnexpectedEof, - "got EOF while trying to skip bytes", - ))); - } - // decrement bytes to skip. The poll_read call already updated self.pos. - *self.as_mut().project().bytes_to_skip -= bytes_skipped as u64; - } - } -} - -impl<R: tokio::io::AsyncRead + Send + Unpin + 'static> BlobReader for NaiveSeeker<R> {} - -#[cfg(test)] -mod tests { - use super::{NaiveSeeker, DISCARD_BUF_SIZE}; - use std::io::{Cursor, SeekFrom}; - use tokio::io::{AsyncReadExt, AsyncSeekExt}; - - /// This seek requires multiple `poll_read` as we use a multiples of - /// DISCARD_BUF_SIZE when doing the seek. - /// This ensures we don't hang indefinitely. - #[tokio::test] - async fn seek() { - let buf = vec![0u8; DISCARD_BUF_SIZE * 4]; - let reader = Cursor::new(&buf); - let mut seeker = NaiveSeeker::new(reader); - seeker.seek(SeekFrom::Start(4000)).await.unwrap(); - } - - #[tokio::test] - async fn seek_read() { - let mut buf = vec![0u8; DISCARD_BUF_SIZE * 2]; - buf.extend_from_slice(&[1u8; DISCARD_BUF_SIZE * 2]); - buf.extend_from_slice(&[2u8; DISCARD_BUF_SIZE * 2]); - - let reader = Cursor::new(&buf); - let mut seeker = NaiveSeeker::new(reader); - - let mut read_buf = vec![0u8; DISCARD_BUF_SIZE]; - seeker.read_exact(&mut read_buf).await.expect("must read"); - assert_eq!(read_buf.as_slice(), &[0u8; DISCARD_BUF_SIZE]); - - seeker - .seek(SeekFrom::Current(DISCARD_BUF_SIZE as i64)) - .await - .expect("must seek"); - seeker.read_exact(&mut read_buf).await.expect("must read"); - assert_eq!(read_buf.as_slice(), &[1u8; DISCARD_BUF_SIZE]); - - seeker - .seek(SeekFrom::Start(2 * 2 * DISCARD_BUF_SIZE as u64)) - .await - .expect("must seek"); - seeker.read_exact(&mut read_buf).await.expect("must read"); - assert_eq!(read_buf.as_slice(), &[2u8; DISCARD_BUF_SIZE]); - } -} diff --git a/tvix/castore/src/blobservice/object_store.rs b/tvix/castore/src/blobservice/object_store.rs index d2d0a288a557..b688ebafc7f4 100644 --- a/tvix/castore/src/blobservice/object_store.rs +++ b/tvix/castore/src/blobservice/object_store.rs @@ -1,4 +1,5 @@ use std::{ + collections::HashMap, io::{self, Cursor}, pin::pin, sync::Arc, @@ -18,22 +19,13 @@ use tracing::{debug, instrument, trace, Level}; use url::Url; use crate::{ + composition::{CompositionContext, ServiceBuilder}, proto::{stat_blob_response::ChunkMeta, StatBlobResponse}, - B3Digest, B3HashingReader, + B3Digest, B3HashingReader, Error, }; use super::{BlobReader, BlobService, BlobWriter, ChunkedReader}; -#[derive(Clone)] -pub struct ObjectStoreBlobService { - object_store: Arc<dyn ObjectStore>, - base_path: Path, - - /// Average chunk size for FastCDC, in bytes. - /// min value is half, max value double of that number. - avg_chunk_size: u32, -} - /// Uses any object storage supported by the [object_store] crate to provide a /// tvix-castore [BlobService]. /// @@ -70,31 +62,14 @@ pub struct ObjectStoreBlobService { /// It also allows signalling any compression of chunks in the content-type. /// Migration *should* be possible by simply adding the right content-types to /// all keys stored so far, but no promises ;-) -impl ObjectStoreBlobService { - /// Constructs a new [ObjectStoreBlobService] from a [Url] supported by - /// [object_store]. - /// Any path suffix becomes the base path of the object store. - /// additional options, the same as in [object_store::parse_url_opts] can - /// be passed. - pub fn parse_url_opts<I, K, V>(url: &Url, options: I) -> Result<Self, object_store::Error> - where - I: IntoIterator<Item = (K, V)>, - K: AsRef<str>, - V: Into<String>, - { - let (object_store, path) = object_store::parse_url_opts(url, options)?; - - Ok(Self { - object_store: Arc::new(object_store), - base_path: path, - avg_chunk_size: 256 * 1024, - }) - } +#[derive(Clone)] +pub struct ObjectStoreBlobService { + object_store: Arc<dyn ObjectStore>, + base_path: Path, - /// Like [Self::parse_url_opts], except without the options. - pub fn parse_url(url: &Url) -> Result<Self, object_store::Error> { - Self::parse_url_opts(url, Vec::<(String, String)>::new()) - } + /// Average chunk size for FastCDC, in bytes. + /// min value is half, max value double of that number. + avg_chunk_size: u32, } #[instrument(level=Level::TRACE, skip_all,fields(base_path=%base_path,blob.digest=%digest),ret(Display))] @@ -117,7 +92,7 @@ fn derive_chunk_path(base_path: &Path, digest: &B3Digest) -> Path { #[async_trait] impl BlobService for ObjectStoreBlobService { - #[instrument(skip_all, ret, err, fields(blob.digest=%digest))] + #[instrument(skip_all, ret(level = Level::TRACE), err, fields(blob.digest=%digest))] async fn has(&self, digest: &B3Digest) -> io::Result<bool> { // TODO: clarify if this should work for chunks or not, and explicitly // document in the proto docs. @@ -269,6 +244,71 @@ impl BlobService for ObjectStoreBlobService { } } +fn default_avg_chunk_size() -> u32 { + 256 * 1024 +} + +#[derive(serde::Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ObjectStoreBlobServiceConfig { + object_store_url: String, + #[serde(default = "default_avg_chunk_size")] + avg_chunk_size: u32, + object_store_options: HashMap<String, String>, +} + +impl TryFrom<url::Url> for ObjectStoreBlobServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + /// Constructs a new [ObjectStoreBlobService] from a [Url] supported by + /// [object_store]. + /// Any path suffix becomes the base path of the object store. + /// additional options, the same as in [object_store::parse_url_opts] can + /// be passed. + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + // We need to convert the URL to string, strip the prefix there, and then + // parse it back as url, as Url::set_scheme() rejects some of the transitions we want to do. + let trimmed_url = { + let s = url.to_string(); + let mut url = Url::parse( + s.strip_prefix("objectstore+") + .ok_or(Error::StorageError("Missing objectstore uri".into()))?, + )?; + // trim the query pairs, they might contain credentials or local settings we don't want to send as-is. + url.set_query(None); + url + }; + Ok(ObjectStoreBlobServiceConfig { + object_store_url: trimmed_url.into(), + object_store_options: url + .query_pairs() + .into_iter() + .map(|(k, v)| (k.to_string(), v.to_string())) + .collect(), + avg_chunk_size: 256 * 1024, + }) + } +} + +#[async_trait] +impl ServiceBuilder for ObjectStoreBlobServiceConfig { + type Output = dyn BlobService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn BlobService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + let (object_store, path) = object_store::parse_url_opts( + &self.object_store_url.parse()?, + &self.object_store_options, + )?; + Ok(Arc::new(ObjectStoreBlobService { + object_store: Arc::new(object_store), + base_path: path, + avg_chunk_size: self.avg_chunk_size, + })) + } +} + /// Reads blob contents from a AsyncRead, chunks and uploads them. /// On success, returns a [StatBlobResponse] pointing to the individual chunks. #[instrument(skip_all, fields(base_path=%base_path, min_chunk_size, avg_chunk_size, max_chunk_size), err)] @@ -309,6 +349,15 @@ async fn chunk_and_upload<R: AsyncRead + Unpin>( .collect::<io::Result<Vec<ChunkMeta>>>() .await?; + let chunks = if chunks.len() < 2 { + // The chunker returned only one chunk, which is the entire blob. + // According to the protocol, we must return an empty list of chunks + // when the blob is not split up further. + vec![] + } else { + chunks + }; + let stat_blob_response = StatBlobResponse { chunks, bao: "".into(), // still todo @@ -512,24 +561,35 @@ where #[cfg(test)] mod test { - use super::chunk_and_upload; + use super::{chunk_and_upload, default_avg_chunk_size}; use crate::{ blobservice::{BlobService, ObjectStoreBlobService}, - fixtures::{BLOB_A, BLOB_A_DIGEST}, + fixtures::{BLOB_A, BLOB_A_DIGEST, BLOB_B, BLOB_B_DIGEST}, }; use std::{io::Cursor, sync::Arc}; use url::Url; /// Tests chunk_and_upload directly, bypassing the BlobWriter at open_write(). + #[rstest::rstest] + #[case::a(&BLOB_A, &BLOB_A_DIGEST)] + #[case::b(&BLOB_B, &BLOB_B_DIGEST)] #[tokio::test] - async fn test_chunk_and_upload() { - let blobsvc = Arc::new( - ObjectStoreBlobService::parse_url(&Url::parse("memory:///").unwrap()).unwrap(), - ); - - let blob_digest = chunk_and_upload( - &mut Cursor::new(BLOB_A.to_vec()), - blobsvc.object_store.clone(), + async fn test_chunk_and_upload( + #[case] blob: &bytes::Bytes, + #[case] blob_digest: &crate::B3Digest, + ) { + let (object_store, base_path) = + object_store::parse_url(&Url::parse("memory:///").unwrap()).unwrap(); + let object_store: Arc<dyn object_store::ObjectStore> = Arc::from(object_store); + let blobsvc = Arc::new(ObjectStoreBlobService { + object_store: object_store.clone(), + avg_chunk_size: default_avg_chunk_size(), + base_path, + }); + + let inserted_blob_digest = chunk_and_upload( + &mut Cursor::new(blob.to_vec()), + object_store, object_store::path::Path::from("/"), 1024 / 2, 1024, @@ -538,9 +598,20 @@ mod test { .await .expect("chunk_and_upload succeeds"); - assert_eq!(BLOB_A_DIGEST.clone(), blob_digest); + assert_eq!(blob_digest.clone(), inserted_blob_digest); // Now we should have the blob - assert!(blobsvc.has(&BLOB_A_DIGEST).await.unwrap()); + assert!(blobsvc.has(blob_digest).await.unwrap()); + + // Check if it was chunked correctly + let chunks = blobsvc.chunks(blob_digest).await.unwrap().unwrap(); + if blob.len() < 1024 / 2 { + // The blob is smaller than the min chunk size, it should have been inserted as a whole + assert!(chunks.is_empty()); + } else if blob.len() > 1024 * 2 { + // The blob is larger than the max chunk size, make sure it was split up into at least + // two chunks + assert!(chunks.len() >= 2); + } } } diff --git a/tvix/castore/src/blobservice/sled.rs b/tvix/castore/src/blobservice/sled.rs deleted file mode 100644 index 3dd4bff7bc8e..000000000000 --- a/tvix/castore/src/blobservice/sled.rs +++ /dev/null @@ -1,150 +0,0 @@ -use super::{BlobReader, BlobService, BlobWriter}; -use crate::{B3Digest, Error}; -use std::{ - io::{self, Cursor, Write}, - path::Path, - task::Poll, -}; -use tonic::async_trait; -use tracing::instrument; - -#[derive(Clone)] -pub struct SledBlobService { - db: sled::Db, -} - -impl SledBlobService { - pub fn new<P: AsRef<Path>>(p: P) -> Result<Self, sled::Error> { - let config = sled::Config::default() - .use_compression(false) // is a required parameter - .path(p); - let db = config.open()?; - - Ok(Self { db }) - } - - pub fn new_temporary() -> Result<Self, sled::Error> { - let config = sled::Config::default().temporary(true); - let db = config.open()?; - - Ok(Self { db }) - } -} - -#[async_trait] -impl BlobService for SledBlobService { - #[instrument(skip(self), fields(blob.digest=%digest))] - async fn has(&self, digest: &B3Digest) -> io::Result<bool> { - match self.db.contains_key(digest.as_slice()) { - Ok(has) => Ok(has), - Err(e) => Err(io::Error::new(io::ErrorKind::Other, e.to_string())), - } - } - - #[instrument(skip(self), fields(blob.digest=%digest))] - async fn open_read(&self, digest: &B3Digest) -> io::Result<Option<Box<dyn BlobReader>>> { - match self.db.get(digest.as_slice()) { - Ok(None) => Ok(None), - Ok(Some(data)) => Ok(Some(Box::new(Cursor::new(data[..].to_vec())))), - Err(e) => Err(io::Error::new(io::ErrorKind::Other, e.to_string())), - } - } - - #[instrument(skip(self))] - async fn open_write(&self) -> Box<dyn BlobWriter> { - Box::new(SledBlobWriter::new(self.db.clone())) - } -} - -pub struct SledBlobWriter { - db: sled::Db, - - /// Contains the buffer Vec and hasher, or None if already closed - writers: Option<(Vec<u8>, blake3::Hasher)>, - - /// The digest that has been returned, if we successfully closed. - digest: Option<B3Digest>, -} - -impl SledBlobWriter { - pub fn new(db: sled::Db) -> Self { - Self { - db, - writers: Some((Vec::new(), blake3::Hasher::new())), - digest: None, - } - } -} - -impl tokio::io::AsyncWrite for SledBlobWriter { - fn poll_write( - mut self: std::pin::Pin<&mut Self>, - _cx: &mut std::task::Context<'_>, - b: &[u8], - ) -> std::task::Poll<Result<usize, io::Error>> { - Poll::Ready(match &mut self.writers { - None => Err(io::Error::new( - io::ErrorKind::NotConnected, - "already closed", - )), - Some((ref mut buf, ref mut hasher)) => { - let bytes_written = buf.write(b)?; - hasher.write(&b[..bytes_written]) - } - }) - } - - fn poll_flush( - mut self: std::pin::Pin<&mut Self>, - _cx: &mut std::task::Context<'_>, - ) -> std::task::Poll<Result<(), io::Error>> { - Poll::Ready(match &mut self.writers { - None => Err(io::Error::new( - io::ErrorKind::NotConnected, - "already closed", - )), - Some(_) => Ok(()), - }) - } - - fn poll_shutdown( - self: std::pin::Pin<&mut Self>, - _cx: &mut std::task::Context<'_>, - ) -> std::task::Poll<Result<(), io::Error>> { - // shutdown is "instantaneous", we only write to a Vec<u8> as buffer. - Poll::Ready(Ok(())) - } -} - -#[async_trait] -impl BlobWriter for SledBlobWriter { - async fn close(&mut self) -> io::Result<B3Digest> { - if self.writers.is_none() { - match &self.digest { - Some(digest) => Ok(digest.clone()), - None => Err(io::Error::new( - io::ErrorKind::NotConnected, - "already closed", - )), - } - } else { - let (buf, hasher) = self.writers.take().unwrap(); - - let digest: B3Digest = hasher.finalize().as_bytes().into(); - - // Only insert if the blob doesn't already exist. - if !self.db.contains_key(digest.as_slice()).map_err(|e| { - Error::StorageError(format!("Unable to check if we have blob {}: {}", digest, e)) - })? { - // put buf in there. This will move buf out. - self.db - .insert(digest.as_slice(), buf) - .map_err(|e| Error::StorageError(format!("unable to insert blob: {}", e)))?; - } - - self.digest = Some(digest.clone()); - - Ok(digest) - } - } -} diff --git a/tvix/castore/src/blobservice/tests/mod.rs b/tvix/castore/src/blobservice/tests/mod.rs index 30c4e97634a4..0280faebb171 100644 --- a/tvix/castore/src/blobservice/tests/mod.rs +++ b/tvix/castore/src/blobservice/tests/mod.rs @@ -25,7 +25,6 @@ use self::utils::make_grpc_blob_service_client; #[case::grpc(make_grpc_blob_service_client().await)] #[case::memory(blobservice::from_addr("memory://").await.unwrap())] #[case::objectstore_memory(blobservice::from_addr("objectstore+memory://").await.unwrap())] -#[case::sled(blobservice::from_addr("sled://").await.unwrap())] pub fn blob_services(#[case] blob_service: impl BlobService) {} /// Using [BlobService::has] on a non-existing blob should return false. diff --git a/tvix/castore/src/blobservice/tests/utils.rs b/tvix/castore/src/blobservice/tests/utils.rs index 706c4b5e4319..7df4f00d3a09 100644 --- a/tvix/castore/src/blobservice/tests/utils.rs +++ b/tvix/castore/src/blobservice/tests/utils.rs @@ -2,6 +2,7 @@ use crate::blobservice::{BlobService, MemoryBlobService}; use crate::proto::blob_service_client::BlobServiceClient; use crate::proto::GRPCBlobServiceWrapper; use crate::{blobservice::GRPCBlobService, proto::blob_service_server::BlobServiceServer}; +use hyper_util::rt::TokioIo; use tonic::transport::{Endpoint, Server, Uri}; /// Constructs and returns a gRPC BlobService. @@ -33,7 +34,7 @@ pub async fn make_grpc_blob_service_client() -> Box<dyn BlobService> { .unwrap() .connect_with_connector(tower::service_fn(move |_: Uri| { let right = maybe_right.take().unwrap(); - async move { Ok::<_, std::io::Error>(right) } + async move { Ok::<_, std::io::Error>(TokioIo::new(right)) } })) .await .unwrap(), diff --git a/tvix/castore/src/composition.rs b/tvix/castore/src/composition.rs new file mode 100644 index 000000000000..b251187e1c34 --- /dev/null +++ b/tvix/castore/src/composition.rs @@ -0,0 +1,581 @@ +//! The composition module allows composing different kinds of services based on a set of service +//! configurations _at runtime_. +//! +//! Store configs are deserialized with serde. The registry provides a stateful mapping from the +//! `type` tag of an internally tagged enum on the serde side to a Config struct which is +//! deserialized and then returned as a `Box<dyn ServiceBuilder<Output = dyn BlobService>>` +//! (the same for DirectoryService instead of BlobService etc). +//! +//! ### Example 1.: Implementing a new BlobService +//! +//! You need a Config struct which implements `DeserializeOwned` and +//! `ServiceBuilder<Output = dyn BlobService>`. +//! Provide the user with a function to call with +//! their registry. You register your new type as: +//! +//! ``` +//! use std::sync::Arc; +//! +//! use tvix_castore::composition::*; +//! use tvix_castore::blobservice::BlobService; +//! +//! #[derive(serde::Deserialize)] +//! struct MyBlobServiceConfig { +//! } +//! +//! #[tonic::async_trait] +//! impl ServiceBuilder for MyBlobServiceConfig { +//! type Output = dyn BlobService; +//! async fn build(&self, _: &str, _: &CompositionContext) -> Result<Arc<Self::Output>, Box<dyn std::error::Error + Send + Sync + 'static>> { +//! todo!() +//! } +//! } +//! +//! impl TryFrom<url::Url> for MyBlobServiceConfig { +//! type Error = Box<dyn std::error::Error + Send + Sync>; +//! fn try_from(url: url::Url) -> Result<Self, Self::Error> { +//! todo!() +//! } +//! } +//! +//! pub fn add_my_service(reg: &mut Registry) { +//! reg.register::<Box<dyn ServiceBuilder<Output = dyn BlobService>>, MyBlobServiceConfig>("myblobservicetype"); +//! } +//! ``` +//! +//! Now, when a user deserializes a store config with the type tag "myblobservicetype" into a +//! `Box<dyn ServiceBuilder<Output = Arc<dyn BlobService>>>`, it will be done via `MyBlobServiceConfig`. +//! +//! ### Example 2.: Composing stores to get one store +//! +//! ``` +//! use std::sync::Arc; +//! use tvix_castore::composition::*; +//! use tvix_castore::blobservice::BlobService; +//! +//! # fn main() -> Result<(), Box<dyn std::error::Error>> { +//! # tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(async move { +//! let blob_services_configs_json = serde_json::json!({ +//! "blobstore1": { +//! "type": "memory" +//! }, +//! "blobstore2": { +//! "type": "memory" +//! }, +//! "default": { +//! "type": "combined", +//! "local": "blobstore1", +//! "remote": "blobstore2" +//! } +//! }); +//! +//! let blob_services_configs = with_registry(®, || serde_json::from_value(blob_services_configs_json))?; +//! let mut blob_service_composition = Composition::new(®); +//! blob_service_composition.extend_with_configs::<dyn BlobService>(blob_services_configs); +//! let blob_service: Arc<dyn BlobService> = blob_service_composition.build("default").await?; +//! # Ok(()) +//! # }) +//! # } +//! ``` +//! +//! ### Example 3.: Creating another registry extending the default registry with third-party types +//! +//! ``` +//! # pub fn add_my_service(reg: &mut tvix_castore::composition::Registry) {} +//! let mut my_registry = tvix_castore::composition::Registry::default(); +//! tvix_castore::composition::add_default_services(&mut my_registry); +//! add_my_service(&mut my_registry); +//! ``` +//! +//! Continue with Example 2, with my_registry instead of REG +//! +//! EXPERIMENTAL: If the xp-store-composition feature is enabled, +//! entrypoints can also be URL strings, which are created as +//! anonymous stores. Instantiations of the same URL will +//! result in a new, distinct anonymous store each time, so creating +//! two `memory://` stores with this method will not share the same view. +//! This behavior might change in the future. + +use erased_serde::deserialize; +use futures::future::BoxFuture; +use futures::FutureExt; +use serde::de::DeserializeOwned; +use serde_tagged::de::{BoxFnSeed, SeedFactory}; +use serde_tagged::util::TagString; +use std::any::{Any, TypeId}; +use std::cell::Cell; +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::marker::PhantomData; +use std::sync::{Arc, LazyLock}; +use tonic::async_trait; + +/// Resolves tag names to the corresponding Config type. +// Registry implementation details: +// This is really ugly. Really we would want to store this as a generic static field: +// +// ``` +// struct Registry<T>(BTreeMap<(&'static str), RegistryEntry<T>); +// static REG<T>: Registry<T>; +// ``` +// +// so that one version of the static is generated for each Type that the registry is accessed for. +// However, this is not possible, because generics are only a thing in functions, and even there +// they will not interact with static items: +// https://doc.rust-lang.org/reference/items/static-items.html#statics--generics +// +// So instead, we make this lookup at runtime by putting the TypeId into the key. +// But now we can no longer store the `BoxFnSeed<T>` because we are lacking the generic parameter +// T, so instead store it as `Box<dyn Any>` and downcast to `&BoxFnSeed<T>` when performing the +// lookup. +// I said it was ugly... +#[derive(Default)] +pub struct Registry(BTreeMap<(TypeId, &'static str), Box<dyn Any + Sync>>); +pub type FromUrlSeed<T> = + Box<dyn Fn(url::Url) -> Result<T, Box<dyn std::error::Error + Send + Sync>> + Sync>; +pub struct RegistryEntry<T> { + serde_deserialize_seed: BoxFnSeed<DeserializeWithRegistry<T>>, + from_url_seed: FromUrlSeed<DeserializeWithRegistry<T>>, +} + +struct RegistryWithFakeType<'r, T>(&'r Registry, PhantomData<T>); + +impl<'r, 'de: 'r, T: 'static> SeedFactory<'de, TagString<'de>> for RegistryWithFakeType<'r, T> { + type Value = DeserializeWithRegistry<T>; + type Seed = &'r BoxFnSeed<Self::Value>; + + // Required method + fn seed<E>(self, tag: TagString<'de>) -> Result<Self::Seed, E> + where + E: serde::de::Error, + { + // using find() and not get() because of https://github.com/rust-lang/rust/issues/80389 + let seed: &Box<dyn Any + Sync> = self + .0 + .0 + .iter() + .find(|(k, _)| *k == &(TypeId::of::<T>(), tag.as_ref())) + .ok_or_else(|| serde::de::Error::custom(format!("Unknown type: {}", tag)))? + .1; + + let entry: &RegistryEntry<T> = <dyn Any>::downcast_ref(&**seed).unwrap(); + + Ok(&entry.serde_deserialize_seed) + } +} + +/// Wrapper type which implements Deserialize using the registry +/// +/// Wrap your type in this in order to deserialize it using a registry, e.g. +/// `RegistryWithFakeType<Box<dyn MyTrait>>`, then the types registered for `Box<dyn MyTrait>` +/// will be used. +pub struct DeserializeWithRegistry<T>(pub T); + +impl Registry { + /// Registers a mapping from type tag to a concrete type into the registry. + /// + /// The type parameters are very important: + /// After calling `register::<Box<dyn FooTrait>, FooStruct>("footype")`, when a user + /// deserializes into an input with the type tag "myblobservicetype" into a + /// `Box<dyn FooTrait>`, it will first call the Deserialize imple of `FooStruct` and + /// then convert it into a `Box<dyn FooTrait>` using From::from. + pub fn register< + T: 'static, + C: DeserializeOwned + + TryFrom<url::Url, Error = Box<dyn std::error::Error + Send + Sync>> + + Into<T>, + >( + &mut self, + type_name: &'static str, + ) { + self.0.insert( + (TypeId::of::<T>(), type_name), + Box::new(RegistryEntry { + serde_deserialize_seed: BoxFnSeed::new(|x| { + deserialize::<C>(x) + .map(Into::into) + .map(DeserializeWithRegistry) + }), + from_url_seed: Box::new(|url| { + C::try_from(url) + .map(Into::into) + .map(DeserializeWithRegistry) + }), + }), + ); + } +} + +impl<'de, T: 'static> serde::Deserialize<'de> for DeserializeWithRegistry<T> { + fn deserialize<D>(de: D) -> std::result::Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + serde_tagged::de::internal::deserialize( + de, + "type", + RegistryWithFakeType(ACTIVE_REG.get().unwrap(), PhantomData::<T>), + ) + } +} + +#[derive(Debug, thiserror::Error)] +enum TryFromUrlError { + #[error("Unknown type: {0}")] + UnknownTag(String), +} + +impl<T: 'static> TryFrom<url::Url> for DeserializeWithRegistry<T> { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + let tag = url.scheme().split('+').next().unwrap(); + // same as in the SeedFactory impl: using find() and not get() because of https://github.com/rust-lang/rust/issues/80389 + let seed = ACTIVE_REG + .get() + .unwrap() + .0 + .iter() + .find(|(k, _)| *k == &(TypeId::of::<T>(), tag)) + .ok_or_else(|| Box::new(TryFromUrlError::UnknownTag(tag.into())))? + .1; + let entry: &RegistryEntry<T> = <dyn Any>::downcast_ref(&**seed).unwrap(); + (entry.from_url_seed)(url) + } +} + +thread_local! { + /// The active Registry is global state, because there is no convenient and universal way to pass state + /// into the functions usually used for deserialization, e.g. `serde_json::from_str`, `toml::from_str`, + /// `serde_qs::from_str`. + static ACTIVE_REG: Cell<Option<&'static Registry>> = panic!("reg was accessed before initialization"); +} + +/// Run the provided closure with a registry context. +/// Any serde deserialize calls within the closure will use the registry to resolve tag names to +/// the corresponding Config type. +pub fn with_registry<R>(reg: &'static Registry, f: impl FnOnce() -> R) -> R { + ACTIVE_REG.set(Some(reg)); + let result = f(); + ACTIVE_REG.set(None); + result +} + +/// The provided registry of tvix_castore, with all builtin BlobStore/DirectoryStore implementations +pub static REG: LazyLock<&'static Registry> = LazyLock::new(|| { + let mut reg = Default::default(); + add_default_services(&mut reg); + // explicitly leak to get an &'static, so that we gain `&Registry: Send` from `Registry: Sync` + Box::leak(Box::new(reg)) +}); + +// ---------- End of generic registry code --------- // + +/// Register the builtin services of tvix_castore with the given registry. +/// This is useful for creating your own registry with the builtin types _and_ +/// extra third party types. +pub fn add_default_services(reg: &mut Registry) { + crate::blobservice::register_blob_services(reg); + crate::directoryservice::register_directory_services(reg); +} + +pub struct CompositionContext<'a> { + // The stack used to detect recursive instantiations and prevent deadlocks + // The TypeId of the trait object is included to distinguish e.g. the + // BlobService "default" and the DirectoryService "default". + stack: Vec<(TypeId, String)>, + registry: &'static Registry, + composition: Option<&'a Composition>, +} + +impl<'a> CompositionContext<'a> { + /// Get a composition context for one-off store creation. + pub fn blank(registry: &'static Registry) -> Self { + Self { + registry, + stack: Default::default(), + composition: None, + } + } + + pub async fn resolve<T: ?Sized + Send + Sync + 'static>( + &self, + entrypoint: String, + ) -> Result<Arc<T>, Box<dyn std::error::Error + Send + Sync + 'static>> { + // disallow recursion + if self + .stack + .contains(&(TypeId::of::<T>(), entrypoint.clone())) + { + return Err(CompositionError::Recursion( + self.stack.iter().map(|(_, n)| n.clone()).collect(), + ) + .into()); + } + + Ok(self.build_internal(entrypoint).await?) + } + + #[cfg(feature = "xp-store-composition")] + async fn build_anonymous<T: ?Sized + Send + Sync + 'static>( + &self, + entrypoint: String, + ) -> Result<Arc<T>, Box<dyn std::error::Error + Send + Sync>> { + let url = url::Url::parse(&entrypoint)?; + let config: DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = T>>> = + with_registry(self.registry, || url.try_into())?; + config.0.build("anonymous", self).await + } + + fn build_internal<T: ?Sized + Send + Sync + 'static>( + &self, + entrypoint: String, + ) -> BoxFuture<'_, Result<Arc<T>, CompositionError>> { + #[cfg(feature = "xp-store-composition")] + if entrypoint.contains("://") { + // There is a chance this is a url. we are building an anonymous store + return Box::pin(async move { + self.build_anonymous(entrypoint.clone()) + .await + .map_err(|e| CompositionError::Failed(entrypoint, Arc::from(e))) + }); + } + + let mut stores = match self.composition { + Some(comp) => comp.stores.lock().unwrap(), + None => return Box::pin(futures::future::err(CompositionError::NotFound(entrypoint))), + }; + let entry = match stores.get_mut(&(TypeId::of::<T>(), entrypoint.clone())) { + Some(v) => v, + None => return Box::pin(futures::future::err(CompositionError::NotFound(entrypoint))), + }; + // for lifetime reasons, we put a placeholder value in the hashmap while we figure out what + // the new value should be. the Mutex stays locked the entire time, so nobody will ever see + // this temporary value. + let prev_val = std::mem::replace( + entry, + Box::new(InstantiationState::<T>::Done(Err( + CompositionError::Poisoned(entrypoint.clone()), + ))), + ); + let (new_val, ret) = match *prev_val.downcast::<InstantiationState<T>>().unwrap() { + InstantiationState::Done(service) => ( + InstantiationState::Done(service.clone()), + futures::future::ready(service).boxed(), + ), + // the construction of the store has not started yet. + InstantiationState::Config(config) => { + let (tx, rx) = tokio::sync::watch::channel(None); + ( + InstantiationState::InProgress(rx), + (async move { + let mut new_context = CompositionContext { + composition: self.composition, + registry: self.registry, + stack: self.stack.clone(), + }; + new_context + .stack + .push((TypeId::of::<T>(), entrypoint.clone())); + let res = + config.build(&entrypoint, &new_context).await.map_err(|e| { + match e.downcast() { + Ok(e) => *e, + Err(e) => CompositionError::Failed(entrypoint, e.into()), + } + }); + tx.send(Some(res.clone())).unwrap(); + res + }) + .boxed(), + ) + } + // there is already a task driving forward the construction of this store, wait for it + // to notify us via the provided channel + InstantiationState::InProgress(mut recv) => { + (InstantiationState::InProgress(recv.clone()), { + (async move { + loop { + if let Some(v) = + recv.borrow_and_update().as_ref().map(|res| res.clone()) + { + break v; + } + recv.changed().await.unwrap(); + } + }) + .boxed() + }) + } + }; + *entry = Box::new(new_val); + ret + } +} + +#[async_trait] +/// This is the trait usually implemented on a per-store-type Config struct and +/// used to instantiate it. +pub trait ServiceBuilder: Send + Sync { + type Output: ?Sized; + async fn build( + &self, + instance_name: &str, + context: &CompositionContext, + ) -> Result<Arc<Self::Output>, Box<dyn std::error::Error + Send + Sync + 'static>>; +} + +impl<T: ?Sized, S: ServiceBuilder<Output = T> + 'static> From<S> + for Box<dyn ServiceBuilder<Output = T>> +{ + fn from(t: S) -> Self { + Box::new(t) + } +} + +enum InstantiationState<T: ?Sized> { + Config(Box<dyn ServiceBuilder<Output = T>>), + InProgress(tokio::sync::watch::Receiver<Option<Result<Arc<T>, CompositionError>>>), + Done(Result<Arc<T>, CompositionError>), +} + +pub struct Composition { + registry: &'static Registry, + stores: std::sync::Mutex<HashMap<(TypeId, String), Box<dyn Any + Send + Sync>>>, +} + +#[derive(thiserror::Error, Clone, Debug)] +pub enum CompositionError { + #[error("store not found: {0}")] + NotFound(String), + #[error("recursion not allowed {0:?}")] + Recursion(Vec<String>), + #[error("store construction panicked {0}")] + Poisoned(String), + #[error("instantiation of service {0} failed: {1}")] + Failed(String, Arc<dyn std::error::Error + Send + Sync>), +} + +impl<T: ?Sized + Send + Sync + 'static> + Extend<( + String, + DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = T>>>, + )> for Composition +{ + fn extend<I>(&mut self, configs: I) + where + I: IntoIterator< + Item = ( + String, + DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = T>>>, + ), + >, + { + self.stores + .lock() + .unwrap() + .extend(configs.into_iter().map(|(k, v)| { + ( + (TypeId::of::<T>(), k), + Box::new(InstantiationState::Config(v.0)) as Box<dyn Any + Send + Sync>, + ) + })) + } +} + +impl Composition { + /// The given registry will be used for creation of anonymous stores during composition + pub fn new(registry: &'static Registry) -> Self { + Self { + registry, + stores: Default::default(), + } + } + + pub fn extend_with_configs<T: ?Sized + Send + Sync + 'static>( + &mut self, + // Keep the concrete `HashMap` type here since it allows for type + // inference of what type is previously being deserialized. + configs: HashMap<String, DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = T>>>>, + ) { + self.extend(configs); + } + + /// Looks up the entrypoint name in the composition and returns an instantiated service. + pub async fn build<T: ?Sized + Send + Sync + 'static>( + &self, + entrypoint: &str, + ) -> Result<Arc<T>, CompositionError> { + self.context().build_internal(entrypoint.to_string()).await + } + + pub fn context(&self) -> CompositionContext { + CompositionContext { + registry: self.registry, + stack: vec![], + composition: Some(self), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::blobservice::BlobService; + use std::sync::Arc; + + /// Test that we return a reference to the same instance of MemoryBlobService (via ptr_eq) + /// when instantiating the same entrypoint twice. By instantiating concurrently, we also + /// test the channels notifying the second consumer when the store has been instantiated. + #[tokio::test] + async fn concurrent() { + let blob_services_configs_json = serde_json::json!({ + "default": { + "type": "memory", + } + }); + + let blob_services_configs = + with_registry(®, || serde_json::from_value(blob_services_configs_json)).unwrap(); + let mut blob_service_composition = Composition::new(®); + blob_service_composition.extend_with_configs::<dyn BlobService>(blob_services_configs); + let (blob_service1, blob_service2) = tokio::join!( + blob_service_composition.build::<dyn BlobService>("default"), + blob_service_composition.build::<dyn BlobService>("default") + ); + assert!(Arc::ptr_eq( + &blob_service1.unwrap(), + &blob_service2.unwrap() + )); + } + + /// Test that we throw the correct error when an instantiation would recurse (deadlock) + #[tokio::test] + async fn reject_recursion() { + let blob_services_configs_json = serde_json::json!({ + "default": { + "type": "combined", + "local": "other", + "remote": "other" + }, + "other": { + "type": "combined", + "local": "default", + "remote": "default" + } + }); + + let blob_services_configs = + with_registry(®, || serde_json::from_value(blob_services_configs_json)).unwrap(); + let mut blob_service_composition = Composition::new(®); + blob_service_composition.extend_with_configs::<dyn BlobService>(blob_services_configs); + match blob_service_composition + .build::<dyn BlobService>("default") + .await + { + Err(CompositionError::Recursion(stack)) => { + assert_eq!(stack, vec!["default".to_string(), "other".to_string()]) + } + other => panic!("should have returned an error, returned: {:?}", other.err()), + } + } +} diff --git a/tvix/castore/src/digests.rs b/tvix/castore/src/digests.rs index 2311c95c4ddc..4d919ff0d873 100644 --- a/tvix/castore/src/digests.rs +++ b/tvix/castore/src/digests.rs @@ -6,7 +6,7 @@ use thiserror::Error; pub struct B3Digest(Bytes); // TODO: allow converting these errors to crate::Error -#[derive(Error, Debug)] +#[derive(Error, Debug, PartialEq)] pub enum Error { #[error("invalid digest length: {0}")] InvalidDigestLen(usize), @@ -26,6 +26,11 @@ impl From<B3Digest> for bytes::Bytes { } } +impl From<blake3::Hash> for B3Digest { + fn from(value: blake3::Hash) -> Self { + Self(Bytes::copy_from_slice(value.as_bytes())) + } +} impl From<digest::Output<blake3::Hasher>> for B3Digest { fn from(value: digest::Output<blake3::Hasher>) -> Self { let v = Into::<[u8; B3_LEN]>::into(value); @@ -67,6 +72,12 @@ impl From<&[u8; B3_LEN]> for B3Digest { } } +impl From<B3Digest> for [u8; B3_LEN] { + fn from(value: B3Digest) -> Self { + value.0.to_vec().try_into().unwrap() + } +} + impl Clone for B3Digest { fn clone(&self) -> Self { Self(self.0.to_owned()) diff --git a/tvix/castore/src/directoryservice/bigtable.rs b/tvix/castore/src/directoryservice/bigtable.rs index 0fdb24628f83..73ab4342d832 100644 --- a/tvix/castore/src/directoryservice/bigtable.rs +++ b/tvix/castore/src/directoryservice/bigtable.rs @@ -5,10 +5,14 @@ use futures::stream::BoxStream; use prost::Message; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DurationSeconds}; +use std::sync::Arc; use tonic::async_trait; use tracing::{instrument, trace, warn}; -use super::{utils::traverse_directory, DirectoryPutter, DirectoryService, SimplePutter}; +use super::{ + utils::traverse_directory, Directory, DirectoryPutter, DirectoryService, SimplePutter, +}; +use crate::composition::{CompositionContext, ServiceBuilder}; use crate::{proto, B3Digest, Error}; /// There should not be more than 10 MiB in a single cell. @@ -43,41 +47,6 @@ pub struct BigtableDirectoryService { emulator: std::sync::Arc<(tempfile::TempDir, async_process::Child)>, } -/// Represents configuration of [BigtableDirectoryService]. -/// This currently conflates both connect parameters and data model/client -/// behaviour parameters. -#[serde_as] -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct BigtableParameters { - project_id: String, - instance_name: String, - #[serde(default)] - is_read_only: bool, - #[serde(default = "default_channel_size")] - channel_size: usize, - - #[serde_as(as = "Option<DurationSeconds<String>>")] - #[serde(default = "default_timeout")] - timeout: Option<std::time::Duration>, - table_name: String, - family_name: String, - - #[serde(default = "default_app_profile_id")] - app_profile_id: String, -} - -fn default_app_profile_id() -> String { - "default".to_owned() -} - -fn default_channel_size() -> usize { - 4 -} - -fn default_timeout() -> Option<std::time::Duration> { - Some(std::time::Duration::from_secs(4)) -} - impl BigtableDirectoryService { #[cfg(not(test))] pub async fn connect(params: BigtableParameters) -> Result<Self, bigtable::Error> { @@ -182,7 +151,7 @@ fn derive_directory_key(digest: &B3Digest) -> String { #[async_trait] impl DirectoryService for BigtableDirectoryService { #[instrument(skip(self, digest), err, fields(directory.digest = %digest))] - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error> { + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { let mut client = self.client.clone(); let directory_key = derive_directory_key(digest); @@ -274,28 +243,20 @@ impl DirectoryService for BigtableDirectoryService { // Try to parse the value into a Directory message. let directory = proto::Directory::decode(Bytes::from(row_cell.value)) - .map_err(|e| Error::StorageError(format!("unable to decode directory proto: {}", e)))?; - - // validate the Directory. - directory - .validate() + .map_err(|e| Error::StorageError(format!("unable to decode directory proto: {}", e)))? + .try_into() .map_err(|e| Error::StorageError(format!("invalid Directory message: {}", e)))?; Ok(Some(directory)) } #[instrument(skip(self, directory), err, fields(directory.digest = %directory.digest()))] - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error> { + async fn put(&self, directory: Directory) -> Result<B3Digest, Error> { let directory_digest = directory.digest(); let mut client = self.client.clone(); let directory_key = derive_directory_key(&directory_digest); - // Ensure the directory we're trying to upload passes validation - directory - .validate() - .map_err(|e| Error::InvalidRequest(format!("directory is invalid: {}", e)))?; - - let data = directory.encode_to_vec(); + let data = proto::Directory::from(directory).encode_to_vec(); if data.len() as u64 > CELL_SIZE_LIMIT { return Err(Error::StorageError( "Directory exceeds cell limit on Bigtable".into(), @@ -343,7 +304,7 @@ impl DirectoryService for BigtableDirectoryService { fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<Result<proto::Directory, Error>> { + ) -> BoxStream<'static, Result<Directory, Error>> { traverse_directory(self.clone(), root_directory_digest) } @@ -355,3 +316,73 @@ impl DirectoryService for BigtableDirectoryService { Box::new(SimplePutter::new(self.clone())) } } + +/// Represents configuration of [BigtableDirectoryService]. +/// This currently conflates both connect parameters and data model/client +/// behaviour parameters. +#[serde_as] +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[serde(deny_unknown_fields)] +pub struct BigtableParameters { + project_id: String, + instance_name: String, + #[serde(default)] + is_read_only: bool, + #[serde(default = "default_channel_size")] + channel_size: usize, + + #[serde_as(as = "Option<DurationSeconds<String>>")] + #[serde(default = "default_timeout")] + timeout: Option<std::time::Duration>, + table_name: String, + family_name: String, + + #[serde(default = "default_app_profile_id")] + app_profile_id: String, +} + +#[async_trait] +impl ServiceBuilder for BigtableParameters { + type Output = dyn DirectoryService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn DirectoryService>, Box<dyn std::error::Error + Send + Sync>> { + Ok(Arc::new( + BigtableDirectoryService::connect(self.clone()).await?, + )) + } +} + +impl TryFrom<url::Url> for BigtableParameters { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(mut url: url::Url) -> Result<Self, Self::Error> { + // parse the instance name from the hostname. + let instance_name = url + .host_str() + .ok_or_else(|| Error::StorageError("instance name missing".into()))? + .to_string(); + + // … but add it to the query string now, so we just need to parse that. + url.query_pairs_mut() + .append_pair("instance_name", &instance_name); + + let params: BigtableParameters = serde_qs::from_str(url.query().unwrap_or_default()) + .map_err(|e| Error::InvalidRequest(format!("failed to parse parameters: {}", e)))?; + + Ok(params) + } +} + +fn default_app_profile_id() -> String { + "default".to_owned() +} + +fn default_channel_size() -> usize { + 4 +} + +fn default_timeout() -> Option<std::time::Duration> { + Some(std::time::Duration::from_secs(4)) +} diff --git a/tvix/castore/src/directoryservice/closure_validator.rs b/tvix/castore/src/directoryservice/closure_validator.rs deleted file mode 100644 index 183928a86fad..000000000000 --- a/tvix/castore/src/directoryservice/closure_validator.rs +++ /dev/null @@ -1,268 +0,0 @@ -use std::collections::{HashMap, HashSet}; - -use bstr::ByteSlice; - -use petgraph::{ - graph::{DiGraph, NodeIndex}, - visit::Bfs, -}; -use tracing::instrument; - -use crate::{ - proto::{self, Directory}, - B3Digest, Error, -}; - -/// This can be used to validate a Directory closure (DAG of connected -/// Directories), and their insertion order. -/// -/// Directories need to be inserted (via `add`), in an order from the leaves to -/// the root (DFS Post-Order). -/// During insertion, We validate as much as we can at that time: -/// -/// - individual validation of Directory messages -/// - validation of insertion order (no upload of not-yet-known Directories) -/// - validation of size fields of referred Directories -/// -/// Internally it keeps all received Directories in a directed graph, -/// with node weights being the Directories and edges pointing to child -/// directories. -/// -/// Once all Directories have been inserted, a finalize function can be -/// called to get a (deduplicated and) validated list of directories, in -/// insertion order. -/// During finalize, a check for graph connectivity is performed too, to ensure -/// there's no disconnected components, and only one root. -#[derive(Default)] -pub struct ClosureValidator { - // A directed graph, using Directory as node weight, without edge weights. - // Edges point from parents to children. - graph: DiGraph<Directory, ()>, - - // A lookup table from directory digest to node index. - digest_to_node_ix: HashMap<B3Digest, NodeIndex>, - - /// Keeps track of the last-inserted directory graph node index. - /// On a correct insert, this will be the root node, from which the DFS post - /// order traversal will start from. - last_directory_ix: Option<NodeIndex>, -} - -impl ClosureValidator { - /// Insert a new Directory into the closure. - /// Perform individual Directory validation, validation of insertion order - /// and size fields. - #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest(), directory.size=%directory.size()), err)] - pub fn add(&mut self, directory: proto::Directory) -> Result<(), Error> { - let digest = directory.digest(); - - // If we already saw this node previously, it's already validated and in the graph. - if self.digest_to_node_ix.contains_key(&digest) { - return Ok(()); - } - - // Do some general validation - directory - .validate() - .map_err(|e| Error::InvalidRequest(e.to_string()))?; - - // Ensure the directory only refers to directories which we already accepted. - // We lookup their node indices and add them to a HashSet. - let mut child_ixs = HashSet::new(); - for dir in &directory.directories { - let child_digest = B3Digest::try_from(dir.digest.to_owned()).unwrap(); // validated - - // Ensure the digest has already been seen - let child_ix = *self.digest_to_node_ix.get(&child_digest).ok_or_else(|| { - Error::InvalidRequest(format!( - "'{}' refers to unseen child dir: {}", - dir.name.as_bstr(), - &child_digest - )) - })?; - - // Ensure the size specified in the child node matches the directory size itself. - let recorded_child_size = self - .graph - .node_weight(child_ix) - .expect("node not found") - .size(); - - // Ensure the size specified in the child node matches our records. - if dir.size != recorded_child_size { - return Err(Error::InvalidRequest(format!( - "'{}' has wrong size, specified {}, recorded {}", - dir.name.as_bstr(), - dir.size, - recorded_child_size - ))); - } - - child_ixs.insert(child_ix); - } - - // Insert node into the graph, and add edges to all children. - let node_ix = self.graph.add_node(directory); - for child_ix in child_ixs { - self.graph.add_edge(node_ix, child_ix, ()); - } - - // Record the mapping from digest to node_ix in our lookup table. - self.digest_to_node_ix.insert(digest, node_ix); - - // Update last_directory_ix. - self.last_directory_ix = Some(node_ix); - - Ok(()) - } - - /// Ensure that all inserted Directories are connected, then return a - /// (deduplicated) and validated list of directories, in from-leaves-to-root - /// order. - /// In case no elements have been inserted, returns an empty list. - #[instrument(level = "trace", skip_all, err)] - pub(crate) fn finalize(self) -> Result<Vec<Directory>, Error> { - // If no nodes were inserted, an empty list is returned. - let last_directory_ix = if let Some(x) = self.last_directory_ix { - x - } else { - return Ok(vec![]); - }; - - // do a BFS traversal of the graph, starting with the root node to get - // (the count of) all nodes reachable from there. - let mut traversal = Bfs::new(&self.graph, last_directory_ix); - - let mut visited_directory_count = 0; - #[cfg(debug_assertions)] - let mut visited_directory_ixs = HashSet::new(); - #[cfg_attr(not(debug_assertions), allow(unused))] - while let Some(directory_ix) = traversal.next(&self.graph) { - #[cfg(debug_assertions)] - visited_directory_ixs.insert(directory_ix); - - visited_directory_count += 1; - } - - // If the number of nodes collected equals the total number of nodes in - // the graph, we know all nodes are connected. - if visited_directory_count != self.graph.node_count() { - // more or less exhaustive error reporting. - #[cfg(debug_assertions)] - { - let all_directory_ixs: HashSet<_> = self.graph.node_indices().collect(); - - let unvisited_directories: HashSet<_> = all_directory_ixs - .difference(&visited_directory_ixs) - .map(|ix| self.graph.node_weight(*ix).expect("node not found")) - .collect(); - - return Err(Error::InvalidRequest(format!( - "found {} disconnected directories: {:?}", - self.graph.node_count() - visited_directory_ixs.len(), - unvisited_directories - ))); - } - #[cfg(not(debug_assertions))] - { - return Err(Error::InvalidRequest(format!( - "found {} disconnected directories", - self.graph.node_count() - visited_directory_count - ))); - } - } - - // Dissolve the graph, returning the nodes as a Vec. - // As the graph was populated in a valid DFS PostOrder, we can return - // nodes in that same order. - let (nodes, _edges) = self.graph.into_nodes_edges(); - Ok(nodes.into_iter().map(|x| x.weight).collect()) - } -} - -#[cfg(test)] -mod tests { - use crate::{ - fixtures::{DIRECTORY_A, DIRECTORY_B, DIRECTORY_C}, - proto::{self, Directory}, - }; - use lazy_static::lazy_static; - use rstest::rstest; - - lazy_static! { - pub static ref BROKEN_DIRECTORY : Directory = Directory { - symlinks: vec![proto::SymlinkNode { - name: "".into(), // invalid name! - target: "doesntmatter".into(), - }], - ..Default::default() - }; - - pub static ref BROKEN_PARENT_DIRECTORY: Directory = Directory { - directories: vec![proto::DirectoryNode { - name: "foo".into(), - digest: DIRECTORY_A.digest().into(), - size: DIRECTORY_A.size() + 42, // wrong! - }], - ..Default::default() - }; - } - - use super::ClosureValidator; - - #[rstest] - /// Uploading an empty directory should succeed. - #[case::empty_directory(&[&*DIRECTORY_A], false, Some(vec![&*DIRECTORY_A]))] - /// Uploading A, then B (referring to A) should succeed. - #[case::simple_closure(&[&*DIRECTORY_A, &*DIRECTORY_B], false, Some(vec![&*DIRECTORY_A, &*DIRECTORY_B]))] - /// Uploading A, then A, then C (referring to A twice) should succeed. - /// We pretend to be a dumb client not deduping directories. - #[case::same_child(&[&*DIRECTORY_A, &*DIRECTORY_A, &*DIRECTORY_C], false, Some(vec![&*DIRECTORY_A, &*DIRECTORY_C]))] - /// Uploading A, then C (referring to A twice) should succeed. - #[case::same_child_dedup(&[&*DIRECTORY_A, &*DIRECTORY_C], false, Some(vec![&*DIRECTORY_A, &*DIRECTORY_C]))] - /// Uploading A, then C (referring to A twice), then B (itself referring to A) should fail during close, - /// as B itself would be left unconnected. - #[case::unconnected_node(&[&*DIRECTORY_A, &*DIRECTORY_C, &*DIRECTORY_B], false, None)] - /// Uploading B (referring to A) should fail immediately, because A was never uploaded. - #[case::dangling_pointer(&[&*DIRECTORY_B], true, None)] - /// Uploading a directory failing validation should fail immediately. - #[case::failing_validation(&[&*BROKEN_DIRECTORY], true, None)] - /// Uploading a directory which refers to another Directory with a wrong size should fail. - #[case::wrong_size_in_parent(&[&*DIRECTORY_A, &*BROKEN_PARENT_DIRECTORY], true, None)] - fn test_uploads( - #[case] directories_to_upload: &[&Directory], - #[case] exp_fail_upload_last: bool, - #[case] exp_finalize: Option<Vec<&Directory>>, // Some(_) if finalize successful, None if not. - ) { - let mut dcv = ClosureValidator::default(); - let len_directories_to_upload = directories_to_upload.len(); - - for (i, d) in directories_to_upload.iter().enumerate() { - let resp = dcv.add((*d).clone()); - if i == len_directories_to_upload - 1 && exp_fail_upload_last { - assert!(resp.is_err(), "expect last put to fail"); - - // We don't really care anymore what finalize() would return, as - // the add() failed. - return; - } else { - assert!(resp.is_ok(), "expect put to succeed"); - } - } - - // everything was uploaded successfully. Test finalize(). - let resp = dcv.finalize(); - - match exp_finalize { - Some(directories) => { - assert_eq!( - Vec::from_iter(directories.iter().map(|e| (*e).to_owned())), - resp.expect("drain should succeed") - ); - } - None => { - resp.expect_err("drain should fail"); - } - } - } -} diff --git a/tvix/castore/src/directoryservice/combinators.rs b/tvix/castore/src/directoryservice/combinators.rs new file mode 100644 index 000000000000..4dfc19540c47 --- /dev/null +++ b/tvix/castore/src/directoryservice/combinators.rs @@ -0,0 +1,181 @@ +use std::sync::Arc; + +use futures::stream::BoxStream; +use futures::StreamExt; +use futures::TryFutureExt; +use futures::TryStreamExt; +use tonic::async_trait; +use tracing::{instrument, trace}; + +use super::{Directory, DirectoryGraph, DirectoryService, RootToLeavesValidator, SimplePutter}; +use crate::composition::{CompositionContext, ServiceBuilder}; +use crate::directoryservice::DirectoryPutter; +use crate::B3Digest; +use crate::Error; + +/// Asks near first, if not found, asks far. +/// If found in there, returns it, and *inserts* it into +/// near. +/// Specifically, it always obtains the entire directory closure from far and inserts it into near, +/// which is useful when far does not support accessing intermediate directories (but near does). +/// There is no negative cache. +/// Inserts and listings are not implemented for now. +#[derive(Clone)] +pub struct Cache<DS1, DS2> { + near: DS1, + far: DS2, +} + +impl<DS1, DS2> Cache<DS1, DS2> { + pub fn new(near: DS1, far: DS2) -> Self { + Self { near, far } + } +} + +#[async_trait] +impl<DS1, DS2> DirectoryService for Cache<DS1, DS2> +where + DS1: DirectoryService + Clone + 'static, + DS2: DirectoryService + Clone + 'static, +{ + #[instrument(skip(self, digest), fields(directory.digest = %digest))] + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { + match self.near.get(digest).await? { + Some(directory) => { + trace!("serving from cache"); + Ok(Some(directory)) + } + None => { + trace!("not found in near, asking remote…"); + + let mut copy = DirectoryGraph::with_order( + RootToLeavesValidator::new_with_root_digest(digest.clone()), + ); + + let mut stream = self.far.get_recursive(digest); + let root = stream.try_next().await?; + + if let Some(root) = root.clone() { + copy.add(root) + .map_err(|e| Error::StorageError(e.to_string()))?; + } + + while let Some(dir) = stream.try_next().await? { + copy.add(dir) + .map_err(|e| Error::StorageError(e.to_string()))?; + } + + let copy = copy + .validate() + .map_err(|e| Error::StorageError(e.to_string()))?; + + let mut put = self.near.put_multiple_start(); + for dir in copy.drain_leaves_to_root() { + put.put(dir).await?; + } + put.close().await?; + + Ok(root) + } + } + } + + #[instrument(skip_all)] + async fn put(&self, _directory: Directory) -> Result<B3Digest, Error> { + Err(Error::StorageError("unimplemented".to_string())) + } + + #[instrument(skip_all, fields(directory.digest = %root_directory_digest))] + fn get_recursive( + &self, + root_directory_digest: &B3Digest, + ) -> BoxStream<'static, Result<Directory, Error>> { + let near = self.near.clone(); + let far = self.far.clone(); + let digest = root_directory_digest.clone(); + Box::pin( + (async move { + let mut stream = near.get_recursive(&digest); + match stream.try_next().await? { + Some(first) => { + trace!("serving from cache"); + Ok(futures::stream::once(async { Ok(first) }) + .chain(stream) + .left_stream()) + } + None => { + trace!("not found in near, asking remote…"); + + let mut copy_for_near = DirectoryGraph::with_order( + RootToLeavesValidator::new_with_root_digest(digest.clone()), + ); + let mut copy_for_client = vec![]; + + let mut stream = far.get_recursive(&digest); + while let Some(dir) = stream.try_next().await? { + copy_for_near + .add(dir.clone()) + .map_err(|e| Error::StorageError(e.to_string()))?; + copy_for_client.push(dir); + } + + let copy_for_near = copy_for_near + .validate() + .map_err(|e| Error::StorageError(e.to_string()))?; + let mut put = near.put_multiple_start(); + for dir in copy_for_near.drain_leaves_to_root() { + put.put(dir).await?; + } + put.close().await?; + + Ok(futures::stream::iter(copy_for_client.into_iter().map(Ok)) + .right_stream()) + } + } + }) + .try_flatten_stream(), + ) + } + + #[instrument(skip_all)] + fn put_multiple_start(&self) -> Box<(dyn DirectoryPutter + 'static)> { + Box::new(SimplePutter::new((*self).clone())) + } +} + +#[derive(serde::Deserialize, Debug)] +#[serde(deny_unknown_fields)] +pub struct CacheConfig { + near: String, + far: String, +} + +impl TryFrom<url::Url> for CacheConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + // cache doesn't support host or path in the URL. + if url.has_host() || !url.path().is_empty() { + return Err(Error::StorageError("invalid url".to_string()).into()); + } + Ok(serde_qs::from_str(url.query().unwrap_or_default())?) + } +} + +#[async_trait] +impl ServiceBuilder for CacheConfig { + type Output = dyn DirectoryService; + async fn build<'a>( + &'a self, + _instance_name: &str, + context: &CompositionContext, + ) -> Result<Arc<dyn DirectoryService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + let (near, far) = futures::join!( + context.resolve::<Self::Output>(self.near.clone()), + context.resolve::<Self::Output>(self.far.clone()) + ); + Ok(Arc::new(Cache { + near: near?, + far: far?, + })) + } +} diff --git a/tvix/castore/src/directoryservice/directory_graph.rs b/tvix/castore/src/directoryservice/directory_graph.rs new file mode 100644 index 000000000000..54f3cb3e9353 --- /dev/null +++ b/tvix/castore/src/directoryservice/directory_graph.rs @@ -0,0 +1,404 @@ +use std::collections::HashMap; + +use petgraph::{ + graph::{DiGraph, NodeIndex}, + visit::{Bfs, DfsPostOrder, EdgeRef, IntoNodeIdentifiers, Walker}, + Direction, Incoming, +}; +use tracing::instrument; + +use super::order_validator::{LeavesToRootValidator, OrderValidator, RootToLeavesValidator}; +use crate::{path::PathComponent, B3Digest, Directory, Node}; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("{0}")] + ValidationError(String), +} + +struct EdgeWeight { + name: PathComponent, + size: u64, +} + +/// This can be used to validate and/or re-order a Directory closure (DAG of +/// connected Directories), and their insertion order. +/// +/// The DirectoryGraph is parametrized on the insertion order, and can be +/// constructed using the Default trait, or using `with_order` if the +/// OrderValidator needs to be customized. +/// +/// If the user is receiving directories from canonical protobuf encoding in +/// root-to-leaves order, and parsing them, she can call `digest_allowed` +/// _before_ parsing the protobuf record and then add it with `add_unchecked`. +/// All other users insert the directories via `add`, in their specified order. +/// During insertion, we validate as much as we can at that time: +/// +/// - individual validation of Directory messages +/// - validation of insertion order +/// - validation of size fields of referred Directories +/// +/// Internally it keeps all received Directories in a directed graph, +/// with node weights being the Directories and edges pointing to child/parent +/// directories. +/// +/// Once all Directories have been inserted, a validate function can be +/// called to perform a check for graph connectivity and ensure there's no +/// disconnected components or missing nodes. +/// Finally, the `drain_leaves_to_root` or `drain_root_to_leaves` can be +/// _chained_ on validate to get an iterator over the (deduplicated and) +/// validated list of directories in either order. +#[derive(Default)] +pub struct DirectoryGraph<O> { + // A directed graph, using Directory as node weight. + // Edges point from parents to children. + // + // Nodes with None weigths might exist when a digest has been referred to but the directory + // with this digest has not yet been sent. + // + // The option in the edge weight tracks the pending validation state of the respective edge, for example if + // the child has not been added yet. + graph: DiGraph<Option<Directory>, Option<EdgeWeight>>, + + // A lookup table from directory digest to node index. + digest_to_node_ix: HashMap<B3Digest, NodeIndex>, + + order_validator: O, +} + +pub struct ValidatedDirectoryGraph { + graph: DiGraph<Option<Directory>, Option<EdgeWeight>>, + + root: Option<NodeIndex>, +} + +fn check_edge(edge: &EdgeWeight, child: &Directory) -> Result<(), Error> { + // Ensure the size specified in the child node matches our records. + if edge.size != child.size() { + return Err(Error::ValidationError(format!( + "'{}' has wrong size, specified {}, recorded {}", + edge.name, + edge.size, + child.size(), + ))); + } + Ok(()) +} + +impl DirectoryGraph<LeavesToRootValidator> { + /// Insert a new Directory into the closure + #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest(), directory.size=%directory.size()), err)] + pub fn add(&mut self, directory: Directory) -> Result<(), Error> { + if !self.order_validator.add_directory(&directory) { + return Err(Error::ValidationError( + "unknown directory was referenced".into(), + )); + } + self.add_order_unchecked(directory) + } +} + +impl DirectoryGraph<RootToLeavesValidator> { + /// If the user is parsing directories from canonical protobuf encoding, she can + /// call `digest_allowed` _before_ parsing the protobuf record and then add it + /// with `add_unchecked`. + pub fn digest_allowed(&self, digest: B3Digest) -> bool { + self.order_validator.digest_allowed(&digest) + } + + /// Insert a new Directory into the closure + #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest(), directory.size=%directory.size()), err)] + pub fn add(&mut self, directory: Directory) -> Result<(), Error> { + let digest = directory.digest(); + if !self.order_validator.digest_allowed(&digest) { + return Err(Error::ValidationError("unexpected digest".into())); + } + self.order_validator.add_directory_unchecked(&directory); + self.add_order_unchecked(directory) + } +} + +impl<O: OrderValidator> DirectoryGraph<O> { + /// Customize the ordering, i.e. for pre-setting the root of the RootToLeavesValidator + pub fn with_order(order_validator: O) -> Self { + Self { + graph: Default::default(), + digest_to_node_ix: Default::default(), + order_validator, + } + } + + /// Adds a directory which has already been confirmed to be in-order to the graph + pub fn add_order_unchecked(&mut self, directory: Directory) -> Result<(), Error> { + let digest = directory.digest(); + + // Teach the graph about the existence of a node with this digest + let ix = *self + .digest_to_node_ix + .entry(digest) + .or_insert_with(|| self.graph.add_node(None)); + + if self.graph[ix].is_some() { + // The node is already in the graph, there is nothing to do here. + return Ok(()); + } + + // set up edges to all child directories + for (name, node) in directory.nodes() { + if let Node::Directory { digest, size } = node { + let child_ix = *self + .digest_to_node_ix + .entry(digest.clone()) + .or_insert_with(|| self.graph.add_node(None)); + + let pending_edge_check = match &self.graph[child_ix] { + Some(child) => { + // child is already available, validate the edge now + check_edge( + &EdgeWeight { + name: name.clone(), + size: *size, + }, + child, + )?; + None + } + None => Some(EdgeWeight { + name: name.clone(), + size: *size, + }), // pending validation + }; + self.graph.add_edge(ix, child_ix, pending_edge_check); + } + } + + // validate the edges from parents to this node + // this collects edge ids in a Vec because there is no edges_directed_mut :'c + for edge_id in self + .graph + .edges_directed(ix, Direction::Incoming) + .map(|edge_ref| edge_ref.id()) + .collect::<Vec<_>>() + .into_iter() + { + let edge_weight = self + .graph + .edge_weight_mut(edge_id) + .expect("edge not found") + .take() + .expect("edge is already validated"); + + check_edge(&edge_weight, &directory)?; + } + + // finally, store the directory information in the node weight + self.graph[ix] = Some(directory); + + Ok(()) + } + + #[instrument(level = "trace", skip_all, err)] + pub fn validate(self) -> Result<ValidatedDirectoryGraph, Error> { + // find all initial nodes (nodes without incoming edges) + let mut roots = self + .graph + .node_identifiers() + .filter(|&a| self.graph.neighbors_directed(a, Incoming).next().is_none()); + + let root = roots.next(); + if roots.next().is_some() { + return Err(Error::ValidationError( + "graph has disconnected roots".into(), + )); + } + + // test that the graph is complete + if self.graph.raw_nodes().iter().any(|n| n.weight.is_none()) { + return Err(Error::ValidationError("graph is incomplete".into())); + } + + Ok(ValidatedDirectoryGraph { + graph: self.graph, + root, + }) + } +} + +impl ValidatedDirectoryGraph { + /// Return the list of directories in from-root-to-leaves order. + /// In case no elements have been inserted, returns an empty list. + /// + /// panics if the specified root is not in the graph + #[instrument(level = "trace", skip_all)] + pub fn drain_root_to_leaves(self) -> impl Iterator<Item = Directory> { + let order = match self.root { + Some(root) => { + // do a BFS traversal of the graph, starting with the root node + Bfs::new(&self.graph, root) + .iter(&self.graph) + .collect::<Vec<_>>() + } + None => vec![], // No nodes have been inserted, do not traverse + }; + + let (mut nodes, _edges) = self.graph.into_nodes_edges(); + + order + .into_iter() + .filter_map(move |i| nodes[i.index()].weight.take()) + } + + /// Return the list of directories in from-leaves-to-root order. + /// In case no elements have been inserted, returns an empty list. + /// + /// panics when the specified root is not in the graph + #[instrument(level = "trace", skip_all)] + pub fn drain_leaves_to_root(self) -> impl Iterator<Item = Directory> { + let order = match self.root { + Some(root) => { + // do a DFS Post-Order traversal of the graph, starting with the root node + DfsPostOrder::new(&self.graph, root) + .iter(&self.graph) + .collect::<Vec<_>>() + } + None => vec![], // No nodes have been inserted, do not traverse + }; + + let (mut nodes, _edges) = self.graph.into_nodes_edges(); + + order + .into_iter() + .filter_map(move |i| nodes[i.index()].weight.take()) + } +} + +#[cfg(test)] +mod tests { + use crate::fixtures::{DIRECTORY_A, DIRECTORY_B, DIRECTORY_C}; + use crate::{Directory, Node}; + use rstest::rstest; + use std::sync::LazyLock; + + use super::{DirectoryGraph, LeavesToRootValidator, RootToLeavesValidator}; + + pub static BROKEN_PARENT_DIRECTORY: LazyLock<Directory> = LazyLock::new(|| { + Directory::try_from_iter([( + "foo".try_into().unwrap(), + Node::Directory { + digest: DIRECTORY_A.digest(), + size: DIRECTORY_A.size() + 42, // wrong! + }, + )]) + .unwrap() + }); + + #[rstest] + /// Uploading an empty directory should succeed. + #[case::empty_directory(&[&*DIRECTORY_A], false, Some(vec![&*DIRECTORY_A]))] + /// Uploading A, then B (referring to A) should succeed. + #[case::simple_closure(&[&*DIRECTORY_A, &*DIRECTORY_B], false, Some(vec![&*DIRECTORY_A, &*DIRECTORY_B]))] + /// Uploading A, then A, then C (referring to A twice) should succeed. + /// We pretend to be a dumb client not deduping directories. + #[case::same_child(&[&*DIRECTORY_A, &*DIRECTORY_A, &*DIRECTORY_C], false, Some(vec![&*DIRECTORY_A, &*DIRECTORY_C]))] + /// Uploading A, then C (referring to A twice) should succeed. + #[case::same_child_dedup(&[&*DIRECTORY_A, &*DIRECTORY_C], false, Some(vec![&*DIRECTORY_A, &*DIRECTORY_C]))] + /// Uploading A, then C (referring to A twice), then B (itself referring to A) should fail during close, + /// as B itself would be left unconnected. + #[case::unconnected_node(&[&*DIRECTORY_A, &*DIRECTORY_C, &*DIRECTORY_B], false, None)] + /// Uploading B (referring to A) should fail immediately, because A was never uploaded. + #[case::dangling_pointer(&[&*DIRECTORY_B], true, None)] + /// Uploading a directory which refers to another Directory with a wrong size should fail. + #[case::wrong_size_in_parent(&[&*DIRECTORY_A, &*BROKEN_PARENT_DIRECTORY], true, None)] + fn test_uploads( + #[case] directories_to_upload: &[&Directory], + #[case] exp_fail_upload_last: bool, + #[case] exp_finalize: Option<Vec<&Directory>>, // Some(_) if finalize successful, None if not. + ) { + let mut dcv = DirectoryGraph::<LeavesToRootValidator>::default(); + let len_directories_to_upload = directories_to_upload.len(); + + for (i, d) in directories_to_upload.iter().enumerate() { + let resp = dcv.add((*d).clone()); + if i == len_directories_to_upload - 1 && exp_fail_upload_last { + assert!(resp.is_err(), "expect last put to fail"); + + // We don't really care anymore what finalize() would return, as + // the add() failed. + return; + } else { + assert!(resp.is_ok(), "expect put to succeed"); + } + } + + // everything was uploaded successfully. Test finalize(). + let resp = dcv + .validate() + .map(|validated| validated.drain_leaves_to_root().collect::<Vec<_>>()); + + match exp_finalize { + Some(directories) => { + assert_eq!( + Vec::from_iter(directories.iter().map(|e| (*e).to_owned())), + resp.expect("drain should succeed") + ); + } + None => { + resp.expect_err("drain should fail"); + } + } + } + + #[rstest] + /// Downloading an empty directory should succeed. + #[case::empty_directory(&*DIRECTORY_A, &[&*DIRECTORY_A], false, Some(vec![&*DIRECTORY_A]))] + /// Downlading B, then A (referenced by B) should succeed. + #[case::simple_closure(&*DIRECTORY_B, &[&*DIRECTORY_B, &*DIRECTORY_A], false, Some(vec![&*DIRECTORY_A, &*DIRECTORY_B]))] + /// Downloading C (referring to A twice), then A should succeed. + #[case::same_child_dedup(&*DIRECTORY_C, &[&*DIRECTORY_C, &*DIRECTORY_A], false, Some(vec![&*DIRECTORY_A, &*DIRECTORY_C]))] + /// Downloading C, then B (both referring to A but not referring to each other) should fail immediately as B has no connection to C (the root) + #[case::unconnected_node(&*DIRECTORY_C, &[&*DIRECTORY_C, &*DIRECTORY_B], true, None)] + /// Downloading B (specified as the root) but receiving A instead should fail immediately, because A has no connection to B (the root). + #[case::dangling_pointer(&*DIRECTORY_B, &[&*DIRECTORY_A], true, None)] + /// Downloading a directory which refers to another Directory with a wrong size should fail. + #[case::wrong_size_in_parent(&*BROKEN_PARENT_DIRECTORY, &[&*BROKEN_PARENT_DIRECTORY, &*DIRECTORY_A], true, None)] + fn test_downloads( + #[case] root: &Directory, + #[case] directories_to_upload: &[&Directory], + #[case] exp_fail_upload_last: bool, + #[case] exp_finalize: Option<Vec<&Directory>>, // Some(_) if finalize successful, None if not. + ) { + let mut dcv = + DirectoryGraph::with_order(RootToLeavesValidator::new_with_root_digest(root.digest())); + let len_directories_to_upload = directories_to_upload.len(); + + for (i, d) in directories_to_upload.iter().enumerate() { + let resp = dcv.add((*d).clone()); + if i == len_directories_to_upload - 1 && exp_fail_upload_last { + assert!(resp.is_err(), "expect last put to fail"); + + // We don't really care anymore what finalize() would return, as + // the add() failed. + return; + } else { + assert!(resp.is_ok(), "expect put to succeed"); + } + } + + // everything was uploaded successfully. Test finalize(). + let resp = dcv + .validate() + .map(|validated| validated.drain_leaves_to_root().collect::<Vec<_>>()); + + match exp_finalize { + Some(directories) => { + assert_eq!( + Vec::from_iter(directories.iter().map(|e| (*e).to_owned())), + resp.expect("drain should succeed") + ); + } + None => { + resp.expect_err("drain should fail"); + } + } + } +} diff --git a/tvix/castore/src/directoryservice/from_addr.rs b/tvix/castore/src/directoryservice/from_addr.rs index 31158d3a38cc..2f7fc6d7de5a 100644 --- a/tvix/castore/src/directoryservice/from_addr.rs +++ b/tvix/castore/src/directoryservice/from_addr.rs @@ -1,127 +1,62 @@ +use std::sync::Arc; + use url::Url; -use crate::{proto::directory_service_client::DirectoryServiceClient, Error}; +use crate::composition::{ + with_registry, CompositionContext, DeserializeWithRegistry, ServiceBuilder, REG, +}; -use super::{DirectoryService, GRPCDirectoryService, MemoryDirectoryService, SledDirectoryService}; +use super::DirectoryService; /// Constructs a new instance of a [DirectoryService] from an URI. /// /// The following URIs are supported: /// - `memory:` /// Uses a in-memory implementation. -/// - `sled:` -/// Uses a in-memory sled implementation. -/// - `sled:///absolute/path/to/somewhere` -/// Uses sled, using a path on the disk for persistency. Can be only opened +/// from one process at the same time. +/// - `redb:` +/// Uses a in-memory redb implementation. +/// - `redb:///absolute/path/to/somewhere` +/// Uses redb, using a path on the disk for persistency. Can be only opened /// from one process at the same time. /// - `grpc+unix:///absolute/path/to/somewhere` /// Connects to a local tvix-store gRPC service via Unix socket. /// - `grpc+http://host:port`, `grpc+https://host:port` /// Connects to a (remote) tvix-store gRPC service. -pub async fn from_addr(uri: &str) -> Result<Box<dyn DirectoryService>, crate::Error> { +pub async fn from_addr( + uri: &str, +) -> Result<Arc<dyn DirectoryService>, Box<dyn std::error::Error + Send + Sync>> { #[allow(unused_mut)] let mut url = Url::parse(uri) .map_err(|e| crate::Error::StorageError(format!("unable to parse url: {}", e)))?; - let directory_service: Box<dyn DirectoryService> = match url.scheme() { - "memory" => { - // memory doesn't support host or path in the URL. - if url.has_host() || !url.path().is_empty() { - return Err(Error::StorageError("invalid url".to_string())); - } - Box::<MemoryDirectoryService>::default() - } - "sled" => { - // sled doesn't support host, and a path can be provided (otherwise - // it'll live in memory only). - if url.has_host() { - return Err(Error::StorageError("no host allowed".to_string())); - } - - if url.path() == "/" { - return Err(Error::StorageError( - "cowardly refusing to open / with sled".to_string(), - )); - } - - // TODO: expose compression and other parameters as URL parameters? - - Box::new(if url.path().is_empty() { - SledDirectoryService::new_temporary() - .map_err(|e| Error::StorageError(e.to_string()))? - } else { - SledDirectoryService::new(url.path()) - .map_err(|e| Error::StorageError(e.to_string()))? - }) - } - scheme if scheme.starts_with("grpc+") => { - // schemes starting with grpc+ go to the GRPCPathInfoService. - // That's normally grpc+unix for unix sockets, and grpc+http(s) for the HTTP counterparts. - // - In the case of unix sockets, there must be a path, but may not be a host. - // - In the case of non-unix sockets, there must be a host, but no path. - // Constructing the channel is handled by tvix_castore::channel::from_url. - let client = DirectoryServiceClient::new(crate::tonic::channel_from_url(&url).await?); - Box::new(GRPCDirectoryService::from_client(client)) - } - #[cfg(feature = "cloud")] - "bigtable" => { - use super::bigtable::BigtableParameters; - use super::BigtableDirectoryService; - - // parse the instance name from the hostname. - let instance_name = url - .host_str() - .ok_or_else(|| Error::StorageError("instance name missing".into()))? - .to_string(); - - // … but add it to the query string now, so we just need to parse that. - url.query_pairs_mut() - .append_pair("instance_name", &instance_name); - - let params: BigtableParameters = serde_qs::from_str(url.query().unwrap_or_default()) - .map_err(|e| Error::InvalidRequest(format!("failed to parse parameters: {}", e)))?; + let directory_service_config = with_registry(®, || { + <DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = dyn DirectoryService>>>>::try_from( + url, + ) + })? + .0; + let directory_service = directory_service_config + .build("anonymous", &CompositionContext::blank(®)) + .await?; - Box::new( - BigtableDirectoryService::connect(params) - .await - .map_err(|e| Error::StorageError(e.to_string()))?, - ) - } - _ => { - return Err(crate::Error::StorageError(format!( - "unknown scheme: {}", - url.scheme() - ))) - } - }; Ok(directory_service) } #[cfg(test)] mod tests { + use std::sync::LazyLock; + use super::from_addr; - use lazy_static::lazy_static; use rstest::rstest; use tempfile::TempDir; - lazy_static! { - static ref TMPDIR_SLED_1: TempDir = TempDir::new().unwrap(); - static ref TMPDIR_SLED_2: TempDir = TempDir::new().unwrap(); - } + static TMPDIR_REDB_1: LazyLock<TempDir> = LazyLock::new(|| TempDir::new().unwrap()); + static TMPDIR_REDB_2: LazyLock<TempDir> = LazyLock::new(|| TempDir::new().unwrap()); #[rstest] /// This uses an unsupported scheme. #[case::unsupported_scheme("http://foo.example/test", false)] - /// This configures sled in temporary mode. - #[case::sled_valid_temporary("sled://", true)] - /// This configures sled with /, which should fail. - #[case::sled_invalid_root("sled:///", false)] - /// This configures sled with a host, not path, which should fail. - #[case::sled_invalid_host("sled://foo.example", false)] - /// This configures sled with a valid path path, which should succeed. - #[case::sled_valid_path(&format!("sled://{}", &TMPDIR_SLED_1.path().to_str().unwrap()), true)] - /// This configures sled with a host, and a valid path path, which should fail. - #[case::sled_invalid_host_with_valid_path(&format!("sled://foo.example{}", &TMPDIR_SLED_2.path().to_str().unwrap()), false)] /// This correctly sets the scheme, and doesn't set a path. #[case::memory_valid("memory://", true)] /// This sets a memory url host to `foo` @@ -130,6 +65,16 @@ mod tests { #[case::memory_invalid_root_path("memory:///", false)] /// This sets a memory url path to "/foo", which is invalid. #[case::memory_invalid_root_path_foo("memory:///foo", false)] + /// This configures redb in temporary mode. + #[case::redb_valid_temporary("redb://", true)] + /// This configures redb with /, which should fail. + #[case::redb_invalid_root("redb:///", false)] + /// This configures redb with a host, not path, which should fail. + #[case::redb_invalid_host("redb://foo.example", false)] + /// This configures redb with a valid path, which should succeed. + #[case::redb_valid_path(&format!("redb://{}", &TMPDIR_REDB_1.path().join("foo").to_str().unwrap()), true)] + /// This configures redb with a host, and a valid path path, which should fail. + #[case::redb_invalid_host_with_valid_path(&format!("redb://foo.example{}", &TMPDIR_REDB_2.path().join("bar").to_str().unwrap()), false)] /// Correct scheme to connect to a unix socket. #[case::grpc_valid_unix_socket("grpc+unix:///path/to/somewhere", true)] /// Correct scheme for unix socket, but setting a host too, which is invalid. @@ -142,9 +87,19 @@ mod tests { #[case::grpc_valid_https_host_without_port("grpc+https://localhost", true)] /// Correct scheme to connect to localhost over http, but with additional path, which is invalid. #[case::grpc_invalid_host_and_path("grpc+http://localhost/some-path", false)] + /// A valid example for store composition using anonymous urls + #[cfg_attr( + feature = "xp-store-composition", + case::anonymous_url_composition("cache://?near=memory://&far=memory://", true) + )] + /// Store composition with anonymous urls should fail if the feature is disabled + #[cfg_attr( + not(feature = "xp-store-composition"), + case::anonymous_url_composition("cache://?near=memory://&far=memory://", false) + )] /// A valid example for Bigtable #[cfg_attr( - feature = "cloud", + all(feature = "cloud", feature = "integration"), case::bigtable_valid_url( "bigtable://instance-1?project_id=project-1&table_name=table-1&family_name=cf1", true @@ -152,7 +107,7 @@ mod tests { )] /// A valid example for Bigtable, specifying a custom channel size and timeout #[cfg_attr( - feature = "cloud", + all(feature = "cloud", feature = "integration"), case::bigtable_valid_url( "bigtable://instance-1?project_id=project-1&table_name=table-1&family_name=cf1&channel_size=10&timeout=10", true @@ -160,7 +115,7 @@ mod tests { )] /// A invalid Bigtable example (missing fields) #[cfg_attr( - feature = "cloud", + all(feature = "cloud", feature = "integration"), case::bigtable_invalid_url("bigtable://instance-1", false) )] #[tokio::test] diff --git a/tvix/castore/src/directoryservice/grpc.rs b/tvix/castore/src/directoryservice/grpc.rs index 7402fe1b5659..9696c5631949 100644 --- a/tvix/castore/src/directoryservice/grpc.rs +++ b/tvix/castore/src/directoryservice/grpc.rs @@ -1,44 +1,47 @@ use std::collections::HashSet; -use super::{DirectoryPutter, DirectoryService}; +use super::{Directory, DirectoryPutter, DirectoryService}; +use crate::composition::{CompositionContext, ServiceBuilder}; use crate::proto::{self, get_directory_request::ByWhat}; -use crate::{B3Digest, Error}; +use crate::{B3Digest, DirectoryError, Error}; use async_stream::try_stream; use futures::stream::BoxStream; +use std::sync::Arc; use tokio::spawn; use tokio::sync::mpsc::UnboundedSender; use tokio::task::JoinHandle; use tokio_stream::wrappers::UnboundedReceiverStream; -use tonic::async_trait; -use tonic::Code; -use tonic::{transport::Channel, Status}; -use tracing::{instrument, warn}; +use tonic::{async_trait, Code, Status}; +use tracing::{instrument, warn, Instrument as _}; /// Connects to a (remote) tvix-store DirectoryService over gRPC. #[derive(Clone)] -pub struct GRPCDirectoryService { +pub struct GRPCDirectoryService<T> { /// The internal reference to a gRPC client. /// Cloning it is cheap, and it internally handles concurrent requests. - grpc_client: proto::directory_service_client::DirectoryServiceClient<Channel>, + grpc_client: proto::directory_service_client::DirectoryServiceClient<T>, } -impl GRPCDirectoryService { +impl<T> GRPCDirectoryService<T> { /// construct a [GRPCDirectoryService] from a [proto::directory_service_client::DirectoryServiceClient]. /// panics if called outside the context of a tokio runtime. pub fn from_client( - grpc_client: proto::directory_service_client::DirectoryServiceClient<Channel>, + grpc_client: proto::directory_service_client::DirectoryServiceClient<T>, ) -> Self { Self { grpc_client } } } #[async_trait] -impl DirectoryService for GRPCDirectoryService { +impl<T> DirectoryService for GRPCDirectoryService<T> +where + T: tonic::client::GrpcService<tonic::body::BoxBody> + Send + Sync + Clone + 'static, + T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static, + <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send, + T::Future: Send, +{ #[instrument(level = "trace", skip_all, fields(directory.digest = %digest))] - async fn get( - &self, - digest: &B3Digest, - ) -> Result<Option<crate::proto::Directory>, crate::Error> { + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, crate::Error> { // Get a new handle to the gRPC client, and copy the digest. let mut grpc_client = self.grpc_client.clone(); let digest_cpy = digest.clone(); @@ -66,15 +69,10 @@ impl DirectoryService for GRPCDirectoryService { "requested directory with digest {}, but got {}", digest, actual_digest ))) - } else if let Err(e) = directory.validate() { - // Validate the Directory itself is valid. - warn!("directory failed validation: {}", e.to_string()); - Err(crate::Error::StorageError(format!( - "directory {} failed validation: {}", - digest, e, - ))) } else { - Ok(Some(directory)) + Ok(Some(directory.try_into().map_err(|_| { + Error::StorageError("invalid root digest length in response".to_string()) + })?)) } } Ok(None) => Ok(None), @@ -84,11 +82,11 @@ impl DirectoryService for GRPCDirectoryService { } #[instrument(level = "trace", skip_all, fields(directory.digest = %directory.digest()))] - async fn put(&self, directory: crate::proto::Directory) -> Result<B3Digest, crate::Error> { + async fn put(&self, directory: Directory) -> Result<B3Digest, crate::Error> { let resp = self .grpc_client .clone() - .put(tokio_stream::once(directory)) + .put(tokio_stream::once(proto::Directory::from(directory))) .await; match resp { @@ -107,7 +105,7 @@ impl DirectoryService for GRPCDirectoryService { fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<Result<proto::Directory, Error>> { + ) -> BoxStream<'static, Result<Directory, Error>> { let mut grpc_client = self.grpc_client.clone(); let root_directory_digest = root_directory_digest.clone(); @@ -124,19 +122,11 @@ impl DirectoryService for GRPCDirectoryService { // The Directory digests we received so far let mut received_directory_digests: HashSet<B3Digest> = HashSet::new(); // The Directory digests we're still expecting to get sent. - let mut expected_directory_digests: HashSet<B3Digest> = HashSet::from([root_directory_digest]); + let mut expected_directory_digests: HashSet<B3Digest> = HashSet::from([root_directory_digest.clone()]); loop { match stream.message().await { Ok(Some(directory)) => { - // validate the directory itself. - if let Err(e) = directory.validate() { - Err(crate::Error::StorageError(format!( - "directory {} failed validation: {}", - directory.digest(), - e, - )))?; - } // validate we actually expected that directory, and move it from expected to received. let directory_digest = directory.digest(); let was_expected = expected_directory_digests.remove(&directory_digest); @@ -162,14 +152,28 @@ impl DirectoryService for GRPCDirectoryService { .insert(child_directory_digest); } + let directory = directory.try_into() + .map_err(|e: DirectoryError| Error::StorageError(e.to_string()))?; + yield directory; }, + Ok(None) if expected_directory_digests.len() == 1 && expected_directory_digests.contains(&root_directory_digest) => { + // The root directory of the requested closure was not found, return an + // empty stream + return + } Ok(None) => { - // If we were still expecting something, that's an error. - if !expected_directory_digests.is_empty() { + // The stream has ended + let diff_len = expected_directory_digests + // Account for directories which have been referenced more than once, + // but only received once since they were deduplicated + .difference(&received_directory_digests) + .count(); + // If this is not empty, then the closure is incomplete + if diff_len != 0 { Err(crate::Error::StorageError(format!( "still expected {} directories, but got premature end of stream", - expected_directory_digests.len(), + diff_len )))? } else { return @@ -194,14 +198,17 @@ impl DirectoryService for GRPCDirectoryService { let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); - let task: JoinHandle<Result<proto::PutDirectoryResponse, Status>> = spawn(async move { - let s = grpc_client - .put(UnboundedReceiverStream::new(rx)) - .await? - .into_inner(); + let task: JoinHandle<Result<proto::PutDirectoryResponse, Status>> = spawn( + async move { + let s = grpc_client + .put(UnboundedReceiverStream::new(rx)) + .await? + .into_inner(); - Ok(s) - }); + Ok(s) + } // instrument the task with the current span, this is not done by default + .in_current_span(), + ); Box::new(GRPCPutter { rq: Some((task, tx)), @@ -209,6 +216,40 @@ impl DirectoryService for GRPCDirectoryService { } } +#[derive(serde::Deserialize, Debug)] +#[serde(deny_unknown_fields)] +pub struct GRPCDirectoryServiceConfig { + url: String, +} + +impl TryFrom<url::Url> for GRPCDirectoryServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + // This is normally grpc+unix for unix sockets, and grpc+http(s) for the HTTP counterparts. + // - In the case of unix sockets, there must be a path, but may not be a host. + // - In the case of non-unix sockets, there must be a host, but no path. + // Constructing the channel is handled by tvix_castore::channel::from_url. + Ok(GRPCDirectoryServiceConfig { + url: url.to_string(), + }) + } +} + +#[async_trait] +impl ServiceBuilder for GRPCDirectoryServiceConfig { + type Output = dyn DirectoryService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn DirectoryService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + let client = proto::directory_service_client::DirectoryServiceClient::new( + crate::tonic::channel_from_url(&self.url.parse()?).await?, + ); + Ok(Arc::new(GRPCDirectoryService::from_client(client))) + } +} + /// Allows uploading multiple Directory messages in the same gRPC stream. pub struct GRPCPutter { /// Data about the current request - a handle to the task, and the tx part @@ -225,11 +266,11 @@ pub struct GRPCPutter { #[async_trait] impl DirectoryPutter for GRPCPutter { #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest()), err)] - async fn put(&mut self, directory: proto::Directory) -> Result<(), crate::Error> { + async fn put(&mut self, directory: Directory) -> Result<(), crate::Error> { match self.rq { // If we're not already closed, send the directory to directory_sender. Some((_, ref directory_sender)) => { - if directory_sender.send(directory).is_err() { + if directory_sender.send(directory.into()).is_err() { // If the channel has been prematurely closed, invoke close (so we can peek at the error code) // That error code is much more helpful, because it // contains the error message from the server. diff --git a/tvix/castore/src/directoryservice/memory.rs b/tvix/castore/src/directoryservice/memory.rs index 2cbbbd1b1657..b039d9bc7d84 100644 --- a/tvix/castore/src/directoryservice/memory.rs +++ b/tvix/castore/src/directoryservice/memory.rs @@ -1,12 +1,15 @@ -use crate::{proto, B3Digest, Error}; +use crate::{B3Digest, Error}; use futures::stream::BoxStream; use std::collections::HashMap; -use std::sync::{Arc, RwLock}; +use std::sync::Arc; +use tokio::sync::RwLock; use tonic::async_trait; use tracing::{instrument, warn}; use super::utils::traverse_directory; -use super::{DirectoryPutter, DirectoryService, SimplePutter}; +use super::{Directory, DirectoryPutter, DirectoryService, SimplePutter}; +use crate::composition::{CompositionContext, ServiceBuilder}; +use crate::proto; #[derive(Clone, Default)] pub struct MemoryDirectoryService { @@ -16,8 +19,8 @@ pub struct MemoryDirectoryService { #[async_trait] impl DirectoryService for MemoryDirectoryService { #[instrument(skip(self, digest), fields(directory.digest = %digest))] - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error> { - let db = self.db.read()?; + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { + let db = self.db.read().await; match db.get(digest) { // The directory was not found, return @@ -35,35 +38,20 @@ impl DirectoryService for MemoryDirectoryService { ))); } - // Validate the Directory itself is valid. - if let Err(e) = directory.validate() { - warn!("directory failed validation: {}", e.to_string()); - return Err(Error::StorageError(format!( - "directory {} failed validation: {}", - actual_digest, e, - ))); - } - - Ok(Some(directory.clone())) + Ok(Some(directory.clone().try_into().map_err(|e| { + crate::Error::StorageError(format!("corrupted directory: {}", e)) + })?)) } } } #[instrument(skip(self, directory), fields(directory.digest = %directory.digest()))] - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error> { + async fn put(&self, directory: Directory) -> Result<B3Digest, Error> { let digest = directory.digest(); - // validate the directory itself. - if let Err(e) = directory.validate() { - return Err(Error::InvalidRequest(format!( - "directory {} failed validation: {}", - digest, e, - ))); - } - // store it - let mut db = self.db.write()?; - db.insert(digest.clone(), directory); + let mut db = self.db.write().await; + db.insert(digest.clone(), directory.into()); Ok(digest) } @@ -72,7 +60,7 @@ impl DirectoryService for MemoryDirectoryService { fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<Result<proto::Directory, Error>> { + ) -> BoxStream<'static, Result<Directory, Error>> { traverse_directory(self.clone(), root_directory_digest) } @@ -84,3 +72,30 @@ impl DirectoryService for MemoryDirectoryService { Box::new(SimplePutter::new(self.clone())) } } + +#[derive(serde::Deserialize, Debug)] +#[serde(deny_unknown_fields)] +pub struct MemoryDirectoryServiceConfig {} + +impl TryFrom<url::Url> for MemoryDirectoryServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + // memory doesn't support host or path in the URL. + if url.has_host() || !url.path().is_empty() { + return Err(Error::StorageError("invalid url".to_string()).into()); + } + Ok(MemoryDirectoryServiceConfig {}) + } +} + +#[async_trait] +impl ServiceBuilder for MemoryDirectoryServiceConfig { + type Output = dyn DirectoryService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn DirectoryService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + Ok(Arc::new(MemoryDirectoryService::default())) + } +} diff --git a/tvix/castore/src/directoryservice/mod.rs b/tvix/castore/src/directoryservice/mod.rs index cf6bea39d809..b3cb0f4fd67b 100644 --- a/tvix/castore/src/directoryservice/mod.rs +++ b/tvix/castore/src/directoryservice/mod.rs @@ -1,24 +1,32 @@ -use crate::{proto, B3Digest, Error}; +use crate::composition::{Registry, ServiceBuilder}; +use crate::{B3Digest, Directory, Error}; + +use auto_impl::auto_impl; use futures::stream::BoxStream; use tonic::async_trait; - -mod closure_validator; +mod combinators; +mod directory_graph; mod from_addr; mod grpc; mod memory; +mod object_store; +mod order_validator; +mod redb; mod simple_putter; -mod sled; #[cfg(test)] pub mod tests; mod traverse; mod utils; -pub use self::closure_validator::ClosureValidator; +pub use self::combinators::{Cache, CacheConfig}; +pub use self::directory_graph::{DirectoryGraph, ValidatedDirectoryGraph}; pub use self::from_addr::from_addr; -pub use self::grpc::GRPCDirectoryService; -pub use self::memory::MemoryDirectoryService; +pub use self::grpc::{GRPCDirectoryService, GRPCDirectoryServiceConfig}; +pub use self::memory::{MemoryDirectoryService, MemoryDirectoryServiceConfig}; +pub use self::object_store::{ObjectStoreDirectoryService, ObjectStoreDirectoryServiceConfig}; +pub use self::order_validator::{LeavesToRootValidator, OrderValidator, RootToLeavesValidator}; +pub use self::redb::{RedbDirectoryService, RedbDirectoryServiceConfig}; pub use self::simple_putter::SimplePutter; -pub use self::sled::SledDirectoryService; pub use self::traverse::descend_to; pub use self::utils::traverse_directory; @@ -26,12 +34,13 @@ pub use self::utils::traverse_directory; mod bigtable; #[cfg(feature = "cloud")] -pub use self::bigtable::BigtableDirectoryService; +pub use self::bigtable::{BigtableDirectoryService, BigtableParameters}; /// The base trait all Directory services need to implement. -/// This is a simple get and put of [crate::proto::Directory], returning their +/// This is a simple get and put of [Directory], returning their /// digest. #[async_trait] +#[auto_impl(&, &mut, Arc, Box)] pub trait DirectoryService: Send + Sync { /// Looks up a single Directory message by its digest. /// The returned Directory message *must* be valid. @@ -41,14 +50,14 @@ pub trait DirectoryService: Send + Sync { /// Directory digests that are at the "root", aka the last element that's /// sent to a DirectoryPutter. This makes sense for implementations bundling /// closures of directories together in batches. - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error>; + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error>; /// Uploads a single Directory message, and returns the calculated /// digest, or an error. An error *must* also be returned if the message is /// not valid. - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error>; + async fn put(&self, directory: Directory) -> Result<B3Digest, Error>; - /// Looks up a closure of [proto::Directory]. - /// Ideally this would be a `impl Stream<Item = Result<proto::Directory, Error>>`, + /// Looks up a closure of [Directory]. + /// Ideally this would be a `impl Stream<Item = Result<Directory, Error>>`, /// and we'd be able to add a default implementation for it here, but /// we can't have that yet. /// @@ -61,42 +70,19 @@ pub trait DirectoryService: Send + Sync { /// Directories are sent in an order from the root to the leaves, so that /// the receiving side can validate each message to be a connected to the root /// that has initially been requested. + /// + /// In case the directory can not be found, this should return an empty stream. fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<Result<proto::Directory, Error>>; + ) -> BoxStream<'static, Result<Directory, Error>>; - /// Allows persisting a closure of [proto::Directory], which is a graph of + /// Allows persisting a closure of [Directory], which is a graph of /// connected Directory messages. fn put_multiple_start(&self) -> Box<dyn DirectoryPutter>; } -#[async_trait] -impl<A> DirectoryService for A -where - A: AsRef<dyn DirectoryService> + Send + Sync, -{ - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error> { - self.as_ref().get(digest).await - } - - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error> { - self.as_ref().put(directory).await - } - - fn get_recursive( - &self, - root_directory_digest: &B3Digest, - ) -> BoxStream<Result<proto::Directory, Error>> { - self.as_ref().get_recursive(root_directory_digest) - } - - fn put_multiple_start(&self) -> Box<dyn DirectoryPutter> { - self.as_ref().put_multiple_start() - } -} - -/// Provides a handle to put a closure of connected [proto::Directory] elements. +/// Provides a handle to put a closure of connected [Directory] elements. /// /// The consumer can periodically call [DirectoryPutter::put], starting from the /// leaves. Once the root is reached, [DirectoryPutter::close] can be called to @@ -108,15 +94,28 @@ where /// but a single file or symlink. #[async_trait] pub trait DirectoryPutter: Send { - /// Put a individual [proto::Directory] into the store. + /// Put a individual [Directory] into the store. /// Error semantics and behaviour is up to the specific implementation of /// this trait. /// Due to bursting, the returned error might refer to an object previously /// sent via `put`. - async fn put(&mut self, directory: proto::Directory) -> Result<(), Error>; + async fn put(&mut self, directory: Directory) -> Result<(), Error>; /// Close the stream, and wait for any errors. /// If there's been any invalid Directory message uploaded, and error *must* /// be returned. async fn close(&mut self) -> Result<B3Digest, Error>; } + +/// Registers the builtin DirectoryService implementations with the registry +pub(crate) fn register_directory_services(reg: &mut Registry) { + reg.register::<Box<dyn ServiceBuilder<Output = dyn DirectoryService>>, super::directoryservice::ObjectStoreDirectoryServiceConfig>("objectstore"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn DirectoryService>>, super::directoryservice::MemoryDirectoryServiceConfig>("memory"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn DirectoryService>>, super::directoryservice::CacheConfig>("cache"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn DirectoryService>>, super::directoryservice::GRPCDirectoryServiceConfig>("grpc"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn DirectoryService>>, super::directoryservice::RedbDirectoryServiceConfig>("redb"); + #[cfg(feature = "cloud")] + { + reg.register::<Box<dyn ServiceBuilder<Output = dyn DirectoryService>>, super::directoryservice::BigtableParameters>("bigtable"); + } +} diff --git a/tvix/castore/src/directoryservice/object_store.rs b/tvix/castore/src/directoryservice/object_store.rs new file mode 100644 index 000000000000..5b5281abcd2f --- /dev/null +++ b/tvix/castore/src/directoryservice/object_store.rs @@ -0,0 +1,327 @@ +use std::collections::HashMap; +use std::sync::Arc; + +use data_encoding::HEXLOWER; +use futures::future::Either; +use futures::stream::BoxStream; +use futures::SinkExt; +use futures::StreamExt; +use futures::TryFutureExt; +use futures::TryStreamExt; +use object_store::{path::Path, ObjectStore}; +use prost::Message; +use tokio::io::AsyncWriteExt; +use tokio_util::codec::LengthDelimitedCodec; +use tonic::async_trait; +use tracing::{instrument, trace, warn, Level}; +use url::Url; + +use super::{ + Directory, DirectoryGraph, DirectoryPutter, DirectoryService, LeavesToRootValidator, + RootToLeavesValidator, +}; +use crate::composition::{CompositionContext, ServiceBuilder}; +use crate::{proto, B3Digest, Error, Node}; + +/// Stores directory closures in an object store. +/// Notably, this makes use of the option to disallow accessing child directories except when +/// fetching them recursively via the top-level directory, since all batched writes +/// (using `put_multiple_start`) are stored in a single object. +/// Directories are stored in a length-delimited format with a 1MiB limit. The length field is a +/// u32 and the directories are stored in root-to-leaves topological order, the same way they will +/// be returned to the client in get_recursive. +#[derive(Clone)] +pub struct ObjectStoreDirectoryService { + object_store: Arc<dyn ObjectStore>, + base_path: Path, +} + +#[instrument(level=Level::TRACE, skip_all,fields(base_path=%base_path,blob.digest=%digest),ret(Display))] +fn derive_dirs_path(base_path: &Path, digest: &B3Digest) -> Path { + base_path + .child("dirs") + .child("b3") + .child(HEXLOWER.encode(&digest.as_slice()[..2])) + .child(HEXLOWER.encode(digest.as_slice())) +} + +#[allow(clippy::identity_op)] +const MAX_FRAME_LENGTH: usize = 1 * 1024 * 1024 * 1000; // 1 MiB + // +impl ObjectStoreDirectoryService { + /// Constructs a new [ObjectStoreDirectoryService] from a [Url] supported by + /// [object_store]. + /// Any path suffix becomes the base path of the object store. + /// additional options, the same as in [object_store::parse_url_opts] can + /// be passed. + pub fn parse_url_opts<I, K, V>(url: &Url, options: I) -> Result<Self, object_store::Error> + where + I: IntoIterator<Item = (K, V)>, + K: AsRef<str>, + V: Into<String>, + { + let (object_store, path) = object_store::parse_url_opts(url, options)?; + + Ok(Self { + object_store: Arc::new(object_store), + base_path: path, + }) + } + + /// Like [Self::parse_url_opts], except without the options. + pub fn parse_url(url: &Url) -> Result<Self, object_store::Error> { + Self::parse_url_opts(url, Vec::<(String, String)>::new()) + } +} + +#[async_trait] +impl DirectoryService for ObjectStoreDirectoryService { + /// This is the same steps as for get_recursive anyways, so we just call get_recursive and + /// return the first element of the stream and drop the request. + #[instrument(skip(self, digest), fields(directory.digest = %digest))] + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { + self.get_recursive(digest).take(1).next().await.transpose() + } + + #[instrument(skip(self, directory), fields(directory.digest = %directory.digest()))] + async fn put(&self, directory: Directory) -> Result<B3Digest, Error> { + // Ensure the directory doesn't contain other directory children + if directory + .nodes() + .any(|(_, e)| matches!(e, Node::Directory { .. })) + { + return Err(Error::InvalidRequest( + "only put_multiple_start is supported by the ObjectStoreDirectoryService for directories with children".into(), + )); + } + + let mut handle = self.put_multiple_start(); + handle.put(directory).await?; + handle.close().await + } + + #[instrument(skip_all, fields(directory.digest = %root_directory_digest))] + fn get_recursive( + &self, + root_directory_digest: &B3Digest, + ) -> BoxStream<'static, Result<Directory, Error>> { + // Check that we are not passing on bogus from the object store to the client, and that the + // trust chain from the root digest to the leaves is intact + let mut order_validator = + RootToLeavesValidator::new_with_root_digest(root_directory_digest.clone()); + + let dir_path = derive_dirs_path(&self.base_path, root_directory_digest); + let object_store = self.object_store.clone(); + + Box::pin( + (async move { + let stream = match object_store.get(&dir_path).await { + Ok(v) => v.into_stream(), + Err(object_store::Error::NotFound { .. }) => { + return Ok(Either::Left(futures::stream::empty())) + } + Err(e) => return Err(std::io::Error::from(e).into()), + }; + + // get a reader of the response body. + let r = tokio_util::io::StreamReader::new(stream); + let decompressed_stream = async_compression::tokio::bufread::ZstdDecoder::new(r); + + // the subdirectories are stored in a length delimited format + let delimited_stream = LengthDelimitedCodec::builder() + .max_frame_length(MAX_FRAME_LENGTH) + .length_field_type::<u32>() + .new_read(decompressed_stream); + + let dirs_stream = delimited_stream.map_err(Error::from).and_then(move |buf| { + futures::future::ready((|| { + let mut hasher = blake3::Hasher::new(); + let digest: B3Digest = hasher.update(&buf).finalize().as_bytes().into(); + + // Ensure to only decode the directory objects whose digests we trust + if !order_validator.digest_allowed(&digest) { + return Err(crate::Error::StorageError(format!( + "received unexpected directory {}", + digest + ))); + } + + let directory = proto::Directory::decode(&*buf).map_err(|e| { + warn!("unable to parse directory {}: {}", digest, e); + Error::StorageError(e.to_string()) + })?; + let directory = Directory::try_from(directory).map_err(|e| { + warn!("unable to convert directory {}: {}", digest, e); + Error::StorageError(e.to_string()) + })?; + + // Allow the children to appear next + order_validator.add_directory_unchecked(&directory); + + Ok(directory) + })()) + }); + + Ok(Either::Right(dirs_stream)) + }) + .try_flatten_stream(), + ) + } + + #[instrument(skip_all)] + fn put_multiple_start(&self) -> Box<(dyn DirectoryPutter + 'static)> + where + Self: Clone, + { + Box::new(ObjectStoreDirectoryPutter::new( + self.object_store.clone(), + self.base_path.clone(), + )) + } +} + +#[derive(serde::Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ObjectStoreDirectoryServiceConfig { + object_store_url: String, + #[serde(default)] + object_store_options: HashMap<String, String>, +} + +impl TryFrom<url::Url> for ObjectStoreDirectoryServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + // We need to convert the URL to string, strip the prefix there, and then + // parse it back as url, as Url::set_scheme() rejects some of the transitions we want to do. + let trimmed_url = { + let s = url.to_string(); + let mut url = Url::parse( + s.strip_prefix("objectstore+") + .ok_or(Error::StorageError("Missing objectstore uri".into()))?, + )?; + // trim the query pairs, they might contain credentials or local settings we don't want to send as-is. + url.set_query(None); + url + }; + Ok(ObjectStoreDirectoryServiceConfig { + object_store_url: trimmed_url.into(), + object_store_options: url + .query_pairs() + .into_iter() + .map(|(k, v)| (k.to_string(), v.to_string())) + .collect(), + }) + } +} + +#[async_trait] +impl ServiceBuilder for ObjectStoreDirectoryServiceConfig { + type Output = dyn DirectoryService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn DirectoryService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + let (object_store, path) = object_store::parse_url_opts( + &self.object_store_url.parse()?, + &self.object_store_options, + )?; + Ok(Arc::new(ObjectStoreDirectoryService { + object_store: Arc::new(object_store), + base_path: path, + })) + } +} + +struct ObjectStoreDirectoryPutter { + object_store: Arc<dyn ObjectStore>, + base_path: Path, + + directory_validator: Option<DirectoryGraph<LeavesToRootValidator>>, +} + +impl ObjectStoreDirectoryPutter { + fn new(object_store: Arc<dyn ObjectStore>, base_path: Path) -> Self { + Self { + object_store, + base_path, + directory_validator: Some(Default::default()), + } + } +} + +#[async_trait] +impl DirectoryPutter for ObjectStoreDirectoryPutter { + #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest()), err)] + async fn put(&mut self, directory: Directory) -> Result<(), Error> { + match self.directory_validator { + None => return Err(Error::StorageError("already closed".to_string())), + Some(ref mut validator) => { + validator + .add(directory) + .map_err(|e| Error::StorageError(e.to_string()))?; + } + } + + Ok(()) + } + + #[instrument(level = "trace", skip_all, ret, err)] + async fn close(&mut self) -> Result<B3Digest, Error> { + let validator = match self.directory_validator.take() { + None => return Err(Error::InvalidRequest("already closed".to_string())), + Some(validator) => validator, + }; + + // retrieve the validated directories. + // It is important that they are in topological order (root first), + // since that's how we want to retrieve them from the object store in the end. + let directories = validator + .validate() + .map_err(|e| Error::StorageError(e.to_string()))? + .drain_root_to_leaves() + .collect::<Vec<_>>(); + + // Get the root digest + let root_digest = directories + .first() + .ok_or_else(|| Error::InvalidRequest("got no directories".to_string()))? + .digest(); + + let dir_path = derive_dirs_path(&self.base_path, &root_digest); + + match self.object_store.head(&dir_path).await { + // directory tree already exists, nothing to do + Ok(_) => { + trace!("directory tree already exists"); + } + + // directory tree does not yet exist, compress and upload. + Err(object_store::Error::NotFound { .. }) => { + trace!("uploading directory tree"); + + let object_store_writer = + object_store::buffered::BufWriter::new(self.object_store.clone(), dir_path); + let compressed_writer = + async_compression::tokio::write::ZstdEncoder::new(object_store_writer); + let mut directories_sink = LengthDelimitedCodec::builder() + .max_frame_length(MAX_FRAME_LENGTH) + .length_field_type::<u32>() + .new_write(compressed_writer); + + for directory in directories { + directories_sink + .send(proto::Directory::from(directory).encode_to_vec().into()) + .await?; + } + + let mut compressed_writer = directories_sink.into_inner(); + compressed_writer.shutdown().await?; + } + // other error + Err(err) => Err(std::io::Error::from(err))?, + } + + Ok(root_digest) + } +} diff --git a/tvix/castore/src/directoryservice/order_validator.rs b/tvix/castore/src/directoryservice/order_validator.rs new file mode 100644 index 000000000000..973af92e1294 --- /dev/null +++ b/tvix/castore/src/directoryservice/order_validator.rs @@ -0,0 +1,188 @@ +use std::collections::HashSet; +use tracing::warn; + +use super::Directory; +use crate::{B3Digest, Node}; + +pub trait OrderValidator { + /// Update the order validator's state with the directory + /// Returns whether the directory was accepted + fn add_directory(&mut self, directory: &Directory) -> bool; +} + +#[derive(Default)] +/// Validates that newly introduced directories are already referenced from +/// the root via existing directories. +/// Commonly used when _receiving_ a directory closure _from_ a store. +pub struct RootToLeavesValidator { + /// Only used to remember the root node, not for validation + expected_digests: HashSet<B3Digest>, +} + +impl RootToLeavesValidator { + /// Use to validate the root digest of the closure upon receiving the first + /// directory. + pub fn new_with_root_digest(root_digest: B3Digest) -> Self { + let mut this = Self::default(); + this.expected_digests.insert(root_digest); + this + } + + /// Checks if a directory is in-order based on its digest. + /// + /// Particularly useful when receiving directories in canonical protobuf + /// encoding, so that directories not connected to the root can be rejected + /// without parsing. + /// + /// After parsing, the directory must be passed to `add_directory_unchecked` + /// to add its children to the list of expected digests. + pub fn digest_allowed(&self, digest: &B3Digest) -> bool { + self.expected_digests.is_empty() // we don't know the root node; allow any + || self.expected_digests.contains(digest) + } + + /// Update the order validator's state with the directory + pub fn add_directory_unchecked(&mut self, directory: &Directory) { + // No initial root was specified and this is the first directory + if self.expected_digests.is_empty() { + self.expected_digests.insert(directory.digest()); + } + + // Allow the children to appear next + for (_, node) in directory.nodes() { + if let Node::Directory { digest, .. } = node { + self.expected_digests.insert(digest.clone()); + } + } + } +} + +impl OrderValidator for RootToLeavesValidator { + fn add_directory(&mut self, directory: &Directory) -> bool { + if !self.digest_allowed(&directory.digest()) { + return false; + } + self.add_directory_unchecked(directory); + true + } +} + +#[derive(Default)] +/// Validates that newly uploaded directories only reference directories which +/// have already been introduced. +/// Commonly used when _uploading_ a directory closure _to_ a store. +pub struct LeavesToRootValidator { + /// This is empty in the beginning, and gets filled as leaves and intermediates are + /// inserted + allowed_references: HashSet<B3Digest>, +} + +impl OrderValidator for LeavesToRootValidator { + fn add_directory(&mut self, directory: &Directory) -> bool { + let digest = directory.digest(); + + for (_, node) in directory.nodes() { + if let Node::Directory { + digest: subdir_node_digest, + .. + } = node + { + if !self.allowed_references.contains(subdir_node_digest) { + warn!( + directory.digest = %digest, + subdirectory.digest = %subdir_node_digest, + "unexpected directory reference" + ); + return false; + } + } + } + + self.allowed_references.insert(digest.clone()); + + true + } +} + +#[cfg(test)] +mod tests { + use super::{LeavesToRootValidator, RootToLeavesValidator}; + use crate::directoryservice::order_validator::OrderValidator; + use crate::directoryservice::Directory; + use crate::fixtures::{DIRECTORY_A, DIRECTORY_B, DIRECTORY_C}; + use rstest::rstest; + + #[rstest] + /// Uploading an empty directory should succeed. + #[case::empty_directory(&[&*DIRECTORY_A], false)] + /// Uploading A, then B (referring to A) should succeed. + #[case::simple_closure(&[&*DIRECTORY_A, &*DIRECTORY_B], false)] + /// Uploading A, then A, then C (referring to A twice) should succeed. + /// We pretend to be a dumb client not deduping directories. + #[case::same_child(&[&*DIRECTORY_A, &*DIRECTORY_A, &*DIRECTORY_C], false)] + /// Uploading A, then C (referring to A twice) should succeed. + #[case::same_child_dedup(&[&*DIRECTORY_A, &*DIRECTORY_C], false)] + /// Uploading A, then C (referring to A twice), then B (itself referring to A) should fail during close, + /// as B itself would be left unconnected. + #[case::unconnected_node(&[&*DIRECTORY_A, &*DIRECTORY_C, &*DIRECTORY_B], false)] + /// Uploading B (referring to A) should fail immediately, because A was never uploaded. + #[case::dangling_pointer(&[&*DIRECTORY_B], true)] + fn leaves_to_root( + #[case] directories_to_upload: &[&Directory], + #[case] exp_fail_upload_last: bool, + ) { + let mut validator = LeavesToRootValidator::default(); + let len_directories_to_upload = directories_to_upload.len(); + + for (i, d) in directories_to_upload.iter().enumerate() { + let resp = validator.add_directory(d); + if i == len_directories_to_upload - 1 && exp_fail_upload_last { + assert!(!resp, "expect last put to fail"); + + // We don't really care anymore what finalize() would return, as + // the add() failed. + return; + } else { + assert!(resp, "expect put to succeed"); + } + } + } + + #[rstest] + /// Downloading an empty directory should succeed. + #[case::empty_directory(&*DIRECTORY_A, &[&*DIRECTORY_A], false)] + /// Downlading B, then A (referenced by B) should succeed. + #[case::simple_closure(&*DIRECTORY_B, &[&*DIRECTORY_B, &*DIRECTORY_A], false)] + /// Downloading C (referring to A twice), then A should succeed. + #[case::same_child_dedup(&*DIRECTORY_C, &[&*DIRECTORY_C, &*DIRECTORY_A], false)] + /// Downloading C, then B (both referring to A but not referring to each other) should fail immediately as B has no connection to C (the root) + #[case::unconnected_node(&*DIRECTORY_C, &[&*DIRECTORY_C, &*DIRECTORY_B], true)] + /// Downloading B (specified as the root) but receiving A instead should fail immediately, because A has no connection to B (the root). + #[case::dangling_pointer(&*DIRECTORY_B, &[&*DIRECTORY_A], true)] + fn root_to_leaves( + #[case] root: &Directory, + #[case] directories_to_upload: &[&Directory], + #[case] exp_fail_upload_last: bool, + ) { + let mut validator = RootToLeavesValidator::new_with_root_digest(root.digest()); + let len_directories_to_upload = directories_to_upload.len(); + + for (i, d) in directories_to_upload.iter().enumerate() { + let resp1 = validator.digest_allowed(&d.digest()); + let resp = validator.add_directory(d); + assert_eq!( + resp1, resp, + "digest_allowed should return the same value as add_directory" + ); + if i == len_directories_to_upload - 1 && exp_fail_upload_last { + assert!(!resp, "expect last put to fail"); + + // We don't really care anymore what finalize() would return, as + // the add() failed. + return; + } else { + assert!(resp, "expect put to succeed"); + } + } + } +} diff --git a/tvix/castore/src/directoryservice/redb.rs b/tvix/castore/src/directoryservice/redb.rs new file mode 100644 index 000000000000..d253df503bb3 --- /dev/null +++ b/tvix/castore/src/directoryservice/redb.rs @@ -0,0 +1,303 @@ +use futures::stream::BoxStream; +use prost::Message; +use redb::{Database, TableDefinition}; +use std::{path::PathBuf, sync::Arc}; +use tonic::async_trait; +use tracing::{instrument, warn}; + +use super::{ + traverse_directory, Directory, DirectoryGraph, DirectoryPutter, DirectoryService, + LeavesToRootValidator, +}; +use crate::{ + composition::{CompositionContext, ServiceBuilder}, + digests, proto, B3Digest, Error, +}; + +const DIRECTORY_TABLE: TableDefinition<[u8; digests::B3_LEN], Vec<u8>> = + TableDefinition::new("directory"); + +#[derive(Clone)] +pub struct RedbDirectoryService { + // We wrap the db in an Arc to be able to move it into spawn_blocking, + // as discussed in https://github.com/cberner/redb/issues/789 + db: Arc<Database>, +} + +impl RedbDirectoryService { + /// Constructs a new instance using the specified filesystem path for + /// storage. + pub async fn new(path: PathBuf) -> Result<Self, Error> { + if path == PathBuf::from("/") { + return Err(Error::StorageError( + "cowardly refusing to open / with redb".to_string(), + )); + } + + let db = tokio::task::spawn_blocking(|| -> Result<_, redb::Error> { + let db = redb::Database::create(path)?; + create_schema(&db)?; + Ok(db) + }) + .await??; + + Ok(Self { db: Arc::new(db) }) + } + + /// Constructs a new instance using the in-memory backend. + pub fn new_temporary() -> Result<Self, Error> { + let db = + redb::Database::builder().create_with_backend(redb::backends::InMemoryBackend::new())?; + + create_schema(&db)?; + + Ok(Self { db: Arc::new(db) }) + } +} + +/// Ensures all tables are present. +/// Opens a write transaction and calls open_table on DIRECTORY_TABLE, which will +/// create it if not present. +fn create_schema(db: &redb::Database) -> Result<(), redb::Error> { + let txn = db.begin_write()?; + txn.open_table(DIRECTORY_TABLE)?; + txn.commit()?; + + Ok(()) +} + +#[async_trait] +impl DirectoryService for RedbDirectoryService { + #[instrument(skip(self, digest), fields(directory.digest = %digest))] + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { + let db = self.db.clone(); + + // Retrieves the protobuf-encoded Directory for the corresponding digest. + let db_get_resp = tokio::task::spawn_blocking({ + let digest_as_array: [u8; digests::B3_LEN] = digest.to_owned().into(); + move || -> Result<_, redb::Error> { + let txn = db.begin_read()?; + let table = txn.open_table(DIRECTORY_TABLE)?; + Ok(table.get(digest_as_array)?) + } + }) + .await? + .map_err(|e| { + warn!(err=%e, "failed to retrieve Directory"); + Error::StorageError("failed to retrieve Directory".to_string()) + })?; + + // The Directory was not found, return None. + let directory_data = match db_get_resp { + None => return Ok(None), + Some(d) => d, + }; + + // We check that the digest of the retrieved Directory matches the expected digest. + let actual_digest = blake3::hash(directory_data.value().as_slice()); + if actual_digest.as_bytes() != digest.as_slice() { + warn!(directory.actual_digest=%actual_digest, "requested Directory got the wrong digest"); + return Err(Error::StorageError( + "requested Directory got the wrong digest".to_string(), + )); + } + + // Attempt to decode the retrieved protobuf-encoded Directory, returning a parsing error if + // the decoding failed. + let directory = match proto::Directory::decode(&*directory_data.value()) { + Ok(dir) => { + // The returned Directory must be valid. + dir.try_into().map_err(|e| { + warn!(err=%e, "Directory failed validation"); + Error::StorageError("Directory failed validation".to_string()) + })? + } + Err(e) => { + warn!(err=%e, "failed to parse Directory"); + return Err(Error::StorageError("failed to parse Directory".to_string())); + } + }; + + Ok(Some(directory)) + } + + #[instrument(skip(self, directory), fields(directory.digest = %directory.digest()))] + async fn put(&self, directory: Directory) -> Result<B3Digest, Error> { + tokio::task::spawn_blocking({ + let db = self.db.clone(); + move || { + let digest = directory.digest(); + + // Store the directory in the table. + let txn = db.begin_write()?; + { + let mut table = txn.open_table(DIRECTORY_TABLE)?; + let digest_as_array: [u8; digests::B3_LEN] = digest.clone().into(); + table.insert( + digest_as_array, + proto::Directory::from(directory).encode_to_vec(), + )?; + } + txn.commit()?; + + Ok(digest) + } + }) + .await? + } + + #[instrument(skip_all, fields(directory.digest = %root_directory_digest))] + fn get_recursive( + &self, + root_directory_digest: &B3Digest, + ) -> BoxStream<'static, Result<Directory, Error>> { + // FUTUREWORK: Ideally we should have all of the directory traversing happen in a single + // redb transaction to avoid constantly closing and opening new transactions for the + // database. + traverse_directory(self.clone(), root_directory_digest) + } + + #[instrument(skip_all)] + fn put_multiple_start(&self) -> Box<dyn DirectoryPutter> { + Box::new(RedbDirectoryPutter { + db: self.db.clone(), + directory_validator: Some(Default::default()), + }) + } +} + +pub struct RedbDirectoryPutter { + db: Arc<Database>, + + /// The directories (inside the directory validator) that we insert later, + /// or None, if they were already inserted. + directory_validator: Option<DirectoryGraph<LeavesToRootValidator>>, +} + +#[async_trait] +impl DirectoryPutter for RedbDirectoryPutter { + #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest()), err)] + async fn put(&mut self, directory: Directory) -> Result<(), Error> { + match self.directory_validator { + None => return Err(Error::StorageError("already closed".to_string())), + Some(ref mut validator) => { + validator + .add(directory) + .map_err(|e| Error::StorageError(e.to_string()))?; + } + } + + Ok(()) + } + + #[instrument(level = "trace", skip_all, ret, err)] + async fn close(&mut self) -> Result<B3Digest, Error> { + match self.directory_validator.take() { + None => Err(Error::StorageError("already closed".to_string())), + Some(validator) => { + // Insert all directories as a batch. + tokio::task::spawn_blocking({ + let txn = self.db.begin_write()?; + move || { + // Retrieve the validated directories. + let directories = validator + .validate() + .map_err(|e| Error::StorageError(e.to_string()))? + .drain_leaves_to_root() + .collect::<Vec<_>>(); + + // Get the root digest, which is at the end (cf. insertion order) + let root_digest = directories + .last() + .ok_or_else(|| Error::StorageError("got no directories".to_string()))? + .digest(); + + { + let mut table = txn.open_table(DIRECTORY_TABLE)?; + + // Looping over all the verified directories, queuing them up for a + // batch insertion. + for directory in directories { + let digest_as_array: [u8; digests::B3_LEN] = + directory.digest().into(); + table.insert( + digest_as_array, + proto::Directory::from(directory).encode_to_vec(), + )?; + } + } + + txn.commit()?; + + Ok(root_digest) + } + }) + .await? + } + } + } +} + +#[derive(serde::Deserialize)] +#[serde(deny_unknown_fields)] +pub struct RedbDirectoryServiceConfig { + is_temporary: bool, + #[serde(default)] + /// required when is_temporary = false + path: Option<PathBuf>, +} + +impl TryFrom<url::Url> for RedbDirectoryServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + // redb doesn't support host, and a path can be provided (otherwise + // it'll live in memory only). + if url.has_host() { + return Err(Error::StorageError("no host allowed".to_string()).into()); + } + + Ok(if url.path().is_empty() { + RedbDirectoryServiceConfig { + is_temporary: true, + path: None, + } + } else { + RedbDirectoryServiceConfig { + is_temporary: false, + path: Some(url.path().into()), + } + }) + } +} + +#[async_trait] +impl ServiceBuilder for RedbDirectoryServiceConfig { + type Output = dyn DirectoryService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn DirectoryService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + match self { + RedbDirectoryServiceConfig { + is_temporary: true, + path: None, + } => Ok(Arc::new(RedbDirectoryService::new_temporary()?)), + RedbDirectoryServiceConfig { + is_temporary: true, + path: Some(_), + } => Err(Error::StorageError( + "Temporary RedbDirectoryService can not have path".into(), + ) + .into()), + RedbDirectoryServiceConfig { + is_temporary: false, + path: None, + } => Err(Error::StorageError("RedbDirectoryService is missing path".into()).into()), + RedbDirectoryServiceConfig { + is_temporary: false, + path: Some(path), + } => Ok(Arc::new(RedbDirectoryService::new(path.into()).await?)), + } + } +} diff --git a/tvix/castore/src/directoryservice/simple_putter.rs b/tvix/castore/src/directoryservice/simple_putter.rs index 25617ebcac82..b4daaee61b22 100644 --- a/tvix/castore/src/directoryservice/simple_putter.rs +++ b/tvix/castore/src/directoryservice/simple_putter.rs @@ -1,7 +1,6 @@ -use super::ClosureValidator; use super::DirectoryPutter; use super::DirectoryService; -use crate::proto; +use super::{Directory, DirectoryGraph, LeavesToRootValidator}; use crate::B3Digest; use crate::Error; use tonic::async_trait; @@ -14,7 +13,7 @@ use tracing::warn; pub struct SimplePutter<DS: DirectoryService> { directory_service: DS, - directory_validator: Option<ClosureValidator>, + directory_validator: Option<DirectoryGraph<LeavesToRootValidator>>, } impl<DS: DirectoryService> SimplePutter<DS> { @@ -29,11 +28,13 @@ impl<DS: DirectoryService> SimplePutter<DS> { #[async_trait] impl<DS: DirectoryService + 'static> DirectoryPutter for SimplePutter<DS> { #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest()), err)] - async fn put(&mut self, directory: proto::Directory) -> Result<(), Error> { + async fn put(&mut self, directory: Directory) -> Result<(), Error> { match self.directory_validator { None => return Err(Error::StorageError("already closed".to_string())), Some(ref mut validator) => { - validator.add(directory)?; + validator + .add(directory) + .map_err(|e| Error::StorageError(e.to_string()))?; } } @@ -46,7 +47,11 @@ impl<DS: DirectoryService + 'static> DirectoryPutter for SimplePutter<DS> { None => Err(Error::InvalidRequest("already closed".to_string())), Some(validator) => { // retrieve the validated directories. - let directories = validator.finalize()?; + let directories = validator + .validate() + .map_err(|e| Error::StorageError(e.to_string()))? + .drain_leaves_to_root() + .collect::<Vec<_>>(); // Get the root digest, which is at the end (cf. insertion order) let root_digest = directories diff --git a/tvix/castore/src/directoryservice/sled.rs b/tvix/castore/src/directoryservice/sled.rs deleted file mode 100644 index e4a4c2bbed78..000000000000 --- a/tvix/castore/src/directoryservice/sled.rs +++ /dev/null @@ -1,168 +0,0 @@ -use crate::proto::Directory; -use crate::{proto, B3Digest, Error}; -use futures::stream::BoxStream; -use prost::Message; -use std::ops::Deref; -use std::path::Path; -use tonic::async_trait; -use tracing::{instrument, warn}; - -use super::utils::traverse_directory; -use super::{ClosureValidator, DirectoryPutter, DirectoryService}; - -#[derive(Clone)] -pub struct SledDirectoryService { - db: sled::Db, -} - -impl SledDirectoryService { - pub fn new<P: AsRef<Path>>(p: P) -> Result<Self, sled::Error> { - let config = sled::Config::default() - .use_compression(false) // is a required parameter - .path(p); - let db = config.open()?; - - Ok(Self { db }) - } - - pub fn new_temporary() -> Result<Self, sled::Error> { - let config = sled::Config::default().temporary(true); - let db = config.open()?; - - Ok(Self { db }) - } -} - -#[async_trait] -impl DirectoryService for SledDirectoryService { - #[instrument(skip(self, digest), fields(directory.digest = %digest))] - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error> { - match self.db.get(digest.as_slice()) { - // The directory was not found, return - Ok(None) => Ok(None), - - // The directory was found, try to parse the data as Directory message - Ok(Some(data)) => match Directory::decode(&*data) { - Ok(directory) => { - // Validate the retrieved Directory indeed has the - // digest we expect it to have, to detect corruptions. - let actual_digest = directory.digest(); - if actual_digest != *digest { - return Err(Error::StorageError(format!( - "requested directory with digest {}, but got {}", - digest, actual_digest - ))); - } - - // Validate the Directory itself is valid. - if let Err(e) = directory.validate() { - warn!("directory failed validation: {}", e.to_string()); - return Err(Error::StorageError(format!( - "directory {} failed validation: {}", - actual_digest, e, - ))); - } - - Ok(Some(directory)) - } - Err(e) => { - warn!("unable to parse directory {}: {}", digest, e); - Err(Error::StorageError(e.to_string())) - } - }, - // some storage error? - Err(e) => Err(Error::StorageError(e.to_string())), - } - } - - #[instrument(skip(self, directory), fields(directory.digest = %directory.digest()))] - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error> { - let digest = directory.digest(); - - // validate the directory itself. - if let Err(e) = directory.validate() { - return Err(Error::InvalidRequest(format!( - "directory {} failed validation: {}", - digest, e, - ))); - } - // store it - let result = self.db.insert(digest.as_slice(), directory.encode_to_vec()); - if let Err(e) = result { - return Err(Error::StorageError(e.to_string())); - } - Ok(digest) - } - - #[instrument(skip_all, fields(directory.digest = %root_directory_digest))] - fn get_recursive( - &self, - root_directory_digest: &B3Digest, - ) -> BoxStream<Result<proto::Directory, Error>> { - traverse_directory(self.clone(), root_directory_digest) - } - - #[instrument(skip_all)] - fn put_multiple_start(&self) -> Box<(dyn DirectoryPutter + 'static)> - where - Self: Clone, - { - Box::new(SledDirectoryPutter { - tree: self.db.deref().clone(), - directory_validator: Some(Default::default()), - }) - } -} - -/// Buffers Directory messages to be uploaded and inserts them in a batch -/// transaction on close. -pub struct SledDirectoryPutter { - tree: sled::Tree, - - /// The directories (inside the directory validator) that we insert later, - /// or None, if they were already inserted. - directory_validator: Option<ClosureValidator>, -} - -#[async_trait] -impl DirectoryPutter for SledDirectoryPutter { - #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest()), err)] - async fn put(&mut self, directory: proto::Directory) -> Result<(), Error> { - match self.directory_validator { - None => return Err(Error::StorageError("already closed".to_string())), - Some(ref mut validator) => { - validator.add(directory)?; - } - } - - Ok(()) - } - - #[instrument(level = "trace", skip_all, ret, err)] - async fn close(&mut self) -> Result<B3Digest, Error> { - match self.directory_validator.take() { - None => Err(Error::InvalidRequest("already closed".to_string())), - Some(validator) => { - // retrieve the validated directories. - let directories = validator.finalize()?; - - // Get the root digest, which is at the end (cf. insertion order) - let root_digest = directories - .last() - .ok_or_else(|| Error::InvalidRequest("got no directories".to_string()))? - .digest(); - - let mut batch = sled::Batch::default(); - for directory in directories { - batch.insert(directory.digest().as_slice(), directory.encode_to_vec()); - } - - self.tree - .apply_batch(batch) - .map_err(|e| Error::StorageError(format!("unable to apply batch: {}", e)))?; - - Ok(root_digest) - } - } - } -} diff --git a/tvix/castore/src/directoryservice/tests/mod.rs b/tvix/castore/src/directoryservice/tests/mod.rs index 50c8a5c6d3d5..d394a5679c32 100644 --- a/tvix/castore/src/directoryservice/tests/mod.rs +++ b/tvix/castore/src/directoryservice/tests/mod.rs @@ -8,10 +8,8 @@ use rstest_reuse::{self, *}; use super::DirectoryService; use crate::directoryservice; -use crate::{ - fixtures::{DIRECTORY_A, DIRECTORY_B, DIRECTORY_C}, - proto::{self, Directory}, -}; +use crate::fixtures::{DIRECTORY_A, DIRECTORY_B, DIRECTORY_C, DIRECTORY_D}; +use crate::{Directory, Node}; mod utils; use self::utils::make_grpc_directory_service_client; @@ -25,16 +23,27 @@ use self::utils::make_grpc_directory_service_client; #[rstest] #[case::grpc(make_grpc_directory_service_client().await)] #[case::memory(directoryservice::from_addr("memory://").await.unwrap())] -#[case::sled(directoryservice::from_addr("sled://").await.unwrap())] -#[cfg_attr(feature = "cloud", case::bigtable(directoryservice::from_addr("bigtable://instance-1?project_id=project-1&table_name=table-1&family_name=cf1").await.unwrap()))] +#[case::redb(directoryservice::from_addr("redb://").await.unwrap())] +#[case::objectstore(directoryservice::from_addr("objectstore+memory://").await.unwrap())] +#[cfg_attr(all(feature = "cloud", feature = "integration"), case::bigtable(directoryservice::from_addr("bigtable://instance-1?project_id=project-1&table_name=table-1&family_name=cf1").await.unwrap()))] pub fn directory_services(#[case] directory_service: impl DirectoryService) {} -/// Ensures asking for a directory that doesn't exist returns a Ok(None). +/// Ensures asking for a directory that doesn't exist returns a Ok(None), and a get_recursive +/// returns an empty stream. #[apply(directory_services)] #[tokio::test] async fn test_non_exist(directory_service: impl DirectoryService) { - let resp = directory_service.get(&DIRECTORY_A.digest()).await; - assert!(resp.unwrap().is_none()) + // single get + assert_eq!(Ok(None), directory_service.get(&DIRECTORY_A.digest()).await); + + // recursive get + assert_eq!( + Vec::<Result<Directory, crate::Error>>::new(), + directory_service + .get_recursive(&DIRECTORY_A.digest()) + .collect::<Vec<Result<Directory, crate::Error>>>() + .await + ); } /// Putting a single directory into the store, and then getting it out both via @@ -122,6 +131,46 @@ async fn put_get_multiple_dedup(directory_service: impl DirectoryService) { ) } +/// This tests the insertion and retrieval of a closure which contains a duplicated directory +/// (DIRECTORY_A, which is an empty directory), once in the root, and once in a subdir. +#[apply(directory_services)] +#[tokio::test] +async fn put_get_foo(directory_service: impl DirectoryService) { + let mut handle = directory_service.put_multiple_start(); + handle.put(DIRECTORY_A.clone()).await.unwrap(); + handle.put(DIRECTORY_B.clone()).await.unwrap(); + handle.put(DIRECTORY_D.clone()).await.unwrap(); + let root_digest = handle.close().await.unwrap(); + assert_eq!( + DIRECTORY_D.digest(), + root_digest, + "root digest should match" + ); + + // Ensure we can get the closure back out of the service, and it is returned in a valid order + // (there are multiple valid possibilities) + let retrieved_closure = directory_service + .get_recursive(&DIRECTORY_D.digest()) + .collect::<Vec<_>>() + .await; + + let valid_closures = [ + vec![ + Ok(DIRECTORY_D.clone()), + Ok(DIRECTORY_B.clone()), + Ok(DIRECTORY_A.clone()), + ], + vec![ + Ok(DIRECTORY_D.clone()), + Ok(DIRECTORY_A.clone()), + Ok(DIRECTORY_B.clone()), + ], + ]; + if !valid_closures.contains(&retrieved_closure) { + panic!("invalid closure returned: {:?}", retrieved_closure); + } +} + /// Uploading A, then C (referring to A twice), then B (itself referring to A) should fail during close, /// as B itself would be left unconnected. #[apply(directory_services)] @@ -160,58 +209,20 @@ async fn upload_reject_dangling_pointer(directory_service: impl DirectoryService } } -/// Try uploading a Directory failing its internal validation, ensure it gets -/// rejected. -#[apply(directory_services)] -#[tokio::test] -async fn upload_reject_failing_validation(directory_service: impl DirectoryService) { - let broken_directory = Directory { - symlinks: vec![proto::SymlinkNode { - name: "".into(), // wrong! - target: "doesntmatter".into(), - }], - ..Default::default() - }; - assert!(broken_directory.validate().is_err()); - - // Try to upload via single upload. - assert!( - directory_service - .put(broken_directory.clone()) - .await - .is_err(), - "single upload must fail" - ); - - // Try to upload via put_multiple. We're a bit more permissive here, the - // intermediate .put() might succeed, due to client-side bursting (in the - // case of gRPC), but then the close MUST fail. - let mut handle = directory_service.put_multiple_start(); - if handle.put(broken_directory).await.is_ok() { - assert!( - handle.close().await.is_err(), - "when succeeding put, close must fail" - ) - } -} - /// Try uploading a Directory that refers to a previously-uploaded directory. /// Both pass their isolated validation, but the size field in the parent is wrong. /// This should be rejected. #[apply(directory_services)] #[tokio::test] async fn upload_reject_wrong_size(directory_service: impl DirectoryService) { - let wrong_parent_directory = Directory { - directories: vec![proto::DirectoryNode { - name: "foo".into(), - digest: DIRECTORY_A.digest().into(), + let wrong_parent_directory = Directory::try_from_iter([( + "foo".try_into().unwrap(), + Node::Directory { + digest: DIRECTORY_A.digest(), size: DIRECTORY_A.size() + 42, // wrong! - }], - ..Default::default() - }; - - // Make sure isolated validation itself is ok - assert!(wrong_parent_directory.validate().is_ok()); + }, + )]) + .unwrap(); // Now upload both. Ensure it either fails during the second put, or during // the close. diff --git a/tvix/castore/src/directoryservice/tests/utils.rs b/tvix/castore/src/directoryservice/tests/utils.rs index 0f706695eec8..3d245ea412d5 100644 --- a/tvix/castore/src/directoryservice/tests/utils.rs +++ b/tvix/castore/src/directoryservice/tests/utils.rs @@ -6,6 +6,7 @@ use crate::{ proto::directory_service_server::DirectoryServiceServer, }; +use hyper_util::rt::TokioIo; use tonic::transport::{Endpoint, Server, Uri}; /// Constructs and returns a gRPC DirectoryService. @@ -37,7 +38,7 @@ pub async fn make_grpc_directory_service_client() -> Box<dyn DirectoryService> { .unwrap() .connect_with_connector(tower::service_fn(move |_: Uri| { let right = maybe_right.take().unwrap(); - async move { Ok::<_, std::io::Error>(right) } + async move { Ok::<_, std::io::Error>(TokioIo::new(right)) } })) .await .unwrap(), diff --git a/tvix/castore/src/directoryservice/traverse.rs b/tvix/castore/src/directoryservice/traverse.rs index 573581edbdd7..0bd67e9bcf1f 100644 --- a/tvix/castore/src/directoryservice/traverse.rs +++ b/tvix/castore/src/directoryservice/traverse.rs @@ -1,95 +1,64 @@ -use super::DirectoryService; -use crate::{proto::NamedNode, B3Digest, Error}; -use std::os::unix::ffi::OsStrExt; +use crate::{directoryservice::DirectoryService, Error, Node, Path}; use tracing::{instrument, warn}; /// This descends from a (root) node to the given (sub)path, returning the Node /// at that path, or none, if there's nothing at that path. -#[instrument(skip(directory_service))] +#[instrument(skip(directory_service, path), fields(%path))] pub async fn descend_to<DS>( directory_service: DS, - root_node: crate::proto::node::Node, - path: &std::path::Path, -) -> Result<Option<crate::proto::node::Node>, Error> + root_node: Node, + path: impl AsRef<Path> + std::fmt::Display, +) -> Result<Option<Node>, Error> where DS: AsRef<dyn DirectoryService>, { - // strip a possible `/` prefix from the path. - let path = { - if path.starts_with("/") { - path.strip_prefix("/").unwrap() - } else { - path - } - }; - - let mut cur_node = root_node; - let mut it = path.components(); - - loop { - match it.next() { - None => { - // the (remaining) path is empty, return the node we're current at. - return Ok(Some(cur_node)); + let mut parent_node = root_node; + for component in path.as_ref().components_bytes() { + match parent_node { + Node::File { .. } | Node::Symlink { .. } => { + // There's still some path left, but the parent node is no directory. + // This means the path doesn't exist, as we can't reach it. + return Ok(None); } - Some(first_component) => { - match cur_node { - crate::proto::node::Node::File(_) | crate::proto::node::Node::Symlink(_) => { - // There's still some path left, but the current node is no directory. - // This means the path doesn't exist, as we can't reach it. - return Ok(None); - } - crate::proto::node::Node::Directory(directory_node) => { - let digest: B3Digest = directory_node.digest.try_into().map_err(|_e| { - Error::StorageError("invalid digest length".to_string()) + Node::Directory { digest, .. } => { + // fetch the linked node from the directory_service. + let directory = + directory_service + .as_ref() + .get(&digest) + .await? + .ok_or_else(|| { + // If we didn't get the directory node that's linked, that's a store inconsistency, bail out! + warn!("directory {} does not exist", digest); + + Error::StorageError(format!("directory {} does not exist", digest)) })?; - // fetch the linked node from the directory_service - match directory_service.as_ref().get(&digest).await? { - // If we didn't get the directory node that's linked, that's a store inconsistency, bail out! - None => { - warn!("directory {} does not exist", digest); - - return Err(Error::StorageError(format!( - "directory {} does not exist", - digest - ))); - } - Some(directory) => { - // look for first_component in the [Directory]. - // FUTUREWORK: as the nodes() iterator returns in a sorted fashion, we - // could stop as soon as e.name is larger than the search string. - let child_node = directory.nodes().find(|n| { - n.get_name() == first_component.as_os_str().as_bytes() - }); - - match child_node { - // child node not found means there's no such element inside the directory. - None => { - return Ok(None); - } - // child node found, return to top-of loop to find the next - // node in the path. - Some(child_node) => { - cur_node = child_node; - } - } - } - } - } - } + // look for the component in the [Directory]. + if let Some((_child_name, child_node)) = directory + .into_nodes() + .find(|(name, _node)| name.as_ref() == component) + { + // child node found, update prev_node to that and continue. + parent_node = child_node.clone(); + } else { + // child node not found means there's no such element inside the directory. + return Ok(None); + }; } } } + + // We traversed the entire path, so this must be the node. + Ok(Some(parent_node)) } #[cfg(test)] mod tests { - use std::path::PathBuf; - use crate::{ directoryservice, - fixtures::{DIRECTORY_COMPLICATED, DIRECTORY_WITH_KEEP}, + fixtures::{DIRECTORY_COMPLICATED, DIRECTORY_WITH_KEEP, EMPTY_BLOB_DIGEST}, + Node, PathBuf, }; use super::descend_to; @@ -111,28 +80,30 @@ mod tests { handle.close().await.expect("must upload"); // construct the node for DIRECTORY_COMPLICATED - let node_directory_complicated = - crate::proto::node::Node::Directory(crate::proto::DirectoryNode { - name: "doesntmatter".into(), - digest: DIRECTORY_COMPLICATED.digest().into(), - size: DIRECTORY_COMPLICATED.size(), - }); + let node_directory_complicated = Node::Directory { + digest: DIRECTORY_COMPLICATED.digest(), + size: DIRECTORY_COMPLICATED.size(), + }; // construct the node for DIRECTORY_COMPLICATED - let node_directory_with_keep = crate::proto::node::Node::Directory( - DIRECTORY_COMPLICATED.directories.first().unwrap().clone(), - ); + let node_directory_with_keep = Node::Directory { + digest: DIRECTORY_WITH_KEEP.digest(), + size: DIRECTORY_WITH_KEEP.size(), + }; // construct the node for the .keep file - let node_file_keep = - crate::proto::node::Node::File(DIRECTORY_WITH_KEEP.files.first().unwrap().clone()); + let node_file_keep = Node::File { + digest: EMPTY_BLOB_DIGEST.clone(), + size: 0, + executable: false, + }; // traversal to an empty subpath should return the root node. { let resp = descend_to( &directory_service, node_directory_complicated.clone(), - &PathBuf::from(""), + "".parse::<PathBuf>().unwrap(), ) .await .expect("must succeed"); @@ -145,7 +116,7 @@ mod tests { let resp = descend_to( &directory_service, node_directory_complicated.clone(), - &PathBuf::from("keep"), + "keep".parse::<PathBuf>().unwrap(), ) .await .expect("must succeed"); @@ -158,7 +129,7 @@ mod tests { let resp = descend_to( &directory_service, node_directory_complicated.clone(), - &PathBuf::from("keep/.keep"), + "keep/.keep".parse::<PathBuf>().unwrap(), ) .await .expect("must succeed"); @@ -166,25 +137,12 @@ mod tests { assert_eq!(Some(node_file_keep.clone()), resp); } - // traversal to `keep/.keep` should return the node for the .keep file - { - let resp = descend_to( - &directory_service, - node_directory_complicated.clone(), - &PathBuf::from("/keep/.keep"), - ) - .await - .expect("must succeed"); - - assert_eq!(Some(node_file_keep), resp); - } - // traversal to `void` should return None (doesn't exist) { let resp = descend_to( &directory_service, node_directory_complicated.clone(), - &PathBuf::from("void"), + "void".parse::<PathBuf>().unwrap(), ) .await .expect("must succeed"); @@ -192,12 +150,12 @@ mod tests { assert_eq!(None, resp); } - // traversal to `void` should return None (doesn't exist) + // traversal to `v/oid` should return None (doesn't exist) { let resp = descend_to( &directory_service, node_directory_complicated.clone(), - &PathBuf::from("//v/oid"), + "v/oid".parse::<PathBuf>().unwrap(), ) .await .expect("must succeed"); @@ -211,25 +169,12 @@ mod tests { let resp = descend_to( &directory_service, node_directory_complicated.clone(), - &PathBuf::from("keep/.keep/foo"), + "keep/.keep/foo".parse::<PathBuf>().unwrap(), ) .await .expect("must succeed"); assert_eq!(None, resp); } - - // traversal to a subpath of '/' should return the root node. - { - let resp = descend_to( - &directory_service, - node_directory_complicated.clone(), - &PathBuf::from("/"), - ) - .await - .expect("must succeed"); - - assert_eq!(Some(node_directory_complicated), resp); - } } } diff --git a/tvix/castore/src/directoryservice/utils.rs b/tvix/castore/src/directoryservice/utils.rs index 01c521076c9c..d073c2c3c8ec 100644 --- a/tvix/castore/src/directoryservice/utils.rs +++ b/tvix/castore/src/directoryservice/utils.rs @@ -1,19 +1,22 @@ +use super::Directory; use super::DirectoryService; -use crate::proto; use crate::B3Digest; use crate::Error; -use async_stream::stream; +use crate::Node; +use async_stream::try_stream; use futures::stream::BoxStream; use std::collections::{HashSet, VecDeque}; +use tracing::instrument; use tracing::warn; -/// Traverses a [proto::Directory] from the root to the children. +/// Traverses a [Directory] from the root to the children. /// /// This is mostly BFS, but directories are only returned once. +#[instrument(skip(directory_service))] pub fn traverse_directory<'a, DS: DirectoryService + 'static>( directory_service: DS, root_directory_digest: &B3Digest, -) -> BoxStream<'a, Result<proto::Directory, Error>> { +) -> BoxStream<'a, Result<Directory, Error>> { // The list of all directories that still need to be traversed. The next // element is picked from the front, new elements are enqueued at the // back. @@ -23,60 +26,50 @@ pub fn traverse_directory<'a, DS: DirectoryService + 'static>( // We omit sending the same directories multiple times. let mut sent_directory_digests: HashSet<B3Digest> = HashSet::new(); - let stream = stream! { + let root_directory_digest = root_directory_digest.clone(); + + Box::pin(try_stream! { while let Some(current_directory_digest) = worklist_directory_digests.pop_front() { - match directory_service.get(¤t_directory_digest).await { - // if it's not there, we have an inconsistent store! - Ok(None) => { + let current_directory = match directory_service.get(¤t_directory_digest).await.map_err(|e| { + warn!("failed to look up directory"); + Error::StorageError(format!( + "unable to look up directory {}: {}", + current_directory_digest, e + )) + })? { + // the root node of the requested closure was not found, return an empty list + None if current_directory_digest == root_directory_digest => break, + // if a child directory of the closure is not there, we have an inconsistent store! + None => { warn!("directory {} does not exist", current_directory_digest); - yield Err(Error::StorageError(format!( + Err(Error::StorageError(format!( "directory {} does not exist", current_directory_digest - ))); - } - Err(e) => { - warn!("failed to look up directory"); - yield Err(Error::StorageError(format!( - "unable to look up directory {}: {}", - current_directory_digest, e - ))); + )))?; + break; } + Some(dir) => dir, + }; - // if we got it - Ok(Some(current_directory)) => { - // validate, we don't want to send invalid directories. - if let Err(e) = current_directory.validate() { - warn!("directory failed validation: {}", e.to_string()); - yield Err(Error::StorageError(format!( - "invalid directory: {}", - current_directory_digest - ))); - } - - // We're about to send this directory, so let's avoid sending it again if a - // descendant has it. - sent_directory_digests.insert(current_directory_digest); - - // enqueue all child directory digests to the work queue, as - // long as they're not part of the worklist or already sent. - // This panics if the digest looks invalid, it's supposed to be checked first. - for child_directory_node in ¤t_directory.directories { - // TODO: propagate error - let child_digest: B3Digest = child_directory_node.digest.clone().try_into().unwrap(); + // We're about to send this directory, so let's avoid sending it again if a + // descendant has it. + sent_directory_digests.insert(current_directory_digest); - if worklist_directory_digests.contains(&child_digest) - || sent_directory_digests.contains(&child_digest) - { - continue; - } - worklist_directory_digests.push_back(child_digest); + // enqueue all child directory digests to the work queue, as + // long as they're not part of the worklist or already sent. + // This panics if the digest looks invalid, it's supposed to be checked first. + for (_, child_directory_node) in current_directory.nodes() { + if let Node::Directory{digest: child_digest, ..} = child_directory_node { + if worklist_directory_digests.contains(child_digest) + || sent_directory_digests.contains(child_digest) + { + continue; } - - yield Ok(current_directory); + worklist_directory_digests.push_back(child_digest.clone()); } - }; - } - }; + } - Box::pin(stream) + yield current_directory; + } + }) } diff --git a/tvix/castore/src/errors.rs b/tvix/castore/src/errors.rs index e807a19b9e61..1c4605200842 100644 --- a/tvix/castore/src/errors.rs +++ b/tvix/castore/src/errors.rs @@ -1,8 +1,13 @@ -use std::sync::PoisonError; +use bstr::ByteSlice; use thiserror::Error; use tokio::task::JoinError; use tonic::Status; +use crate::{ + path::{PathComponent, PathComponentError}, + SymlinkTargetError, +}; + /// Errors related to communication with the store. #[derive(Debug, Error, PartialEq)] pub enum Error { @@ -13,12 +18,52 @@ pub enum Error { StorageError(String), } -impl<T> From<PoisonError<T>> for Error { - fn from(value: PoisonError<T>) -> Self { - Error::StorageError(value.to_string()) +/// Errors that occur during construction of [crate::Node] +#[derive(Debug, thiserror::Error, PartialEq)] +pub enum ValidateNodeError { + /// Invalid digest length encountered + #[error("invalid digest length: {0}")] + InvalidDigestLen(usize), + /// Invalid symlink target + #[error("Invalid symlink target: {0}")] + InvalidSymlinkTarget(SymlinkTargetError), +} + +impl From<crate::digests::Error> for ValidateNodeError { + fn from(e: crate::digests::Error) -> Self { + match e { + crate::digests::Error::InvalidDigestLen(n) => ValidateNodeError::InvalidDigestLen(n), + } } } +/// Errors that can occur when populating [crate::Directory] messages, +/// or parsing [crate::proto::Directory] +#[derive(Debug, thiserror::Error, PartialEq)] +pub enum DirectoryError { + /// Multiple elements with the same name encountered + #[error("{:?} is a duplicate name", .0)] + DuplicateName(PathComponent), + /// Node failed validation + #[error("invalid node with name {}: {:?}", .0.as_bstr(), .1.to_string())] + InvalidNode(bytes::Bytes, ValidateNodeError), + #[error("Total size exceeds u64::MAX")] + SizeOverflow, + /// Invalid name encountered + #[error("Invalid name: {0}")] + InvalidName(PathComponentError), + /// This can occur if a protobuf node with a name is passed where we expect + /// it to be anonymous. + #[error("Name is set when it shouldn't")] + NameInAnonymousNode, + /// Elements are not in sorted order. Can only happen on protos + #[error("{:?} is not sorted", .0.as_bstr())] + WrongSorting(bytes::Bytes), + /// This can only happen if there's an unknown node type (on protos) + #[error("No node set")] + NoNodeSet, +} + impl From<JoinError> for Error { fn from(value: JoinError) -> Self { Error::StorageError(value.to_string()) @@ -40,6 +85,42 @@ impl From<crate::tonic::Error> for Error { } } +impl From<redb::Error> for Error { + fn from(value: redb::Error) -> Self { + Error::StorageError(value.to_string()) + } +} + +impl From<redb::DatabaseError> for Error { + fn from(value: redb::DatabaseError) -> Self { + Error::StorageError(value.to_string()) + } +} + +impl From<redb::TableError> for Error { + fn from(value: redb::TableError) -> Self { + Error::StorageError(value.to_string()) + } +} + +impl From<redb::TransactionError> for Error { + fn from(value: redb::TransactionError) -> Self { + Error::StorageError(value.to_string()) + } +} + +impl From<redb::StorageError> for Error { + fn from(value: redb::StorageError) -> Self { + Error::StorageError(value.to_string()) + } +} + +impl From<redb::CommitError> for Error { + fn from(value: redb::CommitError) -> Self { + Error::StorageError(value.to_string()) + } +} + impl From<std::io::Error> for Error { fn from(value: std::io::Error) -> Self { if value.kind() == std::io::ErrorKind::InvalidInput { diff --git a/tvix/castore/src/fixtures.rs b/tvix/castore/src/fixtures.rs index a206d9b7ddc6..db0ee59daf60 100644 --- a/tvix/castore/src/fixtures.rs +++ b/tvix/castore/src/fixtures.rs @@ -1,88 +1,120 @@ -use crate::{ - proto::{self, Directory, DirectoryNode, FileNode, SymlinkNode}, - B3Digest, -}; -use lazy_static::lazy_static; +use bytes::Bytes; +use std::sync::LazyLock; + +use crate::{B3Digest, Directory, Node}; pub const HELLOWORLD_BLOB_CONTENTS: &[u8] = b"Hello World!"; pub const EMPTY_BLOB_CONTENTS: &[u8] = b""; -lazy_static! { - pub static ref DUMMY_DIGEST: B3Digest = { - let u = [0u8; 32]; - (&u).into() - }; - pub static ref DUMMY_DIGEST_2: B3Digest = { - let mut u = [0u8; 32]; - u[0] = 0x10; - (&u).into() - }; - pub static ref DUMMY_DATA_1: bytes::Bytes = vec![0x01, 0x02, 0x03].into(); - pub static ref DUMMY_DATA_2: bytes::Bytes = vec![0x04, 0x05].into(); +pub static DUMMY_DIGEST: LazyLock<B3Digest> = LazyLock::new(|| (&[0u8; 32]).into()); +pub static DUMMY_DIGEST_2: LazyLock<B3Digest> = LazyLock::new(|| { + let mut u = [0u8; 32]; + u[0] = 0x10; + (&u).into() +}); +pub static DUMMY_DATA_1: LazyLock<Bytes> = LazyLock::new(|| vec![0x01, 0x02, 0x03].into()); +pub static DUMMY_DATA_2: LazyLock<Bytes> = LazyLock::new(|| vec![0x04, 0x05].into()); - pub static ref HELLOWORLD_BLOB_DIGEST: B3Digest = - blake3::hash(HELLOWORLD_BLOB_CONTENTS).as_bytes().into(); - pub static ref EMPTY_BLOB_DIGEST: B3Digest = - blake3::hash(EMPTY_BLOB_CONTENTS).as_bytes().into(); +pub static HELLOWORLD_BLOB_DIGEST: LazyLock<B3Digest> = + LazyLock::new(|| blake3::hash(HELLOWORLD_BLOB_CONTENTS).as_bytes().into()); +pub static EMPTY_BLOB_DIGEST: LazyLock<B3Digest> = + LazyLock::new(|| blake3::hash(EMPTY_BLOB_CONTENTS).as_bytes().into()); - // 2 bytes - pub static ref BLOB_A: bytes::Bytes = vec![0x00, 0x01].into(); - pub static ref BLOB_A_DIGEST: B3Digest = blake3::hash(&BLOB_A).as_bytes().into(); +// 2 bytes +pub static BLOB_A: LazyLock<Bytes> = LazyLock::new(|| vec![0x00, 0x01].into()); +pub static BLOB_A_DIGEST: LazyLock<B3Digest> = + LazyLock::new(|| blake3::hash(&BLOB_A).as_bytes().into()); - // 1MB - pub static ref BLOB_B: bytes::Bytes = (0..255).collect::<Vec<u8>>().repeat(4 * 1024).into(); - pub static ref BLOB_B_DIGEST: B3Digest = blake3::hash(&BLOB_B).as_bytes().into(); +// 1MB +pub static BLOB_B: LazyLock<Bytes> = + LazyLock::new(|| (0..255).collect::<Vec<u8>>().repeat(4 * 1024).into()); +pub static BLOB_B_DIGEST: LazyLock<B3Digest> = + LazyLock::new(|| blake3::hash(&BLOB_B).as_bytes().into()); - // Directories - pub static ref DIRECTORY_WITH_KEEP: proto::Directory = proto::Directory { - directories: vec![], - files: vec![FileNode { - name: b".keep".to_vec().into(), - digest: EMPTY_BLOB_DIGEST.clone().into(), - size: 0, - executable: false, - }], - symlinks: vec![], - }; - pub static ref DIRECTORY_COMPLICATED: proto::Directory = proto::Directory { - directories: vec![DirectoryNode { - name: b"keep".to_vec().into(), - digest: DIRECTORY_WITH_KEEP.digest().into(), - size: DIRECTORY_WITH_KEEP.size(), - }], - files: vec![FileNode { - name: b".keep".to_vec().into(), - digest: EMPTY_BLOB_DIGEST.clone().into(), +// Directories +pub static DIRECTORY_WITH_KEEP: LazyLock<Directory> = LazyLock::new(|| { + Directory::try_from_iter([( + ".keep".try_into().unwrap(), + Node::File { + digest: EMPTY_BLOB_DIGEST.clone(), size: 0, executable: false, - }], - symlinks: vec![SymlinkNode { - name: b"aa".to_vec().into(), - target: b"/nix/store/somewhereelse".to_vec().into(), - }], - }; - pub static ref DIRECTORY_A: Directory = Directory::default(); - pub static ref DIRECTORY_B: Directory = Directory { - directories: vec![DirectoryNode { - name: b"a".to_vec().into(), - digest: DIRECTORY_A.digest().into(), + }, + )]) + .unwrap() +}); +pub static DIRECTORY_COMPLICATED: LazyLock<Directory> = LazyLock::new(|| { + Directory::try_from_iter([ + ( + "keep".try_into().unwrap(), + Node::Directory { + digest: DIRECTORY_WITH_KEEP.digest(), + size: DIRECTORY_WITH_KEEP.size(), + }, + ), + ( + ".keep".try_into().unwrap(), + Node::File { + digest: EMPTY_BLOB_DIGEST.clone(), + size: 0, + executable: false, + }, + ), + ( + "aa".try_into().unwrap(), + Node::Symlink { + target: "/nix/store/somewhereelse".try_into().unwrap(), + }, + ), + ]) + .unwrap() +}); +pub static DIRECTORY_A: LazyLock<Directory> = LazyLock::new(Directory::new); +pub static DIRECTORY_B: LazyLock<Directory> = LazyLock::new(|| { + Directory::try_from_iter([( + "a".try_into().unwrap(), + Node::Directory { + digest: DIRECTORY_A.digest(), size: DIRECTORY_A.size(), - }], - ..Default::default() - }; - pub static ref DIRECTORY_C: Directory = Directory { - directories: vec![ - DirectoryNode { - name: b"a".to_vec().into(), - digest: DIRECTORY_A.digest().into(), + }, + )]) + .unwrap() +}); +pub static DIRECTORY_C: LazyLock<Directory> = LazyLock::new(|| { + Directory::try_from_iter([ + ( + "a".try_into().unwrap(), + Node::Directory { + digest: DIRECTORY_A.digest(), + size: DIRECTORY_A.size(), + }, + ), + ( + "a'".try_into().unwrap(), + Node::Directory { + digest: DIRECTORY_A.digest(), size: DIRECTORY_A.size(), }, - DirectoryNode { - name: b"a'".to_vec().into(), - digest: DIRECTORY_A.digest().into(), + ), + ]) + .unwrap() +}); +pub static DIRECTORY_D: LazyLock<Directory> = LazyLock::new(|| { + Directory::try_from_iter([ + ( + "a".try_into().unwrap(), + Node::Directory { + digest: DIRECTORY_A.digest(), size: DIRECTORY_A.size(), - } - ], - ..Default::default() - }; -} + }, + ), + ( + "b".try_into().unwrap(), + Node::Directory { + digest: DIRECTORY_B.digest(), + size: DIRECTORY_B.size(), + }, + ), + ]) + .unwrap() +}); diff --git a/tvix/castore/src/fs/fuse.rs b/tvix/castore/src/fs/fuse/mod.rs index cd50618ff5bc..64ef29ed2aa1 100644 --- a/tvix/castore/src/fs/fuse.rs +++ b/tvix/castore/src/fs/fuse/mod.rs @@ -1,8 +1,13 @@ -use std::{io, path::Path, sync::Arc, thread}; +use std::{io, path::Path, sync::Arc}; use fuse_backend_rs::{api::filesystem::FileSystem, transport::FuseSession}; +use parking_lot::Mutex; +use threadpool::ThreadPool; use tracing::{error, instrument}; +#[cfg(test)] +mod tests; + struct FuseServer<FS> where FS: FileSystem + Sync + Send, @@ -46,9 +51,12 @@ where } } +/// Starts a [Filesystem] with the specified number of threads, and provides +/// functions to unmount, and wait for it to have completed. +#[derive(Clone)] pub struct FuseDaemon { - session: FuseSession, - threads: Vec<thread::JoinHandle<()>>, + session: Arc<Mutex<FuseSession>>, + threads: Arc<ThreadPool>, } impl FuseDaemon { @@ -56,7 +64,7 @@ impl FuseDaemon { pub fn new<FS, P>( fs: FS, mountpoint: P, - threads: usize, + num_threads: usize, allow_other: bool, ) -> Result<Self, io::Error> where @@ -73,40 +81,49 @@ impl FuseDaemon { session .mount() .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?; - let mut join_handles = Vec::with_capacity(threads); - for _ in 0..threads { + + // construct a thread pool + let threads = threadpool::Builder::new() + .num_threads(num_threads) + .thread_name("fuse_server".to_string()) + .build(); + + for _ in 0..num_threads { + // for each thread requested, create and start a FuseServer accepting requests. let mut server = FuseServer { server: server.clone(), channel: session .new_channel() .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?, }; - let join_handle = thread::Builder::new() - .name("fuse_server".to_string()) - .spawn(move || { - let _ = server.start(); - })?; - join_handles.push(join_handle); + + threads.execute(move || { + let _ = server.start(); + }); } Ok(FuseDaemon { - session, - threads: join_handles, + session: Arc::new(Mutex::new(session)), + threads: Arc::new(threads), }) } + /// Waits for all threads to finish. + #[instrument(skip_all)] + pub fn wait(&self) { + self.threads.join() + } + + /// Send the unmount command, and waits for all threads to finish. #[instrument(skip_all, err)] - pub fn unmount(&mut self) -> Result<(), io::Error> { + pub fn unmount(&self) -> Result<(), io::Error> { + // Send the unmount command. self.session + .lock() .umount() .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?; - for thread in self.threads.drain(..) { - thread.join().map_err(|_| { - io::Error::new(io::ErrorKind::Other, "failed to join fuse server thread") - })?; - } - + self.wait(); Ok(()) } } diff --git a/tvix/castore/src/fs/tests.rs b/tvix/castore/src/fs/fuse/tests.rs index d6eeb8a4113d..0d68af090daf 100644 --- a/tvix/castore/src/fs/tests.rs +++ b/tvix/castore/src/fs/fuse/tests.rs @@ -1,5 +1,4 @@ use bstr::ByteSlice; -use bytes::Bytes; use std::{ collections::BTreeMap, ffi::{OsStr, OsString}, @@ -11,13 +10,15 @@ use std::{ use tempfile::TempDir; use tokio_stream::{wrappers::ReadDirStream, StreamExt}; -use super::{fuse::FuseDaemon, TvixStoreFs}; -use crate::proto as castorepb; -use crate::proto::node::Node; +use super::FuseDaemon; use crate::{ blobservice::{BlobService, MemoryBlobService}, directoryservice::{DirectoryService, MemoryDirectoryService}, - fixtures, + fixtures, Node, +}; +use crate::{ + fs::{TvixStoreFs, XATTR_NAME_BLOB_DIGEST, XATTR_NAME_DIRECTORY_DIGEST}, + PathComponent, }; const BLOB_A_NAME: &str = "00000000000000000000000000000000-test"; @@ -38,14 +39,14 @@ fn gen_svcs() -> (Arc<dyn BlobService>, Arc<dyn DirectoryService>) { fn do_mount<P: AsRef<Path>, BS, DS>( blob_service: BS, directory_service: DS, - root_nodes: BTreeMap<bytes::Bytes, Node>, + root_nodes: BTreeMap<PathComponent, Node>, mountpoint: P, list_root: bool, show_xattr: bool, ) -> io::Result<FuseDaemon> where - BS: AsRef<dyn BlobService> + Send + Sync + Clone + 'static, - DS: AsRef<dyn DirectoryService> + Send + Sync + Clone + 'static, + BS: BlobService + Send + Sync + Clone + 'static, + DS: DirectoryService + Send + Sync + Clone + 'static, { let fs = TvixStoreFs::new( blob_service, @@ -59,7 +60,7 @@ where async fn populate_blob_a( blob_service: &Arc<dyn BlobService>, - root_nodes: &mut BTreeMap<Bytes, Node>, + root_nodes: &mut BTreeMap<PathComponent, Node>, ) { let mut bw = blob_service.open_write().await; tokio::io::copy(&mut Cursor::new(fixtures::BLOB_A.to_vec()), &mut bw) @@ -68,19 +69,18 @@ async fn populate_blob_a( bw.close().await.expect("must succeed closing"); root_nodes.insert( - BLOB_A_NAME.into(), - Node::File(castorepb::FileNode { - name: BLOB_A_NAME.into(), - digest: fixtures::BLOB_A_DIGEST.clone().into(), + BLOB_A_NAME.try_into().unwrap(), + Node::File { + digest: fixtures::BLOB_A_DIGEST.clone(), size: fixtures::BLOB_A.len() as u64, executable: false, - }), + }, ); } async fn populate_blob_b( blob_service: &Arc<dyn BlobService>, - root_nodes: &mut BTreeMap<Bytes, Node>, + root_nodes: &mut BTreeMap<PathComponent, Node>, ) { let mut bw = blob_service.open_write().await; tokio::io::copy(&mut Cursor::new(fixtures::BLOB_B.to_vec()), &mut bw) @@ -89,20 +89,19 @@ async fn populate_blob_b( bw.close().await.expect("must succeed closing"); root_nodes.insert( - BLOB_B_NAME.into(), - Node::File(castorepb::FileNode { - name: BLOB_B_NAME.into(), - digest: fixtures::BLOB_B_DIGEST.clone().into(), + BLOB_B_NAME.try_into().unwrap(), + Node::File { + digest: fixtures::BLOB_B_DIGEST.clone(), size: fixtures::BLOB_B.len() as u64, executable: false, - }), + }, ); } /// adds a blob containing helloworld and marks it as executable async fn populate_blob_helloworld( blob_service: &Arc<dyn BlobService>, - root_nodes: &mut BTreeMap<Bytes, Node>, + root_nodes: &mut BTreeMap<PathComponent, Node>, ) { let mut bw = blob_service.open_write().await; tokio::io::copy( @@ -114,42 +113,39 @@ async fn populate_blob_helloworld( bw.close().await.expect("must succeed closing"); root_nodes.insert( - HELLOWORLD_BLOB_NAME.into(), - Node::File(castorepb::FileNode { - name: HELLOWORLD_BLOB_NAME.into(), - digest: fixtures::HELLOWORLD_BLOB_DIGEST.clone().into(), + HELLOWORLD_BLOB_NAME.try_into().unwrap(), + Node::File { + digest: fixtures::HELLOWORLD_BLOB_DIGEST.clone(), size: fixtures::HELLOWORLD_BLOB_CONTENTS.len() as u64, executable: true, - }), + }, ); } -async fn populate_symlink(root_nodes: &mut BTreeMap<Bytes, Node>) { +async fn populate_symlink(root_nodes: &mut BTreeMap<PathComponent, Node>) { root_nodes.insert( - SYMLINK_NAME.into(), - Node::Symlink(castorepb::SymlinkNode { - name: SYMLINK_NAME.into(), - target: BLOB_A_NAME.into(), - }), + SYMLINK_NAME.try_into().unwrap(), + Node::Symlink { + target: BLOB_A_NAME.try_into().unwrap(), + }, ); } /// This writes a symlink pointing to /nix/store/somewhereelse, /// which is the same symlink target as "aa" inside DIRECTORY_COMPLICATED. -async fn populate_symlink2(root_nodes: &mut BTreeMap<Bytes, Node>) { +async fn populate_symlink2(root_nodes: &mut BTreeMap<PathComponent, Node>) { root_nodes.insert( - SYMLINK_NAME2.into(), - Node::Symlink(castorepb::SymlinkNode { - name: SYMLINK_NAME2.into(), - target: "/nix/store/somewhereelse".into(), - }), + SYMLINK_NAME2.try_into().unwrap(), + Node::Symlink { + target: "/nix/store/somewhereelse".try_into().unwrap(), + }, ); } async fn populate_directory_with_keep( blob_service: &Arc<dyn BlobService>, directory_service: &Arc<dyn DirectoryService>, - root_nodes: &mut BTreeMap<Bytes, Node>, + root_nodes: &mut BTreeMap<PathComponent, Node>, ) { // upload empty blob let mut bw = blob_service.open_write().await; @@ -165,45 +161,42 @@ async fn populate_directory_with_keep( .expect("must succeed uploading"); root_nodes.insert( - DIRECTORY_WITH_KEEP_NAME.into(), - castorepb::node::Node::Directory(castorepb::DirectoryNode { - name: DIRECTORY_WITH_KEEP_NAME.into(), - digest: fixtures::DIRECTORY_WITH_KEEP.digest().into(), + DIRECTORY_WITH_KEEP_NAME.try_into().unwrap(), + Node::Directory { + digest: fixtures::DIRECTORY_WITH_KEEP.digest(), size: fixtures::DIRECTORY_WITH_KEEP.size(), - }), + }, ); } /// Create a root node for DIRECTORY_WITH_KEEP, but don't upload the Directory /// itself. -async fn populate_directorynode_without_directory(root_nodes: &mut BTreeMap<Bytes, Node>) { +async fn populate_directorynode_without_directory(root_nodes: &mut BTreeMap<PathComponent, Node>) { root_nodes.insert( - DIRECTORY_WITH_KEEP_NAME.into(), - castorepb::node::Node::Directory(castorepb::DirectoryNode { - name: DIRECTORY_WITH_KEEP_NAME.into(), - digest: fixtures::DIRECTORY_WITH_KEEP.digest().into(), + DIRECTORY_WITH_KEEP_NAME.try_into().unwrap(), + Node::Directory { + digest: fixtures::DIRECTORY_WITH_KEEP.digest(), size: fixtures::DIRECTORY_WITH_KEEP.size(), - }), + }, ); } /// Insert BLOB_A, but don't provide the blob .keep is pointing to. -async fn populate_filenode_without_blob(root_nodes: &mut BTreeMap<Bytes, Node>) { +async fn populate_filenode_without_blob(root_nodes: &mut BTreeMap<PathComponent, Node>) { root_nodes.insert( - BLOB_A_NAME.into(), - Node::File(castorepb::FileNode { - name: BLOB_A_NAME.into(), - digest: fixtures::BLOB_A_DIGEST.clone().into(), + BLOB_A_NAME.try_into().unwrap(), + Node::File { + digest: fixtures::BLOB_A_DIGEST.clone(), size: fixtures::BLOB_A.len() as u64, executable: false, - }), + }, ); } async fn populate_directory_complicated( blob_service: &Arc<dyn BlobService>, directory_service: &Arc<dyn DirectoryService>, - root_nodes: &mut BTreeMap<Bytes, Node>, + root_nodes: &mut BTreeMap<PathComponent, Node>, ) { // upload empty blob let mut bw = blob_service.open_write().await; @@ -225,12 +218,11 @@ async fn populate_directory_complicated( .expect("must succeed uploading"); root_nodes.insert( - DIRECTORY_COMPLICATED_NAME.into(), - Node::Directory(castorepb::DirectoryNode { - name: DIRECTORY_COMPLICATED_NAME.into(), - digest: fixtures::DIRECTORY_COMPLICATED.digest().into(), + DIRECTORY_COMPLICATED_NAME.try_into().unwrap(), + Node::Directory { + digest: fixtures::DIRECTORY_COMPLICATED.digest(), size: fixtures::DIRECTORY_COMPLICATED.size(), - }), + }, ); } @@ -247,7 +239,7 @@ async fn mount() { let (blob_service, directory_service) = gen_svcs(); - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, BTreeMap::default(), @@ -270,7 +262,7 @@ async fn root() { let tmpdir = TempDir::new().unwrap(); let (blob_service, directory_service) = gen_svcs(); - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, BTreeMap::default(), @@ -304,7 +296,7 @@ async fn root_with_listing() { populate_blob_a(&blob_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -348,7 +340,7 @@ async fn stat_file_at_root() { populate_blob_a(&blob_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -385,7 +377,7 @@ async fn read_file_at_root() { populate_blob_a(&blob_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -422,7 +414,7 @@ async fn read_large_file_at_root() { populate_blob_b(&blob_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -467,7 +459,7 @@ async fn symlink_readlink() { populate_symlink(&mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -514,7 +506,7 @@ async fn read_stat_through_symlink() { populate_blob_a(&blob_service, &mut root_nodes).await; populate_symlink(&mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -559,7 +551,7 @@ async fn read_stat_directory() { populate_directory_with_keep(&blob_service, &directory_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -596,7 +588,7 @@ async fn xattr() { populate_directory_with_keep(&blob_service, &directory_service, &mut root_nodes).await; populate_blob_a(&blob_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -614,12 +606,12 @@ async fn xattr() { // There should be 1 key, XATTR_NAME_DIRECTORY_DIGEST. assert_eq!(1, xattr_names.len(), "there should be 1 xattr name"); assert_eq!( - super::XATTR_NAME_DIRECTORY_DIGEST, + XATTR_NAME_DIRECTORY_DIGEST, xattr_names.first().unwrap().as_encoded_bytes() ); // The key should equal to the string-formatted b3 digest. - let val = xattr::get(&p, OsStr::from_bytes(super::XATTR_NAME_DIRECTORY_DIGEST)) + let val = xattr::get(&p, OsStr::from_bytes(XATTR_NAME_DIRECTORY_DIGEST)) .expect("must succeed") .expect("must be some"); assert_eq!( @@ -643,12 +635,12 @@ async fn xattr() { // There should be 1 key, XATTR_NAME_BLOB_DIGEST. assert_eq!(1, xattr_names.len(), "there should be 1 xattr name"); assert_eq!( - super::XATTR_NAME_BLOB_DIGEST, + XATTR_NAME_BLOB_DIGEST, xattr_names.first().unwrap().as_encoded_bytes() ); // The key should equal to the string-formatted b3 digest. - let val = xattr::get(&p, OsStr::from_bytes(super::XATTR_NAME_BLOB_DIGEST)) + let val = xattr::get(&p, OsStr::from_bytes(XATTR_NAME_BLOB_DIGEST)) .expect("must succeed") .expect("must be some"); assert_eq!( @@ -679,7 +671,7 @@ async fn read_blob_inside_dir() { populate_directory_with_keep(&blob_service, &directory_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -719,7 +711,7 @@ async fn read_blob_deep_inside_dir() { populate_directory_complicated(&blob_service, &directory_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -762,7 +754,7 @@ async fn readdir() { populate_directory_complicated(&blob_service, &directory_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -822,7 +814,7 @@ async fn readdir_deep() { populate_directory_complicated(&blob_service, &directory_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -872,7 +864,7 @@ async fn check_attributes() { populate_symlink(&mut root_nodes).await; populate_blob_helloworld(&blob_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -947,7 +939,7 @@ async fn compare_inodes_directories() { populate_directory_with_keep(&blob_service, &directory_service, &mut root_nodes).await; populate_directory_complicated(&blob_service, &directory_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -991,7 +983,7 @@ async fn compare_inodes_files() { populate_directory_complicated(&blob_service, &directory_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -1040,7 +1032,7 @@ async fn compare_inodes_symlinks() { populate_directory_complicated(&blob_service, &directory_service, &mut root_nodes).await; populate_symlink2(&mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -1083,7 +1075,7 @@ async fn read_wrong_paths_in_root() { populate_blob_a(&blob_service, &mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -1138,7 +1130,7 @@ async fn disallow_writes() { let (blob_service, directory_service) = gen_svcs(); let root_nodes = BTreeMap::default(); - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -1170,7 +1162,7 @@ async fn missing_directory() { populate_directorynode_without_directory(&mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, @@ -1218,7 +1210,7 @@ async fn missing_blob() { populate_filenode_without_blob(&mut root_nodes).await; - let mut fuse_daemon = do_mount( + let fuse_daemon = do_mount( blob_service, directory_service, root_nodes, diff --git a/tvix/castore/src/fs/inodes.rs b/tvix/castore/src/fs/inodes.rs index c22bd4b2ebdc..2696fdede378 100644 --- a/tvix/castore/src/fs/inodes.rs +++ b/tvix/castore/src/fs/inodes.rs @@ -2,10 +2,7 @@ //! about inodes, which present tvix-castore nodes in a filesystem. use std::time::Duration; -use bytes::Bytes; - -use crate::proto as castorepb; -use crate::B3Digest; +use crate::{path::PathComponent, B3Digest, Node}; #[derive(Clone, Debug)] pub enum InodeData { @@ -20,27 +17,23 @@ pub enum InodeData { /// lookup and did fetch the data. #[derive(Clone, Debug)] pub enum DirectoryInodeData { - Sparse(B3Digest, u64), // digest, size - Populated(B3Digest, Vec<(u64, castorepb::node::Node)>), // [(child_inode, node)] + Sparse(B3Digest, u64), // digest, size + Populated(B3Digest, Vec<(u64, PathComponent, Node)>), // [(child_inode, name, node)] } impl InodeData { /// Constructs a new InodeData by consuming a [Node]. - /// It splits off the orginal name, so it can be used later. - pub fn from_node(node: castorepb::node::Node) -> (Self, Bytes) { + pub fn from_node(node: &Node) -> Self { match node { - castorepb::node::Node::Directory(n) => ( - Self::Directory(DirectoryInodeData::Sparse( - n.digest.try_into().unwrap(), - n.size, - )), - n.name, - ), - castorepb::node::Node::File(n) => ( - Self::Regular(n.digest.try_into().unwrap(), n.size, n.executable), - n.name, - ), - castorepb::node::Node::Symlink(n) => (Self::Symlink(n.target), n.name), + Node::Directory { digest, size } => { + Self::Directory(DirectoryInodeData::Sparse(digest.clone(), *size)) + } + Node::File { + digest, + size, + executable, + } => Self::Regular(digest.clone(), *size, *executable), + Node::Symlink { target } => Self::Symlink(target.clone().into()), } } @@ -57,16 +50,18 @@ impl InodeData { children.len() as u64 } }, - mode: match self { - InodeData::Regular(_, _, false) => libc::S_IFREG | 0o444, // no-executable files - InodeData::Regular(_, _, true) => libc::S_IFREG | 0o555, // executable files - InodeData::Symlink(_) => libc::S_IFLNK | 0o444, - InodeData::Directory(_) => libc::S_IFDIR | 0o555, - }, + mode: self.as_fuse_type() | self.mode(), ..Default::default() } } + fn mode(&self) -> u32 { + match self { + InodeData::Regular(_, _, false) | InodeData::Symlink(_) => 0o444, + InodeData::Regular(_, _, true) | InodeData::Directory(_) => 0o555, + } + } + pub fn as_fuse_entry(&self, inode: u64) -> fuse_backend_rs::api::filesystem::Entry { fuse_backend_rs::api::filesystem::Entry { inode, diff --git a/tvix/castore/src/fs/mod.rs b/tvix/castore/src/fs/mod.rs index 826523131fbd..4f50868b8f44 100644 --- a/tvix/castore/src/fs/mod.rs +++ b/tvix/castore/src/fs/mod.rs @@ -9,24 +9,19 @@ pub mod fuse; #[cfg(feature = "virtiofs")] pub mod virtiofs; -#[cfg(test)] -mod tests; - pub use self::root_nodes::RootNodes; use self::{ file_attr::ROOT_FILE_ATTR, inode_tracker::InodeTracker, inodes::{DirectoryInodeData, InodeData}, }; -use crate::proto as castorepb; use crate::{ blobservice::{BlobReader, BlobService}, directoryservice::DirectoryService, - proto::{node::Node, NamedNode}, - B3Digest, + path::PathComponent, + B3Digest, Node, }; use bstr::ByteVec; -use bytes::Bytes; use fuse_backend_rs::abi::fuse_abi::{stat64, OpenOptions}; use fuse_backend_rs::api::filesystem::{ Context, FileSystem, FsOptions, GetxattrReply, ListxattrReply, ROOT_ID, @@ -46,7 +41,7 @@ use tokio::{ io::{AsyncReadExt, AsyncSeekExt}, sync::mpsc, }; -use tracing::{debug, error, instrument, warn, Span}; +use tracing::{debug, error, instrument, warn, Instrument as _, Span}; /// This implements a read-only FUSE filesystem for a tvix-store /// with the passed [BlobService], [DirectoryService] and [RootNodes]. @@ -92,7 +87,7 @@ pub struct TvixStoreFs<BS, DS, RN> { show_xattr: bool, /// This maps a given basename in the root to the inode we allocated for the node. - root_nodes: RwLock<HashMap<Bytes, u64>>, + root_nodes: RwLock<HashMap<PathComponent, u64>>, /// This keeps track of inodes and data alongside them. inode_tracker: RwLock<InodeTracker>, @@ -108,7 +103,7 @@ pub struct TvixStoreFs<BS, DS, RN> { u64, ( Span, - Arc<Mutex<mpsc::Receiver<(usize, Result<Node, crate::Error>)>>>, + Arc<Mutex<mpsc::Receiver<(usize, Result<(PathComponent, Node), crate::Error>)>>>, ), >, >, @@ -126,8 +121,8 @@ pub struct TvixStoreFs<BS, DS, RN> { impl<BS, DS, RN> TvixStoreFs<BS, DS, RN> where - BS: AsRef<dyn BlobService> + Clone + Send, - DS: AsRef<dyn DirectoryService> + Clone + Send + 'static, + BS: BlobService + Clone + Send, + DS: DirectoryService + Clone + Send + 'static, RN: RootNodes + Clone + 'static, { pub fn new( @@ -159,7 +154,7 @@ where /// Retrieves the inode for a given root node basename, if present. /// This obtains a read lock on self.root_nodes. - fn get_inode_for_root_name(&self, name: &[u8]) -> Option<u64> { + fn get_inode_for_root_name(&self, name: &PathComponent) -> Option<u64> { self.root_nodes.read().get(name).cloned() } @@ -170,8 +165,12 @@ where /// It is ok if it's a [DirectoryInodeData::Sparse] - in that case, a lookup /// in self.directory_service is performed, and self.inode_tracker is updated with the /// [DirectoryInodeData::Populated]. + #[allow(clippy::type_complexity)] #[instrument(skip(self), err)] - fn get_directory_children(&self, ino: u64) -> io::Result<(B3Digest, Vec<(u64, Node)>)> { + fn get_directory_children( + &self, + ino: u64, + ) -> io::Result<(B3Digest, Vec<(u64, PathComponent, Node)>)> { let data = self.inode_tracker.read().get(ino).unwrap(); match *data { // if it's populated already, return children. @@ -187,7 +186,7 @@ where .block_on({ let directory_service = self.directory_service.clone(); let parent_digest = parent_digest.to_owned(); - async move { directory_service.as_ref().get(&parent_digest).await } + async move { directory_service.get(&parent_digest).await } })? .ok_or_else(|| { warn!(directory.digest=%parent_digest, "directory not found"); @@ -201,13 +200,13 @@ where let children = { let mut inode_tracker = self.inode_tracker.write(); - let children: Vec<(u64, castorepb::node::Node)> = directory - .nodes() - .map(|child_node| { - let (inode_data, _) = InodeData::from_node(child_node.clone()); + let children: Vec<(u64, PathComponent, Node)> = directory + .into_nodes() + .map(|(child_name, child_node)| { + let inode_data = InodeData::from_node(&child_node); let child_ino = inode_tracker.put(inode_data); - (child_ino, child_node) + (child_ino, child_name, child_node) }) .collect(); @@ -241,12 +240,12 @@ where /// In the case the name can't be found, a libc::ENOENT is returned. fn name_in_root_to_ino_and_data( &self, - name: &std::ffi::CStr, + name: &PathComponent, ) -> io::Result<(u64, Arc<InodeData>)> { // Look up the inode for that root node. // If there's one, [self.inode_tracker] MUST also contain the data, // which we can then return. - if let Some(inode) = self.get_inode_for_root_name(name.to_bytes()) { + if let Some(inode) = self.get_inode_for_root_name(name) { return Ok(( inode, self.inode_tracker @@ -260,7 +259,8 @@ where // We don't have it yet, look it up in [self.root_nodes]. match self.tokio_handle.block_on({ let root_nodes_provider = self.root_nodes_provider.clone(); - async move { root_nodes_provider.get_by_basename(name.to_bytes()).await } + let name = name.clone(); + async move { root_nodes_provider.get_by_basename(&name).await } }) { // if there was an error looking up the root node, propagate up an IO error. Err(_e) => Err(io::Error::from_raw_os_error(libc::EIO)), @@ -268,15 +268,9 @@ where Ok(None) => Err(io::Error::from_raw_os_error(libc::ENOENT)), // The root node does exist Ok(Some(root_node)) => { - // The name must match what's passed in the lookup, otherwise this is also a ENOENT. - if root_node.get_name() != name.to_bytes() { - debug!(root_node.name=?root_node.get_name(), found_node.name=%name.to_string_lossy(), "node name mismatch"); - return Err(io::Error::from_raw_os_error(libc::ENOENT)); - } - // Let's check if someone else beat us to updating the inode tracker and // root_nodes map. This avoids locking inode_tracker for writing. - if let Some(ino) = self.root_nodes.read().get(name.to_bytes()) { + if let Some(ino) = self.root_nodes.read().get(name) { return Ok(( *ino, self.inode_tracker.read().get(*ino).expect("must exist"), @@ -290,9 +284,9 @@ where // insert the (sparse) inode data and register in // self.root_nodes. - let (inode_data, name) = InodeData::from_node(root_node); + let inode_data = InodeData::from_node(&root_node); let ino = inode_tracker.put(inode_data.clone()); - root_nodes.insert(name, ino); + root_nodes.insert(name.to_owned(), ino); Ok((ino, Arc::new(inode_data))) } @@ -306,10 +300,22 @@ const ROOT_NODES_BUFFER_SIZE: usize = 16; const XATTR_NAME_DIRECTORY_DIGEST: &[u8] = b"user.tvix.castore.directory.digest"; const XATTR_NAME_BLOB_DIGEST: &[u8] = b"user.tvix.castore.blob.digest"; +#[cfg(all(feature = "virtiofs", target_os = "linux"))] +impl<BS, DS, RN> fuse_backend_rs::api::filesystem::Layer for TvixStoreFs<BS, DS, RN> +where + BS: BlobService + Clone + Send + 'static, + DS: DirectoryService + Send + Clone + 'static, + RN: RootNodes + Clone + 'static, +{ + fn root_inode(&self) -> Self::Inode { + ROOT_ID + } +} + impl<BS, DS, RN> FileSystem for TvixStoreFs<BS, DS, RN> where - BS: AsRef<dyn BlobService> + Clone + Send + 'static, - DS: AsRef<dyn DirectoryService> + Send + Clone + 'static, + BS: BlobService + Clone + Send + 'static, + DS: DirectoryService + Send + Clone + 'static, RN: RootNodes + Clone + 'static, { type Handle = u64; @@ -348,13 +354,17 @@ where ) -> io::Result<fuse_backend_rs::api::filesystem::Entry> { debug!("lookup"); + // convert the CStr to a PathComponent + // If it can't be converted, we definitely don't have anything here. + let name: PathComponent = name.try_into().map_err(|_| std::io::ErrorKind::NotFound)?; + // This goes from a parent inode to a node. // - If the parent is [ROOT_ID], we need to check // [self.root_nodes] (fetching from a [RootNode] provider if needed) // - Otherwise, lookup the parent in [self.inode_tracker] (which must be // a [InodeData::Directory]), and find the child with that name. if parent == ROOT_ID { - let (ino, inode_data) = self.name_in_root_to_ino_and_data(name)?; + let (ino, inode_data) = self.name_in_root_to_ino_and_data(&name)?; debug!(inode_data=?&inode_data, ino=ino, "Some"); return Ok(inode_data.as_fuse_entry(ino)); @@ -367,7 +377,7 @@ where // Search for that name in the list of children and return the FileAttrs. // in the children, find the one with the desired name. - if let Some((child_ino, _)) = children.iter().find(|e| e.1.get_name() == name.to_bytes()) { + if let Some((child_ino, _, _)) = children.iter().find(|(_, n, _)| n == &name) { // lookup the child [InodeData] in [self.inode_tracker]. // We know the inodes for children have already been allocated. let child_inode_data = self.inode_tracker.read().get(*child_ino).unwrap(); @@ -400,16 +410,20 @@ where // This task will run in the background immediately and will exit // after the stream ends or if we no longer want any more entries. - self.tokio_handle.spawn(async move { - let mut stream = root_nodes_provider.list().enumerate(); - while let Some(node) = stream.next().await { - if tx.send(node).await.is_err() { - // If we get a send error, it means the sync code - // doesn't want any more entries. - break; + self.tokio_handle.spawn( + async move { + let mut stream = root_nodes_provider.list().enumerate(); + while let Some(e) = stream.next().await { + if tx.send(e).await.is_err() { + // If we get a send error, it means the sync code + // doesn't want any more entries. + break; + } } } - }); + // instrument the task with the current span, this is not done by default + .in_current_span(), + ); // Put the rx part into [self.dir_handles]. // TODO: this will overflow after 2**64 operations, @@ -462,12 +476,12 @@ where .map_err(|_| crate::Error::StorageError("mutex poisoned".into()))?; while let Some((i, n)) = rx.blocking_recv() { - let root_node = n.map_err(|e| { + let (name, node) = n.map_err(|e| { warn!("failed to retrieve root node: {}", e); io::Error::from_raw_os_error(libc::EIO) })?; - let (inode_data, name) = InodeData::from_node(root_node); + let inode_data = InodeData::from_node(&node); // obtain the inode, or allocate a new one. let ino = self.get_inode_for_root_name(&name).unwrap_or_else(|| { @@ -482,7 +496,7 @@ where ino, offset: offset + (i as u64) + 1, type_: inode_data.as_fuse_type(), - name: &name, + name: name.as_ref(), })?; // If the buffer is full, add_entry will return `Ok(0)`. if written == 0 { @@ -496,15 +510,17 @@ where let (parent_digest, children) = self.get_directory_children(inode)?; Span::current().record("directory.digest", parent_digest.to_string()); - for (i, (ino, child_node)) in children.into_iter().skip(offset as usize).enumerate() { - let (inode_data, name) = InodeData::from_node(child_node); + for (i, (ino, child_name, child_node)) in + children.into_iter().skip(offset as usize).enumerate() + { + let inode_data = InodeData::from_node(&child_node); // the second parameter will become the "offset" parameter on the next call. let written = add_entry(fuse_backend_rs::api::filesystem::DirEntry { ino, offset: offset + (i as u64) + 1, type_: inode_data.as_fuse_type(), - name: &name, + name: child_name.as_ref(), })?; // If the buffer is full, add_entry will return `Ok(0)`. if written == 0 { @@ -549,12 +565,12 @@ where .map_err(|_| crate::Error::StorageError("mutex poisoned".into()))?; while let Some((i, n)) = rx.blocking_recv() { - let root_node = n.map_err(|e| { + let (name, node) = n.map_err(|e| { warn!("failed to retrieve root node: {}", e); io::Error::from_raw_os_error(libc::EPERM) })?; - let (inode_data, name) = InodeData::from_node(root_node); + let inode_data = InodeData::from_node(&node); // obtain the inode, or allocate a new one. let ino = self.get_inode_for_root_name(&name).unwrap_or_else(|| { @@ -570,7 +586,7 @@ where ino, offset: offset + (i as u64) + 1, type_: inode_data.as_fuse_type(), - name: &name, + name: name.as_ref(), }, inode_data.as_fuse_entry(ino), )?; @@ -586,8 +602,8 @@ where let (parent_digest, children) = self.get_directory_children(inode)?; Span::current().record("directory.digest", parent_digest.to_string()); - for (i, (ino, child_node)) in children.into_iter().skip(offset as usize).enumerate() { - let (inode_data, name) = InodeData::from_node(child_node); + for (i, (ino, name, child_node)) in children.into_iter().skip(offset as usize).enumerate() { + let inode_data = InodeData::from_node(&child_node); // the second parameter will become the "offset" parameter on the next call. let written = add_entry( @@ -595,7 +611,7 @@ where ino, offset: offset + (i as u64) + 1, type_: inode_data.as_fuse_type(), - name: &name, + name: name.as_ref(), }, inode_data.as_fuse_entry(ino), )?; @@ -640,6 +656,7 @@ where ) -> io::Result<( Option<Self::Handle>, fuse_backend_rs::api::filesystem::OpenOptions, + Option<u32>, )> { if inode == ROOT_ID { return Err(io::Error::from_raw_os_error(libc::ENOSYS)); @@ -658,7 +675,7 @@ where match self.tokio_handle.block_on({ let blob_service = self.blob_service.clone(); let blob_digest = blob_digest.clone(); - async move { blob_service.as_ref().open_read(&blob_digest).await } + async move { blob_service.open_read(&blob_digest).await } }) { Ok(None) => { warn!("blob not found"); @@ -683,6 +700,7 @@ where Ok(( Some(fh), fuse_backend_rs::api::filesystem::OpenOptions::empty(), + None, )) } } diff --git a/tvix/castore/src/fs/root_nodes.rs b/tvix/castore/src/fs/root_nodes.rs index 6609e049a1fc..5ed1a4d8d6c0 100644 --- a/tvix/castore/src/fs/root_nodes.rs +++ b/tvix/castore/src/fs/root_nodes.rs @@ -1,7 +1,6 @@ use std::collections::BTreeMap; -use crate::{proto::node::Node, Error}; -use bytes::Bytes; +use crate::{path::PathComponent, Error, Node}; use futures::stream::BoxStream; use tonic::async_trait; @@ -11,11 +10,12 @@ use tonic::async_trait; pub trait RootNodes: Send + Sync { /// Looks up a root CA node based on the basename of the node in the root /// directory of the filesystem. - async fn get_by_basename(&self, name: &[u8]) -> Result<Option<Node>, Error>; + async fn get_by_basename(&self, name: &PathComponent) -> Result<Option<Node>, Error>; - /// Lists all root CA nodes in the filesystem. An error can be returned - /// in case listing is not allowed - fn list(&self) -> BoxStream<Result<Node, Error>>; + /// Lists all root CA nodes in the filesystem, as a tuple of (base)name + /// and Node. + /// An error can be returned in case listing is not allowed. + fn list(&self) -> BoxStream<Result<(PathComponent, Node), Error>>; } #[async_trait] @@ -23,15 +23,17 @@ pub trait RootNodes: Send + Sync { /// the key is the node name. impl<T> RootNodes for T where - T: AsRef<BTreeMap<Bytes, Node>> + Send + Sync, + T: AsRef<BTreeMap<PathComponent, Node>> + Send + Sync, { - async fn get_by_basename(&self, name: &[u8]) -> Result<Option<Node>, Error> { + async fn get_by_basename(&self, name: &PathComponent) -> Result<Option<Node>, Error> { Ok(self.as_ref().get(name).cloned()) } - fn list(&self) -> BoxStream<Result<Node, Error>> { + fn list(&self) -> BoxStream<Result<(PathComponent, Node), Error>> { Box::pin(tokio_stream::iter( - self.as_ref().iter().map(|(_, v)| Ok(v.clone())), + self.as_ref() + .iter() + .map(|(name, node)| Ok((name.to_owned(), node.to_owned()))), )) } } diff --git a/tvix/castore/src/import/archive.rs b/tvix/castore/src/import/archive.rs index adcfb871d5e3..4cbff687b864 100644 --- a/tvix/castore/src/import/archive.rs +++ b/tvix/castore/src/import/archive.rs @@ -1,51 +1,58 @@ -use std::io::{Cursor, Write}; -use std::sync::Arc; -use std::{collections::HashMap, path::PathBuf}; +//! Imports from an archive (tarballs) + +use std::collections::HashMap; use petgraph::graph::{DiGraph, NodeIndex}; use petgraph::visit::{DfsPostOrder, EdgeRef}; use petgraph::Direction; use tokio::io::AsyncRead; -use tokio::sync::Semaphore; -use tokio::task::JoinSet; use tokio_stream::StreamExt; use tokio_tar::Archive; -use tokio_util::io::InspectReader; use tracing::{instrument, warn, Level}; use crate::blobservice::BlobService; use crate::directoryservice::DirectoryService; -use crate::import::{ingest_entries, Error as ImportError, IngestionEntry}; -use crate::proto::node::Node; -use crate::B3Digest; +use crate::import::{ingest_entries, IngestionEntry, IngestionError}; +use crate::Node; -/// Files smaller than this threshold, in bytes, are uploaded to the [BlobService] in the -/// background. -/// -/// This is a u32 since we acquire a weighted semaphore using the size of the blob. -/// [Semaphore::acquire_many_owned] takes a u32, so we need to ensure the size of -/// the blob can be represented using a u32 and will not cause an overflow. -const CONCURRENT_BLOB_UPLOAD_THRESHOLD: u32 = 1024 * 1024; +use super::blobs::{self, ConcurrentBlobUploader}; -/// The maximum amount of bytes allowed to be buffered in memory to perform async blob uploads. -const MAX_TARBALL_BUFFER_SIZE: usize = 128 * 1024 * 1024; +type TarPathBuf = std::path::PathBuf; #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("error reading archive entry: {0}")] - Io(#[from] std::io::Error), + #[error("unable to construct stream of entries: {0}")] + Entries(std::io::Error), + + #[error("unable to read next entry: {0}")] + NextEntry(std::io::Error), + + #[error("unable to read path for entry: {0}")] + PathRead(std::io::Error), + + #[error("unable to convert path {0} for entry: {1}")] + PathConvert(TarPathBuf, std::io::Error), + + #[error("unable to read size field for {0}: {1}")] + Size(TarPathBuf, std::io::Error), + + #[error("unable to read mode field for {0}: {1}")] + Mode(TarPathBuf, std::io::Error), + + #[error("unable to read link name field for {0}: {1}")] + LinkName(TarPathBuf, std::io::Error), #[error("unsupported tar entry {0} type: {1:?}")] - UnsupportedTarEntry(PathBuf, tokio_tar::EntryType), + EntryType(TarPathBuf, tokio_tar::EntryType), #[error("symlink missing target {0}")] - MissingSymlinkTarget(PathBuf), + MissingSymlinkTarget(TarPathBuf), #[error("unexpected number of top level directory entries")] UnexpectedNumberOfTopLevelEntries, - #[error("failed to import into castore {0}")] - Import(#[from] ImportError), + #[error(transparent)] + BlobUploadError(#[from] blobs::Error), } /// Ingests elements from the given tar [`Archive`] into a the passed [`BlobService`] and @@ -55,10 +62,10 @@ pub async fn ingest_archive<BS, DS, R>( blob_service: BS, directory_service: DS, mut archive: Archive<R>, -) -> Result<Node, Error> +) -> Result<Node, IngestionError<Error>> where BS: BlobService + Clone + 'static, - DS: AsRef<dyn DirectoryService>, + DS: DirectoryService, R: AsyncRead + Unpin, { // Since tarballs can have entries in any arbitrary order, we need to @@ -68,105 +75,68 @@ where // In the first phase, collect up all the regular files and symlinks. let mut nodes = IngestionEntryGraph::new(); - let semaphore = Arc::new(Semaphore::new(MAX_TARBALL_BUFFER_SIZE)); - let mut async_blob_uploads: JoinSet<Result<(), Error>> = JoinSet::new(); + let mut blob_uploader = ConcurrentBlobUploader::new(blob_service); + + let mut entries_iter = archive.entries().map_err(Error::Entries)?; + while let Some(mut entry) = entries_iter.try_next().await.map_err(Error::NextEntry)? { + let tar_path: TarPathBuf = entry.path().map_err(Error::PathRead)?.into(); - let mut entries_iter = archive.entries()?; - while let Some(mut entry) = entries_iter.try_next().await? { - let path: PathBuf = entry.path()?.into(); + // construct a castore PathBuf, which we use in the produced IngestionEntry. + let path = crate::path::PathBuf::from_host_path(tar_path.as_path(), true) + .map_err(|e| Error::PathConvert(tar_path.clone(), e))?; let header = entry.header(); let entry = match header.entry_type() { tokio_tar::EntryType::Regular | tokio_tar::EntryType::GNUSparse | tokio_tar::EntryType::Continuous => { - let header_size = header.size()?; - - // If the blob is small enough, read it off the wire, compute the digest, - // and upload it to the [BlobService] in the background. - let (size, digest) = if header_size <= CONCURRENT_BLOB_UPLOAD_THRESHOLD as u64 { - let mut buffer = Vec::with_capacity(header_size as usize); - let mut hasher = blake3::Hasher::new(); - let mut reader = InspectReader::new(&mut entry, |bytes| { - hasher.write_all(bytes).unwrap(); - }); - - // Ensure that we don't buffer into memory until we've acquired a permit. - // This prevents consuming too much memory when performing concurrent - // blob uploads. - let permit = semaphore - .clone() - // This cast is safe because ensure the header_size is less than - // CONCURRENT_BLOB_UPLOAD_THRESHOLD which is a u32. - .acquire_many_owned(header_size as u32) - .await - .unwrap(); - let size = tokio::io::copy(&mut reader, &mut buffer).await?; - - let digest: B3Digest = hasher.finalize().as_bytes().into(); - - { - let blob_service = blob_service.clone(); - let digest = digest.clone(); - async_blob_uploads.spawn({ - async move { - let mut writer = blob_service.open_write().await; - - tokio::io::copy(&mut Cursor::new(buffer), &mut writer).await?; - - let blob_digest = writer.close().await?; - - assert_eq!(digest, blob_digest, "Tvix bug: blob digest mismatch"); - - // Make sure we hold the permit until we finish writing the blob - // to the [BlobService]. - drop(permit); - Ok(()) - } - }); - } - - (size, digest) - } else { - let mut writer = blob_service.open_write().await; - - let size = tokio::io::copy(&mut entry, &mut writer).await?; - - let digest = writer.close().await?; - - (size, digest) - }; + let size = header + .size() + .map_err(|e| Error::Size(tar_path.clone(), e))?; + + let digest = blob_uploader + .upload(&path, size, &mut entry) + .await + .map_err(Error::BlobUploadError)?; + + let executable = entry + .header() + .mode() + .map_err(|e| Error::Mode(tar_path, e))? + & 64 + != 0; IngestionEntry::Regular { path, size, - executable: entry.header().mode()? & 64 != 0, + executable, digest, } } tokio_tar::EntryType::Symlink => IngestionEntry::Symlink { target: entry - .link_name()? - .ok_or_else(|| Error::MissingSymlinkTarget(path.clone()))? - .into(), + .link_name() + .map_err(|e| Error::LinkName(tar_path.clone(), e))? + .ok_or_else(|| Error::MissingSymlinkTarget(tar_path.clone()))? + .into_owned() + .into_os_string() + .into_encoded_bytes(), path, }, // Push a bogus directory marker so we can make sure this directoy gets // created. We don't know the digest and size until after reading the full // tarball. - tokio_tar::EntryType::Directory => IngestionEntry::Dir { path: path.clone() }, + tokio_tar::EntryType::Directory => IngestionEntry::Dir { path }, tokio_tar::EntryType::XGlobalHeader | tokio_tar::EntryType::XHeader => continue, - entry_type => return Err(Error::UnsupportedTarEntry(path, entry_type)), + entry_type => return Err(Error::EntryType(tar_path, entry_type).into()), }; nodes.add(entry)?; } - while let Some(result) = async_blob_uploads.join_next().await { - result.expect("task panicked")?; - } + blob_uploader.join().await.map_err(Error::BlobUploadError)?; let root_node = ingest_entries( directory_service, @@ -193,7 +163,7 @@ where /// An error is returned if this is not the case and ingestion will fail. struct IngestionEntryGraph { graph: DiGraph<IngestionEntry, ()>, - path_to_index: HashMap<PathBuf, NodeIndex>, + path_to_index: HashMap<crate::path::PathBuf, NodeIndex>, root_node: Option<NodeIndex>, } @@ -218,7 +188,7 @@ impl IngestionEntryGraph { /// and new nodes are not directories, the node is replaced and is disconnected from its /// children. pub fn add(&mut self, entry: IngestionEntry) -> Result<NodeIndex, Error> { - let path = entry.path().to_path_buf(); + let path = entry.path().to_owned(); let index = match self.path_to_index.get(entry.path()) { Some(&index) => { @@ -233,12 +203,12 @@ impl IngestionEntryGraph { None => self.graph.add_node(entry), }; - // A path with 1 component is the root node + // for archives, a path with 1 component is the root node if path.components().count() == 1 { // We expect archives to contain a single root node, if there is another root node // entry with a different path name, this is unsupported. if let Some(root_node) = self.root_node { - if self.get_node(root_node).path() != path { + if self.get_node(root_node).path() != path.as_ref() { return Err(Error::UnexpectedNumberOfTopLevelEntries); } } @@ -247,7 +217,7 @@ impl IngestionEntryGraph { } else if let Some(parent_path) = path.parent() { // Recursively add the parent node until it hits the root node. let parent_index = self.add(IngestionEntry::Dir { - path: parent_path.to_path_buf(), + path: parent_path.to_owned(), })?; // Insert an edge from the parent directory to the child entry. @@ -322,38 +292,43 @@ impl IngestionEntryGraph { #[cfg(test)] mod test { - use crate::import::IngestionEntry; - use crate::B3Digest; + use std::sync::LazyLock; use super::{Error, IngestionEntryGraph}; + use crate::import::IngestionEntry; + use crate::B3Digest; - use lazy_static::lazy_static; use rstest::rstest; - lazy_static! { - pub static ref EMPTY_DIGEST: B3Digest = blake3::hash(&[]).as_bytes().into(); - pub static ref DIR_A: IngestionEntry = IngestionEntry::Dir { path: "a".into() }; - pub static ref DIR_B: IngestionEntry = IngestionEntry::Dir { path: "b".into() }; - pub static ref DIR_A_B: IngestionEntry = IngestionEntry::Dir { path: "a/b".into() }; - pub static ref FILE_A: IngestionEntry = IngestionEntry::Regular { - path: "a".into(), - size: 0, - executable: false, - digest: EMPTY_DIGEST.clone(), - }; - pub static ref FILE_A_B: IngestionEntry = IngestionEntry::Regular { - path: "a/b".into(), - size: 0, - executable: false, - digest: EMPTY_DIGEST.clone(), - }; - pub static ref FILE_A_B_C: IngestionEntry = IngestionEntry::Regular { - path: "a/b/c".into(), - size: 0, - executable: false, - digest: EMPTY_DIGEST.clone(), - }; - } + pub static EMPTY_DIGEST: LazyLock<B3Digest> = + LazyLock::new(|| blake3::hash(&[]).as_bytes().into()); + pub static DIR_A: LazyLock<IngestionEntry> = LazyLock::new(|| IngestionEntry::Dir { + path: "a".parse().unwrap(), + }); + pub static DIR_B: LazyLock<IngestionEntry> = LazyLock::new(|| IngestionEntry::Dir { + path: "b".parse().unwrap(), + }); + pub static DIR_A_B: LazyLock<IngestionEntry> = LazyLock::new(|| IngestionEntry::Dir { + path: "a/b".parse().unwrap(), + }); + pub static FILE_A: LazyLock<IngestionEntry> = LazyLock::new(|| IngestionEntry::Regular { + path: "a".parse().unwrap(), + size: 0, + executable: false, + digest: EMPTY_DIGEST.clone(), + }); + pub static FILE_A_B: LazyLock<IngestionEntry> = LazyLock::new(|| IngestionEntry::Regular { + path: "a/b".parse().unwrap(), + size: 0, + executable: false, + digest: EMPTY_DIGEST.clone(), + }); + pub static FILE_A_B_C: LazyLock<IngestionEntry> = LazyLock::new(|| IngestionEntry::Regular { + path: "a/b/c".parse().unwrap(), + size: 0, + executable: false, + digest: EMPTY_DIGEST.clone(), + }); #[rstest] #[case::implicit_directories(&[&*FILE_A_B_C], &[&*FILE_A_B_C, &*DIR_A_B, &*DIR_A])] diff --git a/tvix/castore/src/import/blobs.rs b/tvix/castore/src/import/blobs.rs new file mode 100644 index 000000000000..f71ee1e63768 --- /dev/null +++ b/tvix/castore/src/import/blobs.rs @@ -0,0 +1,190 @@ +use std::{ + io::{Cursor, Write}, + sync::Arc, +}; + +use tokio::{ + io::AsyncRead, + sync::Semaphore, + task::{JoinError, JoinSet}, +}; +use tokio_util::io::InspectReader; + +use crate::{blobservice::BlobService, B3Digest, Path, PathBuf}; + +/// Files smaller than this threshold, in bytes, are uploaded to the [BlobService] in the +/// background. +/// +/// This is a u32 since we acquire a weighted semaphore using the size of the blob. +/// [Semaphore::acquire_many_owned] takes a u32, so we need to ensure the size of +/// the blob can be represented using a u32 and will not cause an overflow. +const CONCURRENT_BLOB_UPLOAD_THRESHOLD: u32 = 1024 * 1024; + +/// The maximum amount of bytes allowed to be buffered in memory to perform async blob uploads. +const MAX_BUFFER_SIZE: usize = 128 * 1024 * 1024; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("unable to read blob contents for {0}: {1}")] + BlobRead(PathBuf, std::io::Error), + + #[error("unable to check whether blob at {0} already exists: {1}")] + BlobCheck(PathBuf, std::io::Error), + + // FUTUREWORK: proper error for blob finalize + #[error("unable to finalize blob {0}: {1}")] + BlobFinalize(PathBuf, std::io::Error), + + #[error("unexpected size for {path} wanted: {wanted} got: {got}")] + UnexpectedSize { + path: PathBuf, + wanted: u64, + got: u64, + }, + + #[error("blob upload join error: {0}")] + JoinError(#[from] JoinError), +} + +/// The concurrent blob uploader provides a mechanism for concurrently uploading small blobs. +/// This is useful when ingesting from sources like tarballs and archives which each blob entry +/// must be read sequentially. Ingesting many small blobs sequentially becomes slow due to +/// round trip time with the blob service. The concurrent blob uploader will buffer small +/// blobs in memory and upload them to the blob service in the background. +/// +/// Once all blobs have been uploaded, make sure to call [ConcurrentBlobUploader::join] to wait +/// for all background jobs to complete and check for any errors. +pub struct ConcurrentBlobUploader<BS> { + blob_service: BS, + upload_tasks: JoinSet<Result<(), Error>>, + upload_semaphore: Arc<Semaphore>, +} + +impl<BS> ConcurrentBlobUploader<BS> +where + BS: BlobService + Clone + 'static, +{ + /// Creates a new concurrent blob uploader which uploads blobs to the provided + /// blob service. + pub fn new(blob_service: BS) -> Self { + Self { + blob_service, + upload_tasks: JoinSet::new(), + upload_semaphore: Arc::new(Semaphore::new(MAX_BUFFER_SIZE)), + } + } + + /// Uploads a blob to the blob service. If the blob is small enough it will be read to a buffer + /// and uploaded in the background. + /// This will read the entirety of the provided reader unless an error occurs, even if blobs + /// are uploaded in the background.. + pub async fn upload<R>( + &mut self, + path: &Path, + expected_size: u64, + mut r: R, + ) -> Result<B3Digest, Error> + where + R: AsyncRead + Unpin, + { + if expected_size < CONCURRENT_BLOB_UPLOAD_THRESHOLD as u64 { + let mut buffer = Vec::with_capacity(expected_size as usize); + let mut hasher = blake3::Hasher::new(); + let mut reader = InspectReader::new(&mut r, |bytes| { + hasher.write_all(bytes).unwrap(); + }); + + let permit = self + .upload_semaphore + .clone() + // This cast is safe because ensure the header_size is less than + // CONCURRENT_BLOB_UPLOAD_THRESHOLD which is a u32. + .acquire_many_owned(expected_size as u32) + .await + .unwrap(); + let size = tokio::io::copy(&mut reader, &mut buffer) + .await + .map_err(|e| Error::BlobRead(path.into(), e))?; + let digest: B3Digest = hasher.finalize().as_bytes().into(); + + if size != expected_size { + return Err(Error::UnexpectedSize { + path: path.into(), + wanted: expected_size, + got: size, + }); + } + + self.upload_tasks.spawn({ + let blob_service = self.blob_service.clone(); + let expected_digest = digest.clone(); + let path = path.to_owned(); + let r = Cursor::new(buffer); + async move { + // We know the blob digest already, check it exists before sending it. + if blob_service + .has(&expected_digest) + .await + .map_err(|e| Error::BlobCheck(path.clone(), e))? + { + drop(permit); + return Ok(()); + } + + let digest = upload_blob(&blob_service, &path, expected_size, r).await?; + + assert_eq!(digest, expected_digest, "Tvix bug: blob digest mismatch"); + + // Make sure we hold the permit until we finish writing the blob + // to the [BlobService]. + drop(permit); + Ok(()) + } + }); + + return Ok(digest); + } + + upload_blob(&self.blob_service, path, expected_size, r).await + } + + /// Waits for all background upload jobs to complete, returning any upload errors. + pub async fn join(mut self) -> Result<(), Error> { + while let Some(result) = self.upload_tasks.join_next().await { + result??; + } + Ok(()) + } +} + +async fn upload_blob<BS, R>( + blob_service: &BS, + path: &Path, + expected_size: u64, + mut r: R, +) -> Result<B3Digest, Error> +where + BS: BlobService, + R: AsyncRead + Unpin, +{ + let mut writer = blob_service.open_write().await; + + let size = tokio::io::copy(&mut r, &mut writer) + .await + .map_err(|e| Error::BlobRead(path.into(), e))?; + + let digest = writer + .close() + .await + .map_err(|e| Error::BlobFinalize(path.into(), e))?; + + if size != expected_size { + return Err(Error::UnexpectedSize { + path: path.into(), + wanted: expected_size, + got: size, + }); + } + + Ok(digest) +} diff --git a/tvix/castore/src/import/error.rs b/tvix/castore/src/import/error.rs index 15dd0664deaa..e3fba617e08f 100644 --- a/tvix/castore/src/import/error.rs +++ b/tvix/castore/src/import/error.rs @@ -1,39 +1,20 @@ -use std::{fs::FileType, path::PathBuf}; +use super::PathBuf; use crate::Error as CastoreError; +/// Represents all error types that emitted by ingest_entries. +/// It can represent errors uploading individual Directories and finalizing +/// the upload. +/// It also contains a generic error kind that'll carry ingestion-method +/// specific errors. #[derive(Debug, thiserror::Error)] -pub enum Error { +pub enum IngestionError<E: std::fmt::Display> { + #[error("error from producer: {0}")] + Producer(#[from] E), + #[error("failed to upload directory at {0}: {1}")] UploadDirectoryError(PathBuf, CastoreError), - #[error("invalid encoding encountered for entry {0:?}")] - InvalidEncoding(PathBuf), - - #[error("unable to stat {0}: {1}")] - UnableToStat(PathBuf, std::io::Error), - - #[error("unable to open {0}: {1}")] - UnableToOpen(PathBuf, std::io::Error), - - #[error("unable to read {0}: {1}")] - UnableToRead(PathBuf, std::io::Error), - - #[error("unsupported file {0} type: {1:?}")] - UnsupportedFileType(PathBuf, FileType), -} - -impl From<CastoreError> for Error { - fn from(value: CastoreError) -> Self { - match value { - CastoreError::InvalidRequest(_) => panic!("tvix bug"), - CastoreError::StorageError(_) => panic!("error"), - } - } -} - -impl From<Error> for std::io::Error { - fn from(value: Error) -> Self { - std::io::Error::new(std::io::ErrorKind::Other, value) - } + #[error("failed to finalize directory upload: {0}")] + FinalizeDirectoryUpload(CastoreError), } diff --git a/tvix/castore/src/import/fs.rs b/tvix/castore/src/import/fs.rs index 6709d4a127e9..78eac6f6128d 100644 --- a/tvix/castore/src/import/fs.rs +++ b/tvix/castore/src/import/fs.rs @@ -1,22 +1,29 @@ +//! Import from a real filesystem. + use futures::stream::BoxStream; use futures::StreamExt; +use std::fs::FileType; +use std::os::unix::ffi::OsStringExt; use std::os::unix::fs::MetadataExt; use std::os::unix::fs::PermissionsExt; -use std::path::Path; +use tokio::io::BufReader; +use tokio_util::io::InspectReader; +use tracing::info_span; use tracing::instrument; +use tracing::Instrument; +use tracing::Span; +use tracing_indicatif::span_ext::IndicatifSpanExt; use walkdir::DirEntry; use walkdir::WalkDir; use crate::blobservice::BlobService; use crate::directoryservice::DirectoryService; -use crate::proto::node::Node; +use crate::refscan::{ReferenceReader, ReferenceScanner}; +use crate::{B3Digest, Node}; use super::ingest_entries; -use super::upload_blob_at_path; -use super::Error; use super::IngestionEntry; - -///! Imports that deal with a real filesystem. +use super::IngestionError; /// Ingests the contents at a given path into the tvix store, interacting with a [BlobService] and /// [DirectoryService]. It returns the root node or an error. @@ -25,25 +32,45 @@ use super::IngestionEntry; /// /// This function will walk the filesystem using `walkdir` and will consume /// `O(#number of entries)` space. -#[instrument(skip(blob_service, directory_service), fields(path), err)] -pub async fn ingest_path<BS, DS, P>( +#[instrument( + skip(blob_service, directory_service, reference_scanner), + fields(path), + err +)] +pub async fn ingest_path<BS, DS, P, P2>( blob_service: BS, directory_service: DS, path: P, -) -> Result<Node, Error> + reference_scanner: Option<&ReferenceScanner<P2>>, +) -> Result<Node, IngestionError<Error>> where - P: AsRef<Path> + std::fmt::Debug, + P: AsRef<std::path::Path> + std::fmt::Debug, BS: BlobService + Clone, - DS: AsRef<dyn DirectoryService>, + DS: DirectoryService, + P2: AsRef<[u8]> + Send + Sync, { + let span = Span::current(); + let iter = WalkDir::new(path.as_ref()) .follow_links(false) .follow_root_links(false) .contents_first(true) .into_iter(); - let entries = dir_entries_to_ingestion_stream(blob_service, iter, path.as_ref()); - ingest_entries(directory_service, entries).await + let entries = + dir_entries_to_ingestion_stream(blob_service, iter, path.as_ref(), reference_scanner); + ingest_entries( + directory_service, + entries.inspect({ + let span = span.clone(); + move |e| { + if e.is_ok() { + span.pb_inc(1) + } + } + }), + ) + .await } /// Converts an iterator of [walkdir::DirEntry]s into a stream of ingestion entries. @@ -52,16 +79,18 @@ where /// The produced stream is buffered, so uploads can happen concurrently. /// /// The root is the [Path] in the filesystem that is being ingested into the castore. -pub fn dir_entries_to_ingestion_stream<'a, BS, I>( +pub fn dir_entries_to_ingestion_stream<'a, BS, I, P>( blob_service: BS, iter: I, - root: &'a Path, + root: &'a std::path::Path, + reference_scanner: Option<&'a ReferenceScanner<P>>, ) -> BoxStream<'a, Result<IngestionEntry, Error>> where BS: BlobService + Clone + 'a, I: Iterator<Item = Result<DirEntry, walkdir::Error>> + Send + 'a, + P: AsRef<[u8]> + Send + Sync, { - let prefix = root.parent().unwrap_or_else(|| Path::new("")); + let prefix = root.parent().unwrap_or_else(|| std::path::Path::new("")); Box::pin( futures::stream::iter(iter) @@ -70,9 +99,15 @@ where async move { match x { Ok(dir_entry) => { - dir_entry_to_ingestion_entry(blob_service, &dir_entry, prefix).await + dir_entry_to_ingestion_entry( + blob_service, + &dir_entry, + prefix, + reference_scanner, + ) + .await } - Err(e) => Err(Error::UnableToStat( + Err(e) => Err(Error::Stat( prefix.to_path_buf(), e.into_io_error().expect("walkdir err must be some"), )), @@ -88,35 +123,54 @@ where /// /// The prefix path is stripped from the path of each entry. This is usually the parent path /// of the path being ingested so that the last element of the stream only has one component. -pub async fn dir_entry_to_ingestion_entry<BS>( +pub async fn dir_entry_to_ingestion_entry<BS, P>( blob_service: BS, entry: &DirEntry, - prefix: &Path, + prefix: &std::path::Path, + reference_scanner: Option<&ReferenceScanner<P>>, ) -> Result<IngestionEntry, Error> where BS: BlobService, + P: AsRef<[u8]>, { let file_type = entry.file_type(); - let path = entry + let fs_path = entry .path() .strip_prefix(prefix) - .expect("Tvix bug: failed to strip root path prefix") - .to_path_buf(); + .expect("Tvix bug: failed to strip root path prefix"); + + // convert to castore PathBuf + let path = crate::path::PathBuf::from_host_path(fs_path, false) + .unwrap_or_else(|e| panic!("Tvix bug: walkdir direntry cannot be parsed: {}", e)); if file_type.is_dir() { Ok(IngestionEntry::Dir { path }) } else if file_type.is_symlink() { let target = std::fs::read_link(entry.path()) - .map_err(|e| Error::UnableToStat(entry.path().to_path_buf(), e))?; + .map_err(|e| Error::Stat(entry.path().to_path_buf(), e))? + .into_os_string() + .into_vec(); + + if let Some(reference_scanner) = &reference_scanner { + reference_scanner.scan(&target); + } Ok(IngestionEntry::Symlink { path, target }) } else if file_type.is_file() { let metadata = entry .metadata() - .map_err(|e| Error::UnableToStat(entry.path().to_path_buf(), e.into()))?; + .map_err(|e| Error::Stat(entry.path().to_path_buf(), e.into()))?; - let digest = upload_blob_at_path(blob_service, entry.path().to_path_buf()).await?; + let digest = upload_blob(blob_service, entry.path().to_path_buf(), reference_scanner) + .instrument({ + let span = info_span!("upload_blob", "indicatif.pb_show" = tracing::field::Empty); + span.pb_set_message(&format!("Uploading blob for {:?}", fs_path)); + span.pb_set_style(&tvix_tracing::PB_TRANSFER_STYLE); + + span + }) + .await?; Ok(IngestionEntry::Regular { path, @@ -127,6 +181,73 @@ where digest, }) } else { - Ok(IngestionEntry::Unknown { path, file_type }) + return Err(Error::FileType(fs_path.to_path_buf(), file_type)); } } + +/// Uploads the file at the provided [Path] the the [BlobService]. +#[instrument(skip(blob_service, reference_scanner), fields(path), err)] +async fn upload_blob<BS, P>( + blob_service: BS, + path: impl AsRef<std::path::Path>, + reference_scanner: Option<&ReferenceScanner<P>>, +) -> Result<B3Digest, Error> +where + BS: BlobService, + P: AsRef<[u8]>, +{ + let span = Span::current(); + span.pb_start(); + + let file = tokio::fs::File::open(path.as_ref()) + .await + .map_err(|e| Error::BlobRead(path.as_ref().to_path_buf(), e))?; + + let metadata = file + .metadata() + .await + .map_err(|e| Error::Stat(path.as_ref().to_path_buf(), e))?; + + span.pb_set_length(metadata.len()); + let reader = InspectReader::new(file, |d| { + span.pb_inc(d.len() as u64); + }); + + let mut writer = blob_service.open_write().await; + if let Some(reference_scanner) = reference_scanner { + let mut reader = ReferenceReader::new(reference_scanner, BufReader::new(reader)); + tokio::io::copy(&mut reader, &mut writer) + .await + .map_err(|e| Error::BlobRead(path.as_ref().to_path_buf(), e))?; + } else { + tokio::io::copy(&mut BufReader::new(reader), &mut writer) + .await + .map_err(|e| Error::BlobRead(path.as_ref().to_path_buf(), e))?; + } + + let digest = writer + .close() + .await + .map_err(|e| Error::BlobFinalize(path.as_ref().to_path_buf(), e))?; + + Ok(digest) +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("unsupported file type at {0}: {1:?}")] + FileType(std::path::PathBuf, FileType), + + #[error("unable to stat {0}: {1}")] + Stat(std::path::PathBuf, std::io::Error), + + #[error("unable to open {0}: {1}")] + Open(std::path::PathBuf, std::io::Error), + + #[error("unable to read {0}: {1}")] + BlobRead(std::path::PathBuf, std::io::Error), + + // TODO: proper error for blob finalize + #[error("unable to finalize blob {0}: {1}")] + BlobFinalize(std::path::PathBuf, std::io::Error), +} diff --git a/tvix/castore/src/import/mod.rs b/tvix/castore/src/import/mod.rs index e9fdc750f8c1..6e10a64939a4 100644 --- a/tvix/castore/src/import/mod.rs +++ b/tvix/castore/src/import/mod.rs @@ -4,33 +4,20 @@ //! Specific implementations, such as ingesting from the filesystem, live in //! child modules. -use crate::blobservice::BlobService; -use crate::directoryservice::DirectoryPutter; -use crate::directoryservice::DirectoryService; -use crate::proto::node::Node; -use crate::proto::Directory; -use crate::proto::DirectoryNode; -use crate::proto::FileNode; -use crate::proto::SymlinkNode; -use crate::B3Digest; +use crate::directoryservice::{DirectoryPutter, DirectoryService}; +use crate::path::{Path, PathBuf}; +use crate::{B3Digest, Directory, Node, SymlinkTargetError}; use futures::{Stream, StreamExt}; -use std::fs::FileType; - use tracing::Level; -#[cfg(target_family = "unix")] -use std::os::unix::ffi::OsStrExt; - -use std::{ - collections::HashMap, - path::{Path, PathBuf}, -}; +use std::collections::HashMap; use tracing::instrument; mod error; -pub use error::Error; +pub use error::IngestionError; pub mod archive; +pub mod blobs; pub mod fs; /// Ingests [IngestionEntry] from the given stream into a the passed [DirectoryService]. @@ -51,10 +38,14 @@ pub mod fs; /// /// On success, returns the root node. #[instrument(skip_all, ret(level = Level::TRACE), err)] -pub async fn ingest_entries<DS, S>(directory_service: DS, mut entries: S) -> Result<Node, Error> +pub async fn ingest_entries<DS, S, E>( + directory_service: DS, + mut entries: S, +) -> Result<Node, IngestionError<E>> where - DS: AsRef<dyn DirectoryService>, - S: Stream<Item = Result<IngestionEntry, Error>> + Send + std::marker::Unpin, + DS: DirectoryService, + S: Stream<Item = Result<IngestionEntry, E>> + Send + std::marker::Unpin, + E: std::error::Error, { // For a given path, this holds the [Directory] structs as they are populated. let mut directories: HashMap<PathBuf, Directory> = HashMap::default(); @@ -68,28 +59,12 @@ where // we break the loop manually. .expect("Tvix bug: unexpected end of stream")?; - debug_assert!( - entry - .path() - .components() - .all(|x| matches!(x, std::path::Component::Normal(_))), - "path may only contain normal components" - ); - - let name = entry - .path() - .file_name() - // If this is the root node, it will have an empty name. - .unwrap_or_default() - .as_bytes() - .to_owned() - .into(); - let node = match &mut entry { IngestionEntry::Dir { .. } => { // If the entry is a directory, we traversed all its children (and // populated it in `directories`). - // If we don't have it in there, it's an empty directory. + // If we don't have it in directories, it's a directory without + // children. let directory = directories .remove(entry.path()) // In that case, it contained no children @@ -102,48 +77,75 @@ where // If we don't have one yet (as that's the first one to upload), // initialize the putter. maybe_directory_putter - .get_or_insert_with(|| directory_service.as_ref().put_multiple_start()) + .get_or_insert_with(|| directory_service.put_multiple_start()) .put(directory) - .await?; + .await + .map_err(|e| { + IngestionError::UploadDirectoryError(entry.path().to_owned(), e) + })?; - Node::Directory(DirectoryNode { - name, - digest: directory_digest.into(), + Node::Directory { + digest: directory_digest, size: directory_size, - }) + } } - IngestionEntry::Symlink { ref target, .. } => Node::Symlink(SymlinkNode { - name, - target: target.as_os_str().as_bytes().to_owned().into(), - }), + IngestionEntry::Symlink { ref target, .. } => Node::Symlink { + target: bytes::Bytes::copy_from_slice(target).try_into().map_err( + |e: SymlinkTargetError| { + IngestionError::UploadDirectoryError( + entry.path().to_owned(), + crate::Error::StorageError(format!("invalid symlink target: {}", e)), + ) + }, + )?, + }, IngestionEntry::Regular { size, executable, digest, .. - } => Node::File(FileNode { - name, - digest: digest.to_owned().into(), + } => Node::File { + digest: digest.clone(), size: *size, executable: *executable, - }), - IngestionEntry::Unknown { path, file_type } => { - return Err(Error::UnsupportedFileType(path.clone(), *file_type)); - } + }, }; - if entry.path().components().count() == 1 { + let parent = entry + .path() + .parent() + .expect("Tvix bug: got entry with root node"); + + if parent == crate::Path::ROOT { break node; - } + } else { + let name = entry + .path() + .file_name() + // If this is the root node, it will have an empty name. + .unwrap_or_else(|| "".try_into().unwrap()) + .to_owned(); - // record node in parent directory, creating a new [Directory] if not there yet. - directories - .entry(entry.path().parent().unwrap().to_path_buf()) - .or_default() - .add(node); + // record node in parent directory, creating a new [Directory] if not there yet. + directories + .entry(parent.to_owned()) + .or_default() + .add(name, node) + .map_err(|e| { + IngestionError::UploadDirectoryError( + entry.path().to_owned(), + crate::Error::StorageError(e.to_string()), + ) + })?; + } }; assert!( + entries.count().await == 0, + "Tvix bug: left over elements in the stream" + ); + + assert!( directories.is_empty(), "Tvix bug: left over directories after processing ingestion stream" ); @@ -152,19 +154,15 @@ where // they're all persisted to the backend. if let Some(mut directory_putter) = maybe_directory_putter { #[cfg_attr(not(debug_assertions), allow(unused))] - let root_directory_digest = directory_putter.close().await?; + let root_directory_digest = directory_putter + .close() + .await + .map_err(|e| IngestionError::FinalizeDirectoryUpload(e))?; #[cfg(debug_assertions)] { - if let Node::Directory(directory_node) = &root_node { - debug_assert_eq!( - root_directory_digest, - directory_node - .digest - .to_vec() - .try_into() - .expect("invalid digest len") - ) + if let Node::Directory { digest, .. } = &root_node { + debug_assert_eq!(&root_directory_digest, digest); } else { unreachable!("Tvix bug: directory putter initialized but no root directory node"); } @@ -174,31 +172,6 @@ where Ok(root_node) } -/// Uploads the file at the provided [Path] the the [BlobService]. -#[instrument(skip(blob_service), fields(path), err)] -async fn upload_blob_at_path<BS>(blob_service: BS, path: PathBuf) -> Result<B3Digest, Error> -where - BS: BlobService, -{ - let mut file = match tokio::fs::File::open(&path).await { - Ok(file) => file, - Err(e) => return Err(Error::UnableToRead(path, e)), - }; - - let mut writer = blob_service.open_write().await; - - if let Err(e) = tokio::io::copy(&mut file, &mut writer).await { - return Err(Error::UnableToRead(path, e)); - }; - - let digest = writer - .close() - .await - .map_err(|e| Error::UnableToRead(path, e))?; - - Ok(digest) -} - #[derive(Debug, Clone, Eq, PartialEq)] pub enum IngestionEntry { Regular { @@ -209,15 +182,11 @@ pub enum IngestionEntry { }, Symlink { path: PathBuf, - target: PathBuf, + target: Vec<u8>, }, Dir { path: PathBuf, }, - Unknown { - path: PathBuf, - file_type: FileType, - }, } impl IngestionEntry { @@ -226,7 +195,6 @@ impl IngestionEntry { IngestionEntry::Regular { path, .. } => path, IngestionEntry::Symlink { path, .. } => path, IngestionEntry::Dir { path } => path, - IngestionEntry::Unknown { path, .. } => path, } } @@ -234,3 +202,137 @@ impl IngestionEntry { matches!(self, IngestionEntry::Dir { .. }) } } + +#[cfg(test)] +mod test { + use rstest::rstest; + + use crate::fixtures::{DIRECTORY_COMPLICATED, DIRECTORY_WITH_KEEP, EMPTY_BLOB_DIGEST}; + use crate::{directoryservice::MemoryDirectoryService, fixtures::DUMMY_DIGEST}; + use crate::{Directory, Node}; + + use super::ingest_entries; + use super::IngestionEntry; + + #[rstest] + #[case::single_file(vec![IngestionEntry::Regular { + path: "foo".parse().unwrap(), + size: 42, + executable: true, + digest: DUMMY_DIGEST.clone(), + }], + Node::File{digest: DUMMY_DIGEST.clone(), size: 42, executable: true} + )] + #[case::single_symlink(vec![IngestionEntry::Symlink { + path: "foo".parse().unwrap(), + target: b"blub".into(), + }], + Node::Symlink{target: "blub".try_into().unwrap()} + )] + #[case::single_dir(vec![IngestionEntry::Dir { + path: "foo".parse().unwrap(), + }], + Node::Directory{digest: Directory::default().digest(), size: Directory::default().size()} + )] + #[case::dir_with_keep(vec![ + IngestionEntry::Regular { + path: "foo/.keep".parse().unwrap(), + size: 0, + executable: false, + digest: EMPTY_BLOB_DIGEST.clone(), + }, + IngestionEntry::Dir { + path: "foo".parse().unwrap(), + }, + ], + Node::Directory{ digest: DIRECTORY_WITH_KEEP.digest(), size: DIRECTORY_WITH_KEEP.size()} + )] + /// This is intentionally a bit unsorted, though it still satisfies all + /// requirements we have on the order of elements in the stream. + #[case::directory_complicated(vec![ + IngestionEntry::Regular { + path: "blub/.keep".parse().unwrap(), + size: 0, + executable: false, + digest: EMPTY_BLOB_DIGEST.clone(), + }, + IngestionEntry::Regular { + path: "blub/keep/.keep".parse().unwrap(), + size: 0, + executable: false, + digest: EMPTY_BLOB_DIGEST.clone(), + }, + IngestionEntry::Dir { + path: "blub/keep".parse().unwrap(), + }, + IngestionEntry::Symlink { + path: "blub/aa".parse().unwrap(), + target: b"/nix/store/somewhereelse".into(), + }, + IngestionEntry::Dir { + path: "blub".parse().unwrap(), + }, + ], + Node::Directory{ digest: DIRECTORY_COMPLICATED.digest(), size: DIRECTORY_COMPLICATED.size() } + )] + #[tokio::test] + async fn test_ingestion(#[case] entries: Vec<IngestionEntry>, #[case] exp_root_node: Node) { + let directory_service = MemoryDirectoryService::default(); + + let root_node = ingest_entries( + directory_service.clone(), + futures::stream::iter(entries.into_iter().map(Ok::<_, std::io::Error>)), + ) + .await + .expect("must succeed"); + + assert_eq!(exp_root_node, root_node, "root node should match"); + } + + #[rstest] + #[should_panic] + #[case::empty_entries(vec![])] + #[should_panic] + #[case::missing_intermediate_dir(vec![ + IngestionEntry::Regular { + path: "blub/.keep".parse().unwrap(), + size: 0, + executable: false, + digest: EMPTY_BLOB_DIGEST.clone(), + }, + ])] + #[should_panic] + #[case::leaf_after_parent(vec![ + IngestionEntry::Dir { + path: "blub".parse().unwrap(), + }, + IngestionEntry::Regular { + path: "blub/.keep".parse().unwrap(), + size: 0, + executable: false, + digest: EMPTY_BLOB_DIGEST.clone(), + }, + ])] + #[should_panic] + #[case::root_in_entry(vec![ + IngestionEntry::Regular { + path: ".keep".parse().unwrap(), + size: 0, + executable: false, + digest: EMPTY_BLOB_DIGEST.clone(), + }, + IngestionEntry::Dir { + path: "".parse().unwrap(), + }, + ])] + #[tokio::test] + async fn test_ingestion_fail(#[case] entries: Vec<IngestionEntry>) { + let directory_service = MemoryDirectoryService::default(); + + let _ = ingest_entries( + directory_service.clone(), + futures::stream::iter(entries.into_iter().map(Ok::<_, std::io::Error>)), + ) + .await; + } +} diff --git a/tvix/castore/src/lib.rs b/tvix/castore/src/lib.rs index 1a7ac6b4b415..93d06fd4582d 100644 --- a/tvix/castore/src/lib.rs +++ b/tvix/castore/src/lib.rs @@ -3,18 +3,26 @@ mod errors; mod hashing_reader; pub mod blobservice; +pub mod composition; pub mod directoryservice; pub mod fixtures; +pub mod refscan; #[cfg(feature = "fs")] pub mod fs; +mod nodes; +pub use nodes::*; + +mod path; +pub use path::{Path, PathBuf, PathComponent, PathComponentError}; + pub mod import; pub mod proto; pub mod tonic; pub use digests::{B3Digest, B3_LEN}; -pub use errors::Error; +pub use errors::{DirectoryError, Error, ValidateNodeError}; pub use hashing_reader::{B3HashingReader, HashingReader}; #[cfg(test)] diff --git a/tvix/castore/src/nodes/directory.rs b/tvix/castore/src/nodes/directory.rs new file mode 100644 index 000000000000..f80e055dde80 --- /dev/null +++ b/tvix/castore/src/nodes/directory.rs @@ -0,0 +1,287 @@ +use std::collections::btree_map::{self, BTreeMap}; + +use crate::{errors::DirectoryError, path::PathComponent, proto, B3Digest, Node}; + +/// A Directory contains nodes, which can be Directory, File or Symlink nodes. +/// It attaches names to these nodes, which is the basename in that directory. +/// These names: +/// - MUST not contain slashes or null bytes +/// - MUST not be '.' or '..' +/// - MUST be unique across all three lists +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct Directory { + nodes: BTreeMap<PathComponent, Node>, +} + +impl Directory { + /// Constructs a new, empty Directory. + pub fn new() -> Self { + Directory { + nodes: BTreeMap::new(), + } + } + + /// Construct a [Directory] from tuples of name and [Node]. + /// + /// Inserting multiple elements with the same name will yield an error, as + /// well as exceeding the maximum size. + pub fn try_from_iter<T: IntoIterator<Item = (PathComponent, Node)>>( + iter: T, + ) -> Result<Directory, DirectoryError> { + let mut nodes = BTreeMap::new(); + + iter.into_iter().try_fold(0u64, |size, (name, node)| { + check_insert_node(size, &mut nodes, name, node) + })?; + + Ok(Self { nodes }) + } + + /// The size of a directory is the number of all regular and symlink elements, + /// the number of directory elements, and their size fields. + pub fn size(&self) -> u64 { + // It's impossible to create a Directory where the size overflows, because we + // check before every add() that the size won't overflow. + (self.nodes.len() as u64) + + self + .nodes() + .map(|(_name, n)| match n { + Node::Directory { size, .. } => 1 + size, + Node::File { .. } | Node::Symlink { .. } => 1, + }) + .sum::<u64>() + } + + /// Calculates the digest of a Directory, which is the blake3 hash of a + /// Directory protobuf message, serialized in protobuf canonical form. + pub fn digest(&self) -> B3Digest { + proto::Directory::from(self.clone()).digest() + } + + /// Allows iterating over all nodes (directories, files and symlinks) + /// For each, it returns a tuple of its name and node. + /// The elements are sorted by their names. + pub fn nodes(&self) -> impl Iterator<Item = (&PathComponent, &Node)> + Send + Sync + '_ { + self.nodes.iter() + } + + /// Dissolves a Directory into its individual names and nodes. + /// The elements are sorted by their names. + pub fn into_nodes(self) -> impl Iterator<Item = (PathComponent, Node)> + Send + Sync { + self.nodes.into_iter() + } + + /// Adds the specified [Node] to the [Directory] with a given name. + /// + /// Inserting a node that already exists with the same name in the directory + /// will yield an error, as well as exceeding the maximum size. + /// + /// In case you want to construct a [Directory] from multiple elements, use + /// [from_iter] instead. + pub fn add(&mut self, name: PathComponent, node: Node) -> Result<(), DirectoryError> { + check_insert_node(self.size(), &mut self.nodes, name, node)?; + Ok(()) + } +} + +fn checked_sum(iter: impl IntoIterator<Item = u64>) -> Option<u64> { + iter.into_iter().try_fold(0u64, |acc, i| acc.checked_add(i)) +} + +/// Helper function dealing with inserting nodes into the nodes [BTreeMap], +/// after ensuring the new size doesn't overlow and the key doesn't exist already. +/// +/// Returns the new total size, or an error. +fn check_insert_node( + current_size: u64, + nodes: &mut BTreeMap<PathComponent, Node>, + name: PathComponent, + node: Node, +) -> Result<u64, DirectoryError> { + // Check that the even after adding this new directory entry, the size calculation will not + // overflow + let new_size = checked_sum([ + current_size, + 1, + match node { + Node::Directory { size, .. } => size, + _ => 0, + }, + ]) + .ok_or(DirectoryError::SizeOverflow)?; + + match nodes.entry(name) { + btree_map::Entry::Vacant(e) => { + e.insert(node); + } + btree_map::Entry::Occupied(occupied) => { + return Err(DirectoryError::DuplicateName(occupied.key().to_owned())) + } + } + + Ok(new_size) +} + +#[cfg(test)] +mod test { + use super::{Directory, Node}; + use crate::fixtures::DUMMY_DIGEST; + use crate::{DirectoryError, PathComponent}; + + #[test] + fn from_iter_single() { + Directory::try_from_iter([( + PathComponent::try_from("b").unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + )]) + .unwrap(); + } + + #[test] + fn from_iter_multiple() { + let d = Directory::try_from_iter([ + ( + "b".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ), + ( + "a".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ), + ( + "z".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ), + ( + "f".try_into().unwrap(), + Node::File { + digest: DUMMY_DIGEST.clone(), + size: 1, + executable: true, + }, + ), + ( + "c".try_into().unwrap(), + Node::File { + digest: DUMMY_DIGEST.clone(), + size: 1, + executable: true, + }, + ), + ( + "g".try_into().unwrap(), + Node::File { + digest: DUMMY_DIGEST.clone(), + size: 1, + executable: true, + }, + ), + ( + "t".try_into().unwrap(), + Node::Symlink { + target: "a".try_into().unwrap(), + }, + ), + ( + "o".try_into().unwrap(), + Node::Symlink { + target: "a".try_into().unwrap(), + }, + ), + ( + "e".try_into().unwrap(), + Node::Symlink { + target: "a".try_into().unwrap(), + }, + ), + ]) + .unwrap(); + + // Convert to proto struct and back to ensure we are not generating any invalid structures + crate::Directory::try_from(crate::proto::Directory::from(d)) + .expect("directory should be valid"); + } + + #[test] + fn add_nodes_to_directory() { + let mut d = Directory::new(); + + d.add( + "b".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ) + .unwrap(); + d.add( + "a".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ) + .unwrap(); + + // Convert to proto struct and back to ensure we are not generating any invalid structures + crate::Directory::try_from(crate::proto::Directory::from(d)) + .expect("directory should be valid"); + } + + #[test] + fn validate_overflow() { + let mut d = Directory::new(); + + assert_eq!( + d.add( + "foo".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: u64::MAX + } + ), + Err(DirectoryError::SizeOverflow) + ); + } + + #[test] + fn add_duplicate_node_to_directory() { + let mut d = Directory::new(); + + d.add( + "a".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ) + .unwrap(); + assert_eq!( + format!( + "{}", + d.add( + "a".try_into().unwrap(), + Node::File { + digest: DUMMY_DIGEST.clone(), + size: 1, + executable: true + } + ) + .expect_err("adding duplicate dir entry must fail") + ), + "\"a\" is a duplicate name" + ); + } +} diff --git a/tvix/castore/src/nodes/mod.rs b/tvix/castore/src/nodes/mod.rs new file mode 100644 index 000000000000..ac7aa1e666df --- /dev/null +++ b/tvix/castore/src/nodes/mod.rs @@ -0,0 +1,48 @@ +//! This holds types describing nodes in the tvix-castore model. +mod directory; +mod symlink_target; + +use crate::B3Digest; +pub use directory::Directory; +pub use symlink_target::{SymlinkTarget, SymlinkTargetError}; + +/// A Node is either a [DirectoryNode], [FileNode] or [SymlinkNode]. +/// Nodes themselves don't have names, what gives them names is either them +/// being inside a [Directory], or a root node with its own name attached to it. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Node { + /// A DirectoryNode is a pointer to a [Directory], by its [Directory::digest]. + /// It also records a`size`. + /// Such a node is either an element in the [Directory] it itself is contained in, + /// or a standalone root node. + Directory { + /// The blake3 hash of a Directory message, serialized in protobuf canonical form. + digest: B3Digest, + /// Number of child elements in the Directory referred to by `digest`. + /// Calculated by summing up the numbers of nodes, and for each directory, + /// its size field. Can be used for inode allocation. + /// This field is precisely as verifiable as any other Merkle tree edge. + /// Resolve `digest`, and you can compute it incrementally. Resolve the entire + /// tree, and you can fully compute it from scratch. + /// A credulous implementation won't reject an excessive size, but this is + /// harmless: you'll have some ordinals without nodes. Undersizing is obvious + /// and easy to reject: you won't have an ordinal for some nodes. + size: u64, + }, + /// A FileNode represents a regular or executable file in a Directory or at the root. + File { + /// The blake3 digest of the file contents + digest: B3Digest, + + /// The file content size + size: u64, + + /// Whether the file is executable + executable: bool, + }, + /// A SymlinkNode represents a symbolic link in a Directory or at the root. + Symlink { + /// The target of the symlink. + target: SymlinkTarget, + }, +} diff --git a/tvix/castore/src/nodes/symlink_target.rs b/tvix/castore/src/nodes/symlink_target.rs new file mode 100644 index 000000000000..e9a1a0bd05c2 --- /dev/null +++ b/tvix/castore/src/nodes/symlink_target.rs @@ -0,0 +1,223 @@ +use bstr::ByteSlice; +use std::fmt::{self, Debug, Display}; + +/// A wrapper type for symlink targets. +/// Internally uses a [bytes::Bytes], but disallows empty targets and those +/// containing null bytes. +#[repr(transparent)] +#[derive(Clone, PartialEq, Eq)] +pub struct SymlinkTarget { + inner: bytes::Bytes, +} + +/// The maximum length a symlink target can have. +/// Linux allows 4095 bytes here. +pub const MAX_TARGET_LEN: usize = 4095; + +impl AsRef<[u8]> for SymlinkTarget { + fn as_ref(&self) -> &[u8] { + self.inner.as_ref() + } +} + +impl From<SymlinkTarget> for bytes::Bytes { + fn from(value: SymlinkTarget) -> Self { + value.inner + } +} + +fn validate_symlink_target<B: AsRef<[u8]>>(symlink_target: B) -> Result<B, SymlinkTargetError> { + let v = symlink_target.as_ref(); + + if v.is_empty() { + return Err(SymlinkTargetError::Empty); + } + if v.len() > MAX_TARGET_LEN { + return Err(SymlinkTargetError::TooLong); + } + if v.contains(&0x00) { + return Err(SymlinkTargetError::Null); + } + + Ok(symlink_target) +} + +impl TryFrom<bytes::Bytes> for SymlinkTarget { + type Error = SymlinkTargetError; + + fn try_from(value: bytes::Bytes) -> Result<Self, Self::Error> { + if let Err(e) = validate_symlink_target(&value) { + return Err(SymlinkTargetError::Convert(value, Box::new(e))); + } + + Ok(Self { inner: value }) + } +} + +impl TryFrom<&'static [u8]> for SymlinkTarget { + type Error = SymlinkTargetError; + + fn try_from(value: &'static [u8]) -> Result<Self, Self::Error> { + if let Err(e) = validate_symlink_target(&value) { + return Err(SymlinkTargetError::Convert(value.into(), Box::new(e))); + } + + Ok(Self { + inner: bytes::Bytes::from_static(value), + }) + } +} + +impl TryFrom<&str> for SymlinkTarget { + type Error = SymlinkTargetError; + + fn try_from(value: &str) -> Result<Self, Self::Error> { + if let Err(e) = validate_symlink_target(value) { + return Err(SymlinkTargetError::Convert( + value.to_owned().into(), + Box::new(e), + )); + } + + Ok(Self { + inner: bytes::Bytes::copy_from_slice(value.as_bytes()), + }) + } +} + +impl Debug for SymlinkTarget { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(self.inner.as_bstr(), f) + } +} + +impl Display for SymlinkTarget { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(self.inner.as_bstr(), f) + } +} + +/// Errors created when constructing / converting to [SymlinkTarget]. +#[derive(Debug, PartialEq, Eq, thiserror::Error)] +#[cfg_attr(test, derive(Clone))] +pub enum SymlinkTargetError { + #[error("cannot be empty")] + Empty, + #[error("cannot contain null bytes")] + Null, + #[error("cannot be over {} bytes long", MAX_TARGET_LEN)] + TooLong, + #[error("unable to convert '{:?}", .0.as_bstr())] + Convert(bytes::Bytes, Box<Self>), +} + +#[cfg(test)] +mod tests { + use bytes::Bytes; + use rstest::rstest; + + use super::validate_symlink_target; + use super::{SymlinkTarget, SymlinkTargetError}; + + #[rstest] + #[case::empty(b"", SymlinkTargetError::Empty)] + #[case::null(b"foo\0", SymlinkTargetError::Null)] + fn errors(#[case] v: &'static [u8], #[case] err: SymlinkTargetError) { + { + assert_eq!( + Err(err.clone()), + validate_symlink_target(v), + "validate_symlink_target must fail as expected" + ); + } + + let exp_err_v = Bytes::from_static(v); + + // Bytes + { + let v = Bytes::from_static(v); + assert_eq!( + Err(SymlinkTargetError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + SymlinkTarget::try_from(v), + "conversion must fail as expected" + ); + } + // &[u8] + { + assert_eq!( + Err(SymlinkTargetError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + SymlinkTarget::try_from(v), + "conversion must fail as expected" + ); + } + // &str, if this is valid UTF-8 + { + if let Ok(v) = std::str::from_utf8(v) { + assert_eq!( + Err(SymlinkTargetError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + SymlinkTarget::try_from(v), + "conversion must fail as expected" + ); + } + } + } + + #[test] + fn error_toolong() { + assert_eq!( + Err(SymlinkTargetError::TooLong), + validate_symlink_target("X".repeat(5000).into_bytes().as_slice()) + ) + } + + #[rstest] + #[case::boring(b"aa")] + #[case::dot(b".")] + #[case::dotsandslashes(b"./..")] + #[case::dotdot(b"..")] + #[case::slashes(b"a/b")] + #[case::slashes_and_absolute(b"/a/b")] + #[case::invalid_utf8(b"\xc5\xc4\xd6")] + fn success(#[case] v: &'static [u8]) { + let exp = SymlinkTarget { inner: v.into() }; + + // Bytes + { + let v: Bytes = v.into(); + assert_eq!( + Ok(exp.clone()), + SymlinkTarget::try_from(v), + "conversion must succeed" + ) + } + + // &[u8] + { + assert_eq!( + Ok(exp.clone()), + SymlinkTarget::try_from(v), + "conversion must succeed" + ) + } + + // &str, if this is valid UTF-8 + { + if let Ok(v) = std::str::from_utf8(v) { + assert_eq!( + Ok(exp.clone()), + SymlinkTarget::try_from(v), + "conversion must succeed" + ) + } + } + } +} diff --git a/tvix/castore/src/path/component.rs b/tvix/castore/src/path/component.rs new file mode 100644 index 000000000000..78aca03c50fe --- /dev/null +++ b/tvix/castore/src/path/component.rs @@ -0,0 +1,268 @@ +use bstr::ByteSlice; +use std::fmt::{self, Debug, Display}; + +/// A wrapper type for validated path components in the castore model. +/// Internally uses a [bytes::Bytes], but disallows +/// slashes, and null bytes to be present, as well as +/// '.', '..' and the empty string. +/// It also rejects components that are too long (> 255 bytes). +#[repr(transparent)] +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct PathComponent { + pub(super) inner: bytes::Bytes, +} + +/// The maximum length an individual path component can have. +/// Linux allows 255 bytes of actual name, so we pick that. +pub const MAX_NAME_LEN: usize = 255; + +impl AsRef<[u8]> for PathComponent { + fn as_ref(&self) -> &[u8] { + self.inner.as_ref() + } +} + +impl From<PathComponent> for bytes::Bytes { + fn from(value: PathComponent) -> Self { + value.inner + } +} + +pub(super) fn validate_name<B: AsRef<[u8]>>(name: B) -> Result<(), PathComponentError> { + match name.as_ref() { + b"" => Err(PathComponentError::Empty), + b".." => Err(PathComponentError::Parent), + b"." => Err(PathComponentError::CurDir), + v if v.len() > MAX_NAME_LEN => Err(PathComponentError::TooLong), + v if v.contains(&0x00) => Err(PathComponentError::Null), + v if v.contains(&b'/') => Err(PathComponentError::Slashes), + _ => Ok(()), + } +} + +impl TryFrom<bytes::Bytes> for PathComponent { + type Error = PathComponentError; + + fn try_from(value: bytes::Bytes) -> Result<Self, Self::Error> { + if let Err(e) = validate_name(&value) { + return Err(PathComponentError::Convert(value, Box::new(e))); + } + + Ok(Self { inner: value }) + } +} + +impl TryFrom<&'static [u8]> for PathComponent { + type Error = PathComponentError; + + fn try_from(value: &'static [u8]) -> Result<Self, Self::Error> { + if let Err(e) = validate_name(value) { + return Err(PathComponentError::Convert(value.into(), Box::new(e))); + } + + Ok(Self { + inner: bytes::Bytes::from_static(value), + }) + } +} + +impl TryFrom<&str> for PathComponent { + type Error = PathComponentError; + + fn try_from(value: &str) -> Result<Self, Self::Error> { + if let Err(e) = validate_name(value) { + return Err(PathComponentError::Convert( + value.to_owned().into(), + Box::new(e), + )); + } + + Ok(Self { + inner: bytes::Bytes::copy_from_slice(value.as_bytes()), + }) + } +} + +impl TryFrom<&std::ffi::CStr> for PathComponent { + type Error = PathComponentError; + + fn try_from(value: &std::ffi::CStr) -> Result<Self, Self::Error> { + let value = value.to_bytes(); + if let Err(e) = validate_name(value) { + return Err(PathComponentError::Convert( + value.to_owned().into(), + Box::new(e), + )); + } + + Ok(Self { + inner: bytes::Bytes::copy_from_slice(value), + }) + } +} + +impl Debug for PathComponent { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(self.inner.as_bstr(), f) + } +} + +impl Display for PathComponent { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(self.inner.as_bstr(), f) + } +} + +/// Errors created when parsing / validating [PathComponent]. +#[derive(Debug, PartialEq, thiserror::Error)] +#[cfg_attr(test, derive(Clone))] +pub enum PathComponentError { + #[error("cannot be empty")] + Empty, + #[error("cannot contain null bytes")] + Null, + #[error("cannot be '.'")] + CurDir, + #[error("cannot be '..'")] + Parent, + #[error("cannot contain slashes")] + Slashes, + #[error("cannot be over {} bytes long", MAX_NAME_LEN)] + TooLong, + #[error("unable to convert '{:?}'", .0.as_bstr())] + Convert(bytes::Bytes, #[source] Box<Self>), +} + +#[cfg(test)] +mod tests { + use std::ffi::CString; + + use bytes::Bytes; + use rstest::rstest; + + use super::{validate_name, PathComponent, PathComponentError}; + + #[rstest] + #[case::empty(b"", PathComponentError::Empty)] + #[case::null(b"foo\0", PathComponentError::Null)] + #[case::curdir(b".", PathComponentError::CurDir)] + #[case::parent(b"..", PathComponentError::Parent)] + #[case::slashes1(b"a/b", PathComponentError::Slashes)] + #[case::slashes2(b"/", PathComponentError::Slashes)] + fn errors(#[case] v: &'static [u8], #[case] err: PathComponentError) { + { + assert_eq!( + Err(err.clone()), + validate_name(v), + "validate_name must fail as expected" + ); + } + + let exp_err_v = Bytes::from_static(v); + + // Bytes + { + let v = Bytes::from_static(v); + assert_eq!( + Err(PathComponentError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + PathComponent::try_from(v), + "conversion must fail as expected" + ); + } + // &[u8] + { + assert_eq!( + Err(PathComponentError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + PathComponent::try_from(v), + "conversion must fail as expected" + ); + } + // &str, if it is valid UTF-8 + { + if let Ok(v) = std::str::from_utf8(v) { + assert_eq!( + Err(PathComponentError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + PathComponent::try_from(v), + "conversion must fail as expected" + ); + } + } + // &CStr, if it can be constructed (fails if the payload contains null bytes) + { + if let Ok(v) = CString::new(v) { + let v = v.as_ref(); + assert_eq!( + Err(PathComponentError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + PathComponent::try_from(v), + "conversion must fail as expected" + ); + } + } + } + + #[test] + fn error_toolong() { + assert_eq!( + Err(PathComponentError::TooLong), + validate_name("X".repeat(500).into_bytes().as_slice()) + ) + } + + #[test] + fn success() { + let exp = PathComponent { inner: "aa".into() }; + + // Bytes + { + let v: Bytes = "aa".into(); + assert_eq!( + Ok(exp.clone()), + PathComponent::try_from(v), + "conversion must succeed" + ); + } + + // &[u8] + { + let v: &[u8] = b"aa"; + assert_eq!( + Ok(exp.clone()), + PathComponent::try_from(v), + "conversion must succeed" + ); + } + + // &str + { + let v: &str = "aa"; + assert_eq!( + Ok(exp.clone()), + PathComponent::try_from(v), + "conversion must succeed" + ); + } + + // &CStr + { + let v = CString::new("aa").expect("CString must construct"); + let v = v.as_c_str(); + assert_eq!( + Ok(exp.clone()), + PathComponent::try_from(v), + "conversion must succeed" + ); + } + } +} diff --git a/tvix/castore/src/path/mod.rs b/tvix/castore/src/path/mod.rs new file mode 100644 index 000000000000..15f31a570da9 --- /dev/null +++ b/tvix/castore/src/path/mod.rs @@ -0,0 +1,470 @@ +//! Contains data structures to deal with Paths in the tvix-castore model. +use bstr::ByteSlice; +use std::{ + borrow::Borrow, + fmt::{self, Debug, Display}, + mem, + ops::Deref, + str::FromStr, +}; + +mod component; +pub use component::{PathComponent, PathComponentError}; + +/// Represents a Path in the castore model. +/// These are always relative, and platform-independent, which distinguishes +/// them from the ones provided in the standard library. +#[derive(Eq, Hash, PartialEq)] +#[repr(transparent)] // SAFETY: Representation has to match [u8] +pub struct Path { + // As node names in the castore model cannot contain slashes, + // we use them as component separators here. + inner: [u8], +} + +#[allow(dead_code)] +impl Path { + // SAFETY: The empty path is valid. + pub const ROOT: &'static Path = unsafe { Path::from_bytes_unchecked(&[]) }; + + /// Convert a byte slice to a path, without checking validity. + const unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Path { + // SAFETY: &[u8] and &Path have the same representation. + unsafe { mem::transmute(bytes) } + } + + fn from_bytes(bytes: &[u8]) -> Option<&Path> { + if !bytes.is_empty() { + // Ensure all components are valid castore node names. + for component in bytes.split_str(b"/") { + if component::validate_name(component).is_err() { + return None; + } + } + } + + // SAFETY: We have verified that the path contains no empty components. + Some(unsafe { Path::from_bytes_unchecked(bytes) }) + } + + pub fn into_boxed_bytes(self: Box<Path>) -> Box<[u8]> { + // SAFETY: Box<Path> and Box<[u8]> have the same representation. + unsafe { mem::transmute(self) } + } + + /// Returns the path without its final component, if there is one. + /// + /// Note that the parent of a bare file name is [Path::ROOT]. + /// [Path::ROOT] is the only path without a parent. + pub fn parent(&self) -> Option<&Path> { + // The root does not have a parent. + if self.inner.is_empty() { + return None; + } + + Some( + if let Some((parent, _file_name)) = self.inner.rsplit_once_str(b"/") { + // SAFETY: The parent of a valid Path is a valid Path. + unsafe { Path::from_bytes_unchecked(parent) } + } else { + // The parent of a bare file name is the root. + Path::ROOT + }, + ) + } + + /// Creates a PathBuf with `name` adjoined to self. + pub fn try_join(&self, name: &[u8]) -> Result<PathBuf, std::io::Error> { + let mut v = PathBuf::with_capacity(self.inner.len() + name.len() + 1); + v.inner.extend_from_slice(&self.inner); + v.try_push(name)?; + + Ok(v) + } + + /// Provides an iterator over the components of the path, + /// which are invividual [PathComponent]. + /// In case the path is empty, an empty iterator is returned. + pub fn components(&self) -> impl Iterator<Item = PathComponent> + '_ { + let mut iter = self.inner.split_str(&b"/"); + + // We don't want to return an empty element, consume it if it's the only one. + if self.inner.is_empty() { + let _ = iter.next(); + } + + iter.map(|b| PathComponent { + inner: bytes::Bytes::copy_from_slice(b), + }) + } + + /// Produces an iterator over the components of the path, which are + /// individual byte slices. + /// In case the path is empty, an empty iterator is returned. + pub fn components_bytes(&self) -> impl Iterator<Item = &[u8]> { + let mut iter = self.inner.split_str(&b"/"); + + // We don't want to return an empty element, consume it if it's the only one. + if self.inner.is_empty() { + let _ = iter.next(); + } + + iter + } + + /// Returns the final component of the Path, if there is one, in bytes. + pub fn file_name(&self) -> Option<PathComponent> { + self.components().last() + } + + /// Returns the final component of the Path, if there is one, in bytes. + pub fn file_name_bytes(&self) -> Option<&[u8]> { + self.components_bytes().last() + } + + pub fn as_bytes(&self) -> &[u8] { + &self.inner + } +} + +impl Debug for Path { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(self.inner.as_bstr(), f) + } +} + +impl Display for Path { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(self.inner.as_bstr(), f) + } +} + +impl AsRef<Path> for Path { + fn as_ref(&self) -> &Path { + self + } +} + +/// Represents a owned PathBuf in the castore model. +/// These are always relative, and platform-independent, which distinguishes +/// them from the ones provided in the standard library. +#[derive(Clone, Default, Eq, Hash, PartialEq)] +pub struct PathBuf { + inner: Vec<u8>, +} + +impl Deref for PathBuf { + type Target = Path; + + fn deref(&self) -> &Self::Target { + // SAFETY: PathBuf always contains a valid Path. + unsafe { Path::from_bytes_unchecked(&self.inner) } + } +} + +impl AsRef<Path> for PathBuf { + fn as_ref(&self) -> &Path { + self + } +} + +impl ToOwned for Path { + type Owned = PathBuf; + + fn to_owned(&self) -> Self::Owned { + PathBuf { + inner: self.inner.to_owned(), + } + } +} + +impl Borrow<Path> for PathBuf { + fn borrow(&self) -> &Path { + self + } +} + +impl From<Box<Path>> for PathBuf { + fn from(value: Box<Path>) -> Self { + // SAFETY: Box<Path> is always a valid path. + unsafe { PathBuf::from_bytes_unchecked(value.into_boxed_bytes().into_vec()) } + } +} + +impl From<&Path> for PathBuf { + fn from(value: &Path) -> Self { + value.to_owned() + } +} + +impl FromStr for PathBuf { + type Err = std::io::Error; + + fn from_str(s: &str) -> Result<PathBuf, Self::Err> { + Ok(Path::from_bytes(s.as_bytes()) + .ok_or(std::io::ErrorKind::InvalidData)? + .to_owned()) + } +} + +impl Debug for PathBuf { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&**self, f) + } +} + +impl Display for PathBuf { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&**self, f) + } +} + +impl PathBuf { + pub fn new() -> PathBuf { + Self::default() + } + + pub fn with_capacity(capacity: usize) -> PathBuf { + // SAFETY: The empty path is a valid path. + Self { + inner: Vec::with_capacity(capacity), + } + } + + /// Adjoins `name` to self. + pub fn try_push(&mut self, name: &[u8]) -> Result<(), std::io::Error> { + if component::validate_name(name).is_err() { + return Err(std::io::ErrorKind::InvalidData.into()); + } + + if !self.inner.is_empty() { + self.inner.push(b'/'); + } + + self.inner.extend_from_slice(name); + + Ok(()) + } + + /// Convert a byte vector to a PathBuf, without checking validity. + unsafe fn from_bytes_unchecked(bytes: Vec<u8>) -> PathBuf { + PathBuf { inner: bytes } + } + + /// Convert from a [&std::path::Path] to [Self]. + /// + /// - Self uses `/` as path separator. + /// - Absolute paths are always rejected, are are these with custom prefixes. + /// - Repeated separators are deduplicated. + /// - Occurrences of `.` are normalized away. + /// - A trailing slash is normalized away. + /// + /// A `canonicalize_dotdot` boolean controls whether `..` will get + /// canonicalized if possible, or should return an error. + /// + /// For more exotic paths, this conversion might produce different results + /// on different platforms, due to different underlying byte + /// representations, which is why it's restricted to unix for now. + #[cfg(unix)] + pub fn from_host_path( + host_path: &std::path::Path, + canonicalize_dotdot: bool, + ) -> Result<Self, std::io::Error> { + let mut p = PathBuf::with_capacity(host_path.as_os_str().len()); + + for component in host_path.components() { + match component { + std::path::Component::Prefix(_) | std::path::Component::RootDir => { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "found disallowed prefix or rootdir", + )) + } + std::path::Component::CurDir => continue, // ignore + std::path::Component::ParentDir => { + if canonicalize_dotdot { + // Try popping the last element from the path being constructed. + // FUTUREWORK: pop method? + p = p + .parent() + .ok_or_else(|| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + "found .. going too far up", + ) + })? + .to_owned(); + } else { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "found disallowed ..", + )); + } + } + std::path::Component::Normal(s) => { + // append the new component to the path being constructed. + p.try_push(s.as_encoded_bytes()).map_err(|_| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + "encountered invalid node in sub_path component", + ) + })? + } + } + } + + Ok(p) + } + + pub fn into_boxed_path(self) -> Box<Path> { + // SAFETY: Box<[u8]> and Box<Path> have the same representation, + // and PathBuf always contains a valid Path. + unsafe { mem::transmute(self.inner.into_boxed_slice()) } + } + + pub fn into_bytes(self) -> Vec<u8> { + self.inner + } +} + +#[cfg(test)] +mod test { + use super::{Path, PathBuf}; + use bstr::ByteSlice; + use rstest::rstest; + + // TODO: add some manual tests including invalid UTF-8 (hard to express + // with rstest) + + #[rstest] + #[case::empty("", 0)] + #[case("a", 1)] + #[case("a/b", 2)] + #[case("a/b/c", 3)] + // add two slightly more cursed variants. + // Technically nothing prevents us from representing this with castore, + // but maybe we want to disallow constructing paths like this as it's a + // bad idea. + #[case::cursed("C:\\a/b", 2)] + #[case::cursed("\\\\tvix-store", 1)] + pub fn from_str(#[case] s: &str, #[case] num_components: usize) { + let p: PathBuf = s.parse().expect("must parse"); + + assert_eq!(s.as_bytes(), p.as_bytes(), "inner bytes mismatch"); + assert_eq!( + num_components, + p.components_bytes().count(), + "number of components mismatch" + ); + } + + #[rstest] + #[case::absolute("/a/b")] + #[case::two_forward_slashes_start("//a/b")] + #[case::two_forward_slashes_middle("a/b//c/d")] + #[case::trailing_slash("a/b/")] + #[case::dot(".")] + #[case::dotdot("..")] + #[case::dot_start("./a")] + #[case::dotdot_start("../a")] + #[case::dot_middle("a/./b")] + #[case::dotdot_middle("a/../b")] + #[case::dot_end("a/b/.")] + #[case::dotdot_end("a/b/..")] + #[case::null("fo\0o")] + pub fn from_str_fail(#[case] s: &str) { + s.parse::<PathBuf>().expect_err("must fail"); + } + + #[rstest] + #[case("foo", "")] + #[case("foo/bar", "foo")] + #[case("foo2/bar2", "foo2")] + #[case("foo/bar/baz", "foo/bar")] + pub fn parent(#[case] p: PathBuf, #[case] exp_parent: PathBuf) { + assert_eq!(Some(&*exp_parent), p.parent()); + } + + #[rstest] + pub fn no_parent() { + assert!(Path::ROOT.parent().is_none()); + } + + #[rstest] + #[case("a", "b", "a/b")] + #[case("a", "b", "a/b")] + pub fn join_push(#[case] mut p: PathBuf, #[case] name: &str, #[case] exp_p: PathBuf) { + assert_eq!(exp_p, p.try_join(name.as_bytes()).expect("join failed")); + p.try_push(name.as_bytes()).expect("push failed"); + assert_eq!(exp_p, p); + } + + #[rstest] + #[case("a", "/")] + #[case("a", "")] + #[case("a", "b/c")] + #[case("", "/")] + #[case("", "")] + #[case("", "b/c")] + #[case("", ".")] + #[case("", "..")] + pub fn join_push_fail(#[case] mut p: PathBuf, #[case] name: &str) { + p.try_join(name.as_bytes()) + .expect_err("join succeeded unexpectedly"); + p.try_push(name.as_bytes()) + .expect_err("push succeeded unexpectedly"); + } + + #[rstest] + #[case::empty("", vec![])] + #[case("a", vec!["a"])] + #[case("a/b", vec!["a", "b"])] + #[case("a/b/c", vec!["a","b", "c"])] + pub fn components_bytes(#[case] p: PathBuf, #[case] exp_components: Vec<&str>) { + assert_eq!( + exp_components, + p.components_bytes() + .map(|x| x.to_str().unwrap()) + .collect::<Vec<_>>() + ); + } + + #[rstest] + #[case::empty("", "", false)] + #[case::path("a", "a", false)] + #[case::path2("a/b", "a/b", false)] + #[case::double_slash_middle("a//b", "a/b", false)] + #[case::dot(".", "", false)] + #[case::dot_start("./a/b", "a/b", false)] + #[case::dot_middle("a/./b", "a/b", false)] + #[case::dot_end("a/b/.", "a/b", false)] + #[case::trailing_slash("a/b/", "a/b", false)] + #[case::dotdot_canonicalize("a/..", "", true)] + #[case::dotdot_canonicalize2("a/../b", "b", true)] + #[cfg_attr(unix, case::faux_prefix("\\\\nix-store", "\\\\nix-store", false))] + #[cfg_attr(unix, case::faux_letter("C:\\foo.txt", "C:\\foo.txt", false))] + pub fn from_host_path( + #[case] host_path: std::path::PathBuf, + #[case] exp_path: PathBuf, + #[case] canonicalize_dotdot: bool, + ) { + let p = PathBuf::from_host_path(&host_path, canonicalize_dotdot).expect("must succeed"); + + assert_eq!(exp_path, p); + } + + #[rstest] + #[case::absolute("/", false)] + #[case::dotdot_root("..", false)] + #[case::dotdot_root_canonicalize("..", true)] + #[case::dotdot_root_no_canonicalize("a/..", false)] + #[case::invalid_name("foo/bar\0", false)] + // #[cfg_attr(windows, case::prefix("\\\\nix-store", false))] + // #[cfg_attr(windows, case::letter("C:\\foo.txt", false))] + pub fn from_host_path_fail( + #[case] host_path: std::path::PathBuf, + #[case] canonicalize_dotdot: bool, + ) { + PathBuf::from_host_path(&host_path, canonicalize_dotdot).expect_err("must fail"); + } +} diff --git a/tvix/castore/src/proto/grpc_directoryservice_wrapper.rs b/tvix/castore/src/proto/grpc_directoryservice_wrapper.rs index 7d741a3f07bb..62fdb34a25a0 100644 --- a/tvix/castore/src/proto/grpc_directoryservice_wrapper.rs +++ b/tvix/castore/src/proto/grpc_directoryservice_wrapper.rs @@ -1,12 +1,11 @@ -use crate::directoryservice::ClosureValidator; -use crate::proto; -use crate::{directoryservice::DirectoryService, B3Digest}; -use futures::StreamExt; +use crate::directoryservice::{DirectoryGraph, DirectoryService, LeavesToRootValidator}; +use crate::{proto, B3Digest, DirectoryError}; +use futures::stream::BoxStream; +use futures::TryStreamExt; use std::ops::Deref; -use tokio::sync::mpsc::channel; -use tokio_stream::wrappers::ReceiverStream; +use tokio_stream::once; use tonic::{async_trait, Request, Response, Status, Streaming}; -use tracing::{debug, instrument, warn}; +use tracing::{instrument, warn}; pub struct GRPCDirectoryServiceWrapper<T> { directory_service: T, @@ -23,63 +22,55 @@ impl<T> proto::directory_service_server::DirectoryService for GRPCDirectoryServi where T: Deref<Target = dyn DirectoryService> + Send + Sync + 'static, { - type GetStream = ReceiverStream<tonic::Result<proto::Directory, Status>>; + type GetStream = BoxStream<'static, tonic::Result<proto::Directory, Status>>; #[instrument(skip_all)] - async fn get( - &self, + async fn get<'a>( + &'a self, request: Request<proto::GetDirectoryRequest>, ) -> Result<Response<Self::GetStream>, Status> { - let (tx, rx) = channel(5); - let req_inner = request.into_inner(); - // look at the digest in the request and put it in the top of the queue. - match &req_inner.by_what { - None => return Err(Status::invalid_argument("by_what needs to be specified")), - Some(proto::get_directory_request::ByWhat::Digest(ref digest)) => { + let by_what = &req_inner + .by_what + .ok_or_else(|| Status::invalid_argument("invalid by_what"))?; + + match by_what { + proto::get_directory_request::ByWhat::Digest(ref digest) => { let digest: B3Digest = digest .clone() .try_into() .map_err(|_e| Status::invalid_argument("invalid digest length"))?; - if !req_inner.recursive { - let e: Result<proto::Directory, Status> = match self - .directory_service - .get(&digest) - .await - { - Ok(Some(directory)) => Ok(directory), - Ok(None) => { - Err(Status::not_found(format!("directory {} not found", digest))) - } - Err(e) => { - warn!(err = %e, directory.digest=%digest, "failed to get directory"); - Err(e.into()) - } - }; - - if tx.send(e).await.is_err() { - debug!("receiver dropped"); + Ok(tonic::Response::new({ + if !req_inner.recursive { + let directory = self + .directory_service + .get(&digest) + .await + .map_err(|e| { + warn!(err = %e, directory.digest=%digest, "failed to get directory"); + tonic::Status::new(tonic::Code::Internal, e.to_string()) + })? + .ok_or_else(|| { + Status::not_found(format!("directory {} not found", digest)) + })?; + + Box::pin(once(Ok(directory.into()))) + } else { + // If recursive was requested, traverse via get_recursive. + Box::pin( + self.directory_service + .get_recursive(&digest) + .map_ok(proto::Directory::from) + .map_err(|e| { + tonic::Status::new(tonic::Code::Internal, e.to_string()) + }), + ) } - } else { - // If recursive was requested, traverse via get_recursive. - let mut directories_it = self.directory_service.get_recursive(&digest); - - while let Some(e) = directories_it.next().await { - // map err in res from Error to Status - let res = e.map_err(|e| Status::internal(e.to_string())); - if tx.send(res).await.is_err() { - debug!("receiver dropped"); - break; - } - } - } + })) } } - - let receiver_stream = ReceiverStream::new(rx); - Ok(Response::new(receiver_stream)) } #[instrument(skip_all)] @@ -89,14 +80,22 @@ where ) -> Result<Response<proto::PutDirectoryResponse>, Status> { let mut req_inner = request.into_inner(); - // We put all Directory messages we receive into ClosureValidator first. - let mut validator = ClosureValidator::default(); + // We put all Directory messages we receive into DirectoryGraph. + let mut validator = DirectoryGraph::<LeavesToRootValidator>::default(); while let Some(directory) = req_inner.message().await? { - validator.add(directory)?; + validator + .add(directory.try_into().map_err(|e: DirectoryError| { + tonic::Status::new(tonic::Code::Internal, e.to_string()) + })?) + .map_err(|e| tonic::Status::new(tonic::Code::Internal, e.to_string()))?; } // drain, which validates connectivity too. - let directories = validator.finalize()?; + let directories = validator + .validate() + .map_err(|e| tonic::Status::new(tonic::Code::Internal, e.to_string()))? + .drain_leaves_to_root() + .collect::<Vec<_>>(); let mut directory_putter = self.directory_service.put_multiple_start(); for directory in directories { diff --git a/tvix/castore/src/proto/mod.rs b/tvix/castore/src/proto/mod.rs index 39c1bcc6faa0..89c68a4ad97b 100644 --- a/tvix/castore/src/proto/mod.rs +++ b/tvix/castore/src/proto/mod.rs @@ -1,18 +1,14 @@ -#![allow(non_snake_case)] -// https://github.com/hyperium/tonic/issues/1056 -use bstr::ByteSlice; -use std::{collections::HashSet, iter::Peekable, str}; - use prost::Message; +use std::cmp::Ordering; + mod grpc_blobservice_wrapper; mod grpc_directoryservice_wrapper; +use crate::{path::PathComponent, B3Digest, DirectoryError}; pub use grpc_blobservice_wrapper::GRPCBlobServiceWrapper; pub use grpc_directoryservice_wrapper::GRPCDirectoryServiceWrapper; -use crate::{B3Digest, B3_LEN}; - tonic::include_proto!("tvix.castore.v1"); #[cfg(feature = "tonic-reflection")] @@ -24,38 +20,6 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("tvix #[cfg(test)] mod tests; -/// Errors that can occur during the validation of [Directory] messages. -#[derive(Debug, PartialEq, Eq, thiserror::Error)] -pub enum ValidateDirectoryError { - /// Elements are not in sorted order - #[error("{:?} is not sorted", .0.as_bstr())] - WrongSorting(Vec<u8>), - /// Multiple elements with the same name encountered - #[error("{:?} is a duplicate name", .0.as_bstr())] - DuplicateName(Vec<u8>), - /// Invalid node - #[error("invalid node with name {:?}: {:?}", .0.as_bstr(), .1.to_string())] - InvalidNode(Vec<u8>, ValidateNodeError), - #[error("Total size exceeds u32::MAX")] - SizeOverflow, -} - -/// Errors that occur during Node validation -#[derive(Debug, PartialEq, Eq, thiserror::Error)] -pub enum ValidateNodeError { - #[error("No node set")] - NoNodeSet, - /// Invalid digest length encountered - #[error("Invalid Digest length: {0}")] - InvalidDigestLen(usize), - /// Invalid name encountered - #[error("Invalid name: {}", .0.as_bstr())] - InvalidName(Vec<u8>), - /// Invalid symlink target - #[error("Invalid symlink target: {}", .0.as_bstr())] - InvalidSymlinkTarget(Vec<u8>), -} - /// Errors that occur during StatBlobResponse validation #[derive(Debug, PartialEq, Eq, thiserror::Error)] pub enum ValidateStatBlobResponseError { @@ -64,184 +28,6 @@ pub enum ValidateStatBlobResponseError { InvalidDigestLen(usize, usize), } -/// Checks a Node name for validity as an intermediate node. -/// We disallow slashes, null bytes, '.', '..' and the empty string. -fn validate_node_name(name: &[u8]) -> Result<(), ValidateNodeError> { - if name.is_empty() - || name == b".." - || name == b"." - || name.contains(&0x00) - || name.contains(&b'/') - { - Err(ValidateNodeError::InvalidName(name.to_owned())) - } else { - Ok(()) - } -} - -/// NamedNode is implemented for [FileNode], [DirectoryNode] and [SymlinkNode] -/// and [node::Node], so we can ask all of them for the name easily. -pub trait NamedNode { - fn get_name(&self) -> &[u8]; -} - -impl NamedNode for &FileNode { - fn get_name(&self) -> &[u8] { - &self.name - } -} - -impl NamedNode for &DirectoryNode { - fn get_name(&self) -> &[u8] { - &self.name - } -} - -impl NamedNode for &SymlinkNode { - fn get_name(&self) -> &[u8] { - &self.name - } -} - -impl NamedNode for node::Node { - fn get_name(&self) -> &[u8] { - match self { - node::Node::File(node_file) => &node_file.name, - node::Node::Directory(node_directory) => &node_directory.name, - node::Node::Symlink(node_symlink) => &node_symlink.name, - } - } -} - -impl Node { - /// Ensures the node has a valid enum kind (is Some), and passes its - // per-enum validation. - pub fn validate(&self) -> Result<(), ValidateNodeError> { - if let Some(node) = self.node.as_ref() { - node.validate() - } else { - Err(ValidateNodeError::NoNodeSet) - } - } -} - -impl node::Node { - /// Returns the node with a new name. - pub fn rename(self, name: bytes::Bytes) -> Self { - match self { - node::Node::Directory(n) => node::Node::Directory(DirectoryNode { name, ..n }), - node::Node::File(n) => node::Node::File(FileNode { name, ..n }), - node::Node::Symlink(n) => node::Node::Symlink(SymlinkNode { name, ..n }), - } - } - - /// Ensures the node has a valid name, and checks the type-specific fields too. - pub fn validate(&self) -> Result<(), ValidateNodeError> { - match self { - // for a directory root node, ensure the digest has the appropriate size. - node::Node::Directory(directory_node) => { - if directory_node.digest.len() != B3_LEN { - Err(ValidateNodeError::InvalidDigestLen( - directory_node.digest.len(), - ))?; - } - validate_node_name(&directory_node.name) - } - // for a file root node, ensure the digest has the appropriate size. - node::Node::File(file_node) => { - if file_node.digest.len() != B3_LEN { - Err(ValidateNodeError::InvalidDigestLen(file_node.digest.len()))?; - } - validate_node_name(&file_node.name) - } - // ensure the symlink target is not empty and doesn't contain null bytes. - node::Node::Symlink(symlink_node) => { - if symlink_node.target.is_empty() || symlink_node.target.contains(&b'\0') { - Err(ValidateNodeError::InvalidSymlinkTarget( - symlink_node.target.to_vec(), - ))?; - } - validate_node_name(&symlink_node.name) - } - } - } -} - -impl PartialOrd for node::Node { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for node::Node { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.get_name().cmp(other.get_name()) - } -} - -impl PartialOrd for FileNode { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for FileNode { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.get_name().cmp(other.get_name()) - } -} - -impl PartialOrd for SymlinkNode { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for SymlinkNode { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.get_name().cmp(other.get_name()) - } -} - -impl PartialOrd for DirectoryNode { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for DirectoryNode { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.get_name().cmp(other.get_name()) - } -} - -/// Accepts a name, and a mutable reference to the previous name. -/// If the passed name is larger than the previous one, the reference is updated. -/// If it's not, an error is returned. -fn update_if_lt_prev<'n>( - prev_name: &mut &'n [u8], - name: &'n [u8], -) -> Result<(), ValidateDirectoryError> { - if *name < **prev_name { - return Err(ValidateDirectoryError::WrongSorting(name.to_vec())); - } - *prev_name = name; - Ok(()) -} - -/// Inserts the given name into a HashSet if it's not already in there. -/// If it is, an error is returned. -fn insert_once<'n>( - seen_names: &mut HashSet<&'n [u8]>, - name: &'n [u8], -) -> Result<(), ValidateDirectoryError> { - if seen_names.get(name).is_some() { - return Err(ValidateDirectoryError::DuplicateName(name.to_vec())); - } - seen_names.insert(name); - Ok(()) -} - fn checked_sum(iter: impl IntoIterator<Item = u64>) -> Option<u64> { iter.into_iter().try_fold(0u64, |acc, i| acc.checked_add(i)) } @@ -278,117 +64,233 @@ impl Directory { .as_bytes() .into() } +} - /// validate checks the directory for invalid data, such as: - /// - violations of name restrictions - /// - invalid digest lengths - /// - not properly sorted lists - /// - duplicate names in the three lists - pub fn validate(&self) -> Result<(), ValidateDirectoryError> { - let mut seen_names: HashSet<&[u8]> = HashSet::new(); - - let mut last_directory_name: &[u8] = b""; - let mut last_file_name: &[u8] = b""; - let mut last_symlink_name: &[u8] = b""; - - // check directories - for directory_node in &self.directories { - node::Node::Directory(directory_node.clone()) - .validate() - .map_err(|e| { - ValidateDirectoryError::InvalidNode(directory_node.name.to_vec(), e) - })?; - - update_if_lt_prev(&mut last_directory_name, &directory_node.name)?; - insert_once(&mut seen_names, &directory_node.name)?; - } +impl TryFrom<Directory> for crate::Directory { + type Error = DirectoryError; + + fn try_from(value: Directory) -> Result<Self, Self::Error> { + // Check directories, files and symlinks are sorted + // We'll notice duplicates across all three fields when constructing the Directory. + // FUTUREWORK: use is_sorted() once stable, and/or implement the producer for + // [crate::Directory::try_from_iter] iterating over all three and doing all checks inline. + value + .directories + .iter() + .try_fold(&b""[..], |prev_name, e| { + match e.name.as_ref().cmp(prev_name) { + Ordering::Less => Err(DirectoryError::WrongSorting(e.name.to_owned())), + Ordering::Equal => Err(DirectoryError::DuplicateName( + e.name + .to_owned() + .try_into() + .map_err(DirectoryError::InvalidName)?, + )), + Ordering::Greater => Ok(e.name.as_ref()), + } + })?; + value.files.iter().try_fold(&b""[..], |prev_name, e| { + match e.name.as_ref().cmp(prev_name) { + Ordering::Less => Err(DirectoryError::WrongSorting(e.name.to_owned())), + Ordering::Equal => Err(DirectoryError::DuplicateName( + e.name + .to_owned() + .try_into() + .map_err(DirectoryError::InvalidName)?, + )), + Ordering::Greater => Ok(e.name.as_ref()), + } + })?; + value.symlinks.iter().try_fold(&b""[..], |prev_name, e| { + match e.name.as_ref().cmp(prev_name) { + Ordering::Less => Err(DirectoryError::WrongSorting(e.name.to_owned())), + Ordering::Equal => Err(DirectoryError::DuplicateName( + e.name + .to_owned() + .try_into() + .map_err(DirectoryError::InvalidName)?, + )), + Ordering::Greater => Ok(e.name.as_ref()), + } + })?; - // check files - for file_node in &self.files { - node::Node::File(file_node.clone()) - .validate() - .map_err(|e| ValidateDirectoryError::InvalidNode(file_node.name.to_vec(), e))?; + // FUTUREWORK: use is_sorted() once stable, and/or implement the producer for + // [crate::Directory::try_from_iter] iterating over all three and doing all checks inline. + let mut elems: Vec<(PathComponent, crate::Node)> = + Vec::with_capacity(value.directories.len() + value.files.len() + value.symlinks.len()); - update_if_lt_prev(&mut last_file_name, &file_node.name)?; - insert_once(&mut seen_names, &file_node.name)?; + for e in value.directories { + elems.push( + Node { + node: Some(node::Node::Directory(e)), + } + .try_into_name_and_node()?, + ); } - // check symlinks - for symlink_node in &self.symlinks { - node::Node::Symlink(symlink_node.clone()) - .validate() - .map_err(|e| ValidateDirectoryError::InvalidNode(symlink_node.name.to_vec(), e))?; + for e in value.files { + elems.push( + Node { + node: Some(node::Node::File(e)), + } + .try_into_name_and_node()?, + ) + } - update_if_lt_prev(&mut last_symlink_name, &symlink_node.name)?; - insert_once(&mut seen_names, &symlink_node.name)?; + for e in value.symlinks { + elems.push( + Node { + node: Some(node::Node::Symlink(e)), + } + .try_into_name_and_node()?, + ) } - self.size_checked() - .ok_or(ValidateDirectoryError::SizeOverflow)?; + crate::Directory::try_from_iter(elems) + } +} - Ok(()) +impl From<crate::Directory> for Directory { + fn from(value: crate::Directory) -> Self { + let mut directories = vec![]; + let mut files = vec![]; + let mut symlinks = vec![]; + + for (name, node) in value.into_nodes() { + match node { + crate::Node::File { + digest, + size, + executable, + } => files.push(FileNode { + name: name.into(), + digest: digest.into(), + size, + executable, + }), + crate::Node::Directory { digest, size } => directories.push(DirectoryNode { + name: name.into(), + digest: digest.into(), + size, + }), + crate::Node::Symlink { target } => { + symlinks.push(SymlinkNode { + name: name.into(), + target: target.into(), + }); + } + } + } + + Directory { + directories, + files, + symlinks, + } } +} - /// Allows iterating over all three nodes ([DirectoryNode], [FileNode], - /// [SymlinkNode]) in an ordered fashion, as long as the individual lists - /// are sorted (which can be checked by the [Directory::validate]). - pub fn nodes(&self) -> DirectoryNodesIterator { - return DirectoryNodesIterator { - i_directories: self.directories.iter().peekable(), - i_files: self.files.iter().peekable(), - i_symlinks: self.symlinks.iter().peekable(), - }; +impl Node { + /// Converts a proto [Node] to a [crate::Node], and splits off the name as a [PathComponent]. + pub fn try_into_name_and_node(self) -> Result<(PathComponent, crate::Node), DirectoryError> { + let (name_bytes, node) = self.try_into_unchecked_name_and_checked_node()?; + Ok(( + name_bytes.try_into().map_err(DirectoryError::InvalidName)?, + node, + )) } - /// Adds the specified [node::Node] to the [Directory], preserving sorted entries. - /// This assumes the [Directory] to be sorted prior to adding the node. - /// - /// Inserting an element that already exists with the same name in the directory is not - /// supported. - pub fn add(&mut self, node: node::Node) { - debug_assert!( - !self.files.iter().any(|x| x.get_name() == node.get_name()), - "name already exists in files" - ); - debug_assert!( - !self - .directories - .iter() - .any(|x| x.get_name() == node.get_name()), - "name already exists in directories" - ); - debug_assert!( - !self - .symlinks - .iter() - .any(|x| x.get_name() == node.get_name()), - "name already exists in symlinks" - ); - - match node { - node::Node::File(node) => { - let pos = self - .files - .binary_search(&node) - .expect_err("Tvix bug: dir entry with name already exists"); - self.files.insert(pos, node); + /// Converts a proto [Node] to a [crate::Node], and splits off the name as a + /// [bytes::Bytes] without doing any checking of it. + fn try_into_unchecked_name_and_checked_node( + self, + ) -> Result<(bytes::Bytes, crate::Node), DirectoryError> { + match self.node.ok_or_else(|| DirectoryError::NoNodeSet)? { + node::Node::Directory(n) => { + let digest = B3Digest::try_from(n.digest) + .map_err(|e| DirectoryError::InvalidNode(n.name.clone(), e.into()))?; + + let node = crate::Node::Directory { + digest, + size: n.size, + }; + + Ok((n.name, node)) } - node::Node::Directory(node) => { - let pos = self - .directories - .binary_search(&node) - .expect_err("Tvix bug: dir entry with name already exists"); - self.directories.insert(pos, node); + node::Node::File(n) => { + let digest = B3Digest::try_from(n.digest) + .map_err(|e| DirectoryError::InvalidNode(n.name.clone(), e.into()))?; + + let node = crate::Node::File { + digest, + size: n.size, + executable: n.executable, + }; + + Ok((n.name, node)) } - node::Node::Symlink(node) => { - let pos = self - .symlinks - .binary_search(&node) - .expect_err("Tvix bug: dir entry with name already exists"); - self.symlinks.insert(pos, node); + + node::Node::Symlink(n) => { + let node = crate::Node::Symlink { + target: n.target.try_into().map_err(|e| { + DirectoryError::InvalidNode( + n.name.clone(), + crate::ValidateNodeError::InvalidSymlinkTarget(e), + ) + })?, + }; + + Ok((n.name, node)) } } } + + /// Converts a proto [Node] to a [crate::Node], and splits off the name and returns it as a + /// [bytes::Bytes]. + /// + /// The name must be empty. + pub fn try_into_anonymous_node(self) -> Result<crate::Node, DirectoryError> { + let (name, node) = Self::try_into_unchecked_name_and_checked_node(self)?; + + if !name.is_empty() { + return Err(DirectoryError::NameInAnonymousNode); + } + + Ok(node) + } + + /// Constructs a [Node] from a name and [crate::Node]. + /// The name is a [bytes::Bytes], not a [PathComponent], as we have use an + /// empty name in some places. + pub fn from_name_and_node(name: bytes::Bytes, n: crate::Node) -> Self { + match n { + crate::Node::Directory { digest, size } => Self { + node: Some(node::Node::Directory(DirectoryNode { + name, + digest: digest.into(), + size, + })), + }, + crate::Node::File { + digest, + size, + executable, + } => Self { + node: Some(node::Node::File(FileNode { + name, + digest: digest.into(), + size, + executable, + })), + }, + crate::Node::Symlink { target } => Self { + node: Some(node::Node::Symlink(SymlinkNode { + name, + target: target.into(), + })), + }, + } + } } impl StatBlobResponse { @@ -407,65 +309,3 @@ impl StatBlobResponse { Ok(()) } } - -/// Struct to hold the state of an iterator over all nodes of a Directory. -/// -/// Internally, this keeps peekable Iterators over all three lists of a -/// Directory message. -pub struct DirectoryNodesIterator<'a> { - // directory: &Directory, - i_directories: Peekable<std::slice::Iter<'a, DirectoryNode>>, - i_files: Peekable<std::slice::Iter<'a, FileNode>>, - i_symlinks: Peekable<std::slice::Iter<'a, SymlinkNode>>, -} - -/// looks at two elements implementing NamedNode, and returns true if "left -/// is smaller / comes first". -/// -/// Some(_) is preferred over None. -fn left_name_lt_right<A: NamedNode, B: NamedNode>(left: Option<&A>, right: Option<&B>) -> bool { - match left { - // if left is None, right always wins - None => false, - Some(left_inner) => { - // left is Some. - match right { - // left is Some, right is None - left wins. - None => true, - Some(right_inner) => { - // both are Some - compare the name. - return left_inner.get_name() < right_inner.get_name(); - } - } - } - } -} - -impl Iterator for DirectoryNodesIterator<'_> { - type Item = node::Node; - - // next returns the next node in the Directory. - // we peek at all three internal iterators, and pick the one with the - // smallest name, to ensure lexicographical ordering. - // The individual lists are already known to be sorted. - fn next(&mut self) -> Option<Self::Item> { - if left_name_lt_right(self.i_directories.peek(), self.i_files.peek()) { - // i_directories is still in the game, compare with symlinks - if left_name_lt_right(self.i_directories.peek(), self.i_symlinks.peek()) { - self.i_directories - .next() - .cloned() - .map(node::Node::Directory) - } else { - self.i_symlinks.next().cloned().map(node::Node::Symlink) - } - } else { - // i_files is still in the game, compare with symlinks - if left_name_lt_right(self.i_files.peek(), self.i_symlinks.peek()) { - self.i_files.next().cloned().map(node::Node::File) - } else { - self.i_symlinks.next().cloned().map(node::Node::Symlink) - } - } - } -} diff --git a/tvix/castore/src/proto/tests/directory.rs b/tvix/castore/src/proto/tests/directory.rs index 81b73a048d52..efbc4e9f2af1 100644 --- a/tvix/castore/src/proto/tests/directory.rs +++ b/tvix/castore/src/proto/tests/directory.rs @@ -1,7 +1,5 @@ -use crate::proto::{ - node, Directory, DirectoryNode, FileNode, SymlinkNode, ValidateDirectoryError, - ValidateNodeError, -}; +use crate::proto::{Directory, DirectoryError, DirectoryNode, FileNode, SymlinkNode}; +use crate::ValidateNodeError; use hex_literal::hex; @@ -149,7 +147,7 @@ fn digest() { #[test] fn validate_empty() { let d = Directory::default(); - assert_eq!(d.validate(), Ok(())); + assert!(crate::Directory::try_from(d).is_ok()); } #[test] @@ -157,18 +155,15 @@ fn validate_invalid_names() { { let d = Directory { directories: vec![DirectoryNode { - name: "".into(), + name: b"\0"[..].into(), digest: DUMMY_DIGEST.to_vec().into(), size: 42, }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(n, ValidateNodeError::InvalidName(_)) => { - assert_eq!(n, b"") - } - _ => panic!("unexpected error"), - }; + + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); } { @@ -180,12 +175,8 @@ fn validate_invalid_names() { }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(n, ValidateNodeError::InvalidName(_)) => { - assert_eq!(n, b".") - } - _ => panic!("unexpected error"), - }; + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); } { @@ -198,12 +189,8 @@ fn validate_invalid_names() { }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(n, ValidateNodeError::InvalidName(_)) => { - assert_eq!(n, b"..") - } - _ => panic!("unexpected error"), - }; + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); } { @@ -214,12 +201,8 @@ fn validate_invalid_names() { }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(n, ValidateNodeError::InvalidName(_)) => { - assert_eq!(n, b"\x00") - } - _ => panic!("unexpected error"), - }; + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); } { @@ -230,12 +213,20 @@ fn validate_invalid_names() { }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(n, ValidateNodeError::InvalidName(_)) => { - assert_eq!(n, b"foo/bar") - } - _ => panic!("unexpected error"), + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); + } + + { + let d = Directory { + symlinks: vec![SymlinkNode { + name: bytes::Bytes::copy_from_slice("X".repeat(500).into_bytes().as_slice()), + target: "foo".into(), + }], + ..Default::default() }; + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); } } @@ -249,8 +240,8 @@ fn validate_invalid_digest() { }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(_, ValidateNodeError::InvalidDigestLen(n)) => { + match crate::Directory::try_from(d).expect_err("must fail") { + DirectoryError::InvalidNode(_, ValidateNodeError::InvalidDigestLen(n)) => { assert_eq!(n, 2) } _ => panic!("unexpected error"), @@ -276,15 +267,15 @@ fn validate_sorting() { ], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::WrongSorting(s) => { - assert_eq!(s, b"a"); + match crate::Directory::try_from(d).expect_err("must fail") { + DirectoryError::WrongSorting(s) => { + assert_eq!(s.as_ref(), b"a"); } _ => panic!("unexpected error"), } } - // "a" exists twice, bad. + // "a" exists twice (same types), bad. { let d = Directory { directories: vec![ @@ -301,9 +292,31 @@ fn validate_sorting() { ], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::DuplicateName(s) => { - assert_eq!(s, b"a"); + match crate::Directory::try_from(d).expect_err("must fail") { + DirectoryError::DuplicateName(s) => { + assert_eq!(s.as_ref(), b"a"); + } + _ => panic!("unexpected error"), + } + } + + // "a" exists twice (different types), bad. + { + let d = Directory { + directories: vec![DirectoryNode { + name: "a".into(), + digest: DUMMY_DIGEST.to_vec().into(), + size: 42, + }], + symlinks: vec![SymlinkNode { + name: "a".into(), + target: "b".into(), + }], + ..Default::default() + }; + match crate::Directory::try_from(d).expect_err("must fail") { + DirectoryError::DuplicateName(s) => { + assert_eq!(s.as_ref(), b"a"); } _ => panic!("unexpected error"), } @@ -327,7 +340,7 @@ fn validate_sorting() { ..Default::default() }; - d.validate().expect("validate shouldn't error"); + crate::Directory::try_from(d).expect("validate shouldn't error"); } // [b, c] and [a] are both properly sorted. @@ -352,101 +365,6 @@ fn validate_sorting() { ..Default::default() }; - d.validate().expect("validate shouldn't error"); + crate::Directory::try_from(d).expect("validate shouldn't error"); } } - -#[test] -fn validate_overflow() { - let d = Directory { - directories: vec![DirectoryNode { - name: "foo".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: u64::MAX, - }], - ..Default::default() - }; - - match d.validate().expect_err("must fail") { - ValidateDirectoryError::SizeOverflow => {} - _ => panic!("unexpected error"), - } -} - -#[test] -fn add_nodes_to_directory() { - let mut d = Directory { - ..Default::default() - }; - - d.add(node::Node::Directory(DirectoryNode { - name: "b".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - })); - d.add(node::Node::Directory(DirectoryNode { - name: "a".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - })); - d.add(node::Node::Directory(DirectoryNode { - name: "z".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - })); - - d.add(node::Node::File(FileNode { - name: "f".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - executable: true, - })); - d.add(node::Node::File(FileNode { - name: "c".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - executable: true, - })); - d.add(node::Node::File(FileNode { - name: "g".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - executable: true, - })); - - d.add(node::Node::Symlink(SymlinkNode { - name: "t".into(), - target: "a".into(), - })); - d.add(node::Node::Symlink(SymlinkNode { - name: "o".into(), - target: "a".into(), - })); - d.add(node::Node::Symlink(SymlinkNode { - name: "e".into(), - target: "a".into(), - })); - - d.validate().expect("directory should be valid"); -} - -#[test] -#[cfg_attr(not(debug_assertions), ignore)] -#[should_panic = "name already exists in directories"] -fn add_duplicate_node_to_directory_panics() { - let mut d = Directory { - ..Default::default() - }; - - d.add(node::Node::Directory(DirectoryNode { - name: "a".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - })); - d.add(node::Node::File(FileNode { - name: "a".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - executable: true, - })); -} diff --git a/tvix/castore/src/proto/tests/directory_nodes_iterator.rs b/tvix/castore/src/proto/tests/directory_nodes_iterator.rs deleted file mode 100644 index 68f147a33210..000000000000 --- a/tvix/castore/src/proto/tests/directory_nodes_iterator.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::proto::Directory; -use crate::proto::DirectoryNode; -use crate::proto::FileNode; -use crate::proto::NamedNode; -use crate::proto::SymlinkNode; - -#[test] -fn iterator() { - let d = Directory { - directories: vec![ - DirectoryNode { - name: "c".into(), - ..DirectoryNode::default() - }, - DirectoryNode { - name: "d".into(), - ..DirectoryNode::default() - }, - DirectoryNode { - name: "h".into(), - ..DirectoryNode::default() - }, - DirectoryNode { - name: "l".into(), - ..DirectoryNode::default() - }, - ], - files: vec![ - FileNode { - name: "b".into(), - ..FileNode::default() - }, - FileNode { - name: "e".into(), - ..FileNode::default() - }, - FileNode { - name: "g".into(), - ..FileNode::default() - }, - FileNode { - name: "j".into(), - ..FileNode::default() - }, - ], - symlinks: vec![ - SymlinkNode { - name: "a".into(), - ..SymlinkNode::default() - }, - SymlinkNode { - name: "f".into(), - ..SymlinkNode::default() - }, - SymlinkNode { - name: "i".into(), - ..SymlinkNode::default() - }, - SymlinkNode { - name: "k".into(), - ..SymlinkNode::default() - }, - ], - }; - - // We keep this strings here and convert to string to make the comparison - // less messy. - let mut node_names: Vec<String> = vec![]; - - for node in d.nodes() { - node_names.push(String::from_utf8(node.get_name().to_vec()).unwrap()); - } - - assert_eq!( - vec!["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"], - node_names - ); -} diff --git a/tvix/castore/src/proto/tests/mod.rs b/tvix/castore/src/proto/tests/mod.rs index 8d903bacb6c5..9f6330914bff 100644 --- a/tvix/castore/src/proto/tests/mod.rs +++ b/tvix/castore/src/proto/tests/mod.rs @@ -1,2 +1,47 @@ +use super::{node, Node, SymlinkNode}; +use crate::DirectoryError; + mod directory; -mod directory_nodes_iterator; + +/// Create a node with an empty symlink target, and ensure it fails validation. +#[test] +fn convert_symlink_empty_target_invalid() { + Node { + node: Some(node::Node::Symlink(SymlinkNode { + name: "foo".into(), + target: "".into(), + })), + } + .try_into_name_and_node() + .expect_err("must fail validation"); +} + +/// Create a node with a symlink target including null bytes, and ensure it +/// fails validation. +#[test] +fn convert_symlink_target_null_byte_invalid() { + Node { + node: Some(node::Node::Symlink(SymlinkNode { + name: "foo".into(), + target: "foo\0".into(), + })), + } + .try_into_name_and_node() + .expect_err("must fail validation"); +} + +/// Create a node with a name, and ensure our ano +#[test] +fn convert_anonymous_with_name_fail() { + assert_eq!( + DirectoryError::NameInAnonymousNode, + Node { + node: Some(node::Node::Symlink(SymlinkNode { + name: "foo".into(), + target: "somewhereelse".into(), + })), + } + .try_into_anonymous_node() + .expect_err("must fail") + ) +} diff --git a/tvix/castore/src/refscan.rs b/tvix/castore/src/refscan.rs new file mode 100644 index 000000000000..352593020472 --- /dev/null +++ b/tvix/castore/src/refscan.rs @@ -0,0 +1,354 @@ +//! Simple scanner for non-overlapping, known references of Nix store paths in a +//! given string. +//! +//! This is used for determining build references (see +//! //tvix/eval/docs/build-references.md for more details). +//! +//! The scanner itself is using the Wu-Manber string-matching algorithm, using +//! our fork of the `wu-mamber` crate. +use pin_project::pin_project; +use std::collections::BTreeSet; +use std::pin::Pin; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; +use std::task::{ready, Poll}; +use tokio::io::{AsyncBufRead, AsyncRead, ReadBuf}; +use wu_manber::TwoByteWM; + +/// A searcher that incapsulates the candidates and the Wu-Manber searcher. +/// This is separate from the scanner because we need to look for the same +/// pattern in multiple outputs and don't want to pay the price of constructing +/// the searcher for each build output. +pub struct ReferencePatternInner<P> { + candidates: Vec<P>, + longest_candidate: usize, + // FUTUREWORK: Support overlapping patterns to be compatible with cpp Nix + searcher: Option<TwoByteWM>, +} + +#[derive(Clone)] +pub struct ReferencePattern<P> { + inner: Arc<ReferencePatternInner<P>>, +} + +impl<P> ReferencePattern<P> { + pub fn candidates(&self) -> &[P] { + &self.inner.candidates + } + + pub fn longest_candidate(&self) -> usize { + self.inner.longest_candidate + } +} + +impl<P: AsRef<[u8]>> ReferencePattern<P> { + /// Construct a new `ReferencePattern` that knows how to scan for the given + /// candidates. + pub fn new(candidates: Vec<P>) -> Self { + let searcher = if candidates.is_empty() { + None + } else { + Some(TwoByteWM::new(&candidates)) + }; + let longest_candidate = candidates.iter().fold(0, |v, c| v.max(c.as_ref().len())); + + ReferencePattern { + inner: Arc::new(ReferencePatternInner { + searcher, + candidates, + longest_candidate, + }), + } + } +} + +impl<P> From<Vec<P>> for ReferencePattern<P> +where + P: AsRef<[u8]>, +{ + fn from(candidates: Vec<P>) -> Self { + Self::new(candidates) + } +} + +/// Represents a "primed" reference scanner with an automaton that knows the set +/// of bytes patterns to scan for. +pub struct ReferenceScanner<P> { + pattern: ReferencePattern<P>, + matches: Vec<AtomicBool>, +} + +impl<P: AsRef<[u8]>> ReferenceScanner<P> { + /// Construct a new `ReferenceScanner` that knows how to scan for the given + /// candidate bytes patterns. + pub fn new<IP: Into<ReferencePattern<P>>>(pattern: IP) -> Self { + let pattern = pattern.into(); + let mut matches = Vec::new(); + for _ in 0..pattern.candidates().len() { + matches.push(AtomicBool::new(false)); + } + ReferenceScanner { pattern, matches } + } + + /// Scan the given buffer for all non-overlapping matches and collect them + /// in the scanner. + pub fn scan<S: AsRef<[u8]>>(&self, haystack: S) { + if haystack.as_ref().len() < self.pattern.longest_candidate() { + return; + } + + if let Some(searcher) = &self.pattern.inner.searcher { + for m in searcher.find(haystack) { + self.matches[m.pat_idx].store(true, Ordering::Release); + } + } + } + + pub fn pattern(&self) -> &ReferencePattern<P> { + &self.pattern + } + + pub fn matches(&self) -> Vec<bool> { + self.matches + .iter() + .map(|m| m.load(Ordering::Acquire)) + .collect() + } + + pub fn candidate_matches(&self) -> impl Iterator<Item = &P> { + let candidates = self.pattern.candidates(); + self.matches.iter().enumerate().filter_map(|(idx, found)| { + if found.load(Ordering::Acquire) { + Some(&candidates[idx]) + } else { + None + } + }) + } +} + +impl<P: Clone + Ord + AsRef<[u8]>> ReferenceScanner<P> { + /// Finalise the reference scanner and return the resulting matches. + pub fn finalise(self) -> BTreeSet<P> { + self.candidate_matches().cloned().collect() + } +} + +const DEFAULT_BUF_SIZE: usize = 8 * 1024; + +#[pin_project] +pub struct ReferenceReader<'a, P, R> { + scanner: &'a ReferenceScanner<P>, + buffer: Vec<u8>, + consumed: usize, + #[pin] + reader: R, +} + +impl<'a, P, R> ReferenceReader<'a, P, R> +where + P: AsRef<[u8]>, +{ + pub fn new(scanner: &'a ReferenceScanner<P>, reader: R) -> Self { + Self::with_capacity(DEFAULT_BUF_SIZE, scanner, reader) + } + + pub fn with_capacity(capacity: usize, scanner: &'a ReferenceScanner<P>, reader: R) -> Self { + // If capacity is not at least as long as longest_candidate we can't do a scan + let capacity = capacity.max(scanner.pattern().longest_candidate()); + ReferenceReader { + scanner, + buffer: Vec::with_capacity(capacity), + consumed: 0, + reader, + } + } +} + +impl<'a, P, R> AsyncRead for ReferenceReader<'a, P, R> +where + R: AsyncRead, + P: AsRef<[u8]>, +{ + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + buf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll<std::io::Result<()>> { + let internal_buf = ready!(self.as_mut().poll_fill_buf(cx))?; + let amt = buf.remaining().min(internal_buf.len()); + buf.put_slice(&internal_buf[..amt]); + self.consume(amt); + Poll::Ready(Ok(())) + } +} + +impl<'a, P, R> AsyncBufRead for ReferenceReader<'a, P, R> +where + R: AsyncRead, + P: AsRef<[u8]>, +{ + fn poll_fill_buf( + self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> Poll<std::io::Result<&[u8]>> { + #[allow(clippy::manual_saturating_arithmetic)] // for clarity + let overlap = self + .scanner + .pattern + .longest_candidate() + .checked_sub(1) + // If this overflows (longest_candidate = 0), that means there are no needles, + // so there is no need to have any overlap + .unwrap_or(0); + let mut this = self.project(); + // Still data in buffer + if *this.consumed < this.buffer.len() { + return Poll::Ready(Ok(&this.buffer[*this.consumed..])); + } + // We need to copy last `overlap` bytes to front to deal with references that overlap reads + if *this.consumed > overlap { + let start = this.buffer.len() - overlap; + this.buffer.copy_within(start.., 0); + this.buffer.truncate(overlap); + *this.consumed = overlap; + } + // Read at least until self.buffer.len() > overlap so we can do one scan + loop { + let filled = { + let mut buf = ReadBuf::uninit(this.buffer.spare_capacity_mut()); + ready!(this.reader.as_mut().poll_read(cx, &mut buf))?; + buf.filled().len() + }; + // SAFETY: We just read `filled` amount of data above + unsafe { + this.buffer.set_len(filled + this.buffer.len()); + } + if filled == 0 || this.buffer.len() > overlap { + break; + } + } + + #[allow(clippy::needless_borrows_for_generic_args)] // misfiring lint (breaks code below) + this.scanner.scan(&this.buffer); + + Poll::Ready(Ok(&this.buffer[*this.consumed..])) + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + debug_assert!(self.consumed + amt <= self.buffer.len()); + let this = self.project(); + *this.consumed += amt; + } +} + +#[cfg(test)] +mod tests { + use rstest::rstest; + use tokio::io::AsyncReadExt as _; + use tokio_test::io::Builder; + + use super::*; + + // The actual derivation of `nixpkgs.hello`. + const HELLO_DRV: &str = r#"Derive([("out","/nix/store/33l4p0pn0mybmqzaxfkpppyh7vx1c74p-hello-2.12.1","","")],[("/nix/store/6z1jfnqqgyqr221zgbpm30v91yfj3r45-bash-5.1-p16.drv",["out"]),("/nix/store/ap9g09fxbicj836zm88d56dn3ff4clxl-stdenv-linux.drv",["out"]),("/nix/store/pf80kikyxr63wrw56k00i1kw6ba76qik-hello-2.12.1.tar.gz.drv",["out"])],["/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],"x86_64-linux","/nix/store/4xw8n979xpivdc46a9ndcvyhwgif00hz-bash-5.1-p16/bin/bash",["-e","/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],[("buildInputs",""),("builder","/nix/store/4xw8n979xpivdc46a9ndcvyhwgif00hz-bash-5.1-p16/bin/bash"),("cmakeFlags",""),("configureFlags",""),("depsBuildBuild",""),("depsBuildBuildPropagated",""),("depsBuildTarget",""),("depsBuildTargetPropagated",""),("depsHostHost",""),("depsHostHostPropagated",""),("depsTargetTarget",""),("depsTargetTargetPropagated",""),("doCheck","1"),("doInstallCheck",""),("mesonFlags",""),("name","hello-2.12.1"),("nativeBuildInputs",""),("out","/nix/store/33l4p0pn0mybmqzaxfkpppyh7vx1c74p-hello-2.12.1"),("outputs","out"),("patches",""),("pname","hello"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("src","/nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz"),("stdenv","/nix/store/cp65c8nk29qq5cl1wyy5qyw103cwmax7-stdenv-linux"),("strictDeps",""),("system","x86_64-linux"),("version","2.12.1")])"#; + + #[test] + fn test_no_patterns() { + let scanner: ReferenceScanner<String> = ReferenceScanner::new(vec![]); + + scanner.scan(HELLO_DRV); + + let result = scanner.finalise(); + + assert_eq!(result.len(), 0); + } + + #[test] + fn test_single_match() { + let scanner = ReferenceScanner::new(vec![ + "/nix/store/4xw8n979xpivdc46a9ndcvyhwgif00hz-bash-5.1-p16".to_string(), + ]); + scanner.scan(HELLO_DRV); + + let result = scanner.finalise(); + + assert_eq!(result.len(), 1); + assert!(result.contains("/nix/store/4xw8n979xpivdc46a9ndcvyhwgif00hz-bash-5.1-p16")); + } + + #[test] + fn test_multiple_matches() { + let candidates = vec![ + // these exist in the drv: + "/nix/store/33l4p0pn0mybmqzaxfkpppyh7vx1c74p-hello-2.12.1".to_string(), + "/nix/store/pf80kikyxr63wrw56k00i1kw6ba76qik-hello-2.12.1.tar.gz.drv".to_string(), + "/nix/store/cp65c8nk29qq5cl1wyy5qyw103cwmax7-stdenv-linux".to_string(), + // this doesn't: + "/nix/store/fn7zvafq26f0c8b17brs7s95s10ibfzs-emacs-28.2.drv".to_string(), + ]; + + let scanner = ReferenceScanner::new(candidates.clone()); + scanner.scan(HELLO_DRV); + + let result = scanner.finalise(); + assert_eq!(result.len(), 3); + + for c in candidates[..3].iter() { + assert!(result.contains(c)); + } + } + + #[rstest] + #[case::normal(8096, 8096)] + #[case::small_capacity(8096, 1)] + #[case::small_read(1, 8096)] + #[case::all_small(1, 1)] + #[tokio::test] + async fn test_reference_reader(#[case] chunk_size: usize, #[case] capacity: usize) { + let candidates = vec![ + // these exist in the drv: + "33l4p0pn0mybmqzaxfkpppyh7vx1c74p", + "pf80kikyxr63wrw56k00i1kw6ba76qik", + "cp65c8nk29qq5cl1wyy5qyw103cwmax7", + // this doesn't: + "fn7zvafq26f0c8b17brs7s95s10ibfzs", + ]; + let pattern = ReferencePattern::new(candidates.clone()); + let scanner = ReferenceScanner::new(pattern); + let mut mock = Builder::new(); + for c in HELLO_DRV.as_bytes().chunks(chunk_size) { + mock.read(c); + } + let mock = mock.build(); + let mut reader = ReferenceReader::with_capacity(capacity, &scanner, mock); + let mut s = String::new(); + reader.read_to_string(&mut s).await.unwrap(); + assert_eq!(s, HELLO_DRV); + + let result = scanner.finalise(); + assert_eq!(result.len(), 3); + + for c in candidates[..3].iter() { + assert!(result.contains(c)); + } + } + + #[tokio::test] + async fn test_reference_reader_no_patterns() { + let pattern = ReferencePattern::new(Vec::<&str>::new()); + let scanner = ReferenceScanner::new(pattern); + let mut mock = Builder::new(); + mock.read(HELLO_DRV.as_bytes()); + let mock = mock.build(); + let mut reader = ReferenceReader::new(&scanner, mock); + let mut s = String::new(); + reader.read_to_string(&mut s).await.unwrap(); + assert_eq!(s, HELLO_DRV); + + let result = scanner.finalise(); + assert_eq!(result.len(), 0); + } + + // FUTUREWORK: Test with large file +} diff --git a/tvix/castore/src/tests/import.rs b/tvix/castore/src/tests/import.rs index 8b3bd5ce0ffc..51d1b68a4ec9 100644 --- a/tvix/castore/src/tests/import.rs +++ b/tvix/castore/src/tests/import.rs @@ -2,15 +2,11 @@ use crate::blobservice::{self, BlobService}; use crate::directoryservice; use crate::fixtures::*; use crate::import::fs::ingest_path; -use crate::proto; +use crate::Node; -use std::sync::Arc; use tempfile::TempDir; #[cfg(target_family = "unix")] -use std::os::unix::ffi::OsStrExt; - -#[cfg(target_family = "unix")] #[tokio::test] async fn symlink() { let blob_service = blobservice::from_addr("memory://").await.unwrap(); @@ -25,48 +21,47 @@ async fn symlink() { ) .unwrap(); - let root_node = ingest_path( - Arc::from(blob_service), + let root_node = ingest_path::<_, _, _, &[u8]>( + blob_service, directory_service, tmpdir.path().join("doesntmatter"), + None, ) .await .expect("must succeed"); assert_eq!( - proto::node::Node::Symlink(proto::SymlinkNode { - name: "doesntmatter".into(), - target: "/nix/store/somewhereelse".into(), - }), + Node::Symlink { + target: "/nix/store/somewhereelse".try_into().unwrap() + }, root_node, ) } #[tokio::test] async fn single_file() { - let blob_service = - Arc::from(blobservice::from_addr("memory://").await.unwrap()) as Arc<dyn BlobService>; + let blob_service = blobservice::from_addr("memory://").await.unwrap(); let directory_service = directoryservice::from_addr("memory://").await.unwrap(); let tmpdir = TempDir::new().unwrap(); std::fs::write(tmpdir.path().join("root"), HELLOWORLD_BLOB_CONTENTS).unwrap(); - let root_node = ingest_path( + let root_node = ingest_path::<_, _, _, &[u8]>( blob_service.clone(), directory_service, tmpdir.path().join("root"), + None, ) .await .expect("must succeed"); assert_eq!( - proto::node::Node::File(proto::FileNode { - name: "root".into(), - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), + Node::File { + digest: HELLOWORLD_BLOB_DIGEST.clone(), size: HELLOWORLD_BLOB_CONTENTS.len() as u64, executable: false, - }), + }, root_node, ); @@ -77,8 +72,7 @@ async fn single_file() { #[cfg(target_family = "unix")] #[tokio::test] async fn complicated() { - let blob_service = - Arc::from(blobservice::from_addr("memory://").await.unwrap()) as Arc<dyn BlobService>; + let blob_service = blobservice::from_addr("memory://").await.unwrap(); let directory_service = directoryservice::from_addr("memory://").await.unwrap(); let tmpdir = TempDir::new().unwrap(); @@ -92,23 +86,21 @@ async fn complicated() { // File ``keep/.keep` std::fs::write(tmpdir.path().join("keep").join(".keep"), vec![]).unwrap(); - let root_node = ingest_path(blob_service.clone(), &directory_service, tmpdir.path()) - .await - .expect("must succeed"); + let root_node = ingest_path::<_, _, _, &[u8]>( + blob_service.clone(), + &directory_service, + tmpdir.path(), + None, + ) + .await + .expect("must succeed"); // ensure root_node matched expectations assert_eq!( - proto::node::Node::Directory(proto::DirectoryNode { - name: tmpdir - .path() - .file_name() - .unwrap() - .as_bytes() - .to_owned() - .into(), - digest: DIRECTORY_COMPLICATED.digest().into(), + Node::Directory { + digest: DIRECTORY_COMPLICATED.digest().clone(), size: DIRECTORY_COMPLICATED.size(), - }), + }, root_node, ); diff --git a/tvix/castore/src/tonic.rs b/tvix/castore/src/tonic.rs index 4b65d6b028ef..e63e1ad7aab8 100644 --- a/tvix/castore/src/tonic.rs +++ b/tvix/castore/src/tonic.rs @@ -1,3 +1,4 @@ +use hyper_util::rt::TokioIo; use tokio::net::UnixStream; use tonic::transport::{Channel, Endpoint}; @@ -25,7 +26,10 @@ pub async fn channel_from_url(url: &url::Url) -> Result<Channel, self::Error> { let connector = tower::service_fn({ let url = url.clone(); - move |_: tonic::transport::Uri| UnixStream::connect(url.path().to_string().clone()) + move |_: tonic::transport::Uri| { + let unix = UnixStream::connect(url.path().to_string().clone()); + async move { Ok::<_, std::io::Error>(TokioIo::new(unix.await?)) } + } }); // the URL doesn't matter diff --git a/tvix/cli/Cargo.toml b/tvix/cli/Cargo.toml index ce8d36177187..d13cd17cbd0e 100644 --- a/tvix/cli/Cargo.toml +++ b/tvix/cli/Cargo.toml @@ -8,20 +8,29 @@ name = "tvix" path = "src/main.rs" [dependencies] -nix-compat = { path = "../nix-compat" } tvix-build = { path = "../build" } -tvix-castore = { path = "../castore" } tvix-store = { path = "../store", default-features = false, features = []} tvix-eval = { path = "../eval" } tvix-glue = { path = "../glue" } -bytes = "1.4.0" -clap = { version = "4.0", features = ["derive", "env"] } -dirs = "4.0.0" -rustyline = "10.0.0" -thiserror = "1.0.38" -tokio = "1.28.0" -tracing = { version = "0.1.37", features = ["max_level_trace", "release_max_level_info"] } -tracing-subscriber = { version = "0.3.16", features = ["json"] } +tvix-tracing = { path = "../tracing" } +bytes = { workspace = true } +clap = { workspace = true, features = ["derive", "env"] } +dirs = { workspace = true } +rustyline = { workspace = true } +rnix = { workspace = true } +rowan = { workspace = true } +smol_str = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } +tracing-indicatif = { workspace = true } +rustc-hash = { workspace = true } +mimalloc = { workspace = true } +wu-manber = { workspace = true } -[dependencies.wu-manber] -git = "https://github.com/tvlfyi/wu-manber.git" +[dev-dependencies] +expect-test = { workspace = true } + +[features] +default = [] +tracy = ["tvix-tracing/tracy"] diff --git a/tvix/cli/default.nix b/tvix/cli/default.nix index 62e93cc21333..175e088c2dea 100644 --- a/tvix/cli/default.nix +++ b/tvix/cli/default.nix @@ -2,6 +2,9 @@ (depot.tvix.crates.workspaceMembers.tvix-cli.build.override { runTests = true; + testPreRun = '' + export SSL_CERT_FILE=/dev/null + ''; }).overrideAttrs (finalAttrs: previousAttrs: let @@ -27,7 +30,7 @@ let mkExprBenchmark = { expr, description }: let name = "tvix-cli-benchmark-${description}"; in (pkgs.runCommand name { } '' - export SSL_CERT_FILE=${pkgs.cacert.out}/etc/ssl/certs/ca-bundle.crt + export SSL_CERT_FILE=/dev/null ${lib.escapeShellArgs [ "${pkgs.time}/bin/time" "--format" "${benchmark-gnutime-format-string description}" @@ -46,24 +49,29 @@ let # Constructs a Derivation invoking tvix-cli inside a build, ensures the # calculated tvix output path matches what's passed in externally. - mkNixpkgsEvalTest = attrpath: expectedPath: - let - name = "tvix-eval-test-${builtins.replaceStrings [".drv"] ["-drv"] attrpath}"; - in - (pkgs.runCommand name { } '' - export SSL_CERT_FILE=${pkgs.cacert.out}/etc/ssl/certs/ca-bundle.crt - TVIX_OUTPUT=$(${tvix-cli}/bin/tvix -E '(import ${pkgs.path} {}).${attrpath}') - EXPECTED='${/* the verbatim expected Tvix output: */ "=> \"${builtins.unsafeDiscardStringContext expectedPath}\" :: string"}' + mkNixpkgsEvalTest = + { attrPath ? null # An attribute that must already be accessible from `pkgs`. Should evaluate to a store path. + , expr ? null # A Nix expression that should evaluate to a store path. + , expectedPath # The expected store path that should match one of the above. + }: + assert lib.assertMsg (attrPath != null || expr != null) "Either 'attrPath' or 'expr' must be set."; + let + name = "tvix-eval-test-${builtins.replaceStrings [".drv"] ["-drv"] (if expr != null then "custom-expr" else attrPath)}"; + in + (pkgs.runCommand name { } '' + export SSL_CERT_FILE=/dev/null + TVIX_OUTPUT=$(${tvix-cli}/bin/tvix --no-warnings -E '${if expr != null then expr else "(import ${pkgs.path} {}).${attrPath}"}') + EXPECTED='${/* the verbatim expected Tvix output: */ "=> \"${builtins.unsafeDiscardStringContext expectedPath}\" :: string"}' - echo "Tvix output: ''${TVIX_OUTPUT}" - if [ "$TVIX_OUTPUT" != "$EXPECTED" ]; then - echo "Correct would have been ''${EXPECTED}" - exit 1 - fi + echo "Tvix output: ''${TVIX_OUTPUT}" + if [ "$TVIX_OUTPUT" != "$EXPECTED" ]; then + echo "Correct would have been ''${EXPECTED}" + exit 1 + fi - echo "Output was correct." - touch $out - ''); + echo "Output was correct." + touch $out + ''); benchmarks = { @@ -76,13 +84,24 @@ let }; evalTests = { - eval-nixpkgs-stdenv-drvpath = (mkNixpkgsEvalTest "stdenv.drvPath" pkgs.stdenv.drvPath); - eval-nixpkgs-stdenv-outpath = (mkNixpkgsEvalTest "stdenv.outPath" pkgs.stdenv.outPath); - eval-nixpkgs-hello-outpath = (mkNixpkgsEvalTest "hello.outPath" pkgs.hello.outPath); - eval-nixpkgs-firefox-outpath = (mkNixpkgsEvalTest "firefox.outPath" pkgs.firefox.outPath); - eval-nixpkgs-firefox-drvpath = (mkNixpkgsEvalTest "firefox.drvPath" pkgs.firefox.drvPath); - eval-nixpkgs-cross-stdenv-outpath = (mkNixpkgsEvalTest "pkgsCross.aarch64-multiplatform.stdenv.outPath" pkgs.pkgsCross.aarch64-multiplatform.stdenv.outPath); - eval-nixpkgs-cross-hello-outpath = (mkNixpkgsEvalTest "pkgsCross.aarch64-multiplatform.hello.outPath" pkgs.pkgsCross.aarch64-multiplatform.hello.outPath); + eval-nixpkgs-stdenv-drvpath = (mkNixpkgsEvalTest { attrPath = "stdenv.drvPath"; expectedPath = pkgs.stdenv.drvPath; }); + eval-nixpkgs-stdenv-outpath = (mkNixpkgsEvalTest { attrPath = "stdenv.outPath"; expectedPath = pkgs.stdenv.outPath; }); + eval-nixpkgs-hello-outpath = (mkNixpkgsEvalTest { attrPath = "hello.outPath"; expectedPath = pkgs.hello.outPath; }); + eval-nixpkgs-firefox-outpath = (mkNixpkgsEvalTest { attrPath = "firefox.outPath"; expectedPath = pkgs.firefox.outPath; }); + eval-nixpkgs-firefox-drvpath = (mkNixpkgsEvalTest { attrPath = "firefox.drvPath"; expectedPath = pkgs.firefox.drvPath; }); + eval-nixpkgs-cross-stdenv-outpath = (mkNixpkgsEvalTest { attrPath = "pkgsCross.aarch64-multiplatform.stdenv.outPath"; expectedPath = pkgs.pkgsCross.aarch64-multiplatform.stdenv.outPath; }); + eval-nixpkgs-cross-hello-outpath = (mkNixpkgsEvalTest { attrPath = "pkgsCross.aarch64-multiplatform.hello.outPath"; expectedPath = pkgs.pkgsCross.aarch64-multiplatform.hello.outPath; }); + # Our CI runner currently uses Nix version lower than 2.12, which means it uses the old JSON library. + # The NixOS docs generate a JSON file with all the NixOS options, and so output is different between Tvix (and Nix 2.12+) and our CI runner's Nix version, + # so we disable the NixOS docs generation for now. TODO(kranzes): Re-enable NixOS docs once the CI runner is using a newer Nix version. + eval-nixpkgs-nixos-gnome-installer-drvpath = (mkNixpkgsEvalTest { + expr = "(import ${pkgs.path}/nixos/release.nix { configuration = { documentation.nixos.enable = (import ${pkgs.path}/lib).mkForce false; }; }).iso_gnome.${pkgs.system}.drvPath"; + expectedPath = (import "${pkgs.path}/nixos/release.nix" { configuration.documentation.nixos.enable = lib.mkForce false; }).iso_gnome.${pkgs.system}.drvPath; + }); + eval-nixpkgs-nixos-gnome-installer-outpath = (mkNixpkgsEvalTest { + expr = "(import ${pkgs.path}/nixos/release.nix { configuration = { documentation.nixos.enable = (import ${pkgs.path}/lib).mkForce false; }; }).iso_gnome.${pkgs.system}.outPath"; + expectedPath = (import "${pkgs.path}/nixos/release.nix" { configuration.documentation.nixos.enable = lib.mkForce false; }).iso_gnome.${pkgs.system}.outPath; + }); }; in { @@ -91,5 +110,5 @@ in }; # Expose benchmarks and evalTests as standard CI targets. - passthru = benchmarks // evalTests; + passthru = previousAttrs.passthru // benchmarks // evalTests; }) diff --git a/tvix/cli/src/args.rs b/tvix/cli/src/args.rs new file mode 100644 index 000000000000..d47258f10e26 --- /dev/null +++ b/tvix/cli/src/args.rs @@ -0,0 +1,78 @@ +use std::path::PathBuf; + +use clap::Parser; +use tvix_store::utils::ServiceUrlsMemory; + +/// Provides a CLI interface to trigger evaluation using tvix-eval. +/// +/// Uses configured tvix-[ca]store and tvix-build components, +/// and by default a set of builtins similar to these present in Nix. +/// +/// None of the stores available add to the local `/nix/store` location. +/// +/// The CLI interface is not stable and subject to change. +#[derive(Parser, Clone)] +pub struct Args { + /// Path to a script to evaluate + pub script: Option<PathBuf>, + + #[clap(long, short = 'E')] + pub expr: Option<String>, + + /// Dump the raw AST to stdout before interpreting + #[clap(long, env = "TVIX_DISPLAY_AST")] + pub display_ast: bool, + + /// Dump the bytecode to stdout before evaluating + #[clap(long, env = "TVIX_DUMP_BYTECODE")] + pub dump_bytecode: bool, + + /// Trace the runtime of the VM + #[clap(long, env = "TVIX_TRACE_RUNTIME")] + pub trace_runtime: bool, + + /// Capture the time (relative to the start time of evaluation) of all events traced with + /// `--trace-runtime` + #[clap(long, env = "TVIX_TRACE_RUNTIME_TIMING", requires("trace_runtime"))] + pub trace_runtime_timing: bool, + + /// Only compile, but do not execute code. This will make Tvix act + /// sort of like a linter. + #[clap(long)] + pub compile_only: bool, + + /// Don't print warnings. + #[clap(long)] + pub no_warnings: bool, + + /// A colon-separated list of directories to use to resolve `<...>`-style paths + #[clap(long, short = 'I', env = "NIX_PATH")] + pub nix_search_path: Option<String>, + + /// Print "raw" (unquoted) output. + #[clap(long)] + pub raw: bool, + + /// Strictly evaluate values, traversing them and forcing e.g. + /// elements of lists and attribute sets before printing the + /// return value. + #[clap(long)] + pub strict: bool, + + #[clap(flatten)] + pub service_addrs: ServiceUrlsMemory, + + #[arg(long, env, default_value = "dummy://")] + pub build_service_addr: String, + + /// An optional path in which Derivations encountered during evaluation + /// are dumped into, after evaluation. If it doesn't exist, the directory is created. + /// + /// Files dumped there are named like they would show up in `/nix/store`, + /// if produced by Nix. Existing files are not overwritten. + /// + /// This is only for debugging and diffing purposes for post-eval inspection; + /// Tvix does not read from these. + #[clap(long)] + pub drv_dumpdir: Option<PathBuf>, +} diff --git a/tvix/cli/src/assignment.rs b/tvix/cli/src/assignment.rs new file mode 100644 index 000000000000..6fd9725d2956 --- /dev/null +++ b/tvix/cli/src/assignment.rs @@ -0,0 +1,74 @@ +use rnix::{Root, SyntaxKind, SyntaxNode}; +use rowan::ast::AstNode; + +/// An assignment of an identifier to a value in the context of a REPL. +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) struct Assignment<'a> { + pub(crate) ident: &'a str, + pub(crate) value: rnix::ast::Expr, +} + +impl<'a> Assignment<'a> { + /// Try to parse an [`Assignment`] from the given input string. + /// + /// Returns [`None`] if the parsing fails for any reason, since the intent is for us to + /// fall-back to trying to parse the input as a regular expression or other REPL commands for + /// any reason, since the intent is for us to fall-back to trying to parse the input as a + /// regular expression or other REPL command. + pub fn parse(input: &'a str) -> Option<Self> { + let mut tt = rnix::tokenizer::Tokenizer::new(input); + macro_rules! next { + ($kind:ident) => {{ + loop { + let (kind, tok) = tt.next()?; + if kind == SyntaxKind::TOKEN_WHITESPACE { + continue; + } + if kind != SyntaxKind::$kind { + return None; + } + break tok; + } + }}; + } + + let ident = next!(TOKEN_IDENT); + let _equal = next!(TOKEN_ASSIGN); + let (green, errs) = rnix::parser::parse(tt); + let value = Root::cast(SyntaxNode::new_root(green))?.expr()?; + + if !errs.is_empty() { + return None; + } + + Some(Self { ident, value }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn simple_assignments() { + for input in ["x = 4", "x = \t\t\n\t4", "x=4"] { + let res = Assignment::parse(input).unwrap(); + assert_eq!(res.ident, "x"); + assert_eq!(res.value.to_string(), "4"); + } + } + + #[test] + fn complex_exprs() { + let input = "x = { y = 4; z = let q = 7; in [ q (y // { z = 9; }) ]; }"; + let res = Assignment::parse(input).unwrap(); + assert_eq!(res.ident, "x"); + } + + #[test] + fn not_an_assignment() { + let input = "{ x = 4; }"; + let res = Assignment::parse(input); + assert!(res.is_none(), "{input:?}"); + } +} diff --git a/tvix/cli/src/lib.rs b/tvix/cli/src/lib.rs new file mode 100644 index 000000000000..09ab62280945 --- /dev/null +++ b/tvix/cli/src/lib.rs @@ -0,0 +1,273 @@ +use std::path::PathBuf; +use std::rc::Rc; + +use rustc_hash::FxHashMap; +use smol_str::SmolStr; +use std::fmt::Write; +use tracing::{instrument, Span}; +use tracing_indicatif::span_ext::IndicatifSpanExt; +use tvix_build::buildservice; +use tvix_eval::{ + builtins::impure_builtins, + observer::{DisassemblingObserver, TracingObserver}, + ErrorKind, EvalIO, EvalMode, GlobalsMap, SourceCode, Value, +}; +use tvix_glue::{ + builtins::{add_derivation_builtins, add_fetcher_builtins, add_import_builtins}, + configure_nix_path, + tvix_io::TvixIO, + tvix_store_io::TvixStoreIO, +}; + +pub mod args; +pub mod assignment; +pub mod repl; + +pub use args::Args; +pub use repl::Repl; + +pub fn init_io_handle(tokio_runtime: &tokio::runtime::Runtime, args: &Args) -> Rc<TvixStoreIO> { + let (blob_service, directory_service, path_info_service, nar_calculation_service) = + tokio_runtime + .block_on(tvix_store::utils::construct_services( + args.service_addrs.clone(), + )) + .expect("unable to setup {blob|directory|pathinfo}service before interpreter setup"); + + let build_service = tokio_runtime + .block_on({ + let blob_service = blob_service.clone(); + let directory_service = directory_service.clone(); + async move { + buildservice::from_addr( + &args.build_service_addr, + blob_service.clone(), + directory_service.clone(), + ) + .await + } + }) + .expect("unable to setup buildservice before interpreter setup"); + + Rc::new(TvixStoreIO::new( + blob_service.clone(), + directory_service.clone(), + path_info_service, + nar_calculation_service.into(), + build_service.into(), + tokio_runtime.handle().clone(), + )) +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub enum AllowIncomplete { + Allow, + #[default] + RequireComplete, +} + +impl AllowIncomplete { + fn allow(&self) -> bool { + matches!(self, Self::Allow) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct IncompleteInput; + +pub struct EvalResult { + value: Option<Value>, + globals: Rc<GlobalsMap>, +} + +/// Interprets the given code snippet, printing out warnings and errors and returning the result +#[allow(clippy::too_many_arguments)] +pub fn evaluate( + tvix_store_io: Rc<TvixStoreIO>, + code: &str, + path: Option<PathBuf>, + args: &Args, + allow_incomplete: AllowIncomplete, + env: Option<&FxHashMap<SmolStr, Value>>, + globals: Option<Rc<GlobalsMap>>, + source_map: Option<SourceCode>, +) -> Result<EvalResult, IncompleteInput> { + let span = Span::current(); + span.pb_start(); + span.pb_set_style(&tvix_tracing::PB_SPINNER_STYLE); + span.pb_set_message("Setting up evaluator…"); + + let mut eval_builder = tvix_eval::Evaluation::builder(Box::new(TvixIO::new( + tvix_store_io.clone() as Rc<dyn EvalIO>, + )) as Box<dyn EvalIO>) + .enable_import() + .env(env); + + if args.strict { + eval_builder = eval_builder.mode(EvalMode::Strict); + } + + match globals { + Some(globals) => { + eval_builder = eval_builder.with_globals(globals); + } + None => { + eval_builder = eval_builder.add_builtins(impure_builtins()); + eval_builder = add_derivation_builtins(eval_builder, Rc::clone(&tvix_store_io)); + eval_builder = add_fetcher_builtins(eval_builder, Rc::clone(&tvix_store_io)); + eval_builder = add_import_builtins(eval_builder, Rc::clone(&tvix_store_io)); + } + }; + eval_builder = configure_nix_path(eval_builder, &args.nix_search_path); + + if let Some(source_map) = source_map { + eval_builder = eval_builder.with_source_map(source_map); + } + + let source_map = eval_builder.source_map().clone(); + let (result, globals) = { + let mut compiler_observer = + DisassemblingObserver::new(source_map.clone(), std::io::stderr()); + if args.dump_bytecode { + eval_builder.set_compiler_observer(Some(&mut compiler_observer)); + } + + let mut runtime_observer = TracingObserver::new(std::io::stderr()); + if args.trace_runtime { + if args.trace_runtime_timing { + runtime_observer.enable_timing() + } + eval_builder.set_runtime_observer(Some(&mut runtime_observer)); + } + + span.pb_set_message("Evaluating…"); + + let eval = eval_builder.build(); + let globals = eval.globals(); + let result = eval.evaluate(code, path); + (result, globals) + }; + + if allow_incomplete.allow() + && result.errors.iter().any(|err| { + matches!( + &err.kind, + ErrorKind::ParseErrors(pes) + if pes.iter().any(|pe| matches!(pe, rnix::parser::ParseError::UnexpectedEOF)) + ) + }) + { + return Err(IncompleteInput); + } + + if args.display_ast { + if let Some(ref expr) = result.expr { + eprintln!("AST: {}", tvix_eval::pretty_print_expr(expr)); + } + } + + for error in &result.errors { + error.fancy_format_stderr(); + } + + if !args.no_warnings { + for warning in &result.warnings { + warning.fancy_format_stderr(&source_map); + } + } + + if let Some(dumpdir) = &args.drv_dumpdir { + // Dump all known derivations files to `dumpdir`. + std::fs::create_dir_all(dumpdir).expect("failed to create drv dumpdir"); + tvix_store_io + .known_paths + .borrow() + .get_derivations() + // Skip already dumped derivations. + .filter(|(drv_path, _)| !dumpdir.join(drv_path.to_string()).exists()) + .for_each(|(drv_path, drv)| { + std::fs::write(dumpdir.join(drv_path.to_string()), drv.to_aterm_bytes()) + .expect("failed to write drv to dumpdir"); + }) + } + + Ok(EvalResult { + globals, + value: result.value, + }) +} + +pub struct InterpretResult { + output: String, + success: bool, + pub(crate) globals: Option<Rc<GlobalsMap>>, +} + +impl InterpretResult { + pub fn empty_success(globals: Option<Rc<GlobalsMap>>) -> Self { + Self { + output: String::new(), + success: true, + globals, + } + } + + pub fn finalize(self) -> bool { + print!("{}", self.output); + self.success + } + + pub fn output(&self) -> &str { + &self.output + } + + pub fn success(&self) -> bool { + self.success + } +} + +/// Interprets the given code snippet, printing out warnings, errors +/// and the result itself. The return value indicates whether +/// evaluation succeeded. +#[instrument(skip_all, fields(indicatif.pb_show=1))] +#[allow(clippy::too_many_arguments)] +pub fn interpret( + tvix_store_io: Rc<TvixStoreIO>, + code: &str, + path: Option<PathBuf>, + args: &Args, + explain: bool, + allow_incomplete: AllowIncomplete, + env: Option<&FxHashMap<SmolStr, Value>>, + globals: Option<Rc<GlobalsMap>>, + source_map: Option<SourceCode>, +) -> Result<InterpretResult, IncompleteInput> { + let mut output = String::new(); + let result = evaluate( + tvix_store_io, + code, + path, + args, + allow_incomplete, + env, + globals, + source_map, + )?; + + if let Some(value) = result.value.as_ref() { + if explain { + writeln!(&mut output, "=> {}", value.explain()).unwrap(); + } else if args.raw { + writeln!(&mut output, "{}", value.to_contextful_str().unwrap()).unwrap(); + } else { + writeln!(&mut output, "=> {} :: {}", value, value.type_of()).unwrap(); + } + } + + // inform the caller about any errors + Ok(InterpretResult { + output, + success: result.value.is_some(), + globals: Some(result.globals), + }) +} diff --git a/tvix/cli/src/main.rs b/tvix/cli/src/main.rs index 5635f446b993..338486195e3d 100644 --- a/tvix/cli/src/main.rs +++ b/tvix/cli/src/main.rs @@ -1,206 +1,39 @@ use clap::Parser; -use rustyline::{error::ReadlineError, Editor}; +use mimalloc::MiMalloc; use std::rc::Rc; use std::{fs, path::PathBuf}; -use tracing::Level; -use tracing_subscriber::fmt::writer::MakeWriterExt; -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; -use tracing_subscriber::{EnvFilter, Layer}; -use tvix_build::buildservice; -use tvix_eval::builtins::impure_builtins; -use tvix_eval::observer::{DisassemblingObserver, TracingObserver}; -use tvix_eval::{EvalIO, Value}; -use tvix_glue::builtins::add_fetcher_builtins; -use tvix_glue::builtins::add_import_builtins; -use tvix_glue::tvix_io::TvixIO; +use tvix_cli::args::Args; +use tvix_cli::repl::Repl; +use tvix_cli::{init_io_handle, interpret, AllowIncomplete}; +use tvix_eval::observer::DisassemblingObserver; +use tvix_eval::EvalMode; use tvix_glue::tvix_store_io::TvixStoreIO; -use tvix_glue::{builtins::add_derivation_builtins, configure_nix_path}; -#[derive(Parser)] -struct Args { - #[arg(long)] - log_level: Option<Level>, - - /// Path to a script to evaluate - script: Option<PathBuf>, - - #[clap(long, short = 'E')] - expr: Option<String>, - - /// Dump the raw AST to stdout before interpreting - #[clap(long, env = "TVIX_DISPLAY_AST")] - display_ast: bool, - - /// Dump the bytecode to stdout before evaluating - #[clap(long, env = "TVIX_DUMP_BYTECODE")] - dump_bytecode: bool, - - /// Trace the runtime of the VM - #[clap(long, env = "TVIX_TRACE_RUNTIME")] - trace_runtime: bool, - - /// Capture the time (relative to the start time of evaluation) of all events traced with - /// `--trace-runtime` - #[clap(long, env = "TVIX_TRACE_RUNTIME_TIMING", requires("trace_runtime"))] - trace_runtime_timing: bool, - - /// Only compile, but do not execute code. This will make Tvix act - /// sort of like a linter. - #[clap(long)] - compile_only: bool, - - /// Don't print warnings. - #[clap(long)] - no_warnings: bool, - - /// A colon-separated list of directories to use to resolve `<...>`-style paths - #[clap(long, short = 'I', env = "NIX_PATH")] - nix_search_path: Option<String>, - - /// Print "raw" (unquoted) output. - #[clap(long)] - raw: bool, - - /// Strictly evaluate values, traversing them and forcing e.g. - /// elements of lists and attribute sets before printing the - /// return value. - #[clap(long)] - strict: bool, - - #[arg(long, env, default_value = "memory://")] - blob_service_addr: String, - - #[arg(long, env, default_value = "memory://")] - directory_service_addr: String, - - #[arg(long, env, default_value = "memory://")] - path_info_service_addr: String, - - #[arg(long, env, default_value = "dummy://")] - build_service_addr: String, -} - -/// Interprets the given code snippet, printing out warnings, errors -/// and the result itself. The return value indicates whether -/// evaluation succeeded. -fn interpret(code: &str, path: Option<PathBuf>, args: &Args, explain: bool) -> bool { - let tokio_runtime = tokio::runtime::Runtime::new().expect("failed to setup tokio runtime"); - - let (blob_service, directory_service, path_info_service) = tokio_runtime - .block_on({ - let blob_service_addr = args.blob_service_addr.clone(); - let directory_service_addr = args.directory_service_addr.clone(); - let path_info_service_addr = args.path_info_service_addr.clone(); - async move { - tvix_store::utils::construct_services( - blob_service_addr, - directory_service_addr, - path_info_service_addr, - ) - .await - } - }) - .expect("unable to setup {blob|directory|pathinfo}service before interpreter setup"); - - let build_service = tokio_runtime - .block_on({ - let blob_service = blob_service.clone(); - let directory_service = directory_service.clone(); - async move { - buildservice::from_addr( - &args.build_service_addr, - blob_service.clone(), - directory_service.clone(), - ) - .await - } - }) - .expect("unable to setup buildservice before interpreter setup"); - - let tvix_store_io = Rc::new(TvixStoreIO::new( - blob_service.clone(), - directory_service.clone(), - path_info_service.into(), - build_service.into(), - tokio_runtime.handle().clone(), - )); - - let mut eval = tvix_eval::Evaluation::new( - Box::new(TvixIO::new(tvix_store_io.clone() as Rc<dyn EvalIO>)) as Box<dyn EvalIO>, - true, - ); - eval.strict = args.strict; - eval.builtins.extend(impure_builtins()); - add_derivation_builtins(&mut eval, Rc::clone(&tvix_store_io)); - add_fetcher_builtins(&mut eval, Rc::clone(&tvix_store_io)); - add_import_builtins(&mut eval, tvix_store_io); - configure_nix_path(&mut eval, &args.nix_search_path); - - let source_map = eval.source_map(); - let result = { - let mut compiler_observer = - DisassemblingObserver::new(source_map.clone(), std::io::stderr()); - if args.dump_bytecode { - eval.compiler_observer = Some(&mut compiler_observer); - } - - let mut runtime_observer = TracingObserver::new(std::io::stderr()); - if args.trace_runtime { - if args.trace_runtime_timing { - runtime_observer.enable_timing() - } - eval.runtime_observer = Some(&mut runtime_observer); - } - - eval.evaluate(code, path) - }; - - if args.display_ast { - if let Some(ref expr) = result.expr { - eprintln!("AST: {}", tvix_eval::pretty_print_expr(expr)); - } - } - - for error in &result.errors { - error.fancy_format_stderr(); - } - - if !args.no_warnings { - for warning in &result.warnings { - warning.fancy_format_stderr(&source_map); - } - } - - if let Some(value) = result.value.as_ref() { - if explain { - println!("=> {}", value.explain()); - } else { - println_result(value, args.raw); - } - } - - // inform the caller about any errors - result.errors.is_empty() -} +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; /// Interpret the given code snippet, but only run the Tvix compiler /// on it and return errors and warnings. fn lint(code: &str, path: Option<PathBuf>, args: &Args) -> bool { - let mut eval = tvix_eval::Evaluation::new_impure(); - eval.strict = args.strict; + let mut eval_builder = tvix_eval::Evaluation::builder_impure(); - let source_map = eval.source_map(); + if args.strict { + eval_builder = eval_builder.mode(EvalMode::Strict); + } + + let source_map = eval_builder.source_map().clone(); let mut compiler_observer = DisassemblingObserver::new(source_map.clone(), std::io::stderr()); if args.dump_bytecode { - eval.compiler_observer = Some(&mut compiler_observer); + eval_builder.set_compiler_observer(Some(&mut compiler_observer)); } if args.trace_runtime { eprintln!("warning: --trace-runtime has no effect with --compile-only!"); } + let eval = eval_builder.build(); let result = eval.compile_only(code, path); if args.display_ast { @@ -224,36 +57,40 @@ fn lint(code: &str, path: Option<PathBuf>, args: &Args) -> bool { fn main() { let args = Args::parse(); - // configure log settings - let level = args.log_level.unwrap_or(Level::INFO); - - let subscriber = tracing_subscriber::registry().with( - tracing_subscriber::fmt::Layer::new() - .with_writer(std::io::stderr.with_max_level(level)) - .compact() - .with_filter( - EnvFilter::builder() - .with_default_directive(level.into()) - .from_env() - .expect("invalid RUST_LOG"), - ), - ); - subscriber - .try_init() + let _ = tvix_tracing::TracingBuilder::default() + .enable_progressbar() + .build() .expect("unable to set up tracing subscriber"); + let tokio_runtime = tokio::runtime::Runtime::new().expect("failed to setup tokio runtime"); + + let io_handle = init_io_handle(&tokio_runtime, &args); if let Some(file) = &args.script { - run_file(file.clone(), &args) + run_file(io_handle, file.clone(), &args) } else if let Some(expr) = &args.expr { - if !interpret(expr, None, &args, false) { + if !interpret( + io_handle, + expr, + None, + &args, + false, + AllowIncomplete::RequireComplete, + None, // TODO(aspen): Pass in --arg/--argstr here + None, + None, + ) + .unwrap() + .finalize() + { std::process::exit(1); } } else { - run_prompt(&args) + let mut repl = Repl::new(io_handle, &args); + repl.run() } } -fn run_file(mut path: PathBuf, args: &Args) { +fn run_file(io_handle: Rc<TvixStoreIO>, mut path: PathBuf, args: &Args) { if path.is_dir() { path.push("default.nix"); } @@ -262,76 +99,22 @@ fn run_file(mut path: PathBuf, args: &Args) { let success = if args.compile_only { lint(&contents, Some(path), args) } else { - interpret(&contents, Some(path), args, false) + interpret( + io_handle, + &contents, + Some(path), + args, + false, + AllowIncomplete::RequireComplete, + None, + None, + None, + ) + .unwrap() + .finalize() }; if !success { std::process::exit(1); } } - -fn println_result(result: &Value, raw: bool) { - if raw { - println!("{}", result.to_contextful_str().unwrap()) - } else { - println!("=> {} :: {}", result, result.type_of()) - } -} - -fn state_dir() -> Option<PathBuf> { - let mut path = dirs::data_dir(); - if let Some(p) = path.as_mut() { - p.push("tvix") - } - path -} - -fn run_prompt(args: &Args) { - let mut rl = Editor::<()>::new().expect("should be able to launch rustyline"); - - if args.compile_only { - eprintln!("warning: `--compile-only` has no effect on REPL usage!"); - } - - let history_path = match state_dir() { - // Attempt to set up these paths, but do not hard fail if it - // doesn't work. - Some(mut path) => { - let _ = std::fs::create_dir_all(&path); - path.push("history.txt"); - let _ = rl.load_history(&path); - Some(path) - } - - None => None, - }; - - loop { - let readline = rl.readline("tvix-repl> "); - match readline { - Ok(line) => { - if line.is_empty() { - continue; - } - - rl.add_history_entry(&line); - - if let Some(without_prefix) = line.strip_prefix(":d ") { - interpret(without_prefix, None, args, true); - } else { - interpret(&line, None, args, false); - } - } - Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => break, - - Err(err) => { - eprintln!("error: {}", err); - break; - } - } - } - - if let Some(path) = history_path { - rl.save_history(&path).unwrap(); - } -} diff --git a/tvix/cli/src/repl.rs b/tvix/cli/src/repl.rs new file mode 100644 index 000000000000..e4b499609829 --- /dev/null +++ b/tvix/cli/src/repl.rs @@ -0,0 +1,274 @@ +use std::path::PathBuf; +use std::rc::Rc; + +use rustc_hash::FxHashMap; +use rustyline::{error::ReadlineError, Editor}; +use smol_str::SmolStr; +use tvix_eval::{GlobalsMap, SourceCode, Value}; +use tvix_glue::tvix_store_io::TvixStoreIO; + +use crate::{ + assignment::Assignment, evaluate, interpret, AllowIncomplete, Args, IncompleteInput, + InterpretResult, +}; + +fn state_dir() -> Option<PathBuf> { + let mut path = dirs::data_dir(); + if let Some(p) = path.as_mut() { + p.push("tvix") + } + path +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) enum ReplCommand<'a> { + Expr(&'a str), + Assign(Assignment<'a>), + Explain(&'a str), + Print(&'a str), + Quit, + Help, +} + +impl<'a> ReplCommand<'a> { + const HELP: &'static str = " +Welcome to the Tvix REPL! + +The following commands are supported: + + <expr> Evaluate a Nix language expression and print the result, along with its inferred type + <x> = <expr> Bind the result of an expression to a variable + :d <expr> Evaluate a Nix language expression and print a detailed description of the result + :p <expr> Evaluate a Nix language expression and print the result recursively + :q Exit the REPL + :?, :h Display this help text +"; + + pub fn parse(input: &'a str) -> Self { + if input.starts_with(':') { + if let Some(without_prefix) = input.strip_prefix(":d ") { + return Self::Explain(without_prefix); + } else if let Some(without_prefix) = input.strip_prefix(":p ") { + return Self::Print(without_prefix); + } + + let input = input.trim_end(); + match input { + ":q" => return Self::Quit, + ":h" | ":?" => return Self::Help, + _ => {} + } + } + + if let Some(assignment) = Assignment::parse(input) { + return Self::Assign(assignment); + } + + Self::Expr(input) + } +} + +pub struct CommandResult { + output: String, + continue_: bool, +} + +impl CommandResult { + pub fn finalize(self) -> bool { + print!("{}", self.output); + self.continue_ + } + + pub fn output(&self) -> &str { + &self.output + } +} + +pub struct Repl<'a> { + /// In-progress multiline input, when the input so far doesn't parse as a complete expression + multiline_input: Option<String>, + rl: Editor<()>, + /// Local variables defined at the top-level in the repl + env: FxHashMap<SmolStr, Value>, + + io_handle: Rc<TvixStoreIO>, + args: &'a Args, + source_map: SourceCode, + globals: Option<Rc<GlobalsMap>>, +} + +impl<'a> Repl<'a> { + pub fn new(io_handle: Rc<TvixStoreIO>, args: &'a Args) -> Self { + let rl = Editor::<()>::new().expect("should be able to launch rustyline"); + Self { + multiline_input: None, + rl, + env: FxHashMap::default(), + io_handle, + args, + source_map: Default::default(), + globals: None, + } + } + + pub fn run(&mut self) { + if self.args.compile_only { + eprintln!("warning: `--compile-only` has no effect on REPL usage!"); + } + + let history_path = match state_dir() { + // Attempt to set up these paths, but do not hard fail if it + // doesn't work. + Some(mut path) => { + let _ = std::fs::create_dir_all(&path); + path.push("history.txt"); + let _ = self.rl.load_history(&path); + Some(path) + } + + None => None, + }; + + loop { + let prompt = if self.multiline_input.is_some() { + " > " + } else { + "tvix-repl> " + }; + + let readline = self.rl.readline(prompt); + match readline { + Ok(line) => { + if !self.send(line).finalize() { + break; + } + } + Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => break, + + Err(err) => { + eprintln!("error: {}", err); + break; + } + } + } + + if let Some(path) = history_path { + self.rl.save_history(&path).unwrap(); + } + } + + /// Send a line of user input to the REPL. Returns a result indicating the output to show to the + /// user, and whether or not to continue + pub fn send(&mut self, line: String) -> CommandResult { + if line.is_empty() { + return CommandResult { + output: String::new(), + continue_: true, + }; + } + + let input = if let Some(mi) = &mut self.multiline_input { + mi.push('\n'); + mi.push_str(&line); + mi + } else { + &line + }; + + let res = match ReplCommand::parse(input) { + ReplCommand::Quit => { + return CommandResult { + output: String::new(), + continue_: false, + }; + } + ReplCommand::Help => { + println!("{}", ReplCommand::HELP); + Ok(InterpretResult::empty_success(None)) + } + ReplCommand::Expr(input) => interpret( + Rc::clone(&self.io_handle), + input, + None, + self.args, + false, + AllowIncomplete::Allow, + Some(&self.env), + self.globals.clone(), + Some(self.source_map.clone()), + ), + ReplCommand::Assign(Assignment { ident, value }) => { + match evaluate( + Rc::clone(&self.io_handle), + &value.to_string(), /* FIXME: don't re-parse */ + None, + self.args, + AllowIncomplete::Allow, + Some(&self.env), + self.globals.clone(), + Some(self.source_map.clone()), + ) { + Ok(result) => { + if let Some(value) = result.value { + self.env.insert(ident.into(), value); + } + Ok(InterpretResult::empty_success(Some(result.globals))) + } + Err(incomplete) => Err(incomplete), + } + } + ReplCommand::Explain(input) => interpret( + Rc::clone(&self.io_handle), + input, + None, + self.args, + true, + AllowIncomplete::Allow, + Some(&self.env), + self.globals.clone(), + Some(self.source_map.clone()), + ), + ReplCommand::Print(input) => interpret( + Rc::clone(&self.io_handle), + input, + None, + &Args { + strict: true, + ..(self.args.clone()) + }, + false, + AllowIncomplete::Allow, + Some(&self.env), + self.globals.clone(), + Some(self.source_map.clone()), + ), + }; + + match res { + Ok(InterpretResult { + output, + globals, + success: _, + }) => { + self.rl.add_history_entry(input); + self.multiline_input = None; + if globals.is_some() { + self.globals = globals; + } + CommandResult { + output, + continue_: true, + } + } + Err(IncompleteInput) => { + if self.multiline_input.is_none() { + self.multiline_input = Some(line); + } + CommandResult { + output: String::new(), + continue_: true, + } + } + } + } +} diff --git a/tvix/eval/src/tests/tvix_tests/readDir/bar b/tvix/cli/tests/.skip-tree index e69de29bb2d1..e69de29bb2d1 100644 --- a/tvix/eval/src/tests/tvix_tests/readDir/bar +++ b/tvix/cli/tests/.skip-tree diff --git a/tvix/cli/tests/import.nix b/tvix/cli/tests/import.nix new file mode 100644 index 000000000000..d5d41d3917f3 --- /dev/null +++ b/tvix/cli/tests/import.nix @@ -0,0 +1 @@ +{}: import ./six.nix { } diff --git a/tvix/cli/tests/repl.rs b/tvix/cli/tests/repl.rs new file mode 100644 index 000000000000..7b9b9e34550a --- /dev/null +++ b/tvix/cli/tests/repl.rs @@ -0,0 +1,98 @@ +use std::ffi::OsString; + +use clap::Parser; +use expect_test::expect; +use tvix_cli::init_io_handle; + +macro_rules! test_repl { + ($name:ident() {$($send:expr => $expect:expr;)*}) => { + #[test] + fn $name() { + let tokio_runtime = tokio::runtime::Runtime::new().unwrap(); + let args = tvix_cli::Args::parse_from(vec![ + OsString::from("tvix"), + OsString::from("--nix-search-path"), + OsString::from("nixpkgs=/tmp"), + ]); + let mut repl = tvix_cli::Repl::new(init_io_handle(&tokio_runtime, &args), &args); + $({ + let result = repl.send($send.into()); + $expect.assert_eq(result.output()) + ; + })* + } + } +} + +test_repl!(simple_expr_eval() { + "1" => expect![[r#" + => 1 :: int + "#]]; +}); + +test_repl!(multiline_input() { + "{ x = 1; " => expect![[""]]; + "y = 2; }" => expect![[r#" + => { x = 1; y = 2; } :: set + "#]]; +}); + +test_repl!(bind_literal() { + "x = 1" => expect![[""]]; + "x" => expect![[r#" + => 1 :: int + "#]]; +}); + +test_repl!(bind_lazy() { + "x = { z = 1; }" => expect![[""]]; + "x" => expect![[r#" + => { z = 1; } :: set + "#]]; + "x.z" => expect![[r#" + => 1 :: int + "#]]; + "x.z" => expect![[r#" + => 1 :: int + "#]]; +}); + +test_repl!(bind_lazy_errors() { + r#"x = (_: "x" + 1)"# => expect![[""]]; + "x null" => expect![[""]]; +}); + +test_repl!(bind_referencing_import() { + "six = import ./tests/six.nix {}" => expect![[""]]; + "six.six" => expect![[r#" + => 6 :: int + "#]]; + "imported = import ./tests/import.nix" => expect![[""]]; + "(imported {}).six" => expect![[r#" + => 6 :: int + "#]]; +}); + +test_repl!(deep_print() { + "builtins.map (x: x + 1) [ 1 2 3 ]" => expect![[r#" + => [ <CODE> <CODE> <CODE> ] :: list + "#]]; + ":p builtins.map (x: x + 1) [ 1 2 3 ]" => expect![[r#" + => [ 2 3 4 ] :: list + "#]]; +}); + +test_repl!(explain() { + ":d { x = 1; y = [ 2 3 4 ]; }" => expect![[r#" + => a 2-item attribute set + "#]]; +}); + +test_repl!(reference_nix_path() { + "<nixpkgs>" => expect![[r#" + => /tmp :: path + "#]]; + "<nixpkgs>" => expect![[r#" + => /tmp :: path + "#]]; +}); diff --git a/tvix/cli/tests/six.nix b/tvix/cli/tests/six.nix new file mode 100644 index 000000000000..71ec46c407ba --- /dev/null +++ b/tvix/cli/tests/six.nix @@ -0,0 +1 @@ +{}: { six = builtins.foldl' (x: y: x + y) 0 [ 1 2 3 ]; } diff --git a/tvix/clippy.toml b/tvix/clippy.toml index be7709684c6f..31952cc80ad1 100644 --- a/tvix/clippy.toml +++ b/tvix/clippy.toml @@ -1,6 +1,8 @@ # prevents a false-positive lint on our types containing bytes::Bytes # https://rust-lang.github.io/rust-clippy/master/index.html#/mutable_key_type ignore-interior-mutability = [ + # make sure to specify the originating type name, not re-exports! "bytes::Bytes", - "tvix_castore::digests::B3Digest" + "tvix_castore::digests::B3Digest", + "tvix_castore::path::component::PathComponent" ] diff --git a/tvix/crate-hashes.json b/tvix/crate-hashes.json index ca45e4317698..42b46c2515d2 100644 --- a/tvix/crate-hashes.json +++ b/tvix/crate-hashes.json @@ -1,4 +1,4 @@ { - "bigtable_rs 0.2.9 (git+https://github.com/flokli/bigtable_rs?rev=0af404741dfc40eb9fa99cf4d4140a09c5c20df7#0af404741dfc40eb9fa99cf4d4140a09c5c20df7)": "1njjam1lx2xlnm7a41lga8601vmjgqz0fvc77x24gd04pc7avxll", - "wu-manber 0.1.0 (git+https://github.com/tvlfyi/wu-manber.git#0d5b22bea136659f7de60b102a7030e0daaa503d)": "1zhk83lbq99xzyjwphv2qrb8f8qgfqwa5bbbvyzm0z0bljsjv0pd" + "git+https://github.com/liufuyang/bigtable_rs?rev=1818355a5373a5bc2c84287e3a4e3807154ac8ef#0.2.10": "0mn6iw1z7gdxbarsqiwscbdr25nplwlvzs0rs51vgnnjfsnbgl6q", + "git+https://github.com/tvlfyi/wu-manber.git#wu-manber@0.1.0": "1zhk83lbq99xzyjwphv2qrb8f8qgfqwa5bbbvyzm0z0bljsjv0pd" } \ No newline at end of file diff --git a/tvix/default.nix b/tvix/default.nix index f562cf37de78..49b6a9e03e11 100644 --- a/tvix/default.nix +++ b/tvix/default.nix @@ -2,79 +2,9 @@ { pkgs, lib, depot, ... }: let - # crate override for crates that need protobuf - protobufDep = prev: (prev.nativeBuildInputs or [ ]) ++ [ pkgs.buildPackages.protobuf ]; - iconvDarwinDep = lib.optional pkgs.stdenv.isDarwin pkgs.libiconv; - - # On Darwin, some crates producing binaries need to be able to link against security. - darwinDeps = lib.optionals pkgs.stdenv.isDarwin (with pkgs.buildPackages.darwin.apple_sdk.frameworks; [ - Security - SystemConfiguration - ]); - # Load the crate2nix crate tree. - crates = import ./Cargo.nix { - inherit pkgs; - nixpkgs = pkgs.path; - - # Hack to fix Darwin build - # See https://github.com/NixOS/nixpkgs/issues/218712 - buildRustCrateForPkgs = pkgs: - if pkgs.stdenv.isDarwin then - let - buildRustCrate = pkgs.buildRustCrate; - buildRustCrate_ = args: buildRustCrate args // { dontStrip = true; }; - override = o: args: buildRustCrate.override o (args // { dontStrip = true; }); - in - pkgs.makeOverridable override { } - else pkgs.buildRustCrate; - - defaultCrateOverrides = pkgs.defaultCrateOverrides // { - zstd-sys = prev: { - nativeBuildInputs = prev.nativeBuildInputs or [ ]; - buildInputs = prev.buildInputs or [ ] ++ iconvDarwinDep; - }; - - opentelemetry-proto = prev: { - nativeBuildInputs = protobufDep prev; - }; - - prost-build = prev: { - nativeBuildInputs = protobufDep prev; - }; - - prost-wkt-types = prev: { - nativeBuildInputs = protobufDep prev; - }; - - tonic-reflection = prev: { - nativeBuildInputs = protobufDep prev; - }; - - tvix-build = prev: { - PROTO_ROOT = depot.tvix.build.protos.protos; - nativeBuildInputs = protobufDep prev; - buildInputs = darwinDeps; - }; - - tvix-castore = prev: { - PROTO_ROOT = depot.tvix.castore.protos.protos; - nativeBuildInputs = protobufDep prev; - }; - - tvix-cli = prev: { - buildInputs = prev.buildInputs or [ ] ++ darwinDeps; - }; - - tvix-store = prev: { - PROTO_ROOT = depot.tvix.store.protos.protos; - nativeBuildInputs = protobufDep prev; - # fuse-backend-rs uses DiskArbitration framework to handle mount/unmount on Darwin - buildInputs = prev.buildInputs or [ ] - ++ darwinDeps - ++ lib.optional pkgs.stdenv.isDarwin pkgs.buildPackages.darwin.apple_sdk.frameworks.DiskArbitration; - }; - }; + crates = pkgs.callPackage ./Cargo.nix { + defaultCrateOverrides = depot.tvix.utils.defaultCrateOverridesForPkgs pkgs; }; # Cargo dependencies to be used with nixpkgs rustPlatform functions. @@ -85,8 +15,8 @@ let # and the outputHash as value. outputHashes = builtins.listToAttrs (map - (crateName: - (lib.nameValuePair "${crateName}-${crates.internal.crates.${crateName}.version}" crates.internal.crates.${crateName}.src.outputHash) + (k: + (lib.nameValuePair "${crates.internal.crates.${k}.crateName}-${crates.internal.crates.${k}.version}" crates.internal.crates.${k}.src.outputHash) ) [ "bigtable_rs" "wu-manber" @@ -111,57 +41,6 @@ in { inherit crates protos; - # Run crate2nix generate, ensure the output doesn't differ afterwards - # (and doesn't fail). - # - # Currently this re-downloads every crate every time - # crate2nix-check (but not crate2nix) is built. - # TODO(amjoseph): be less wasteful with bandwidth. - # - crate2nix-check = - let - outputHashAlgo = "sha256"; - in - pkgs.stdenv.mkDerivation { - inherit src; - - # Important: we include the hash of the Cargo.lock file and - # Cargo.nix file in the derivation name. This forces the FOD - # to be rebuilt/reverified whenever either of them changes. - name = "tvix-crate2nix-check-" + - (builtins.substring 0 8 (builtins.hashFile "sha256" ./Cargo.lock)) + - "-" + - (builtins.substring 0 8 (builtins.hashFile "sha256" ./Cargo.nix)); - - nativeBuildInputs = with pkgs; [ git cacert cargo ]; - buildPhase = '' - export CARGO_HOME=$(mktemp -d) - - # The following command can be omitted, in which case - # crate2nix-generate will run it automatically, but won't show the - # output, which makes it look like the build is somehow "stuck" for a - # minute or two. - cargo metadata > /dev/null - - # running this command counteracts depotfmt brokenness - git init - - ${depot.tools.crate2nix-generate}/bin/crate2nix-generate - - # technically unnecessary, but provides more-helpful output in case of error - diff -ur Cargo.nix ${src}/Cargo.nix - - # the FOD hash will check that the (re-)generated Cargo.nix matches the committed Cargo.nix - cp Cargo.nix $out - ''; - - # This is an FOD in order to allow `cargo` to perform network access. - outputHashMode = "flat"; - inherit outputHashAlgo; - outputHash = builtins.hashFile outputHashAlgo ./Cargo.nix; - env.SSL_CERT_FILE = "${pkgs.cacert.out}/etc/ssl/certs/ca-bundle.crt"; - }; - # Provide the Tvix logo in both .webp and .png format. logo = pkgs.runCommand "logo" { @@ -186,6 +65,7 @@ in inherit cargoDeps src; name = "tvix-rust-docs"; PROTO_ROOT = protos; + TVIX_BUILD_SANDBOX_SHELL = "/homeless-shelter"; nativeBuildInputs = with pkgs; [ cargo @@ -197,7 +77,7 @@ in buildInputs = [ pkgs.fuse - ] ++ iconvDarwinDep; + ] ++ lib.optional pkgs.stdenv.isDarwin pkgs.libiconv; buildPhase = '' cargo doc --document-private-items @@ -211,6 +91,7 @@ in inherit cargoDeps src; name = "tvix-clippy"; PROTO_ROOT = protos; + TVIX_BUILD_SANDBOX_SHELL = "/homeless-shelter"; buildInputs = [ pkgs.fuse @@ -224,15 +105,25 @@ in rustPlatform.cargoSetupHook ]; - # Allow blocks_in_conditions due to false positives with #[tracing::instrument(…)]: - # https://github.com/rust-lang/rust-clippy/issues/12281 - buildPhase = "cargo clippy --tests --all-features --benches --examples -- -Dwarnings -A clippy::blocks_in_conditions | tee $out"; + buildPhase = "cargo clippy --tests --all-features --benches --examples -- -Dwarnings | tee $out"; }; + crate2nix-check = + let + crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; + in + crate2nix-check.command.overrideAttrs { + meta.ci.extraSteps = { + inherit crate2nix-check; + }; + }; + meta.ci.targets = [ "clippy" - "crate2nix-check" "shell" "rust-docs" + "crate2nix-check" ]; + + utils = import ./utils.nix { inherit pkgs lib depot; }; } diff --git a/tvix/docs/book.toml b/tvix/docs/book.toml index 7318a9023348..56bdd860cdde 100644 --- a/tvix/docs/book.toml +++ b/tvix/docs/book.toml @@ -9,3 +9,18 @@ title = "Tvix Docs" # override the /usr/bin/plantuml default plantuml-cmd = "plantuml" use-data-uris = true + +[preprocessor.admonish] +command = "mdbook-admonish" +after = ["links"] # ensure `{{#include}}` also gets processed +assets_version = "3.0.2" # do not edit: managed by `mdbook-admonish install` + +[preprocessor.d2] +command = "d2" +after = ["links"] # ensure `{{#include}}` also gets processed + +[output] + +[output.html] +additional-css = ["./mdbook-admonish.css", "./mdbook-extra.css"] +additional-js = ["./mdbook-extra.js"] diff --git a/tvix/docs/default.nix b/tvix/docs/default.nix index 9fc2f765767a..3b102e4b7ce2 100644 --- a/tvix/docs/default.nix +++ b/tvix/docs/default.nix @@ -9,7 +9,10 @@ pkgs.stdenv.mkDerivation { src = lib.cleanSource ./.; nativeBuildInputs = [ + pkgs.d2 pkgs.mdbook + pkgs.mdbook-admonish + pkgs.mdbook-d2 pkgs.mdbook-plantuml pkgs.plantuml ]; diff --git a/tvix/docs/mdbook-admonish.css b/tvix/docs/mdbook-admonish.css new file mode 100644 index 000000000000..45aeff051115 --- /dev/null +++ b/tvix/docs/mdbook-admonish.css @@ -0,0 +1,348 @@ +@charset "UTF-8"; +:is(.admonition) { + display: flow-root; + margin: 1.5625em 0; + padding: 0 1.2rem; + color: var(--fg); + page-break-inside: avoid; + background-color: var(--bg); + border: 0 solid black; + border-inline-start-width: 0.4rem; + border-radius: 0.2rem; + box-shadow: 0 0.2rem 1rem rgba(0, 0, 0, 0.05), 0 0 0.1rem rgba(0, 0, 0, 0.1); +} +@media print { + :is(.admonition) { + box-shadow: none; + } +} +:is(.admonition) > * { + box-sizing: border-box; +} +:is(.admonition) :is(.admonition) { + margin-top: 1em; + margin-bottom: 1em; +} +:is(.admonition) > .tabbed-set:only-child { + margin-top: 0; +} +html :is(.admonition) > :last-child { + margin-bottom: 1.2rem; +} + +a.admonition-anchor-link { + display: none; + position: absolute; + left: -1.2rem; + padding-right: 1rem; +} +a.admonition-anchor-link:link, a.admonition-anchor-link:visited { + color: var(--fg); +} +a.admonition-anchor-link:link:hover, a.admonition-anchor-link:visited:hover { + text-decoration: none; +} +a.admonition-anchor-link::before { + content: "§"; +} + +:is(.admonition-title, summary.admonition-title) { + position: relative; + min-height: 4rem; + margin-block: 0; + margin-inline: -1.6rem -1.2rem; + padding-block: 0.8rem; + padding-inline: 4.4rem 1.2rem; + font-weight: 700; + background-color: rgba(68, 138, 255, 0.1); + print-color-adjust: exact; + -webkit-print-color-adjust: exact; + display: flex; +} +:is(.admonition-title, summary.admonition-title) p { + margin: 0; +} +html :is(.admonition-title, summary.admonition-title):last-child { + margin-bottom: 0; +} +:is(.admonition-title, summary.admonition-title)::before { + position: absolute; + top: 0.625em; + inset-inline-start: 1.6rem; + width: 2rem; + height: 2rem; + background-color: #448aff; + print-color-adjust: exact; + -webkit-print-color-adjust: exact; + mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"></svg>'); + -webkit-mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"></svg>'); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-size: contain; + content: ""; +} +:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link { + display: initial; +} + +details.admonition > summary.admonition-title::after { + position: absolute; + top: 0.625em; + inset-inline-end: 1.6rem; + height: 2rem; + width: 2rem; + background-color: currentcolor; + mask-image: var(--md-details-icon); + -webkit-mask-image: var(--md-details-icon); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-size: contain; + content: ""; + transform: rotate(0deg); + transition: transform 0.25s; +} +details[open].admonition > summary.admonition-title::after { + transform: rotate(90deg); +} + +:root { + --md-details-icon: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42Z'/></svg>"); +} + +:root { + --md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z'/></svg>"); + --md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z'/></svg>"); + --md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z'/></svg>"); + --md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.58.58 0 0 1-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27z'/></svg>"); + --md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m9 20.42-6.21-6.21 2.83-2.83L9 14.77l9.88-9.89 2.83 2.83L9 20.42z'/></svg>"); + --md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m15.07 11.25-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 0 0-2-2 2 2 0 0 0-2 2H8a4 4 0 0 1 4-4 4 4 0 0 1 4 4 3.2 3.2 0 0 1-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10c0-5.53-4.5-10-10-10z'/></svg>"); + --md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 14h-2V9h2m0 9h-2v-2h2M1 21h22L12 2 1 21z'/></svg>"); + --md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6.91 17.09 4 12 9.09 6.91 4 4 6.91 9.09 12 4 17.09 6.91 20 12 14.91 17.09 20 20 17.09 14.91 12 20 6.91z'/></svg>"); + --md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 15H6l7-14v8h5l-7 14v-8z'/></svg>"); + --md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 0 0-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z'/></svg>"); + --md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 0 1 .75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z'/></svg>"); + --md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z'/></svg>"); +} + +:is(.admonition):is(.admonish-note) { + border-color: #448aff; +} + +:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(68, 138, 255, 0.1); +} +:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #448aff; + mask-image: var(--md-admonition-icon--admonish-note); + -webkit-mask-image: var(--md-admonition-icon--admonish-note); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) { + border-color: #00b0ff; +} + +:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(0, 176, 255, 0.1); +} +:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #00b0ff; + mask-image: var(--md-admonition-icon--admonish-abstract); + -webkit-mask-image: var(--md-admonition-icon--admonish-abstract); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +:is(.admonition):is(.admonish-info, .admonish-todo) { + border-color: #00b8d4; +} + +:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(0, 184, 212, 0.1); +} +:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #00b8d4; + mask-image: var(--md-admonition-icon--admonish-info); + -webkit-mask-image: var(--md-admonition-icon--admonish-info); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) { + border-color: #00bfa5; +} + +:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(0, 191, 165, 0.1); +} +:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #00bfa5; + mask-image: var(--md-admonition-icon--admonish-tip); + -webkit-mask-image: var(--md-admonition-icon--admonish-tip); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) { + border-color: #00c853; +} + +:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(0, 200, 83, 0.1); +} +:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #00c853; + mask-image: var(--md-admonition-icon--admonish-success); + -webkit-mask-image: var(--md-admonition-icon--admonish-success); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) { + border-color: #64dd17; +} + +:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(100, 221, 23, 0.1); +} +:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #64dd17; + mask-image: var(--md-admonition-icon--admonish-question); + -webkit-mask-image: var(--md-admonition-icon--admonish-question); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) { + border-color: #ff9100; +} + +:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(255, 145, 0, 0.1); +} +:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #ff9100; + mask-image: var(--md-admonition-icon--admonish-warning); + -webkit-mask-image: var(--md-admonition-icon--admonish-warning); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) { + border-color: #ff5252; +} + +:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(255, 82, 82, 0.1); +} +:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #ff5252; + mask-image: var(--md-admonition-icon--admonish-failure); + -webkit-mask-image: var(--md-admonition-icon--admonish-failure); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +:is(.admonition):is(.admonish-danger, .admonish-error) { + border-color: #ff1744; +} + +:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(255, 23, 68, 0.1); +} +:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #ff1744; + mask-image: var(--md-admonition-icon--admonish-danger); + -webkit-mask-image: var(--md-admonition-icon--admonish-danger); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +:is(.admonition):is(.admonish-bug) { + border-color: #f50057; +} + +:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(245, 0, 87, 0.1); +} +:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #f50057; + mask-image: var(--md-admonition-icon--admonish-bug); + -webkit-mask-image: var(--md-admonition-icon--admonish-bug); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +:is(.admonition):is(.admonish-example) { + border-color: #7c4dff; +} + +:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(124, 77, 255, 0.1); +} +:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #7c4dff; + mask-image: var(--md-admonition-icon--admonish-example); + -webkit-mask-image: var(--md-admonition-icon--admonish-example); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +:is(.admonition):is(.admonish-quote, .admonish-cite) { + border-color: #9e9e9e; +} + +:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) { + background-color: rgba(158, 158, 158, 0.1); +} +:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before { + background-color: #9e9e9e; + mask-image: var(--md-admonition-icon--admonish-quote); + -webkit-mask-image: var(--md-admonition-icon--admonish-quote); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + mask-size: contain; + -webkit-mask-repeat: no-repeat; +} + +.navy :is(.admonition) { + background-color: var(--sidebar-bg); +} + +.ayu :is(.admonition), +.coal :is(.admonition) { + background-color: var(--theme-hover); +} + +.rust :is(.admonition) { + background-color: var(--sidebar-bg); + color: var(--sidebar-fg); +} +.rust .admonition-anchor-link:link, .rust .admonition-anchor-link:visited { + color: var(--sidebar-fg); +} diff --git a/tvix/docs/mdbook-extra.css b/tvix/docs/mdbook-extra.css new file mode 100644 index 000000000000..7a50fdbeed68 --- /dev/null +++ b/tvix/docs/mdbook-extra.css @@ -0,0 +1,7 @@ +@charset "utf-8"; + +.hljs-meta.prompt_ { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} diff --git a/tvix/docs/mdbook-extra.js b/tvix/docs/mdbook-extra.js new file mode 100644 index 000000000000..bff412e69eb2 --- /dev/null +++ b/tvix/docs/mdbook-extra.js @@ -0,0 +1,24 @@ +"use strict" + +function main() { + document.removeEventListener("DOMContentLoaded", main, false) + + // NOTE: this is a hacky solution but should do the job for making a + // listenable audio link + function playAudio(evt) { + evt.preventDefault() + var audio = document.createElement("audio") + audio.addEventListener("ended", function() { audio.delete() }, false) + audio.addEventListener("loadeddata", function() { audio.play() }, false) + audio.src = evt.target.href + audio.load() + } + + var audios = document.querySelectorAll("a[href^=\"data:audio/\"]") + Array.prototype.forEach.call(audios, function setupAudio(elem) { + elem.setAttribute("role", "button") + elem.addEventListener("click", playAudio, false) + }) +} + +document.addEventListener("DOMContentLoaded", main, false) diff --git a/tvix/docs/src/SUMMARY.md b/tvix/docs/src/SUMMARY.md index b0e47a001108..cce6d8966df6 100644 --- a/tvix/docs/src/SUMMARY.md +++ b/tvix/docs/src/SUMMARY.md @@ -1,10 +1,49 @@ # Summary +# Welcome +* [Introduction](./introduction.md) +* [Community](./community.md) +* [Getting Started](./getting-started.md) + +# Contributing +* [Gerrit](./contributing/gerrit.md) +* [Email](./contributing/email.md) +* [Code & Commits](./contributing/code-&-commits.md) + # Tvix - [Architecture & data flow](./architecture.md) - [TODOs](./TODO.md) +# Evaluator +- [Compilation of Bindings](./eval/bindings.md) +- [Builtins](./eval/builtins.md) +- [Build References](./eval/build-references.md) +- [Catchable Errors](./eval/catchable-errors.md) +- [Known Optimisation Potential](./eval/known-optimisation-potential.md) +- [Langugage Issues](./eval/language-issues.md) +- [Attrset Opcodes](./eval/opcodes-attrsets.md) +- [Recursive attribute sets](./eval/recursive-attrs.md) +- [VM Loop](./eval/vm-loop.md) +- [Abandoned](./eval/abandoned/index.md) + - [Thread-local VM](./eval/abandoned/thread-local-vm.md) + +# Store +- [Store API](./store/api.md) +- [BlobStore Chunking](./castore/blobstore-chunking.md) +- [BlobStore Protocol](./castore/blobstore-protocol.md) +- [Data Model](./castore/data-model.md) +- [Why not git trees?](./castore/why-not-git-trees.md) + +# Builder +- [Build API](./build/index.md) + # Nix - [Specification of the Nix Language](./language-spec.md) - [Nix language version history](./lang-version.md) - [Value Pointer Equality](./value-pointer-equality.md) +- [Daemon Protocol](./nix-daemon/index.md) + - [Handshake](./nix-daemon/handshake.md) + - [Logging](./nix-daemon/logging.md) + - [Operations](./nix-daemon/operations.md) + - [Serialization](./nix-daemon/serialization.md) + - [Changelog](./nix-daemon/changelog.md) diff --git a/tvix/docs/src/TODO.md b/tvix/docs/src/TODO.md index 6644bb6bac03..4db77b04d442 100644 --- a/tvix/docs/src/TODO.md +++ b/tvix/docs/src/TODO.md @@ -10,16 +10,95 @@ Feel free to add new ideas. Before picking something, ask in `#tvix-dev` to make sure noone is working on this, or has some specific design in mind already. ## Cleanups +### Nix language test suite + - Think about how to merge, but "categorize" `tvix_tests` in `glue` and `eval`. + We currently only have this split as they need a different feature set / + builtins. - move some of the rstest cases in `tvix-glue` to the `.nix`/`.exp` mechanism. - - Parts requiring test fixtures need some special convention. - Some of these also cannot be checked into the repo, like the import tests - adding special files to test filtering. - - add `nix_oracle` mechanism from `tvix-eval` to `tvix-glue`. + Some of them need test fixtures, which cannot be represented in git (special + file types in the import tests for example). Needs some support from the test + suite to create these fixtures on demand. + - extend `verify-lang-tests/default.nix` mechanism to validate `tvix-eval` and + `tvix-glue` test cases (or the common structure above). + - absorb `eval/tests/nix_oracle.rs` into `tvix_tests`, or figure out why it's + not possible (and document) it. It looks like it's only as nix is invoked + with a different level of `--strict`, but the toplevel doc-comment suggests + its generic? + +### Correctness > Performance +A lot of the Nix behaviour isn't well documented out, and before going too deep +into performance optimizations, we need to ensure we properly grasped all hidden +features. This is to avoid doing a lot of "overall architecture perf-related +work" and increased code complexity based on a mental model that might get +disproved later on, as we work towards correctness. + +We do this by evaluating more and more parts of the official Nix test suite, as +well as our own Tvix test suite, and compare it with Nix' output. + +Additionally, we evaluate attributes from nixpkgs, compare calculated output +paths (to determine equivalence of evaluated A-Terms) and fix differences as we +encounter them. + +This currently is a very manual and time-consuming process, both in terms of +setup, as well as spotting the source of the differences (and "compensating" for +the resulting diff noise on resulting mismtaches). + + - We could use some better tooling that periodically evaluates nixpkgs, and + compares the output paths with the ones produced by Nix + - We could use some better tooling that can spot the (real) differences between + two (graphs of) derivations, while removing all resulting noise from the diff +in resulting store paths. + + +### Performance +Even while keeping in mind some of the above caveats, there's some obvious +low-langing fruits that could have a good impact on performance, with somewhat +limited risk of becoming obsolete in case of behaviorial changes due to +correctness: + + - String Contexts currently do a lot of indirections (edef) + (NixString -> NixStringInner -> HashSet[element] -> NixContextElement -> String -> data) + to get to the actual data. We should improve this. There's various ideas, one + of it is globally interning all Nix context elements, and only keeping + indices into that. We might need to have different representations for small + amount of context elements or larger ones, and need tooling to reason about + the amount of contexts we have. + - To calculate NAR size and digest (used for output path calculation of FODs), + our current `SimpleRenderer` `NarCalculationService` sequentially asks for + one blob after another (and internally these might consists out of multiple + chunks too). + That's a lot of roundtrips, adding up to a lot of useless waiting. + While we cannot avoid having to feed all bytes sequentially through sha256, + we already know what blobs to fetch and in which order. + There should be a way to buffer some "amount of upcoming bytes" in memory, + and not requesting these seqentially. + This is somewhat the "spiritual counterpart" to our sequential ingestion + code (`ConcurrentBlobUploader`, used by `ingest_nar`), which keeps + "some amount of outgoing bytes" in memory. + Our seekable NAR AsyncRead implementation already removes most complexity in + rendering everything between blobs. + It should be possible to extend / write a wrapped version of it that + prefetches a configurable sliding window of blobs. + Per-blob prefetching itself is somewhat blocked until the {Chunk/Blob}Service + split is done, as then prefetching there would only be a matter of adding it + into the one `BlobReader`. + +### Error cleanup + - Currently, all services use tvix_castore::Error, which only has two kinds + (invalid request, storage error), containing an (owned) string. + This is quite primitive. We should have individual error types for BS, DS, PS. + Maybe these should have some generics to still be able to carry errors from + the underlying backend, similar to `IngestionError`. + There was an attempt to give PS separate error types (cl/11695), but this + ended up very verbose. + Every error had to be boxed, and a possible additional message be added. Some + errors that didn't wrap another underlying errors were hard to construct, too + (requiring the addition of errors). All of this without even having added + proper backtrace support, which would be quite helpful in store hierarchies. + `anyhow`'s `.context()` gives us most of this out of the box. Maybe we can + use that, using enums rather than `&'static str` as context in some cases? ## Fixes towards correctness - - `builtins.toXML` is missing string context. See b/398. - - `builtins.toXML` self-closing tags need to be configurable in a more granular - fashion, requires third-party crate support. See b/399. - `rnix` only supports string source files, but `NixString` uses bytes (and Nix source code might be no valid UTF-8). @@ -47,22 +126,12 @@ Extend the other pages in here. Some ideas on what should be tackled: ## Features -### CLI - - `nix repl` can set variables and effectively mutates a global scope. We - should update the existing / add another repl that allows the same. We don't - want to mutate the evaluator, but should construct a new one, passing in the - root scope returned from the previous evaluation. - ### Fetchers Some more fetcher-related builtins need work: - `fetchGit` - `fetchTree` (hairy, seems there's no proper spec and the URL syntax seems subject to change/underdocumented) -### Convert builtins:fetchurl to Fetches -We need to convert `builtins:fetchurl`-style calls to `builtins.derivation` to -fetches, not Derivations (tracked in `KnownPaths`). - ### Derivation -> Build While we have some support for `structuredAttrs` and `fetchClosure` (at least enough to calculate output hashes, aka produce identical ATerm), the code @@ -80,14 +149,51 @@ there are ruled out, adding other types of builders might be interesting. - gVisor - Cloud Hypervisor (using similar technique as `//tvix//boot`). -Long-term, we want to extend traits and gRPC protocol to expose more telemetry, -logs etc, but this is something requiring a lot of designing. +Long-term, we want to extend traits and gRPC protocol. +This requires some more designing. Some goals: + + - (more granular) control while a build is happening + - expose more telemetry and logs + + - Add pre-flight checks in the OCI builder: + - ensure `fusermount` suid binary exists + - ensure `allow_other` is set + - ensure `runc` exists in `$PATH` + ### Store composition - Combinators: list-by-priority, first-come-first-serve, cache - - How do describe hierarchies. URL format too one-dimensional, but we might get - quite far with a similar "substituters" concept that Nix uses, to construct - the composed stores. + - Store composition hierarchies (@yuka). + - URL format too one-dimensional. + - We want to have nice and simple user-facing substituter config, including + sensible default wrappers for caching, retries, fallbacks, as well as + granular control for power-users. + - Current design idea: + - Have a concept similar to rclone config (map with store aliases as + keys, allowing to refer to stores by their alias from other parts of + the config). + It allows both referring to by name, as well as ad-hoc definition: + https://rclone.org/docs/#syntax-of-remote-paths + - Each store needs to be aware of its "instance name", so it can be + included in logs, metrics, … + - Have a "instantiation function" traversing such a config data structure, + creating store instances and plugging them together, ultimately returning + a dyn …Service interface. + - No reconfiguration/reconcilation for now + - Making URLs the primary data format would get ugly quite easily (hello + multiple layers of escaping!), so best to convert the existing URL + syntax to our new config format on the fly and then use one codepath + to instantiate/assemble. Similarly, something like the "user-facing + substituter config" mentioned above could aalso be converted to such a + config format under the hood. + - Maybe add a ?cache=$other_url parameter support to the URL syntax, to + easily wrap a store with a caching frontend, using $other_url as the + "near" store URL. + - Each store should get its instance name passed down, and add this as a + field in the instrumentation calls. This causes log messages and + per-instance store metrics to be traceable back to the specific instance + (if multiple backends of the same type are present). + ### Store Config There's already serde for some store options (bigtable uses `serde_qs`). We might also have common options global over all backends, like chunking @@ -98,32 +204,33 @@ logs etc, but this is something requiring a lot of designing. ### BlobService - On the trait side, currently there's no way to distinguish reading a known-chunk vs blob, so we might be calling `.chunks()` unnecessarily often. - At least for the `object_store` backend, this might be a problem. + At least for the `object_store` backend, this might be a problem, causing a + lot of round-trips. It also doesn't compose well - every implementation of + `BlobService` needs to both solve the "holding metadata about chunking info" + as well as "storing chunks" questions. + Design idea (@flokli): split these two concerns into two separate traits: + - a `ChunkService` dealing with retrieving individual chunks, by their + content digests. Chunks are small enough to keep around in contiguous + memory. + - a `BlobService` storing metadata about blobs. + + Individual stores would not need to implement `BlobReader` anymore, but that + could be a global thing with access to the whole store composition layer, + which should make it easier to reuse chunks from other backends. Unclear + if the write path should be structured the same way. At least for some + backends, we want the remote end to be able to decide about chunking. + - While `object_store` recently got support for `Content-Type` (https://github.com/apache/arrow-rs/pull/5650), there's no support on the local filesystem yet. We'd need to add support to this (through xattrs). -### DirectoryService - - Add an `object_store` variant, storing a Directory *closure* keyed by the - root `Directory` digest. This won't allow indexing intermediate Directory - nodes, but once we have `DirectoryService` composition, it shouldn't be an - issue. - - [redb](https://www.redb.org/) backend - ### PathInfoService - - [redb](https://www.redb.org/) backend - sqlite backend (different schema than the Nix one, we need the root nodes data!) -### Nix-compat -- Async NAR reader (@edef?) - ### Nix Daemon protocol -- Some work ongoing on the worker operation parsing. Partially blocked on the async NAR reader. +- Some work ongoing on the worker operation parsing (griff, picnoir) ### O11Y - - gRPC trace propagation (cl/10532) - - `tracing-tracy` (cl/10952) - - `[tracing-]indicatif` for progress/log reporting (floklis stash) - - unification into `tvix-tracing` crate, currently a lot of boilerplate - in `tvix-store` CLI entrypoint, and half of the boilerplate copied over to - `tvix-cli`. + - Trace propagation for object_store once they support a way to register a + middleware, so we can use that to register a tracing middleware. + https://github.com/apache/arrow-rs/issues/5990 diff --git a/tvix/docs/src/architecture.md b/tvix/docs/src/architecture.md index 5e0aa95f1a08..02ffdfdcd2b0 100644 --- a/tvix/docs/src/architecture.md +++ b/tvix/docs/src/architecture.md @@ -21,6 +21,15 @@ gRPC. The rest of this document outlines the components. ### Coordinator +```admonish warning +Currently there's no separate coordinator. Most of the interaction between +store, builder and evaluator is done by library code living in the `tvix-glue` +crate (and `tvix-cli` is a user of it). + +Keep in mind some of the statements below are outdated and neither reflect +reality nor desired design anymore. +``` + *Purpose:* The coordinator (in the simplest case, the Tvix CLI tool) oversees the flow of a build process and delegates tasks to the right subcomponents. For example, if a user runs the equivalent of diff --git a/tvix/docs/src/build/index.md b/tvix/docs/src/build/index.md new file mode 100644 index 000000000000..cf9580c98a82 --- /dev/null +++ b/tvix/docs/src/build/index.md @@ -0,0 +1,59 @@ +# Builder Protocol + +The builder protocol is used by tvix-glue to trigger builds. + +One goal of the protocol is to not be too tied to the Nix implementation itself, +allowing it to be used for other builds/workloads in the future. + +This means the builder protocol is versatile enough to express the environment a +Nix build expects, while not being aware of "what any of this means". + +For example, it is not aware of how certain environment variables are set in a +nix build, but allows specifying environent variables that should be set. + +It's also not aware of what nix store paths are. Instead, it allows: + + - specifying a list of paths expected to be produced during the build + - specifying a list of castore root nodes to be present in a specified + `inputs_dir`. + - specifying which paths are write-able during build. + +In case all specified paths are produced, and the command specified in +`command_args` succeeds, the build is considered to be successful. + +This happens to be sufficient to *also* express how Nix builds works. + +Check `build/protos/build.proto` for a detailed description of the individual +fields, and the tests in `glue/src/tvix_build.rs` for some examples. + +The following sections describe some aspects of Nix builds, and how this is +(planned to be) implemented with the Tvix Build protocol. + +## Reference scanning +At the end of a build, Nix does scan a store path for references to other store +paths (*out of the set of all store paths present during the build*). +It does do this by (only) looking for a list of nixbase32-encoded hashes in +filenames (?), symlink targets and blob contents. + +While we could do this entirely outside the builder protocol, it'd mean a build +client would be required to download the produced outputs locally, and do the +refscan there. This is undesireable, as the builder already has all produced +outputs locally, and it'd make more sense for it do do it. + +Instead, we want to describe reference scanning in a generic fashion. + +One proposed way to do this is to add an additional field `refscan_needles` to +the `BuildRequest` message. +If this is an non-empty list, all paths in `outputs` are scanned for these. + +The `Build` response message would then be extended with an `outputs_needles` +field, containing the same number of elements as the existing `outputs` field. +In there, we'd have a list of numbers, indexing into `refscan_needles` +originally specified. + +For Nix, `refscan_needles` would be populated with the nixbase32 hash parts of +every input store path and output store path. The latter is necessary to scan +for references between multi-output derivations. + +This is sufficient to construct the referred store paths in each build output on +the build client. diff --git a/tvix/castore/docs/blobstore-chunking.md b/tvix/docs/src/castore/blobstore-chunking.md index 49bbe6927554..d8c3d54b52f0 100644 --- a/tvix/castore/docs/blobstore-chunking.md +++ b/tvix/docs/src/castore/blobstore-chunking.md @@ -73,11 +73,11 @@ This means one only needs to the root digest to validate a constructions, and th constructions can be sent [separately][bao-spec]. This relieves us from the need of having to encode more granular chunking into -our data model / identifier upfront, but can make this a mostly a transport/ +our data model / identifier upfront, but can make this mostly a transport/ storage concern. -For the some more description on the (remote) protocol, check -`./blobstore-protocol.md`. +For some more description on the (remote) protocol, check +[BlobStore Protocol](./blobstore-protocol.md). #### Logical vs. physical chunking diff --git a/tvix/castore/docs/blobstore-protocol.md b/tvix/docs/src/castore/blobstore-protocol.md index 048cafc3d877..0dff787ccb00 100644 --- a/tvix/castore/docs/blobstore-protocol.md +++ b/tvix/docs/src/castore/blobstore-protocol.md @@ -41,7 +41,7 @@ It also puts very little requirements on someone implementing a new The gRPC protocol is documented in `../protos/rpc_blobstore.proto`. Contrary to the `BlobService` trait, it does not have any options for seeking/ ranging, as it's more desirable to provide this through chunking (see also -`./blobstore-chunking.md`). +[BlobStore Chunking](./blobstore-chunking.md). ## Composition Different `BlobStore` are supposed to be "composed"/"layered" to express @@ -76,7 +76,7 @@ an additional additional field in the response, which would allow clients to populate their local chunk store in a single roundtrip. ## Verified Streaming -As already described in `./docs/blobstore-chunking.md`, the physical chunk +As already described in [BlobStore Chunking](./blobstore-chunking.md), the physical chunk information sent in a `BlobService.Stat()` response is still sufficient to fetch in an authenticated fashion. diff --git a/tvix/castore/docs/data-model.md b/tvix/docs/src/castore/data-model.md index 2df6761aae8f..7f7e396a2267 100644 --- a/tvix/castore/docs/data-model.md +++ b/tvix/docs/src/castore/data-model.md @@ -2,7 +2,7 @@ This provides some more notes on the fields used in castore.proto. -See `//tvix/store/docs/api.md` for the full context. +See [Store API](../store/api.md) for the full context. ## Directory message `Directory` messages use the blake3 hash of their canonical protobuf @@ -15,8 +15,8 @@ a directory. All three message types have a `name` field, specifying the (base)name of the element (which MUST not contain slashes or null bytes, and MUST not be '.' or '..'). -For reproducibility reasons, the lists MUST be sorted by that name and also -MUST be unique across all three lists. +For reproducibility reasons, the lists MUST be sorted by that name and the +name MUST be unique across all three lists. In addition to the `name` field, the various *Node messages have the following fields: @@ -27,7 +27,7 @@ A `DirectoryNode` message represents a child directory. It has a `digest` field, which points to the identifier of another `Directory` message, making a `Directory` a merkle tree (or strictly speaking, a graph, as two elements pointing to a child directory with the same contents would point -to the same `Directory` message. +to the same `Directory` message). There's also a `size` field, containing the (total) number of all child elements in the referenced `Directory`, which helps for inode calculation. diff --git a/tvix/castore/docs/why-not-git-trees.md b/tvix/docs/src/castore/why-not-git-trees.md index fd46252cf55c..4a12b4ef5554 100644 --- a/tvix/castore/docs/why-not-git-trees.md +++ b/tvix/docs/src/castore/why-not-git-trees.md @@ -48,7 +48,7 @@ The git tree object format uses sha1 both for references to other trees and hashes of blobs, which isn't really a hash function to fundamentally base everything on in 2023. The [migration to sha256][git-sha256] also has been dead for some years now, -and it's unclear how a "blake3" version of this would even look like. +and it's unclear what a "blake3" version of this would even look like. [bao]: https://github.com/oconnor663/bao [blake3]: https://github.com/BLAKE3-team/BLAKE3 diff --git a/tvix/docs/src/community.md b/tvix/docs/src/community.md new file mode 100644 index 000000000000..9ab117c552f3 --- /dev/null +++ b/tvix/docs/src/community.md @@ -0,0 +1,23 @@ +# Community + +## Chatroom + +Tvix development discussions happen on IRC. We use the [hackint][] IRC network +where you should be able to join using your favorite client/protocol. + +* [IRC][] / [Webchat][] +* [Matrix][] +* [XMPP][] + +## Mailing list + +Discussions on larger architectural problems and thoughts occasionally happen +on the [TVL Public Inbox][public inbox] mailing list. + +[hackint]: https://hackint.org/ +[IRC]: ircs://irc.hackint.org:6697/#tvix-dev +[Webchat]: https://webirc.hackint.org/#ircs://irc.hackint.org/#tvix-dev +[Matrix]: matrix:r/tvix-dev:hackint.org?action=join +[XMPP]: xmpp:#tvix-dev@irc.hackint.org?join +[depot@tvl.su]: mailto:depot@tvl.su +[public inbox]: https://inbox.tvl.su/depot/ diff --git a/tvix/docs/src/contributing/code-&-commits.md b/tvix/docs/src/contributing/code-&-commits.md new file mode 100644 index 000000000000..628c124bf12f --- /dev/null +++ b/tvix/docs/src/contributing/code-&-commits.md @@ -0,0 +1,76 @@ +# Code & Commits + +## Code quality + +This one should go without saying — but please ensure that your code quality +does not fall below the rest of the project. This is of course very subjective, +but as an example if you place code that throws away errors into a block in +which errors are handled properly your change will be rejected. + + +```admonish hint +Usually there is a strong correlation between the visual appearance of a code +block and its quality. This is a simple way to sanity-check your work while +squinting and keeping some distance from your screen ;-) +``` + + +## Commit messages + +The [Angular Conventional Commits][angular] style is the general commit style +used in the Tvix project. Commit messages should be structured like this: + +```admonish example + type(scope): Subject line with at most a 72 character length + + Body of the commit message with an empty line between subject and + body. This text should explain what the change does and why it has + been made, *especially* if it introduces a new feature. + + Relevant issues should be mentioned if they exist. +``` + +Where `type` can be one of: + +* `feat`: A new feature has been introduced +* `fix`: An issue of some kind has been fixed +* `docs`: Documentation or comments have been updated +* `style`: Formatting changes only +* `refactor`: Hopefully self-explanatory! +* `test`: Added missing tests / fixed tests +* `chore`: Maintenance work +* `subtree`: Operations involving `git subtree` + +And `scope` should refer to some kind of logical grouping inside of the +project. + +It does not make sense to include the full path unless it aids in +disambiguating. For example, when changing the struct fields in +`tvix/glue/src/builtins/fetchers.rs` it is enough to write +`refactor(tvix/glue): …`. + +Please take a look at the existing commit log for examples. + + +## Commit content + +Multiple changes should be divided into multiple git commits whenever possible. +Common sense applies. + +The fix for a single-line whitespace issue is fine to include in a different +commit. Introducing a new feature and refactoring (unrelated) code in the same +commit is not fine. + +`git commit -a` is generally **taboo**, whereas on the command line you should +be preferring `git commit -p`. + + +```admonish tip +Tooling can really help this process. The [lazygit][] TUI or [magit][] for +Emacs are worth looking into. +``` + + +[angular]: https://www.conventionalcommits.org/en/ +[lazygit]: https://github.com/jesseduffield/lazygit +[magit]: https://magit.vc diff --git a/tvix/docs/src/contributing/email.md b/tvix/docs/src/contributing/email.md new file mode 100644 index 000000000000..238ff388f595 --- /dev/null +++ b/tvix/docs/src/contributing/email.md @@ -0,0 +1,33 @@ +# Submitting changes via email + +With SSO & local accounts, hopefully Tvix provides you a low-friction or +privacy-respecting way to make contributions by means of +[TVL’s self-hosted Gerrit][gerrit]. However, if you still decide differently, +you may submit a patch via email to `depot@tvl.su` where it will be added to +Gerrit by a contributor. + +Please keep in mind this process is more complicated requiring extra work from +both us & you: + +* You will need to manually check the Gerrit website for updates & someone will + need to relay potential comments to/from Gerrit to you as you won’t get + emails from Gerrit. +* New revisions need to be stewarded by someone uploading changes to Gerrit + on your behalf. +* As CLs cannot change owners, if you decide to get a Gerrit account later on + existing CLs need to be abandoned then recreated. This introduces more churn + to the review process since prior discussion are disconnected. + +Create an appropriate commit locally then send it us using either of these +options: + +* `git format-patch`: This will create a `*.patch` file which you should email to + us. +* `git send-email`: If configured on your system, this will take care of the + whole emailing process for you. + +The email address is a [public inbox][]. + + +[gerrit]: ../contributing/gerrit.html +[public inbox]: https://inbox.tvl.su/depot/ diff --git a/tvix/docs/src/contributing/gerrit.md b/tvix/docs/src/contributing/gerrit.md new file mode 100644 index 000000000000..3644e8cb0200 --- /dev/null +++ b/tvix/docs/src/contributing/gerrit.md @@ -0,0 +1,110 @@ +# Contributing to Tvix + +## Registration + +Self-hosted [Gerrit](https://www.gerritcodereview.com) & changelists (CLs) are +the preferred method of contributions & review. + +TVL’s Gerrit supports single sign-on (SSO) using a GitHub, GitLab, or +StackOverflow account. + +Additionally if you would prefer not to use an SSO option or wish to have a +backup authentication strategy in the event of downed server or otherwise, we +recommend setting up a TVL-specific LDAP account. + +You can create such an account by following these instructions: + +1. Checkout [TVL’s monorepo][check-out-monorepo] if you haven’t already +2. Be a member of `#tvix-dev` (and/or `#tvl`) on [hackint][], a communication + network. +3. Generate a user entry using [//web/pwcrypt](https://signup.tvl.fyi/). +4. Commit that generated user entry to our LDAP server configuration in + [ops/users][ops-users] (for an example, see: + [CL/2671](https://cl.tvl.fyi/c/depot/+/2671)) +5. If only using LDAP, submit the patch via email (see [<cite>Submitting + changes via email</cite>][email]) + + +## Gerrit setup + +Gerrit uses the concept of change IDs to track commits across rebases and other +operations that might change their hashes, and link them to unique changes in +Gerrit. + +First, [upload your public SSH keys to Gerrit][Gerrit SSH]. Then change your +remote to point to your newly-registered user over SSH. Then follow up with Git +config by setting the default push URLs for & installing commit hooks for a +smoother Gerrit experience. + +```console +$ cd depot +$ git remote set-url origin "ssh://$USER@code.tvl.fyi:29418/depot" +$ git config remote.origin.url "ssh://$USER@code.tvl.fyi:29418/depot" +$ git config remote.origin.push "HEAD:refs/for/canon" +$ curl -L --compressed https://cl.tvl.fyi/tools/hooks/commit-msg | tee .git/hooks/commit-msg +… +if ! mv "${dest}" "$1" ; then + echo "cannot mv ${dest} to $1" + exit 1 +fi +$ chmod +x .git/hooks/commit-msg +``` + +## Gerrit workflow + +The workflow on Gerrit is quite different than the pull request (PR) model that +many developers are more likely to be accustomed to. Instead of pushing changes +to remote branches, all changes have to be pushed to `refs/for/canon`. For each +commit that is pushed there, a change request is created automatically + +Every time you create a new commit the change hook will insert a unique +`Change-Id` tag into the commit message. Once you are satisfied with the state +of your commit and want to submit it for review, you push it to a Git `ref` +called `refs/for/canon`. This designates the commits as changelists (CLs) +targeted for the `canon` branch. + +After you feel satisfied with your changes changes, push to the default: + +```console +$ git commit -m 'docs(REVIEWS): Fixed all the errors in the reviews docs' +$ git push origin +``` + +Or to a special target, such as a work-in-progress CL: + +```console +$ git push origin HEAD:refs/for/canon%wip +``` + +During the review process, the reviewer(s) might ask you to make changes. You +can simply amend[^amend] your commit(s) then push to the same ref (`--force*` +flags not needed). Gerrit will automatically update your changes. + +```admonish caution +Every individual commit will become a separate change. We do *not* squash +related commits, but instead submit them one by one. Be aware that if you are +expecting a different behavior such as attempt something like an unsquashed +subtree merge, you will produce a *lot* of CLs. This is strongly discouraged. +``` + +```admonish tip +If do not have experience with the Gerrit model, consider reading the +[<cite>Working with Gerrit: An example</cite>][Gerrit Walkthrough] or +[<cite>Basic Gerrit Walkthrough — For GitHub Users</cite>][github-diff]. + +It will also be important to read about [attention sets][] to understand how +your ‘turn’ works, how notifications will be distributed to users through the +system, as well as the other [attention set rules][attention-set-rules]. +``` + + +[check-out-monorepo]: ./getting-started#tvl-monorepo +[email]: ../contributing/email.html +[Gerrit SSH]: https://cl.tvl.fyi/settings/#SSHKeys +[Gerrit walkthrough]: https://gerrit-review.googlesource.com/Documentation/intro-gerrit-walkthrough.html +[ops-users]: https://code.tvl.fyi/tree/ops/users/default.nix +[hackint]: https://hackint.org +[github-diff]: https://gerrit.wikimedia.org/r/Documentation/intro-gerrit-walkthrough-github.html +[attention sets]: https://gerrit-review.googlesource.com/Documentation/user-attention-set.html +[attention-set-rules]: https://gerrit-review.googlesource.com/Documentation/user-attention-set.html#_rules +[^keycloak]: [^amend]: `git commit --amend` diff --git a/tvix/docs/src/eval/abandoned/index.md b/tvix/docs/src/eval/abandoned/index.md new file mode 100644 index 000000000000..1cef704d08d7 --- /dev/null +++ b/tvix/docs/src/eval/abandoned/index.md @@ -0,0 +1,3 @@ +# Abandoned ideas + +This chapter keeps track of abandoned ideas, and why they were abandoned. diff --git a/tvix/eval/docs/abandoned/thread-local-vm.md b/tvix/docs/src/eval/abandoned/thread-local-vm.md index c6a2d5e07e5c..c6a2d5e07e5c 100644 --- a/tvix/eval/docs/abandoned/thread-local-vm.md +++ b/tvix/docs/src/eval/abandoned/thread-local-vm.md diff --git a/tvix/docs/src/eval/bindings.md b/tvix/docs/src/eval/bindings.md new file mode 100644 index 000000000000..4fb35b623580 --- /dev/null +++ b/tvix/docs/src/eval/bindings.md @@ -0,0 +1,134 @@ +# Compilation of bindings + +Compilation of Nix bindings is one of the most mind-bending parts of Nix +evaluation. The implementation of just the compilation is currently almost 1000 +lines of code, excluding the various insane test cases we dreamt up for it. + +## What is a binding? + +In short, any attribute set or `let`-expression. Tvix currently does not treat +formals in function parameters (e.g. `{ name ? "fred" }: ...`) the same as these +bindings. + +They have two very difficult features: + +1. Keys can mutually refer to each other in `rec` sets or `let`-bindings, + including out of definition order. +2. Attribute sets can be nested, and parts of one attribute set can be defined + in multiple separate bindings. + +Tvix resolves as much of this logic statically (i.e. at compile-time) as +possible, but the procedure is quite complicated. + +## High-level concept + +The idea behind the way we compile bindings is to fully resolve nesting +statically, and use the usual mechanisms (i.e. recursion/thunking/value +capturing) for resolving dynamic values. + +This is done by compiling bindings in several phases: + +1. An initial compilation phase *only* for plain inherit statements (i.e. + `inherit name;`), *not* for namespaced inherits (i.e. `inherit (from) + name;`). + +2. A declaration-only phase, in which we use the compiler's scope tracking logic + to calculate the physical runtime stack indices (further referred to as + "stack slots" or just "slots") that all values will end up in. + + In this phase, whenever we encounter a nested attribute set, it is merged + into a custom data structure that acts like a synthetic AST node. + + This can be imagined similar to a rewrite like this: + + ```nix + # initial code: + { + a.b = 1; + a.c = 2; + } + + # rewritten form: + { + a = { + b = 1; + c = 2; + }; + } + ``` + + The rewrite applies to attribute sets and `let`-bindings alike. + + At the end of this phase, we know the stack slots of all namespaces for + inheriting from, all values inherited from them, and all values (and + optionally keys) of bindings at the current level. + + Only statically known keys are actually merged, so any dynamic keys that + conflict will lead to a "key already defined" error at runtime. + +3. A compilation phase, in which all values (and, when necessary, keys) are + actually compiled. In this phase the custom data structure used for merging + is encountered when compiling values. + + As this data structure acts like an AST node, the process begins recursively + for each nested attribute set. + +At the end of this process we have bytecode that leaves the required values (and +optionally keys) on the stack. In the case of attribute sets, a final operation +is emitted that constructs the actual attribute set structure at runtime. For +`let`-bindings a final operation is emitted that removes these locals from the +stack when the scope ends. + +## Moving parts + +```admonish caution +This documents the *current* implementation. If you only care about the +conceptual aspects, see above. +``` + +There's a few types involved: + +* `PeekableAttrs`: peekable iterator over an attribute path (e.g. `a.b.c`) +* `BindingsKind`: enum defining the kind of bindings (attrs/recattrs/let) +* `AttributeSet`: struct holding the bindings kind, the AST nodes with inherits + (both namespaced and not), and an internal representation of bindings + (essentially a vector of tuples of the peekable attrs and the expression to + compile for the value). +* `Binding`: enum describing the kind of binding (namespaced inherit, attribute + set, plain binding of *any other value type*) +* `KeySlot`: enum describing the location in which a key slot is placed at + runtime (nowhere, statically known value in a slot, dynamic value in a slot) +* `TrackedBinding`: struct representing statically known information about a + single binding (its key slot, value slot and `Binding`) +* `TrackedBindings`: vector of tracked bindings, which implements logic for + merging attribute sets together + +And quite a few methods on `Compiler`: + +* `compile_bindings`: entry point for compiling anything that looks like a + binding, this calls out to the functions below. +* `compile_plain_inherits`: takes all inherits of a bindings node and compiles + the ones that are trivial to compile (i.e. just plain inherits without a + namespace). The `rnix` parser does not represent namespaced/plain inherits in + different nodes, so this function also aggregates the namespaced inherits and + returns them for further use +* `declare_namespaced_inherits`: passes over all namespaced inherits and + declares them on the locals stack, as well as inserts them into the provided + `TrackedBindings` +* `declare_bindings`: declares all regular key/value bindings in a bindings + scope, but without actually compiling their keys or values. + + There's a lot of heavy lifting going on here: + + 1. It invokes the various pieces of logic responsible for merging nested + attribute sets together, creating intermediate data structures in the value + slots of bindings that can be recursively processed the same way. + 2. It decides on the key slots of expressions based on the kind of bindings, + and the type of expression providing the key. +* `bind_values`: runs the actual compilation of values. Notably this function is + responsible for recursively compiling merged attribute sets when it encounters + a `Binding::Set` (on which it invokes `compile_bindings` itself). + +In addition to these several methods (such as `compile_attr_set`, +`compile_let_in`, ...) invoke the binding-kind specific logic and then call out +to the functions above. diff --git a/tvix/eval/docs/build-references.md b/tvix/docs/src/eval/build-references.md index badcea11550e..dd53f65d83aa 100644 --- a/tvix/eval/docs/build-references.md +++ b/tvix/docs/src/eval/build-references.md @@ -1,5 +1,4 @@ -Build references in derivations -=============================== +# Build references in derivations This document describes how build references are calculated in Tvix. Build references are used to determine which store paths should be available to a @@ -23,8 +22,10 @@ formats: This format is used for a special case where a derivation attribute directly refers to a derivation path (e.g. by accessing `.drvPath` on a derivation). - Note: In C++ Nix this case is quite special and actually requires a - store-database query during evaluation. + ```admonish note + In C++ Nix this case is quite special and actually requires a store-database + query during evaluation. + ``` 3. `<path>` - a non-descript store path input, usually a plain source file (e.g. from something like `src = ./.` or `src = ./foo.txt`). @@ -90,8 +91,10 @@ C++ Nix has several builtins that interface directly with string contexts: * `unsafeDiscardOutputDependency`: drops dependencies on the *outputs* of a `.drv` in the context, passing only the literal `.drv` itself - Note: This is only used for special test-cases in nixpkgs, and deprecated Nix + ```admonish note + This is only used for special test-cases in nixpkgs, and deprecated Nix commands like `nix-push`. + ``` * `getContext`: returns the string context in serialised form as a Nix attribute set * `appendContext`: adds a given string context to the string in the same format @@ -159,8 +162,10 @@ one evaluation should be created in Nix. This metadata needs to be available in These queries will need to be asked of the metadata when populating the derivation fields. -Note: Depending on how we implement `builtins.placeholder`, it might be useful +```admonish note +Depending on how we implement `builtins.placeholder`, it might be useful to track created placeholders in this metadata, too. +``` ### Context builtins diff --git a/tvix/eval/docs/builtins.md b/tvix/docs/src/eval/builtins.md index dba4c48c65e1..d9fcd72ccab5 100644 --- a/tvix/eval/docs/builtins.md +++ b/tvix/docs/src/eval/builtins.md @@ -1,5 +1,4 @@ -Nix builtins -============ +# Nix builtins Nix has a lot of built-in functions, some of which are accessible in the global scope, and some of which are only accessible through the diff --git a/tvix/eval/docs/catchable-errors.md b/tvix/docs/src/eval/catchable-errors.md index ce320a921777..ce320a921777 100644 --- a/tvix/eval/docs/catchable-errors.md +++ b/tvix/docs/src/eval/catchable-errors.md diff --git a/tvix/eval/docs/known-optimisation-potential.md b/tvix/docs/src/eval/known-optimisation-potential.md index 0ab185fe1be2..11babcb59ac1 100644 --- a/tvix/eval/docs/known-optimisation-potential.md +++ b/tvix/docs/src/eval/known-optimisation-potential.md @@ -1,5 +1,4 @@ -Known Optimisation Potential -============================ +# Known Optimisation Potential There are several areas of the Tvix evaluator code base where potentially large performance gains can be achieved through diff --git a/tvix/eval/docs/language-issues.md b/tvix/docs/src/eval/language-issues.md index 152e6594a1d0..152e6594a1d0 100644 --- a/tvix/eval/docs/language-issues.md +++ b/tvix/docs/src/eval/language-issues.md diff --git a/tvix/eval/docs/opcodes-attrsets.md b/tvix/docs/src/eval/opcodes-attrsets.md index 7026f3319dda..7026f3319dda 100644 --- a/tvix/eval/docs/opcodes-attrsets.md +++ b/tvix/docs/src/eval/opcodes-attrsets.md diff --git a/tvix/eval/docs/recursive-attrs.md b/tvix/docs/src/eval/recursive-attrs.md index c30cfd33e6c7..5ce1cb2b64ff 100644 --- a/tvix/eval/docs/recursive-attrs.md +++ b/tvix/docs/src/eval/recursive-attrs.md @@ -1,5 +1,4 @@ -Recursive attribute sets -======================== +# Recursive attribute sets The construction behaviour of recursive attribute sets is very specific, and a bit peculiar. diff --git a/tvix/eval/docs/vm-loop.md b/tvix/docs/src/eval/vm-loop.md index 6266d34709cb..a75c7eec31df 100644 --- a/tvix/eval/docs/vm-loop.md +++ b/tvix/docs/src/eval/vm-loop.md @@ -1,5 +1,4 @@ -tvix-eval VM loop -================= +# tvix-eval VM loop This document describes the new tvix-eval VM execution loop implemented in the chain focusing around cl/8104. diff --git a/tvix/docs/src/getting-started.md b/tvix/docs/src/getting-started.md new file mode 100644 index 000000000000..1cbb6de7d4f7 --- /dev/null +++ b/tvix/docs/src/getting-started.md @@ -0,0 +1,59 @@ +# Getting Started + +## Getting the code, a developer shell, & building the CLI + +Tvix can be built with the Rust standard `cargo build`. A Nix shell is provided +with the correctly-versioned tooling to build. + +### TVL monorepo + +```console +$ git clone https://code.tvl.fyi/depot.git +$ cd depot +``` + +[Direnv][] is highly recommended in order to enable [`mg`][mg], a tool for +workflows in monorepos. Follow the [Direnv installation +instructions][direnv-inst], then after it’s set up continue with: + +```console +$ direnv allow +$ mg shell //tvix:shell +$ cd tvix +$ cargo build +``` + +### Or just Tvix + +At present, this option isn’t suitable for contributions & lacks the tooling of +the monorepo, but still provides a `shell.nix` which can be used for building +the Tvix project. + +```console +$ git clone https://code.tvl.fyi/depot.git:workspace=views/tvix.git +$ cd tvix +$ nix-shell +$ cargo build +``` + + +# Builds & tests + +All projects are built using [Nix][] to avoid ‘build pollution’ via the user’s +local environment. + +If you have Nix installed and are contributing to a project tracked in this +repository, you can usually build the project by calling `nix-build -A +path.to.project`. + +For example, to build a project located at `//tools/foo` you would call +`nix-build -A tools.foo` + +If the project has tests, check that they still work before submitting your +change. + + +[Direnv]: https://direnv.net +[direnv-inst]: https://direnv.net/docs/installation.html +[Nix]: https://nixos.org/nix/ +[mg]: https://code.tvl.fyi/tree/tools/magrathea diff --git a/tvix/docs/src/introduction.md b/tvix/docs/src/introduction.md new file mode 100644 index 000000000000..744fbeec9fbe --- /dev/null +++ b/tvix/docs/src/introduction.md @@ -0,0 +1,23 @@ +# Introduction + +Tvix (\[tvɪks\], [🔈][pronunciation]) is a new Rust implementation of the +components of the [Nix package manager][Nix]. + +Tvix’s modularity & composability allows recombining its parts in novel ways. +It also provides library access to Nix data formats and concepts. In the +long-run, Tvix aims to produce a Nixpkgs-compatible alternative to NixCpp +with respects to evaluation and building Nix expressions & systems. + +Tvix still is in its early stages of development, **you cannot yet use it as a +Nix replacement**. However, if you willing to roll up your sleeves and pipe +together some existing functionality, it may already provide most of what is +needed for your usecase! [Get in touch](./community.md) if you want to +collaborate or contribute. + +Tvix is developed as a GPLv3-licensed free software project with +source code available in the [TVL monorepo][]. + +[Nix]: https://nixos.org +[TVL]: https://tvl.fyi +[TVL monorepo]: https://cs.tvl.fyi/depot/-/tree/tvix +[pronunciation]: data:audio/mpeg;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4Ljc2LjEwMAAAAAAAAAAAAAAA//NgxAAdEr31SGDGIQAoBRVe/7Yuv8SvC9C3dwMwOCEAE6YG/Cc/fQkSu5PE0Jzr6cRKhH6IEIIiIhOyU5Xdxbk5/0+vpvppXc/hQkrn7iCrn6e/XPield3Mq5oXh3cOLjgB3/+Zl4HAMuH/mAZpM8w8PDw9wAIk//5//gAODz/D1QNAKDLoeuUxZd2VeX0qV80WaVrSQech1Qpo//NixBofrA4YAVQoAYBzKPexmkFBrpGj2IrFxAh2NqwmjI9Bz+zGah1nVTsQQYlvF69rIzoTfLO6sqxMenRnYhhQe0yrQUNoTIrIymeh9/WtTnRjsk4wUEzE/10PE3ibzlRnQc6/o9BICCbzEVRN/E4CAAcgABBIgEtvMot7RXUwz1qnlmvx3zszWyTQ3PnVX6qRmWjvMuWn9CQGyP/zYsQrJuN+NYuYWAEASB1virzQzUvD2SBsJ598MYyYWUpZ6qA6mEkHbSSIDhm8/H9plcHHrYez50ll+Wj//uv7ZT1GfzU3fbbr+n7LPuVZHL9SPn+nww5M3d//3WdmV5O//9HYa2v9/MO7/iPY+tbPP3mqOf7M9YkkMSav2ub42nG43G5HIvvggKFUSYCII1JJlw5Z6Zl7q1gf4Yn/82LEHyfjCo29jHgCUQzqTIkkWtXFjjE6fsipzrFmZQMjI5ItTsH9c63TUWysQ5U0gKuGfMHW9xc1on58bw/fZTZkXamGN4tIM0bGPq0SlY8sJwn//v8/eNU1//j5zvGMb1u8e9/hz3nUPeb4v////r5+a1/9//97/3nesw9/3pKBi////wi4LtEAQQBKQdcrtttdriljiVQZDRBu//NgxA8jssa+X4xAAIyZIQuhQmsVXnSZQfa38AQAguDwKgVRGIoN7QuWGlkB4o01SRTOVz0IMe20lLfhYMST5BsMuNazInz4SXvROUIqeXKGlRF+tFu/ufB9OrGVnjnFYHB/ZL/3//yicvMVv8JzcxLo90MU0OFzaD9BIV4nxgAM8o54spq1vWJ3J1euBsqXgjzNIQwkDXFa+z0M//NixA8jY36IAZlAAE0Rhou7HpU1l3MchEFXAVQ+LzxKHghCoadED8LrAiMaa3xRZJAknkov/0FXWIS2baSv/8BUUcW+QUiR1evWF///Bt0o6RW5m5hYJUYsXF8p////0IR5Zrg8JXOOYVF8gZJHCk1zqTKx/Hf/NfEKJk//Q4OOvjk2lgr2KwVRuroANCW22220WC22WxxSJFJw///zYsQRIPpawl+PQAJIok7ku2H1FcavOpWYUpCxe5s1Q+UMGBAYIxQMDgDA7pVwZaCAHim/+9y90RRhX/+fFaUgdCMJty+f/76mfduCSBt2zTfz///0ic173oKSszA1maHKny9l0yXDjzAfxax9QnSpfGXFwuopIpFDapMcuhPXAR3d0afa5G6KRfINNDCox6CHM0gRpAHhcjpg5S//82LEHSehUqZ/2MAAstHIU01fRJTCUN0W5ONikDty+mkOcMdZggMiyaKrk5FopDHCDIREY5AUvBrQy6mEtXwj5KF2NnjqmcNPxI1hFYIw4cDPo7jsORGJyxhvu7VJ9JSU9PfHgh+s+kasgvIDmlycQOTKARwslggLg44MRq0e9zQPs94laXjb3mzJ4UOxRZAAVyUswcgDasxCuqXL//NgxA4fmbakXspMYGEihpTRnTNbuO2ScS7G8HnUYI0VUba51KySxTFPhAGIBWhZaUlpDwIKEUEFhRRIzMs0un31sV8pgYkDIo/////NZ7kCXBR5z/SmcfCtV7CBYROck2wt1PNAIWBpH20Ch06Mi7nAk6+0XTcL0j1jHvMKBjRANkjutdRwilbDIuehzRxbsWWi8O2LtKEAnFGg//NixB4Y2VKpHsDEnBAxM9VjUzUTxwpSxo3AKtq31VWBlKwUfHv8MKcPFQF6xg8NDlvb/jYab0ka3Q02RWr6nnoat/kxFMsfSd9N1V70VMQEQlUAAWVIF9yCKxm5BjQQyFCjvEAhZkFiwpgEl+ZTMQ9VBAo8lZIkcRIsmUt2JOCoEsO02W3zMnWjMttVnOJbLY1fZOAgf61FKRAJy//zYsRKHYIKclTJhJz/EmyjLKhmM5jG/m/MKFyxPj5WLwlshMRM9RJbjSEpKJ2XajtyqPrsVoMplgElrTccgAtkE8gNDDUgCYAXcJ+KZwji3XvujuyuqqkxkbfGZ1DKtgZj2KNQokgJo0LNS43+WVCkYca9L7GVPh3PpOFRqX6l/5/3Rur//7Lw/2/gXzNXUmb/8+r+cqrG1/jHV1L/82LEZB9r2lmdUxgBY12NW/8yra/VWCY2onY2OqTCqWoDlFYuNJIHSADU0zPoXEANHC/CJQ9VXi2VkPWYu/o3ey675hhm83g4Gol1zFaZnNPdWtnvpzz3pm23+qfMRrP3/6/r/X0+hh85+nmX/Xfm9z9jxwgQSQmIOEPp/VLtr+7q30XaQOBi7SH6gvr/6+/759gUGYNgwPy9etHb//NgxHYY48Zc8484AJ+xN8+cpj5c1N6jT6efgxULyUJDRo8HjxIoqkgnU6rJKkyo1MmEVdlbq8/tio2Xzz+92+/hh7Y2PfDnnZb////tivb//ppv///3GtRNroKtdtiYhOyKSA54dcWIJUKiA8CqGhH/EQqaTS22Kh0VuREVT2/1jkddqAETOd02plawNh7D0gUlIdr7skBZn36Z//NixKEgqp6NlYxYAILyK/Me3NLnji/AGNiP/ppZtSKjlJ0l2MObV3mZmlKRXWLGCQYQn9E46Jzv2Dzpxf/ysWLHKsCQYdizplszP2DBZSnMOXSKJbJb9FksHm6vsrKhodn6+PayULvD6VXqeH9uhIKMilwo0yP2CBnvLSy5ndd/2V52KZe9tOpbuyd50yIzNGgAOzgxhghLnrj73v/zYsSuHxo60l/PYAIQvV0+Y8c5Eve9aCLA7KyvyIpHHTD8kJXBY/XQ6tJix57v/z7aytZXaxOQCgTtIiBnYRmvAn2ZvJfF28zb+Z/Wrwcqb/5/Lgd8RmsQIfWbvKmJZVsISTlOJrSMeiTp8eUdLeIww1K0tPobChnijzJqdpCJGzAMMm+137+u1ZW2uNLKYbv3Gp79FOb9/28bG1f/82LEwR+bMspeEZOsn/dzWfGbF0+9GL7VV/TnVRMHHkLI1ESlvkmsXHOKdIxhqJB5JP0v3//d3ec/7ZetjPpTRMCX/o6Cn9pNqMqqp20AIAUhbGQ2DwQQQajwGmTvpPPSJnvJq0tNMO2ctFOry7oUse5nGs7ig8jCIYQ3qdHYjFUUgVysGNUxCFFnQIsEwuheniLPf/0BXDnTKQBN//NgxNIfOz7PHjBM8CgRwalCwMUpnK7E5qBQEbDK2TUjYjWH2k3dej3zKqqtTHLqs9vnyUABQryVhSrrkyQmUKEyNw88ZKsHE3objjf+74httv+/7btZmU0T2JS6eKit8fLYwttZwfiZViggsacmKkdh5ktgIc8eqhp1WK2SNdYROKUApEUkD5b///7JlyI0S////2igt0ZUAoGR//NixOQd0rLHHlmEPAgysKqZnSLShsPjwV5YYAMPciIi7Ci6nWZJTz0MYSRsSxCiSQ4VJOUHQ7EQ9wkfzy/kPTrqVTK7NYDABwwlZGkyjLS80AYda6qhOy6TSym7epLitq8UJx4QIyIy1Hp4tNC4hSzspu9rPQ/P/9ZVIn0qoAIfdBUESW1UKGLSz4/pEzRC1EQ6kweN/JKHRUpUe//zYsT8KGruolJL04QXyh0uNArGozLD+BhSxsBVGq6QCMKqsGYMBMrUgqki2HXQme1PcskWvW74a8ra7QoAigIobgqjopUJPqbNBY8/DxS92FTwxupQx5wodcqHbcTeCAXqmqkinH6iNJHaKmXLGKEJhKncFgtEGSwkgSSOXMhMm5/3nEpmStNNRqu3p21/LaxJL1RjKUv/Khuu8yP/82DE6iJa2pZMSUfE0e5SmVHKxvSa6AMK0cpeIjjGM6sxUOVjKIh0ylZSpV8xqCQc3A1lRkqr88y7rO1aKlwMtBNoJmhGGCDxgh6UJfVM2PXVKmLM5lkah6mdmczj0nZS6sSjUtgKHoakUZGigFACs7Sl4SZKW8wDBTbOU6IMuq/75Tvn5yU53/OJJUcSx5kjM+fsYU+Z//USxW//82LE7yQTFmmCwYswDAQ86RpBWGiqw1Dp3DqwVATjoifDskVQVcoKB0NHutyw0Gmekq5p7JVuUeqqTEFNRaqqUJagECihZAmgmpE40ouLi2v/mRkfRrLJUcZlDBQoYGCDo5GyhgcdDIjWWWW//////mrKGBgg7oZMoYGiORqGCggYMFUcjL/7LmasoYGCDhI6GTLLZZZZb5GrWSx0//NixO4ikg4wCtGFFDJlWVDJlYMFBAwjoZFLP/8mVrLY5GrWSo5MrUKCBwxKtUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zYsTtH1vZLBQwRq1VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU= diff --git a/tvix/docs/src/language-spec.md b/tvix/docs/src/language-spec.md index 0ff1dc491e3c..b3908b2cf48a 100644 --- a/tvix/docs/src/language-spec.md +++ b/tvix/docs/src/language-spec.md @@ -1,8 +1,10 @@ # Specification of the Nix Language -WARNING: This document is a work in progress. Please keep an eye on +```admonish attention +This document is a work in progress. Please keep an eye on [`topic:nix-spec`](https://cl.tvl.fyi/q/topic:nix-spec) for ongoing CLs. +``` Nix is a general-purpose, functional programming language which this document aims to describe. diff --git a/tvix/docs/src/nix-daemon/changelog.md b/tvix/docs/src/nix-daemon/changelog.md new file mode 100644 index 000000000000..41c168374c50 --- /dev/null +++ b/tvix/docs/src/nix-daemon/changelog.md @@ -0,0 +1,202 @@ + + +## Nix version protocol + +| Nix version | Protocol | +| --------------- | -------- | +| 0.11 | 1.02 | +| 0.12 | 1.04 | +| 0.13 | 1.05 | +| 0.14 | 1.05 | +| 0.15 | 1.05 | +| 0.16 | 1.06 | +| 1.0 | 1.10 | +| 1.1 | 1.11 | +| 1.2 | 1.12 | +| 1.3 - 1.5.3 | 1.13 | +| 1.6 - 1.10 | 1.14 | +| 1.11 - 1.11.16 | 1.15 | +| 2.0 - 2.0.4 | 1.20 | +| 2.1 - 2.3.18 | 1.21 | +| 2.4 - 2.6.1 | 1.32 | +| 2.7.0 | 1.33 | +| 2.8.0 - 2.14.1 | 1.34 | +| 2.15.0 - 2.19.4 | 1.35 | +| 2.20.0 - 2.22.0 | 1.37 | + +In commit [be64fbb501][be64fbb501] support was droped for protocol versions older than 1.10. +This happened when the protocol was between 1.17 and 1.18 and was released with Nix 2.0. +So this means that any version of Nix 2.x can't talk to Nix 0.x. + +## Operation History + +| Op | Id | Commit | Protocol | Nix Version | Notes | +| --------------- | -- | -------------- | -------- | ----------- | ----- | +| *Quit | 0 | [a711689368][a711689368] || 0.11 | Became dead code in [7951c3c54][7951c3c54] (Nix 0.11) and removed in [d3c61d83b][d3c61d83b] (Nix 1.8) | +| IsValidPath | 1 | [a711689368][a711689368] || 0.11 || +| HasSubstitutes | 3 | [0565b5f2b3][0565b5f2b3] || 0.11 | Obsolete [09a6321aeb][09a6321aeb]<br>Nix 1.2 Protocol 1.12 | +| QueryPathHash | 4 | [0565b5f2b3][0565b5f2b3] || 0.11 | Obsolete [e0204f8d46][e0204f8d46]<br>Nix 2.0 Protocol 1.16 | +| QueryReferences | 5 | [0565b5f2b3][0565b5f2b3] || 0.11 | Obsolete [e0204f8d46][e0204f8d46]<br>Nix 2.0 Protocol 1.16 | +| QueryReferrers | 6 | [0565b5f2b3][0565b5f2b3] || 0.11 || +| AddToStore | 7 | [0263279071][0263279071] || 0.11 || +| AddTextToStore | 8 | [0263279071][0263279071] || 0.11 | Obsolete [c602ebfb34][c602ebfb34]<br>Nix 2.4 Protocol 1.25 | +| BuildPaths | 9 | [0565b5f2b3][0565b5f2b3] || 0.11 || +| EnsurePath | 10 | [0565b5f2b3][0565b5f2b3] || 0.11 || +| AddTempRoot | 11 | [e25fad691a][e25fad691a] || 0.11 || +| AddIndirectRoot | 12 | [74033a844f][74033a844f] || 0.11 || +| SyncWithGC | 13 | [e25fad691a][e25fad691a] || 0.11 | Obsolete [9947f1646a][9947f1646a]<br> Nix 2.5.0 Protocol 1.32 | +| FindRoots | 14 | [29cf434a35][29cf434a35] || 0.11 || +| *CollectGarbage | 15 | [a9c4f66cfb][a9c4f66cfb] || 0.11 | Removed [a72709afd8][a72709afd8]<br>Nix 0.12 Protocol 1.02 | +| ExportPath | 16 | [0f5da8a83c][0f5da8a83c] || 0.11 | Obsolete [538a64e8c3][538a64e8c3]<br>Nix 2.0 Protocol 1.17 | +| *ImportPath | 17 | [0f5da8a83c][0f5da8a83c] || 0.11 | Removed [273b288a7e][273b288a7e]<br>Nix 1.0 Protocol 1.09 | +| QueryDeriver | 18 | [6d1a1191b0][6d1a1191b0] || 0.11 | Obsolete [e0204f8d46][e0204f8d46]<br>Nix 2.0 Protocol 1.16 | +| SetOptions | 19 | [f3441e6122][f3441e6122] || 0.11 || +| CollectGarbage | 20 | [a72709afd8][a72709afd8] | 1.02 | 0.12 || +| QuerySubstitutablePathInfo | 21 | [03427e76f1][03427e76f1] | 1.02 | 0.12 || +| QueryDerivationOutputs | 22 | [e42401ee7b][e42401ee7b] | 1.05 | 1.0 | Obsolete [d38f860c3e][d38f860c3e]<br>Nix 2.4 Protocol 1.22* | +| QueryAllValidPaths | 23 | [24035b98b1][24035b98b1] | 1.05 | 1.0 || +| *QueryFailedPaths | 24 | [f92c9a0ac5][f92c9a0ac5] | 1.05 | 1.0 | Removed [8cffec848][8cffec848]<br>Nix 2.0 Protocol 1.16 | +| *ClearFailedPaths | 25 | [f92c9a0ac5][f92c9a0ac5] | 1.05 | 1.0 | Removed [8cffec848][8cffec848]<br>Nix 2.0 Protocol 1.16 | +| QueryPathInfo | 26 | [1db6259076][1db6259076] | 1.06 | 1.0 || +| ImportPaths | 27 | [273b288a7e][273b288a7e] | 1.09 | 1.0 | Obsolete [538a64e8c3][538a64e8c3]<br>Nix 2.0 Protocol 1.17 | +| QueryDerivationOutputNames | 28 | [af2e53fd48][af2e53fd48]<br>([194d21f9f6][194d21f9f6]) | 1.08 | 1.0 | Obsolete<br>[045b07200c][045b07200c]<br>Nix 2.4 Protocol 1.21 | +| QueryPathFromHashPart | 29 | [ccc52adfb2][ccc52adfb2] | 1.11 | 1.1 || +| QuerySubstitutablePathInfos | 30 | [eb3036da87][eb3036da87] | 1.12* | 1.2 || +| QueryValidPaths | 31 | [58ef4d9a95][58ef4d9a95] | 1.12 | 1.2 || +| QuerySubstitutablePaths | 32 | [09a6321aeb][09a6321aeb] | 1.12 | 1.2 || +| QueryValidDerivers | 33 | [2754a07ead][2754a07ead] | 1.13* | 1.3 || +| OptimiseStore | 34 | [8fb8c26b6d][2754a07ead] | 1.14 | 1.8 || +| VerifyStore | 35 | [b755752f76][b755752f76] | 1.14 | 1.9 || +| BuildDerivation | 36 | [71a5161365][71a5161365] | 1.14 | 1.10 || +| AddSignatures | 37 | [d0f5719c2a][d0f5719c2a] | 1.16 | 2.0 || +| NarFromPath | 38 | [b4b5e9ce2f][b4b5e9ce2f] | 1.17 | 2.0 || +| AddToStoreNar | 39 | [584f8a62de][584f8a62de] | 1.17 | 2.0 || +| QueryMissing | 40 | [ba20730b3f][ba20730b3f] | 1.19* | 2.0 || +| QueryDerivationOutputMap | 41 | [d38f860c3e][d38f860c3e] | 1.22* | 2.4 || +| RegisterDrvOutput | 42 | [58cdab64ac][58cdab64ac] | 1.27 | 2.4 || +| QueryRealisation | 43 | [58cdab64ac][58cdab64ac] | 1.27 | 2.4 || +| AddMultipleToStore | 44 | [fe1f34fa60][fe1f34fa60] | 1.32* | 2.4 || +| AddBuildLog | 45 | [4dda1f92aa][4dda1f92aa] | 1.32 | 2.6.0 || +| BuildPathsWithResults | 46 | [a4604f1928][a4604f1928] | 1.34* | 2.8.0 || +| AddPermRoot | 47 | [226b0f3956][226b0f3956] | 1.36* | 2.20.0 || + +Notes: Ops that start with * have been removed. +Protocol version that ends with * was bumped while adding that operation. Otherwise protocol version referes to the protocol version at the time the operation was added (so only at the next protocol version can you assume the operation is present/removed/obsolete since it was added/removed/obsoleted between protocol versions). + +## Protocol version change log + +- 1.01 [f3441e6122][f3441e6122] Initial Version +- 1.02 [c370755583][c370755583] Use build hook +- 1.03 [db4f4a8425][db4f4a8425] Backward compatibility check +- 1.04 [96598e7b06][96598e7b06] SetOptions buildVerbosity +- 1.05 [60ec75048a][60ec75048a] SetOptions useAtime & maxAtime +- 1.06 [6846ed8b44][6846ed8b44] SetOptions buildCores +- 1.07 [bdf089f463][bdf089f463] QuerySubstitutablePathInfo narSize +- 1.08 [b1eb252172][b1eb252172] STDERR_ERROR exit status +- 1.09 [e0bd307802][e0bd307802] ImportPath not supported on versions older than 1.09 +- 1.10 [db5b86ef13][db5b86ef13] SetOptions build-use-substitutess +- 1.11 [4bc4da331a][4bc4da331a] open connection reserveSpace +- 1.12 [eb3036da87][eb3036da87] Implement QuerySubstitutablePathInfos +- 1.13 [2754a07ead][2754a07ead] Implement QueryValidDerivers +- 1.14 [a583a2bc59][a583a2bc59] open connection cpu affinity +- 1.15 [d1e3bf01bc][d1e3bf01bc] BuildPaths buildMode +- 1.16 [9cee600c88][9cee600c88] QueryPathInfo ultimate & sigs +- 1.17 [ddea253ff8][ddea253ff8] QueryPathInfo returns valid bool +- 1.18 [4b8f1b0ec0][4b8f1b0ec0] Select between AddToStoreNar and ImportPaths +- 1.19 [ba20730b3f][ba20730b3f] Implement QueryMissing +- 1.20 [cfc8132391][cfc8132391] Don't send activity and result logs to old clients +- 1.21 [6185d25e52][6185d25e52] AddToStoreNar uses TunnelLogger for data +- 1.22 [d38f860c3e][d38f860c3e] Implement QueryDerivationOutputMap and obsolete QueryDerivationOutputs +- 1.23 [4c0077a07d][4c0077a07d] AddToStoreNar uses FramedSink/-Source for data +- 1.24 [5ccd94501d][5ccd94501d] Allow trustless building of CA derivations +- 1.25 [e34fe47d0c][e34fe47d0c] New implementation of AddToStore +- 1.26 [c43e882f54][c43e882f54] STDERR_ERROR serialize exception +- 1.27 [3a63fc6cd5][3a63fc6cd5] QueryValidPaths substitute flag +- 1.28 [27b5747ca7][27b5747ca7] BuildDerivation returns builtOutputs +- 1.29 [9d309de0de][9d309de0de] BuildDerivation returns timesBuilt, isNonDeterministic, startTime & stopTime +- 1.30 [e5951a6b2f][e5951a6b2f] Bump version number for DerivedPath changes +- 1.31 [a8416866cf][a8416866cf] RegisterDrvOutput & QueryRealisation send realisations as JSON +- 1.32 [fe1f34fa60][fe1f34fa60] Implement AddMultipleToStore +- 1.33 [35dbdbedd4][35dbdbedd4] open connection sends nix version +- 1.34 [a4604f1928][a4604f1928] Implement BuildPathsWithResults +- 1.35 [9207f94582][9207f94582] open connection sends trusted option +- 1.36 [226b0f3956][226b0f3956] Implement AddPermRoot +- 1.37 [1e3d811840][1e3d811840] Serialize BuildResult send cpuUser & cpuSystem + + + +[0263279071]: https://github.com/NixOS/nix/commit/0263279071 +[03427e76f1]: https://github.com/NixOS/nix/commit/03427e76f1 +[045b07200c]: https://github.com/NixOS/nix/commit/045b07200c +[0565b5f2b3]: https://github.com/NixOS/nix/commit/0565b5f2b3 +[09a6321aeb]: https://github.com/NixOS/nix/commit/09a6321aeb +[0f5da8a83c]: https://github.com/NixOS/nix/commit/0f5da8a83c +[194d21f9f6]: https://github.com/NixOS/nix/commit/194d21f9f6 +[1db6259076]: https://github.com/NixOS/nix/commit/1db6259076 +[1e3d811840]: https://github.com/NixOS/nix/commit/1e3d811840 +[24035b98b1]: https://github.com/NixOS/nix/commit/24035b98b1 +[226b0f3956]: https://github.com/NixOS/nix/commit/226b0f3956 +[273b288a7e]: https://github.com/NixOS/nix/commit/273b288a7e +[2754a07ead]: https://github.com/NixOS/nix/commit/2754a07ead +[27b5747ca7]: https://github.com/NixOS/nix/commit/27b5747ca7 +[29cf434a35]: https://github.com/NixOS/nix/commit/29cf434a35 +[35dbdbedd4]: https://github.com/NixOS/nix/commit/35dbdbedd4 +[3a63fc6cd5]: https://github.com/NixOS/nix/commit/3a63fc6cd5 +[4b8f1b0ec0]: https://github.com/NixOS/nix/commit/4b8f1b0ec0 +[4bc4da331a]: https://github.com/NixOS/nix/commit/4bc4da331a +[4c0077a07d]: https://github.com/NixOS/nix/commit/4c0077a07d +[4dda1f92aa]: https://github.com/NixOS/nix/commit/4dda1f92aa +[538a64e8c3]: https://github.com/NixOS/nix/commit/538a64e8c3 +[584f8a62de]: https://github.com/NixOS/nix/commit/584f8a62de +[58cdab64ac]: https://github.com/NixOS/nix/commit/58cdab64ac +[58ef4d9a95]: https://github.com/NixOS/nix/commit/58ef4d9a95 +[5ccd94501d]: https://github.com/NixOS/nix/commit/5ccd94501d +[60ec75048a]: https://github.com/NixOS/nix/commit/60ec75048a +[6185d25e52]: https://github.com/NixOS/nix/commit/6185d25e52 +[6846ed8b44]: https://github.com/NixOS/nix/commit/6846ed8b44 +[6d1a1191b0]: https://github.com/NixOS/nix/commit/6d1a1191b0 +[71a5161365]: https://github.com/NixOS/nix/commit/71a5161365 +[74033a844f]: https://github.com/NixOS/nix/commit/74033a844f +[7951c3c54]: https://github.com/NixOS/nix/commit/7951c3c54 +[8cffec848]: https://github.com/NixOS/nix/commit/8cffec848 +[8fb8c26b6d]: https://github.com/NixOS/nix/commit/8fb8c26b6d +[9207f94582]: https://github.com/NixOS/nix/commit/9207f94582 +[96598e7b06]: https://github.com/NixOS/nix/commit/96598e7b06 +[9947f1646a]: https://github.com/NixOS/nix/commit/9947f1646a +[9cee600c88]: https://github.com/NixOS/nix/commit/9cee600c88 +[9d309de0de]: https://github.com/NixOS/nix/commit/9d309de0de +[a4604f1928]: https://github.com/NixOS/nix/commit/a4604f1928 +[a583a2bc59]: https://github.com/NixOS/nix/commit/a583a2bc59 +[a711689368]: https://github.com/NixOS/nix/commit/a711689368 +[a72709afd8]: https://github.com/NixOS/nix/commit/a72709afd8 +[a8416866cf]: https://github.com/NixOS/nix/commit/a8416866cf +[a9c4f66cfb]: https://github.com/NixOS/nix/commit/a9c4f66cfb +[af2e53fd48]: https://github.com/NixOS/nix/commit/af2e53fd48 +[b1eb252172]: https://github.com/NixOS/nix/commit/b1eb252172 +[b4b5e9ce2f]: https://github.com/NixOS/nix/commit/b4b5e9ce2f +[b755752f76]: https://github.com/NixOS/nix/commit/b755752f76 +[ba20730b3f]: https://github.com/NixOS/nix/commit/ba20730b3f +[bdf089f463]: https://github.com/NixOS/nix/commit/bdf089f463 +[be64fbb501]: https://github.com/NixOS/nix/commit/be64fbb501 +[c370755583]: https://github.com/NixOS/nix/commit/c370755583 +[c43e882f54]: https://github.com/NixOS/nix/commit/c43e882f54 +[c602ebfb34]: https://github.com/NixOS/nix/commit/c602ebfb34 +[ccc52adfb2]: https://github.com/NixOS/nix/commit/ccc52adfb2 +[cfc8132391]: https://github.com/NixOS/nix/commit/cfc8132391 +[d0f5719c2a]: https://github.com/NixOS/nix/commit/d0f5719c2a +[d1e3bf01bc]: https://github.com/NixOS/nix/commit/d1e3bf01bc +[d38f860c3e]: https://github.com/NixOS/nix/commit/d38f860c3e +[d3c61d83b]: https://github.com/NixOS/nix/commit/d3c61d83b +[db4f4a8425]: https://github.com/NixOS/nix/commit/db4f4a8425 +[db5b86ef13]: https://github.com/NixOS/nix/commit/db5b86ef13 +[ddea253ff8]: https://github.com/NixOS/nix/commit/ddea253ff8 +[e0204f8d46]: https://github.com/NixOS/nix/commit/e0204f8d46 +[e0bd307802]: https://github.com/NixOS/nix/commit/e0bd307802 +[e25fad691a]: https://github.com/NixOS/nix/commit/e25fad691a +[e34fe47d0c]: https://github.com/NixOS/nix/commit/e34fe47d0c +[e42401ee7b]: https://github.com/NixOS/nix/commit/e42401ee7b +[e5951a6b2f]: https://github.com/NixOS/nix/commit/e5951a6b2f +[eb3036da87]: https://github.com/NixOS/nix/commit/eb3036da87 +[f3441e6122]: https://github.com/NixOS/nix/commit/f3441e6122 +[f92c9a0ac5]: https://github.com/NixOS/nix/commit/f92c9a0ac5 +[fe1f34fa60]: https://github.com/NixOS/nix/commit/fe1f34fa60 diff --git a/tvix/docs/src/nix-daemon/handshake.md b/tvix/docs/src/nix-daemon/handshake.md new file mode 100644 index 000000000000..0a436372b3ff --- /dev/null +++ b/tvix/docs/src/nix-daemon/handshake.md @@ -0,0 +1,32 @@ + + +## client -> server +- 0x6e697863 :: [Int](#int) (hardcoded, 'nixc' in ASCII) + +## server -> client +- 0x6478696f :: [Int](#int) (hardcoded, 'dxio' in ASCII) +- protocolVersion :: [Int](#int) + +## client -> server +- clientVersion :: [Int](#int) + +### If clientVersion is 1.14 or later +- sendCpu :: [Bool](#bool) (hardcoded to false in client) +#### If sendCpu is true +- cpuAffinity :: [Int](#int) (obsolete and ignored) + +### If clientVersion is 1.11 or later +- reserveSpace :: [Bool](#bool) (obsolete, ignored and set to false) + + +## server -> client + +### If clientVersion is 1.33 or later +- nixVersion :: String + +### If clientVersion is 1.35 or later +- trusted :: OptTrusted + +## server -> client +- send logs +- [operation](./operations.md) :: Int \ No newline at end of file diff --git a/tvix/docs/src/nix-daemon/index.md b/tvix/docs/src/nix-daemon/index.md new file mode 100644 index 000000000000..e47c20151e0d --- /dev/null +++ b/tvix/docs/src/nix-daemon/index.md @@ -0,0 +1,15 @@ +# Nix Daemon Protocol + +The Nix Daemon protocol is what's used to communicate with the `nix-daemon`, +either on the local system (in which case the communication happens via a Unix +domain socket), or with a remote Nix (in which this is tunneled over SSH). + +It uses a custom binary format which isn't too documented. The subpages here +collect serve as an in-depth detail about some of the inner workings, data types +etc. + +A first implementation of this exists in +[griff/Nix.rs](https://github.com/griff/Nix.rs/tree/main). + +Work is underway to port / factor this out into reusable building blocks into +the [nix-compat] crate. diff --git a/tvix/docs/src/nix-daemon/logging.md b/tvix/docs/src/nix-daemon/logging.md new file mode 100644 index 000000000000..c2828b13c21a --- /dev/null +++ b/tvix/docs/src/nix-daemon/logging.md @@ -0,0 +1,124 @@ +# Logging + +Because the daemon protocol only has one sender stream and one receiver stream +logging messages need to be carefully interleaved with requests and responses. +Usually this means that after the operation and all of its inputs (the request) +has been read logging hijacks the sender stream (in the server case) and uses +it to send typed logging messages while the request is being processed. When +the response has been generated it will send `STDERR_LAST` to mark that what +follows is the response data to the request. If the request failed a +`STDERR_ERROR` message is sent with the error and no response is sent. + +While not in this state between request reading and response sending all +messages and activities are buffered until next time the logger can send data. + +The logging messages supported are: +- [`STDERR_LAST`](#stderr_last) +- [`STDERR_ERROR`](#stderr_error) +- [`STDERR_NEXT`](#stderr_next) +- [`STDERR_READ`](#stderr_read) +- [`STDERR_WRITE`](#stderr_write) +- [`STDERR_START_ACTIVITY`](#stderr_start_activity) +- [`STDERR_STOP_ACTIVITY`](#stderr_stop_activity) +- [`STDERR_RESULT`](#stderr_result) + + +### `STDERR_LAST` +Marks the end of the logs, normal processing can resume. + +- 0x616c7473 :: [UInt64][se-UInt64] (hardcoded, 'alts' in ASCII) + + +### `STDERR_ERROR` +This also marks the end of this log "session" and so it +has the same effect as `STDERR_LAST`. +On the client the error is thrown as an exception and no response is read. + +#### If protocol version is 1.26 or newer +- 0x63787470 :: [UInt64][se-UInt64] (hardcoded, 'cxtp' in ASCII) +- error :: [Error][se-Error] + +#### If protocol version is older than 1.26 +- 0x63787470 :: [UInt64][se-UInt64] (hardcoded, 'cxtp' in ASCII) +- msg :: [String][se-String] (If logger is JSON, invalid UTF-8 is replaced with U+FFFD) +- exitStatus :: [Int][se-Int] + + +### `STDERR_NEXT` +Normal string log message. + +- 0x6f6c6d67 :: [UInt64][se-UInt64] (hardcoded, 'olmg' in ASCII) +- msg :: [String][se-String] (If logger is JSON, invalid UTF-8 is replaced with U+FFFD) + + +### `STDERR_READ` +Reader interface used by ImportsPaths and AddToStoreNar (between 1.21 and 1.23). +It works by sending a desired buffer length and then on the receiver stream it +reads bytes buffer of that length. If it receives 0 bytes it sees this as an +unexpected EOF. + +- 0x64617461 :: [UInt64][se-UInt64] (hardcoded, 'data' in ASCII) +- desiredLen :: [Size][se-Size] + + +### `STDERR_WRITE` +Writer interface used by ExportPath. Simply writes a buffer. + +- 0x64617416 :: [UInt64][se-UInt64] (hardcoded) +- buffer :: [Bytes][se-Bytes] + + +### `STDERR_START_ACTIVITY` +Begins an activity. In other tracing frameworks this would be called a span. + +Implemented in protocol 1.20. To achieve backwards compatible with older +versions of the protocol instead of sending an `STDERR_START_ACTIVITY` +the level is checked against enabled logging level and the text field is +sent as a simple log message with `STDERR_NEXT`. + +- 0x53545254 :: [UInt64][se-UInt64] (hardcoded, 'STRT' in ASCII) +- act :: [UInt64][se-UInt64] +- level :: [Verbosity][se-Verbosity] +- type :: [ActivityType][se-ActivityType] +- text :: [String][se-String] (If logger is JSON, invalid UTF-8 is replaced with U+FFFD) +- fields :: [List][se-List] of [Field][se-Field] +- parent :: [UInt64][se-UInt64] + + +act is atomic (nextId++ + (getPid() << 32)) + + +### `STDERR_STOP_ACTIVITY` +Stops the given activity. The activity id should not send any more results. +Just sends `ActivityId`. + +Implemented in protocol 1.20. When backwards compatible with older versions of +the protocol and this message would have been sent it is instead ignored. + +- 0x53544f50 :: [UInt64][se-UInt64] (hardcoded, 'STOP' in ASCII) + + +### `STDERR_RESULT` +Sends results for a given activity. + +Implemented in protocol 1.20. When backwards compatible with older versions of +the protocol and this message would have been sent it is instead ignored. + +- 0x52534c54 :: [UInt64][se-UInt64] (hardcoded, 'RSLT' in ASCII) +- act :: [UInt64][se-UInt64] +- type :: [ResultType][se-ResultType] +- fields :: [List][se-List] of [Field][se-Field] + + + +[se-UInt64]: ./serialization.md#uint64 +[se-Int]: ./serialization.md#int +[se-Size]: ./serialization.md#size +[se-Verbosity]: ./serialization.md#verbosity +[se-ActivityType]: ./serialization.md#activitytype +[se-ResultType]: ./serialization.md#resulttype +[se-Bytes]: ./serialization.md#bytes +[se-String]: ./serialization.md#string +[se-List]: ./serialization.md#list-of-x +[se-Error]: ./serialization.md#error +[se-Field]: ./serialization.md#field \ No newline at end of file diff --git a/tvix/docs/src/nix-daemon/operations.md b/tvix/docs/src/nix-daemon/operations.md new file mode 100644 index 000000000000..80708c9104b5 --- /dev/null +++ b/tvix/docs/src/nix-daemon/operations.md @@ -0,0 +1,904 @@ + +# TOC + +| Operation | Id | +| ----------------------------------------------------------- | -- | +| [IsValidPath](#isvalidpath) | 1 | +| [HasSubstitutes](#hassubstitutes) | 3 | +| [QueryReferrers](#queryreferrers) | 6 | +| [AddToStore](#addtostore) | 7 | +| [BuildPaths](#buildpaths) | 9 | +| [EnsurePath](#ensurepath) | 10 | +| [AddTempRoot](#addtemproot) | 11 | +| [AddIndirectRoot](#addindirectroot) | 12 | +| [FindRoots](#findroots) | 14 | +| [SetOptions](#setoptions) | 19 | +| [CollectGarbage](#collectgarbage) | 20 | +| [QueryAllValidPaths](#queryallvalidpaths) | 23 | +| [QueryPathInfo](#querypathinfo) | 26 | +| [QueryPathFromHashPart](#querypathfromhashpart) | 29 | +| [QueryValidPaths](#queryvalidpaths) | 31 | +| [QuerySubstitutablePaths](#querysubstitutablepaths) | 32 | +| [QueryValidDerivers](#queryvalidderivers) | 33 | +| [OptimiseStore](#optimisestore) | 34 | +| [VerifyStore](#verifystore) | 35 | +| [BuildDerivation](#buildderivation) | 36 | +| [AddSignatures](#addsignatures) | 37 | +| [NarFromPath](#narfrompath) | 38 | +| [AddToStoreNar](#addtostore) | 39 | +| [QueryMissing](#querymissing) | 40 | +| [QueryDerivationOutputMap](#queryderivationoutputmap) | 41 | +| [RegisterDrvOutput](#registerdrvoutput) | 42 | +| [QueryRealisation](#queryrealisation) | 43 | +| [AddMultipleToStore](#addmultipletostore) | 44 | +| [AddBuildLog](#addbuildlog) | 45 | +| [BuildPathsWithResults](#buildpathswithresults) | 46 | +| [AddPermRoot](#addpermroot) | 47 | + + +## Obsolete operations + +| Operation | Id | +| ----------------------------------------------------------- | -- | +| [QueryPathHash](#querypathhash) | 4 | +| [QueryReferences](#queryreferences) | 5 | +| [AddTextToStore](#addtexttostore) | 8 | +| [SyncWithGC](#syncwithgc) | 13 | +| [ExportPath](#exportpath) | 16 | +| [QueryDeriver](#queryderiver) | 18 | +| [QuerySubstitutablePathInfo](#querysubstitutablepathinfo) | 21 | +| [QueryDerivationOutputs](#queryderivationoutputs) | 22 | +| [ImportPaths](#importpaths) | 27 | +| [QueryDerivationOutputNames](#queryderivationoutputnames) | 28 | +| [QuerySubstitutablePathInfos](#querysubstitutablepathinfos) | 30 | + + +## Removed operations + +| Operation | Id | +| ------------------------------------------------- | -- | +| [Quit](#quit-removed) | 0 | +| [ImportPath](#importpath-removed) | 17 | +| [Old CollectGarbage](#old-collectgarbage-removed) | 15 | +| [QueryFailedPaths](#queryfailedpaths) | 24 | +| [ClearFailedPaths](#clearfailedpaths) | 25 | + + + +## Quit (removed) + +**Id:** 0<br> +**Introduced:** Nix 0.11<br> +**Removed:** Became dead code in Nix 0.11 and removed in Nix 1.8 + + +## IsValidPath + +**Id:** 1<br> +**Introduced:** Nix 0.11<br> + +As the name says checks that a store path is valid i.e. in the store. + +This is a pretty core operation used everywhere. + + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs +isValid :: [Bool][se-Bool] + + +## HasSubstitutes + +**Id:** 3<br> +**Introduced:** Nix 0.11<br> +**Obsolete** Protocol 1.12, Nix 1.2<br> + +Replaced by QuerySubstitutablePaths. + +Checks if we can substitute the input path from a substituter. Uses +QuerySubstitutablePaths under the hood :/ + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs +hasSubstitutes :: [Bool][se-Bool] + + +## QueryPathHash + +**Id:** 4<br> +**Introduced:** Nix 0.11<br> +**Obsolete:** Protocol 1.16, Nix 2.0<br> + +Retrieves the base16 NAR hash of a given store path. + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs +hash :: [NARHash][se-NARHash] + + +## QueryReferences + +**Id:** 5<br> +**Introduced:** Nix 0.11<br> +**Obsolete:** Protocol 1.16, Nix 2.0<br> + +Retrieves the references of a given path + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs +references :: [Set][se-Set] of [StorePath][se-StorePath] + + +## QueryReferrers + +**Id:** 6<br> +**Introduced:** Nix 0.11<br> + +Retrieves the referrers of a given path. + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs +referrers :: [Set][se-Set] of [StorePath][se-StorePath] + + +## AddToStore + +**Id:** 7<br> +**Introduced:** Nix 0.11<br> + +Add a new path to the store. + +### Before protocol version 1.25 +#### Inputs +- baseName :: [StorePathName][se-StorePathName] +- fixed :: [Bool64][se-Bool64] +- recursive :: [FileIngestionMethod][se-FileIngestionMethod] +- hashAlgo :: [HashAlgorithm][se-HashAlgorithm] +- NAR dump + +If fixed is `true`, hashAlgo is forced to `sha256` and recursive is forced to +`NixArchive`. + +Only `Flat` and `NixArchive` values are supported for the recursive input +parameter. + +#### Outputs +path :: [StorePath][se-StorePath] + +### Protocol version 1.25 or newer +#### Inputs +- name :: [StorePathName][se-StorePathName] +- camStr :: [ContentAddressMethodWithAlgo][se-ContentAddressMethodWithAlgo] +- refs :: [Set][se-Set] of [StorePath][se-StorePath] +- repairBool :: [Bool64][se-Bool64] +- [Framed][se-Framed] NAR dump + +#### Outputs +info :: [ValidPathInfo][se-ValidPathInfo] + + +## AddTextToStore + +**Id:** 8<br> +**Introduced:** Nix 0.11<br> +**Obsolete:** Protocol 1.25, Nix 2.4 + +Add a text file as a store path. + +This was obsoleted by adding the functionality implemented by this operation +to [AddToStore](#addtostore). And so this corresponds to calling +[AddToStore](#addtostore) with `camStr` set to `text:sha256` and `text` +wrapped as a NAR. + +### Inputs +- suffix :: [StorePathName][se-StorePathName] +- text :: [Bytes][se-Bytes] +- refs :: [Set][se-Set] of [StorePath][se-StorePath] + +### Outpus +path :: [StorePath][se-StorePath] + + +## BuildPaths + +**Id:** 9<br> +****Introduced:**** Nix 0.11<br> + +Build (or substitute) a list of derivations. + +### Inputs +paths :: [Set][se-Set] of [DerivedPath][se-DerivedPath] + +#### Protocol 1.15 or newer +mode :: [BuildMode][se-BuildMode] (defaults to Normal) + +Check that connection is trusted before allowing Repair mode. + +### Outputs +1 :: [Int][se-Int] (hardcoded and ignored by client) + + +## EnsurePath + +**Id:** 10<br> +**Introduced:** Nix 0.11<br> + +Checks if a path is valid. Note: it may be made valid by running a substitute. + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs +1 :: [Int][se-Int] (hardcoded and ignored by client) + + +## AddTempRoot + +**Id:** 11<br> +**Introduced:** Nix 0.11<br> + +Creates a temporary GC root for the given store path. + +Temporary GC roots are valid only for the life of the connection and are used +primarily to prevent the GC from pulling the rug out from under the client and +deleting store paths that the client is actively doing something with. + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs +1 :: [Int][se-Int] (hardcoded and ignored by client) + + +## AddIndirectRoot + +**Id:** 12<br> +**Introduced:** Nix 0.11<br> + +Add an indirect root, which is a weak reference to the user-facing symlink +created by [AddPermRoot](#addpermroot). + +Only ever sent on the local unix socket nix daemon. + +### Inputs +path :: [Path][se-Path] + +### Outputs +1 :: [Int][se-Int] (hardcoded and ignored by client) + + +## SyncWithGC + +**Id:** 13<br> +**Introduced:** Nix 0.11<br> +**Obsolete:** Protocol 1.32, Nix 2.5.0 + +Acquire the global GC lock, then immediately release it. This function must be +called after registering a new permanent root, but before exiting. Otherwise, +it is possible that a running garbage collector doesn't see the new root and +deletes the stuff we've just built. By acquiring the lock briefly, we ensure +that either: + +- The collector is already running, and so we block until the + collector is finished. The collector will know about our + *temporary* locks, which should include whatever it is we + want to register as a permanent lock. +- The collector isn't running, or it's just started but hasn't + acquired the GC lock yet. In that case we get and release + the lock right away, then exit. The collector scans the + permanent root and sees ours. + +In either case the permanent root is seen by the collector. + +Was made obsolete by using [AddTempRoot](#addtemproot) to accomplish the same +thing. + + +## FindRoots + +**Id:** 14<br> +**Introduced:** Nix 0.11<br> + +Find the GC roots. + +### Outputs +roots :: [Map][se-Map] of [Path][se-Path] to [StorePath][se-StorePath] + +The key is the link pointing to the given store path. + + +## Old CollectGarbage (removed) + +**Id:** 15<br> +**Introduced:** Nix 0.11<br> +**Removed:** Protocol 1.02, Nix 0.12<br> + + +## ExportPath + +**Id:** 16<br> +**Introduced:** Nix 0.11<br> +**Obsolete:** Protocol 1.17, Nix 2.0<br> + +Export a store path in the binary format nix-store --import expects. See implementation there https://github.com/NixOS/nix/blob/db3bf180a569cb20db42c5e4669d2277be6f46b6/src/libstore/export-import.cc#L29 for more details. + +### Inputs +- path :: [StorePath][se-StorePath] +- sign :: [Int][se-Int] (ignored and hardcoded to 0 in client) + +### Outputs +Uses [`STDERR_WRITE`](./logging.md#stderr_write) to send dump in +[export format][se-ExportFormat] + +After dump it outputs. + +1 :: [Int][se-Int] (hardcoded) + + +## ImportPath (removed) + +**Id:** 17<br> +**Introduced:** Nix 0.11<br> +**Removed:** Protocol 1.09, Nix 1.0<br> + + +## QueryDeriver + +**Id:** 18<br> +**Introduced:** Nix 0.11<br> +**Obsolete:** Protocol 1.16, Nix 2.0<br> + +Returns the store path of the derivation for a given store path. + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs +deriver :: [OptStorePath][se-OptStorePath] + + +## SetOptions + +**Id:** 19<br> +**Introduced:** Nix 0.11<br> + +Sends client options to the remote side. + +Only ever used right after the handshake. + +### Inputs + +- keepFailed :: [Bool][se-Bool] +- keepGoing :: [Bool][se-Bool] +- tryFallback :: [Bool][se-Bool] +- verbosity :: [Verbosity][se-Verbosity] +- maxBuildJobs :: [Int][se-Int] +- maxSilentTime :: [Time][se-Time] +- useBuildHook :: [Bool][se-Bool] (ignored and hardcoded to true in client) +- verboseBuild :: [Verbosity][se-Verbosity] +- logType :: [Int][se-Int] (ignored and hardcoded to 0 in client) +- printBuildTrace :: [Int][se-Int] (ignored and hardcoded to 0 in client) +- buildCores :: [Int][se-Int] +- useSubstitutes :: [Bool][se-Bool] + +### Protocol 1.12 or newer +otherSettings :: [Map][se-Map] of [String][se-String] to [String][se-String] + + +## CollectGarbage + +**Id:** 20<br> +**Introduced:** Protocol 1.02, Nix 0.12<br> + +Find the GC roots. + +### Inputs +- action :: [GCAction][se-GCAction] +- pathsToDelete :: [Set][se-Set] of [StorePath][se-StorePath] +- ignoreLiveness :: [Bool64][se-Bool64] +- maxFreed :: [UInt64][se-UInt64] +- removed :: [Int][se-Int] (ignored and hardcoded to 0 in client) +- removed :: [Int][se-Int] (ignored and hardcoded to 0 in client) +- removed :: [Int][se-Int] (ignored and hardcoded to 0 in client) + +### Outputs +- pathsDeleted :: [Set][se-Set] of [Path][se-Path] +- bytesFreed :: [UInt64][se-UInt64] +- 0 :: [UInt64][se-UInt64] (hardcoded, obsolete and ignored by client) + +Depending on the value of the action input the value of output pathsDeleted +is either, the GC roots, or the paths that would be or have been deleted. + + +## QuerySubstitutablePathInfo + +**Id:** 21<br> +**Introduced:** Protocol 1.02, Nix 0.12<br> +**Obsolete:** Protocol 1.12, Nix 1.2<br> + +Retrieves the various substitutable paths infos for a given path. + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs +found :: [Bool][se-Bool] + +#### If found is true +- info :: [SubstitutablePathInfo][se-SubstitutablePathInfo] + + +## QueryDerivationOutputs + +**Id:** 22<br> +**Introduced:** Protocol 1.05, Nix 1.0<br> +**Obsolete:** Protocol 1.22*, Nix 2.4<br> + +Retrieves all the outputs paths of a given derivation. + +### Inputs +path :: [StorePath][se-StorePath] (must point to a derivation) + +### Outputs +derivationOutputs :: [Set][se-Set] of [StorePath][se-StorePath] + + +## QueryAllValidPaths + +**Id:** 23<br> +**Introduced:** Protocol 1.05, Nix 1.0<br> + +Retrieves all the valid paths contained in the store. + +### Outputs +paths :: [Set][se-Set] of [StorePath][se-StorePath] + + +## QueryFailedPaths (removed) + +**Id:** 24<br> +**Introduced:** Protocol 1.05, Nix 1.0<br> +**Removed:** Protocol 1.16, Nix 2.0<br> + +Failed build caching API only ever used by Hydra. + + +## ClearFailedPaths (removed) + +**Id:** 25<br> +**Introduced:** Protocol 1.05, Nix 1.0<br> +**Removed:** Protocol 1.16, Nix 2.0<br> + +Failed build caching API only ever used by Hydra. + + +## QueryPathInfo + +**Id:** 26<br> +**Introduced:** Protocol 1.06, Nix 1.0<br> + +Retrieves the pathInfo for a given path. + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs + +#### If protocol version is 1.17 or newer +success :: [Bool64][se-Bool64] + +##### If success is true +pathInfo :: [UnkeyedValidPathInfo][se-UnkeyedValidPathInfo] + +#### If protocol version is older than 1.17 +If info not found return error with [`STDERR_ERROR`](./logging.md#stderr_error) + +pathInfo :: [UnkeyedValidPathInfo][se-UnkeyedValidPathInfo] + + +## ImportPaths + +**Id:** 27<br> +**Introduced:** Protocol 1.09, Nix 1.0<br> +**Obsolete:** Protocol 1.17, Nix 2.0<br> + +Older way of adding a store path to the remote store. + +It was obsoleted and replaced by AddToStoreNar because it sends the NAR +before the metadata about the store path and so you would typically have +to store the NAR in memory or temporarily on disk before processing it. + +### Inputs +[List of NAR dumps][se-ImportPaths] coming from one or more ExportPath operations. + +### Outputs +importedPaths :: [List][se-List] of [StorePath][se-StorePath] + + +## QueryDerivationOutputNames + +**Id:** 28<br> +**Introduced:** Protocol 1.08, Nix 1.0<br> +**Obsolete:** Protocol 1.21, Nix 2.4<br> + +Retrieves the name of the outputs of a given derivation. EG. out, dev, etc. + +### Inputs +path :: [StorePath][se-StorePath] (must be a derivation path) + +### Outputs +names :: [Set][se-Set] of [OutputName][se-OutputName] + + +## QueryPathFromHashPart + +**Id:** 29<br> +**Introduced:** Protocol 1.11, Nix 1.1<br> + +Retrieves a store path from a nixbase32 (input) hash. + +### Inputs +hashPart :: [StorePathHash][se-StorePathHash] + +### Outputs +path :: [OptStorePath][se-OptStorePath] + + +## QuerySubstitutablePathInfos + +**Id:** 30<br> +**Introduced:** Protocol 1.12*, Nix 1.2<br> +**Obsolete:** Protocol 1.19*, Nix 2.0<br> + +Retrieves the various substitutable paths infos for set of store paths. + +Only ever used in the fallback for QueryMissing which means that if protocol is 1.19 or later +it is never sent and is therefore obsolete after that. + +### Inputs +#### If protocol version is 1.22 or newer +paths :: [Map][se-Map] of [StorePath][se-StorePath] to [OptContentAddress][se-OptContentAddress] + +#### If protocol version older than 1.22 +paths :: [Set][se-Set] of [StorePath][se-StorePath] + +### Outputs +infos :: [Map][se-Map] of [StorePath][se-StorePath] to [SubstitutablePathInfo][se-SubstitutablePathInfo] + + +## QueryValidPaths + +**Id:** 31<br> +**Introduced:** Protocol 1.12, Nix 1.2<br> + +Takes a list of store paths and returns a new list only containing the valid store paths + +## Inputs +paths :: [Set][se-Set] of [StorePath][se-StorePath] + +### If protocol version is 1.27 or newer +substitute :: [Bool][se-Bool] (defaults to false if not sent) + +## Outputs +paths :: [Set][se-Set] of [StorePath][se-StorePath] + + +## QuerySubstitutablePaths + +**Id:** 32<br> +**Introduced:** Protocol 1.12, Nix 1.2<br> + +Takes a set of store path, returns a filtered new set of paths that can be +substituted. + +In versions of the protocol prior to 1.12 [HasSubstitutes](#hassubstitutes) +is used to implement the functionality that this operation provides. + +### Inputs +paths :: [Set][se-Set] of [StorePath][se-StorePath] + +### Outputs +paths :: [Set][se-Set] of [StorePath][se-StorePath] + + +## QueryValidDerivers + +**Id:** 33<br> +**Introduced:** Protocol 1.13*, Nix 1.3<br> + +Retrieves the derivers of a given path. + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs +derivers :: [Set][se-Set] of [StorePath][se-StorePath] + + +## OptimiseStore + +**Id:** 34<br> +**Introduced:** Protocol 1.14, Nix 1.8<br> + +Optimise store by hardlinking files with the same content. + +### Outputs +1 :: [Int][se-Int] (hardcoded and ignored by client) + + +## VerifyStore + +**Id:** 35<br> +**Introduced:** Protocol 1.14, Nix 1.9<br> + +Verify store either only db and existence of path or entire contents of store +paths against the NAR hash. + +### Inputs +- checkContents :: [Bool64][se-Bool64] +- repair :: [Bool64][se-Bool64] + +### Outputs +errors :: [Bool][se-Bool] + + +## BuildDerivation + +**Id:** 36<br> +**Introduced:** Protocol 1.14, Nix 1.10<br> + +Main build operation used when remote building. + +When functioning as a remote builder this operation is used instead of +BuildPaths so that it doesn't have to send the entire tree of derivations +to the remote side first before it can start building. What this does +instead is have a reduced version of the derivation to be built sent as +part of its input and then only building that derivation. + +The paths required by the build need to be part of the remote store +(by copying with AddToStoreNar or substituting) before this operation is +called. + +### Inputs +- drvPath :: [StorePath][se-StorePath] +- drv :: [BasicDerivation][se-BasicDerivation] +- buildMode :: [BuildMode][se-BuildMode] + +### Outputs +buildResult :: [BuildResult][se-BuildResult] + + +## AddSignatures + +**Id:** 37<br> +**Introduced:** Protocol 1.16, Nix 2.0<br> + +Add the signatures associated to a given path. Used by `nix store copy-sigs` and `nix store sign`. + +### Inputs +- path :: [StorePath][se-StorePath] +- signatures :: [Set][se-Set] of [Signature][se-Signature] + +### Outputs +1 :: [Int][se-Int] (hardcoded and ignored by client) + + +## NarFromPath + +**Id:** 38<br> +**Introduced:** Protocol 1.17, Nix 2.0<br> + +Main way of getting the contents of a store path to the client. + +As the name suggests this is done by sending a NAR file. + +It replaced the now obsolete ExportPath operation and is used by newer clients to +implement the export functionality for cli. It is also used when remote building +to transfer build results from remote builder to client. + +### Inputs +path :: [StorePath][se-StorePath] + +### Outputs +NAR dumped straight to the stream. + + +## AddToStoreNar + +**Id:** 39<br> +**Introduced:** Protocol 1.17, Nix 2.0<br> + +Dumps a path as a NAR + +### Inputs +- path :: [StorePath][se-StorePath] +- deriver :: [OptStorePath][se-OptStorePath] +- narHash :: [NARHash][se-NARHash] +- references :: [Set][se-Set] of [StorePath][se-StorePath] +- registrationTime :: [Time][se-Time] +- narSize :: [UInt64][se-UInt64] +- ultimate :: [Bool64][se-Bool64] +- signatures :: [Set][se-Set] of [Signature][se-Signature] +- ca :: [OptContentAddress][se-OptContentAddress] +- repair :: [Bool64][se-Bool64] +- dontCheckSigs :: [Bool64][se-Bool64] + +#### If protocol version is 1.23 or newer +[Framed][se-Framed] NAR dump + +#### If protocol version is between 1.21 and 1.23 +NAR dump sent using [`STDERR_READ`](./logging.md#stderr_read) + +#### If protocol version is older than 1.21 +NAR dump sent raw on stream + + +## QueryMissing + +**Id:** 40<br> +**Introduced:** Protocol 1.19*, Nix 2.0<br> + +### Inputs +targets :: [List][se-List] of [DerivedPath][se-DerivedPath] + +### Outputs +- willBuild :: [Set][se-Set] of [StorePath][se-StorePath] +- willSubstitute :: [Set][se-Set] of [StorePath][se-StorePath] +- unknown :: [Set][se-Set] of [StorePath][se-StorePath] +- downloadSize :: [UInt64][se-UInt64] +- narSize :: [UInt64][se-UInt64] + + +## QueryDerivationOutputMap + +**Id:** 41<br> +**Introduced:** Protocol 1.22*, Nix 2.4<br> + +Retrieves an associative map outputName -> storePath for a given derivation. + +### Inputs +path :: [StorePath][se-StorePath] (must be a derivation path) + +### Outputs +outputs :: [Map][se-Map] of [OutputName][se-OutputName] to [OptStorePath][se-OptStorePath] + + +## RegisterDrvOutput + +**Id:** 42<br> +**Introduced:** Protocol 1.27, Nix 2.4<br> + +Registers a DRV output + +### Inputs +#### If protocol is 1.31 or newer +realisation :: [Realisation][se-Realisation] + +#### If protocol is older than 1.31 +- outputId :: [DrvOutput][se-DrvOutput] +- outputPath :: [StorePath][se-StorePath] + + +## QueryRealisation + +**Id:** 43<br> +**Introduced:** Protocol 1.27, Nix 2.4<br> + +Retrieves the realisations attached to a drv output id realisations. + +### Inputs +outputId :: [DrvOutput][se-DrvOutput] + +### Outputs +#### If protocol is 1.31 or newer +realisations :: [Set][se-Set] of [Realisation][se-Realisation] + +#### If protocol is older than 1.31 +outPaths :: [Set][se-Set] of [StorePath][se-StorePath] + + +## AddMultipleToStore + +**Id:** 44<br> +**Introduced:** Protocol 1.32*, Nix 2.4<br> + +A pipelined version of [AddToStoreNar](#addtostorenar) where you can add +multiple paths in one go. + +Added because the protocol doesn't support pipelining and so on a low latency +connection waiting for the request/response of [AddToStoreNar](#addtostorenar) +for each small NAR was costly. + +### Inputs +- repair :: [Bool64][se-Bool64] +- dontCheckSigs :: [Bool64][se-Bool64] +- [Framed][se-Framed] stream of [add multiple NAR dump][se-AddMultipleToStore] + + +## AddBuildLog + +**Id:** 45<br> +**Introduced:** Protocol 1.32, Nix 2.6.0<br> + +Attach some build logs to a given build. + +### Inputs +- path :: [BaseStorePath][se-BaseStorePath] +- [Framed][se-Framed] stream of log lines + +### Outputs +1 :: [Int][se-Int] (hardcoded and ignored by client) + + +## BuildPathsWithResults + +**Id:** 46<br> +**Introduced:** Protocol 1.34*, Nix 2.8.0<br> + +Build (or substitute) a list of derivations and returns a list of results. + +### Inputs +- drvs :: [List][se-List] of [DerivedPath][se-DerivedPath] +- mode :: [BuildMode][se-BuildMode] + +### Outputs +results :: [List][se-List] of [KeyedBuildResult][se-KeyedBuildResult] + + +## AddPermRoot + +**Id:** 47<br> +**Introduced:** Protocol 1.36*, Nix 2.20.0<br> + +### Inputs +- storePath :: [StorePath][se-StorePath] +- gcRoot :: [Path][se-Path] + +### Outputs +gcRoot :: [Path][se-Path] + + + +[se-Int]: ./serialization.md#int +[se-UInt8]: ./serialization.md#uint8 +[se-UInt64]: ./serialization.md#uint64 +[se-Bool]: ./serialization.md#bool +[se-Bool64]: ./serialization.md#bool64 +[se-Time]: ./serialization.md#time +[se-FileIngestionMethod]: ./serialization.md#fileingestionmethod +[se-BuildMode]: ./serialization.md#buildmode +[se-Verbosity]: ./serialization.md#verbosity +[se-GCAction]: ./serialization.md#gcaction +[se-Bytes]: ./serialization.md#bytes +[se-String]: ./serialization.md#string +[se-StorePath]: ./serialization.md#storepath +[se-BaseStorePath]: ./serialization.md#basestorepath +[se-OptStorePath]: ./serialization.md#optstorepath +[se-ContentAddressMethodWithAlgo]: ./serialization.md#contentaddressmethodwithalgo +[se-OptContentAddress]: ./serialization.md#optcontentaddress +[se-DerivedPath]: ./serialization.md#derivedpath +[se-DrvOutput]: ./serialization.md#drvoutput +[se-Realisation]: ./serialization.md#realisation +[se-List]: ./serialization.md#list-of-x +[se-Set]: ./serialization.md#set-of-x +[se-Map]: ./serialization.md#map-of-x-to-y +[se-SubstitutablePathInfo]: ./serialization.md#substitutablepathinfo +[se-ValidPathInfo]: ./serialization.md#validpathinfo +[se-UnkeyedValidPathInfo]: ./serialization.md#unkeyedvalidpathinfo +[se-BuildResult]: ./serialization.md#buildmode +[se-KeyedBuildResult]: ./serialization.md#keyedbuildresult +[se-BasicDerivation]: ./serialization.md#basicderivation +[se-Framed]: ./serialization.md#framed +[se-AddMultipleToStore]: ./serialization.md#addmultipletostore-format +[se-ExportFormat]: ./serialization.md#export-path-format +[se-ImportPaths]: ./serialization.md#import-paths-format \ No newline at end of file diff --git a/tvix/docs/src/nix-daemon/serialization.md b/tvix/docs/src/nix-daemon/serialization.md new file mode 100644 index 000000000000..1042c956ba71 --- /dev/null +++ b/tvix/docs/src/nix-daemon/serialization.md @@ -0,0 +1,409 @@ + +### UInt64 +Little endian byte order + +### Bytes + +- len :: [UInt64](#uint64) +- len bytes of content +- padding with zeros to ensure 64 bit alignment of content + padding + + +## Int serializers + +### Int +[UInt64](#uint64) cast to C `unsigned int` with upper bounds checking. + +### Int64 +[UInt64](#uint64) cast to C `int64_t` with upper bounds checking. +This means that negative numbers can be written but not read. +Since this is only used for cpuSystem and cpuUser it is fine that +negative numbers aren't supported. + +### UInt8 +[UInt64](#uint64) cast to C `uint8_t` with upper bounds checking. + +### Size +[UInt64](#uint64) cast to C `size_t` with upper bounds checking. + +### Time +[UInt64](#uint64) cast to C `time_t` with upper bounds checking. +This means that negative numbers can be written but not read. + +### Bool +Sent as an [Int](#int) where 0 is false and everything else is true. + +### Bool64 +Sent as an [UInt64](#uint64) where 0 is false and everything else is true. + +### FileIngestionMethod +An [UInt8](#uint8) enum with the following possible values: + +| Name | Int | +| ---------- | --- | +| Flat | 0 | +| NixArchive | 1 | + +### BuildMode +An [Int](#int) enum with the following possible values: + +| Name | Int | +| ------ | --- | +| Normal | 0 | +| Repair | 1 | +| Check | 2 | + +### Verbosity +An [Int](#int) enum with the following possible values: + +| Name | Int | +| --------- | --- | +| Error | 0 | +| Warn | 1 | +| Notice | 2 | +| Info | 3 | +| Talkative | 4 | +| Chatty | 5 | +| Debug | 6 | +| Vomit | 7 | + +### GCAction +An [Int](#int) enum with the following possible values: + +| Name | Int | +| -------------- | --- | +| ReturnLive | 0 | +| ReturnDead | 1 | +| DeleteDead | 2 | +| DeleteSpecific | 3 | + +### BuildStatus +An [Int](#int) enum with the following possible values: + +| Name | Int | +| ---------------------- | --- | +| Built | 0 | +| Substituted | 1 | +| AlreadyValid | 2 | +| PermanentFailure | 3 | +| InputRejected | 4 | +| OutputRejected | 5 | +| TransientFailure | 6 | +| CachedFailure | 7 | +| TimedOut | 8 | +| MiscFailure | 9 | +| DependencyFailed | 10 | +| LogLimitExceeded | 11 | +| NotDeterministic | 12 | +| ResolvesToAlreadyValid | 13 | +| NoSubstituters | 14 | + +### ActivityType +An [Int](#int) enum with the following possible values: + +| Name | Int | +| ------------- | --- | +| Unknown | 0 | +| CopyPath | 100 | +| FileTransfer | 101 | +| Realise | 102 | +| CopyPaths | 103 | +| Builds | 104 | +| Build | 105 | +| OptimiseStore | 106 | +| VerifyPaths | 107 | +| Substitute | 108 | +| QueryPathInfo | 109 | +| PostBuildHook | 110 | +| BuildWaiting | 111 | +| FetchTree | 112 | + +### ResultType +An [Int](#int) enum with the following possible values: + +| Name | Int | +| ---------------- | --- | +| FileLinked | 100 | +| BuildLogLine | 101 | +| UntrustedPath | 102 | +| CorruptedPath | 103 | +| SetPhase | 104 | +| Progress | 105 | +| SetExpected | 106 | +| PostBuildLogLine | 107 | +| FetchStatus | 108 | + +### FieldType +An [Int](#int) enum with the following possible values: + +| Name | Int | +| ------ | --- | +| Int | 0 | +| String | 1 | + +### OptTrusted +An [UInt8](#uint8) optional enum with the following possible values: + +| Name | Int | +| ---------------- | --- | +| None | 0 | +| Some(Trusted) | 1 | +| Some(NotTrusted) | 2 | + + +## Bytes serializers + +### String +Simply a [Bytes](#bytes) that has some UTF-8 string like semantics sometimes. + +### StorePath +[String](#string) representation of a full store path including the store directory. + +### BaseStorePath +[String](#string) representation of the basename of a store path. That is the store path +without the /nix/store prefix. + +### StorePathName +[String](#string) representation of the name part of a base store path. This is the part +of the store path after the nixbase32 hash and '-' + +It must have the following format: +- Deny ".", "..", or those strings followed by '-' +- Otherwise check that each character is 0-9, a-z, A-Z or one of +-._?= + +### StorePathHash +[String](#string) representation of the hash part of a base store path. This is the part +of the store path at the beginning and before the '-' and is in nixbase32 format. + + +### OutputName +[String](#string) representation of the name of a derivation output. +This is usually combined with the name in the derivation to form the store path name for the +store path with this output. + +Since output name is usually combined to form a store path name its format must follow the +same rules as [StorePathName](#storepathname): +- Deny ".", "..", or those strings followed by '-' +- Otherwise check that each character is 0-9, a-z, A-Z or one of +-._?= + + +### OptStorePath +Optional store path. + +If no store path this is serialized as the empty string otherwise it is the same as +[StorePath](#storepath). + +### Path +[String](#string) representation of an absolute path. + +### NARHash +[String](#string) base16-encoded NAR SHA256 hash without algorithm prefix. + +### Signature +[String](#string) with a signature for the given store path or realisation. This should be +in the format `name`:`base 64 encoded signature` but this is not enforced in the protocol. + +### HashAlgorithm +[String](#string) with one of the following values: +- md5 +- sha1 +- sha256 +- sha512 + +### HashDigest +[String](#string) with a hash digest in any encoding + +### OptHashDigest +Optional version of [HashDigest](#hashdigest) where empty string means +no value. + + +### ContentAddressMethodWithAlgo +[String](#string) with one of the following formats: +- text:[HashAlgorithm](#hashalgorithm) +- fixed:r:[HashAlgorithm](#hashalgorithm) +- fixed:[HashAlgorithm](#hashalgorithm) + +### OptContentAddressMethodWithAlgo +Optional version of [ContentAddressMethodWithAlgo](#contentaddressmethodwithalgo) +where empty string means no value. + +### ContentAddress +[String](#string) with the format: +- [ContentAddressMethodWithAlgo](#contentaddressmethodwithalgo):[HashDigest](#hashdigest) + +### OptContentAddress +Optional version of [ContentAddress](#contentaddress) where empty string means +no content address. + +### DerivedPath +#### If protocol is 1.30 or newer +output-names = [OutputName](#outputname), { "," [OutputName](#outputname) }<br> +output-spec = "*" | output-names<br> +derived-path = [StorePath](#storepath), [ "!", output-spec ]<br> + +#### If protocol is older than 1.30 +[StorePath](#storepath), [ "!", [OutputName](#outputname), { "," [OutputName](#outputname) } ] + +### DrvOutput +[String](#string) with format: +- `hash with any prefix` "!" [OutputName](#outputname) + +### Realisation +A JSON object sent as a [String](#string). + +The JSON object has the following keys: +| Key | Value | +| --------------------- | -------------------------------- | +| id | [DrvOutput](#drvoutput) | +| outPath | [StorePath](#storepath) | +| signatures | Array of [Signature](#signature) | +| dependentRealisations | Object where key is [DrvOutput](#drvoutput) and value is [StorePath](#storepath) | + + +## Complex serializers + +### List of x +A list is encoded as a [Size](#size) length n followed by n encodings of x + +### Map of x to y +A map is encoded as a [Size](#size) length n followed by n encodings of pairs of x and y + +### Set of x +A set is encoded as a [Size](#size) length n followed by n encodings of x + +### BuildResult +- status :: [BuildStatus](#buildstatus) +- errorMsg :: [String](#string) + +#### Protocol 1.29 or newer +- timesBuilt :: [Int](#int) (defaults to 0) +- isNonDeterministic :: [Bool64](#bool64) (defaults to false) +- startTime :: [Time](#time) (defaults to 0) +- stopTime :: [Time](#time) (defaults to 0) + +#### Protocol 1.37 or newer +- cpuUser :: [OptMicroseconds](#optmicroseconds) (defaults to none) +- cpuSystem :: [OptMicroseconds](#optmicroseconds) (defaults to none) + +#### Protocol 1.28 or newer +builtOutputs :: [Map](#map-of-x-to-y) of [DrvOutput](#drvoutput) to [Realisation](#realisations) + +### KeyedBuildResult +- path :: [DerivedPath](#derivedpath) +- result :: [BuildResult](#buildresult) + +### OptMicroseconds +Optional microseconds. + +- tag :: [UInt8](#uint8) + +#### If tag is 1 +- seconds :: [Int64](#int64) + + +### SubstitutablePathInfo +- deriver :: [OptStorePath](#optstorepath) +- references :: [Set][#set-of-x] of [StorePath](#storepath) +- downloadSize :: [UInt64](#uint64) +- narSize :: [UInt64](#uint64) + + +### UnkeyedValidPathInfo +- deriver :: [OptStorePath](#optstorepath) +- narHash :: [NARHash](#narhash) +- references :: [Set](#set-of-x) of [StorePath](#storepath) +- registrationTime :: [Time](#time) +- narSize :: [UInt64](#uint64) + +#### If protocol version is 1.16 or above +- ultimate :: [Bool64](#bool64) (defaults to false) +- signatures :: [Set](#set-of-x) of [Signature](#signature) +- ca :: [OptContentAddress](#optcontentaddress) + + +### ValidPathInfo +- path :: [StorePath](#storepath) +- info :: [UnkeyedValidPathInfo](#unkeyedvalidpathinfo) + +### DerivationOutput +- path :: [OptStorePath](#optstorepath) +- hashAlgo :: [OptContentAddressMethodWithAlgo](#optcontentaddressmethodwithalgo) +- hash :: [OptHashDigest](#opthashdigest) + +### BasicDerivation +- outputs :: [Map](#map-of-x-to-y) of [OutputName](#outputname) to [DerivationOutput](#derivationoutput) +- inputSrcs :: [Set](#set-of-x) of [StorePath](#storepath) +- platform :: [String](#string) +- builder :: [String](#string) +- args :: [List](#list-of-x) of [String](#string) +- env :: [Map](#map-of-x-to-y) of [String](#string) to [String](#string) + +### TraceLine +- havePos :: [Size](#size) (hardcoded to 0) +- hint :: [String](#string) (If logger is JSON, invalid UTF-8 is replaced with U+FFFD) + +### Error +- type :: [String](#string) (hardcoded to `Error`) +- level :: [Verbosity](#verbosity) +- name :: [String](#string) (removed and hardcoded to `Error`) +- msg :: [String](#string) (If logger is JSON, invalid UTF-8 is replaced with U+FFFD) +- havePos :: [Size](#size) (hardcoded to 0) +- traces :: [List](#list-of-x) of [TraceLine](#traceline) + +## Field +- type :: [FieldType](#fieldtype) + +### If type is Int +- value :: [UInt64](#uint64) + +### If type is String +- value :: [String](#string) + + +## Framed + +At protocol 1.23 [AddToStoreNar](./operations.md#addtostorenar) introduced a +framed streaming for sending the NAR dump and later versions of the protocol +also used this framing for other operations. + +At its core the framed streaming is just a series of [UInt64](#uint64) `size` +followed by `size` bytes. The stream is terminated when `size` is zero. + +Unlike [Bytes](#bytes), frames are *NOT* padded. + +This method of sending data has the advantage of not having to parse the data +to find where it ends. Older versions of the protocol would potentially parse +the NAR twice. + + +## AddMultipleToStore format + +Paths must be topologically sorted. + +- expected :: [UInt64](#uint64) + +### Repeated expected times +- info :: [ValidPathInfo](#validpathinfo) +- NAR dump + + +## Export path format +- NAR dump +- 0x4558494es :: [Int](#int) (hardcoded, 'EXIN' in ASCII) +- path :: [StorePath](#storepath) +- references :: [Set](#set-of-x) of [StorePath](#storepath) +- deriver :: [OptStorePath](#optstorepath) +- hasSignature :: [Int](#int) (hardcoded to 0 in newer versions) + +#### If hasSignature is 1 +- signature :: [String](#string) (ignored) + + +## Import paths format + +- hasNext :: [UInt64](#uint64) + +### While hasNext is 1 +- [Export path format](#export-path-format) +- hasNext :: [UInt64](#uint64) diff --git a/tvix/store/docs/api.md b/tvix/docs/src/store/api.md index c1dacc89a598..89495a0d1c32 100644 --- a/tvix/store/docs/api.md +++ b/tvix/docs/src/store/api.md @@ -1,11 +1,10 @@ -tvix-[ca]store API -============== +# tvix-[ca]store API This document outlines the design of the API exposed by tvix-castore and tvix- store, as well as other implementations of this store protocol. This document is meant to be read side-by-side with -[castore.md](../../tvix-castore/docs/castore.md) which describes the data model +[Data Model](../castore/data-model.md) which describes the data model in more detail. The store API has four main consumers: @@ -205,7 +204,7 @@ and potentially a chain of `Directory` objects requested from When the desired file is reached, the *BlobService* can be used to read the contents of this file, and return it back to the evaluator. -FUTUREWORK: define how importing from symlinks should/does work. +FUTUREWORK: Define how importing from symlinks should/does work. Contrary to Nix, this has the advantage of not having to copy all of the contents of a store path to the evaluating machine, but really only fetching diff --git a/tvix/docs/src/value-pointer-equality.md b/tvix/docs/src/value-pointer-equality.md index d84efcb50ca9..a4539513ef73 100644 --- a/tvix/docs/src/value-pointer-equality.md +++ b/tvix/docs/src/value-pointer-equality.md @@ -47,8 +47,10 @@ works in C++ Nix, the only production ready Nix implementation currently availab ## Nix (Pointer) Equality in C++ Nix -TIP: The summary presented here is up-to-date as of 2023-06-27 and was tested -with Nix 2.3, 2.11 and 2.15. +```admonish info +The summary presented here is up-to-date as of 2023-06-27 and was tested with +Nix 2.3, 2.11 and 2.15. +``` ### `EvalState::eqValues` and `ExprOpEq::eval` diff --git a/tvix/eval/Cargo.toml b/tvix/eval/Cargo.toml index 677ce6ab85be..c413e1780f21 100644 --- a/tvix/eval/Cargo.toml +++ b/tvix/eval/Cargo.toml @@ -8,40 +8,42 @@ name = "tvix_eval" [dependencies] builtin-macros = { path = "./builtin-macros", package = "tvix-eval-builtin-macros" } -bytes = "1.4.0" -bstr = { version = "1.8.0", features = ["serde"] } -codemap = "0.1.3" -codemap-diagnostic = "0.1.1" -dirs = "4.0.0" -genawaiter = { version = "0.99.1", default_features = false } -imbl = { version = "2.0", features = [ "serde" ] } -itertools = "0.12.0" -lazy_static = "1.4.0" -lexical-core = { version = "0.8.5", features = ["format", "parse-floats"] } -os_str_bytes = { version = "6.3", features = ["conversions"] } -path-clean = "0.1" -proptest = { version = "1.3.0", default_features = false, features = ["std", "alloc", "tempfile"], optional = true } -regex = "1.6.0" -rnix = "0.11.0" -rowan = "*" # pinned by rnix -serde = { version = "1.0", features = [ "rc", "derive" ] } -serde_json = "1.0" -smol_str = "0.2.0" -tabwriter = "1.2" -test-strategy = { version = "0.2.1", optional = true } +bytes = { workspace = true } +bstr = { workspace = true, features = ["serde"] } +codemap = { workspace = true } +codemap-diagnostic = { workspace = true } +dirs = { workspace = true } +genawaiter = { workspace = true } +itertools = { workspace = true } +lexical-core = { workspace = true, features = ["format", "parse-floats"] } +os_str_bytes = { workspace = true, features = ["conversions"] } +path-clean = { workspace = true } +proptest = { workspace = true, features = ["std", "alloc", "tempfile"], optional = true } +regex = { workspace = true } +rnix = { workspace = true } +rowan = { workspace = true } # pinned by rnix +serde = { workspace = true, features = ["rc", "derive"] } +serde_json = { workspace = true } +smol_str = { workspace = true } +tabwriter = { workspace = true } +test-strategy = { workspace = true, optional = true } toml = "0.6.0" -xml-rs = "0.8.4" -sha2 = "0.10.8" -sha1 = "0.10.6" -md-5 = "0.10.6" -data-encoding = "2.5.0" +sha2 = { workspace = true } +sha1 = { workspace = true } +md-5 = { workspace = true } +data-encoding = { workspace = true } +rustc-hash = { workspace = true } +nohash-hasher = { workspace = true } +vu128 = { workspace = true } +thiserror.workspace = true [dev-dependencies] -criterion = "0.5" -itertools = "0.12.0" -pretty_assertions = "1.2.1" -rstest = "0.19.0" -tempfile = "3.3.0" +criterion = { workspace = true } +itertools = { workspace = true } +mimalloc = { workspace = true } +pretty_assertions = { workspace = true } +rstest = { workspace = true } +tempfile = { workspace = true } [features] default = ["impure", "arbitrary", "nix_tests"] @@ -54,7 +56,12 @@ nix_tests = [] impure = [] # Enables Arbitrary impls for internal types (required to run tests) -arbitrary = ["proptest", "test-strategy", "imbl/proptest"] +arbitrary = ["proptest", "test-strategy"] + +# Don't leak strings (enable this if you care about peak memory usage of eval) +# +# This is intended as a stop-gap until we have a garbage collector +no_leak = [] [[bench]] name = "eval" diff --git a/tvix/eval/benches/eval.rs b/tvix/eval/benches/eval.rs index 57d4eb71b59f..f4d6489f1e5c 100644 --- a/tvix/eval/benches/eval.rs +++ b/tvix/eval/benches/eval.rs @@ -1,8 +1,14 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use itertools::Itertools; +use mimalloc::MiMalloc; + +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; fn interpret(code: &str) { - tvix_eval::Evaluation::new_pure().evaluate(code, None); + tvix_eval::Evaluation::builder_pure() + .build() + .evaluate(code, None); } fn eval_literals(c: &mut Criterion) { diff --git a/tvix/eval/build.rs b/tvix/eval/build.rs index a9c9a78b060d..b37a6e8a0c8d 100644 --- a/tvix/eval/build.rs +++ b/tvix/eval/build.rs @@ -5,5 +5,10 @@ fn main() { "cargo:rustc-env=TVIX_CURRENT_SYSTEM={}", &env::var("TARGET").unwrap() ); - println!("cargo:rerun-if-changed-env=TARGET") + println!("cargo:rerun-if-changed-env=TARGET"); + + // Pick up new test case files + // https://github.com/la10736/rstest/issues/256 + println!("cargo:rerun-if-changed=src/tests/nix_tests"); + println!("cargo:rerun-if-changed=src/tests/tvix_tests") } diff --git a/tvix/eval/builtin-macros/Cargo.toml b/tvix/eval/builtin-macros/Cargo.toml index 3a35ea12a0c0..0696d742b342 100644 --- a/tvix/eval/builtin-macros/Cargo.toml +++ b/tvix/eval/builtin-macros/Cargo.toml @@ -5,9 +5,9 @@ authors = [ "Griffin Smith <root@gws.fyi>" ] edition = "2021" [dependencies] -syn = { version = "1.0.57", features = ["full", "parsing", "printing", "visit", "visit-mut", "extra-traits"] } -quote = "1.0.8" -proc-macro2 = "1" +syn = { version = "1.0.109", features = ["full", "parsing", "printing", "visit", "visit-mut", "extra-traits"] } +quote = { workspace = true } +proc-macro2 = { workspace = true } [lib] proc-macro = true diff --git a/tvix/eval/builtin-macros/src/lib.rs b/tvix/eval/builtin-macros/src/lib.rs index 5cc9807f54fe..9b14aee44605 100644 --- a/tvix/eval/builtin-macros/src/lib.rs +++ b/tvix/eval/builtin-macros/src/lib.rs @@ -281,31 +281,45 @@ pub fn builtins(args: TokenStream, item: TokenStream) -> TokenStream { let ty = &arg.ty; let ident = &arg.name; - if arg.strict { - if arg.catch { - f.block = Box::new(parse_quote_spanned! {arg.span=> { - let #ident: #ty = tvix_eval::generators::request_force(&co, values.pop() - .expect("Tvix bug: builtin called with incorrect number of arguments")).await; + f.block = Box::new(match arg { + BuiltinArgument { + strict: true, + catch: true, + .. + } => parse_quote_spanned! { + arg.span => { + let #ident: #ty = tvix_eval::generators::request_force( + &co, values.pop().expect("Tvix bug: builtin called with incorrect number of arguments") + ).await; #block - }}); - } else { - f.block = Box::new(parse_quote_spanned! {arg.span=> { - let #ident: #ty = tvix_eval::generators::request_force(&co, values.pop() - .expect("Tvix bug: builtin called with incorrect number of arguments")).await; + } + }, + BuiltinArgument { + strict: true, + catch: false, + .. + } => parse_quote_spanned! { + arg.span => { + let #ident: #ty = tvix_eval::generators::request_force( + &co, values.pop().expect("Tvix bug: builtin called with incorrect number of arguments") + ).await; if #ident.is_catchable() { return Ok(#ident); } #block - }}); - } - } else { - f.block = Box::new(parse_quote_spanned! {arg.span=> { - let #ident: #ty = values.pop() - .expect("Tvix bug: builtin called with incorrect number of arguments"); - - #block - }}) - } + } + }, + BuiltinArgument { + strict: false, + catch: _, + .. + } => parse_quote_spanned! { + arg.span => { + let #ident: #ty = values.pop().expect("Tvix bug: builtin called with incorrect number of arguments"); + #block + } + }, + }); } let fn_name = f.sig.ident.clone(); diff --git a/tvix/eval/clippy.toml b/tvix/eval/clippy.toml new file mode 100644 index 000000000000..c5302112b3ae --- /dev/null +++ b/tvix/eval/clippy.toml @@ -0,0 +1,3 @@ +# See https://nnethercote.github.io/perf-book/hashing.html. Use FxHashMap and +# FxHashSet, not HashMap and HashSet +disallowed-types = ["std::collections::HashMap", "std::collections::HashSet"] diff --git a/tvix/eval/default.nix b/tvix/eval/default.nix index 91661291f7b6..9370c81ced1c 100644 --- a/tvix/eval/default.nix +++ b/tvix/eval/default.nix @@ -1,9 +1,16 @@ # TODO: find a way to build the benchmarks via crate2nix -{ depot, pkgs, ... }: +{ depot, pkgs, lib, ... }: -depot.tvix.crates.workspaceMembers.tvix-eval.build.override { +(depot.tvix.crates.workspaceMembers.tvix-eval.build.override { runTests = true; # Make C++ Nix available, to compare eval results against. testInputs = [ pkgs.nix ]; -} +}).overrideAttrs (old: rec { + meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { + inherit (old) crateName; + features = [ "nix_tests" ]; + override.testInputs = [ pkgs.nix ]; + }); +}) diff --git a/tvix/eval/src/builtins/impure.rs b/tvix/eval/src/builtins/impure.rs index c82b910f5ffa..dccb7fbb7d8a 100644 --- a/tvix/eval/src/builtins/impure.rs +++ b/tvix/eval/src/builtins/impure.rs @@ -9,7 +9,6 @@ use std::{ use crate::{ self as tvix_eval, errors::ErrorKind, - io::FileType, value::NixAttrs, vm::generators::{self, GenCo}, NixString, Value, @@ -60,12 +59,7 @@ mod impure_builtins { NixString::from( String::from_utf8(name.to_vec()).expect("parsing file name as string"), ), - Value::from(match ftype { - FileType::Directory => "directory", - FileType::Regular => "regular", - FileType::Symlink => "symlink", - FileType::Unknown => "unknown", - }), + Value::from(ftype.to_string()), ) }); @@ -87,6 +81,18 @@ mod impure_builtins { } } } + + #[builtin("readFileType")] + async fn builtin_read_file_type(co: GenCo, path: Value) -> Result<Value, ErrorKind> { + match coerce_value_to_path(&co, path).await? { + Err(cek) => Ok(Value::from(cek)), + Ok(path) => Ok(Value::from( + generators::request_read_file_type(&co, path) + .await + .to_string(), + )), + } + } } /// Return all impure builtins, that is all builtins which may perform I/O diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs index 04a0b3dd33ea..f130bbc5b15f 100644 --- a/tvix/eval/src/builtins/mod.rs +++ b/tvix/eval/src/builtins/mod.rs @@ -6,11 +6,10 @@ use bstr::{ByteSlice, ByteVec}; use builtin_macros::builtins; use genawaiter::rc::Gen; -use imbl::OrdMap; use regex::Regex; use std::cmp::{self, Ordering}; +use std::collections::BTreeMap; use std::collections::VecDeque; -use std::collections::{BTreeMap, HashSet}; use std::path::PathBuf; use crate::arithmetic_op; @@ -85,9 +84,9 @@ mod pure_builtins { use std::ffi::OsString; use bstr::{BString, ByteSlice, B}; - use imbl::Vector; use itertools::Itertools; use os_str_bytes::OsStringBytes; + use rustc_hash::FxHashSet; use crate::{value::PointerEquality, AddContext, NixContext, NixContextElement}; @@ -245,7 +244,7 @@ mod pure_builtins { #[builtin("concatLists")] async fn builtin_concat_lists(co: GenCo, lists: Value) -> Result<Value, ErrorKind> { - let mut out = imbl::Vector::new(); + let mut out = Vec::new(); for value in lists.to_list()? { let list = try_value!(generators::request_force(&co, value).await).to_list()?; @@ -258,7 +257,7 @@ mod pure_builtins { #[builtin("concatMap")] async fn builtin_concat_map(co: GenCo, f: Value, list: Value) -> Result<Value, ErrorKind> { let list = list.to_list()?; - let mut res = imbl::Vector::new(); + let mut res = Vec::new(); for val in list { let out = generators::request_call_with(&co, f.clone(), [val]).await; let out = try_value!(generators::request_force(&co, out).await); @@ -274,9 +273,10 @@ mod pure_builtins { list: Value, ) -> Result<Value, ErrorKind> { let mut separator = separator.to_contextful_str()?; + let mut context = NixContext::new(); - if let Some(sep_context) = separator.context_mut() { - context = context.join(sep_context); + if let Some(sep_context) = separator.take_context() { + context.extend(sep_context.into_iter()) } let list = list.to_list()?; let mut res = BString::default(); @@ -296,13 +296,8 @@ mod pure_builtins { { Ok(mut s) => { res.push_str(&s); - if let Some(ref mut other_context) = s.context_mut() { - // It is safe to consume the other context here - // because the `list` and `separator` are originally - // moved, here. - // We are not going to use them again - // because the result here is a string. - context = context.join(other_context); + if let Some(other_context) = s.take_context() { + context.extend(other_context.into_iter()); } } Err(c) => return Ok(Value::Catchable(Box::new(c))), @@ -390,13 +385,13 @@ mod pure_builtins { #[builtin("filter")] async fn builtin_filter(co: GenCo, pred: Value, list: Value) -> Result<Value, ErrorKind> { let list: NixList = list.to_list()?; - let mut out = imbl::Vector::new(); + let mut out = Vec::new(); for value in list { let result = generators::request_call_with(&co, pred.clone(), [value.clone()]).await; let verdict = try_value!(generators::request_force(&co, result).await); if verdict.as_bool()? { - out.push_back(value); + out.push(value); } } @@ -469,15 +464,6 @@ mod pure_builtins { toml::from_str(toml_str.to_str()?).map_err(|err| err.into()) } - #[builtin("filterSource")] - #[allow(non_snake_case)] - async fn builtin_filterSource(_co: GenCo, #[lazy] _e: Value) -> Result<Value, ErrorKind> { - // TODO: implement for nixpkgs compatibility - Ok(Value::from(CatchableErrorKind::UnimplementedFeature( - "filterSource".into(), - ))) - } - #[builtin("genericClosure")] async fn builtin_generic_closure(co: GenCo, input: Value) -> Result<Value, ErrorKind> { let attrs = input.to_attrs()?; @@ -493,7 +479,7 @@ mod pure_builtins { let operator = attrs.select_required("operator")?; - let mut res = imbl::Vector::new(); + let mut res = Vec::new(); let mut done_keys: Vec<Value> = vec![]; while let Some(val) = work_set.pop_front() { @@ -511,7 +497,7 @@ mod pure_builtins { continue; } - res.push_back(val.clone()); + res.push(val.clone()); let op_result = generators::request_force( &co, @@ -532,18 +518,18 @@ mod pure_builtins { #[lazy] generator: Value, length: Value, ) -> Result<Value, ErrorKind> { - let mut out = imbl::Vector::<Value>::new(); let len = length.as_int()?; + let mut out = Vec::with_capacity( + len.try_into() + .map_err(|_| ErrorKind::Abort(format!("can not create list of size {}", len)))?, + ); + // the best span we can get… let span = generators::request_span(&co).await; for i in 0..len { - let val = Value::Thunk(Thunk::new_suspended_call( - generator.clone(), - i.into(), - span.clone(), - )); - out.push_back(val); + let val = Value::Thunk(Thunk::new_suspended_call(generator.clone(), i.into(), span)); + out.push(val); } Ok(Value::List(out.into())) @@ -564,7 +550,7 @@ mod pure_builtins { #[builtin("groupBy")] async fn builtin_group_by(co: GenCo, f: Value, list: Value) -> Result<Value, ErrorKind> { - let mut res: BTreeMap<NixString, imbl::Vector<Value>> = BTreeMap::new(); + let mut res: BTreeMap<NixString, Vec<Value>> = BTreeMap::new(); for val in list.to_list()? { let key = try_value!( generators::request_force( @@ -575,7 +561,7 @@ mod pure_builtins { ) .to_str()?; - res.entry(key).or_default().push_back(val); + res.entry(key).or_default().push(val); } Ok(Value::attrs(NixAttrs::from_iter( res.into_iter() @@ -641,7 +627,7 @@ mod pure_builtins { let elements = groups .into_iter() .map(|(key, group)| { - let mut outputs: Vector<NixString> = Vector::new(); + let mut outputs: Vec<NixString> = Vec::new(); let mut is_path = false; let mut all_outputs = false; @@ -654,7 +640,7 @@ mod pure_builtins { NixContextElement::Single { name, derivation } => { debug_assert!(derivation == key, "Unexpected group containing mixed keys, expected: {:?}, encountered {:?}", key, derivation); - outputs.push_back(name.clone().into()); + outputs.push(name.clone().into()); } NixContextElement::Derivation(drv_path) => { @@ -681,7 +667,7 @@ mod pure_builtins { vec_attrs.push(("outputs", Value::List(outputs .into_iter() .map(|s| s.into()) - .collect::<Vector<Value>>() + .collect::<Vec<Value>>() .into() ))); } @@ -717,7 +703,7 @@ mod pure_builtins { // // In this implementation, we do none of that, no syntax checks, no realization. // The next `TODO` are the checks that Nix implements. - let mut ctx_elements: HashSet<NixContextElement> = HashSet::new(); + let mut ctx_elements: FxHashSet<NixContextElement> = FxHashSet::default(); let span = generators::request_span(&co).await; let origin = origin .coerce_to_string( @@ -764,9 +750,8 @@ mod pure_builtins { } if let Some(origin_ctx) = origin.context_mut() { - // FUTUREWORK(performance): avoid this clone - // and extend in-place. - *origin_ctx = origin_ctx.clone().join(&mut ctx_elements.into()); + origin_ctx.extend(ctx_elements) + // TODO: didn't we forget cases where origin had no context? } Ok(origin.into()) @@ -809,7 +794,7 @@ mod pure_builtins { } let mut right_keys = right_set.keys(); - let mut out: OrdMap<NixString, Value> = OrdMap::new(); + let mut out: BTreeMap<NixString, Value> = BTreeMap::new(); // Both iterators have at least one entry let mut left = left_keys.next().unwrap(); @@ -990,15 +975,16 @@ mod pure_builtins { } #[builtin("map")] - async fn builtin_map(co: GenCo, #[lazy] f: Value, list: Value) -> Result<Value, ErrorKind> { - let mut out = imbl::Vector::<Value>::new(); + async fn builtin_map(co: GenCo, #[lazy] f: Value, list_val: Value) -> Result<Value, ErrorKind> { + let list = list_val.to_list()?; + let mut out = Vec::with_capacity(list.len()); // the best span we can get… let span = generators::request_span(&co).await; - for val in list.to_list()? { - let result = Value::Thunk(Thunk::new_suspended_call(f.clone(), val, span.clone())); - out.push_back(result) + for val in list { + let result = Value::Thunk(Thunk::new_suspended_call(f.clone(), val, span)); + out.push(result) } Ok(Value::List(out.into())) @@ -1011,7 +997,7 @@ mod pure_builtins { attrs: Value, ) -> Result<Value, ErrorKind> { let attrs = attrs.to_attrs()?; - let mut out = imbl::OrdMap::new(); + let mut out: BTreeMap<NixString, Value> = BTreeMap::new(); // the best span we can get… let span = generators::request_span(&co).await; @@ -1020,9 +1006,9 @@ mod pure_builtins { let result = Value::Thunk(Thunk::new_suspended_call( f.clone(), key.clone().into(), - span.clone(), + span, )); - let result = Value::Thunk(Thunk::new_suspended_call(result, value, span.clone())); + let result = Value::Thunk(Thunk::new_suspended_call(result, value, span)); out.insert(key, result); } @@ -1057,7 +1043,7 @@ mod pure_builtins { // and then a compressor name will be extracted from that. grp.map(|g| Value::from(g.as_str())).unwrap_or(Value::Null) }) - .collect::<imbl::Vector<Value>>() + .collect::<Vec<Value>>() .into(), )), None => Ok(Value::Null), @@ -1100,17 +1086,17 @@ mod pure_builtins { #[builtin("partition")] async fn builtin_partition(co: GenCo, pred: Value, list: Value) -> Result<Value, ErrorKind> { - let mut right: imbl::Vector<Value> = Default::default(); - let mut wrong: imbl::Vector<Value> = Default::default(); + let mut right: Vec<Value> = Default::default(); + let mut wrong: Vec<Value> = Default::default(); let list: NixList = list.to_list()?; for elem in list { let result = generators::request_call_with(&co, pred.clone(), [elem.clone()]).await; if try_value!(generators::request_force(&co, result).await).as_bool()? { - right.push_back(elem); + right.push(elem); } else { - wrong.push_back(elem); + wrong.push(elem); }; } @@ -1133,7 +1119,7 @@ mod pure_builtins { .to_list()? .into_iter() .map(|v| v.to_str()) - .collect::<Result<HashSet<_>, _>>()?; + .collect::<Result<FxHashSet<_>, _>>()?; let res = attrs.iter().filter_map(|(k, v)| { if !keys.contains(k) { Some((k.clone(), v.clone())) @@ -1169,8 +1155,8 @@ mod pure_builtins { let mut empty_string_replace = false; let mut context = NixContext::new(); - if let Some(string_context) = string.context_mut() { - context = context.join(string_context); + if let Some(string_context) = string.take_context() { + context.extend(string_context.into_iter()); } // This can't be implemented using Rust's string.replace() as @@ -1200,8 +1186,8 @@ mod pure_builtins { if string[i..i + from.len()] == *from { res.push_str(&to); i += from.len(); - if let Some(to_ctx) = to.context_mut() { - context = context.join(to_ctx); + if let Some(to_ctx) = to.take_context() { + context.extend(to_ctx.into_iter()); } // remember if we applied the empty from->to @@ -1232,8 +1218,8 @@ mod pure_builtins { if from.is_empty() { res.push_str(&to); - if let Some(to_ctx) = to.context_mut() { - context = context.join(to_ctx); + if let Some(to_ctx) = to.take_context() { + context.extend(to_ctx.into_iter()); } break; } @@ -1265,12 +1251,12 @@ mod pure_builtins { let re = Regex::new(re.to_str()?).unwrap(); let mut capture_locations = re.capture_locations(); let num_captures = capture_locations.len(); - let mut ret = imbl::Vector::new(); + let mut ret = Vec::new(); let mut pos = 0; while let Some(thematch) = re.captures_read_at(&mut capture_locations, text, pos) { // push the unmatched characters preceding the match - ret.push_back(Value::from(NixString::new_inherit_context_from( + ret.push(Value::from(NixString::new_inherit_context_from( &s, &text[pos..thematch.start()], ))); @@ -1279,7 +1265,7 @@ mod pure_builtins { // group in the regex, containing the characters // matched by that capture group, or null if no match. // We skip capture 0; it represents the whole match. - let v: imbl::Vector<Value> = (1..num_captures) + let v: Vec<Value> = (1..num_captures) .map(|i| capture_locations.get(i)) .map(|o| { o.map(|(start, end)| { @@ -1290,14 +1276,17 @@ mod pure_builtins { .unwrap_or(Value::Null) }) .collect(); - ret.push_back(Value::List(NixList::from(v))); + ret.push(Value::List(NixList::from(v))); + if pos == text.len() { + break; + } pos = thematch.end(); } // push the unmatched characters following the last match // Here, a surprising thing happens: we silently discard the original // context. This is as intended, Nix does the same. - ret.push_back(Value::from(&text[pos..])); + ret.push(Value::from(&text[pos..])); Ok(Value::List(NixList::from(ret))) } @@ -1504,15 +1493,19 @@ mod pure_builtins { } let mut buf: Vec<u8> = vec![]; - to_xml::value_to_xml(&mut buf, &value)?; - Ok(String::from_utf8(buf)?.into()) - } - - #[builtin("placeholder")] - async fn builtin_placeholder(co: GenCo, #[lazy] _x: Value) -> Result<Value, ErrorKind> { - generators::emit_warning_kind(&co, WarningKind::NotImplemented("builtins.placeholder")) - .await; - Ok("<builtins.placeholder-is-not-implemented-in-tvix-yet>".into()) + let context = to_xml::value_to_xml(&mut buf, &value)?; + + Ok(( + buf, + // FUTUREWORK: We have a distinction between an empty context, and + // no context at all. Fix this. + if !context.is_empty() { + Some(Box::new(context)) + } else { + None + }, + ) + .into()) } #[builtin("trace")] @@ -1612,10 +1605,16 @@ pub fn pure_builtins() -> Vec<(&'static str, Value)> { crate::systems::llvm_triple_to_nix_double(CURRENT_PLATFORM).into(), )); - // TODO: implement for nixpkgs compatibility result.push(( "__curPos", - Value::from(CatchableErrorKind::UnimplementedFeature("__curPos".into())), + Value::Thunk(Thunk::new_suspended_native(Box::new(move || { + // TODO: implement for nixpkgs compatibility + Ok(Value::attrs(NixAttrs::from_iter([ + ("line", 42.into()), + ("column", 42.into()), + ("file", Value::String("/deep/thought".into())), + ]))) + }))), )); result @@ -1623,6 +1622,8 @@ pub fn pure_builtins() -> Vec<(&'static str, Value)> { #[builtins] mod placeholder_builtins { + use crate::NixContext; + use super::*; #[builtin("unsafeDiscardStringContext")] @@ -1671,24 +1672,17 @@ mod placeholder_builtins { .to_contextful_str()?; // If there's any context, we will swap any ... by a path one. - if let Some(ctx) = v.context_mut() { - let new_context: tvix_eval::NixContext = ctx - .iter() - .map(|elem| match elem { - // FUTUREWORK(performance): ideally, we should either: - // (a) do interior mutation of the existing context. - // (b) let the structural sharing make those clones cheap. - crate::NixContextElement::Derivation(drv_path) => { - crate::NixContextElement::Plain(drv_path.to_string()) - } - elem => elem.clone(), - }) - .collect::<HashSet<_>>() - .into(); + if let Some(c) = v.take_context() { + let mut context = NixContext::new(); + context.extend(c.into_iter().map(|elem| match elem { + crate::NixContextElement::Derivation(drv_path) => { + crate::NixContextElement::Plain(drv_path.to_string()) + } + elem => elem.clone(), + })); - *ctx = new_context; + return Ok(Value::String(NixString::new_context_from(context, v))); } - Ok(Value::from(v)) } @@ -1709,6 +1703,7 @@ mod placeholder_builtins { _name: Value, _attrset: Value, ) -> Result<Value, ErrorKind> { + // TODO: implement for nixpkgs compatibility generators::emit_warning_kind( &co, WarningKind::NotImplemented("builtins.unsafeGetAttrsPos"), diff --git a/tvix/eval/src/builtins/to_xml.rs b/tvix/eval/src/builtins/to_xml.rs index bb12cebfc9d0..093e127fe25e 100644 --- a/tvix/eval/src/builtins/to_xml.rs +++ b/tvix/eval/src/builtins/to_xml.rs @@ -3,112 +3,98 @@ //! things in nixpkgs rely on. use bstr::ByteSlice; +use std::borrow::Cow; use std::{io::Write, rc::Rc}; -use xml::writer::events::XmlEvent; -use xml::writer::EmitterConfig; -use xml::writer::EventWriter; -use crate::{ErrorKind, Value}; +use crate::{ErrorKind, NixContext, NixContextElement, Value}; /// Recursively serialise a value to XML. The value *must* have been /// deep-forced before being passed to this function. -pub fn value_to_xml<W: Write>(mut writer: W, value: &Value) -> Result<(), ErrorKind> { - let config = EmitterConfig { - perform_indent: true, - pad_self_closing: true, - - // Nix uses single-quotes *only* in the document declaration, - // so we need to write it manually. - write_document_declaration: false, - ..Default::default() - }; - +/// On success, returns the NixContext. +pub fn value_to_xml<W: Write>(mut writer: W, value: &Value) -> Result<NixContext, ErrorKind> { // Write a literal document declaration, using C++-Nix-style // single quotes. writeln!(writer, "<?xml version='1.0' encoding='utf-8'?>")?; - let mut writer = EventWriter::new_with_config(writer, config); - - writer.write(XmlEvent::start_element("expr"))?; - value_variant_to_xml(&mut writer, value)?; - writer.write(XmlEvent::end_element())?; + let mut emitter = XmlEmitter::new(writer); - // Unwrap the writer to add the final newline that C++ Nix adds. - writeln!(writer.into_inner())?; + emitter.write_open_tag("expr", &[])?; + value_variant_to_xml(&mut emitter, value)?; + emitter.write_closing_tag("expr")?; - Ok(()) + Ok(emitter.into_context()) } fn write_typed_value<W: Write, V: ToString>( - w: &mut EventWriter<W>, - name: &str, + w: &mut XmlEmitter<W>, + name_unescaped: &str, value: V, ) -> Result<(), ErrorKind> { - w.write(XmlEvent::start_element(name).attr("value", &value.to_string()))?; - w.write(XmlEvent::end_element())?; + w.write_self_closing_tag(name_unescaped, &[("value", &value.to_string())])?; Ok(()) } -fn value_variant_to_xml<W: Write>(w: &mut EventWriter<W>, value: &Value) -> Result<(), ErrorKind> { +fn value_variant_to_xml<W: Write>(w: &mut XmlEmitter<W>, value: &Value) -> Result<(), ErrorKind> { match value { Value::Thunk(t) => return value_variant_to_xml(w, &t.value()), Value::Null => { - w.write(XmlEvent::start_element("null"))?; - w.write(XmlEvent::end_element()) + w.write_open_tag("null", &[])?; + w.write_closing_tag("null")?; } Value::Bool(b) => return write_typed_value(w, "bool", b), Value::Integer(i) => return write_typed_value(w, "int", i), Value::Float(f) => return write_typed_value(w, "float", f), - Value::String(s) => return write_typed_value(w, "string", s.to_str()?), + Value::String(s) => { + if let Some(context) = s.context() { + w.extend_context(context.iter().cloned()); + } + return write_typed_value(w, "string", s.to_str()?); + } Value::Path(p) => return write_typed_value(w, "path", p.to_string_lossy()), Value::List(list) => { - w.write(XmlEvent::start_element("list"))?; + w.write_open_tag("list", &[])?; for elem in list.into_iter() { value_variant_to_xml(w, elem)?; } - w.write(XmlEvent::end_element()) + w.write_closing_tag("list")?; } Value::Attrs(attrs) => { - w.write(XmlEvent::start_element("attrs"))?; + w.write_open_tag("attrs", &[])?; for elem in attrs.iter() { - w.write(XmlEvent::start_element("attr").attr("name", &elem.0.to_str_lossy()))?; + w.write_open_tag("attr", &[("name", &elem.0.to_str_lossy())])?; value_variant_to_xml(w, elem.1)?; - w.write(XmlEvent::end_element())?; + w.write_closing_tag("attr")?; } - w.write(XmlEvent::end_element()) + w.write_closing_tag("attrs")?; } Value::Closure(c) => { - w.write(XmlEvent::start_element("function"))?; + w.write_open_tag("function", &[])?; match &c.lambda.formals { Some(formals) => { - let mut attrspat = XmlEvent::start_element("attrspat"); + let mut attrs: Vec<(&str, &str)> = Vec::with_capacity(2); if formals.ellipsis { - attrspat = attrspat.attr("ellipsis", "1"); + attrs.push(("ellipsis", "1")); } if let Some(ref name) = &formals.name { - attrspat = attrspat.attr("name", name.as_str()); + attrs.push(("name", name.as_str())); } - w.write(attrspat)?; - + w.write_open_tag("attrspat", &attrs)?; for arg in formals.arguments.iter() { - w.write( - XmlEvent::start_element("attr").attr("name", &arg.0.to_str_lossy()), - )?; - w.write(XmlEvent::end_element())?; + w.write_self_closing_tag("attr", &[("name", &arg.0.to_str_lossy())])?; } - w.write(XmlEvent::end_element())?; + w.write_closing_tag("attrspat")?; } None => { // TODO(tazjin): tvix does not currently persist function @@ -120,17 +106,16 @@ fn value_variant_to_xml<W: Write>(w: &mut EventWriter<W>, value: &Value) -> Resu // If we don't want to persist the data, we can re-parse the // AST from the spans of the lambda's bytecode and figure it // out that way, but it needs some investigating. - w.write(XmlEvent::start_element("varpat").attr("name", /* fake: */ "x"))?; - w.write(XmlEvent::end_element())?; + w.write_self_closing_tag("varpat", &[("name", /* fake: */ "x")])?; } } - w.write(XmlEvent::end_element()) + w.write_closing_tag("function")?; } Value::Builtin(_) => { - w.write(XmlEvent::start_element("unevaluated"))?; - w.write(XmlEvent::end_element()) + w.write_open_tag("unevaluated", &[])?; + w.write_closing_tag("unevaluated")?; } Value::AttrNotFound @@ -148,7 +133,189 @@ fn value_variant_to_xml<W: Write>(w: &mut EventWriter<W>, value: &Value) -> Resu Value::Catchable(_) => { panic!("tvix bug: value_to_xml() called on a value which had not been deep-forced") } - }?; + }; Ok(()) } + +/// A simple-stupid XML emitter, which implements only the subset needed for byte-by-byte compat with C++ nix’ `builtins.toXML`. +struct XmlEmitter<W> { + /// The current indentation + cur_indent: usize, + writer: W, + context: NixContext, +} + +impl<W: Write> XmlEmitter<W> { + pub fn new(writer: W) -> Self { + XmlEmitter { + cur_indent: 0, + writer, + context: Default::default(), + } + } + + /// Write an open tag with the given name (which is not escaped!) + /// and attributes (Keys are not escaped! Only attribute values are.) + pub fn write_open_tag( + &mut self, + name_unescaped: &str, + attrs: &[(&str, &str)], + ) -> std::io::Result<()> { + self.add_indent()?; + self.writer.write_all(b"<")?; + self.writer.write_all(name_unescaped.as_bytes())?; + self.write_attrs_escape_vals(attrs)?; + self.writer.write_all(b">\n")?; + self.cur_indent += 2; + Ok(()) + } + + /// Write a self-closing open tag with the given name (which is not escaped!) + /// and attributes (Keys are not escaped! Only attribute values are.) + pub fn write_self_closing_tag( + &mut self, + name_unescaped: &str, + attrs: &[(&str, &str)], + ) -> std::io::Result<()> { + self.add_indent()?; + self.writer.write_all(b"<")?; + self.writer.write_all(name_unescaped.as_bytes())?; + self.write_attrs_escape_vals(attrs)?; + self.writer.write_all(b" />\n")?; + Ok(()) + } + + /// Write a closing tag with the given name (which is not escaped!) + pub fn write_closing_tag(&mut self, name_unescaped: &str) -> std::io::Result<()> { + self.cur_indent -= 2; + self.add_indent()?; + self.writer.write_all(b"</")?; + self.writer.write_all(name_unescaped.as_bytes())?; + self.writer.write_all(b">\n")?; + Ok(()) + } + + #[inline] + fn add_indent(&mut self) -> std::io::Result<()> { + self.writer.write_all(&b" ".repeat(self.cur_indent)) + } + + /// Write an attribute list + fn write_attrs_escape_vals(&mut self, attrs: &[(&str, &str)]) -> std::io::Result<()> { + for (name, val) in attrs { + self.writer.write_all(b" ")?; + self.writer.write_all(name.as_bytes())?; + self.writer.write_all(br#"=""#)?; + self.writer + .write_all(Self::escape_attr_value(val).as_bytes())?; + self.writer.write_all(b"\"")?; + } + Ok(()) + } + + /// Escape the given attribute value, making sure we only actually clone the string if we needed to replace something. + fn escape_attr_value(s: &str) -> Cow<str> { + let mut last_escape: usize = 0; + let mut res: Cow<str> = Cow::Borrowed(""); + // iterating via char_indices gives us the ability to index the original string slice at character boundaries + for (idx, c) in s.char_indices() { + match Self::should_escape_char(c) { + None => {} + Some(new) => { + // add characters since the last escape we did + res += &s[last_escape..idx]; + // add the escaped value + res += new; + last_escape = idx + 1; + } + } + } + // we did not need to escape anything, so borrow original string + if last_escape == 0 { + Cow::Borrowed(s) + } else { + // add the remaining characters + res += &s[last_escape..]; + res + } + } + + fn should_escape_char(c: char) -> Option<&'static str> { + match c { + '<' => Some("<"), + '>' => Some(">"), + '"' => Some("""), + '\'' => Some("'"), + '&' => Some("&"), + '\n' => Some("
"), + '\r' => Some("
"), + _ => None, + } + } + + /// Extends the existing context with more context elements. + fn extend_context<T>(&mut self, iter: T) + where + T: IntoIterator<Item = NixContextElement>, + { + self.context.extend(iter) + } + + /// Consumes [Self] and returns the [NixContext] collected. + fn into_context(self) -> NixContext { + self.context + } +} + +#[cfg(test)] +mod tests { + use bytes::buf::Writer; + use pretty_assertions::assert_eq; + + use crate::builtins::to_xml::XmlEmitter; + use std::borrow::Cow; + + #[test] + fn xml_gen() { + let mut buf = Vec::new(); + let mut x = XmlEmitter::new(&mut buf); + x.write_open_tag("hello", &[("hi", "it’s me"), ("no", "<escape>")]) + .unwrap(); + x.write_self_closing_tag("self-closing", &[("tag", "yay")]) + .unwrap(); + x.write_closing_tag("hello").unwrap(); + + assert_eq!( + std::str::from_utf8(&buf).unwrap(), + r##"<hello hi="it’s me" no="<escape>"> + <self-closing tag="yay" /> +</hello> +"## + ); + } + + #[test] + fn xml_escape() { + match XmlEmitter::<Writer<Vec<u8>>>::escape_attr_value("ab<>c&de") { + Cow::Owned(s) => assert_eq!(s, "ab<>c&de".to_string(), "escape stuff"), + Cow::Borrowed(s) => panic!("s should be owned {}", s), + } + match XmlEmitter::<Writer<Vec<u8>>>::escape_attr_value("") { + Cow::Borrowed(s) => assert_eq!(s, "", "empty escape is borrowed"), + Cow::Owned(s) => panic!("s should be borrowed {}", s), + } + match XmlEmitter::<Writer<Vec<u8>>>::escape_attr_value("hi!Å·bla") { + Cow::Borrowed(s) => assert_eq!(s, "hi!Å·bla", "no escape is borrowed"), + Cow::Owned(s) => panic!("s should be borrowed {}", s), + } + match XmlEmitter::<Writer<Vec<u8>>>::escape_attr_value("hi!<Å·>bla") { + Cow::Owned(s) => assert_eq!( + s, + "hi!<Å·>bla".to_string(), + "multi-byte chars are correctly used" + ), + Cow::Borrowed(s) => panic!("s should be owned {}", s), + } + } +} diff --git a/tvix/eval/src/chunk.rs b/tvix/eval/src/chunk.rs index f1a35a6ce162..2a5446a782ed 100644 --- a/tvix/eval/src/chunk.rs +++ b/tvix/eval/src/chunk.rs @@ -1,9 +1,10 @@ +use crate::opcode::{CodeIdx, ConstantIdx, Op, OpArg}; +use crate::value::Value; +use crate::{CoercionKind, SourceCode}; use std::io::Write; -use std::ops::{Index, IndexMut}; -use crate::opcode::{CodeIdx, ConstantIdx, OpCode}; -use crate::value::Value; -use crate::SourceCode; +/// Maximum size of a u64 encoded in the vu128 varint encoding. +const U64_VARINT_SIZE: usize = 9; /// Represents a source location from which one or more operations /// were compiled. @@ -30,39 +31,69 @@ struct SourceSpan { /// emitted by the compiler. #[derive(Debug, Default)] pub struct Chunk { - pub code: Vec<OpCode>, + pub code: Vec<u8>, pub constants: Vec<Value>, spans: Vec<SourceSpan>, + + /// Index of the last operation (i.e. not data) written to the code vector. + /// Some operations (e.g. jump patching) need to know this. + last_op: usize, } -impl Index<ConstantIdx> for Chunk { - type Output = Value; +impl Chunk { + pub fn push_op(&mut self, op: Op, span: codemap::Span) -> usize { + self.last_op = self.code.len(); + self.code.push(op as u8); + self.push_span(span, self.last_op); + self.last_op + } - fn index(&self, index: ConstantIdx) -> &Self::Output { - &self.constants[index.0] + pub fn push_uvarint(&mut self, data: u64) { + let mut encoded = [0u8; U64_VARINT_SIZE]; + let bytes_written = vu128::encode_u64(&mut encoded, data); + self.code.extend_from_slice(&encoded[..bytes_written]); } -} -impl Index<CodeIdx> for Chunk { - type Output = OpCode; + pub fn read_uvarint(&self, idx: usize) -> (u64, usize) { + debug_assert!( + idx < self.code.len(), + "invalid bytecode (missing varint operand)", + ); - fn index(&self, index: CodeIdx) -> &Self::Output { - &self.code[index.0] + if self.code.len() - idx >= U64_VARINT_SIZE { + vu128::decode_u64( + &self.code[idx..idx + U64_VARINT_SIZE] + .try_into() + .expect("size statically checked"), + ) + } else { + let mut tmp = [0u8; U64_VARINT_SIZE]; + tmp[..self.code.len() - idx].copy_from_slice(&self.code[idx..]); + vu128::decode_u64(&tmp) + } } -} -impl IndexMut<CodeIdx> for Chunk { - fn index_mut(&mut self, index: CodeIdx) -> &mut Self::Output { - &mut self.code[index.0] + pub fn push_u16(&mut self, data: u16) { + self.code.extend_from_slice(&data.to_le_bytes()) } -} -impl Chunk { - pub fn push_op(&mut self, data: OpCode, span: codemap::Span) -> CodeIdx { - let idx = self.code.len(); - self.code.push(data); - self.push_span(span, idx); - CodeIdx(idx) + /// Patches the argument to the jump operand of the jump at the given index + /// to point to the *next* instruction that will be emitted. + pub fn patch_jump(&mut self, idx: usize) { + let offset = (self.code.len() - idx - /* arg idx = */ 1 - /* jump arg size = */ 2) as u16; + self.code[idx + 1..idx + 3].copy_from_slice(&offset.to_le_bytes()) + } + + pub fn read_u16(&self, idx: usize) -> u16 { + if idx + 2 > self.code.len() { + panic!("Tvix bug: invalid bytecode (expected u16 operand not found)") + } + + let byte_array: &[u8; 2] = &self.code[idx..idx + 2] + .try_into() + .expect("fixed-size slice can not fail to convert to array"); + + u16::from_le_bytes(*byte_array) } /// Get the first span of a chunk, no questions asked. @@ -70,23 +101,13 @@ impl Chunk { self.spans[0].span } - /// Return a reference to the last op in the chunk, if any - pub fn last_op(&self) -> Option<&OpCode> { - self.code.last() - } - - /// Pop the last operation from the chunk and clean up its tracked - /// span. Used when the compiler backtracks. - pub fn pop_op(&mut self) { - // Simply drop the last op. - self.code.pop(); - - if let Some(span) = self.spans.last() { - // If the last span started at this op, drop it. - if span.start == self.code.len() { - self.spans.pop(); - } + /// Return the last op in the chunk together with its index, if any. + pub fn last_op(&self) -> Option<(Op, usize)> { + if self.code.is_empty() { + return None; } + + Some((self.code[self.last_op].into(), self.last_op)) } pub fn push_constant(&mut self, data: Value) -> ConstantIdx { @@ -100,8 +121,6 @@ impl Chunk { self.constants.get(constant.0) } - // Span tracking implementation - fn push_span(&mut self, span: codemap::Span, start: usize) { match self.spans.last_mut() { // We do not need to insert the same span again, as this @@ -136,66 +155,88 @@ impl Chunk { } /// Write the disassembler representation of the operation at - /// `idx` to the specified writer. + /// `idx` to the specified writer, and return how many bytes in the code to + /// skip for the next op. pub fn disassemble_op<W: Write>( &self, writer: &mut W, source: &SourceCode, width: usize, idx: CodeIdx, - ) -> Result<(), std::io::Error> { + ) -> Result<usize, std::io::Error> { write!(writer, "{:#width$x}\t ", idx.0, width = width)?; // Print continuation character if the previous operation was at // the same line, otherwise print the line. let line = source.get_line(self.get_span(idx)); - if idx.0 > 0 && source.get_line(self.get_span(CodeIdx(idx.0 - 1))) == line { + if idx.0 > 0 && source.get_line(self.get_span(idx - 1)) == line { write!(writer, " |\t")?; } else { write!(writer, "{:4}\t", line)?; } - match self[idx] { - OpCode::OpConstant(idx) => { - let val_str = match &self[idx] { - Value::Thunk(t) => t.debug_repr(), - Value::Closure(c) => format!("closure({:p})", c.lambda), - val => format!("{}", val), - }; + let _fmt_constant = |idx: ConstantIdx| match &self.constants[idx.0] { + Value::Thunk(t) => t.debug_repr(), + Value::Closure(c) => format!("closure({:p})", c.lambda), + Value::Blueprint(b) => format!("blueprint({:p})", b), + val => format!("{}", val), + }; - writeln!(writer, "OpConstant({}@{})", val_str, idx.0) + let op: Op = self.code[idx.0].into(); + + match op.arg_type() { + OpArg::None => { + writeln!(writer, "Op{:?}", op)?; + Ok(1) } - op => writeln!(writer, "{:?}", op), - }?; - Ok(()) - } + OpArg::Fixed => { + let arg = self.read_u16(idx.0 + 1); + writeln!(writer, "Op{:?}({})", op, arg)?; + Ok(3) + } - /// Extend this chunk with the content of another, moving out of the other - /// in the process. - /// - /// This is used by the compiler when it detects that it unnecessarily - /// thunked a nested expression. - pub fn extend(&mut self, other: Self) { - // Some operations need to be modified in certain ways before being - // valid as part of the new chunk. - let const_count = self.constants.len(); - for (idx, op) in other.code.iter().enumerate() { - let span = other.get_span(CodeIdx(idx)); - match op { - // As the constants shift, the index needs to be moved relatively. - OpCode::OpConstant(ConstantIdx(idx)) => { - self.push_op(OpCode::OpConstant(ConstantIdx(idx + const_count)), span) + OpArg::Uvarint => { + let (arg, size) = self.read_uvarint(idx.0 + 1); + writeln!(writer, "Op{:?}({})", op, arg)?; + Ok(1 + size) + } + + _ => match op { + Op::CoerceToString => { + let kind: CoercionKind = self.code[idx.0 + 1].into(); + writeln!(writer, "Op{:?}({:?})", op, kind)?; + Ok(2) } - // Other operations either operate on relative offsets, or no - // offsets, and are safe to keep as-is. - _ => self.push_op(*op, span), - }; - } + Op::Closure | Op::ThunkClosure | Op::ThunkSuspended => { + let mut cidx = idx.0 + 1; - self.constants.extend(other.constants); - self.spans.extend(other.spans); + let (bp_idx, size) = self.read_uvarint(cidx); + cidx += size; + + let (packed_count, size) = self.read_uvarint(cidx); + cidx += size; + + let captures_with = packed_count & 0b1 == 1; + let count = packed_count >> 1; + + write!(writer, "Op{:?}(BP @ {}, ", op, bp_idx)?; + if captures_with { + write!(writer, "captures with, ")?; + } + writeln!(writer, "{} upvalues)", count)?; + + for _ in 0..count { + let (_, size) = self.read_uvarint(cidx); + cidx += size; + } + + Ok(cidx - idx.0) + } + _ => panic!("Tvix bug: don't know how to format argument for Op{:?}", op), + }, + } } } @@ -211,79 +252,49 @@ mod tests { #[test] fn push_op() { let mut chunk = Chunk::default(); - chunk.push_op(OpCode::OpAdd, dummy_span()); - assert_eq!(chunk.code.last().unwrap(), &OpCode::OpAdd); + let idx = chunk.push_op(Op::Add, dummy_span()); + assert_eq!(*chunk.code.last().unwrap(), Op::Add as u8); + assert_eq!(chunk.code[idx], Op::Add as u8); } #[test] - fn extend_empty() { + fn push_op_with_arg() { let mut chunk = Chunk::default(); - chunk.push_op(OpCode::OpAdd, dummy_span()); + let mut idx = chunk.push_op(Op::Constant, dummy_span()); + chunk.push_uvarint(42); - let other = Chunk::default(); - chunk.extend(other); + assert_eq!(chunk.code[idx], Op::Constant as u8); - assert_eq!( - chunk.code, - vec![OpCode::OpAdd], - "code should not have changed" - ); + idx += 1; + let (arg, size) = chunk.read_uvarint(idx); + assert_eq!(idx + size, chunk.code.len()); + assert_eq!(arg, 42); } #[test] - fn extend_simple() { - let span = dummy_span(); + fn push_jump() { let mut chunk = Chunk::default(); - chunk.push_op(OpCode::OpAdd, span); - let mut other = Chunk::default(); - other.push_op(OpCode::OpSub, span); - other.push_op(OpCode::OpMul, span); + chunk.push_op(Op::Constant, dummy_span()); + chunk.push_uvarint(0); - let expected_code = vec![OpCode::OpAdd, OpCode::OpSub, OpCode::OpMul]; + let idx = chunk.push_op(Op::Jump, dummy_span()); + chunk.push_u16(0); - chunk.extend(other); + chunk.push_op(Op::Constant, dummy_span()); + chunk.push_uvarint(1); - assert_eq!(chunk.code, expected_code, "code should have been extended"); - } + chunk.patch_jump(idx); + chunk.push_op(Op::Return, dummy_span()); - #[test] - fn extend_with_constant() { - let span = dummy_span(); - let mut chunk = Chunk::default(); - chunk.push_op(OpCode::OpAdd, span); - let cidx = chunk.push_constant(Value::Integer(0)); - assert_eq!( - cidx.0, 0, - "first constant in main chunk should have index 0" - ); - chunk.push_op(OpCode::OpConstant(cidx), span); - - let mut other = Chunk::default(); - other.push_op(OpCode::OpSub, span); - let other_cidx = other.push_constant(Value::Integer(1)); - assert_eq!( - other_cidx.0, 0, - "first constant in other chunk should have index 0" - ); - other.push_op(OpCode::OpConstant(other_cidx), span); - - chunk.extend(other); - - let expected_code = vec![ - OpCode::OpAdd, - OpCode::OpConstant(ConstantIdx(0)), - OpCode::OpSub, - OpCode::OpConstant(ConstantIdx(1)), // <- note: this was rewritten + #[rustfmt::skip] + let expected: Vec<u8> = vec![ + Op::Constant as u8, 0, + Op::Jump as u8, 2, 0, + Op::Constant as u8, 1, + Op::Return as u8, ]; - assert_eq!( - chunk.code, expected_code, - "code should have been extended and rewritten" - ); - - assert_eq!(chunk.constants.len(), 2); - assert!(matches!(chunk.constants[0], Value::Integer(0))); - assert!(matches!(chunk.constants[1], Value::Integer(1))); + assert_eq!(chunk.code, expected); } } diff --git a/tvix/eval/src/compiler/bindings.rs b/tvix/eval/src/compiler/bindings.rs index 634cc5402247..6a3ae485936c 100644 --- a/tvix/eval/src/compiler/bindings.rs +++ b/tvix/eval/src/compiler/bindings.rs @@ -9,6 +9,8 @@ use std::iter::Peekable; use rnix::ast::HasEntry; use rowan::ast::AstChildren; +use crate::spans::{EntireFile, OrEntireFile}; + use super::*; type PeekableAttrs = Peekable<AstChildren<ast::Attr>>; @@ -556,6 +558,15 @@ impl Compiler<'_, '_> { self.scope_mut().end_scope(); } + /// Emit definitions for all variables in the top-level global env passed to the evaluation (eg + /// local variables in the REPL) + pub(super) fn compile_env(&mut self, env: &FxHashMap<SmolStr, Value>) { + for (name, value) in env { + self.scope_mut().declare_constant(name.to_string()); + self.emit_constant(value.clone(), &EntireFile); + } + } + /// Actually binds all tracked bindings by emitting the bytecode that places /// them in their stack slots. fn bind_values(&mut self, bindings: TrackedBindings) { @@ -569,7 +580,7 @@ impl Compiler<'_, '_> { KeySlot::Static { slot, name } => { let span = self.scope()[slot].span; - self.emit_constant(name.as_str().into(), &span); + self.emit_constant(name.as_str().into(), &OrEntireFile(span)); self.scope_mut().mark_initialised(slot); } @@ -594,7 +605,7 @@ impl Compiler<'_, '_> { c.emit_force(&namespace); c.emit_constant(name.as_str().into(), &span); - c.push_op(OpCode::OpAttrsSelect, &span); + c.push_op(Op::AttrsSelect, &span); }) } @@ -621,7 +632,8 @@ impl Compiler<'_, '_> { if self.scope()[idx].needs_finaliser { let stack_idx = self.scope().stack_index(idx); let span = self.scope()[idx].span; - self.push_op(OpCode::OpFinalise(stack_idx), &span); + self.push_op(Op::Finalise, &OrEntireFile(span)); + self.push_uvarint(stack_idx.0 as u64) } } } @@ -656,11 +668,8 @@ impl Compiler<'_, '_> { self.bind_values(bindings); if kind.is_attrs() { - self.push_op(OpCode::OpAttrs(Count(count)), node); - } - - if count == 0 { - self.unthunk(); + self.push_op(Op::Attrs, node); + self.push_uvarint(count as u64); } } @@ -686,7 +695,7 @@ impl Compiler<'_, '_> { self.scope_mut().end_scope(); self.emit_constant("body".into(), node); - self.push_op(OpCode::OpAttrsSelect, node); + self.push_op(Op::AttrsSelect, node); } /// Is the given identifier defined *by the user* in any current scope? @@ -707,8 +716,9 @@ impl Compiler<'_, '_> { match self.scope_mut().resolve_local(ident) { LocalPosition::Unknown => { // Are we possibly dealing with an upvalue? - if let Some(idx) = self.resolve_upvalue(self.contexts.len() - 1, ident, node) { - self.push_op(OpCode::OpGetUpvalue(idx), node); + if let Some(idx) = self.resolve_upvalue(self.contexts.len() - 1, ident) { + self.push_op(Op::GetUpvalue, node); + self.push_uvarint(idx.0 as u64); return; } @@ -731,7 +741,7 @@ impl Compiler<'_, '_> { self.thunk(slot, node, |c, _| { c.context_mut().captures_with_stack = true; c.emit_constant(ident.into(), node); - c.push_op(OpCode::OpResolveWith, node); + c.push_op(Op::ResolveWith, node); }); return; } @@ -742,18 +752,17 @@ impl Compiler<'_, '_> { LocalPosition::Known(idx) => { let stack_idx = self.scope().stack_index(idx); - self.push_op(OpCode::OpGetLocal(stack_idx), node); + self.push_op(Op::GetLocal, node); + self.push_uvarint(stack_idx.0 as u64); } // This identifier is referring to a value from the same scope which // is not yet defined. This identifier access must be thunked. LocalPosition::Recursive(idx) => self.thunk(slot, node, move |compiler, _| { - let upvalue_idx = compiler.add_upvalue( - compiler.contexts.len() - 1, - node, - UpvalueKind::Local(idx), - ); - compiler.push_op(OpCode::OpGetUpvalue(upvalue_idx), node); + let upvalue_idx = + compiler.add_upvalue(compiler.contexts.len() - 1, UpvalueKind::Local(idx)); + compiler.push_op(Op::GetUpvalue, node); + compiler.push_uvarint(upvalue_idx.0 as u64); }), }; } @@ -766,12 +775,7 @@ impl Compiler<'_, '_> { /// Private compiler helpers related to bindings. impl Compiler<'_, '_> { - fn resolve_upvalue<N: ToSpan>( - &mut self, - ctx_idx: usize, - name: &str, - node: &N, - ) -> Option<UpvalueIdx> { + fn resolve_upvalue(&mut self, ctx_idx: usize, name: &str) -> Option<UpvalueIdx> { if ctx_idx == 0 { // There can not be any upvalue at the outermost context. return None; @@ -784,7 +788,7 @@ impl Compiler<'_, '_> { // stack (i.e. in the right position) *during* their runtime // construction LocalPosition::Known(idx) | LocalPosition::Recursive(idx) => { - return Some(self.add_upvalue(ctx_idx, node, UpvalueKind::Local(idx))) + return Some(self.add_upvalue(ctx_idx, UpvalueKind::Local(idx))) } LocalPosition::Unknown => { /* continue below */ } @@ -792,19 +796,14 @@ impl Compiler<'_, '_> { // If the upvalue comes from even further up, we need to recurse to make // sure that the upvalues are created at each level. - if let Some(idx) = self.resolve_upvalue(ctx_idx - 1, name, node) { - return Some(self.add_upvalue(ctx_idx, node, UpvalueKind::Upvalue(idx))); + if let Some(idx) = self.resolve_upvalue(ctx_idx - 1, name) { + return Some(self.add_upvalue(ctx_idx, UpvalueKind::Upvalue(idx))); } None } - fn add_upvalue<N: ToSpan>( - &mut self, - ctx_idx: usize, - node: &N, - kind: UpvalueKind, - ) -> UpvalueIdx { + fn add_upvalue(&mut self, ctx_idx: usize, kind: UpvalueKind) -> UpvalueIdx { // If there is already an upvalue closing over the specified index, // retrieve that instead. for (idx, existing) in self.contexts[ctx_idx].scope.upvalues.iter().enumerate() { @@ -813,11 +812,7 @@ impl Compiler<'_, '_> { } } - let span = self.span_for(node); - self.contexts[ctx_idx] - .scope - .upvalues - .push(Upvalue { kind, span }); + self.contexts[ctx_idx].scope.upvalues.push(Upvalue { kind }); let idx = UpvalueIdx(self.contexts[ctx_idx].lambda.upvalue_count); self.contexts[ctx_idx].lambda.upvalue_count += 1; diff --git a/tvix/eval/src/compiler/import.rs b/tvix/eval/src/compiler/import.rs index 9036eec81731..862e792df566 100644 --- a/tvix/eval/src/compiler/import.rs +++ b/tvix/eval/src/compiler/import.rs @@ -65,6 +65,7 @@ async fn import_impl( globals .upgrade() .expect("globals dropped while still in use"), + None, &source, &file, &mut NoOpObserver::default(), diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs index 60c55dda27b4..33b70b87ce84 100644 --- a/tvix/eval/src/compiler/mod.rs +++ b/tvix/eval/src/compiler/mod.rs @@ -20,16 +20,16 @@ mod scope; use codemap::Span; use rnix::ast::{self, AstToken}; +use rustc_hash::FxHashMap; use smol_str::SmolStr; -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use std::rc::{Rc, Weak}; use crate::chunk::Chunk; use crate::errors::{CatchableErrorKind, Error, ErrorKind, EvalResult}; use crate::observer::CompilerObserver; -use crate::opcode::{CodeIdx, ConstantIdx, Count, JumpOffset, OpCode, UpvalueIdx}; -use crate::spans::LightSpan; +use crate::opcode::{CodeIdx, Op, Position, UpvalueIdx}; use crate::spans::ToSpan; use crate::value::{Closure, Formals, Lambda, NixAttrs, Thunk, Value}; use crate::warnings::{EvalWarning, WarningKind}; @@ -45,11 +45,6 @@ pub struct CompilationOutput { pub lambda: Rc<Lambda>, pub warnings: Vec<EvalWarning>, pub errors: Vec<Error>, - - // This field must outlive the rc::Weak reference which breaks the - // builtins -> import -> builtins reference cycle. For this - // reason, it must be passed to the VM. - pub globals: Rc<GlobalsMap>, } /// Represents the lambda currently being compiled. @@ -57,7 +52,6 @@ struct LambdaCtx { lambda: Lambda, scope: Scope, captures_with_stack: bool, - unthunk: bool, } impl LambdaCtx { @@ -66,7 +60,6 @@ impl LambdaCtx { lambda: Lambda::default(), scope: Default::default(), captures_with_stack: false, - unthunk: false, } } @@ -75,7 +68,6 @@ impl LambdaCtx { lambda: Lambda::default(), scope: self.scope.inherit(), captures_with_stack: false, - unthunk: false, } } } @@ -123,7 +115,7 @@ impl TrackedFormal { /// The map of globally available functions and other values that /// should implicitly be resolvable in the global scope. -pub(crate) type GlobalsMap = HashMap<&'static str, Value>; +pub type GlobalsMap = FxHashMap<&'static str, Value>; /// Set of builtins that (if they exist) should be made available in /// the global scope, meaning that they can be accessed not just @@ -193,6 +185,7 @@ impl<'source, 'observer> Compiler<'source, 'observer> { pub(crate) fn new( location: Option<PathBuf>, globals: Rc<GlobalsMap>, + env: Option<&FxHashMap<SmolStr, Value>>, source: &'source SourceCode, file: &'source codemap::File, observer: &'observer mut dyn CompilerObserver, @@ -228,7 +221,7 @@ impl<'source, 'observer> Compiler<'source, 'observer> { #[cfg(not(target_arch = "wasm32"))] debug_assert!(root_dir.is_absolute()); - Ok(Self { + let mut compiler = Self { root_dir, source, file, @@ -238,7 +231,13 @@ impl<'source, 'observer> Compiler<'source, 'observer> { warnings: vec![], errors: vec![], dead_scope: 0, - }) + }; + + if let Some(env) = env { + compiler.compile_env(env); + } + + Ok(compiler) } } @@ -268,13 +267,37 @@ impl Compiler<'_, '_> { /// Push a single instruction to the current bytecode chunk and /// track the source span from which it was compiled. - fn push_op<T: ToSpan>(&mut self, data: OpCode, node: &T) -> CodeIdx { + fn push_op<T: ToSpan>(&mut self, data: Op, node: &T) -> CodeIdx { if self.dead_scope > 0 { return CodeIdx(0); } let span = self.span_for(node); - self.chunk().push_op(data, span) + CodeIdx(self.chunk().push_op(data, span)) + } + + fn push_u8(&mut self, data: u8) { + if self.dead_scope > 0 { + return; + } + + self.chunk().code.push(data); + } + + fn push_uvarint(&mut self, data: u64) { + if self.dead_scope > 0 { + return; + } + + self.chunk().push_uvarint(data); + } + + fn push_u16(&mut self, data: u16) { + if self.dead_scope > 0 { + return; + } + + self.chunk().push_u16(data); } /// Emit a single constant to the current bytecode chunk and track @@ -285,7 +308,8 @@ impl Compiler<'_, '_> { } let idx = self.chunk().push_constant(value); - self.push_op(OpCode::OpConstant(idx), node); + self.push_op(Op::Constant, node); + self.push_uvarint(idx.0 as u64); } } @@ -398,7 +422,7 @@ impl Compiler<'_, '_> { Value::UnresolvedPath(Box::new(home_relative_path.into())), node, ); - self.push_op(OpCode::OpResolveHomePath, node); + self.push_op(Op::ResolveHomePath, node); return; } else if raw_path.starts_with('<') { // TODO: decide what to do with findFile @@ -414,7 +438,7 @@ impl Compiler<'_, '_> { // Make a thunk to resolve the path (without using `findFile`, at least for now?) return self.thunk(slot, node, move |c, _| { c.emit_constant(Value::UnresolvedPath(Box::new(path.into())), node); - c.push_op(OpCode::OpFindFile, node); + c.push_op(Op::FindFile, node); }); } else { let mut buf = self.root_dir.clone(); @@ -450,13 +474,15 @@ impl Compiler<'_, '_> { ast::InterpolPart::Interpolation(ipol) => { self.compile(slot, ipol.expr().unwrap()); // implicitly forces as well - self.push_op( - OpCode::OpCoerceToString(CoercionKind { - strong: false, - import_paths: true, - }), - ipol, - ); + self.push_op(Op::CoerceToString, ipol); + + let encoded: u8 = CoercionKind { + strong: false, + import_paths: true, + } + .into(); + + self.push_u8(encoded); } ast::InterpolPart::Literal(lit) => { @@ -466,7 +492,8 @@ impl Compiler<'_, '_> { } if parts.len() != 1 { - self.push_op(OpCode::OpInterpolate(Count(parts.len())), parent_node); + self.push_op(Op::Interpolate, parent_node); + self.push_uvarint(parts.len() as u64); } } @@ -492,8 +519,8 @@ impl Compiler<'_, '_> { self.emit_force(op); let opcode = match op.operator().unwrap() { - ast::UnaryOpKind::Invert => OpCode::OpInvert, - ast::UnaryOpKind::Negate => OpCode::OpNegate, + ast::UnaryOpKind::Invert => Op::Invert, + ast::UnaryOpKind::Negate => Op::Negate, }; self.push_op(opcode, op); @@ -524,21 +551,21 @@ impl Compiler<'_, '_> { self.emit_force(&op.rhs().unwrap()); match op.operator().unwrap() { - BinOpKind::Add => self.push_op(OpCode::OpAdd, op), - BinOpKind::Sub => self.push_op(OpCode::OpSub, op), - BinOpKind::Mul => self.push_op(OpCode::OpMul, op), - BinOpKind::Div => self.push_op(OpCode::OpDiv, op), - BinOpKind::Update => self.push_op(OpCode::OpAttrsUpdate, op), - BinOpKind::Equal => self.push_op(OpCode::OpEqual, op), - BinOpKind::Less => self.push_op(OpCode::OpLess, op), - BinOpKind::LessOrEq => self.push_op(OpCode::OpLessOrEq, op), - BinOpKind::More => self.push_op(OpCode::OpMore, op), - BinOpKind::MoreOrEq => self.push_op(OpCode::OpMoreOrEq, op), - BinOpKind::Concat => self.push_op(OpCode::OpConcat, op), + BinOpKind::Add => self.push_op(Op::Add, op), + BinOpKind::Sub => self.push_op(Op::Sub, op), + BinOpKind::Mul => self.push_op(Op::Mul, op), + BinOpKind::Div => self.push_op(Op::Div, op), + BinOpKind::Update => self.push_op(Op::AttrsUpdate, op), + BinOpKind::Equal => self.push_op(Op::Equal, op), + BinOpKind::Less => self.push_op(Op::Less, op), + BinOpKind::LessOrEq => self.push_op(Op::LessOrEq, op), + BinOpKind::More => self.push_op(Op::More, op), + BinOpKind::MoreOrEq => self.push_op(Op::MoreOrEq, op), + BinOpKind::Concat => self.push_op(Op::Concat, op), BinOpKind::NotEqual => { - self.push_op(OpCode::OpEqual, op); - self.push_op(OpCode::OpInvert, op) + self.push_op(Op::Equal, op); + self.push_op(Op::Invert, op) } // Handled by separate branch above. @@ -559,20 +586,22 @@ impl Compiler<'_, '_> { self.compile(slot, node.lhs().unwrap()); self.emit_force(&node.lhs().unwrap()); - let throw_idx = self.push_op(OpCode::OpJumpIfCatchable(JumpOffset(0)), node); + let throw_idx = self.push_op(Op::JumpIfCatchable, node); + self.push_u16(0); // If this value is false, jump over the right-hand side - the // whole expression is false. - let end_idx = self.push_op(OpCode::OpJumpIfFalse(JumpOffset(0)), node); + let end_idx = self.push_op(Op::JumpIfFalse, node); + self.push_u16(0); // Otherwise, remove the previous value and leave the // right-hand side on the stack. Its result is now the value // of the whole expression. - self.push_op(OpCode::OpPop, node); + self.push_op(Op::Pop, node); self.compile(slot, node.rhs().unwrap()); self.emit_force(&node.rhs().unwrap()); self.patch_jump(end_idx); - self.push_op(OpCode::OpAssertBool, node); + self.push_op(Op::AssertBool, node); self.patch_jump(throw_idx); } @@ -587,16 +616,18 @@ impl Compiler<'_, '_> { self.compile(slot, node.lhs().unwrap()); self.emit_force(&node.lhs().unwrap()); - let throw_idx = self.push_op(OpCode::OpJumpIfCatchable(JumpOffset(0)), node); + let throw_idx = self.push_op(Op::JumpIfCatchable, node); + self.push_u16(0); // Opposite of above: If this value is **true**, we can // short-circuit the right-hand side. - let end_idx = self.push_op(OpCode::OpJumpIfTrue(JumpOffset(0)), node); - self.push_op(OpCode::OpPop, node); + let end_idx = self.push_op(Op::JumpIfTrue, node); + self.push_u16(0); + self.push_op(Op::Pop, node); self.compile(slot, node.rhs().unwrap()); self.emit_force(&node.rhs().unwrap()); self.patch_jump(end_idx); - self.push_op(OpCode::OpAssertBool, node); + self.push_op(Op::AssertBool, node); self.patch_jump(throw_idx); } @@ -610,17 +641,20 @@ impl Compiler<'_, '_> { // Leave left-hand side value on the stack and invert it. self.compile(slot, node.lhs().unwrap()); self.emit_force(&node.lhs().unwrap()); - let throw_idx = self.push_op(OpCode::OpJumpIfCatchable(JumpOffset(0)), node); - self.push_op(OpCode::OpInvert, node); + let throw_idx = self.push_op(Op::JumpIfCatchable, node); + self.push_u16(0); + self.push_op(Op::Invert, node); // Exactly as `||` (because `a -> b` = `!a || b`). - let end_idx = self.push_op(OpCode::OpJumpIfTrue(JumpOffset(0)), node); - self.push_op(OpCode::OpPop, node); + let end_idx = self.push_op(Op::JumpIfTrue, node); + self.push_u16(0); + + self.push_op(Op::Pop, node); self.compile(slot, node.rhs().unwrap()); self.emit_force(&node.rhs().unwrap()); self.patch_jump(end_idx); - self.push_op(OpCode::OpAssertBool, node); + self.push_op(Op::AssertBool, node); self.patch_jump(throw_idx); } @@ -655,11 +689,8 @@ impl Compiler<'_, '_> { self.scope_mut().mark_initialised(item_slot); } - if count == 0 { - self.unthunk(); - } - - self.push_op(OpCode::OpList(Count(count)), node); + self.push_op(Op::List, node); + self.push_uvarint(count as u64); self.scope_mut().end_scope(); } @@ -688,7 +719,7 @@ impl Compiler<'_, '_> { // next nested element, for all fragments except the last one. for (count, fragment) in node.attrpath().unwrap().attrs().enumerate() { if count > 0 { - self.push_op(OpCode::OpAttrsTrySelect, &fragment); + self.push_op(Op::AttrsTrySelect, &fragment); self.emit_force(&fragment); } @@ -697,7 +728,7 @@ impl Compiler<'_, '_> { // After the last fragment, emit the actual instruction that // leaves a boolean on the stack. - self.push_op(OpCode::OpHasAttr, node); + self.push_op(Op::HasAttr, node); } /// When compiling select or select_or expressions, an optimisation is @@ -721,8 +752,9 @@ impl Compiler<'_, '_> { // set that is lacking a key, because that thunk is never // evaluated). If anything is missing, just move on. We may // want to emit warnings here in the future. - if let Some(OpCode::OpConstant(ConstantIdx(idx))) = self.chunk().code.last().cloned() { - let constant = &mut self.chunk().constants[idx]; + if let Some((Op::Constant, op_idx)) = self.chunk().last_op() { + let (idx, _) = self.chunk().read_uvarint(op_idx + 1); + let constant = &mut self.chunk().constants[idx as usize]; if let Value::Attrs(attrs) = constant { let mut path_iter = path.attrs(); @@ -734,10 +766,6 @@ impl Compiler<'_, '_> { if let Some(ident) = expr_static_attr_str(&attr) { if let Some(selected_value) = attrs.select(ident.as_bytes()) { *constant = selected_value.clone(); - - // If this worked, we can unthunk the current thunk. - self.unthunk(); - return true; } } @@ -771,7 +799,7 @@ impl Compiler<'_, '_> { self.emit_force(&set); self.compile_attr(slot, &fragment); - self.push_op(OpCode::OpAttrsSelect, &fragment); + self.push_op(Op::AttrsSelect, &fragment); } } @@ -821,11 +849,13 @@ impl Compiler<'_, '_> { for fragment in path.attrs() { self.emit_force(&fragment); self.compile_attr(slot, &fragment.clone()); - self.push_op(OpCode::OpAttrsTrySelect, &fragment); - jumps.push(self.push_op(OpCode::OpJumpIfNotFound(JumpOffset(0)), &fragment)); + self.push_op(Op::AttrsTrySelect, &fragment); + jumps.push(self.push_op(Op::JumpIfNotFound, &fragment)); + self.push_u16(0); } - let final_jump = self.push_op(OpCode::OpJump(JumpOffset(0)), &path); + let final_jump = self.push_op(Op::Jump, &path); + self.push_u16(0); for jump in jumps { self.patch_jump(jump); @@ -853,17 +883,22 @@ impl Compiler<'_, '_> { // Compile the assertion condition to leave its value on the stack. self.compile(slot, node.condition().unwrap()); self.emit_force(&node.condition().unwrap()); - let throw_idx = self.push_op(OpCode::OpJumpIfCatchable(JumpOffset(0)), node); - let then_idx = self.push_op(OpCode::OpJumpIfFalse(JumpOffset(0)), node); - self.push_op(OpCode::OpPop, node); + let throw_idx = self.push_op(Op::JumpIfCatchable, node); + self.push_u16(0); + + let then_idx = self.push_op(Op::JumpIfFalse, node); + self.push_u16(0); + + self.push_op(Op::Pop, node); self.compile(slot, node.body().unwrap()); - let else_idx = self.push_op(OpCode::OpJump(JumpOffset(0)), node); + let else_idx = self.push_op(Op::Jump, node); + self.push_u16(0); self.patch_jump(then_idx); - self.push_op(OpCode::OpPop, node); - self.push_op(OpCode::OpAssertFail, &node.condition().unwrap()); + self.push_op(Op::Pop, node); + self.push_op(Op::AssertFail, &node.condition().unwrap()); self.patch_jump(else_idx); self.patch_jump(throw_idx); @@ -885,22 +920,20 @@ impl Compiler<'_, '_> { self.compile(slot, node.condition().unwrap()); self.emit_force(&node.condition().unwrap()); - let throw_idx = self.push_op( - OpCode::OpJumpIfCatchable(JumpOffset(0)), - &node.condition().unwrap(), - ); - let then_idx = self.push_op( - OpCode::OpJumpIfFalse(JumpOffset(0)), - &node.condition().unwrap(), - ); + let throw_idx = self.push_op(Op::JumpIfCatchable, &node.condition().unwrap()); + self.push_u16(0); - self.push_op(OpCode::OpPop, node); // discard condition value + let then_idx = self.push_op(Op::JumpIfFalse, &node.condition().unwrap()); + self.push_u16(0); + + self.push_op(Op::Pop, node); // discard condition value self.compile(slot, node.body().unwrap()); - let else_idx = self.push_op(OpCode::OpJump(JumpOffset(0)), node); + let else_idx = self.push_op(Op::Jump, node); + self.push_u16(0); self.patch_jump(then_idx); // patch jump *to* else_body - self.push_op(OpCode::OpPop, node); // discard condition value + self.push_op(Op::Pop, node); // discard condition value self.compile(slot, node.else_body().unwrap()); self.patch_jump(else_idx); // patch jump *over* else body @@ -929,11 +962,12 @@ impl Compiler<'_, '_> { self.scope_mut().push_with(); - self.push_op(OpCode::OpPushWith(with_idx), &node.namespace().unwrap()); + self.push_op(Op::PushWith, &node.namespace().unwrap()); + self.push_uvarint(with_idx.0 as u64); self.compile(slot, node.body().unwrap()); - self.push_op(OpCode::OpPopWith, node); + self.push_op(Op::PopWith, node); self.scope_mut().pop_with(); self.cleanup_scope(node); } @@ -993,13 +1027,15 @@ impl Compiler<'_, '_> { // At call time, the attribute set is already at the top of the stack. self.scope_mut().mark_initialised(set_idx); self.emit_force(pattern); - let throw_idx = self.push_op(OpCode::OpJumpIfCatchable(JumpOffset(0)), pattern); + let throw_idx = self.push_op(Op::JumpIfCatchable, pattern); + self.push_u16(0); + // Evaluation fails on a type error, even if the argument(s) are unused. - self.push_op(OpCode::OpAssertAttrs, pattern); + self.push_op(Op::AssertAttrs, pattern); let ellipsis = pattern.ellipsis_token().is_some(); if !ellipsis { - self.push_op(OpCode::OpValidateClosedFormals, pattern); + self.push_op(Op::ValidateClosedFormals, pattern); } // Similar to `let ... in ...`, we now do multiple passes over @@ -1039,7 +1075,8 @@ impl Compiler<'_, '_> { // attempt to select from it. let stack_idx = self.scope().stack_index(set_idx); for tracked_formal in entries.iter() { - self.push_op(OpCode::OpGetLocal(stack_idx), pattern); + self.push_op(Op::GetLocal, pattern); + self.push_uvarint(stack_idx.0 as u64); self.emit_literal_ident(&tracked_formal.pattern_entry().ident().unwrap()); let idx = tracked_formal.local_idx(); @@ -1068,14 +1105,14 @@ impl Compiler<'_, '_> { // we only know better after compiling the default expression, so // avoiding unnecessary locals would mean we'd need to modify the chunk // after the fact. - self.push_op(OpCode::OpAttrsTrySelect, &pattern_entry.ident().unwrap()); - let jump_to_default = - self.push_op(OpCode::OpJumpIfNotFound(JumpOffset(0)), default_expr); + self.push_op(Op::AttrsTrySelect, &pattern_entry.ident().unwrap()); + let jump_to_default = self.push_op(Op::JumpIfNotFound, default_expr); + self.push_u16(0); self.emit_constant(Value::FinaliseRequest(false), default_expr); - let jump_over_default = - self.push_op(OpCode::OpJump(JumpOffset(0)), default_expr); + let jump_over_default = self.push_op(Op::Jump, default_expr); + self.push_u16(0); self.patch_jump(jump_to_default); @@ -1087,7 +1124,7 @@ impl Compiler<'_, '_> { self.patch_jump(jump_over_default); } TrackedFormal::NoDefault { pattern_entry, .. } => { - self.push_op(OpCode::OpAttrsSelect, &pattern_entry.ident().unwrap()); + self.push_op(Op::AttrsSelect, &pattern_entry.ident().unwrap()); } } @@ -1111,23 +1148,16 @@ impl Compiler<'_, '_> { let finalise_request_stack_idx = self.scope().stack_index(*finalise_request_idx); // TODO(sterni): better spans - self.push_op( - OpCode::OpGetLocal(finalise_request_stack_idx), - pattern - ); + self.push_op(Op::GetLocal, pattern); + self.push_uvarint(finalise_request_stack_idx.0 as u64); let jump_over_finalise = - self.push_op( - OpCode::OpJumpIfNoFinaliseRequest( - JumpOffset(0)), - pattern - ); - self.push_op( - OpCode::OpFinalise(stack_idx), - pattern, - ); + self.push_op(Op::JumpIfNoFinaliseRequest, pattern); + self.push_u16(0); + self.push_op(Op::Finalise, pattern); + self.push_uvarint(stack_idx.0 as u64); self.patch_jump(jump_over_finalise); // Get rid of finaliser request value on the stack - self.push_op(OpCode::OpPop, pattern); + self.push_op(Op::Pop, pattern); } } } @@ -1186,12 +1216,6 @@ impl Compiler<'_, '_> { }) } - /// Mark the current thunk as redundant, i.e. possible to merge directly - /// into its parent lambda context without affecting runtime behaviour. - fn unthunk(&mut self) { - self.context_mut().unthunk = true; - } - /// Compile an expression into a runtime closure or thunk fn compile_lambda_or_thunk<N, F>( &mut self, @@ -1220,31 +1244,15 @@ impl Compiler<'_, '_> { self.patch_jump(throw_idx); } - // TODO: determine and insert enclosing name, if available. - // Pop the lambda context back off, and emit the finished // lambda as a constant. let mut compiled = self.contexts.pop().unwrap(); - // The compiler might have decided to unthunk, i.e. raise the compiled - // code to the parent context. In that case we do so and return right - // away. - if compiled.unthunk && is_suspended_thunk { - self.chunk().extend(compiled.lambda.chunk); - return; - } - // Emit an instruction to inform the VM that the chunk has ended. compiled .lambda .chunk - .push_op(OpCode::OpReturn, self.span_for(node)); - - // Capturing the with stack counts as an upvalue, as it is - // emitted as an upvalue data instruction. - if compiled.captures_with_stack { - compiled.lambda.upvalue_count += 1; - } + .push_op(Op::Return, self.span_for(node)); let lambda = Rc::new(compiled.lambda); if is_suspended_thunk { @@ -1254,10 +1262,10 @@ impl Compiler<'_, '_> { } // If no upvalues are captured, emit directly and move on. - if lambda.upvalue_count == 0 { + if lambda.upvalue_count == 0 && !compiled.captures_with_stack { self.emit_constant( if is_suspended_thunk { - Value::Thunk(Thunk::new_suspended(lambda, LightSpan::new_actual(span))) + Value::Thunk(Thunk::new_suspended(lambda, span)) } else { Value::Closure(Rc::new(Closure::new(lambda))) }, @@ -1274,12 +1282,13 @@ impl Compiler<'_, '_> { let code_idx = self.push_op( if is_suspended_thunk { - OpCode::OpThunkSuspended(blueprint_idx) + Op::ThunkSuspended } else { - OpCode::OpThunkClosure(blueprint_idx) + Op::ThunkClosure }, node, ); + self.push_uvarint(blueprint_idx.0 as u64); self.emit_upvalue_data( outer_slot, @@ -1290,18 +1299,21 @@ impl Compiler<'_, '_> { if !is_suspended_thunk && !self.scope()[outer_slot].needs_finaliser { if !self.scope()[outer_slot].must_thunk { - // The closure has upvalues, but is not recursive. Therefore no thunk is required, - // which saves us the overhead of Rc<RefCell<>> - self.chunk()[code_idx] = OpCode::OpClosure(blueprint_idx); + // The closure has upvalues, but is not recursive. Therefore no + // thunk is required, which saves us the overhead of + // Rc<RefCell<>> + self.chunk().code[code_idx.0] = Op::Closure as u8; } else { - // This case occurs when a closure has upvalue-references to itself but does not need a - // finaliser. Since no OpFinalise will be emitted later on we synthesize one here. - // It is needed here only to set [`Closure::is_finalised`] which is used for sanity checks. + // This case occurs when a closure has upvalue-references to + // itself but does not need a finaliser. Since no OpFinalise + // will be emitted later on we synthesize one here. It is needed + // here only to set [`Closure::is_finalised`] which is used for + // sanity checks. #[cfg(debug_assertions)] - self.push_op( - OpCode::OpFinalise(self.scope().stack_index(outer_slot)), - &self.span_for(node), - ); + { + self.push_op(Op::Finalise, &self.span_for(node)); + self.push_uvarint(self.scope().stack_index(outer_slot).0 as u64); + } } } } @@ -1314,7 +1326,7 @@ impl Compiler<'_, '_> { self.compile(slot, node.argument().unwrap()); self.compile(slot, node.lambda().unwrap()); self.emit_force(&node.lambda().unwrap()); - self.push_op(OpCode::OpCall, node); + self.push_op(Op::Call, node); } /// Emit the data instructions that the runtime needs to correctly @@ -1322,10 +1334,18 @@ impl Compiler<'_, '_> { fn emit_upvalue_data<T: ToSpan>( &mut self, slot: LocalIdx, - node: &T, + _: &T, // TODO upvalues: Vec<Upvalue>, capture_with: bool, ) { + // Push the count of arguments to be expected, with one bit set to + // indicate whether the with stack needs to be captured. + let mut count = (upvalues.len() as u64) << 1; + if capture_with { + count |= 1; + } + self.push_uvarint(count); + for upvalue in upvalues { match upvalue.kind { UpvalueKind::Local(idx) => { @@ -1335,27 +1355,22 @@ impl Compiler<'_, '_> { // If the target is not yet initialised, we need to defer // the local access if !target.initialised { - self.push_op(OpCode::DataDeferredLocal(stack_idx), &upvalue.span); + self.push_uvarint(Position::deferred_local(stack_idx).0); self.scope_mut().mark_needs_finaliser(slot); } else { // a self-reference if slot == idx { self.scope_mut().mark_must_thunk(slot); } - self.push_op(OpCode::DataStackIdx(stack_idx), &upvalue.span); + self.push_uvarint(Position::stack_index(stack_idx).0); } } UpvalueKind::Upvalue(idx) => { - self.push_op(OpCode::DataUpvalueIdx(idx), &upvalue.span); + self.push_uvarint(Position::upvalue_index(idx).0); } }; } - - if capture_with { - // TODO(tazjin): probably better to emit span for the ident that caused this - self.push_op(OpCode::DataCaptureWith, node); - } } /// Emit the literal string value of an identifier. Required for @@ -1372,20 +1387,7 @@ impl Compiler<'_, '_> { /// not known at the time when the jump operation itself is /// emitted. fn patch_jump(&mut self, idx: CodeIdx) { - let offset = JumpOffset(self.chunk().code.len() - 1 - idx.0); - - match &mut self.chunk().code[idx.0] { - OpCode::OpJump(n) - | OpCode::OpJumpIfFalse(n) - | OpCode::OpJumpIfTrue(n) - | OpCode::OpJumpIfCatchable(n) - | OpCode::OpJumpIfNotFound(n) - | OpCode::OpJumpIfNoFinaliseRequest(n) => { - *n = offset; - } - - op => panic!("attempted to patch unsupported op: {:?}", op), - } + self.chunk().patch_jump(idx.0); } /// Decrease scope depth of the current function and emit @@ -1401,7 +1403,8 @@ impl Compiler<'_, '_> { } if popcount > 0 { - self.push_op(OpCode::OpCloseScope(Count(popcount)), node); + self.push_op(Op::CloseScope, node); + self.push_uvarint(popcount as u64); } } @@ -1459,16 +1462,7 @@ impl Compiler<'_, '_> { } fn emit_force<N: ToSpan>(&mut self, node: &N) { - if let Some(&OpCode::OpConstant(c)) = self.chunk().last_op() { - if !self.chunk().get_constant(c).unwrap().is_thunk() { - // Optimization: Don't emit a force op for non-thunk constants, since they don't - // need one! - // TODO: this is probably doable for more ops (?) - return; - } - } - - self.push_op(OpCode::OpForce, node); + self.push_op(Op::Force, node); } fn emit_warning<N: ToSpan>(&mut self, node: &N, kind: WarningKind) { @@ -1549,6 +1543,7 @@ fn compile_src_builtin( &parsed.tree().expr().unwrap(), None, weak.upgrade().unwrap(), + None, &source, &file, &mut crate::observer::NoOpObserver {}, @@ -1565,10 +1560,7 @@ fn compile_src_builtin( }); } - Ok(Value::Thunk(Thunk::new_suspended( - result.lambda, - LightSpan::Actual { span: file.span }, - ))) + Ok(Value::Thunk(Thunk::new_suspended(result.lambda, file.span))) }))) } @@ -1589,7 +1581,7 @@ pub fn prepare_globals( Rc::new_cyclic(Box::new(move |weak: &Weak<GlobalsMap>| { // First step is to construct the builtins themselves as // `NixAttrs`. - let mut builtins: GlobalsMap = HashMap::from_iter(builtins); + let mut builtins: GlobalsMap = FxHashMap::from_iter(builtins); // At this point, optionally insert `import` if enabled. To // "tie the knot" of `import` needing the full set of globals @@ -1602,7 +1594,7 @@ pub fn prepare_globals( // Next, the actual map of globals which the compiler will use // to resolve identifiers is constructed. - let mut globals: GlobalsMap = HashMap::new(); + let mut globals: GlobalsMap = FxHashMap::default(); // builtins contain themselves (`builtins.builtins`), which we // can resolve by manually constructing a suspended thunk that @@ -1655,11 +1647,12 @@ pub fn compile( expr: &ast::Expr, location: Option<PathBuf>, globals: Rc<GlobalsMap>, + env: Option<&FxHashMap<SmolStr, Value>>, source: &SourceCode, file: &codemap::File, observer: &mut dyn CompilerObserver, ) -> EvalResult<CompilationOutput> { - let mut c = Compiler::new(location, globals.clone(), source, file, observer)?; + let mut c = Compiler::new(location, globals.clone(), env, source, file, observer)?; let root_span = c.span_for(expr); let root_slot = c.scope_mut().declare_phantom(root_span, false); @@ -1670,7 +1663,13 @@ pub fn compile( // unevaluated state (though in practice, a value *containing* a // thunk might be returned). c.emit_force(expr); - c.push_op(OpCode::OpReturn, &root_span); + if let Some(env) = env { + if !env.is_empty() { + c.push_op(Op::CloseScope, &root_span); + c.push_uvarint(env.len() as u64); + } + } + c.push_op(Op::Return, &root_span); let lambda = Rc::new(c.contexts.pop().unwrap().lambda); c.observer.observe_compiled_toplevel(&lambda); @@ -1679,6 +1678,5 @@ pub fn compile( lambda, warnings: c.warnings, errors: c.errors, - globals, }) } diff --git a/tvix/eval/src/compiler/scope.rs b/tvix/eval/src/compiler/scope.rs index 892727c107c9..b8cd855ecde5 100644 --- a/tvix/eval/src/compiler/scope.rs +++ b/tvix/eval/src/compiler/scope.rs @@ -10,10 +10,8 @@ //! stack indices. To do this, the compiler simulates where locals //! will be at runtime using the data structures implemented here. -use std::{ - collections::{hash_map, HashMap}, - ops::Index, -}; +use rustc_hash::FxHashMap; +use std::{collections::hash_map, ops::Index}; use smol_str::SmolStr; @@ -38,7 +36,7 @@ pub struct Local { name: LocalName, /// Source span at which this local was declared. - pub span: codemap::Span, + pub span: Option<codemap::Span>, /// Scope depth of this local. pub depth: usize, @@ -73,6 +71,10 @@ impl Local { LocalName::Phantom => false, } } + + pub fn is_used(&self) -> bool { + self.depth == 0 || self.used || self.is_ignored() + } } /// Represents the current position of an identifier as resolved in a scope. @@ -103,7 +105,6 @@ pub enum UpvalueKind { #[derive(Clone, Debug)] pub struct Upvalue { pub kind: UpvalueKind, - pub span: codemap::Span, } /// The index of a local in the scope's local array at compile time. @@ -164,7 +165,7 @@ pub struct Scope { pub upvalues: Vec<Upvalue>, /// Secondary by-name index over locals. - by_name: HashMap<String, ByName>, + by_name: FxHashMap<String, ByName>, /// How many scopes "deep" are these locals? scope_depth: usize, @@ -240,7 +241,7 @@ impl Scope { let idx = self.locals.len(); self.locals.push(Local { initialised, - span, + span: Some(span), name: LocalName::Phantom, depth: self.scope_depth, needs_finaliser: false, @@ -263,7 +264,7 @@ impl Scope { let idx = LocalIdx(self.locals.len()); self.locals.push(Local { name: LocalName::Ident(name.clone()), - span, + span: Some(span), depth: self.scope_depth, initialised: false, needs_finaliser: false, @@ -286,6 +287,23 @@ impl Scope { (idx, shadowed) } + pub fn declare_constant(&mut self, name: String) -> LocalIdx { + let idx = LocalIdx(self.locals.len()); + self.locals.push(Local { + name: LocalName::Ident(name.clone()), + span: None, + depth: 0, + initialised: true, + used: false, + needs_finaliser: false, + must_thunk: false, + }); + // We don't need to worry about shadowing for constants; they're defined at the toplevel + // always + self.by_name.insert(name, ByName::Single(idx)); + idx + } + /// Mark local as initialised after compiling its expression. pub fn mark_initialised(&mut self, idx: LocalIdx) { self.locals[idx.0].initialised = true; @@ -348,8 +366,8 @@ impl Scope { // lifetime, and emit a warning otherwise (unless the // user explicitly chose to ignore it by prefixing the // identifier with `_`) - if !local.used && !local.is_ignored() { - unused_spans.push(local.span); + if !local.is_used() { + unused_spans.extend(local.span); } // remove the by-name index if this was a named local diff --git a/tvix/eval/src/errors.rs b/tvix/eval/src/errors.rs index 652252dadfa0..9c3383fc5d94 100644 --- a/tvix/eval/src/errors.rs +++ b/tvix/eval/src/errors.rs @@ -10,7 +10,6 @@ use std::{fmt::Debug, fmt::Display, num::ParseIntError}; use codemap::{File, Span}; use codemap_diagnostic::{ColorConfig, Diagnostic, Emitter, Level, SpanLabel, SpanStyle}; use smol_str::SmolStr; -use xml::writer::Error as XmlError; use crate::spans::ToSpan; use crate::value::{CoercionKind, NixString}; @@ -36,96 +35,109 @@ use crate::{SourceCode, Value}; /// because Rust's magic `?`-syntax does not work on nested Result /// values like this. // TODO(amjoseph): investigate result<T,Either<CatchableErrorKind,ErrorKind>> -#[derive(Clone, Debug)] +#[derive(thiserror::Error, Clone, Debug)] pub enum CatchableErrorKind { + #[error("error thrown: {0}")] Throw(Box<str>), + + #[error("assertion failed")] AssertionFailed, + + #[error("feature {0} is not implemented yet")] UnimplementedFeature(Box<str>), + /// Resolving a user-supplied angle brackets path literal failed in some way. + #[error("Nix path entry could not be resolved: {0}")] NixPathResolution(Box<str>), } -impl Display for CatchableErrorKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - CatchableErrorKind::Throw(s) => write!(f, "error thrown: {}", s), - CatchableErrorKind::AssertionFailed => write!(f, "assertion failed"), - CatchableErrorKind::UnimplementedFeature(s) => { - write!(f, "feature {} is not implemented yet", s) - } - CatchableErrorKind::NixPathResolution(s) => { - write!(f, "Nix path entry could not be resolved: {}", s) - } - } - } -} - -#[derive(Clone, Debug)] +#[derive(thiserror::Error, Clone, Debug)] pub enum ErrorKind { /// These are user-generated errors through builtins. + #[error("evaluation aborted: {0}")] Abort(String), + #[error("division by zero")] DivisionByZero, - DuplicateAttrsKey { - key: String, - }, + #[error("attribute key '{key}' already defined")] + DuplicateAttrsKey { key: String }, /// Attempted to specify an invalid key type (e.g. integer) in a /// dynamic attribute name. + #[error( + "found attribute name '{0}' of type '{}', but attribute names must be strings", + .0.type_of() + )] InvalidAttributeName(Value), - AttributeNotFound { - name: String, - }, + #[error("attribute with name '{name}' could not be found in the set")] + AttributeNotFound { name: String }, /// Attempted to index into a list beyond its boundaries. - IndexOutOfBounds { - index: i64, - }, + #[error("list index '{index}' is out of bounds")] + IndexOutOfBounds { index: i64 }, /// Attempted to call `builtins.tail` on an empty list. + #[error("'tail' called on an empty list")] TailEmptyList, + #[error("expected value of type '{expected}', but found a '{actual}'")] TypeError { expected: &'static str, actual: &'static str, }, + #[error("can not compare a {lhs} with a {rhs}")] Incomparable { lhs: &'static str, rhs: &'static str, }, /// Resolving a user-supplied relative or home-relative path literal failed in some way. + #[error("could not resolve path: {0}")] RelativePathResolution(String), /// Dynamic keys are not allowed in some scopes. + #[error("dynamically evaluated keys are not allowed in {0}")] DynamicKeyInScope(&'static str), /// Unknown variable in statically known scope. + #[error("variable not found")] UnknownStaticVariable, /// Unknown variable in dynamic scope (with, rec, ...). + #[error( + r#"variable '{0}' could not be found + +Note that this occured within a `with`-expression. The problem may be related +to a missing value in the attribute set(s) included via `with`."# + )] UnknownDynamicVariable(String), /// User is defining the same variable twice at the same depth. - VariableAlreadyDefined(Span), + #[error("variable has already been defined")] + VariableAlreadyDefined(Option<Span>), /// Attempt to call something that is not callable. + #[error("only functions and builtins can be called, but this is a '{0}'")] NotCallable(&'static str), /// Infinite recursion encountered while forcing thunks. + #[error("infinite recursion encountered")] InfiniteRecursion { first_force: Span, suspended_at: Option<Span>, content_span: Option<Span>, }, + // Errors themselves ignored here & handled in Self::spans instead + #[error("failed to parse Nix code:")] ParseErrors(Vec<rnix::parser::ParseError>), /// An error occured while executing some native code (e.g. a /// builtin), and needs to be chained up. + #[error("while evaluating this as native code ({gen_type})")] NativeError { gen_type: &'static str, err: Box<Error>, @@ -133,31 +145,44 @@ pub enum ErrorKind { /// An error occured while executing Tvix bytecode, but needs to /// be chained up. + #[error("while evaluating this Nix code")] BytecodeError(Box<Error>), /// Given type can't be coerced to a string in the respective context + #[error("cannot ({}) coerce {from} to a string{}", + (if .kind.strong { "strongly" } else { "weakly" }), + (if *.from == "set" { + ", missing a `__toString` or `outPath` attribute" + } else { + "" + }) + )] NotCoercibleToString { from: &'static str, kind: CoercionKind, }, /// The given string doesn't represent an absolute path + #[error("string '{}' does not represent an absolute path", .0.to_string_lossy())] NotAnAbsolutePath(PathBuf), /// An error occurred when parsing an integer + #[error("invalid integer: {0}")] ParseIntError(ParseIntError), // Errors specific to nested attribute sets and merges thereof. /// Nested attributes can not be merged with an inherited value. - UnmergeableInherit { - name: SmolStr, - }, + #[error("cannot merge a nested attribute set into the inherited entry '{name}'")] + UnmergeableInherit { name: SmolStr }, /// Nested attributes can not be merged with values that are not /// literal attribute sets. + #[error("nested attribute sets or keys can only be merged with literal attribute sets")] UnmergeableValue, + // Errors themselves ignored here & handled in Self::spans instead /// Parse errors occured while importing a file. + #[error("parse errors occured while importing '{}'", .path.to_string_lossy())] ImportParseError { path: PathBuf, file: Arc<File>, @@ -165,44 +190,70 @@ pub enum ErrorKind { }, /// Compilation errors occured while importing a file. - ImportCompilerError { - path: PathBuf, - errors: Vec<Error>, - }, + #[error("compiler errors occured while importing '{}'", .path.to_string_lossy())] + ImportCompilerError { path: PathBuf, errors: Vec<Error> }, /// I/O errors + #[error("I/O error: {}", + ({ + let mut msg = String::new(); + + if let Some(path) = .path { + msg.push_str(&format!("{}: ", path.display())); + } + + msg.push_str(&.error.to_string()); + + msg + }) + )] IO { path: Option<PathBuf>, error: Rc<io::Error>, }, /// Errors parsing JSON, or serializing as JSON. + #[error("Error converting JSON to a Nix value or back: {0}")] JsonError(String), /// Nix value that can not be serialised to JSON. + #[error("a {0} cannot be converted to JSON")] NotSerialisableToJson(&'static str), /// Errors converting TOML to a value + #[error("Error converting TOML to a Nix value: {0}")] FromTomlError(String), + /// An unexpected argument was supplied to a builtin + #[error("Unexpected agrument `{0}` passed to builtin")] + UnexpectedArgumentBuiltin(NixString), + /// An unexpected argument was supplied to a function that takes formal parameters - UnexpectedArgument { - arg: NixString, - formals_span: Span, - }, + #[error("Unexpected argument `{arg}` supplied to function")] + UnexpectedArgumentFormals { arg: NixString, formals_span: Span }, /// Invalid UTF-8 was encoutered somewhere + #[error("Invalid UTF-8 in string")] Utf8, - /// Errors while serialising to XML. - Xml(Rc<XmlError>), - /// Variant for errors that bubble up to eval from other Tvix /// components. + #[error("{0}")] TvixError(Rc<dyn error::Error>), /// Variant for code paths that are known bugs in Tvix (usually /// issues with the compiler/VM interaction). + #[error("{}", + ({ + let mut disp = format!("Tvix bug: {}", .msg); + + if let Some(metadata) = .metadata { + disp.push_str(&format!("; metadata: {:?}", metadata)); + } + + disp + }) + )] TvixBug { msg: &'static str, metadata: Option<Rc<dyn Debug>>, @@ -211,15 +262,18 @@ pub enum ErrorKind { /// Tvix internal warning for features triggered by users that are /// not actually implemented yet, and without which eval can not /// proceed. + #[error("feature not yet implemented in Tvix: {0}")] NotImplemented(&'static str), /// Internal variant which should disappear during error construction. + #[error("internal ErrorKind::WithContext variant leaked")] WithContext { context: String, underlying: Box<ErrorKind>, }, /// Unexpected context string + #[error("unexpected context string")] UnexpectedContext, /// Top-level evaluation result was a catchable Nix error, and @@ -228,10 +282,12 @@ pub enum ErrorKind { /// This variant **must** only be used at the top-level of /// tvix-eval when returning a result to the user, never inside of /// eval code. + #[error("{0}")] CatchableError(CatchableErrorKind), /// Invalid hash type specified, must be one of "md5", "sha1", "sha256" /// or "sha512" + #[error("unknown hash type '{0}'")] UnknownHashType(String), } @@ -248,7 +304,6 @@ impl error::Error for Error { errors.first().map(|e| e as &dyn error::Error) } ErrorKind::IO { error, .. } => Some(error.as_ref()), - ErrorKind::Xml(error) => Some(error.as_ref()), ErrorKind::TvixError(error) => Some(error.as_ref()), _ => None, } @@ -285,12 +340,6 @@ impl From<bstr::FromUtf8Error> for ErrorKind { } } -impl From<XmlError> for ErrorKind { - fn from(err: XmlError) -> Self { - Self::Xml(Rc::new(err)) - } -} - impl From<io::Error> for ErrorKind { fn from(e: io::Error) -> Self { ErrorKind::IO { @@ -342,209 +391,6 @@ impl Error { } } -impl Display for ErrorKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match &self { - ErrorKind::Abort(msg) => write!(f, "evaluation aborted: {}", msg), - - ErrorKind::DivisionByZero => write!(f, "division by zero"), - - ErrorKind::DuplicateAttrsKey { key } => { - write!(f, "attribute key '{}' already defined", key) - } - - ErrorKind::InvalidAttributeName(val) => write!( - f, - "found attribute name '{}' of type '{}', but attribute names must be strings", - val, - val.type_of() - ), - - ErrorKind::AttributeNotFound { name } => write!( - f, - "attribute with name '{}' could not be found in the set", - name - ), - - ErrorKind::IndexOutOfBounds { index } => { - write!(f, "list index '{}' is out of bounds", index) - } - - ErrorKind::TailEmptyList => write!(f, "'tail' called on an empty list"), - - ErrorKind::TypeError { expected, actual } => write!( - f, - "expected value of type '{}', but found a '{}'", - expected, actual - ), - - ErrorKind::Incomparable { lhs, rhs } => { - write!(f, "can not compare a {} with a {}", lhs, rhs) - } - - ErrorKind::RelativePathResolution(err) => { - write!(f, "could not resolve path: {}", err) - } - - ErrorKind::DynamicKeyInScope(scope) => { - write!(f, "dynamically evaluated keys are not allowed in {}", scope) - } - - ErrorKind::UnknownStaticVariable => write!(f, "variable not found"), - - ErrorKind::UnknownDynamicVariable(name) => write!( - f, - r#"variable '{}' could not be found - -Note that this occured within a `with`-expression. The problem may be related -to a missing value in the attribute set(s) included via `with`."#, - name - ), - - ErrorKind::VariableAlreadyDefined(_) => write!(f, "variable has already been defined"), - - ErrorKind::NotCallable(other_type) => { - write!( - f, - "only functions and builtins can be called, but this is a '{}'", - other_type - ) - } - - ErrorKind::InfiniteRecursion { .. } => write!(f, "infinite recursion encountered"), - - // Errors themselves ignored here & handled in Self::spans instead - ErrorKind::ParseErrors(_) => write!(f, "failed to parse Nix code:"), - - ErrorKind::NativeError { gen_type, .. } => { - write!(f, "while evaluating this as native code ({})", gen_type) - } - - ErrorKind::BytecodeError(_) => write!(f, "while evaluating this Nix code"), - - ErrorKind::NotCoercibleToString { kind, from } => { - let kindly = if kind.strong { "strongly" } else { "weakly" }; - - let hint = if *from == "set" { - ", missing a `__toString` or `outPath` attribute" - } else { - "" - }; - - write!(f, "cannot ({kindly}) coerce {from} to a string{hint}") - } - - ErrorKind::NotAnAbsolutePath(given) => { - write!( - f, - "string '{}' does not represent an absolute path", - given.to_string_lossy() - ) - } - - ErrorKind::ParseIntError(err) => { - write!(f, "invalid integer: {}", err) - } - - ErrorKind::UnmergeableInherit { name } => { - write!( - f, - "cannot merge a nested attribute set into the inherited entry '{}'", - name - ) - } - - ErrorKind::UnmergeableValue => { - write!( - f, - "nested attribute sets or keys can only be merged with literal attribute sets" - ) - } - - // Errors themselves ignored here & handled in Self::spans instead - ErrorKind::ImportParseError { path, .. } => { - write!( - f, - "parse errors occured while importing '{}'", - path.to_string_lossy() - ) - } - - ErrorKind::ImportCompilerError { path, .. } => { - writeln!( - f, - "compiler errors occured while importing '{}'", - path.to_string_lossy() - ) - } - - ErrorKind::IO { path, error } => { - write!(f, "I/O error: ")?; - if let Some(path) = path { - write!(f, "{}: ", path.display())?; - } - write!(f, "{error}") - } - - ErrorKind::JsonError(msg) => { - write!(f, "Error converting JSON to a Nix value or back: {msg}") - } - - ErrorKind::NotSerialisableToJson(_type) => { - write!(f, "a {} cannot be converted to JSON", _type) - } - - ErrorKind::FromTomlError(msg) => { - write!(f, "Error converting TOML to a Nix value: {msg}") - } - - ErrorKind::UnexpectedArgument { arg, .. } => { - write!(f, "Unexpected argument `{arg}` supplied to function",) - } - - ErrorKind::Utf8 => { - write!(f, "Invalid UTF-8 in string") - } - - ErrorKind::Xml(error) => write!(f, "failed to serialise to XML: {error}"), - - ErrorKind::TvixError(inner_error) => { - write!(f, "{inner_error}") - } - - ErrorKind::TvixBug { msg, metadata } => { - write!(f, "Tvix bug: {}", msg)?; - - if let Some(metadata) = metadata { - write!(f, "; metadata: {:?}", metadata)?; - } - - Ok(()) - } - - ErrorKind::NotImplemented(feature) => { - write!(f, "feature not yet implemented in Tvix: {}", feature) - } - - ErrorKind::WithContext { .. } => { - panic!("internal ErrorKind::WithContext variant leaked") - } - - ErrorKind::UnexpectedContext => { - write!(f, "unexpected context string") - } - - ErrorKind::CatchableError(inner) => { - write!(f, "{}", inner) - } - - ErrorKind::UnknownHashType(hash_type) => { - write!(f, "unknown hash type '{}'", hash_type) - } - } - } -} - impl Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.kind) @@ -791,7 +637,8 @@ impl Error { ErrorKind::DuplicateAttrsKey { .. } => "in this attribute set", ErrorKind::InvalidAttributeName(_) => "in this attribute set", ErrorKind::RelativePathResolution(_) => "in this path literal", - ErrorKind::UnexpectedArgument { .. } => "in this function call", + ErrorKind::UnexpectedArgumentBuiltin { .. } => "while calling this builtin", + ErrorKind::UnexpectedArgumentFormals { .. } => "in this function call", ErrorKind::UnexpectedContext => "in this string", // The spans for some errors don't have any more descriptive stuff @@ -823,7 +670,6 @@ impl Error { | ErrorKind::JsonError(_) | ErrorKind::NotSerialisableToJson(_) | ErrorKind::FromTomlError(_) - | ErrorKind::Xml(_) | ErrorKind::Utf8 | ErrorKind::TvixError(_) | ErrorKind::TvixBug { .. } @@ -867,15 +713,15 @@ impl Error { ErrorKind::ImportCompilerError { .. } => "E028", ErrorKind::IO { .. } => "E029", ErrorKind::JsonError { .. } => "E030", - ErrorKind::UnexpectedArgument { .. } => "E031", + ErrorKind::UnexpectedArgumentFormals { .. } => "E031", ErrorKind::RelativePathResolution(_) => "E032", ErrorKind::DivisionByZero => "E033", - ErrorKind::Xml(_) => "E034", ErrorKind::FromTomlError(_) => "E035", ErrorKind::NotSerialisableToJson(_) => "E036", ErrorKind::UnexpectedContext => "E037", ErrorKind::Utf8 => "E038", ErrorKind::UnknownHashType(_) => "E039", + ErrorKind::UnexpectedArgumentBuiltin { .. } => "E040", // Special error code for errors from other Tvix // components. We may want to introduce a code namespacing @@ -913,7 +759,7 @@ impl Error { spans_for_parse_errors(&file, errors) } - ErrorKind::UnexpectedArgument { formals_span, .. } => { + ErrorKind::UnexpectedArgumentFormals { formals_span, .. } => { vec![ SpanLabel { label: self.span_label(), diff --git a/tvix/eval/src/io.rs b/tvix/eval/src/io.rs index f775077af818..f30ef164c41a 100644 --- a/tvix/eval/src/io.rs +++ b/tvix/eval/src/io.rs @@ -16,15 +16,17 @@ //! how store paths are opened and so on. use std::{ - fs::File, io, path::{Path, PathBuf}, }; -#[cfg(target_family = "unix")] +#[cfg(all(target_family = "unix", feature = "impure"))] use std::os::unix::ffi::OsStringExt; -/// Types of files as represented by `builtins.readDir` in Nix. +#[cfg(feature = "impure")] +use std::fs::File; + +/// Types of files as represented by `builtins.readFileType` and `builtins.readDir` in Nix. #[derive(Debug)] pub enum FileType { Directory, @@ -33,6 +35,33 @@ pub enum FileType { Unknown, } +impl std::fmt::Display for FileType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let type_as_str = match &self { + FileType::Directory => "directory", + FileType::Regular => "regular", + FileType::Symlink => "symlink", + FileType::Unknown => "unknown", + }; + + write!(f, "{}", type_as_str) + } +} + +impl From<std::fs::FileType> for FileType { + fn from(value: std::fs::FileType) -> Self { + if value.is_file() { + Self::Regular + } else if value.is_dir() { + Self::Directory + } else if value.is_symlink() { + Self::Symlink + } else { + Self::Unknown + } + } +} + /// Represents all possible filesystem interactions that exist in the Nix /// language, and that need to be executed somehow. /// @@ -52,6 +81,10 @@ pub trait EvalIO { /// Open the file at the specified path to a `io::Read`. fn open(&self, path: &Path) -> io::Result<Box<dyn io::Read>>; + /// Return the [FileType] of the given path, or an error if it doesn't + /// exist. + fn file_type(&self, path: &Path) -> io::Result<FileType>; + /// Read the directory at the specified path and return the names /// of its entries associated with their [`FileType`]. /// @@ -92,13 +125,28 @@ pub struct StdIO; #[cfg(feature = "impure")] impl EvalIO for StdIO { fn path_exists(&self, path: &Path) -> io::Result<bool> { - path.try_exists() + // In general, an IO error indicates the path doesn't exist + Ok(path.try_exists().unwrap_or(false)) } fn open(&self, path: &Path) -> io::Result<Box<dyn io::Read>> { Ok(Box::new(File::open(path)?)) } + fn file_type(&self, path: &Path) -> io::Result<FileType> { + let file_type = std::fs::symlink_metadata(path)?; + + Ok(if file_type.is_dir() { + FileType::Directory + } else if file_type.is_file() { + FileType::Regular + } else if file_type.is_symlink() { + FileType::Symlink + } else { + FileType::Unknown + }) + } + fn read_dir(&self, path: &Path) -> io::Result<Vec<(bytes::Bytes, FileType)>> { let mut result = vec![]; @@ -148,6 +196,13 @@ impl EvalIO for DummyIO { )) } + fn file_type(&self, _: &Path) -> io::Result<FileType> { + Err(io::Error::new( + io::ErrorKind::Unsupported, + "I/O methods are not implemented in DummyIO", + )) + } + fn read_dir(&self, _: &Path) -> io::Result<Vec<(bytes::Bytes, FileType)>> { Err(io::Error::new( io::ErrorKind::Unsupported, diff --git a/tvix/eval/src/lib.rs b/tvix/eval/src/lib.rs index 845964cb7e00..a4ef3f01e40a 100644 --- a/tvix/eval/src/lib.rs +++ b/tvix/eval/src/lib.rs @@ -29,87 +29,349 @@ mod vm; mod warnings; mod nix_search_path; -#[cfg(test)] +#[cfg(all(test, feature = "arbitrary"))] mod properties; #[cfg(test)] mod test_utils; #[cfg(test)] mod tests; +use rustc_hash::FxHashMap; use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; use std::sync::Arc; -use crate::compiler::GlobalsMap; use crate::observer::{CompilerObserver, RuntimeObserver}; use crate::value::Lambda; use crate::vm::run_lambda; // Re-export the public interface used by other crates. -pub use crate::compiler::{compile, prepare_globals, CompilationOutput}; +pub use crate::compiler::{compile, prepare_globals, CompilationOutput, GlobalsMap}; pub use crate::errors::{AddContext, CatchableErrorKind, Error, ErrorKind, EvalResult}; pub use crate::io::{DummyIO, EvalIO, FileType}; pub use crate::pretty_ast::pretty_print_expr; pub use crate::source::SourceCode; pub use crate::value::{NixContext, NixContextElement}; -pub use crate::vm::generators; +pub use crate::vm::{generators, EvalMode}; pub use crate::warnings::{EvalWarning, WarningKind}; pub use builtin_macros; +use smol_str::SmolStr; pub use crate::value::{Builtin, CoercionKind, NixAttrs, NixList, NixString, Value}; #[cfg(feature = "impure")] pub use crate::io::StdIO; +struct BuilderBuiltins { + builtins: Vec<(&'static str, Value)>, + src_builtins: Vec<(&'static str, &'static str)>, +} + +enum BuilderGlobals { + Builtins(BuilderBuiltins), + Globals(Rc<GlobalsMap>), +} + +/// Builder for building an [`Evaluation`]. +/// +/// Construct an [`EvaluationBuilder`] by calling one of: +/// +/// - [`Evaluation::builder`] / [`EvaluationBuilder::new`] +/// - [`Evaluation::builder_impure`] [`EvaluationBuilder::new_impure`] +/// - [`Evaluation::builder_pure`] [`EvaluationBuilder::new_pure`] +/// +/// Then configure the fields by calling the various methods on [`EvaluationBuilder`], and finally +/// call [`build`](Self::build) to construct an [`Evaluation`] +pub struct EvaluationBuilder<'co, 'ro, 'env, IO> { + source_map: Option<SourceCode>, + globals: BuilderGlobals, + env: Option<&'env FxHashMap<SmolStr, Value>>, + io_handle: IO, + enable_import: bool, + mode: EvalMode, + nix_path: Option<String>, + compiler_observer: Option<&'co mut dyn CompilerObserver>, + runtime_observer: Option<&'ro mut dyn RuntimeObserver>, +} + +impl<'co, 'ro, 'env, IO> EvaluationBuilder<'co, 'ro, 'env, IO> +where + IO: AsRef<dyn EvalIO> + 'static, +{ + /// Build an [`Evaluation`] based on the configuration in this builder. + /// + /// This: + /// + /// - Adds a `"storeDir"` builtin containing the store directory of the configured IO handle + /// - Sets up globals based on the configured builtins + /// - Copies all other configured fields to the [`Evaluation`] + pub fn build(self) -> Evaluation<'co, 'ro, 'env, IO> { + let source_map = self.source_map.unwrap_or_default(); + + let globals = match self.globals { + BuilderGlobals::Globals(globals) => globals, + BuilderGlobals::Builtins(BuilderBuiltins { + mut builtins, + src_builtins, + }) => { + // Insert a storeDir builtin *iff* a store directory is present. + if let Some(store_dir) = self.io_handle.as_ref().store_dir() { + builtins.push(("storeDir", store_dir.into())); + } + + crate::compiler::prepare_globals( + builtins, + src_builtins, + source_map.clone(), + self.enable_import, + ) + } + }; + + Evaluation { + source_map, + globals, + env: self.env, + io_handle: self.io_handle, + mode: self.mode, + nix_path: self.nix_path, + compiler_observer: self.compiler_observer, + runtime_observer: self.runtime_observer, + } + } +} + +// NOTE(aspen): The methods here are intentionally incomplete; feel free to add new ones (ideally +// with similar naming conventions to the ones already present) but don't expose fields publically! +impl<'co, 'ro, 'env, IO> EvaluationBuilder<'co, 'ro, 'env, IO> { + pub fn new(io_handle: IO) -> Self { + let mut builtins = builtins::pure_builtins(); + builtins.extend(builtins::placeholders()); // these are temporary + + Self { + source_map: None, + enable_import: false, + io_handle, + globals: BuilderGlobals::Builtins(BuilderBuiltins { + builtins, + src_builtins: vec![], + }), + env: None, + mode: Default::default(), + nix_path: None, + compiler_observer: None, + runtime_observer: None, + } + } + + pub fn io_handle<IO2>(self, io_handle: IO2) -> EvaluationBuilder<'co, 'ro, 'env, IO2> { + EvaluationBuilder { + io_handle, + source_map: self.source_map, + globals: self.globals, + env: self.env, + enable_import: self.enable_import, + mode: self.mode, + nix_path: self.nix_path, + compiler_observer: self.compiler_observer, + runtime_observer: self.runtime_observer, + } + } + + pub fn with_enable_import(self, enable_import: bool) -> Self { + Self { + enable_import, + ..self + } + } + + pub fn disable_import(self) -> Self { + self.with_enable_import(false) + } + + pub fn enable_import(self) -> Self { + self.with_enable_import(true) + } + + fn builtins_mut(&mut self) -> &mut BuilderBuiltins { + match &mut self.globals { + BuilderGlobals::Builtins(builtins) => builtins, + BuilderGlobals::Globals(_) => { + panic!("Cannot modify builtins on an EvaluationBuilder with globals configured") + } + } + } + + /// Add additional builtins (represented as tuples of name and [`Value`]) to this evaluation + /// builder. + /// + /// # Panics + /// + /// Panics if this evaluation builder has had globals set via [`with_globals`] + pub fn add_builtins<I>(mut self, builtins: I) -> Self + where + I: IntoIterator<Item = (&'static str, Value)>, + { + self.builtins_mut().builtins.extend(builtins); + self + } + + /// Add additional builtins that are implemented in Nix source code (represented as tuples of + /// name and nix source) to this evaluation builder. + /// + /// # Panics + /// + /// Panics if this evaluation builder has had globals set via [`with_globals`] + pub fn add_src_builtin(mut self, name: &'static str, src: &'static str) -> Self { + self.builtins_mut().src_builtins.push((name, src)); + self + } + + /// Set the globals for this evaluation builder to a previously-constructed globals map. + /// Intended to allow sharing globals across multiple evaluations (eg for the REPL). + /// + /// Discards any builtins previously configured via [`add_builtins`] and [`add_src_builtins`]. + /// If either of those methods is called on the evaluation builder after this one, they will + /// panic. + pub fn with_globals(self, globals: Rc<GlobalsMap>) -> Self { + Self { + globals: BuilderGlobals::Globals(globals), + ..self + } + } + + pub fn with_source_map(self, source_map: SourceCode) -> Self { + debug_assert!( + self.source_map.is_none(), + "Cannot set the source_map on an EvaluationBuilder twice" + ); + Self { + source_map: Some(source_map), + ..self + } + } + + pub fn mode(self, mode: EvalMode) -> Self { + Self { mode, ..self } + } + + pub fn nix_path(self, nix_path: Option<String>) -> Self { + Self { nix_path, ..self } + } + + pub fn env(self, env: Option<&'env FxHashMap<SmolStr, Value>>) -> Self { + Self { env, ..self } + } + + pub fn compiler_observer( + self, + compiler_observer: Option<&'co mut dyn CompilerObserver>, + ) -> Self { + Self { + compiler_observer, + ..self + } + } + + pub fn set_compiler_observer( + &mut self, + compiler_observer: Option<&'co mut dyn CompilerObserver>, + ) { + self.compiler_observer = compiler_observer; + } + + pub fn runtime_observer(self, runtime_observer: Option<&'ro mut dyn RuntimeObserver>) -> Self { + Self { + runtime_observer, + ..self + } + } + + pub fn set_runtime_observer(&mut self, runtime_observer: Option<&'ro mut dyn RuntimeObserver>) { + self.runtime_observer = runtime_observer; + } +} + +impl<'co, 'ro, 'env, IO> EvaluationBuilder<'co, 'ro, 'env, IO> { + pub fn source_map(&mut self) -> &SourceCode { + self.source_map.get_or_insert_with(SourceCode::default) + } +} + +impl<'co, 'ro, 'env> EvaluationBuilder<'co, 'ro, 'env, Box<dyn EvalIO>> { + /// Initialize an `Evaluation`, without the import statement available, and + /// all IO operations stubbed out. + pub fn new_pure() -> Self { + Self::new(Box::new(DummyIO) as Box<dyn EvalIO>).with_enable_import(false) + } + + #[cfg(feature = "impure")] + /// Configure an `Evaluation` to have impure features available + /// with the given I/O implementation. + /// + /// If no I/O implementation is supplied, [`StdIO`] is used by + /// default. + pub fn enable_impure(mut self, io: Option<Box<dyn EvalIO>>) -> Self { + self.io_handle = io.unwrap_or_else(|| Box::new(StdIO) as Box<dyn EvalIO>); + self.enable_import = true; + self.builtins_mut() + .builtins + .extend(builtins::impure_builtins()); + + // Make `NIX_PATH` resolutions work by default, unless the + // user already overrode this with something else. + if self.nix_path.is_none() { + self.nix_path = std::env::var("NIX_PATH").ok(); + } + self + } + + #[cfg(feature = "impure")] + /// Initialise an `Evaluation`, with all impure features turned on by default. + pub fn new_impure() -> Self { + Self::new_pure().enable_impure(None) + } +} + /// An `Evaluation` represents how a piece of Nix code is evaluated. It can be /// instantiated and configured directly, or it can be accessed through the /// various simplified helper methods available below. /// /// Public fields are intended to be set by the caller. Setting all /// fields is optional. -pub struct Evaluation<'co, 'ro, IO> { +pub struct Evaluation<'co, 'ro, 'env, IO> { /// Source code map used for error reporting. source_map: SourceCode, - /// Set of all builtins that should be available during the - /// evaluation. - /// - /// This defaults to all pure builtins. Users might want to add - /// the set of impure builtins, or other custom builtins. - pub builtins: Vec<(&'static str, Value)>, + /// Set of all global values available at the top-level scope + globals: Rc<GlobalsMap>, - /// Set of builtins that are implemented in Nix itself and should - /// be compiled and inserted in the builtins set. - pub src_builtins: Vec<(&'static str, &'static str)>, + /// Top-level variables to define in the evaluation + env: Option<&'env FxHashMap<SmolStr, Value>>, /// Implementation of file-IO to use during evaluation, e.g. for /// impure builtins. /// /// Defaults to [`DummyIO`] if not set explicitly. - pub io_handle: IO, - - /// Determines whether the `import` builtin should be made - /// available. Note that this depends on the `io_handle` being - /// able to read the files specified as arguments to `import`. - pub enable_import: bool, + io_handle: IO, - /// Determines whether the returned value should be strictly - /// evaluated, that is whether its list and attribute set elements - /// should be forced recursively. - pub strict: bool, + /// Specification for how to handle top-level values returned by evaluation + /// + /// See the documentation for [`EvalMode`] for more information. + mode: EvalMode, /// (optional) Nix search path, e.g. the value of `NIX_PATH` used /// for resolving items on the search path (such as `<nixpkgs>`). - pub nix_path: Option<String>, + nix_path: Option<String>, /// (optional) compiler observer for reporting on compilation /// details, like the emitted bytecode. - pub compiler_observer: Option<&'co mut dyn CompilerObserver>, + compiler_observer: Option<&'co mut dyn CompilerObserver>, /// (optional) runtime observer, for reporting on execution steps /// of Nix code. - pub runtime_observer: Option<&'ro mut dyn RuntimeObserver>, + runtime_observer: Option<&'ro mut dyn RuntimeObserver>, } /// Result of evaluating a piece of Nix code. If evaluation succeeded, a value @@ -131,73 +393,44 @@ pub struct EvaluationResult { pub expr: Option<rnix::ast::Expr>, } -impl<'co, 'ro, IO> Evaluation<'co, 'ro, IO> -where - IO: AsRef<dyn EvalIO> + 'static, -{ - /// Initialize an `Evaluation`. - pub fn new(io_handle: IO, enable_import: bool) -> Self { - let mut builtins = builtins::pure_builtins(); - builtins.extend(builtins::placeholders()); // these are temporary +impl<'co, 'ro, 'env, IO> Evaluation<'co, 'ro, 'env, IO> { + /// Make a new [builder][] for configuring an evaluation + /// + /// [builder]: EvaluationBuilder + pub fn builder(io_handle: IO) -> EvaluationBuilder<'co, 'ro, 'env, IO> { + EvaluationBuilder::new(io_handle) + } - Self { - source_map: SourceCode::default(), - enable_import, - io_handle, - builtins, - src_builtins: vec![], - strict: false, - nix_path: None, - compiler_observer: None, - runtime_observer: None, - } + /// Clone the reference to the map of Nix globals for this evaluation. If [`Value`]s are shared + /// across subsequent [`Evaluation`]s, it is important that those evaluations all have the same + /// underlying globals map. + pub fn globals(&self) -> Rc<GlobalsMap> { + self.globals.clone() } -} -impl<'co, 'ro> Evaluation<'co, 'ro, Box<dyn EvalIO>> { - /// Initialize an `Evaluation`, without the import statement available, and - /// all IO operations stubbed out. - pub fn new_pure() -> Self { - Self::new(Box::new(DummyIO) as Box<dyn EvalIO>, false) + /// Clone the reference to the contained source code map. This is used after an evaluation for + /// pretty error printing. Also, if [`Value`]s are shared across subsequent [`Evaluation`]s, it + /// is important that those evaluations all have the same underlying source code map. + pub fn source_map(&self) -> SourceCode { + self.source_map.clone() } +} +impl<'co, 'ro, 'env> Evaluation<'co, 'ro, 'env, Box<dyn EvalIO>> { #[cfg(feature = "impure")] - /// Configure an `Evaluation` to have impure features available - /// with the given I/O implementation. - /// - /// If no I/O implementation is supplied, [`StdIO`] is used by - /// default. - pub fn enable_impure(&mut self, io: Option<Box<dyn EvalIO>>) { - self.io_handle = io.unwrap_or_else(|| Box::new(StdIO) as Box<dyn EvalIO>); - self.enable_import = true; - self.builtins.extend(builtins::impure_builtins()); - - // Make `NIX_PATH` resolutions work by default, unless the - // user already overrode this with something else. - if self.nix_path.is_none() { - self.nix_path = std::env::var("NIX_PATH").ok(); - } + pub fn builder_impure() -> EvaluationBuilder<'co, 'ro, 'env, Box<dyn EvalIO>> { + EvaluationBuilder::new_impure() } - #[cfg(feature = "impure")] - /// Initialise an `Evaluation`, with all impure features turned on by default. - pub fn new_impure() -> Self { - let mut eval = Self::new_pure(); - eval.enable_impure(None); - eval + pub fn builder_pure() -> EvaluationBuilder<'co, 'ro, 'env, Box<dyn EvalIO>> { + EvaluationBuilder::new_pure() } } -impl<'co, 'ro, IO> Evaluation<'co, 'ro, IO> +impl<'co, 'ro, 'env, IO> Evaluation<'co, 'ro, 'env, IO> where IO: AsRef<dyn EvalIO> + 'static, { - /// Clone the reference to the contained source code map. This is used after - /// an evaluation for pretty error printing. - pub fn source_map(&self) -> SourceCode { - self.source_map.clone() - } - /// Only compile the provided source code, at an optional location of the /// source code (i.e. path to the file it was read from; used for error /// reporting, and for resolving relative paths in impure functions) @@ -227,9 +460,8 @@ where file, location, source, - self.builtins, - self.src_builtins, - self.enable_import, + self.globals, + self.env, compiler_observer, ); @@ -257,20 +489,14 @@ where let mut noop_observer = observer::NoOpObserver::default(); let compiler_observer = self.compiler_observer.take().unwrap_or(&mut noop_observer); - // Insert a storeDir builtin *iff* a store directory is present. - if let Some(store_dir) = self.io_handle.as_ref().store_dir() { - self.builtins.push(("storeDir", store_dir.into())); - } - - let (lambda, globals) = match parse_compile_internal( + let lambda = match parse_compile_internal( &mut result, code.as_ref(), file.clone(), location, source.clone(), - self.builtins, - self.src_builtins, - self.enable_import, + self.globals.clone(), + self.env, compiler_observer, ) { None => return result, @@ -302,9 +528,9 @@ where self.io_handle, runtime_observer, source.clone(), - globals, + self.globals, lambda, - self.strict, + self.mode, ); match vm_result { @@ -339,11 +565,10 @@ fn parse_compile_internal( file: Arc<codemap::File>, location: Option<PathBuf>, source: SourceCode, - builtins: Vec<(&'static str, Value)>, - src_builtins: Vec<(&'static str, &'static str)>, - enable_import: bool, + globals: Rc<GlobalsMap>, + env: Option<&FxHashMap<SmolStr, Value>>, compiler_observer: &mut dyn CompilerObserver, -) -> Option<(Rc<Lambda>, Rc<GlobalsMap>)> { +) -> Option<Rc<Lambda>> { let parsed = rnix::ast::Root::parse(code); let parse_errors = parsed.errors(); @@ -361,13 +586,11 @@ fn parse_compile_internal( // the result, in case the caller needs it for something. result.expr = parsed.tree().expr(); - let builtins = - crate::compiler::prepare_globals(builtins, src_builtins, source.clone(), enable_import); - let compiler_result = match compiler::compile( result.expr.as_ref().unwrap(), location, - builtins, + globals, + env, &source, &file, compiler_observer, @@ -390,5 +613,5 @@ fn parse_compile_internal( // Return the lambda (for execution) and the globals map (to // ensure the invariant that the globals outlive the runtime). - Some((compiler_result.lambda, compiler_result.globals)) + Some(compiler_result.lambda) } diff --git a/tvix/eval/src/nix_search_path.rs b/tvix/eval/src/nix_search_path.rs index 566ca122384b..369c5b6857ba 100644 --- a/tvix/eval/src/nix_search_path.rs +++ b/tvix/eval/src/nix_search_path.rs @@ -197,6 +197,8 @@ mod tests { } } + // this uses StdIO, which is only available with the impure feature. + #[cfg(feature = "impure")] mod resolve { use crate::StdIO; use path_clean::PathClean; diff --git a/tvix/eval/src/observer.rs b/tvix/eval/src/observer.rs index f5de399315c7..5e6526418b3b 100644 --- a/tvix/eval/src/observer.rs +++ b/tvix/eval/src/observer.rs @@ -13,7 +13,7 @@ use tabwriter::TabWriter; use crate::chunk::Chunk; use crate::generators::VMRequest; -use crate::opcode::{CodeIdx, OpCode}; +use crate::opcode::{CodeIdx, Op}; use crate::value::Lambda; use crate::SourceCode; use crate::Value; @@ -73,7 +73,7 @@ pub trait RuntimeObserver { /// Called when the runtime *begins* executing an instruction. The /// provided stack is the state at the beginning of the operation. - fn observe_execute_op(&mut self, _ip: CodeIdx, _: &OpCode, _: &[Value]) {} + fn observe_execute_op(&mut self, _ip: CodeIdx, _: &Op, _: &[Value]) {} } #[derive(Default)] @@ -112,8 +112,12 @@ impl<W: Write> DisassemblingObserver<W> { // calculate width of the widest address in the chunk let width = format!("{:#x}", chunk.code.len() - 1).len(); - for (idx, _) in chunk.code.iter().enumerate() { - let _ = chunk.disassemble_op(&mut self.writer, &self.source, width, CodeIdx(idx)); + let mut idx = 0; + while idx < chunk.code.len() { + let size = chunk + .disassemble_op(&mut self.writer, &self.source, width, CodeIdx(idx)) + .expect("writing debug output should work"); + idx += size; } } } @@ -304,7 +308,7 @@ impl<W: Write> RuntimeObserver for TracingObserver<W> { ); } - fn observe_execute_op(&mut self, ip: CodeIdx, op: &OpCode, stack: &[Value]) { + fn observe_execute_op(&mut self, ip: CodeIdx, op: &Op, stack: &[Value]) { self.maybe_write_time(); let _ = write!(&mut self.writer, "{:04} {:?}\t", ip.0, op); self.write_stack(stack); diff --git a/tvix/eval/src/opcode.rs b/tvix/eval/src/opcode.rs index f89c1c12e7fd..ddf1304b3aea 100644 --- a/tvix/eval/src/opcode.rs +++ b/tvix/eval/src/opcode.rs @@ -52,8 +52,7 @@ pub struct JumpOffset(pub usize); #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Count(pub usize); -/// All variants of this enum carry a bounded amount of data to -/// ensure that no heap allocations are needed for an Opcode. +/// Op represents all instructions in the Tvix abstract machine. /// /// In documentation comments, stack positions are referred to by /// indices written in `{}` as such, where required: @@ -70,187 +69,182 @@ pub struct Count(pub usize); /// /// Unless otherwise specified, operations leave their result at the /// top of the stack. -#[warn(variant_size_differences)] -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum OpCode { +#[repr(u8)] +#[derive(Debug, PartialEq, Eq)] +pub enum Op { /// Push a constant onto the stack. - OpConstant(ConstantIdx), + Constant, - // Unary operators - /// Discard a value from the stack. - OpPop, + /// Discard the value on top of the stack. + Pop, /// Invert the boolean at the top of the stack. - OpInvert, + Invert, - // Binary operators /// Invert the sign of the number at the top of the stack. - OpNegate, + Negate, /// Sum up the two numbers at the top of the stack. - OpAdd, + Add, /// Subtract the number at {1} from the number at {2}. - OpSub, + Sub, /// Multiply the two numbers at the top of the stack. - OpMul, + Mul, /// Divide the two numbers at the top of the stack. - OpDiv, + Div, - // Comparison operators /// Check the two values at the top of the stack for Nix-equality. - OpEqual, + Equal, /// Check whether the value at {2} is less than {1}. - OpLess, + Less, /// Check whether the value at {2} is less than or equal to {1}. - OpLessOrEq, + LessOrEq, /// Check whether the value at {2} is greater than {1}. - OpMore, + More, /// Check whether the value at {2} is greater than or equal to {1}. - OpMoreOrEq, + MoreOrEq, - // Logical operators & generic jumps /// Jump forward in the bytecode specified by the number of /// instructions in its usize operand. - OpJump(JumpOffset), + Jump, /// Jump forward in the bytecode specified by the number of /// instructions in its usize operand, *if* the value at the top /// of the stack is `true`. - OpJumpIfTrue(JumpOffset), + JumpIfTrue, /// Jump forward in the bytecode specified by the number of /// instructions in its usize operand, *if* the value at the top /// of the stack is `false`. - OpJumpIfFalse(JumpOffset), + JumpIfFalse, /// Pop one stack item and jump forward in the bytecode /// specified by the number of instructions in its usize /// operand, *if* the value at the top of the stack is a /// Value::Catchable. - OpJumpIfCatchable(JumpOffset), + JumpIfCatchable, /// Jump forward in the bytecode specified by the number of /// instructions in its usize operand, *if* the value at the top /// of the stack is the internal value representing a missing /// attribute set key. - OpJumpIfNotFound(JumpOffset), + JumpIfNotFound, /// Jump forward in the bytecode specified by the number of /// instructions in its usize operand, *if* the value at the top /// of the stack is *not* the internal value requesting a /// stack value finalisation. - OpJumpIfNoFinaliseRequest(JumpOffset), + JumpIfNoFinaliseRequest, + + /// Construct an attribute set from the given number of key-value pairs on + /// the top of the stack. The operand gives the count of *pairs*, not the + /// number of *stack values* - the actual number of values popped off the + /// stack will be twice the argument to this op. + Attrs, - // Attribute sets - /// Construct an attribute set from the given number of key-value pairs on the top of the stack - /// - /// Note that this takes the count of *pairs*, not the number of *stack values* - the actual - /// number of values popped off the stack will be twice the argument to this op - OpAttrs(Count), /// Merge the attribute set at {2} into the attribute set at {1}, /// and leave the new set at the top of the stack. - OpAttrsUpdate, + AttrsUpdate, /// Select the attribute with the name at {1} from the set at {2}. - OpAttrsSelect, + AttrsSelect, /// Select the attribute with the name at {1} from the set at {2}, but leave /// a `Value::AttrNotFound` in the stack instead of failing if it is /// missing. - OpAttrsTrySelect, + AttrsTrySelect, /// Check for the presence of the attribute with the name at {1} in the set /// at {2}. - OpHasAttr, + HasAttr, /// Throw an error if the attribute set at the top of the stack has any attributes /// other than those listed in the formals of the current lambda /// /// Panics if the current frame is not a lambda with formals - OpValidateClosedFormals, + ValidateClosedFormals, - // `with`-handling /// Push a value onto the runtime `with`-stack to enable dynamic identifier /// resolution. The absolute stack index of the value is supplied as a usize /// operand. - OpPushWith(StackIdx), + PushWith, /// Pop the last runtime `with`-stack element. - OpPopWith, + PopWith, /// Dynamically resolve an identifier with the name at {1} from the runtime /// `with`-stack. - OpResolveWith, + ResolveWith, // Lists /// Construct a list from the given number of values at the top of the /// stack. - OpList(Count), + List, /// Concatenate the lists at {2} and {1}. - OpConcat, + Concat, // Strings /// Interpolate the given number of string fragments into a single string. - OpInterpolate(Count), + Interpolate, /// Force the Value on the stack and coerce it to a string - OpCoerceToString(crate::CoercionKind), + CoerceToString, // Paths /// Attempt to resolve the Value on the stack using the configured [`NixSearchPath`][] /// /// [`NixSearchPath`]: crate::nix_search_path::NixSearchPath - OpFindFile, + FindFile, /// Attempt to resolve a path literal relative to the home dir - OpResolveHomePath, + ResolveHomePath, // Type assertion operators /// Assert that the value at {1} is a boolean, and fail with a runtime error /// otherwise. - OpAssertBool, - OpAssertAttrs, + AssertBool, + AssertAttrs, /// Access local identifiers with statically known positions. - OpGetLocal(StackIdx), + GetLocal, /// Close scopes while leaving their expression value around. - OpCloseScope(Count), // number of locals to pop + CloseScope, /// Return an error indicating that an `assert` failed - OpAssertFail, + AssertFail, // Lambdas & closures /// Call the value at {1} in a new VM callframe - OpCall, + Call, /// Retrieve the upvalue at the given index from the closure or thunk /// currently under evaluation. - OpGetUpvalue(UpvalueIdx), + GetUpvalue, /// Construct a closure which has upvalues but no self-references - OpClosure(ConstantIdx), + Closure, /// Construct a closure which has self-references (direct or via upvalues) - OpThunkClosure(ConstantIdx), + ThunkClosure, /// Construct a suspended thunk, used to delay a computation for laziness. - OpThunkSuspended(ConstantIdx), + ThunkSuspended, /// Force the value at {1} until it is a `Thunk::Evaluated`. - OpForce, + Force, /// Finalise initialisation of the upvalues of the value in the given stack /// index (which must be a Value::Thunk) after the scope is fully bound. - OpFinalise(StackIdx), + Finalise, /// Final instruction emitted in a chunk. Does not have an /// inherent effect, but can simplify VM logic as a marker in some @@ -258,27 +252,140 @@ pub enum OpCode { /// /// Can be thought of as "returning" the value to the parent /// frame, hence the name. - OpReturn, - - // [`OpClosure`], [`OpThunkSuspended`], and [`OpThunkClosure`] have a - // variable number of arguments to the instruction, which is - // represented here by making their data part of the opcodes. - // Each of these two opcodes has a `ConstantIdx`, which must - // reference a `Value::Blueprint(Lambda)`. The `upvalue_count` - // field in that `Lambda` indicates the number of arguments it - // takes, and the opcode must be followed by exactly this number - // of `Data*` opcodes. The VM skips over these by advancing the - // instruction pointer. - // - // It is illegal for a `Data*` opcode to appear anywhere else. - /// Populate a static upvalue by copying from the stack immediately. - DataStackIdx(StackIdx), - /// Populate a static upvalue of a thunk by copying it the stack, but do - /// when the thunk is finalised (by OpFinalise) rather than immediately. - DataDeferredLocal(StackIdx), - /// Populate a static upvalue by copying it from the upvalues of an - /// enclosing scope. - DataUpvalueIdx(UpvalueIdx), - /// Populate dynamic upvalues by saving a copy of the with-stack. - DataCaptureWith, + Return, + + /// Sentinel value to signal invalid bytecode. This MUST always be the last + /// value in the enum. Do not move it! + Invalid, +} + +const _ASSERT_SMALL_OP: () = assert!(std::mem::size_of::<Op>() == 1); + +impl From<u8> for Op { + fn from(num: u8) -> Self { + if num >= Self::Invalid as u8 { + return Self::Invalid; + } + + // SAFETY: As long as `Invalid` remains the last variant of the enum, + // and as long as variant values are not specified manually, this + // conversion is safe. + unsafe { std::mem::transmute(num) } + } +} + +pub enum OpArg { + None, + Uvarint, + Fixed, + Custom, +} + +impl Op { + pub fn arg_type(&self) -> OpArg { + match self { + Op::Constant + | Op::Attrs + | Op::PushWith + | Op::List + | Op::Interpolate + | Op::GetLocal + | Op::CloseScope + | Op::GetUpvalue + | Op::Finalise => OpArg::Uvarint, + + Op::Jump + | Op::JumpIfTrue + | Op::JumpIfFalse + | Op::JumpIfCatchable + | Op::JumpIfNotFound + | Op::JumpIfNoFinaliseRequest => OpArg::Fixed, + + Op::CoerceToString | Op::Closure | Op::ThunkClosure | Op::ThunkSuspended => { + OpArg::Custom + } + _ => OpArg::None, + } + } +} + +/// Position is used to represent where to capture an upvalue from. +#[derive(Clone, Copy)] +pub struct Position(pub u64); + +impl Position { + pub fn stack_index(idx: StackIdx) -> Self { + Position((idx.0 as u64) << 2) + } + + pub fn deferred_local(idx: StackIdx) -> Self { + Position(((idx.0 as u64) << 2) | 1) + } + + pub fn upvalue_index(idx: UpvalueIdx) -> Self { + Position(((idx.0 as u64) << 2) | 2) + } + + pub fn runtime_stack_index(&self) -> Option<StackIdx> { + if (self.0 & 0b11) == 0 { + return Some(StackIdx((self.0 >> 2) as usize)); + } + + None + } + + pub fn runtime_deferred_local(&self) -> Option<StackIdx> { + if (self.0 & 0b11) == 1 { + return Some(StackIdx((self.0 >> 2) as usize)); + } + + None + } + + pub fn runtime_upvalue_index(&self) -> Option<UpvalueIdx> { + if (self.0 & 0b11) == 2 { + return Some(UpvalueIdx((self.0 >> 2) as usize)); + } + + None + } +} + +#[cfg(test)] +mod position_tests { + use super::Position; // he-he + use super::{StackIdx, UpvalueIdx}; + + #[test] + fn test_stack_index_position() { + let idx = StackIdx(42); + let pos = Position::stack_index(idx); + let result = pos.runtime_stack_index(); + + assert_eq!(result, Some(idx)); + assert_eq!(pos.runtime_deferred_local(), None); + assert_eq!(pos.runtime_upvalue_index(), None); + } + + #[test] + fn test_deferred_local_position() { + let idx = StackIdx(42); + let pos = Position::deferred_local(idx); + let result = pos.runtime_deferred_local(); + + assert_eq!(result, Some(idx)); + assert_eq!(pos.runtime_stack_index(), None); + assert_eq!(pos.runtime_upvalue_index(), None); + } + + #[test] + fn test_upvalue_index_position() { + let idx = UpvalueIdx(42); + let pos = Position::upvalue_index(idx); + let result = pos.runtime_upvalue_index(); + + assert_eq!(result, Some(idx)); + assert_eq!(pos.runtime_stack_index(), None); + assert_eq!(pos.runtime_deferred_local(), None); + } } diff --git a/tvix/eval/src/spans.rs b/tvix/eval/src/spans.rs index f422093b0d12..df2b9a725562 100644 --- a/tvix/eval/src/spans.rs +++ b/tvix/eval/src/spans.rs @@ -5,37 +5,6 @@ use codemap::{File, Span}; use rnix::ast; use rowan::ast::AstNode; -/// Helper struct to carry information required for making a span, but -/// without actually performing the (expensive) span lookup. -/// -/// This is used for tracking spans across thunk boundaries, as they -/// are frequently instantiated but spans are only used in error or -/// warning cases. -#[derive(Clone, Debug)] -pub enum LightSpan { - /// The span has already been computed and can just be used right - /// away. - Actual { span: Span }, -} - -impl LightSpan { - pub fn new_actual(span: Span) -> Self { - Self::Actual { span } - } - - pub fn span(&self) -> Span { - match self { - LightSpan::Actual { span } => *span, - } - } -} - -impl From<Span> for LightSpan { - fn from(span: Span) -> Self { - LightSpan::Actual { span } - } -} - /// Trait implemented by all types from which we can retrieve a span. pub trait ToSpan { fn span_for(&self, file: &File) -> Span; @@ -66,6 +35,33 @@ impl ToSpan for rnix::SyntaxNode { } } +/// A placeholder [`ToSpan`] implementation covering the entire source file. +#[derive(Debug, Clone, Copy)] +pub struct EntireFile; + +impl ToSpan for EntireFile { + fn span_for(&self, file: &File) -> Span { + file.span + } +} + +/// A placeholder [`ToSpan`] implementation which falls back to the entire file if its wrapped value +/// is [`None`] +#[derive(Debug, Clone, Copy)] +pub struct OrEntireFile<T>(pub Option<T>); + +impl<T> ToSpan for OrEntireFile<T> +where + T: ToSpan, +{ + fn span_for(&self, file: &File) -> Span { + match &self.0 { + Some(t) => t.span_for(file), + None => EntireFile.span_for(file), + } + } +} + /// Generates a `ToSpan` implementation for a type implementing /// `rowan::AstNode`. This is impossible to do as a blanket /// implementation because `rustc` forbids these implementations for diff --git a/tvix/eval/src/tests/mod.rs b/tvix/eval/src/tests/mod.rs index 5a7708e298e8..21b5d35e6af0 100644 --- a/tvix/eval/src/tests/mod.rs +++ b/tvix/eval/src/tests/mod.rs @@ -1,203 +1,6 @@ -use crate::{value::Value, EvalIO}; -use builtin_macros::builtins; -use pretty_assertions::assert_eq; -use rstest::rstest; -use std::path::PathBuf; - /// Module for one-off tests which do not follow the rest of the /// test layout. mod one_offs; -#[builtins] -mod mock_builtins { - //! Builtins which are required by language tests, but should not - //! actually exist in //tvix/eval. - use crate as tvix_eval; - use crate::generators::GenCo; - use crate::*; - use genawaiter::rc::Gen; - - #[builtin("derivation")] - async fn builtin_derivation(co: GenCo, input: Value) -> Result<Value, ErrorKind> { - let input = input.to_attrs()?; - let attrs = input.update(NixAttrs::from_iter( - [ - ( - "outPath", - "/nix/store/00000000000000000000000000000000-mock", - ), - ( - "drvPath", - "/nix/store/00000000000000000000000000000000-mock.drv", - ), - ("type", "derivation"), - ] - .into_iter(), - )); - - Ok(Value::Attrs(Box::new(attrs))) - } -} - -fn eval_test(code_path: PathBuf, expect_success: bool) { - std::env::set_var("TEST_VAR", "foo"); // for eval-okay-getenv.nix - - eprintln!("path: {}", code_path.display()); - assert_eq!( - code_path.extension().unwrap(), - "nix", - "test files always end in .nix" - ); - - let code = std::fs::read_to_string(&code_path).expect("should be able to read test code"); - - let mut eval = crate::Evaluation::new_impure(); - eval.strict = true; - eval.builtins.extend(mock_builtins::builtins()); - - let result = eval.evaluate(code, Some(code_path.clone())); - let failed = match result.value { - Some(Value::Catchable(_)) => true, - _ => !result.errors.is_empty(), - }; - if expect_success && failed { - panic!( - "{}: evaluation of eval-okay test should succeed, but failed with {:?}", - code_path.display(), - result.errors, - ); - } - - if !expect_success && failed { - return; - } - // !expect_success can also mean the output differs, so don't panic if the - // evaluation didn't fail. - - let value = result.value.unwrap(); - let result_str = value.to_string(); - - let exp_path = code_path.with_extension("exp"); - if exp_path.exists() { - // If there's an .exp file provided alongside, compare it with the - // output of the NixValue .to_string() method. - let exp_str = std::fs::read_to_string(&exp_path).expect("unable to read .exp file"); - - if expect_success { - assert_eq!( - result_str, - exp_str.trim(), - "{}: result value representation (left) must match expectation (right)", - code_path.display() - ); - } else { - assert_ne!( - result_str, - exp_str.trim(), - "{}: test passed unexpectedly! consider moving it out of notyetpassing", - code_path.display() - ); - - // Early return here, we don't compare .xml outputs if this is a ! - // expect_success test. - return; - } - } - - let exp_xml_path = code_path.with_extension("exp.xml"); - if exp_xml_path.exists() { - // If there's an XML file provided alongside, compare it with the - // output produced when serializing the Value as XML. - let exp_xml_str = std::fs::read_to_string(exp_xml_path).expect("unable to read .xml file"); - - let mut xml_actual_buf = Vec::new(); - crate::builtins::value_to_xml(&mut xml_actual_buf, &value).expect("value_to_xml failed"); - - assert_eq!( - String::from_utf8(xml_actual_buf).expect("to_xml produced invalid utf-8"), - exp_xml_str, - "{}: result value representation (left) must match expectation (right)", - code_path.display() - ); - } -} - -// identity-* tests contain Nix code snippets which should evaluate to -// themselves exactly (i.e. literals). -#[rstest] -fn identity(#[files("src/tests/tvix_tests/identity-*.nix")] code_path: PathBuf) { - let code = std::fs::read_to_string(code_path).expect("should be able to read test code"); - - let mut eval = crate::Evaluation::new(Box::new(crate::StdIO) as Box<dyn EvalIO>, false); - eval.strict = true; - - let result = eval.evaluate(&code, None); - assert!( - result.errors.is_empty(), - "evaluation of identity test failed: {:?}", - result.errors - ); - - let result_str = result.value.unwrap().to_string(); - - assert_eq!( - result_str, - code.trim(), - "result value representation (left) must match expectation (right)" - ) -} - -// eval-okay-* tests contain a snippet of Nix code, and an expectation -// of the produced string output of the evaluator. -// -// These evaluations are always supposed to succeed, i.e. all snippets -// are guaranteed to be valid Nix code. -#[rstest] -fn eval_okay(#[files("src/tests/tvix_tests/eval-okay-*.nix")] code_path: PathBuf) { - eval_test(code_path, true) -} - -// eval-okay-* tests from the original Nix test suite. -#[cfg(feature = "nix_tests")] -#[rstest] -fn nix_eval_okay(#[files("src/tests/nix_tests/eval-okay-*.nix")] code_path: PathBuf) { - eval_test(code_path, true) -} - -// eval-okay-* tests from the original Nix test suite which do not yet pass for tvix -// -// Eventually there will be none of these left, and this function -// will disappear :) -// -// Please don't submit failing tests unless they're in -// notyetpassing; this makes the test suite much more useful for -// regression testing, since there should always be zero non-ignored -// failing tests. -#[rstest] -fn nix_eval_okay_currently_failing( - #[files("src/tests/nix_tests/notyetpassing/eval-okay-*.nix")] code_path: PathBuf, -) { - eval_test(code_path, false) -} - -#[rstest] -fn eval_okay_currently_failing( - #[files("src/tests/tvix_tests/notyetpassing/eval-okay-*.nix")] code_path: PathBuf, -) { - eval_test(code_path, false) -} - -// eval-fail-* tests contain a snippet of Nix code, which is -// expected to fail evaluation. The exact type of failure -// (assertion, parse error, etc) is not currently checked. -#[rstest] -fn eval_fail(#[files("src/tests/tvix_tests/eval-fail-*.nix")] code_path: PathBuf) { - eval_test(code_path, false) -} - -// eval-fail-* tests from the original Nix test suite. #[cfg(feature = "nix_tests")] -#[rstest] -fn nix_eval_fail(#[files("src/tests/nix_tests/eval-fail-*.nix")] code_path: PathBuf) { - eval_test(code_path, false) -} +mod nix_tests; diff --git a/tvix/eval/src/tests/nix_tests.rs b/tvix/eval/src/tests/nix_tests.rs new file mode 100644 index 000000000000..b17fe98bc9e4 --- /dev/null +++ b/tvix/eval/src/tests/nix_tests.rs @@ -0,0 +1,212 @@ +use crate::value::Value; +use builtin_macros::builtins; +use pretty_assertions::assert_eq; +use rstest::rstest; +use std::path::PathBuf; + +#[builtins] +mod mock_builtins { + //! Builtins which are required by language tests, but should not + //! actually exist in //tvix/eval. + use crate as tvix_eval; + use crate::generators::GenCo; + use crate::*; + use genawaiter::rc::Gen; + + #[builtin("derivation")] + async fn builtin_derivation(co: GenCo, input: Value) -> Result<Value, ErrorKind> { + let input = input.to_attrs()?; + let attrs = input.update(NixAttrs::from_iter( + [ + ( + "outPath", + "/nix/store/00000000000000000000000000000000-mock", + ), + ( + "drvPath", + "/nix/store/00000000000000000000000000000000-mock.drv", + ), + ("type", "derivation"), + ] + .into_iter(), + )); + + Ok(Value::Attrs(Box::new(attrs))) + } +} + +#[cfg(feature = "impure")] +fn eval_test(code_path: PathBuf, expect_success: bool) { + use crate::vm::EvalMode; + + std::env::set_var("TEST_VAR", "foo"); // for eval-okay-getenv.nix + + eprintln!("path: {}", code_path.display()); + assert_eq!( + code_path.extension().unwrap(), + "nix", + "test files always end in .nix" + ); + + let code = std::fs::read_to_string(&code_path).expect("should be able to read test code"); + + let eval = crate::Evaluation::builder_impure() + .mode(EvalMode::Strict) + .add_builtins(mock_builtins::builtins()) + .build(); + + let result = eval.evaluate(code, Some(code_path.clone())); + let failed = match result.value { + Some(Value::Catchable(_)) => true, + _ => !result.errors.is_empty(), + }; + if expect_success && failed { + panic!( + "{}: evaluation of eval-okay test should succeed, but failed with {:?}", + code_path.display(), + result.errors, + ); + } + + if !expect_success && failed { + return; + } + // !expect_success can also mean the output differs, so don't panic if the + // evaluation didn't fail. + + let value = result.value.unwrap(); + let result_str = value.to_string(); + + let exp_path = code_path.with_extension("exp"); + if exp_path.exists() { + // If there's an .exp file provided alongside, compare it with the + // output of the NixValue .to_string() method. + let exp_str = std::fs::read_to_string(&exp_path).expect("unable to read .exp file"); + + if expect_success { + assert_eq!( + result_str, + exp_str.trim(), + "{}: result value representation (left) must match expectation (right)", + code_path.display() + ); + } else { + assert_ne!( + result_str, + exp_str.trim(), + "{}: test passed unexpectedly! consider moving it out of notyetpassing", + code_path.display() + ); + + // Early return here, we don't compare .xml outputs if this is a ! + // expect_success test. + return; + } + } + + let exp_xml_path = code_path.with_extension("exp.xml"); + if exp_xml_path.exists() { + // If there's an XML file provided alongside, compare it with the + // output produced when serializing the Value as XML. + let exp_xml_str = std::fs::read_to_string(exp_xml_path).expect("unable to read .xml file"); + + let mut xml_actual_buf = Vec::new(); + crate::builtins::value_to_xml(&mut xml_actual_buf, &value).expect("value_to_xml failed"); + + assert_eq!( + String::from_utf8(xml_actual_buf).expect("to_xml produced invalid utf-8"), + exp_xml_str, + "{}: result value representation (left) must match expectation (right)", + code_path.display() + ); + } +} + +// identity-* tests contain Nix code snippets which should evaluate to +// themselves exactly (i.e. literals). +#[cfg(feature = "impure")] +#[rstest] +fn identity(#[files("src/tests/tvix_tests/identity-*.nix")] code_path: PathBuf) { + use crate::{vm::EvalMode, EvalIO}; + + let code = std::fs::read_to_string(code_path).expect("should be able to read test code"); + + let eval = crate::Evaluation::builder(Box::new(crate::StdIO) as Box<dyn EvalIO>) + .disable_import() + .mode(EvalMode::Strict) + .build(); + + let result = eval.evaluate(&code, None); + assert!( + result.errors.is_empty(), + "evaluation of identity test failed: {:?}", + result.errors + ); + + let result_str = result.value.unwrap().to_string(); + + assert_eq!( + result_str, + code.trim(), + "result value representation (left) must match expectation (right)" + ) +} + +// eval-okay-* tests contain a snippet of Nix code, and an expectation +// of the produced string output of the evaluator. +// +// These evaluations are always supposed to succeed, i.e. all snippets +// are guaranteed to be valid Nix code. +#[cfg(feature = "impure")] +#[rstest] +fn eval_okay(#[files("src/tests/tvix_tests/eval-okay-*.nix")] code_path: PathBuf) { + eval_test(code_path, true) +} + +// eval-okay-* tests from the original Nix test suite. +#[cfg(feature = "impure")] +#[rstest] +fn nix_eval_okay(#[files("src/tests/nix_tests/eval-okay-*.nix")] code_path: PathBuf) { + eval_test(code_path, true) +} + +// eval-okay-* tests from the original Nix test suite which do not yet pass for tvix +// +// Eventually there will be none of these left, and this function +// will disappear :) +// +// Please don't submit failing tests unless they're in +// notyetpassing; this makes the test suite much more useful for +// regression testing, since there should always be zero non-ignored +// failing tests. +#[cfg(feature = "impure")] +#[rstest] +fn nix_eval_okay_currently_failing( + #[files("src/tests/nix_tests/notyetpassing/eval-okay-*.nix")] code_path: PathBuf, +) { + eval_test(code_path, false) +} + +#[cfg(feature = "impure")] +#[rstest] +fn eval_okay_currently_failing( + #[files("src/tests/tvix_tests/notyetpassing/eval-okay-*.nix")] code_path: PathBuf, +) { + eval_test(code_path, false) +} + +// eval-fail-* tests contain a snippet of Nix code, which is +// expected to fail evaluation. The exact type of failure +// (assertion, parse error, etc) is not currently checked. +#[cfg(feature = "impure")] +#[rstest] +fn eval_fail(#[files("src/tests/tvix_tests/eval-fail-*.nix")] code_path: PathBuf) { + eval_test(code_path, false) +} + +// eval-fail-* tests from the original Nix test suite. +#[cfg(feature = "impure")] +#[rstest] +fn nix_eval_fail(#[files("src/tests/nix_tests/eval-fail-*.nix")] code_path: PathBuf) { + eval_test(code_path, false) +} diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.exp b/tvix/eval/src/tests/nix_tests/eval-okay-readDir.exp index 6413f6d4f9ec..6413f6d4f9ec 100644 --- a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.exp +++ b/tvix/eval/src/tests/nix_tests/eval-okay-readDir.exp diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.nix.disabled b/tvix/eval/src/tests/nix_tests/eval-okay-readDir.nix index a7ec9292aae2..a7ec9292aae2 100644 --- a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.nix.disabled +++ b/tvix/eval/src/tests/nix_tests/eval-okay-readDir.nix diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readFileType.exp b/tvix/eval/src/tests/nix_tests/eval-okay-readFileType.exp index 6413f6d4f9ec..6413f6d4f9ec 100644 --- a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readFileType.exp +++ b/tvix/eval/src/tests/nix_tests/eval-okay-readFileType.exp diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readFileType.nix b/tvix/eval/src/tests/nix_tests/eval-okay-readFileType.nix index 174fb6c3a028..174fb6c3a028 100644 --- a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readFileType.nix +++ b/tvix/eval/src/tests/nix_tests/eval-okay-readFileType.nix diff --git a/tvix/eval/src/tests/tvix_tests/readDir/foo/.keep b/tvix/eval/src/tests/nix_tests/readDir/bar index e69de29bb2d1..e69de29bb2d1 100644 --- a/tvix/eval/src/tests/tvix_tests/readDir/foo/.keep +++ b/tvix/eval/src/tests/nix_tests/readDir/bar diff --git a/tvix/eval/src/tests/nix_tests/readDir/foo/git-hates-directories b/tvix/eval/src/tests/nix_tests/readDir/foo/git-hates-directories new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/tvix/eval/src/tests/nix_tests/readDir/foo/git-hates-directories diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/ldir b/tvix/eval/src/tests/nix_tests/readDir/ldir index 19102815663d..19102815663d 120000 --- a/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/ldir +++ b/tvix/eval/src/tests/nix_tests/readDir/ldir diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/linked b/tvix/eval/src/tests/nix_tests/readDir/linked index c503f86a0cf7..c503f86a0cf7 120000 --- a/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/linked +++ b/tvix/eval/src/tests/nix_tests/readDir/linked diff --git a/tvix/eval/src/tests/one_offs.rs b/tvix/eval/src/tests/one_offs.rs index 565d1dd48f77..49ed713fc96c 100644 --- a/tvix/eval/src/tests/one_offs.rs +++ b/tvix/eval/src/tests/one_offs.rs @@ -5,8 +5,9 @@ fn test_source_builtin() { // Test an evaluation with a source-only builtin. The test ensures // that the artificially constructed thunking is correct. - let mut eval = Evaluation::new_impure(); - eval.src_builtins.push(("testSourceBuiltin", "42")); + let eval = Evaluation::builder_pure() + .add_src_builtin("testSourceBuiltin", "42") + .build(); let result = eval.evaluate("builtins.testSourceBuiltin", None); assert!( @@ -25,7 +26,9 @@ fn test_source_builtin() { #[test] fn skip_broken_bytecode() { - let result = Evaluation::new_pure().evaluate(/* code = */ "x", None); + let result = Evaluation::builder_pure() + .build() + .evaluate(/* code = */ "x", None); assert_eq!(result.errors.len(), 1); diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-split.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-split.exp new file mode 100644 index 000000000000..eb2117a0ce56 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-split.exp @@ -0,0 +1 @@ +[ [ "" [ "a" ] "c" ] [ "" [ "a" ] "b" [ "c" ] "" ] [ "" [ "a" null ] "b" [ null "c" ] "" ] [ " " [ "FOO" ] " " ] [ "" [ "abc" ] "" [ "" ] "" ] [ "" [ "abc" ] "" [ "" ] "" ] [ "" [ ] "" ] ] diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-split.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-split.nix new file mode 100644 index 000000000000..95305040dce2 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-split.nix @@ -0,0 +1,10 @@ +[ + (builtins.split "(a)b" "abc") + (builtins.split "([ac])" "abc") + (builtins.split "(a)|(c)" "abc") + (builtins.split "([[:upper:]]+)" " FOO ") + + (builtins.split "(.*)" "abc") + (builtins.split "([abc]*)" "abc") + (builtins.split ".*" "") +] diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-path-exists-child-of-file.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-path-exists-child-of-file.exp new file mode 100644 index 000000000000..c508d5366f70 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-path-exists-child-of-file.exp @@ -0,0 +1 @@ +false diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-path-exists-child-of-file.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-path-exists-child-of-file.nix new file mode 100644 index 000000000000..c756bff755ba --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-path-exists-child-of-file.nix @@ -0,0 +1 @@ +builtins.pathExists ("/dev/null/.") diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.exp deleted file mode 100644 index bf8d2c14ea4f..000000000000 --- a/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.exp +++ /dev/null @@ -1 +0,0 @@ -{ bar = "regular"; foo = "directory"; } diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.nix.disabled b/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.nix.disabled deleted file mode 100644 index a7ec9292aae2..000000000000 --- a/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.nix.disabled +++ /dev/null @@ -1 +0,0 @@ -builtins.readDir ./readDir diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-toxml-empty.exp.xml b/tvix/eval/src/tests/tvix_tests/eval-okay-toxml-empty.exp.xml new file mode 100644 index 000000000000..468972b2f819 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-toxml-empty.exp.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='utf-8'?> +<expr> + <attrs> + </attrs> +</expr> diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-toxml-empty.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-toxml-empty.nix new file mode 100644 index 000000000000..ffcd4415b08f --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-toxml-empty.nix @@ -0,0 +1 @@ +{ } diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-toxml.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-toxml.exp new file mode 100644 index 000000000000..9ae16de526f1 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-toxml.exp @@ -0,0 +1 @@ +"<?xml version='1.0' encoding='utf-8'?>\n<expr>\n <attrs>\n <attr name=\"&-{\">\n <string value=\";&"\" />\n </attr>\n <attr name=\"a\">\n <string value=\"s\" />\n </attr>\n </attrs>\n</expr>\n" diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-toxml.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-toxml.nix new file mode 100644 index 000000000000..7d074048ddec --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-toxml.nix @@ -0,0 +1,2 @@ +# Check some corner cases regarding escaping. +builtins.toXML { a = "s"; "&-{" = ";&\""; } diff --git a/tvix/eval/src/value/arbitrary.rs b/tvix/eval/src/value/arbitrary.rs index bf53f4fcb28a..49b9f2eea3fb 100644 --- a/tvix/eval/src/value/arbitrary.rs +++ b/tvix/eval/src/value/arbitrary.rs @@ -1,6 +1,6 @@ //! Support for configurable generation of arbitrary nix values -use imbl::proptest::{ord_map, vector}; +use proptest::collection::{btree_map, vec}; use proptest::{prelude::*, strategy::BoxedStrategy}; use std::ffi::OsString; @@ -33,16 +33,16 @@ impl Arbitrary for NixAttrs { fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { prop_oneof![ // Empty attrs representation - Just(Self(AttrsRep::Empty)), + Just(AttrsRep::Empty.into()), // KV representation (name/value pairs) ( any_with::<Value>(args.clone()), any_with::<Value>(args.clone()) ) - .prop_map(|(name, value)| Self(AttrsRep::KV { name, value })), + .prop_map(|(name, value)| AttrsRep::KV { name, value }.into()), // Map representation - ord_map(NixString::arbitrary(), Value::arbitrary_with(args), 0..100) - .prop_map(|map| Self(AttrsRep::Im(map))) + btree_map(NixString::arbitrary(), Value::arbitrary_with(args), 0..100) + .prop_map(|map| AttrsRep::Map(map).into()) ] .boxed() } @@ -53,7 +53,7 @@ impl Arbitrary for NixList { type Strategy = BoxedStrategy<Self>; fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { - vector(<Value as Arbitrary>::arbitrary_with(args), 0..100) + vec(<Value as Arbitrary>::arbitrary_with(args), 0..100) .prop_map(NixList::from) .boxed() } diff --git a/tvix/eval/src/value/attrs.rs b/tvix/eval/src/value/attrs.rs index 33259c8058eb..8d06240c65f5 100644 --- a/tvix/eval/src/value/attrs.rs +++ b/tvix/eval/src/value/attrs.rs @@ -6,11 +6,12 @@ //! Due to this, construction and management of attribute sets has //! some peculiarities that are encapsulated within this module. use std::borrow::Borrow; +use std::collections::{btree_map, BTreeMap}; use std::iter::FromIterator; +use std::rc::Rc; +use std::sync::LazyLock; use bstr::BStr; -use imbl::{ordmap, OrdMap}; -use lazy_static::lazy_static; use serde::de::{Deserializer, Error, Visitor}; use serde::Deserialize; @@ -21,12 +22,8 @@ use super::Value; use crate::errors::ErrorKind; use crate::CatchableErrorKind; -lazy_static! { - static ref NAME_S: NixString = "name".into(); - static ref NAME_REF: &'static NixString = &NAME_S; - static ref VALUE_S: NixString = "value".into(); - static ref VALUE_REF: &'static NixString = &VALUE_S; -} +static NAME: LazyLock<NixString> = LazyLock::new(|| "name".into()); +static VALUE: LazyLock<NixString> = LazyLock::new(|| "value".into()); #[cfg(test)] mod tests; @@ -36,7 +33,7 @@ pub(super) enum AttrsRep { #[default] Empty, - Im(OrdMap<NixString, Value>), + Map(BTreeMap<NixString, Value>), /// Warning: this represents a **two**-attribute attrset, with /// attribute names "name" and "value", like `{name="foo"; @@ -48,28 +45,6 @@ pub(super) enum AttrsRep { } impl AttrsRep { - /// Retrieve reference to a mutable map inside of an attrs, - /// optionally changing the representation if required. - fn map_mut(&mut self) -> &mut OrdMap<NixString, Value> { - match self { - AttrsRep::Im(m) => m, - - AttrsRep::Empty => { - *self = AttrsRep::Im(OrdMap::new()); - self.map_mut() - } - - AttrsRep::KV { name, value } => { - *self = AttrsRep::Im(ordmap! { - NAME_S.clone() => name.clone(), - VALUE_S.clone() => value.clone() - }); - - self.map_mut() - } - } - } - fn select(&self, key: &BStr) -> Option<&Value> { match self { AttrsRep::Empty => None, @@ -80,7 +55,7 @@ impl AttrsRep { _ => None, }, - AttrsRep::Im(map) => map.get(key), + AttrsRep::Map(map) => map.get(key), } } @@ -88,18 +63,18 @@ impl AttrsRep { match self { AttrsRep::Empty => false, AttrsRep::KV { .. } => key == "name" || key == "value", - AttrsRep::Im(map) => map.contains_key(key), + AttrsRep::Map(map) => map.contains_key(key), } } } #[repr(transparent)] #[derive(Clone, Debug, Default)] -pub struct NixAttrs(pub(super) AttrsRep); +pub struct NixAttrs(pub(super) Rc<AttrsRep>); -impl From<OrdMap<NixString, Value>> for NixAttrs { - fn from(map: OrdMap<NixString, Value>) -> Self { - NixAttrs(AttrsRep::Im(map)) +impl From<AttrsRep> for NixAttrs { + fn from(rep: AttrsRep) -> Self { + NixAttrs(Rc::new(rep)) } } @@ -112,34 +87,41 @@ where where T: IntoIterator<Item = (K, V)>, { - NixAttrs(AttrsRep::Im(iter.into_iter().collect())) + AttrsRep::Map( + iter.into_iter() + .map(|(k, v)| (k.into(), v.into())) + .collect(), + ) + .into() + } +} + +impl From<BTreeMap<NixString, Value>> for NixAttrs { + fn from(map: BTreeMap<NixString, Value>) -> Self { + AttrsRep::Map(map).into() } } impl TotalDisplay for NixAttrs { fn total_fmt(&self, f: &mut std::fmt::Formatter<'_>, set: &mut ThunkSet) -> std::fmt::Result { - f.write_str("{ ")?; - - match &self.0 { - AttrsRep::KV { name, value } => { - f.write_str("name = ")?; - name.total_fmt(f, set)?; - f.write_str("; ")?; - - f.write_str("value = ")?; - value.total_fmt(f, set)?; - f.write_str("; ")?; - } - - AttrsRep::Im(map) => { - for (name, value) in map { - write!(f, "{} = ", name.ident_str())?; - value.total_fmt(f, set)?; - f.write_str("; ")?; + if let Some(Value::String(s)) = self.select("type") { + if *s == "derivation" { + write!(f, "«derivation ")?; + if let Some(p) = self.select("drvPath") { + p.total_fmt(f, set)?; + } else { + write!(f, "???")?; } + return write!(f, "»"); } + } - AttrsRep::Empty => { /* no values to print! */ } + f.write_str("{ ")?; + + for (name, value) in self.iter_sorted() { + write!(f, "{} = ", name.ident_str())?; + value.total_fmt(f, set)?; + f.write_str("; ")?; } f.write_str("}") @@ -183,25 +165,22 @@ impl<'de> Deserialize<'de> for NixAttrs { impl NixAttrs { pub fn empty() -> Self { - Self(AttrsRep::Empty) + AttrsRep::Empty.into() } /// Compare two attribute sets by pointer equality. Only makes - /// sense for some attribute set reprsentations, i.e. returning + /// sense for some attribute set representations, i.e. returning /// `false` does not mean that the two attribute sets do not have /// equal *content*. pub fn ptr_eq(&self, other: &Self) -> bool { - match (&self.0, &other.0) { - (AttrsRep::Im(lhs), AttrsRep::Im(rhs)) => lhs.ptr_eq(rhs), - _ => false, - } + Rc::ptr_eq(&self.0, &other.0) } /// Return an attribute set containing the merge of the two /// provided sets. Keys from the `other` set have precedence. pub fn update(self, other: Self) -> Self { // Short-circuit on some optimal cases: - match (&self.0, &other.0) { + match (self.0.as_ref(), other.0.as_ref()) { (AttrsRep::Empty, AttrsRep::Empty) => return self, (AttrsRep::Empty, _) => return other, (_, AttrsRep::Empty) => return self, @@ -210,41 +189,44 @@ impl NixAttrs { // Explicitly handle all branches instead of falling // through, to ensure that we get at least some compiler // errors if variants are modified. - (AttrsRep::Im(_), AttrsRep::Im(_)) - | (AttrsRep::Im(_), AttrsRep::KV { .. }) - | (AttrsRep::KV { .. }, AttrsRep::Im(_)) => {} + (AttrsRep::Map(_), AttrsRep::Map(_)) + | (AttrsRep::Map(_), AttrsRep::KV { .. }) + | (AttrsRep::KV { .. }, AttrsRep::Map(_)) => {} }; // Slightly more advanced, but still optimised updates - match (self.0, other.0) { - (AttrsRep::Im(mut m), AttrsRep::KV { name, value }) => { - m.insert(NAME_S.clone(), name); - m.insert(VALUE_S.clone(), value); - NixAttrs(AttrsRep::Im(m)) + match (Rc::unwrap_or_clone(self.0), Rc::unwrap_or_clone(other.0)) { + (AttrsRep::Map(mut m), AttrsRep::KV { name, value }) => { + m.insert(NAME.clone(), name); + m.insert(VALUE.clone(), value); + AttrsRep::Map(m).into() } - (AttrsRep::KV { name, value }, AttrsRep::Im(mut m)) => { - match m.entry(NAME_S.clone()) { - imbl::ordmap::Entry::Vacant(e) => { + (AttrsRep::KV { name, value }, AttrsRep::Map(mut m)) => { + match m.entry(NAME.clone()) { + btree_map::Entry::Vacant(e) => { e.insert(name); } - imbl::ordmap::Entry::Occupied(_) => { /* name from `m` has precedence */ } + btree_map::Entry::Occupied(_) => { /* name from `m` has precedence */ } }; - match m.entry(VALUE_S.clone()) { - imbl::ordmap::Entry::Vacant(e) => { + match m.entry(VALUE.clone()) { + btree_map::Entry::Vacant(e) => { e.insert(value); } - imbl::ordmap::Entry::Occupied(_) => { /* value from `m` has precedence */ } + btree_map::Entry::Occupied(_) => { /* value from `m` has precedence */ } }; - NixAttrs(AttrsRep::Im(m)) + AttrsRep::Map(m).into() } // Plain merge of maps. - (AttrsRep::Im(m1), AttrsRep::Im(m2)) => NixAttrs(AttrsRep::Im(m2.union(m1))), + (AttrsRep::Map(mut m1), AttrsRep::Map(m2)) => { + m1.extend(m2); + AttrsRep::Map(m1).into() + } // Cases handled above by the borrowing match: _ => unreachable!(), @@ -253,16 +235,16 @@ impl NixAttrs { /// Return the number of key-value entries in an attrset. pub fn len(&self) -> usize { - match &self.0 { - AttrsRep::Im(map) => map.len(), + match self.0.as_ref() { + AttrsRep::Map(map) => map.len(), AttrsRep::Empty => 0, AttrsRep::KV { .. } => 2, } } pub fn is_empty(&self) -> bool { - match &self.0 { - AttrsRep::Im(map) => map.is_empty(), + match self.0.as_ref() { + AttrsRep::Map(map) => map.is_empty(), AttrsRep::Empty => true, AttrsRep::KV { .. } => false, } @@ -298,8 +280,8 @@ impl NixAttrs { /// Construct an iterator over all the key-value pairs in the attribute set. #[allow(clippy::needless_lifetimes)] pub fn iter<'a>(&'a self) -> Iter<KeyValue<'a>> { - Iter(match &self.0 { - AttrsRep::Im(map) => KeyValue::Im(map.iter()), + Iter(match &self.0.as_ref() { + AttrsRep::Map(map) => KeyValue::Map(map.iter()), AttrsRep::Empty => KeyValue::Empty, AttrsRep::KV { @@ -327,10 +309,12 @@ impl NixAttrs { /// Construct an iterator over all the keys of the attribute set pub fn keys(&self) -> Keys { - Keys(match &self.0 { + Keys(match self.0.as_ref() { AttrsRep::Empty => KeysInner::Empty, - AttrsRep::Im(m) => KeysInner::Im(m.keys()), AttrsRep::KV { .. } => KeysInner::KV(IterKV::default()), + + // TODO(tazjin): only sort when required, not always. + AttrsRep::Map(m) => KeysInner::Map(m.keys()), }) } @@ -349,7 +333,7 @@ impl NixAttrs { // Optimisation: Empty attribute set if count == 0 { - return Ok(Ok(NixAttrs(AttrsRep::Empty))); + return Ok(Ok(AttrsRep::Empty.into())); } // Optimisation: KV pattern @@ -359,14 +343,14 @@ impl NixAttrs { } } - let mut attrs = NixAttrs(AttrsRep::Im(OrdMap::new())); + let mut attrs_map = BTreeMap::new(); for _ in 0..count { let value = stack_slice.pop().unwrap(); let key = stack_slice.pop().unwrap(); match key { - Value::String(ks) => set_attr(&mut attrs, ks, value)?, + Value::String(ks) => set_attr(&mut attrs_map, ks, value)?, Value::Null => { // This is in fact valid, but leads to the value @@ -381,13 +365,13 @@ impl NixAttrs { } } - Ok(Ok(attrs)) + Ok(Ok(AttrsRep::Map(attrs_map).into())) } /// Construct an optimized "KV"-style attribute set given the value for the /// `"name"` key, and the value for the `"value"` key pub(crate) fn from_kv(name: Value, value: Value) -> Self { - NixAttrs(AttrsRep::KV { name, value }) + AttrsRep::KV { name, value }.into() } } @@ -396,12 +380,12 @@ impl IntoIterator for NixAttrs { type IntoIter = OwnedAttrsIterator; fn into_iter(self) -> Self::IntoIter { - match self.0 { + match Rc::unwrap_or_clone(self.0) { AttrsRep::Empty => OwnedAttrsIterator(IntoIterRepr::Empty), AttrsRep::KV { name, value } => OwnedAttrsIterator(IntoIterRepr::Finite( - vec![(NAME_REF.clone(), name), (VALUE_REF.clone(), value)].into_iter(), + vec![(NAME.clone(), name), (VALUE.clone(), value)].into_iter(), )), - AttrsRep::Im(map) => OwnedAttrsIterator(IntoIterRepr::Im(map.into_iter())), + AttrsRep::Map(map) => OwnedAttrsIterator(IntoIterRepr::Map(map.into_iter())), } } } @@ -422,8 +406,8 @@ impl IntoIterator for NixAttrs { fn attempt_optimise_kv(slice: &mut [Value]) -> Option<NixAttrs> { let (name_idx, value_idx) = { match (&slice[2], &slice[0]) { - (Value::String(s1), Value::String(s2)) if (*s1 == *NAME_S && *s2 == *VALUE_S) => (3, 1), - (Value::String(s1), Value::String(s2)) if (*s1 == *VALUE_S && *s2 == *NAME_S) => (1, 3), + (Value::String(s1), Value::String(s2)) if (*s1 == *NAME && *s2 == *VALUE) => (3, 1), + (Value::String(s1), Value::String(s2)) if (*s1 == *VALUE && *s2 == *NAME) => (1, 3), // Technically this branch lets type errors pass, // but they will be caught during normal attribute @@ -440,13 +424,17 @@ fn attempt_optimise_kv(slice: &mut [Value]) -> Option<NixAttrs> { /// Set an attribute on an in-construction attribute set, while /// checking against duplicate keys. -fn set_attr(attrs: &mut NixAttrs, key: NixString, value: Value) -> Result<(), ErrorKind> { - match attrs.0.map_mut().entry(key) { - imbl::ordmap::Entry::Occupied(entry) => Err(ErrorKind::DuplicateAttrsKey { +fn set_attr( + map: &mut BTreeMap<NixString, Value>, + key: NixString, + value: Value, +) -> Result<(), ErrorKind> { + match map.entry(key) { + btree_map::Entry::Occupied(entry) => Err(ErrorKind::DuplicateAttrsKey { key: entry.key().to_string(), }), - imbl::ordmap::Entry::Vacant(entry) => { + btree_map::Entry::Vacant(entry) => { entry.insert(value); Ok(()) } @@ -484,7 +472,7 @@ pub enum KeyValue<'a> { at: IterKV, }, - Im(imbl::ordmap::Iter<'a, NixString, Value>), + Map(btree_map::Iter<'a, NixString, Value>), } /// Iterator over a Nix attribute set. @@ -498,18 +486,18 @@ impl<'a> Iterator for Iter<KeyValue<'a>> { fn next(&mut self) -> Option<Self::Item> { match &mut self.0 { - KeyValue::Im(inner) => inner.next(), + KeyValue::Map(inner) => inner.next(), KeyValue::Empty => None, KeyValue::KV { name, value, at } => match at { IterKV::Name => { at.next(); - Some((&NAME_REF, name)) + Some((&NAME, name)) } IterKV::Value => { at.next(); - Some((&VALUE_REF, value)) + Some((&VALUE, value)) } IterKV::Done => None, @@ -523,7 +511,7 @@ impl<'a> ExactSizeIterator for Iter<KeyValue<'a>> { match &self.0 { KeyValue::Empty => 0, KeyValue::KV { .. } => 2, - KeyValue::Im(inner) => inner.len(), + KeyValue::Map(inner) => inner.len(), } } } @@ -531,7 +519,7 @@ impl<'a> ExactSizeIterator for Iter<KeyValue<'a>> { enum KeysInner<'a> { Empty, KV(IterKV), - Im(imbl::ordmap::Keys<'a, NixString, Value>), + Map(btree_map::Keys<'a, NixString, Value>), } pub struct Keys<'a>(KeysInner<'a>); @@ -544,14 +532,14 @@ impl<'a> Iterator for Keys<'a> { KeysInner::Empty => None, KeysInner::KV(at @ IterKV::Name) => { at.next(); - Some(&NAME_REF) + Some(&NAME) } KeysInner::KV(at @ IterKV::Value) => { at.next(); - Some(&VALUE_REF) + Some(&VALUE) } KeysInner::KV(IterKV::Done) => None, - KeysInner::Im(m) => m.next(), + KeysInner::Map(m) => m.next(), } } } @@ -571,7 +559,7 @@ impl<'a> ExactSizeIterator for Keys<'a> { match &self.0 { KeysInner::Empty => 0, KeysInner::KV(_) => 2, - KeysInner::Im(m) => m.len(), + KeysInner::Map(m) => m.len(), } } } @@ -580,7 +568,7 @@ impl<'a> ExactSizeIterator for Keys<'a> { pub enum IntoIterRepr { Empty, Finite(std::vec::IntoIter<(NixString, Value)>), - Im(imbl::ordmap::ConsumingIter<(NixString, Value)>), + Map(btree_map::IntoIter<NixString, Value>), } /// Wrapper type which hides the internal implementation details from @@ -595,7 +583,7 @@ impl Iterator for OwnedAttrsIterator { match &mut self.0 { IntoIterRepr::Empty => None, IntoIterRepr::Finite(inner) => inner.next(), - IntoIterRepr::Im(inner) => inner.next(), + IntoIterRepr::Map(m) => m.next(), } } } @@ -605,7 +593,7 @@ impl ExactSizeIterator for OwnedAttrsIterator { match &self.0 { IntoIterRepr::Empty => 0, IntoIterRepr::Finite(inner) => inner.len(), - IntoIterRepr::Im(inner) => inner.len(), + IntoIterRepr::Map(inner) => inner.len(), } } } @@ -615,7 +603,7 @@ impl DoubleEndedIterator for OwnedAttrsIterator { match &mut self.0 { IntoIterRepr::Empty => None, IntoIterRepr::Finite(inner) => inner.next_back(), - IntoIterRepr::Im(inner) => inner.next_back(), + IntoIterRepr::Map(inner) => inner.next_back(), } } } diff --git a/tvix/eval/src/value/attrs/tests.rs b/tvix/eval/src/value/attrs/tests.rs index 534b78a00d10..e8798797fda7 100644 --- a/tvix/eval/src/value/attrs/tests.rs +++ b/tvix/eval/src/value/attrs/tests.rs @@ -9,7 +9,7 @@ fn test_empty_attrs() { .unwrap(); assert!( - matches!(attrs, NixAttrs(AttrsRep::Empty)), + matches!(attrs.0.as_ref(), AttrsRep::Empty), "empty attribute set should use optimised representation" ); } @@ -21,7 +21,7 @@ fn test_simple_attrs() { .unwrap(); assert!( - matches!(attrs, NixAttrs(AttrsRep::Im(_))), + matches!(attrs.0.as_ref(), AttrsRep::Map(_)), "simple attribute set should use map representation", ) } @@ -45,8 +45,8 @@ fn test_kv_attrs() { .expect("constructing K/V pair attrs should succeed") .unwrap(); - match kv_attrs { - NixAttrs(AttrsRep::KV { name, value }) + match kv_attrs.0.as_ref() { + AttrsRep::KV { name, value } if name.to_str().unwrap() == meaning_val.to_str().unwrap() || value.to_str().unwrap() == forty_two_val.to_str().unwrap() => {} @@ -84,10 +84,10 @@ fn test_kv_attrs_iter() { let mut iter = kv_attrs.iter().collect::<Vec<_>>().into_iter(); let (k, v) = iter.next().unwrap(); - assert!(k == *NAME_REF); + assert!(*k == *NAME); assert!(v.to_str().unwrap() == meaning_val.to_str().unwrap()); let (k, v) = iter.next().unwrap(); - assert!(k == *VALUE_REF); + assert!(*k == *VALUE); assert!(v.as_int().unwrap() == forty_two_val.as_int().unwrap()); assert!(iter.next().is_none()); } diff --git a/tvix/eval/src/value/json.rs b/tvix/eval/src/value/json.rs index c48e9c1f4e85..24a6bcaf6f21 100644 --- a/tvix/eval/src/value/json.rs +++ b/tvix/eval/src/value/json.rs @@ -47,8 +47,8 @@ impl Value { for val in l.into_iter() { match generators::request_to_json(co, val).await { - Ok((v, mut ctx)) => { - context = context.join(&mut ctx); + Ok((v, ctx)) => { + context.extend(ctx.into_iter()); out.push(v) } Err(cek) => return Ok(Err(cek)), @@ -100,8 +100,8 @@ impl Value { out.insert( name.to_str()?.to_owned(), match generators::request_to_json(co, value).await { - Ok((v, mut ctx)) => { - context = context.join(&mut ctx); + Ok((v, ctx)) => { + context.extend(ctx.into_iter()); v } Err(cek) => return Ok(Err(cek)), diff --git a/tvix/eval/src/value/list.rs b/tvix/eval/src/value/list.rs index 2b8b3de28d19..3e4b23a93f42 100644 --- a/tvix/eval/src/value/list.rs +++ b/tvix/eval/src/value/list.rs @@ -2,8 +2,6 @@ use std::ops::Index; use std::rc::Rc; -use imbl::{vector, Vector}; - use serde::Deserialize; use super::thunk::ThunkSet; @@ -12,7 +10,7 @@ use super::Value; #[repr(transparent)] #[derive(Clone, Debug, Deserialize)] -pub struct NixList(Rc<Vector<Value>>); +pub struct NixList(Rc<Vec<Value>>); impl TotalDisplay for NixList { fn total_fmt(&self, f: &mut std::fmt::Formatter<'_>, set: &mut ThunkSet) -> std::fmt::Result { @@ -27,8 +25,8 @@ impl TotalDisplay for NixList { } } -impl From<Vector<Value>> for NixList { - fn from(vs: Vector<Value>) -> Self { +impl From<Vec<Value>> for NixList { + fn from(vs: Vec<Value>) -> Self { Self(Rc::new(vs)) } } @@ -54,10 +52,10 @@ impl NixList { stack_slice.len(), ); - NixList(Rc::new(Vector::from_iter(stack_slice))) + NixList(Rc::new(stack_slice)) } - pub fn iter(&self) -> vector::Iter<Value> { + pub fn iter(&self) -> std::slice::Iter<Value> { self.0.iter() } @@ -65,19 +63,14 @@ impl NixList { Rc::ptr_eq(&self.0, &other.0) } - pub fn into_inner(self) -> Vector<Value> { + pub fn into_inner(self) -> Vec<Value> { Rc::try_unwrap(self.0).unwrap_or_else(|rc| (*rc).clone()) } - - #[deprecated(note = "callers should avoid constructing from Vec")] - pub fn from_vec(vs: Vec<Value>) -> Self { - Self(Rc::new(Vector::from_iter(vs))) - } } impl IntoIterator for NixList { type Item = Value; - type IntoIter = imbl::vector::ConsumingIter<Value>; + type IntoIter = std::vec::IntoIter<Value>; fn into_iter(self) -> Self::IntoIter { self.into_inner().into_iter() @@ -86,7 +79,7 @@ impl IntoIterator for NixList { impl<'a> IntoIterator for &'a NixList { type Item = &'a Value; - type IntoIter = imbl::vector::Iter<'a, Value>; + type IntoIter = std::slice::Iter<'a, Value>; fn into_iter(self) -> Self::IntoIter { self.0.iter() diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index c171c9a04eb8..19ff17feab51 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -5,8 +5,10 @@ use std::fmt::Display; use std::num::{NonZeroI32, NonZeroUsize}; use std::path::PathBuf; use std::rc::Rc; +use std::sync::LazyLock; use bstr::{BString, ByteVec}; +use codemap::Span; use lexical_core::format::CXX_LITERAL; use serde::Deserialize; @@ -23,7 +25,6 @@ mod thunk; use crate::errors::{CatchableErrorKind, ErrorKind}; use crate::opcode::StackIdx; -use crate::spans::LightSpan; use crate::vm::generators::{self, GenCo}; use crate::AddContext; pub use attrs::NixAttrs; @@ -37,8 +38,6 @@ pub use thunk::Thunk; pub use self::thunk::ThunkSet; -use lazy_static::lazy_static; - #[warn(variant_size_differences)] #[derive(Clone, Debug, Deserialize)] #[serde(untagged)] @@ -84,7 +83,6 @@ pub enum Value { FinaliseRequest(bool), #[serde(skip)] - // TODO(tazjin): why is this in a Box? Catchable(Box<CatchableErrorKind>), } @@ -108,16 +106,15 @@ where } } -lazy_static! { - static ref WRITE_FLOAT_OPTIONS: lexical_core::WriteFloatOptions = - lexical_core::WriteFloatOptionsBuilder::new() - .trim_floats(true) - .round_mode(lexical_core::write_float_options::RoundMode::Round) - .positive_exponent_break(Some(NonZeroI32::new(5).unwrap())) - .max_significant_digits(Some(NonZeroUsize::new(6).unwrap())) - .build() - .unwrap(); -} +static WRITE_FLOAT_OPTIONS: LazyLock<lexical_core::WriteFloatOptions> = LazyLock::new(|| { + lexical_core::WriteFloatOptionsBuilder::new() + .trim_floats(true) + .round_mode(lexical_core::write_float_options::RoundMode::Round) + .positive_exponent_break(Some(NonZeroI32::new(5).unwrap())) + .max_significant_digits(Some(NonZeroUsize::new(6).unwrap())) + .build() + .unwrap() +}); // Helper macros to generate the to_*/as_* macros while accounting for // thunks. @@ -187,6 +184,21 @@ pub struct CoercionKind { pub import_paths: bool, } +impl From<CoercionKind> for u8 { + fn from(k: CoercionKind) -> u8 { + k.strong as u8 | (k.import_paths as u8) << 1 + } +} + +impl From<u8> for CoercionKind { + fn from(byte: u8) -> Self { + CoercionKind { + strong: byte & 0x01 != 0, + import_paths: byte & 0x02 != 0, + } + } +} + impl<T> From<T> for Value where T: Into<NixString>, @@ -196,14 +208,6 @@ where } } -/// Constructors -impl Value { - /// Construct a [`Value::Attrs`] from a [`NixAttrs`]. - pub fn attrs(attrs: NixAttrs) -> Self { - Self::Attrs(Box::new(attrs)) - } -} - /// Controls what kind of by-pointer equality comparison is allowed. /// /// See `//tvix/docs/value-pointer-equality.md` for details. @@ -220,11 +224,16 @@ pub enum PointerEquality { } impl Value { + /// Construct a [`Value::Attrs`] from a [`NixAttrs`]. + pub fn attrs(attrs: NixAttrs) -> Self { + Self::Attrs(Box::new(attrs)) + } + /// Deeply forces a value, traversing e.g. lists and attribute sets and forcing /// their contents, too. /// /// This is a generator function. - pub(super) async fn deep_force(self, co: GenCo, span: LightSpan) -> Result<Value, ErrorKind> { + pub(super) async fn deep_force(self, co: GenCo, span: Span) -> Result<Value, ErrorKind> { if let Some(v) = Self::deep_force_(self.clone(), co, span).await? { Ok(v) } else { @@ -233,11 +242,7 @@ impl Value { } /// Returns Some(v) or None to indicate the returned value is myself - async fn deep_force_( - myself: Value, - co: GenCo, - span: LightSpan, - ) -> Result<Option<Value>, ErrorKind> { + async fn deep_force_(myself: Value, co: GenCo, span: Span) -> Result<Option<Value>, ErrorKind> { // This is a stack of values which still remain to be forced. let mut vals = vec![myself]; @@ -256,7 +261,7 @@ impl Value { if !thunk_set.insert(t) { continue; } - Thunk::force_(t.clone(), &co, span.clone()).await? + Thunk::force_(t.clone(), &co, span).await? } else { v }; @@ -307,7 +312,7 @@ impl Value { self, co: GenCo, kind: CoercionKind, - span: LightSpan, + span: Span, ) -> Result<Value, ErrorKind> { self.coerce_to_string_(&co, kind, span).await } @@ -318,7 +323,7 @@ impl Value { self, co: &GenCo, kind: CoercionKind, - span: LightSpan, + span: Span, ) -> Result<Value, ErrorKind> { let mut result = BString::default(); let mut vals = vec![self]; @@ -331,15 +336,15 @@ impl Value { loop { let value = if let Some(v) = vals.pop() { - v.force(co, span.clone()).await? + v.force(co, span).await? } else { return Ok(Value::String(NixString::new_context_from(context, result))); }; let coerced: Result<BString, _> = match (value, kind) { // coercions that are always done (Value::String(mut s), _) => { - if let Some(ctx) = s.context_mut() { - context = context.join(ctx); + if let Some(ctx) = s.take_context() { + context.extend(ctx.into_iter()); } Ok((*s).into()) } @@ -377,7 +382,7 @@ impl Value { // `__toString` is preferred. (Value::Attrs(attrs), kind) => { if let Some(to_string) = attrs.select("__toString") { - let callable = to_string.clone().force(co, span.clone()).await?; + let callable = to_string.clone().force(co, span).await?; // Leave the attribute set on the stack as an argument // to the function call. @@ -467,7 +472,7 @@ impl Value { other: Value, co: GenCo, ptr_eq: PointerEquality, - span: LightSpan, + span: Span, ) -> Result<Value, ErrorKind> { self.nix_eq(other, &co, ptr_eq, span).await } @@ -487,7 +492,7 @@ impl Value { other: Value, co: &GenCo, ptr_eq: PointerEquality, - span: LightSpan, + span: Span, ) -> Result<Value, ErrorKind> { // this is a stack of ((v1,v2),peq) triples to be compared; // after each triple is popped off of the stack, v1 is @@ -513,13 +518,13 @@ impl Value { } }; - Thunk::force_(thunk, co, span.clone()).await? + Thunk::force_(thunk, co, span).await? } _ => a, }; - let b = b.force(co, span.clone()).await?; + let b = b.force(co, span).await?; debug_assert!(!matches!(a, Value::Thunk(_))); debug_assert!(!matches!(b, Value::Thunk(_))); @@ -568,11 +573,11 @@ impl Value { #[allow(clippy::single_match)] // might need more match arms later match (a1.select("type"), a2.select("type")) { (Some(v1), Some(v2)) => { - let s1 = v1.clone().force(co, span.clone()).await?; + let s1 = v1.clone().force(co, span).await?; if s1.is_catchable() { return Ok(s1); } - let s2 = v2.clone().force(co, span.clone()).await?; + let s2 = v2.clone().force(co, span).await?; if s2.is_catchable() { return Ok(s2); } @@ -593,8 +598,8 @@ impl Value { .context("comparing derivations")? .clone(); - let out1 = out1.clone().force(co, span.clone()).await?; - let out2 = out2.clone().force(co, span.clone()).await?; + let out1 = out1.clone().force(co, span).await?; + let out2 = out2.clone().force(co, span).await?; if out1.is_catchable() { return Ok(out1); @@ -745,7 +750,7 @@ impl Value { self, other: Self, co: GenCo, - span: LightSpan, + span: Span, ) -> Result<Result<Ordering, CatchableErrorKind>, ErrorKind> { Self::nix_cmp_ordering_(self, other, co, span).await } @@ -754,7 +759,7 @@ impl Value { myself: Self, other: Self, co: GenCo, - span: LightSpan, + span: Span, ) -> Result<Result<Ordering, CatchableErrorKind>, ErrorKind> { // this is a stack of ((v1,v2),peq) triples to be compared; // after each triple is popped off of the stack, v1 is @@ -770,14 +775,14 @@ impl Value { }; if ptr_eq == PointerEquality::AllowAll { if a.clone() - .nix_eq(b.clone(), &co, PointerEquality::AllowAll, span.clone()) + .nix_eq(b.clone(), &co, PointerEquality::AllowAll, span) .await? .as_bool()? { continue; } - a = a.force(&co, span.clone()).await?; - b = b.force(&co, span.clone()).await?; + a = a.force(&co, span).await?; + b = b.force(&co, span).await?; } let result = match (a, b) { (Value::Catchable(c), _) => return Ok(Err(*c)), @@ -820,7 +825,7 @@ impl Value { } // TODO(amjoseph): de-asyncify this (when called directly by the VM) - pub async fn force(self, co: &GenCo, span: LightSpan) -> Result<Value, ErrorKind> { + pub async fn force(self, co: &GenCo, span: Span) -> Result<Value, ErrorKind> { if let Value::Thunk(thunk) = self { // TODO(amjoseph): use #[tailcall::mutual] return Thunk::force_(thunk, co, span).await; @@ -829,7 +834,7 @@ impl Value { } // need two flavors, because async - pub async fn force_owned_genco(self, co: GenCo, span: LightSpan) -> Result<Value, ErrorKind> { + pub async fn force_owned_genco(self, co: GenCo, span: Span) -> Result<Value, ErrorKind> { if let Value::Thunk(thunk) = self { // TODO(amjoseph): use #[tailcall::mutual] return Thunk::force_(thunk, &co, span).await; @@ -881,6 +886,12 @@ impl Value { | Value::FinaliseRequest(_) => "an internal Tvix evaluator value".into(), } } + + /// Constructs a thunk that will be evaluated lazily at runtime. This lets + /// users of Tvix implement their own lazy builtins and so on. + pub fn suspended_native_thunk(native: Box<dyn Fn() -> Result<Value, ErrorKind>>) -> Self { + Value::Thunk(Thunk::new_suspended_native(native)) + } } trait TotalDisplay { diff --git a/tvix/eval/src/value/string/context.rs b/tvix/eval/src/value/string/context.rs new file mode 100644 index 000000000000..e1c04735ddde --- /dev/null +++ b/tvix/eval/src/value/string/context.rs @@ -0,0 +1,161 @@ +use rustc_hash::FxHashSet; +use serde::Serialize; + +use super::NixString; + +#[derive(Clone, Debug, Serialize, Hash, PartialEq, Eq)] +pub enum NixContextElement { + /// A plain store path (e.g. source files copied to the store) + Plain(String), + + /// Single output of a derivation, represented by its name and its derivation path. + Single { name: String, derivation: String }, + + /// A reference to a complete derivation + /// including its source and its binary closure. + /// It is used for the `drvPath` attribute context. + /// The referred string is the store path to + /// the derivation path. + Derivation(String), +} + +/// Nix context strings representation in Tvix. This tracks a set of different kinds of string +/// dependencies that we can come across during manipulation of our language primitives, mostly +/// strings. There's some simple algebra of context strings and how they propagate w.r.t. primitive +/// operations, e.g. concatenation, interpolation and other string operations. +#[repr(transparent)] +#[derive(Clone, Debug, Serialize, Default)] +pub struct NixContext(FxHashSet<NixContextElement>); + +impl From<NixContextElement> for NixContext { + fn from(value: NixContextElement) -> Self { + let mut set = FxHashSet::default(); + set.insert(value); + Self(set) + } +} + +impl From<FxHashSet<NixContextElement>> for NixContext { + fn from(value: FxHashSet<NixContextElement>) -> Self { + Self(value) + } +} + +impl<const N: usize> From<[NixContextElement; N]> for NixContext { + fn from(value: [NixContextElement; N]) -> Self { + let mut set = FxHashSet::default(); + for elt in value { + set.insert(elt); + } + Self(set) + } +} + +impl NixContext { + /// Creates an empty context that can be populated + /// and passed to form a contextful [NixString], albeit + /// if the context is concretly empty, the resulting [NixString] + /// will be contextless. + pub fn new() -> Self { + Self::default() + } + + /// For internal consumers, we let people observe + /// if the [NixContext] is actually empty or not + /// to decide whether they want to skip the allocation + /// of a full blown [HashSet]. + pub(crate) fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Consumes a new [NixContextElement] and add it if not already + /// present in this context. + pub fn append(mut self, other: NixContextElement) -> Self { + self.0.insert(other); + self + } + + /// Extends the existing context with more context elements. + pub fn extend<T>(&mut self, iter: T) + where + T: IntoIterator<Item = NixContextElement>, + { + self.0.extend(iter) + } + + /// Copies from another [NixString] its context strings + /// in this context. + pub fn mimic(&mut self, other: &NixString) { + if let Some(context) = other.context() { + self.extend(context.iter().cloned()); + } + } + + /// Iterates over "plain" context elements, e.g. sources imported + /// in the store without more information, i.e. `toFile` or coerced imported paths. + /// It yields paths to the store. + pub fn iter_plain(&self) -> impl Iterator<Item = &str> { + self.iter().filter_map(|elt| { + if let NixContextElement::Plain(s) = elt { + Some(s.as_str()) + } else { + None + } + }) + } + + /// Iterates over "full derivations" context elements, e.g. something + /// referring to their `drvPath`, i.e. their full sources and binary closure. + /// It yields derivation paths. + pub fn iter_derivation(&self) -> impl Iterator<Item = &str> { + self.iter().filter_map(|elt| { + if let NixContextElement::Derivation(s) = elt { + Some(s.as_str()) + } else { + None + } + }) + } + + /// Iterates over "single" context elements, e.g. single derived paths, + /// or also known as the single output of a given derivation. + /// The first element of the tuple is the output name + /// and the second element is the derivation path. + pub fn iter_single_outputs(&self) -> impl Iterator<Item = (&str, &str)> { + self.iter().filter_map(|elt| { + if let NixContextElement::Single { name, derivation } = elt { + Some((name.as_str(), derivation.as_str())) + } else { + None + } + }) + } + + /// Iterates over any element of the context. + pub fn iter(&self) -> impl Iterator<Item = &NixContextElement> { + self.0.iter() + } + + /// Produces a list of owned references to this current context, + /// no matter its type. + pub fn to_owned_references(self) -> Vec<String> { + self.0 + .into_iter() + .map(|ctx| match ctx { + NixContextElement::Derivation(drv_path) => drv_path, + NixContextElement::Plain(store_path) => store_path, + NixContextElement::Single { derivation, .. } => derivation, + }) + .collect() + } +} + +impl IntoIterator for NixContext { + type Item = NixContextElement; + + type IntoIter = std::collections::hash_set::IntoIter<NixContextElement>; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} diff --git a/tvix/eval/src/value/string.rs b/tvix/eval/src/value/string/mod.rs index ceb43f1ea5ed..5bcb4786b283 100644 --- a/tvix/eval/src/value/string.rs +++ b/tvix/eval/src/value/string/mod.rs @@ -1,158 +1,30 @@ //! This module implements Nix language strings. //! -//! Nix language strings never need to be modified on the language -//! level, allowing us to shave off some memory overhead and only -//! paying the cost when creating new strings. +//! See [`NixString`] for more information about the internals of string values + use bstr::{BStr, BString, ByteSlice, Chars}; +use nohash_hasher::BuildNoHashHasher; use rnix::ast; -use std::alloc::{alloc, dealloc, handle_alloc_error, Layout}; +#[cfg(feature = "no_leak")] +use rustc_hash::FxHashSet; +use rustc_hash::FxHasher; +use std::alloc::dealloc; +use std::alloc::{alloc, handle_alloc_error, Layout}; use std::borrow::{Borrow, Cow}; -use std::collections::HashSet; +use std::cell::RefCell; use std::ffi::c_void; use std::fmt::{self, Debug, Display}; -use std::hash::Hash; +use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::ptr::{self, NonNull}; use std::slice; use serde::de::{Deserializer, Visitor}; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, Serialize, Hash, PartialEq, Eq)] -pub enum NixContextElement { - /// A plain store path (e.g. source files copied to the store) - Plain(String), - - /// Single output of a derivation, represented by its name and its derivation path. - Single { name: String, derivation: String }, - - /// A reference to a complete derivation - /// including its source and its binary closure. - /// It is used for the `drvPath` attribute context. - /// The referred string is the store path to - /// the derivation path. - Derivation(String), -} - -/// Nix context strings representation in Tvix. This tracks a set of different kinds of string -/// dependencies that we can come across during manipulation of our language primitives, mostly -/// strings. There's some simple algebra of context strings and how they propagate w.r.t. primitive -/// operations, e.g. concatenation, interpolation and other string operations. -#[repr(transparent)] -#[derive(Clone, Debug, Serialize, Default)] -pub struct NixContext(HashSet<NixContextElement>); - -impl From<NixContextElement> for NixContext { - fn from(value: NixContextElement) -> Self { - Self([value].into()) - } -} +use serde::Deserialize; -impl From<HashSet<NixContextElement>> for NixContext { - fn from(value: HashSet<NixContextElement>) -> Self { - Self(value) - } -} +mod context; -impl NixContext { - /// Creates an empty context that can be populated - /// and passed to form a contextful [NixString], albeit - /// if the context is concretly empty, the resulting [NixString] - /// will be contextless. - pub fn new() -> Self { - Self::default() - } - - /// For internal consumers, we let people observe - /// if the [NixContext] is actually empty or not - /// to decide whether they want to skip the allocation - /// of a full blown [HashSet]. - pub(crate) fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Consumes a new [NixContextElement] and add it if not already - /// present in this context. - pub fn append(mut self, other: NixContextElement) -> Self { - self.0.insert(other); - self - } - - /// Consumes both ends of the join into a new NixContent - /// containing the union of elements of both ends. - pub fn join(mut self, other: &mut NixContext) -> Self { - let other_set = std::mem::take(&mut other.0); - let mut set: HashSet<NixContextElement> = std::mem::take(&mut self.0); - set.extend(other_set); - Self(set) - } - - /// Copies from another [NixString] its context strings - /// in this context. - pub fn mimic(&mut self, other: &NixString) { - if let Some(context) = other.context() { - self.0.extend(context.iter().cloned()); - } - } - - /// Iterates over "plain" context elements, e.g. sources imported - /// in the store without more information, i.e. `toFile` or coerced imported paths. - /// It yields paths to the store. - pub fn iter_plain(&self) -> impl Iterator<Item = &str> { - self.iter().filter_map(|elt| { - if let NixContextElement::Plain(s) = elt { - Some(s.as_str()) - } else { - None - } - }) - } - - /// Iterates over "full derivations" context elements, e.g. something - /// referring to their `drvPath`, i.e. their full sources and binary closure. - /// It yields derivation paths. - pub fn iter_derivation(&self) -> impl Iterator<Item = &str> { - self.iter().filter_map(|elt| { - if let NixContextElement::Derivation(s) = elt { - Some(s.as_str()) - } else { - None - } - }) - } - - /// Iterates over "single" context elements, e.g. single derived paths, - /// or also known as the single output of a given derivation. - /// The first element of the tuple is the output name - /// and the second element is the derivation path. - pub fn iter_single_outputs(&self) -> impl Iterator<Item = (&str, &str)> { - self.iter().filter_map(|elt| { - if let NixContextElement::Single { name, derivation } = elt { - Some((name.as_str(), derivation.as_str())) - } else { - None - } - }) - } - - /// Iterates over any element of the context. - pub fn iter(&self) -> impl Iterator<Item = &NixContextElement> { - self.0.iter() - } - - /// Produces a list of owned references to this current context, - /// no matter its type. - pub fn to_owned_references(self) -> Vec<String> { - self.0 - .into_iter() - .map(|ctx| match ctx { - NixContextElement::Derivation(drv_path) => drv_path, - NixContextElement::Plain(store_path) => store_path, - NixContextElement::Single { derivation, .. } => derivation, - }) - .collect() - } -} +pub use context::{NixContext, NixContextElement}; /// This type is never instantiated, but serves to document the memory layout of the actual heap /// allocation for Nix strings. @@ -374,6 +246,59 @@ impl NixStringInner { } } +#[derive(Default)] +struct InternerInner { + #[allow(clippy::disallowed_types)] // Not using the default hasher + map: std::collections::HashMap<u64, NonNull<c_void>, BuildNoHashHasher<u64>>, + #[cfg(feature = "no_leak")] + #[allow(clippy::disallowed_types)] // Not using the default hasher + interned_strings: FxHashSet<NonNull<c_void>>, +} + +unsafe impl Send for InternerInner {} + +fn hash<T>(s: T) -> u64 +where + T: Hash, +{ + let mut hasher = FxHasher::default(); + s.hash(&mut hasher); + hasher.finish() +} + +impl InternerInner { + pub fn intern(&mut self, s: &[u8]) -> NixString { + let hash = hash(s); + if let Some(s) = self.map.get(&hash) { + return NixString(*s); + } + + let string = NixString::new_inner(s, None); + self.map.insert(hash, string.0); + #[cfg(feature = "no_leak")] + self.interned_strings.insert(string.0); + string + } +} + +#[derive(Default)] +struct Interner(RefCell<InternerInner>); + +impl Interner { + pub fn intern(&self, s: &[u8]) -> NixString { + self.0.borrow_mut().intern(s) + } + + #[cfg(feature = "no_leak")] + pub fn is_interned_string(&self, string: &NixString) -> bool { + self.0.borrow().interned_strings.contains(&string.0) + } +} + +thread_local! { + static INTERNER: Interner = Interner::default(); +} + /// Nix string values /// /// # Internals @@ -393,7 +318,23 @@ unsafe impl Send for NixString {} unsafe impl Sync for NixString {} impl Drop for NixString { + #[cfg(not(feature = "no_leak"))] fn drop(&mut self) { + if self.context().is_some() { + // SAFETY: There's no way to construct a NixString that doesn't leave the allocation correct + // according to the rules of dealloc + unsafe { + NixStringInner::dealloc(self.0); + } + } + } + + #[cfg(feature = "no_leak")] + fn drop(&mut self) { + if INTERNER.with(|i| i.is_interned_string(self)) { + return; + } + // SAFETY: There's no way to construct a NixString that doesn't leave the allocation correct // according to the rules of dealloc unsafe { @@ -404,9 +345,17 @@ impl Drop for NixString { impl Clone for NixString { fn clone(&self) -> Self { - // SAFETY: There's no way to construct a NixString that doesn't leave the allocation correct - // according to the rules of clone - unsafe { Self(NixStringInner::clone(self.0)) } + if cfg!(feature = "no_leak") || self.context().is_some() { + // SAFETY: There's no way to construct a NixString that doesn't leave the allocation correct + // according to the rules of clone + unsafe { Self(NixStringInner::clone(self.0)) } + } else { + // SAFETY: + // + // - NixStrings are never mutated + // - NixStrings are never freed + Self(self.0) + } } } @@ -425,7 +374,7 @@ impl Debug for NixString { impl PartialEq for NixString { fn eq(&self, other: &Self) -> bool { - self.as_bstr() == other.as_bstr() + self.0 == other.0 || self.as_bstr() == other.as_bstr() } } @@ -451,6 +400,9 @@ impl PartialOrd for NixString { impl Ord for NixString { fn cmp(&self, other: &Self) -> std::cmp::Ordering { + if self.0 == other.0 { + return std::cmp::Ordering::Equal; + } self.as_bstr().cmp(other.as_bstr()) } } @@ -614,8 +566,30 @@ mod arbitrary { } } +/// Set non-scientifically. TODO(aspen): think more about what this should be +const INTERN_THRESHOLD: usize = 32; + impl NixString { fn new(contents: &[u8], context: Option<Box<NixContext>>) -> Self { + debug_assert!( + !context.as_deref().is_some_and(NixContext::is_empty), + "BUG: initialized with empty context" + ); + + if !cfg!(feature = "no_leak") /* It's only safe to intern if we leak strings, since there's + * nothing yet preventing interned strings from getting freed + * (and then used by other copies) otherwise + */ + && contents.len() <= INTERN_THRESHOLD + && context.is_none() + { + return INTERNER.with(|i| i.intern(contents)); + } + + Self::new_inner(contents, context) + } + + fn new_inner(contents: &[u8], context: Option<Box<NixContext>>) -> Self { // SAFETY: We're always fully initializing a NixString here: // // 1. NixStringInner::alloc sets up the len for us @@ -707,8 +681,10 @@ impl NixString { let context = [self.context(), other.context()] .into_iter() .flatten() - .fold(NixContext::new(), |acc_ctx, new_ctx| { - acc_ctx.join(&mut new_ctx.clone()) + .fold(NixContext::new(), |mut acc_ctx, new_ctx| { + // TODO: consume new_ctx? + acc_ctx.extend(new_ctx.iter().cloned()); + acc_ctx }); Self::new_context_from(context, s) } @@ -719,33 +695,59 @@ impl NixString { // // Also, we're using the same lifetime and mutability as self, to fit the // pointer-to-reference conversion rules - unsafe { NixStringInner::context_ref(self.0).as_deref() } + let context = unsafe { NixStringInner::context_ref(self.0).as_deref() }; + + debug_assert!( + !context.is_some_and(NixContext::is_empty), + "BUG: empty context" + ); + + context } - pub(crate) fn context_mut(&mut self) -> Option<&mut NixContext> { + pub(crate) fn context_mut(&mut self) -> &mut Option<Box<NixContext>> { // SAFETY: There's no way to construct an uninitialized or invalid NixString (see the SAFETY // comment in `new`). // // Also, we're using the same lifetime and mutability as self, to fit the // pointer-to-reference conversion rules - unsafe { NixStringInner::context_mut(self.0).as_deref_mut() } + let context = unsafe { NixStringInner::context_mut(self.0) }; + + debug_assert!( + !context.as_deref().is_some_and(NixContext::is_empty), + "BUG: empty context" + ); + + context } + /// Iterates over all context elements. + /// See [iter_plain], [iter_derivation], [iter_single_outputs]. pub fn iter_context(&self) -> impl Iterator<Item = &NixContext> { self.context().into_iter() } - pub fn iter_plain(&self) -> impl Iterator<Item = &str> { + /// Iterates over "plain" context elements, e.g. sources imported + /// in the store without more information, i.e. `toFile` or coerced imported paths. + /// It yields paths to the store. + pub fn iter_ctx_plain(&self) -> impl Iterator<Item = &str> { self.iter_context().flat_map(|context| context.iter_plain()) } - pub fn iter_derivation(&self) -> impl Iterator<Item = &str> { + /// Iterates over "full derivations" context elements, e.g. something + /// referring to their `drvPath`, i.e. their full sources and binary closure. + /// It yields derivation paths. + pub fn iter_ctx_derivation(&self) -> impl Iterator<Item = &str> { return self .iter_context() .flat_map(|context| context.iter_derivation()); } - pub fn iter_single_outputs(&self) -> impl Iterator<Item = (&str, &str)> { + /// Iterates over "single" context elements, e.g. single derived paths, + /// or also known as the single output of a given derivation. + /// The first element of the tuple is the output name + /// and the second element is the derivation path. + pub fn iter_ctx_single_outputs(&self) -> impl Iterator<Item = (&str, &str)> { return self .iter_context() .flat_map(|context| context.iter_single_outputs()); @@ -756,12 +758,16 @@ impl NixString { self.context().is_some() } + /// This clears the context of the string, returning + /// the removed dependency tracking information. + pub fn take_context(&mut self) -> Option<Box<NixContext>> { + self.context_mut().take() + } + /// This clears the context of that string, losing /// all dependency tracking information. pub fn clear_context(&mut self) { - // SAFETY: There's no way to construct an uninitialized or invalid NixString (see the SAFETY - // comment in `new`). - *unsafe { NixStringInner::context_mut(self.0) } = None; + let _ = self.take_context(); } pub fn chars(&self) -> Chars<'_> { @@ -849,7 +855,7 @@ impl Display for NixString { } } -#[cfg(test)] +#[cfg(all(test, feature = "arbitrary"))] mod tests { use test_strategy::proptest; diff --git a/tvix/eval/src/value/thunk.rs b/tvix/eval/src/value/thunk.rs index a67537f945a9..4b915019d47c 100644 --- a/tvix/eval/src/value/thunk.rs +++ b/tvix/eval/src/value/thunk.rs @@ -18,17 +18,16 @@ //! object, but when forcing a thunk, the runtime *must* mutate the //! memoisable slot. +use rustc_hash::FxHashSet; use std::{ cell::{Ref, RefCell, RefMut}, - collections::HashSet, fmt::Debug, rc::Rc, }; use crate::{ errors::ErrorKind, - opcode::OpCode, - spans::LightSpan, + opcode::Op, upvalues::Upvalues, value::Closure, vm::generators::{self, GenCo}, @@ -59,7 +58,7 @@ enum ThunkRepr { Suspended { lambda: Rc<Lambda>, upvalues: Rc<Upvalues>, - light_span: LightSpan, + span: Span, }, /// Thunk is a suspended native computation. @@ -69,10 +68,10 @@ enum ThunkRepr { /// value means that infinite recursion has occured. Blackhole { /// Span at which the thunk was first forced. - forced_at: LightSpan, + forced_at: Span, /// Span at which the thunk was originally suspended. - suspended_at: Option<LightSpan>, + suspended_at: Option<Span>, /// Span of the first instruction of the actual code inside /// the thunk. @@ -143,11 +142,11 @@ impl Thunk { ))))) } - pub fn new_suspended(lambda: Rc<Lambda>, light_span: LightSpan) -> Self { + pub fn new_suspended(lambda: Rc<Lambda>, span: Span) -> Self { Thunk(Rc::new(RefCell::new(ThunkRepr::Suspended { upvalues: Rc::new(Upvalues::with_capacity(lambda.upvalue_count)), lambda: lambda.clone(), - light_span, + span, }))) } @@ -162,9 +161,8 @@ impl Thunk { /// particularly useful in builtin implementations if the result of calling /// a function does not need to be forced immediately, because e.g. it is /// stored in an attribute set. - pub fn new_suspended_call(callee: Value, arg: Value, light_span: LightSpan) -> Self { + pub fn new_suspended_call(callee: Value, arg: Value, span: Span) -> Self { let mut lambda = Lambda::default(); - let span = light_span.span(); let arg_idx = lambda.chunk().push_constant(arg); let f_idx = lambda.chunk().push_constant(callee); @@ -172,28 +170,28 @@ impl Thunk { // This is basically a recreation of compile_apply(): // We need to push the argument onto the stack and then the function. // The function (not the argument) needs to be forced before calling. - lambda.chunk.push_op(OpCode::OpConstant(arg_idx), span); - lambda.chunk().push_op(OpCode::OpConstant(f_idx), span); - lambda.chunk.push_op(OpCode::OpForce, span); - lambda.chunk.push_op(OpCode::OpCall, span); + lambda.chunk.push_op(Op::Constant, span); + lambda.chunk.push_uvarint(arg_idx.0 as u64); + lambda.chunk.push_op(Op::Constant, span); + lambda.chunk.push_uvarint(f_idx.0 as u64); + lambda.chunk.push_op(Op::Force, span); + lambda.chunk.push_op(Op::Call, span); // Inform the VM that the chunk has ended - lambda.chunk.push_op(OpCode::OpReturn, span); + lambda.chunk.push_op(Op::Return, span); Thunk(Rc::new(RefCell::new(ThunkRepr::Suspended { upvalues: Rc::new(Upvalues::with_capacity(0)), lambda: Rc::new(lambda), - light_span, + span, }))) } - fn prepare_blackhole(&self, forced_at: LightSpan) -> ThunkRepr { + fn prepare_blackhole(&self, forced_at: Span) -> ThunkRepr { match &*self.0.borrow() { - ThunkRepr::Suspended { - light_span, lambda, .. - } => ThunkRepr::Blackhole { + ThunkRepr::Suspended { span, lambda, .. } => ThunkRepr::Blackhole { forced_at, - suspended_at: Some(light_span.clone()), + suspended_at: Some(*span), content_span: Some(lambda.chunk.first_span()), }, @@ -205,14 +203,10 @@ impl Thunk { } } - pub async fn force(myself: Thunk, co: GenCo, span: LightSpan) -> Result<Value, ErrorKind> { + pub async fn force(myself: Thunk, co: GenCo, span: Span) -> Result<Value, ErrorKind> { Self::force_(myself, &co, span).await } - pub async fn force_( - mut myself: Thunk, - co: &GenCo, - span: LightSpan, - ) -> Result<Value, ErrorKind> { + pub async fn force_(mut myself: Thunk, co: &GenCo, span: Span) -> Result<Value, ErrorKind> { // This vector of "thunks which point to the thunk-being-forced", to // be updated along with it, is necessary in order to write this // function in iterative (and later, mutual-tail-call) form. @@ -232,7 +226,7 @@ impl Thunk { // Begin evaluation of this thunk by marking it as a blackhole, meaning // that any other forcing frame encountering this thunk before its // evaluation is completed detected an evaluation cycle. - let inner = myself.0.replace(myself.prepare_blackhole(span.clone())); + let inner = myself.0.replace(myself.prepare_blackhole(span)); match inner { // If there was already a blackhole in the thunk, this is an @@ -243,8 +237,8 @@ impl Thunk { content_span, } => { return Err(ErrorKind::InfiniteRecursion { - first_force: forced_at.span(), - suspended_at: suspended_at.map(|s| s.span()), + first_force: forced_at, + suspended_at, content_span, }) } @@ -262,13 +256,12 @@ impl Thunk { ThunkRepr::Suspended { lambda, upvalues, - light_span, + span, } => { // TODO(amjoseph): use #[tailcall::mutual] here. This can // be turned into a tailcall to vm::execute_bytecode() by // passing `also_update` to it. - let value = - generators::request_enter_lambda(co, lambda, upvalues, light_span).await; + let value = generators::request_enter_lambda(co, lambda, upvalues, span).await; myself.0.replace(ThunkRepr::Evaluated(value)); continue; } @@ -422,7 +415,7 @@ impl TotalDisplay for Thunk { /// The inner `HashSet` is not available on the outside, as it would be /// potentially unsafe to interact with the pointers in the set. #[derive(Default)] -pub struct ThunkSet(HashSet<*const ThunkRepr>); +pub struct ThunkSet(FxHashSet<*const ThunkRepr>); impl ThunkSet { /// Check whether the given thunk has already been seen. Will mark the thunk diff --git a/tvix/eval/src/vm/generators.rs b/tvix/eval/src/vm/generators.rs index 79de6886923a..ae9a8dd6ab51 100644 --- a/tvix/eval/src/vm/generators.rs +++ b/tvix/eval/src/vm/generators.rs @@ -81,7 +81,7 @@ pub enum VMRequest { EnterLambda { lambda: Rc<Lambda>, upvalues: Rc<Upvalues>, - light_span: LightSpan, + span: Span, }, /// Emit a runtime warning (already containing a span) through the VM. @@ -121,6 +121,9 @@ pub enum VMRequest { /// Request serialisation of a value to JSON, according to the /// slightly odd Nix evaluation rules. ToJson(Value), + + /// Request the VM for the file type of the given path. + ReadFileType(PathBuf), } /// Human-readable representation of a generator message, used by observers. @@ -178,6 +181,7 @@ impl Display for VMRequest { VMRequest::Span => write!(f, "span"), VMRequest::TryForce(v) => write!(f, "try_force({})", v.type_of()), VMRequest::ToJson(v) => write!(f, "to_json({})", v.type_of()), + VMRequest::ReadFileType(p) => write!(f, "read_file_type({})", p.to_string_lossy()), } } } @@ -198,10 +202,12 @@ pub enum VMResponse { Directory(Vec<(bytes::Bytes, FileType)>), /// VM response with a span to use at the current point. - Span(LightSpan), + Span(Span), /// [std::io::Reader] produced by the VM in response to some IO operation. Reader(Box<dyn std::io::Read>), + + FileType(FileType), } impl Display for VMResponse { @@ -213,6 +219,7 @@ impl Display for VMResponse { VMResponse::Directory(d) => write!(f, "dir(len = {})", d.len()), VMResponse::Span(_) => write!(f, "span"), VMResponse::Reader(_) => write!(f, "reader"), + VMResponse::FileType(t) => write!(f, "file_type({})", t), } } } @@ -234,7 +241,7 @@ where { /// Helper function to re-enqueue the current generator while it /// is awaiting a value. - fn reenqueue_generator(&mut self, name: &'static str, span: LightSpan, generator: Generator) { + fn reenqueue_generator(&mut self, name: &'static str, span: Span, generator: Generator) { self.frames.push(Frame::Generator { name, generator, @@ -244,7 +251,7 @@ where } /// Helper function to enqueue a new generator. - pub(super) fn enqueue_generator<F, G>(&mut self, name: &'static str, span: LightSpan, gen: G) + pub(super) fn enqueue_generator<F, G>(&mut self, name: &'static str, span: Span, gen: G) where F: Future<Output = Result<Value, ErrorKind>> + 'static, G: FnOnce(GenCo) -> F, @@ -265,7 +272,7 @@ where pub(crate) fn run_generator( &mut self, name: &'static str, - span: LightSpan, + span: Span, frame_id: usize, state: GeneratorState, mut generator: Generator, @@ -302,8 +309,8 @@ where // this function prepares the frame stack and yields // back to the outer VM loop. VMRequest::ForceValue(value) => { - self.reenqueue_generator(name, span.clone(), generator); - self.enqueue_generator("force", span.clone(), |co| { + self.reenqueue_generator(name, span, generator); + self.enqueue_generator("force", span, |co| { value.force_owned_genco(co, span) }); return Ok(false); @@ -311,8 +318,8 @@ where // Generator has requested a deep-force. VMRequest::DeepForceValue(value) => { - self.reenqueue_generator(name, span.clone(), generator); - self.enqueue_generator("deep_force", span.clone(), |co| { + self.reenqueue_generator(name, span, generator); + self.enqueue_generator("deep_force", span, |co| { value.deep_force(co, span) }); return Ok(false); @@ -322,10 +329,10 @@ where // Logic is similar to `ForceValue`, except with the // value being taken from that stack. VMRequest::WithValue(idx) => { - self.reenqueue_generator(name, span.clone(), generator); + self.reenqueue_generator(name, span, generator); let value = self.stack[self.with_stack[idx]].clone(); - self.enqueue_generator("force", span.clone(), |co| { + self.enqueue_generator("force", span, |co| { value.force_owned_genco(co, span) }); @@ -336,13 +343,13 @@ where // with-stack. Logic is same as above, except for the // value being from that stack. VMRequest::CapturedWithValue(idx) => { - self.reenqueue_generator(name, span.clone(), generator); + self.reenqueue_generator(name, span, generator); let call_frame = self.last_call_frame() .expect("Tvix bug: generator requested captured with-value, but there is no call frame"); let value = call_frame.upvalues.with_stack().unwrap()[idx].clone(); - self.enqueue_generator("force", span.clone(), |co| { + self.enqueue_generator("force", span, |co| { value.force_owned_genco(co, span) }); @@ -351,23 +358,23 @@ where VMRequest::NixEquality(values, ptr_eq) => { let values = *values; - self.reenqueue_generator(name, span.clone(), generator); - self.enqueue_generator("nix_eq", span.clone(), |co| { + self.reenqueue_generator(name, span, generator); + self.enqueue_generator("nix_eq", span, |co| { values.0.nix_eq_owned_genco(values.1, co, ptr_eq, span) }); return Ok(false); } VMRequest::StringCoerce(val, kind) => { - self.reenqueue_generator(name, span.clone(), generator); - self.enqueue_generator("coerce_to_string", span.clone(), |co| { + self.reenqueue_generator(name, span, generator); + self.enqueue_generator("coerce_to_string", span, |co| { val.coerce_to_string(co, kind, span) }); return Ok(false); } VMRequest::Call(callable) => { - self.reenqueue_generator(name, span.clone(), generator); + self.reenqueue_generator(name, span, generator); self.call_value(span, None, callable)?; return Ok(false); } @@ -375,12 +382,12 @@ where VMRequest::EnterLambda { lambda, upvalues, - light_span, + span, } => { self.reenqueue_generator(name, span, generator); self.frames.push(Frame::CallFrame { - span: light_span, + span, call_frame: CallFrame { lambda, upvalues, @@ -424,7 +431,7 @@ where path: Some(path), error: e.into(), }) - .with_span(&span, self)?; + .with_span(span, self)?; message = VMResponse::Path(imported); } @@ -438,7 +445,7 @@ where path: Some(path), error: e.into(), }) - .with_span(&span, self)?; + .with_span(span, self)?; message = VMResponse::Reader(reader) } @@ -453,7 +460,7 @@ where error: e.into(), }) .map(Value::Bool) - .with_span(&span, self)?; + .with_span(span, self)?; message = VMResponse::Value(exists); } @@ -467,43 +474,57 @@ where path: Some(path), error: e.into(), }) - .with_span(&span, self)?; + .with_span(span, self)?; message = VMResponse::Directory(dir); } VMRequest::Span => { - message = VMResponse::Span(self.reasonable_light_span()); + message = VMResponse::Span(self.reasonable_span); } VMRequest::TryForce(value) => { self.try_eval_frames.push(frame_id); - self.reenqueue_generator(name, span.clone(), generator); + self.reenqueue_generator(name, span, generator); debug_assert!( self.frames.len() == frame_id + 1, "generator should be reenqueued with the same frame ID" ); - self.enqueue_generator("force", span.clone(), |co| { + self.enqueue_generator("force", span, |co| { value.force_owned_genco(co, span) }); return Ok(false); } VMRequest::ToJson(value) => { - self.reenqueue_generator(name, span.clone(), generator); + self.reenqueue_generator(name, span, generator); self.enqueue_generator("to_json", span, |co| { value.into_contextful_json_generator(co) }); return Ok(false); } + + VMRequest::ReadFileType(path) => { + let file_type = self + .io_handle + .as_ref() + .file_type(&path) + .map_err(|e| ErrorKind::IO { + path: Some(path), + error: e.into(), + }) + .with_span(span, self)?; + + message = VMResponse::FileType(file_type); + } } } // Generator has completed, and its result value should // be left on the stack. genawaiter::GeneratorState::Complete(result) => { - let value = result.with_span(&span, self)?; + let value = result.with_span(span, self)?; self.stack.push(value); return Ok(true); } @@ -683,12 +704,12 @@ pub(crate) async fn request_enter_lambda( co: &GenCo, lambda: Rc<Lambda>, upvalues: Rc<Upvalues>, - light_span: LightSpan, + span: Span, ) -> Value { let msg = VMRequest::EnterLambda { lambda, upvalues, - light_span, + span, }; match co.yield_(msg).await { @@ -745,6 +766,7 @@ pub async fn request_open_file(co: &GenCo, path: PathBuf) -> Box<dyn std::io::Re } } +#[cfg_attr(not(feature = "impure"), allow(unused))] pub(crate) async fn request_path_exists(co: &GenCo, path: PathBuf) -> Value { match co.yield_(VMRequest::PathExists(path)).await { VMResponse::Value(value) => value, @@ -755,6 +777,7 @@ pub(crate) async fn request_path_exists(co: &GenCo, path: PathBuf) -> Value { } } +#[cfg_attr(not(feature = "impure"), allow(unused))] pub(crate) async fn request_read_dir(co: &GenCo, path: PathBuf) -> Vec<(bytes::Bytes, FileType)> { match co.yield_(VMRequest::ReadDir(path)).await { VMResponse::Directory(dir) => dir, @@ -765,7 +788,7 @@ pub(crate) async fn request_read_dir(co: &GenCo, path: PathBuf) -> Vec<(bytes::B } } -pub(crate) async fn request_span(co: &GenCo) -> LightSpan { +pub(crate) async fn request_span(co: &GenCo) -> Span { match co.yield_(VMRequest::Span).await { VMResponse::Span(span) => span, msg => panic!( @@ -789,6 +812,17 @@ pub(crate) async fn request_to_json( } } +#[cfg_attr(not(feature = "impure"), allow(unused))] +pub(crate) async fn request_read_file_type(co: &GenCo, path: PathBuf) -> FileType { + match co.yield_(VMRequest::ReadFileType(path)).await { + VMResponse::FileType(file_type) => file_type, + msg => panic!( + "Tvix bug: VM responded with incorrect generator message: {}", + msg + ), + } +} + /// Call the given value as if it was an attribute set containing a functor. The /// arguments must already be prepared on the stack when a generator frame from /// this function is invoked. diff --git a/tvix/eval/src/vm/macros.rs b/tvix/eval/src/vm/macros.rs index d8a09706ab9c..f9c084d41f91 100644 --- a/tvix/eval/src/vm/macros.rs +++ b/tvix/eval/src/vm/macros.rs @@ -49,7 +49,7 @@ macro_rules! cmp_op { } } - let gen_span = $frame.current_light_span(); + let gen_span = $frame.current_span(); $vm.push_call_frame($span, $frame); $vm.enqueue_generator("compare", gen_span, |co| compare(a, b, co)); return Ok(false); diff --git a/tvix/eval/src/vm/mod.rs b/tvix/eval/src/vm/mod.rs index 5c244cc3ca97..0630ed4174e8 100644 --- a/tvix/eval/src/vm/mod.rs +++ b/tvix/eval/src/vm/mod.rs @@ -14,8 +14,9 @@ mod macros; use bstr::{BString, ByteSlice, ByteVec}; use codemap::Span; +use rustc_hash::FxHashMap; use serde_json::json; -use std::{cmp::Ordering, collections::HashMap, ops::DerefMut, path::PathBuf, rc::Rc}; +use std::{cmp::Ordering, ops::DerefMut, path::PathBuf, rc::Rc}; use crate::{ arithmetic_op, @@ -27,8 +28,7 @@ use crate::{ lifted_pop, nix_search_path::NixSearchPath, observer::RuntimeObserver, - opcode::{CodeIdx, Count, JumpOffset, OpCode, StackIdx, UpvalueIdx}, - spans::LightSpan, + opcode::{CodeIdx, Op, Position, UpvalueIdx}, upvalues::Upvalues, value::{ Builtin, BuiltinResult, Closure, CoercionKind, Lambda, NixAttrs, NixContext, NixList, @@ -51,7 +51,7 @@ trait GetSpan { impl<'o, IO> GetSpan for &VM<'o, IO> { fn get_span(self) -> Span { - self.reasonable_span.span() + self.reasonable_span } } @@ -61,9 +61,9 @@ impl GetSpan for &CallFrame { } } -impl GetSpan for &LightSpan { +impl GetSpan for &Span { fn get_span(self) -> Span { - self.span() + *self } } @@ -94,7 +94,7 @@ impl<T, S: GetSpan, IO> WithSpan<T, S, IO> for Result<T, ErrorKind> { Frame::CallFrame { span, .. } => { error = Error::new( ErrorKind::BytecodeError(Box::new(error)), - span.span(), + *span, vm.source.clone(), ); } @@ -104,7 +104,7 @@ impl<T, S: GetSpan, IO> WithSpan<T, S, IO> for Result<T, ErrorKind> { err: Box::new(error), gen_type: name, }, - span.span(), + *span, vm.source.clone(), ); } @@ -146,10 +146,32 @@ impl CallFrame { /// Increment this frame's instruction pointer and return the operation that /// the pointer moved past. - fn inc_ip(&mut self) -> OpCode { - let op = self.chunk()[self.ip]; + fn inc_ip(&mut self) -> Op { + debug_assert!( + self.ip.0 < self.chunk().code.len(), + "out of bounds code at IP {} in {:p}", + self.ip.0, + self.lambda + ); + + let op = self.chunk().code[self.ip.0]; self.ip += 1; - op + op.into() + } + + /// Read a varint-encoded operand and return it. The frame pointer is + /// incremented internally. + fn read_uvarint(&mut self) -> u64 { + let (arg, size) = self.chunk().read_uvarint(self.ip.0); + self.ip += size; + arg + } + + /// Read a fixed-size u16 and increment the frame pointer. + fn read_u16(&mut self) -> u16 { + let arg = self.chunk().read_u16(self.ip.0); + self.ip += 2; + arg } /// Construct an error result from the given ErrorKind and the source span @@ -163,13 +185,6 @@ impl CallFrame { pub fn current_span(&self) -> Span { self.chunk().get_span(self.ip - 1) } - - /// Returns the information needed to calculate the current span, - /// but without performing that calculation. - // TODO: why pub? - pub(crate) fn current_light_span(&self) -> LightSpan { - LightSpan::new_actual(self.current_span()) - } } /// A frame represents an execution state of the VM. The VM has a stack of @@ -187,7 +202,7 @@ enum Frame { call_frame: CallFrame, /// Span from which the call frame was launched. - span: LightSpan, + span: Span, }, /// Generator represents a frame that can yield further @@ -201,7 +216,7 @@ enum Frame { name: &'static str, /// Span from which the generator was launched. - span: LightSpan, + span: Span, state: GeneratorState, @@ -211,15 +226,15 @@ enum Frame { } impl Frame { - pub fn span(&self) -> LightSpan { + pub fn span(&self) -> Span { match self { - Frame::CallFrame { span, .. } | Frame::Generator { span, .. } => span.clone(), + Frame::CallFrame { span, .. } | Frame::Generator { span, .. } => *span, } } } #[derive(Default)] -struct ImportCache(HashMap<PathBuf, Value>); +struct ImportCache(FxHashMap<PathBuf, Value>); /// The `ImportCache` holds the `Value` resulting from `import`ing a certain /// file, so that the same file doesn't need to be re-evaluated multiple times. @@ -309,7 +324,7 @@ struct VM<'o, IO> { /// /// The VM should update this whenever control flow changes take place (i.e. /// entering or exiting a frame to yield control somewhere). - reasonable_span: LightSpan, + reasonable_span: Span, /// This field is responsible for handling `builtins.tryEval`. When that /// builtin is encountered, it sends a special message to the VM which @@ -343,7 +358,7 @@ where observer: &'o mut dyn RuntimeObserver, source: SourceCode, globals: Rc<GlobalsMap>, - reasonable_span: LightSpan, + reasonable_span: Span, ) -> Self { Self { nix_search_path, @@ -362,7 +377,7 @@ where } /// Push a call frame onto the frame stack. - fn push_call_frame(&mut self, span: LightSpan, call_frame: CallFrame) { + fn push_call_frame(&mut self, span: Span, call_frame: CallFrame) { self.frames.push(Frame::CallFrame { span, call_frame }) } @@ -434,8 +449,8 @@ where /// stack. In this case, the frame is not returned to the frame stack. /// /// 2. The code encounters a generator, in which case the frame in its - /// current state is pushed back on the stack, and the generator is left on - /// top of it for the outer loop to execute. + /// current state is pushed back on the stack, and the generator is left + /// on top of it for the outer loop to execute. /// /// 3. An error is encountered. /// @@ -444,27 +459,35 @@ where /// /// The return value indicates whether the bytecode has been executed to /// completion, or whether it has been suspended in favour of a generator. - fn execute_bytecode(&mut self, span: LightSpan, mut frame: CallFrame) -> EvalResult<bool> { + fn execute_bytecode(&mut self, span: Span, mut frame: CallFrame) -> EvalResult<bool> { loop { let op = frame.inc_ip(); self.observer.observe_execute_op(frame.ip, &op, &self.stack); match op { - OpCode::OpThunkSuspended(idx) | OpCode::OpThunkClosure(idx) => { - let blueprint = match &frame.chunk()[idx] { + Op::ThunkSuspended | Op::ThunkClosure => { + let idx = frame.read_uvarint() as usize; + + let blueprint = match &frame.chunk().constants[idx] { Value::Blueprint(lambda) => lambda.clone(), _ => panic!("compiler bug: non-blueprint in blueprint slot"), }; - let upvalue_count = blueprint.upvalue_count; - let thunk = if matches!(op, OpCode::OpThunkClosure(_)) { + let upvalue_count = frame.read_uvarint(); + + debug_assert!( + (upvalue_count >> 1) == blueprint.upvalue_count as u64, + "TODO: new upvalue count not correct", + ); + + let thunk = if op == Op::ThunkClosure { debug_assert!( - upvalue_count > 0, - "OpThunkClosure should not be called for plain lambdas" + (((upvalue_count >> 1) > 0) || (upvalue_count & 0b1 == 1)), + "OpThunkClosure should not be called for plain lambdas", ); Thunk::new_closure(blueprint) } else { - Thunk::new_suspended(blueprint, frame.current_light_span()) + Thunk::new_suspended(blueprint, frame.current_span()) }; let upvalues = thunk.upvalues_mut(); self.stack.push(Value::Thunk(thunk.clone())); @@ -477,17 +500,17 @@ where self.populate_upvalues(&mut frame, upvalue_count, upvalues)?; } - OpCode::OpForce => { + Op::Force => { if let Some(Value::Thunk(_)) = self.stack.last() { let thunk = match self.stack_pop() { Value::Thunk(t) => t, _ => unreachable!(), }; - let gen_span = frame.current_light_span(); + let gen_span = frame.current_span(); self.push_call_frame(span, frame); - self.enqueue_generator("force", gen_span.clone(), |co| { + self.enqueue_generator("force", gen_span, |co| { Thunk::force(thunk, co, gen_span) }); @@ -495,27 +518,37 @@ where } } - OpCode::OpGetUpvalue(upv_idx) => { - let value = frame.upvalue(upv_idx).clone(); + Op::GetUpvalue => { + let idx = UpvalueIdx(frame.read_uvarint() as usize); + let value = frame.upvalue(idx).clone(); self.stack.push(value); } // Discard the current frame. - OpCode::OpReturn => { + Op::Return => { // TODO(amjoseph): I think this should assert `==` rather // than `<=` but it fails with the stricter condition. debug_assert!(self.stack.len() - 1 <= frame.stack_offset); return Ok(true); } - OpCode::OpConstant(idx) => { - let c = frame.chunk()[idx].clone(); + Op::Constant => { + let idx = frame.read_uvarint() as usize; + + debug_assert!( + idx < frame.chunk().constants.len(), + "out of bounds constant at IP {} in {:p}", + frame.ip.0, + frame.lambda + ); + + let c = frame.chunk().constants[idx].clone(); self.stack.push(c); } - OpCode::OpCall => { + Op::Call => { let callable = self.stack_pop(); - self.call_value(frame.current_light_span(), Some((span, frame)), callable)?; + self.call_value(frame.current_span(), Some((span, frame)), callable)?; // exit this loop and let the outer loop enter the new call return Ok(true); @@ -523,7 +556,8 @@ where // Remove the given number of elements from the stack, // but retain the top value. - OpCode::OpCloseScope(Count(count)) => { + Op::CloseScope => { + let count = frame.read_uvarint() as usize; // Immediately move the top value into the right // position. let target_idx = self.stack.len() - 1 - count; @@ -535,15 +569,22 @@ where } } - OpCode::OpClosure(idx) => { - let blueprint = match &frame.chunk()[idx] { + Op::Closure => { + let idx = frame.read_uvarint() as usize; + let blueprint = match &frame.chunk().constants[idx] { Value::Blueprint(lambda) => lambda.clone(), _ => panic!("compiler bug: non-blueprint in blueprint slot"), }; - let upvalue_count = blueprint.upvalue_count; + let upvalue_count = frame.read_uvarint(); + debug_assert!( - upvalue_count > 0, + (upvalue_count >> 1) == blueprint.upvalue_count as u64, + "TODO: new upvalue count not correct in closure", + ); + + debug_assert!( + ((upvalue_count >> 1) > 0 || (upvalue_count & 0b1 == 1)), "OpClosure should not be called for plain lambdas" ); @@ -556,7 +597,7 @@ where )))); } - OpCode::OpAttrsSelect => lifted_pop! { + Op::AttrsSelect => lifted_pop! { self(key, attrs) => { let key = key.to_str().with_span(&frame, self)?; let attrs = attrs.to_attrs().with_span(&frame, self)?; @@ -576,21 +617,24 @@ where } }, - OpCode::OpJumpIfFalse(JumpOffset(offset)) => { + Op::JumpIfFalse => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); if !self.stack_peek(0).as_bool().with_span(&frame, self)? { frame.ip += offset; } } - OpCode::OpJumpIfCatchable(JumpOffset(offset)) => { + Op::JumpIfCatchable => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); if self.stack_peek(0).is_catchable() { frame.ip += offset; } } - OpCode::OpJumpIfNoFinaliseRequest(JumpOffset(offset)) => { + Op::JumpIfNoFinaliseRequest => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); match self.stack_peek(0) { Value::FinaliseRequest(finalise) => { @@ -602,11 +646,11 @@ where } } - OpCode::OpPop => { + Op::Pop => { self.stack.pop(); } - OpCode::OpAttrsTrySelect => { + Op::AttrsTrySelect => { let key = self.stack_pop().to_str().with_span(&frame, self)?; let value = match self.stack_pop() { Value::Attrs(attrs) => match attrs.select(&key) { @@ -620,12 +664,14 @@ where self.stack.push(value); } - OpCode::OpGetLocal(StackIdx(local_idx)) => { + Op::GetLocal => { + let local_idx = frame.read_uvarint() as usize; let idx = frame.stack_offset + local_idx; self.stack.push(self.stack[idx].clone()); } - OpCode::OpJumpIfNotFound(JumpOffset(offset)) => { + Op::JumpIfNotFound => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); if matches!(self.stack_peek(0), Value::AttrNotFound) { self.stack_pop(); @@ -633,16 +679,17 @@ where } } - OpCode::OpJump(JumpOffset(offset)) => { + Op::Jump => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); frame.ip += offset; } - OpCode::OpEqual => lifted_pop! { + Op::Equal => lifted_pop! { self(b, a) => { - let gen_span = frame.current_light_span(); + let gen_span = frame.current_span(); self.push_call_frame(span, frame); - self.enqueue_generator("nix_eq", gen_span.clone(), |co| { + self.enqueue_generator("nix_eq", gen_span, |co| { a.nix_eq_owned_genco(b, co, PointerEquality::ForbidAll, gen_span) }); return Ok(false); @@ -653,7 +700,7 @@ where // top is not of the expected type. This is necessary // to implement some specific behaviours of Nix // exactly. - OpCode::OpAssertBool => { + Op::AssertBool => { let val = self.stack_peek(0); // TODO(edef): propagate this into is_bool, since bottom values *are* values of any type if !val.is_catchable() && !val.is_bool() { @@ -667,7 +714,7 @@ where } } - OpCode::OpAssertAttrs => { + Op::AssertAttrs => { let val = self.stack_peek(0); // TODO(edef): propagate this into is_attrs, since bottom values *are* values of any type if !val.is_catchable() && !val.is_attrs() { @@ -681,9 +728,9 @@ where } } - OpCode::OpAttrs(Count(count)) => self.run_attrset(&frame, count)?, + Op::Attrs => self.run_attrset(frame.read_uvarint() as usize, &frame)?, - OpCode::OpAttrsUpdate => lifted_pop! { + Op::AttrsUpdate => lifted_pop! { self(rhs, lhs) => { let rhs = rhs.to_attrs().with_span(&frame, self)?; let lhs = lhs.to_attrs().with_span(&frame, self)?; @@ -691,28 +738,30 @@ where } }, - OpCode::OpInvert => lifted_pop! { + Op::Invert => lifted_pop! { self(v) => { let v = v.as_bool().with_span(&frame, self)?; self.stack.push(Value::Bool(!v)); } }, - OpCode::OpList(Count(count)) => { + Op::List => { + let count = frame.read_uvarint() as usize; let list = NixList::construct(count, self.stack.split_off(self.stack.len() - count)); self.stack.push(Value::List(list)); } - OpCode::OpJumpIfTrue(JumpOffset(offset)) => { + Op::JumpIfTrue => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); if self.stack_peek(0).as_bool().with_span(&frame, self)? { frame.ip += offset; } } - OpCode::OpHasAttr => lifted_pop! { + Op::HasAttr => lifted_pop! { self(key, attrs) => { let key = key.to_str().with_span(&frame, self)?; let result = match attrs { @@ -727,19 +776,20 @@ where } }, - OpCode::OpConcat => lifted_pop! { + Op::Concat => lifted_pop! { self(rhs, lhs) => { let rhs = rhs.to_list().with_span(&frame, self)?.into_inner(); - let lhs = lhs.to_list().with_span(&frame, self)?.into_inner(); - self.stack.push(Value::List(NixList::from(lhs + rhs))) + let mut lhs = lhs.to_list().with_span(&frame, self)?.into_inner(); + lhs.extend(rhs.into_iter()); + self.stack.push(Value::List(lhs.into())) } }, - OpCode::OpResolveWith => { + Op::ResolveWith => { let ident = self.stack_pop().to_str().with_span(&frame, self)?; // Re-enqueue this frame. - let op_span = frame.current_light_span(); + let op_span = frame.current_span(); self.push_call_frame(span, frame); // Construct a generator frame doing the lookup in constant @@ -762,27 +812,33 @@ where return Ok(false); } - OpCode::OpFinalise(StackIdx(idx)) => match &self.stack[frame.stack_offset + idx] { - Value::Closure(_) => panic!("attempted to finalise a closure"), - Value::Thunk(thunk) => thunk.finalise(&self.stack[frame.stack_offset..]), - _ => panic!("attempted to finalise a non-thunk"), - }, + Op::Finalise => { + let idx = frame.read_uvarint() as usize; + match &self.stack[frame.stack_offset + idx] { + Value::Closure(_) => panic!("attempted to finalise a closure"), + Value::Thunk(thunk) => thunk.finalise(&self.stack[frame.stack_offset..]), + _ => panic!("attempted to finalise a non-thunk"), + } + } + + Op::CoerceToString => { + let kind: CoercionKind = frame.chunk().code[frame.ip.0].into(); + frame.ip.0 += 1; - OpCode::OpCoerceToString(kind) => { let value = self.stack_pop(); - let gen_span = frame.current_light_span(); + let gen_span = frame.current_span(); self.push_call_frame(span, frame); - self.enqueue_generator("coerce_to_string", gen_span.clone(), |co| { + self.enqueue_generator("coerce_to_string", gen_span, |co| { value.coerce_to_string(co, kind, gen_span) }); return Ok(false); } - OpCode::OpInterpolate(Count(count)) => self.run_interpolate(&frame, count)?, + Op::Interpolate => self.run_interpolate(frame.read_uvarint(), &frame)?, - OpCode::OpValidateClosedFormals => { + Op::ValidateClosedFormals => { let formals = frame.lambda.formals.as_ref().expect( "OpValidateClosedFormals called within the frame of a lambda without formals", ); @@ -797,7 +853,7 @@ where if !formals.contains(arg) { return frame.error( self, - ErrorKind::UnexpectedArgument { + ErrorKind::UnexpectedArgumentFormals { arg: arg.clone(), formals_span: formals.span, }, @@ -806,9 +862,9 @@ where } } - OpCode::OpAdd => lifted_pop! { + Op::Add => lifted_pop! { self(b, a) => { - let gen_span = frame.current_light_span(); + let gen_span = frame.current_span(); self.push_call_frame(span, frame); // OpAdd can add not just numbers, but also string-like @@ -819,21 +875,21 @@ where } }, - OpCode::OpSub => lifted_pop! { + Op::Sub => lifted_pop! { self(b, a) => { let result = arithmetic_op!(&a, &b, -).with_span(&frame, self)?; self.stack.push(result); } }, - OpCode::OpMul => lifted_pop! { + Op::Mul => lifted_pop! { self(b, a) => { let result = arithmetic_op!(&a, &b, *).with_span(&frame, self)?; self.stack.push(result); } }, - OpCode::OpDiv => lifted_pop! { + Op::Div => lifted_pop! { self(b, a) => { match b { Value::Integer(0) => return frame.error(self, ErrorKind::DivisionByZero), @@ -848,7 +904,7 @@ where } }, - OpCode::OpNegate => match self.stack_pop() { + Op::Negate => match self.stack_pop() { Value::Integer(i) => self.stack.push(Value::Integer(-i)), Value::Float(f) => self.stack.push(Value::Float(-f)), Value::Catchable(cex) => self.stack.push(Value::Catchable(cex)), @@ -863,12 +919,12 @@ where } }, - OpCode::OpLess => cmp_op!(self, frame, span, <), - OpCode::OpLessOrEq => cmp_op!(self, frame, span, <=), - OpCode::OpMore => cmp_op!(self, frame, span, >), - OpCode::OpMoreOrEq => cmp_op!(self, frame, span, >=), + Op::Less => cmp_op!(self, frame, span, <), + Op::LessOrEq => cmp_op!(self, frame, span, <=), + Op::More => cmp_op!(self, frame, span, >), + Op::MoreOrEq => cmp_op!(self, frame, span, >=), - OpCode::OpFindFile => match self.stack_pop() { + Op::FindFile => match self.stack_pop() { Value::UnresolvedPath(path) => { let resolved = self .nix_search_path @@ -880,7 +936,7 @@ where _ => panic!("tvix compiler bug: OpFindFile called on non-UnresolvedPath"), }, - OpCode::OpResolveHomePath => match self.stack_pop() { + Op::ResolveHomePath => match self.stack_pop() { Value::UnresolvedPath(path) => { match dirs::home_dir() { None => { @@ -903,24 +959,23 @@ where } }, - OpCode::OpPushWith(StackIdx(idx)) => self.with_stack.push(frame.stack_offset + idx), + Op::PushWith => self + .with_stack + .push(frame.stack_offset + frame.read_uvarint() as usize), - OpCode::OpPopWith => { + Op::PopWith => { self.with_stack.pop(); } - OpCode::OpAssertFail => { + Op::AssertFail => { self.stack .push(Value::from(CatchableErrorKind::AssertionFailed)); } - // Data-carrying operands should never be executed, - // that is a critical error in the VM/compiler. - OpCode::DataStackIdx(_) - | OpCode::DataDeferredLocal(_) - | OpCode::DataUpvalueIdx(_) - | OpCode::DataCaptureWith => { - panic!("Tvix bug: attempted to execute data-carrying operand") + // Encountering an invalid opcode is a critical error in the + // VM/compiler. + Op::Invalid => { + panic!("Tvix bug: attempted to execute invalid opcode") } } } @@ -940,7 +995,7 @@ where &self.stack[self.stack.len() - 1 - offset] } - fn run_attrset(&mut self, frame: &CallFrame, count: usize) -> EvalResult<()> { + fn run_attrset(&mut self, count: usize, frame: &CallFrame) -> EvalResult<()> { let attrs = NixAttrs::construct(count, self.stack.split_off(self.stack.len() - count * 2)) .with_span(frame, self)? .map(Value::attrs) @@ -978,7 +1033,7 @@ where /// Interpolate string fragments by popping the specified number of /// fragments of the stack, evaluating them to strings, and pushing /// the concatenated result string back on the stack. - fn run_interpolate(&mut self, frame: &CallFrame, count: usize) -> EvalResult<()> { + fn run_interpolate(&mut self, count: u64, frame: &CallFrame) -> EvalResult<()> { let mut out = BString::default(); // Interpolation propagates the context and union them. let mut context: NixContext = NixContext::new(); @@ -994,8 +1049,8 @@ where } let mut nix_string = val.to_contextful_str().with_span(frame, self)?; out.push_str(nix_string.as_bstr()); - if let Some(nix_string_ctx) = nix_string.context_mut() { - context = context.join(nix_string_ctx); + if let Some(nix_string_ctx) = nix_string.take_context() { + context.extend(nix_string_ctx.into_iter()) } } @@ -1004,12 +1059,6 @@ where Ok(()) } - /// Returns a reasonable light span for the current situation that the VM is - /// in. - pub fn reasonable_light_span(&self) -> LightSpan { - self.reasonable_span.clone() - } - /// Apply an argument from the stack to a builtin, and attempt to call it. /// /// All calls are tail-calls in Tvix, as every function application is a @@ -1017,7 +1066,7 @@ where /// /// Due to this, once control flow exits this function, the generator will /// automatically be run by the VM. - fn call_builtin(&mut self, span: LightSpan, mut builtin: Builtin) -> EvalResult<()> { + fn call_builtin(&mut self, span: Span, mut builtin: Builtin) -> EvalResult<()> { let builtin_name = builtin.name(); self.observer.observe_enter_builtin(builtin_name); @@ -1041,8 +1090,8 @@ where fn call_value( &mut self, - span: LightSpan, - parent: Option<(LightSpan, CallFrame)>, + span: Span, + parent: Option<(Span, CallFrame)>, callable: Value, ) -> EvalResult<()> { match callable { @@ -1098,69 +1147,79 @@ where Ok(()) } - v => Err(ErrorKind::NotCallable(v.type_of())).with_span(&span, self), + v => Err(ErrorKind::NotCallable(v.type_of())).with_span(span, self), } } /// Populate the upvalue fields of a thunk or closure under construction. + /// + /// See the closely tied function `emit_upvalue_data` in the compiler + /// implementation for details on the argument processing. fn populate_upvalues( &mut self, frame: &mut CallFrame, - count: usize, + count: u64, mut upvalues: impl DerefMut<Target = Upvalues>, ) -> EvalResult<()> { - for _ in 0..count { - match frame.inc_ip() { - OpCode::DataStackIdx(StackIdx(stack_idx)) => { - let idx = frame.stack_offset + stack_idx; - - let val = match self.stack.get(idx) { - Some(val) => val.clone(), - None => { - return frame.error( - self, - ErrorKind::TvixBug { - msg: "upvalue to be captured was missing on stack", - metadata: Some(Rc::new(json!({ - "ip": format!("{:#x}", frame.ip.0 - 1), - "stack_idx(relative)": stack_idx, - "stack_idx(absolute)": idx, - }))), - }, - ); - } - }; + // Determine whether to capture the with stack, and then shift the + // actual count of upvalues back. + let capture_with = count & 0b1 == 1; + let count = count >> 1; + if capture_with { + // Start the captured with_stack off of the + // current call frame's captured with_stack, ... + let mut captured_with_stack = frame + .upvalues + .with_stack() + .cloned() + // ... or make an empty one if there isn't one already. + .unwrap_or_else(|| Vec::with_capacity(self.with_stack.len())); + + for idx in &self.with_stack { + captured_with_stack.push(self.stack[*idx].clone()); + } - upvalues.deref_mut().push(val); - } + upvalues.deref_mut().set_with_stack(captured_with_stack); + } - OpCode::DataUpvalueIdx(upv_idx) => { - upvalues.deref_mut().push(frame.upvalue(upv_idx).clone()); - } + for _ in 0..count { + let pos = Position(frame.read_uvarint()); - OpCode::DataDeferredLocal(idx) => { - upvalues.deref_mut().push(Value::DeferredUpvalue(idx)); - } + if let Some(stack_idx) = pos.runtime_stack_index() { + let idx = frame.stack_offset + stack_idx.0; - OpCode::DataCaptureWith => { - // Start the captured with_stack off of the - // current call frame's captured with_stack, ... - let mut captured_with_stack = frame - .upvalues - .with_stack() - .cloned() - // ... or make an empty one if there isn't one already. - .unwrap_or_else(|| Vec::with_capacity(self.with_stack.len())); - - for idx in &self.with_stack { - captured_with_stack.push(self.stack[*idx].clone()); + let val = match self.stack.get(idx) { + Some(val) => val.clone(), + None => { + return frame.error( + self, + ErrorKind::TvixBug { + msg: "upvalue to be captured was missing on stack", + metadata: Some(Rc::new(json!({ + "ip": format!("{:#x}", frame.ip.0 - 1), + "stack_idx(relative)": stack_idx.0, + "stack_idx(absolute)": idx, + }))), + }, + ); } + }; - upvalues.deref_mut().set_with_stack(captured_with_stack); - } + upvalues.deref_mut().push(val); + continue; + } - _ => panic!("compiler error: missing closure operand"), + if let Some(idx) = pos.runtime_deferred_local() { + upvalues.deref_mut().push(Value::DeferredUpvalue(idx)); + continue; } + + if let Some(idx) = pos.runtime_upvalue_index() { + upvalues.deref_mut().push(frame.upvalue(idx).clone()); + continue; + } + + panic!("Tvix bug: invalid capture position emitted") } Ok(()) @@ -1319,6 +1378,18 @@ async fn final_deep_force(co: GenCo) -> Result<Value, ErrorKind> { Ok(generators::request_deep_force(&co, value).await) } +/// Specification for how to handle top-level values returned by evaluation +#[derive(Debug, Clone, Copy, Default)] +pub enum EvalMode { + /// The default. Values are returned from evaluations as-is, without any extra forcing or + /// special handling. + #[default] + Lazy, + + /// Strictly and deeply evaluate top-level values returned by evaluation. + Strict, +} + pub fn run_lambda<IO>( nix_search_path: NixSearchPath, io_handle: IO, @@ -1326,7 +1397,7 @@ pub fn run_lambda<IO>( source: SourceCode, globals: Rc<GlobalsMap>, lambda: Rc<Lambda>, - strict: bool, + mode: EvalMode, ) -> EvalResult<RuntimeResult> where IO: AsRef<dyn EvalIO> + 'static, @@ -1345,17 +1416,18 @@ where observer, source, globals, - root_span.into(), + root_span, ); // When evaluating strictly, synthesise a frame that will instruct // the VM to deep-force the final value before returning it. - if strict { - vm.enqueue_generator("final_deep_force", root_span.into(), final_deep_force); + match mode { + EvalMode::Lazy => {} + EvalMode::Strict => vm.enqueue_generator("final_deep_force", root_span, final_deep_force), } vm.frames.push(Frame::CallFrame { - span: root_span.into(), + span: root_span, call_frame: CallFrame { lambda, upvalues: Rc::new(Upvalues::with_capacity(0)), diff --git a/tvix/eval/tests/nix_oracle.rs b/tvix/eval/tests/nix_oracle.rs index 6bab75cfd979..137dff6b00f6 100644 --- a/tvix/eval/tests/nix_oracle.rs +++ b/tvix/eval/tests/nix_oracle.rs @@ -30,7 +30,14 @@ fn nix_eval(expr: &str, strictness: Strictness) -> String { .arg(format!("({expr})")) .env( "NIX_REMOTE", - format!("local?root={}", store_dir.path().display()), + format!( + "local?root={}", + store_dir + .path() + .canonicalize() + .expect("valid path") + .display() + ), ) .output() .unwrap(); @@ -49,11 +56,18 @@ fn nix_eval(expr: &str, strictness: Strictness) -> String { /// `NIX_INSTANTIATE_BINARY_PATH` env var to resolve the `nix-instantiate` binary) and tvix, and /// assert that the result is identical #[track_caller] +#[cfg(feature = "impure")] fn compare_eval(expr: &str, strictness: Strictness) { + use tvix_eval::{EvalIO, EvalMode}; + let nix_result = nix_eval(expr, strictness); - let mut eval = tvix_eval::Evaluation::new_pure(); - eval.strict = matches!(strictness, Strictness::Strict); - eval.io_handle = Box::new(tvix_eval::StdIO); + let mut eval_builder = tvix_eval::Evaluation::builder_pure(); + if matches!(strictness, Strictness::Strict) { + eval_builder = eval_builder.mode(EvalMode::Strict); + } + let eval = eval_builder + .io_handle(Box::new(tvix_eval::StdIO) as Box<dyn EvalIO>) + .build(); let tvix_result = eval .evaluate(expr, None) @@ -69,6 +83,7 @@ fn compare_eval(expr: &str, strictness: Strictness) { macro_rules! compare_eval_tests { ($strictness:expr, {}) => {}; ($strictness:expr, {$(#[$meta:meta])* $test_name: ident($expr: expr); $($rest:tt)*}) => { + #[cfg(feature = "impure")] #[test] $(#[$meta])* fn $test_name() { diff --git a/tvix/glue/Cargo.toml b/tvix/glue/Cargo.toml index f929d720a0e7..5fac947125af 100644 --- a/tvix/glue/Cargo.toml +++ b/tvix/glue/Cargo.toml @@ -4,47 +4,43 @@ version = "0.1.0" edition = "2021" [dependencies] -async-recursion = "1.0.5" -bstr = "1.6.0" -bytes = "1.4.0" -data-encoding = "2.3.3" -futures = "0.3.30" -magic = "0.16.2" +async-compression = { workspace = true, features = ["tokio", "gzip", "bzip2", "xz"] } +bstr = { workspace = true } +bytes = { workspace = true } +data-encoding = { workspace = true } +futures = { workspace = true } +magic = { workspace = true } nix-compat = { path = "../nix-compat" } -pin-project = "1.1" -reqwest = { version = "0.11.22", features = ["rustls-tls-native-roots"], default-features = false } +pin-project = { workspace = true } +reqwest = { workspace = true, features = ["rustls-tls-native-roots"] } tvix-build = { path = "../build", default-features = false, features = []} tvix-eval = { path = "../eval" } tvix-castore = { path = "../castore" } tvix-store = { path = "../store", default-features = false, features = []} -tracing = "0.1.37" -tokio = "1.28.0" -tokio-tar = "0.3.1" -tokio-util = { version = "0.7.9", features = ["io", "io-util", "compat"] } -thiserror = "1.0.38" -serde = "1.0.195" -serde_json = "1.0" -sha2 = "0.10.8" -sha1 = "0.10.6" -md-5 = "0.10.6" -url = "2.4.0" -walkdir = "2.4.0" - -[dependencies.async-compression] -version = "0.4.6" -features = ["tokio", "gzip", "bzip2", "xz"] - -[dependencies.wu-manber] -git = "https://github.com/tvlfyi/wu-manber.git" +tvix-tracing = { path = "../tracing" } +tracing = { workspace = true } +tracing-indicatif = { workspace = true } +tokio = { workspace = true } +tokio-tar = { workspace = true } +tokio-util = { workspace = true, features = ["io", "io-util", "compat"] } +thiserror = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +sha2 = { workspace = true } +sha1 = { workspace = true } +md-5 = { workspace = true } +url = { workspace = true } +walkdir = { workspace = true } +clap = { workspace = true } [dev-dependencies] -criterion = { version = "0.5", features = ["html_reports"] } -hex-literal = "0.4.1" -lazy_static = "1.4.0" -nix = { version = "0.27.1", features = [ "fs" ] } -pretty_assertions = "1.4.0" -rstest = "0.19.0" -tempfile = "3.8.1" +criterion = { workspace = true, features = ["html_reports"] } +hex-literal = { workspace = true } +mimalloc = { workspace = true } +nix = { workspace = true, features = ["fs"] } +pretty_assertions = { workspace = true } +rstest = { workspace = true } +tempfile = { workspace = true } [features] default = ["nix_tests"] diff --git a/tvix/glue/benches/eval.rs b/tvix/glue/benches/eval.rs index dfb4fabe444a..ce14bdcc13ec 100644 --- a/tvix/glue/benches/eval.rs +++ b/tvix/glue/benches/eval.rs @@ -1,11 +1,9 @@ +use clap::Parser; use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use lazy_static::lazy_static; +use mimalloc::MiMalloc; +use std::sync::LazyLock; use std::{env, rc::Rc, sync::Arc, time::Duration}; use tvix_build::buildservice::DummyBuildService; -use tvix_castore::{ - blobservice::{BlobService, MemoryBlobService}, - directoryservice::{DirectoryService, MemoryDirectoryService}, -}; use tvix_eval::{builtins::impure_builtins, EvalIO}; use tvix_glue::{ builtins::{add_derivation_builtins, add_fetcher_builtins, add_import_builtins}, @@ -13,52 +11,55 @@ use tvix_glue::{ tvix_io::TvixIO, tvix_store_io::TvixStoreIO, }; -use tvix_store::pathinfoservice::{MemoryPathInfoService, PathInfoService}; +use tvix_store::utils::{construct_services, ServiceUrlsMemory}; -lazy_static! { - static ref BLOB_SERVICE: Arc<dyn BlobService> = Arc::new(MemoryBlobService::default()); - static ref DIRECTORY_SERVICE: Arc<dyn DirectoryService> = - Arc::new(MemoryDirectoryService::default()); - static ref PATH_INFO_SERVICE: Arc<dyn PathInfoService> = Arc::new(MemoryPathInfoService::new( - BLOB_SERVICE.clone(), - DIRECTORY_SERVICE.clone(), - )); - static ref TOKIO_RUNTIME: tokio::runtime::Runtime = tokio::runtime::Runtime::new().unwrap(); -} +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; + +static TOKIO_RUNTIME: LazyLock<tokio::runtime::Runtime> = + LazyLock::new(|| tokio::runtime::Runtime::new().unwrap()); fn interpret(code: &str) { // TODO: this is a bit annoying. // It'd be nice if we could set this up once and then run evaluate() with a // piece of code. b/262 + let (blob_service, directory_service, path_info_service, nar_calculation_service) = + TOKIO_RUNTIME + .block_on(async { + construct_services(ServiceUrlsMemory::parse_from(std::iter::empty::<&str>())).await + }) + .unwrap(); // We assemble a complete store in memory. let tvix_store_io = Rc::new(TvixStoreIO::new( - BLOB_SERVICE.clone(), - DIRECTORY_SERVICE.clone(), - PATH_INFO_SERVICE.clone(), + blob_service, + directory_service, + path_info_service, + nar_calculation_service.into(), Arc::<DummyBuildService>::default(), TOKIO_RUNTIME.handle().clone(), )); - let mut eval = tvix_eval::Evaluation::new( - Box::new(TvixIO::new(tvix_store_io.clone() as Rc<dyn EvalIO>)) as Box<dyn EvalIO>, - true, - ); + let mut eval_builder = tvix_eval::Evaluation::builder(Box::new(TvixIO::new( + tvix_store_io.clone() as Rc<dyn EvalIO>, + )) as Box<dyn EvalIO>) + .enable_import() + .add_builtins(impure_builtins()); - eval.builtins.extend(impure_builtins()); - add_derivation_builtins(&mut eval, Rc::clone(&tvix_store_io)); - add_fetcher_builtins(&mut eval, Rc::clone(&tvix_store_io)); - add_import_builtins(&mut eval, tvix_store_io); - configure_nix_path( - &mut eval, + eval_builder = add_derivation_builtins(eval_builder, Rc::clone(&tvix_store_io)); + eval_builder = add_fetcher_builtins(eval_builder, Rc::clone(&tvix_store_io)); + eval_builder = add_import_builtins(eval_builder, tvix_store_io); + eval_builder = configure_nix_path( + eval_builder, // The benchmark requires TVIX_BENCH_NIX_PATH to be set, so barf out // early, rather than benchmarking tvix returning an error. &Some(env::var("TVIX_BENCH_NIX_PATH").expect("TVIX_BENCH_NIX_PATH must be set")), ); + let eval = eval_builder.build(); let result = eval.evaluate(code, None); - assert!(result.errors.is_empty()); + assert!(result.errors.is_empty(), "{:#?}", result.errors); } fn eval_nixpkgs(c: &mut Criterion) { @@ -67,6 +68,12 @@ fn eval_nixpkgs(c: &mut Criterion) { interpret(black_box("(import <nixpkgs> {}).hello.outPath")); }) }); + + c.bench_function("firefox outpath", |b| { + b.iter(|| { + interpret(black_box("(import <nixpkgs> {}).firefox.outPath")); + }) + }); } criterion_group!( diff --git a/tvix/glue/build.rs b/tvix/glue/build.rs new file mode 100644 index 000000000000..544c34a6cbcb --- /dev/null +++ b/tvix/glue/build.rs @@ -0,0 +1,6 @@ +fn main() { + // Pick up new test case files + // https://github.com/la10736/rstest/issues/256 + println!("cargo:rerun-if-changed=src/tests/nix_tests"); + println!("cargo:rerun-if-changed=src/tests/tvix_tests") +} diff --git a/tvix/glue/default.nix b/tvix/glue/default.nix index 08f5c2228d76..0ead94a504c3 100644 --- a/tvix/glue/default.nix +++ b/tvix/glue/default.nix @@ -1,8 +1,17 @@ -{ depot, pkgs, ... }: +{ depot, pkgs, lib, ... }: (depot.tvix.crates.workspaceMembers.tvix-glue.build.override { runTests = true; testPreRun = '' - export SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt; + export SSL_CERT_FILE=/dev/null ''; +}).overrideAttrs (old: rec { + meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { + inherit (old) crateName; + features = [ "nix_tests" ]; + override.testPreRun = '' + export SSL_CERT_FILE=/dev/null + ''; + }); }) diff --git a/tvix/glue/src/builtins/derivation.rs b/tvix/glue/src/builtins/derivation.rs index 37d2460d9f93..11b70a934a7b 100644 --- a/tvix/glue/src/builtins/derivation.rs +++ b/tvix/glue/src/builtins/derivation.rs @@ -168,14 +168,21 @@ fn handle_fixed_output( #[builtins(state = "Rc<TvixStoreIO>")] pub(crate) mod derivation_builtins { use std::collections::BTreeMap; + use std::io::Cursor; use crate::builtins::utils::{select_string, strong_importing_coerce_to_string}; + use crate::fetchurl::fetchurl_derivation_to_fetch; use super::*; use bstr::ByteSlice; - use nix_compat::store_path::hash_placeholder; + use md5::Digest; + use nix_compat::nixhash::CAHash; + use nix_compat::store_path::{build_ca_path, hash_placeholder}; + use sha2::Sha256; + use tvix_castore::Node; use tvix_eval::generators::Gen; use tvix_eval::{NixContext, NixContextElement, NixString}; + use tvix_store::pathinfoservice::PathInfo; #[builtin("placeholder")] async fn builtin_placeholder(co: GenCo, input: Value) -> Result<Value, ErrorKind> { @@ -338,9 +345,9 @@ pub(crate) mod derivation_builtins { input_context.mimic(&val_str); if arg_name == "builder" { - drv.builder = val_str.to_str()?.to_owned(); + val_str.to_str()?.clone_into(&mut drv.builder); } else { - drv.system = val_str.to_str()?.to_owned(); + val_str.to_str()?.clone_into(&mut drv.system); } // Either populate drv.environment or structured_attrs. @@ -372,12 +379,12 @@ pub(crate) mod derivation_builtins { return Ok(val); } - let (val_json, mut context) = match val.into_contextful_json(&co).await? { + let (val_json, context) = match val.into_contextful_json(&co).await? { Ok(v) => v, Err(cek) => return Ok(Value::from(cek)), }; - input_context = input_context.join(&mut context); + input_context.extend(context.into_iter()); // No need to check for dups, we only iterate over every attribute name once structured_attrs.insert(arg_name.to_owned(), val_json); @@ -457,18 +464,24 @@ pub(crate) mod derivation_builtins { drv.validate(false) .map_err(DerivationError::InvalidDerivation)?; - // Calculate the derivation_or_fod_hash for the current derivation. - // This one is still intermediate (so not added to known_paths) - let derivation_or_fod_hash_tmp = drv.derivation_or_fod_hash(|drv_path| { - known_paths - .get_hash_derivation_modulo(&drv_path.to_owned()) - .unwrap_or_else(|| panic!("{} not found", drv_path)) - .to_owned() - }); + // Calculate the hash_derivation_modulo for the current derivation.. + debug_assert!( + drv.outputs.values().all(|output| { output.path.is_none() }), + "outputs should still be unset" + ); // Mutate the Derivation struct and set output paths - drv.calculate_output_paths(name, &derivation_or_fod_hash_tmp) - .map_err(DerivationError::InvalidDerivation)?; + drv.calculate_output_paths( + name, + // This one is still intermediate (so not added to known_paths), + // as the outputs are still unset. + &drv.hash_derivation_modulo(|drv_path| { + *known_paths + .get_hash_derivation_modulo(&drv_path.to_owned()) + .unwrap_or_else(|| panic!("{} not found", drv_path)) + }), + ) + .map_err(DerivationError::InvalidDerivation)?; let drv_path = drv .calculate_derivation_path(name) @@ -500,6 +513,17 @@ pub(crate) mod derivation_builtins { ))), ))); + // If the derivation is a fake derivation (builtins:fetchurl), + // synthesize a [Fetch] and add it there, too. + if drv.builder == "builtin:fetchurl" { + let (name, fetch) = + fetchurl_derivation_to_fetch(&drv).map_err(|e| ErrorKind::TvixError(Rc::new(e)))?; + + known_paths + .add_fetch(fetch, &name) + .map_err(|e| ErrorKind::TvixError(Rc::new(e)))?; + } + // Register the Derivation in known_paths. known_paths.add_derivation(drv_path, drv); @@ -507,7 +531,12 @@ pub(crate) mod derivation_builtins { } #[builtin("toFile")] - async fn builtin_to_file(co: GenCo, name: Value, content: Value) -> Result<Value, ErrorKind> { + async fn builtin_to_file( + state: Rc<TvixStoreIO>, + co: GenCo, + name: Value, + content: Value, + ) -> Result<Value, ErrorKind> { if name.is_catchable() { return Ok(name); } @@ -523,24 +552,72 @@ pub(crate) mod derivation_builtins { .to_contextful_str() .context("evaluating the `content` parameter of builtins.toFile")?; - if content.iter_derivation().count() > 0 || content.iter_single_outputs().count() > 0 { + if content.iter_ctx_derivation().count() > 0 + || content.iter_ctx_single_outputs().count() > 0 + { return Err(ErrorKind::UnexpectedContext); } - let path = - nix_compat::store_path::build_text_path(name.to_str()?, &content, content.iter_plain()) - .map_err(|_e| { - nix_compat::derivation::DerivationError::InvalidOutputName( - name.to_str_lossy().into_owned(), + let store_path = state.tokio_handle.block_on(async { + // upload contents to the blobservice and create a root node + let mut blob_writer = state.blob_service.open_write().await; + + let mut r = Cursor::new(&content); + + let blob_size = tokio::io::copy(&mut r, &mut blob_writer).await?; + let blob_digest = blob_writer.close().await?; + let ca_hash = CAHash::Text(Sha256::digest(&content).into()); + + let root_node = Node::File { + digest: blob_digest, + size: blob_size, + executable: false, + }; + + // calculate the nar hash + let (nar_size, nar_sha256) = state + .nar_calculation_service + .calculate_nar(&root_node) + .await + .map_err(|e| ErrorKind::TvixError(Rc::new(e)))?; + + // persist via pathinfo service. + state + .path_info_service + .put(PathInfo { + store_path: build_ca_path( + name.to_str()?, + &ca_hash, + content.iter_ctx_plain(), + false, ) + .map_err(|_e| { + nix_compat::derivation::DerivationError::InvalidOutputName( + name.to_str_lossy().into_owned(), + ) + }) + .map_err(DerivationError::InvalidDerivation)?, + node: root_node, + // assemble references from plain context. + references: content + .iter_ctx_plain() + .map(|elem| StorePath::from_absolute_path(elem.as_bytes())) + .collect::<Result<_, _>>() + .map_err(|e| ErrorKind::TvixError(Rc::new(e)))?, + nar_size, + nar_sha256, + signatures: vec![], + deriver: None, + ca: Some(ca_hash), }) - .map_err(DerivationError::InvalidDerivation)? - .to_absolute_path(); - - let context: NixContext = NixContextElement::Plain(path.clone()).into(); + .await + .map_err(|e| ErrorKind::TvixError(Rc::new(e))) + .map(|path_info| path_info.store_path) + })?; - // TODO: actually persist the file in the store at that path ... + let abs_path = store_path.to_absolute_path(); + let context: NixContext = NixContextElement::Plain(abs_path.clone()).into(); - Ok(Value::from(NixString::new_context_from(context, path))) + Ok(Value::from(NixString::new_context_from(context, abs_path))) } } diff --git a/tvix/glue/src/builtins/errors.rs b/tvix/glue/src/builtins/errors.rs index c05d366f135b..ec85942bb1ee 100644 --- a/tvix/glue/src/builtins/errors.rs +++ b/tvix/glue/src/builtins/errors.rs @@ -4,8 +4,9 @@ use nix_compat::{ store_path::BuildStorePathError, }; use reqwest::Url; -use std::rc::Rc; +use std::{path::PathBuf, rc::Rc}; use thiserror::Error; +use tvix_castore::import; /// Errors related to derivation construction #[derive(Debug, Error)] @@ -52,10 +53,7 @@ pub enum FetcherError { Io(#[from] std::io::Error), #[error(transparent)] - Import(#[from] tvix_castore::import::Error), - - #[error(transparent)] - ImportArchive(#[from] tvix_castore::import::archive::Error), + Import(#[from] tvix_castore::import::IngestionError<import::archive::Error>), #[error("Error calculating store path for fetcher output: {0}")] StorePath(#[from] BuildStorePathError), @@ -66,9 +64,13 @@ pub enum FetcherError { #[derive(Debug, Error)] pub enum ImportError { #[error("non-file '{0}' cannot be imported in 'flat' mode")] - FlatImportOfNonFile(String), + FlatImportOfNonFile(PathBuf), + #[error("hash mismatch at ingestion of '{0}', expected: '{1}', got: '{2}'")] - HashMismatch(String, NixHash, NixHash), + HashMismatch(PathBuf, NixHash, NixHash), + + #[error("path '{}' is not absolute or invalid", .0.display())] + PathNotAbsoluteOrInvalid(PathBuf), } impl From<ImportError> for tvix_eval::ErrorKind { diff --git a/tvix/glue/src/builtins/fetchers.rs b/tvix/glue/src/builtins/fetchers.rs index c7602c03e81f..1ad43b383353 100644 --- a/tvix/glue/src/builtins/fetchers.rs +++ b/tvix/glue/src/builtins/fetchers.rs @@ -6,16 +6,17 @@ use crate::{ tvix_store_io::TvixStoreIO, }; use nix_compat::nixhash; -use nix_compat::nixhash::NixHash; use std::rc::Rc; -use tracing::info; use tvix_eval::builtin_macros::builtins; use tvix_eval::generators::Gen; use tvix_eval::generators::GenCo; use tvix_eval::{CatchableErrorKind, ErrorKind, Value}; +use url::Url; +// Used as a return type for extract_fetch_args, which is sharing some +// parsing code between the fetchurl and fetchTarball builtins. struct NixFetchArgs { - url_str: String, + url: Url, name: Option<String>, sha256: Option<[u8; 32]>, } @@ -30,8 +31,12 @@ async fn extract_fetch_args( // Get the raw bytes, not the ToString repr. let url_str = String::from_utf8(url_str.as_bytes().to_vec()).map_err(|_| ErrorKind::Utf8)?; + + // Parse the URL. + let url = Url::parse(&url_str).map_err(|e| ErrorKind::TvixError(Rc::new(e)))?; + return Ok(Ok(NixFetchArgs { - url_str, + url, name: None, sha256: None, })); @@ -55,7 +60,14 @@ async fn extract_fetch_args( Err(cek) => return Ok(Err(cek)), }; - // TODO: disallow other attrset keys, to match Nix' behaviour. + // Disallow other attrset keys, to match Nix' behaviour. + // We complain about the first unexpected key we find in the list. + const VALID_KEYS: [&[u8]; 3] = [b"url", b"name", b"sha256"]; + if let Some(first_invalid_key) = attrs.keys().find(|k| !&VALID_KEYS.contains(&k.as_bytes())) { + return Err(ErrorKind::UnexpectedArgumentBuiltin( + first_invalid_key.clone(), + )); + } // parse the sha256 string into a digest. let sha256 = match sha256_str { @@ -69,18 +81,16 @@ async fn extract_fetch_args( None => None, }; - Ok(Ok(NixFetchArgs { - url_str, - name, - sha256, - })) + // Parse the URL. + let url = Url::parse(&url_str).map_err(|e| ErrorKind::TvixError(Rc::new(e)))?; + + Ok(Ok(NixFetchArgs { url, name, sha256 })) } #[allow(unused_variables)] // for the `state` arg, for now #[builtins(state = "Rc<TvixStoreIO>")] pub(crate) mod fetcher_builtins { - use crate::builtins::FetcherError; - use url::Url; + use nix_compat::nixhash::NixHash; use super::*; @@ -112,8 +122,6 @@ pub(crate) mod fetcher_builtins { } None => { // If we don't have enough info, do the fetch now. - info!(?fetch, "triggering required fetch"); - let (store_path, _root_node) = state .tokio_handle .block_on(async { state.fetcher.ingest_and_persist(&name, fetch).await }) @@ -138,16 +146,15 @@ pub(crate) mod fetcher_builtins { // Derive the name from the URL basename if not set explicitly. let name = args .name - .unwrap_or_else(|| url_basename(&args.url_str).to_owned()); - - // Parse the URL. - let url = Url::parse(&args.url_str) - .map_err(|e| ErrorKind::TvixError(Rc::new(FetcherError::InvalidUrl(e))))?; + .unwrap_or_else(|| url_basename(&args.url).to_owned()); fetch_lazy( state, name, - Fetch::URL(url, args.sha256.map(NixHash::Sha256)), + Fetch::URL { + url: args.url, + exp_hash: args.sha256.map(NixHash::Sha256), + }, ) } @@ -168,11 +175,14 @@ pub(crate) mod fetcher_builtins { .name .unwrap_or_else(|| DEFAULT_NAME_FETCH_TARBALL.to_owned()); - // Parse the URL. - let url = Url::parse(&args.url_str) - .map_err(|e| ErrorKind::TvixError(Rc::new(FetcherError::InvalidUrl(e))))?; - - fetch_lazy(state, name, Fetch::Tarball(url, args.sha256)) + fetch_lazy( + state, + name, + Fetch::Tarball { + url: args.url, + exp_nar_sha256: args.sha256, + }, + ) } #[builtin("fetchGit")] diff --git a/tvix/glue/src/builtins/import.rs b/tvix/glue/src/builtins/import.rs index 6814781df377..5f495dcc623b 100644 --- a/tvix/glue/src/builtins/import.rs +++ b/tvix/glue/src/builtins/import.rs @@ -1,8 +1,9 @@ //! Implements builtins used to import paths in the store. -use crate::builtins::errors::ImportError; +use crate::tvix_store_io::TvixStoreIO; use std::path::Path; use tvix_castore::import::ingest_entries; +use tvix_castore::Node; use tvix_eval::{ builtin_macros::builtins, generators::{self, GenCo}, @@ -16,7 +17,7 @@ async fn filtered_ingest( co: GenCo, path: &Path, filter: Option<&Value>, -) -> Result<tvix_castore::proto::node::Node, ErrorKind> { +) -> Result<Node, ErrorKind> { let mut entries: Vec<walkdir::DirEntry> = vec![]; let mut it = walkdir::WalkDir::new(path) .follow_links(false) @@ -88,34 +89,235 @@ async fn filtered_ingest( let dir_entries = entries.into_iter().rev().map(Ok); state.tokio_handle.block_on(async { - let entries = tvix_castore::import::fs::dir_entries_to_ingestion_stream( + let entries = tvix_castore::import::fs::dir_entries_to_ingestion_stream::<'_, _, _, &[u8]>( &state.blob_service, dir_entries, path, + None, // TODO re-scan ); ingest_entries(&state.directory_service, entries) .await - .map_err(|err| ErrorKind::IO { + .map_err(|e| ErrorKind::IO { path: Some(path.to_path_buf()), - error: Rc::new(err.into()), + error: Rc::new(std::io::Error::new(std::io::ErrorKind::Other, e)), }) }) } #[builtins(state = "Rc<TvixStoreIO>")] mod import_builtins { - use std::rc::Rc; - use super::*; + use crate::builtins::ImportError; + use crate::tvix_store_io::TvixStoreIO; + use bstr::ByteSlice; use nix_compat::nixhash::{CAHash, NixHash}; + use nix_compat::store_path::{build_ca_path, StorePathRef}; + use sha2::Digest; + use std::rc::Rc; + use tokio::io::AsyncWriteExt; + use tvix_eval::builtins::coerce_value_to_path; use tvix_eval::generators::Gen; use tvix_eval::{generators::GenCo, ErrorKind, Value}; - use tvix_eval::{NixContextElement, NixString}; + use tvix_eval::{FileType, NixContextElement, NixString}; + use tvix_store::path_info::PathInfo; + + // This is a helper used by both builtins.path and builtins.filterSource. + async fn import_helper( + state: Rc<TvixStoreIO>, + co: GenCo, + path: std::path::PathBuf, + name: Option<&Value>, + filter: Option<&Value>, + recursive_ingestion: bool, + expected_sha256: Option<[u8; 32]>, + ) -> Result<Value, ErrorKind> { + let name: String = match name { + Some(name) => generators::request_force(&co, name.clone()) + .await + .to_str()? + .as_bstr() + .to_string(), + None => tvix_store::import::path_to_name(&path) + .expect("Failed to derive the default name out of the path") + .to_string(), + }; + // As a first step, we ingest the contents, and get back a root node, + // and optionally the sha256 a flat file. + let (root_node, ca) = match std::fs::metadata(&path)?.file_type().into() { + // Check if the path points to a regular file. + // If it does, the filter function is never executed, and we copy to the blobservice directly. + // If recursive is false, we need to calculate the sha256 digest of the raw contents, + // as that affects the output path calculation. + FileType::Regular => { + let mut file = state.open(&path)?; - use tvix_castore::B3Digest; + let mut flat_sha256 = (!recursive_ingestion).then(sha2::Sha256::new); + let mut blob_size = 0; - use crate::tvix_store_io::TvixStoreIO; + let mut blob_writer = state + .tokio_handle + .block_on(async { state.blob_service.open_write().await }); + + // read piece by piece and write to blob_writer. + // This is a bit manual due to EvalIO being sync, while everything else async. + { + let mut buf = [0u8; 4096]; + + loop { + // read bytes into buffer, break out if EOF + let len = file.read(&mut buf)?; + if len == 0 { + break; + } + blob_size += len as u64; + + let data = &buf[0..len]; + + // add to blobwriter + state + .tokio_handle + .block_on(async { blob_writer.write_all(data).await })?; + + // update blob_sha256 if needed. + if let Some(h) = flat_sha256.as_mut() { + h.update(data) + } + } + } + + // close the blob writer, construct the root node and the blob_sha256 (later used for output path calculation) + ( + Node::File { + digest: state + .tokio_handle + .block_on(async { blob_writer.close().await })?, + size: blob_size, + executable: false, + }, + { + // If non-recursive ingestion is requested… + if let Some(flat_sha256) = flat_sha256 { + let actual_sha256 = flat_sha256.finalize().into(); + + // compare the recorded flat hash with an upfront one if provided. + if let Some(expected_sha256) = expected_sha256 { + if actual_sha256 != expected_sha256 { + return Err(ImportError::HashMismatch( + path, + NixHash::Sha256(expected_sha256), + NixHash::Sha256(actual_sha256), + ) + .into()); + } + } + + Some(CAHash::Flat(NixHash::Sha256(actual_sha256))) + } else { + None + } + }, + ) + } + + FileType::Directory if !recursive_ingestion => { + return Err(ImportError::FlatImportOfNonFile(path))? + } + + // do the filtered ingest + FileType::Directory => ( + filtered_ingest(state.clone(), co, path.as_ref(), filter).await?, + None, + ), + FileType::Symlink => { + // FUTUREWORK: Nix follows a symlink if it's at the root, + // except if it's not resolve-able (NixOS/nix#7761).i + return Err(tvix_eval::ErrorKind::IO { + path: Some(path), + error: Rc::new(std::io::Error::new( + std::io::ErrorKind::Unsupported, + "builtins.path pointing to a symlink is ill-defined.", + )), + }); + } + FileType::Unknown => { + return Err(tvix_eval::ErrorKind::IO { + path: Some(path), + error: Rc::new(std::io::Error::new( + std::io::ErrorKind::Unsupported, + "unsupported file type", + )), + }) + } + }; + + // Calculate the NAR sha256. + let (nar_size, nar_sha256) = state + .tokio_handle + .block_on(async { + state + .nar_calculation_service + .as_ref() + .calculate_nar(&root_node) + .await + }) + .map_err(|e| tvix_eval::ErrorKind::TvixError(Rc::new(e)))?; + + // Calculate the CA hash for the recursive cases, this is only already + // `Some(_)` for flat ingestion. + let ca = match ca { + None => { + // If an upfront-expected NAR hash was specified, compare. + if let Some(expected_nar_sha256) = expected_sha256 { + if expected_nar_sha256 != nar_sha256 { + return Err(ImportError::HashMismatch( + path, + NixHash::Sha256(expected_nar_sha256), + NixHash::Sha256(nar_sha256), + ) + .into()); + } + } + CAHash::Nar(NixHash::Sha256(nar_sha256)) + } + Some(ca) => ca, + }; + + let store_path = build_ca_path(&name, &ca, Vec::<&str>::new(), false) + .map_err(|e| tvix_eval::ErrorKind::TvixError(Rc::new(e)))?; + + let path_info = state + .tokio_handle + .block_on(async { + state + .path_info_service + .as_ref() + .put(PathInfo { + store_path, + node: root_node, + // There's no reference scanning on path contents ingested like this. + references: vec![], + nar_size, + nar_sha256, + signatures: vec![], + deriver: None, + ca: Some(ca), + }) + .await + }) + .map_err(|e| tvix_eval::ErrorKind::IO { + path: Some(path), + error: Rc::new(e.into()), + })?; + + // We need to attach context to the final output path. + let outpath = path_info.store_path.to_absolute_path(); + + Ok( + NixString::new_context_from(NixContextElement::Plain(outpath.clone()).into(), outpath) + .into(), + ) + } #[builtin("path")] async fn builtin_path( @@ -124,120 +326,58 @@ mod import_builtins { args: Value, ) -> Result<Value, ErrorKind> { let args = args.to_attrs()?; - let path = args.select_required("path")?; - let path = generators::request_force(&co, path.clone()) - .await - .to_path()?; - let name: String = if let Some(name) = args.select("name") { - generators::request_force(&co, name.clone()) - .await - .to_str()? - .as_bstr() - .to_string() - } else { - tvix_store::import::path_to_name(&path) - .expect("Failed to derive the default name out of the path") - .to_string() + + let path = match coerce_value_to_path( + &co, + generators::request_force(&co, args.select_required("path")?.clone()).await, + ) + .await? + { + Ok(path) => path, + Err(cek) => return Ok(cek.into()), }; + let filter = args.select("filter"); + + // Construct a sha256 hasher, which is needed for flat ingestion. let recursive_ingestion = args .select("recursive") .map(|r| r.as_bool()) .transpose()? .unwrap_or(true); // Yes, yes, Nix, by default, puts `recursive = true;`. + let expected_sha256 = args .select("sha256") .map(|h| { h.to_str().and_then(|expected| { - let expected = expected.into_bstring().to_string(); - // TODO: ensure that we fail if this is not a valid str. - nix_compat::nixhash::from_str(&expected, None).map_err(|_err| { - // TODO: a better error would be nice, we use - // DerivationError::InvalidOutputHash usually for derivation construction. - // This is not a derivation construction, should we move it outside and - // generalize? - ErrorKind::TypeError { - expected: "sha256", - actual: "not a sha256", + match nix_compat::nixhash::from_str(expected.to_str()?, Some("sha256")) { + Ok(NixHash::Sha256(digest)) => Ok(digest), + Ok(_) => unreachable!(), + Err(_e) => { + // TODO: a better error would be nice, we use + // DerivationError::InvalidOutputHash usually for derivation construction. + // This is not a derivation construction, should we move it outside and + // generalize? + Err(ErrorKind::TypeError { + expected: "sha256", + actual: "not a sha256", + }) } - }) + } }) }) .transpose()?; - // FUTUREWORK(performance): this opens the file instead of using a stat-like - // system call to the file. - if !recursive_ingestion && state.open(path.as_ref()).is_err() { - Err(ImportError::FlatImportOfNonFile( - path.to_string_lossy().to_string(), - ))?; - } - - let root_node = filtered_ingest(state.clone(), co, path.as_ref(), filter).await?; - let ca: CAHash = if recursive_ingestion { - CAHash::Nar(NixHash::Sha256(state.tokio_handle.block_on(async { - Ok::<_, tvix_eval::ErrorKind>( - state - .path_info_service - .as_ref() - .calculate_nar(&root_node) - .await - .map_err(|e| ErrorKind::TvixError(Rc::new(e)))? - .1, - ) - })?)) - } else { - let digest: B3Digest = match root_node { - tvix_castore::proto::node::Node::File(ref fnode) => { - // It's already validated. - fnode.digest.clone().try_into().unwrap() - } - // We cannot hash anything else than file in flat import mode. - _ => { - return Err(ImportError::FlatImportOfNonFile( - path.to_string_lossy().to_string(), - ) - .into()) - } - }; - - // FUTUREWORK: avoid hashing again. - CAHash::Flat(NixHash::Sha256( - state - .tokio_handle - .block_on(async { state.blob_to_sha256_hash(digest).await })?, - )) - }; - - let obtained_hash = ca.hash().clone().into_owned(); - let (path_info, _hash, output_path) = state.tokio_handle.block_on(async { - state - .node_to_path_info(name.as_ref(), path.as_ref(), ca, root_node) - .await - })?; - - if let Some(expected_sha256) = expected_sha256 { - if obtained_hash != expected_sha256 { - Err(ImportError::HashMismatch( - path.to_string_lossy().to_string(), - expected_sha256, - obtained_hash, - ))?; - } - } - - let _: tvix_store::proto::PathInfo = state.tokio_handle.block_on(async { - // This is necessary to cause the coercion of the error type. - Ok::<_, std::io::Error>(state.path_info_service.as_ref().put(path_info).await?) - })?; - - // We need to attach context to the final output path. - let outpath = output_path.to_absolute_path(); - - Ok( - NixString::new_context_from(NixContextElement::Plain(outpath.clone()).into(), outpath) - .into(), + import_helper( + state, + co, + path, + args.select("name"), + filter, + recursive_ingestion, + expected_sha256, ) + .await } #[builtin("filterSource")] @@ -247,41 +387,48 @@ mod import_builtins { #[lazy] filter: Value, path: Value, ) -> Result<Value, ErrorKind> { - let p = path.to_path()?; - let root_node = filtered_ingest(Rc::clone(&state), co, &p, Some(&filter)).await?; - let name = tvix_store::import::path_to_name(&p)?; + let path = + match coerce_value_to_path(&co, generators::request_force(&co, path).await).await? { + Ok(path) => path, + Err(cek) => return Ok(cek.into()), + }; - let outpath = state - .tokio_handle - .block_on(async { - let (_, nar_sha256) = state - .path_info_service - .as_ref() - .calculate_nar(&root_node) - .await?; + import_helper(state, co, path, None, Some(&filter), true, None).await + } - state - .register_node_in_path_info_service( - name, - &p, - CAHash::Nar(NixHash::Sha256(nar_sha256)), - root_node, - ) - .await - }) - .map_err(|err| ErrorKind::IO { - path: Some(p.to_path_buf()), - error: err.into(), - })? - .to_absolute_path(); + #[builtin("storePath")] + async fn builtin_store_path( + state: Rc<TvixStoreIO>, + co: GenCo, + path: Value, + ) -> Result<Value, ErrorKind> { + let p = match &path { + Value::String(s) => Path::new(s.as_bytes().to_os_str()?), + Value::Path(p) => p.as_path(), + _ => { + return Err(ErrorKind::TypeError { + expected: "string or path", + actual: path.type_of(), + }) + } + }; - Ok( - NixString::new_context_from(NixContextElement::Plain(outpath.clone()).into(), outpath) - .into(), - ) + // For this builtin, the path needs to start with an absolute store path. + let (store_path, _sub_path) = StorePathRef::from_absolute_path_full(p) + .map_err(|_e| ImportError::PathNotAbsoluteOrInvalid(p.to_path_buf()))?; + + if state.path_exists(p)? { + Ok(Value::String(NixString::new_context_from( + [NixContextElement::Plain(store_path.to_absolute_path())].into(), + p.as_os_str().as_encoded_bytes(), + ))) + } else { + Err(ErrorKind::IO { + path: Some(p.to_path_buf()), + error: Rc::new(std::io::ErrorKind::NotFound.into()), + }) + } } } pub use import_builtins::builtins as import_builtins; - -use crate::tvix_store_io::TvixStoreIO; diff --git a/tvix/glue/src/builtins/mod.rs b/tvix/glue/src/builtins/mod.rs index 4081489e0ec3..6149423acff0 100644 --- a/tvix/glue/src/builtins/mod.rs +++ b/tvix/glue/src/builtins/mod.rs @@ -18,13 +18,14 @@ pub use errors::{DerivationError, FetcherError, ImportError}; /// /// As they need to interact with `known_paths`, we also need to pass in /// `known_paths`. -pub fn add_derivation_builtins<IO>(eval: &mut tvix_eval::Evaluation<IO>, io: Rc<TvixStoreIO>) { - eval.builtins - .extend(derivation::derivation_builtins::builtins(Rc::clone(&io))); - - // Add the actual `builtins.derivation` from compiled Nix code - eval.src_builtins - .push(("derivation", include_str!("derivation.nix"))); +pub fn add_derivation_builtins<'co, 'ro, 'env, IO>( + eval_builder: tvix_eval::EvaluationBuilder<'co, 'ro, 'env, IO>, + io: Rc<TvixStoreIO>, +) -> tvix_eval::EvaluationBuilder<'co, 'ro, 'env, IO> { + eval_builder + .add_builtins(derivation::derivation_builtins::builtins(Rc::clone(&io))) + // Add the actual `builtins.derivation` from compiled Nix code + .add_src_builtin("derivation", include_str!("derivation.nix")) } /// Adds fetcher builtins to the passed [tvix_eval::Evaluation]: @@ -32,9 +33,11 @@ pub fn add_derivation_builtins<IO>(eval: &mut tvix_eval::Evaluation<IO>, io: Rc< /// * `fetchurl` /// * `fetchTarball` /// * `fetchGit` -pub fn add_fetcher_builtins<IO>(eval: &mut tvix_eval::Evaluation<IO>, io: Rc<TvixStoreIO>) { - eval.builtins - .extend(fetchers::fetcher_builtins::builtins(Rc::clone(&io))); +pub fn add_fetcher_builtins<'co, 'ro, 'env, IO>( + eval_builder: tvix_eval::EvaluationBuilder<'co, 'ro, 'env, IO>, + io: Rc<TvixStoreIO>, +) -> tvix_eval::EvaluationBuilder<'co, 'ro, 'env, IO> { + eval_builder.add_builtins(fetchers::fetcher_builtins::builtins(Rc::clone(&io))) } /// Adds import-related builtins to the passed [tvix_eval::Evaluation]. @@ -42,10 +45,12 @@ pub fn add_fetcher_builtins<IO>(eval: &mut tvix_eval::Evaluation<IO>, io: Rc<Tvi /// These are `filterSource` and `path` /// /// As they need to interact with the store implementation, we pass [`TvixStoreIO`]. -pub fn add_import_builtins<IO>(eval: &mut tvix_eval::Evaluation<IO>, io: Rc<TvixStoreIO>) { - eval.builtins.extend(import::import_builtins(io)); - +pub fn add_import_builtins<'co, 'ro, 'env, IO>( + eval_builder: tvix_eval::EvaluationBuilder<'co, 'ro, 'env, IO>, + io: Rc<TvixStoreIO>, +) -> tvix_eval::EvaluationBuilder<'co, 'ro, 'env, IO> { // TODO(raitobezarius): evaluate expressing filterSource as Nix code using path (b/372) + eval_builder.add_builtins(import::import_builtins(io)) } #[cfg(test)] @@ -55,12 +60,13 @@ mod tests { use crate::tvix_store_io::TvixStoreIO; use super::{add_derivation_builtins, add_fetcher_builtins, add_import_builtins}; + use clap::Parser; use nix_compat::store_path::hash_placeholder; use rstest::rstest; use tempfile::TempDir; use tvix_build::buildservice::DummyBuildService; use tvix_eval::{EvalIO, EvaluationResult}; - use tvix_store::utils::construct_services; + use tvix_store::utils::{construct_services, ServiceUrlsMemory}; /// evaluates a given nix expression and returns the result. /// Takes care of setting up the evaluator so it knows about the @@ -68,23 +74,26 @@ mod tests { fn eval(str: &str) -> EvaluationResult { // We assemble a complete store in memory. let runtime = tokio::runtime::Runtime::new().expect("Failed to build a Tokio runtime"); - let (blob_service, directory_service, path_info_service) = runtime - .block_on(async { construct_services("memory://", "memory://", "memory://").await }) + let (blob_service, directory_service, path_info_service, nar_calculation_service) = runtime + .block_on(async { + construct_services(ServiceUrlsMemory::parse_from(std::iter::empty::<&str>())).await + }) .expect("Failed to construct store services in memory"); let io = Rc::new(TvixStoreIO::new( blob_service, directory_service, - path_info_service.into(), + path_info_service, + nar_calculation_service.into(), Arc::<DummyBuildService>::default(), runtime.handle().clone(), )); - let mut eval = tvix_eval::Evaluation::new(io.clone() as Rc<dyn EvalIO>, false); - - add_derivation_builtins(&mut eval, Rc::clone(&io)); - add_fetcher_builtins(&mut eval, Rc::clone(&io)); - add_import_builtins(&mut eval, io); + let mut eval_builder = tvix_eval::Evaluation::builder(io.clone() as Rc<dyn EvalIO>); + eval_builder = add_derivation_builtins(eval_builder, Rc::clone(&io)); + eval_builder = add_fetcher_builtins(eval_builder, Rc::clone(&io)); + eval_builder = add_import_builtins(eval_builder, io); + let eval = eval_builder.build(); // run the evaluation itself. eval.evaluate(str, None) @@ -528,14 +537,13 @@ mod tests { assert!(eval_result.errors.is_empty(), "errors should be empty"); } - // Space is an illegal character. + /// Space is an illegal character, but if we specify a name without spaces, it's ok. #[rstest] - #[case( + #[case::rename_success( r#"(builtins.path { name = "valid-name"; path = @fixtures + "/te st"; recursive = true; })"#, true )] - // Space is still an illegal character. - #[case( + #[case::rename_with_spaces_fail( r#"(builtins.path { name = "invalid name"; path = @fixtures + "/te st"; recursive = true; })"#, false )] @@ -574,14 +582,13 @@ mod tests { } } - // Space is an illegal character. + /// Space is an illegal character, but if we specify a name without spaces, it's ok. #[rstest] - #[case( + #[case::rename_success( r#"(builtins.path { name = "valid-name"; path = @fixtures + "/te st"; recursive = false; })"#, true )] - // Space is still an illegal character. - #[case( + #[case::rename_with_spaces_fail( r#"(builtins.path { name = "invalid name"; path = @fixtures + "/te st"; recursive = false; })"#, false )] @@ -622,20 +629,20 @@ mod tests { } #[rstest] - #[case( + #[case::flat_success( r#"(builtins.path { name = "valid-name"; path = @fixtures + "/te st"; recursive = false; sha256 = "sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="; })"#, true )] - #[case( - r#"(builtins.path { name = "valid-name"; path = @fixtures + "/te st"; recursive = true; sha256 = "sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="; })"#, + #[case::flat_fail( + r#"(builtins.path { name = "valid-name"; path = @fixtures + "/te st"; recursive = false; sha256 = "sha256-d6xi4mKdjkX2JFicDIv5niSzpyI0m/Hnm8GGAIU04kY="; })"#, false )] - #[case( + #[case::recursive_success( r#"(builtins.path { name = "valid-name"; path = @fixtures + "/te st"; recursive = true; sha256 = "sha256-d6xi4mKdjkX2JFicDIv5niSzpyI0m/Hnm8GGAIU04kY="; })"#, true )] - #[case( - r#"(builtins.path { name = "valid-name"; path = @fixtures + "/te st"; recursive = false; sha256 = "sha256-d6xi4mKdjkX2JFicDIv5niSzpyI0m/Hnm8GGAIU04kY="; })"#, + #[case::recursive_fail( + r#"(builtins.path { name = "valid-name"; path = @fixtures + "/te st"; recursive = true; sha256 = "sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="; })"#, false )] fn builtins_path_fod_locking(#[case] code: &str, #[case] exp_success: bool) { @@ -739,6 +746,7 @@ mod tests { false )] fn builtins_filter_source_unsupported_files(#[case] code: &str, #[case] exp_success: bool) { + use nix::errno::Errno; use nix::sys::stat; use nix::unistd; use std::os::unix::net::UnixListener; @@ -765,6 +773,15 @@ mod tests { stat::Mode::S_IRWXU, 0, ) + .inspect_err(|e| { + if *e == Errno::EPERM { + eprintln!( + "\ +Missing permissions to create a character device node with mknod(2). +Please run this test as root or set CAP_MKNOD." + ); + } + }) .expect("Failed to create a character device node"); let code_replaced = code.replace("@fixtures", &temp.path().to_string_lossy()); diff --git a/tvix/glue/src/fetchers/decompression.rs b/tvix/glue/src/fetchers/decompression.rs index f96fa60e34f7..69a8297e6aa8 100644 --- a/tvix/glue/src/fetchers/decompression.rs +++ b/tvix/glue/src/fetchers/decompression.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] // TODO - use std::{ io, mem, pin::Pin, @@ -155,9 +153,7 @@ where }; let mut our_buf = ReadBuf::new(buffer); - if let Err(e) = ready!(inner.as_pin_mut().unwrap().poll_read(cx, &mut our_buf)) { - return Poll::Ready(Err(e)); - } + ready!(inner.as_pin_mut().unwrap().poll_read(cx, &mut our_buf))?; let data = our_buf.filled(); if data.len() >= BYTES_NEEDED { diff --git a/tvix/glue/src/fetchers/mod.rs b/tvix/glue/src/fetchers/mod.rs index 4b53d0fdac60..c12598e96328 100644 --- a/tvix/glue/src/fetchers/mod.rs +++ b/tvix/glue/src/fetchers/mod.rs @@ -1,20 +1,20 @@ use futures::TryStreamExt; -use md5::Md5; +use md5::{digest::DynDigest, Md5}; use nix_compat::{ nixhash::{CAHash, HashAlgo, NixHash}, store_path::{build_ca_path, BuildStorePathError, StorePathRef}, }; use sha1::Sha1; use sha2::{digest::Output, Digest, Sha256, Sha512}; -use tokio::io::{AsyncBufRead, AsyncRead, AsyncWrite}; -use tokio_util::io::InspectReader; -use tracing::warn; -use tvix_castore::{ - blobservice::BlobService, - directoryservice::DirectoryService, - proto::{node::Node, FileNode}, +use tokio::io::{AsyncBufRead, AsyncRead, AsyncWrite, AsyncWriteExt, BufReader}; +use tokio_util::io::{InspectReader, InspectWriter}; +use tracing::{instrument, warn, Span}; +use tracing_indicatif::span_ext::IndicatifSpanExt; +use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService, Node}; +use tvix_store::{ + nar::NarCalculationService, + pathinfoservice::{PathInfo, PathInfoService}, }; -use tvix_store::{pathinfoservice::PathInfoService, proto::PathInfo}; use url::Url; use crate::builtins::FetcherError; @@ -25,18 +25,53 @@ use decompression::DecompressedReader; /// Representing options for doing a fetch. #[derive(Clone, Eq, PartialEq)] pub enum Fetch { - /// Fetch a literal file from the given URL, with an optional expected - /// NixHash of it. - /// TODO: check if this is *always* sha256, and if so, make it [u8; 32]. - URL(Url, Option<NixHash>), + /// Fetch a literal file from the given URL, + /// with an optional expected hash. + URL { + /// The URL to fetch from. + url: Url, + /// The expected hash of the file. + exp_hash: Option<NixHash>, + }, /// Fetch a tarball from the given URL and unpack. - /// The file must be a tape archive (.tar) compressed with gzip, bzip2 or xz. + /// The file must be a tape archive (.tar), optionally compressed with gzip, + /// bzip2 or xz. /// The top-level path component of the files in the tarball is removed, /// so it is best if the tarball contains a single directory at top level. /// Optionally, a sha256 digest can be provided to verify the unpacked /// contents against. - Tarball(Url, Option<[u8; 32]>), + Tarball { + /// The URL to fetch from. + url: Url, + /// The expected hash of the contents, as NAR. + exp_nar_sha256: Option<[u8; 32]>, + }, + + /// Fetch a NAR file from the given URL and unpack. + /// The file can optionally be compressed. + NAR { + /// The URL to fetch from. + url: Url, + /// The expected hash of the NAR representation. + /// This unfortunately supports more than sha256. + hash: NixHash, + }, + + /// Fetches a file at a URL, makes it the store path root node, + /// but executable. + /// Used by <nix/fetchurl.nix>, with `executable = true;`. + /// The expected hash is over the NAR representation, but can be not SHA256: + /// ```nix + /// (import <nix/fetchurl.nix> { url = "https://cache.nixos.org/nar/0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz"; hash = "sha1-NKNeU1csW5YJ4lCeWH3Z/apppNU="; executable = true; }) + /// ``` + Executable { + /// The URL to fetch from. + url: Url, + /// The expected hash of the NAR representation. + /// This unfortunately supports more than sha256. + hash: NixHash, + }, /// TODO Git(), @@ -59,27 +94,38 @@ fn redact_url(url: &Url) -> Url { impl std::fmt::Debug for Fetch { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Fetch::URL(url, nixhash) => { + Fetch::URL { url, exp_hash } => { let url = redact_url(url); - if let Some(nixhash) = nixhash { - write!(f, "URL [url: {}, exp_hash: Some({})]", &url, nixhash) + if let Some(exp_hash) = exp_hash { + write!(f, "URL [url: {}, exp_hash: Some({})]", &url, exp_hash) } else { write!(f, "URL [url: {}, exp_hash: None]", &url) } } - Fetch::Tarball(url, exp_digest) => { + Fetch::Tarball { + url, + exp_nar_sha256, + } => { let url = redact_url(url); - if let Some(exp_digest) = exp_digest { + if let Some(exp_nar_sha256) = exp_nar_sha256 { write!( f, - "Tarball [url: {}, exp_hash: Some({})]", + "Tarball [url: {}, exp_nar_sha256: Some({})]", url, - NixHash::Sha256(*exp_digest) + NixHash::Sha256(*exp_nar_sha256) ) } else { write!(f, "Tarball [url: {}, exp_hash: None]", url) } } + Fetch::NAR { url, hash } => { + let url = redact_url(url); + write!(f, "NAR [url: {}, hash: {}]", &url, hash) + } + Fetch::Executable { url, hash } => { + let url = redact_url(url); + write!(f, "Executable [url: {}, hash: {}]", &url, hash) + } Fetch::Git() => todo!(), } } @@ -94,9 +140,28 @@ impl Fetch { name: &'a str, ) -> Result<Option<StorePathRef<'a>>, BuildStorePathError> { let ca_hash = match self { - Fetch::URL(_, Some(nixhash)) => CAHash::Flat(nixhash.clone()), - Fetch::Tarball(_, Some(nar_sha256)) => CAHash::Nar(NixHash::Sha256(*nar_sha256)), - _ => return Ok(None), + Fetch::URL { + exp_hash: Some(exp_hash), + .. + } => CAHash::Flat(exp_hash.clone()), + + Fetch::Tarball { + exp_nar_sha256: Some(exp_nar_sha256), + .. + } => CAHash::Nar(NixHash::Sha256(*exp_nar_sha256)), + + Fetch::NAR { hash, .. } | Fetch::Executable { hash, .. } => { + CAHash::Nar(hash.to_owned()) + } + + Fetch::Git() => todo!(), + + // everything else + Fetch::URL { exp_hash: None, .. } + | Fetch::Tarball { + exp_nar_sha256: None, + .. + } => return Ok(None), }; // calculate the store path of this fetch @@ -105,26 +170,44 @@ impl Fetch { } /// Knows how to fetch a given [Fetch]. -pub struct Fetcher<BS, DS, PS> { +pub struct Fetcher<BS, DS, PS, NS> { http_client: reqwest::Client, blob_service: BS, directory_service: DS, path_info_service: PS, + nar_calculation_service: NS, } -impl<BS, DS, PS> Fetcher<BS, DS, PS> { - pub fn new(blob_service: BS, directory_service: DS, path_info_service: PS) -> Self { +impl<BS, DS, PS, NS> Fetcher<BS, DS, PS, NS> { + pub fn new( + blob_service: BS, + directory_service: DS, + path_info_service: PS, + nar_calculation_service: NS, + ) -> Self { Self { http_client: reqwest::Client::new(), blob_service, directory_service, path_info_service, + nar_calculation_service, } } /// Constructs a HTTP request to the passed URL, and returns a AsyncReadBuf to it. /// In case the URI uses the file:// scheme, use tokio::fs to open it. - async fn download(&self, url: Url) -> Result<Box<dyn AsyncBufRead + Unpin>, FetcherError> { + #[instrument(skip_all, fields(url, indicatif.pb_show=1), err)] + async fn download( + &self, + url: Url, + ) -> Result<Box<dyn AsyncBufRead + Unpin + Send>, FetcherError> { + let span = Span::current(); + span.pb_set_message(&format!( + "📡Fetching {}", + // TOOD: maybe shorten + redact_url(&url) + )); + match url.scheme() { "file" => { let f = tokio::fs::File::open(url.to_file_path().map_err(|_| { @@ -136,16 +219,38 @@ impl<BS, DS, PS> Fetcher<BS, DS, PS> { )) })?) .await?; - Ok(Box::new(tokio::io::BufReader::new(f))) + + span.pb_set_length(f.metadata().await?.len()); + span.pb_set_style(&tvix_tracing::PB_TRANSFER_STYLE); + span.pb_start(); + Ok(Box::new(tokio::io::BufReader::new(InspectReader::new( + f, + move |d| { + span.pb_inc(d.len() as u64); + }, + )))) } _ => { let resp = self.http_client.get(url).send().await?; + + if let Some(content_length) = resp.content_length() { + span.pb_set_length(content_length); + span.pb_set_style(&tvix_tracing::PB_TRANSFER_STYLE); + } else { + span.pb_set_style(&tvix_tracing::PB_TRANSFER_STYLE); + } + span.pb_start(); + Ok(Box::new(tokio_util::io::StreamReader::new( - resp.bytes_stream().map_err(|e| { - let e = e.without_url(); - warn!(%e, "failed to get response body"); - std::io::Error::new(std::io::ErrorKind::BrokenPipe, e) - }), + resp.bytes_stream() + .inspect_ok(move |d| { + span.pb_inc(d.len() as u64); + }) + .map_err(|e| { + let e = e.without_url(); + warn!(%e, "failed to get response body"); + std::io::Error::new(std::io::ErrorKind::BrokenPipe, e) + }), ))) } } @@ -169,11 +274,12 @@ async fn hash<D: Digest + std::io::Write>( Ok((hasher.finalize(), bytes_copied)) } -impl<BS, DS, PS> Fetcher<BS, DS, PS> +impl<BS, DS, PS, NS> Fetcher<BS, DS, PS, NS> where - BS: AsRef<(dyn BlobService + 'static)> + Clone + Send + Sync + 'static, - DS: AsRef<(dyn DirectoryService + 'static)>, + BS: BlobService + Clone + 'static, + DS: DirectoryService + Clone, PS: PathInfoService, + NS: NarCalculationService, { /// Ingest the data from a specified [Fetch]. /// On success, return the root node, a content digest and length. @@ -181,7 +287,7 @@ where /// didn't match the previously communicated hash contained inside the FetchArgs. pub async fn ingest(&self, fetch: Fetch) -> Result<(Node, CAHash, u64), FetcherError> { match fetch { - Fetch::URL(url, exp_nixhash) => { + Fetch::URL { url, exp_hash } => { // Construct a AsyncRead reading from the data as its downloaded. let mut r = self.download(url.clone()).await?; @@ -190,8 +296,8 @@ where // Copy the contents from the download reader to the blob writer. // Calculate the digest of the file received, depending on the - // communicated expected hash (or sha256 if none provided). - let (actual_nixhash, blob_size) = match exp_nixhash + // communicated expected hash algo (or sha256 if none provided). + let (actual_hash, blob_size) = match exp_hash .as_ref() .map(NixHash::algo) .unwrap_or_else(|| HashAlgo::Sha256) @@ -212,29 +318,31 @@ where )?, }; - if let Some(exp_nixhash) = exp_nixhash { - if exp_nixhash != actual_nixhash { + if let Some(exp_hash) = exp_hash { + if exp_hash != actual_hash { return Err(FetcherError::HashMismatch { url, - wanted: exp_nixhash, - got: actual_nixhash, + wanted: exp_hash, + got: actual_hash, }); } } // Construct and return the FileNode describing the downloaded contents. Ok(( - Node::File(FileNode { - name: vec![].into(), - digest: blob_writer.close().await?.into(), + Node::File { + digest: blob_writer.close().await?, size: blob_size, executable: false, - }), - CAHash::Flat(actual_nixhash), + }, + CAHash::Flat(actual_hash), blob_size, )) } - Fetch::Tarball(url, exp_nar_sha256) => { + Fetch::Tarball { + url, + exp_nar_sha256, + } => { // Construct a AsyncRead reading from the data as its downloaded. let r = self.download(url.clone()).await?; @@ -243,10 +351,10 @@ where // Open the archive. let archive = tokio_tar::Archive::new(r); - // Ingest the archive, get the root node + // Ingest the archive, get the root node. let node = tvix_castore::import::archive::ingest_archive( self.blob_service.clone(), - &self.directory_service, + self.directory_service.clone(), archive, ) .await?; @@ -254,9 +362,9 @@ where // If an expected NAR sha256 was provided, compare with the one // calculated from our root node. // Even if no expected NAR sha256 has been provided, we need - // the actual one later. + // the actual one to calculate the store path. let (nar_size, actual_nar_sha256) = self - .path_info_service + .nar_calculation_service .calculate_nar(&node) .await .map_err(|e| { @@ -280,6 +388,155 @@ where nar_size, )) } + Fetch::NAR { + url, + hash: exp_hash, + } => { + // Construct a AsyncRead reading from the data as its downloaded. + let r = self.download(url.clone()).await?; + + // Pop compression. + let r = DecompressedReader::new(r); + + // Wrap the reader, calculating our own hash. + let mut hasher: Box<dyn DynDigest + Send> = match exp_hash.algo() { + HashAlgo::Md5 => Box::new(Md5::new()), + HashAlgo::Sha1 => Box::new(Sha1::new()), + HashAlgo::Sha256 => Box::new(Sha256::new()), + HashAlgo::Sha512 => Box::new(Sha512::new()), + }; + let mut r = tokio_util::io::InspectReader::new(r, |b| { + hasher.update(b); + }); + + // Ingest the NAR, get the root node. + let (root_node, _actual_nar_sha256, actual_nar_size) = + tvix_store::nar::ingest_nar_and_hash( + self.blob_service.clone(), + self.directory_service.clone(), + &mut r, + ) + .await + .map_err(|e| FetcherError::Io(std::io::Error::other(e.to_string())))?; + + // finalize the hasher. + let actual_hash = { + match exp_hash.algo() { + HashAlgo::Md5 => { + NixHash::Md5(hasher.finalize().to_vec().try_into().unwrap()) + } + HashAlgo::Sha1 => { + NixHash::Sha1(hasher.finalize().to_vec().try_into().unwrap()) + } + HashAlgo::Sha256 => { + NixHash::Sha256(hasher.finalize().to_vec().try_into().unwrap()) + } + HashAlgo::Sha512 => { + NixHash::Sha512(hasher.finalize().to_vec().try_into().unwrap()) + } + } + }; + + // Ensure the hash matches. + if exp_hash != actual_hash { + return Err(FetcherError::HashMismatch { + url, + wanted: exp_hash, + got: actual_hash, + }); + } + Ok(( + root_node, + // use a CAHash::Nar with the algo from the input. + CAHash::Nar(exp_hash), + actual_nar_size, + )) + } + Fetch::Executable { + url, + hash: exp_hash, + } => { + // Construct a AsyncRead reading from the data as its downloaded. + let mut r = self.download(url.clone()).await?; + + // Construct a AsyncWrite to write into the BlobService. + let mut blob_writer = self.blob_service.open_write().await; + + // Copy the contents from the download reader to the blob writer. + let file_size = tokio::io::copy(&mut r, &mut blob_writer).await?; + let blob_digest = blob_writer.close().await?; + + // Render the NAR representation on-the-fly into a hash function with + // the same algo as our expected hash. + // We cannot do this upfront, as we don't know the actual size. + // FUTUREWORK: make opportunistic use of Content-Length header? + + let w = tokio::io::sink(); + // Construct the hash function. + let mut hasher: Box<dyn DynDigest + Send> = match exp_hash.algo() { + HashAlgo::Md5 => Box::new(Md5::new()), + HashAlgo::Sha1 => Box::new(Sha1::new()), + HashAlgo::Sha256 => Box::new(Sha256::new()), + HashAlgo::Sha512 => Box::new(Sha512::new()), + }; + + let mut nar_size: u64 = 0; + let mut w = InspectWriter::new(w, |d| { + hasher.update(d); + nar_size += d.len() as u64; + }); + + { + let node = nix_compat::nar::writer::r#async::open(&mut w).await?; + + let blob_reader = self + .blob_service + .open_read(&blob_digest) + .await? + .expect("Tvix bug: just-uploaded blob not found"); + + node.file(true, file_size, &mut BufReader::new(blob_reader)) + .await?; + + w.flush().await?; + } + + // finalize the hasher. + let actual_hash = { + match exp_hash.algo() { + HashAlgo::Md5 => { + NixHash::Md5(hasher.finalize().to_vec().try_into().unwrap()) + } + HashAlgo::Sha1 => { + NixHash::Sha1(hasher.finalize().to_vec().try_into().unwrap()) + } + HashAlgo::Sha256 => { + NixHash::Sha256(hasher.finalize().to_vec().try_into().unwrap()) + } + HashAlgo::Sha512 => { + NixHash::Sha512(hasher.finalize().to_vec().try_into().unwrap()) + } + } + }; + + if exp_hash != actual_hash { + return Err(FetcherError::HashMismatch { + url, + wanted: exp_hash, + got: actual_hash, + }); + } + + // Construct and return the FileNode describing the downloaded contents, + // make it executable. + let root_node = Node::File { + digest: blob_digest, + size: file_size, + executable: true, + }; + + Ok((root_node, CAHash::Nar(actual_hash), file_size)) + } Fetch::Git() => todo!(), } } @@ -297,52 +554,48 @@ where // Fetch file, return the (unnamed) (File)Node of its contents, ca hash and filesize. let (node, ca_hash, size) = self.ingest(fetch).await?; - // Calculate the store path to return later, which is done with the ca_hash. + // Calculate the store path to return, by calculating from ca_hash. let store_path = build_ca_path(name, &ca_hash, Vec::<String>::new(), false)?; - // Rename the node name to match the Store Path. - let node = node.rename(store_path.to_string().into()); - // If the resulting hash is not a CAHash::Nar, we also need to invoke // `calculate_nar` to calculate this representation, as it's required in // the [PathInfo]. + // FUTUREWORK: allow ingest() to return multiple hashes, or have it feed + // nar_calculation_service too? let (nar_size, nar_sha256) = match &ca_hash { - CAHash::Flat(_nix_hash) => self - .path_info_service + CAHash::Nar(NixHash::Sha256(nar_sha256)) => (size, *nar_sha256), + CAHash::Nar(_) | CAHash::Flat(_) => self + .nar_calculation_service .calculate_nar(&node) .await .map_err(|e| FetcherError::Io(e.into()))?, - CAHash::Nar(NixHash::Sha256(nar_sha256)) => (size, *nar_sha256), - CAHash::Nar(_) => unreachable!("Tvix bug: fetch returned non-sha256 CAHash::Nar"), CAHash::Text(_) => unreachable!("Tvix bug: fetch returned CAHash::Text"), }; // Construct the PathInfo and persist it. let path_info = PathInfo { - node: Some(tvix_castore::proto::Node { node: Some(node) }), + store_path: store_path.to_owned(), + node: node.clone(), references: vec![], - narinfo: Some(tvix_store::proto::NarInfo { - nar_size, - nar_sha256: nar_sha256.to_vec().into(), - signatures: vec![], - reference_names: vec![], - deriver: None, - ca: Some(ca_hash.into()), - }), + nar_size, + nar_sha256, + signatures: vec![], + deriver: None, + ca: Some(ca_hash), }; - let path_info = self - .path_info_service + self.path_info_service .put(path_info) .await .map_err(|e| FetcherError::Io(e.into()))?; - Ok((store_path, path_info.node.unwrap().node.unwrap())) + Ok((store_path, node)) } } /// Attempts to mimic `nix::libutil::baseNameOf` -pub(crate) fn url_basename(s: &str) -> &str { +pub(crate) fn url_basename(url: &Url) -> &str { + let s = url.path(); if s.is_empty() { return ""; } @@ -373,38 +626,82 @@ pub(crate) fn url_basename(s: &str) -> &str { #[cfg(test)] mod tests { mod fetch { - use nix_compat::nixbase32; - - use crate::fetchers::Fetch; - use super::super::*; - - #[test] - fn fetchurl_store_path() { - let url = Url::parse("https://raw.githubusercontent.com/aaptel/notmuch-extract-patch/f732a53e12a7c91a06755ebfab2007adc9b3063b/notmuch-extract-patch").unwrap(); - let exp_nixhash = NixHash::Sha256( - nixbase32::decode_fixed("0nawkl04sj7psw6ikzay7kydj3dhd0fkwghcsf5rzaw4bmp4kbax") - .unwrap(), - ); - - let fetch = Fetch::URL(url, Some(exp_nixhash)); + use crate::fetchers::Fetch; + use nix_compat::{nixbase32, nixhash}; + use rstest::rstest; + + #[rstest] + #[case::url_no_hash( + Fetch::URL{ + url: Url::parse("https://raw.githubusercontent.com/aaptel/notmuch-extract-patch/f732a53e12a7c91a06755ebfab2007adc9b3063b/notmuch-extract-patch").unwrap(), + exp_hash: None, + }, + None, + "notmuch-extract-patch" + )] + #[case::url_sha256( + Fetch::URL{ + url: Url::parse("https://raw.githubusercontent.com/aaptel/notmuch-extract-patch/f732a53e12a7c91a06755ebfab2007adc9b3063b/notmuch-extract-patch").unwrap(), + exp_hash: Some(nixhash::from_sri_str("sha256-Xa1Jbl2Eq5+L0ww+Ph1osA3Z/Dxe/RkN1/dITQCdXFk=").unwrap()), + }, + Some(StorePathRef::from_bytes(b"06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch").unwrap()), + "notmuch-extract-patch" + )] + #[case::url_custom_name( + Fetch::URL{ + url: Url::parse("https://test.example/owo").unwrap(), + exp_hash: Some(nixhash::from_sri_str("sha256-Xa1Jbl2Eq5+L0ww+Ph1osA3Z/Dxe/RkN1/dITQCdXFk=").unwrap()), + }, + Some(StorePathRef::from_bytes(b"06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch").unwrap()), + "notmuch-extract-patch" + )] + #[case::nar_sha256( + Fetch::NAR{ + url: Url::parse("https://cache.nixos.org/nar/0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz").unwrap(), + hash: nixhash::from_sri_str("sha256-oj6yfWKbcEerK8D9GdPJtIAOveNcsH1ztGeSARGypRA=").unwrap(), + }, + Some(StorePathRef::from_bytes(b"b40vjphshq4fdgv8s3yrp0bdlafi4920-0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz").unwrap()), + "0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz" + )] + #[case::nar_sha1( + Fetch::NAR{ + url: Url::parse("https://cache.nixos.org/nar/0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz").unwrap(), + hash: nixhash::from_sri_str("sha1-F/fMsgwkXF8fPCg1v9zPZ4yOFIA=").unwrap(), + }, + Some(StorePathRef::from_bytes(b"8kx7fdkdbzs4fkfb57xq0cbhs20ymq2n-0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz").unwrap()), + "0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz" + )] + #[case::nar_sha1( + Fetch::Executable{ + url: Url::parse("https://cache.nixos.org/nar/0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz").unwrap(), + hash: nixhash::from_sri_str("sha1-NKNeU1csW5YJ4lCeWH3Z/apppNU=").unwrap(), + }, + Some(StorePathRef::from_bytes(b"y92hm2xfk1009hrq0ix80j4m5k4j4w21-0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz").unwrap()), + "0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz" + )] + fn fetch_store_path( + #[case] fetch: Fetch, + #[case] exp_path: Option<StorePathRef>, + #[case] name: &str, + ) { assert_eq!( - "06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch", - &fetch - .store_path("notmuch-extract-patch") - .unwrap() - .unwrap() - .to_string(), - ) + exp_path, + fetch.store_path(name).expect("invalid name"), + "unexpected calculated store path" + ); } #[test] fn fetch_tarball_store_path() { let url = Url::parse("https://github.com/NixOS/nixpkgs/archive/91050ea1e57e50388fa87a3302ba12d188ef723a.tar.gz").unwrap(); - let exp_nixbase32 = + let exp_sha256 = nixbase32::decode_fixed("1hf6cgaci1n186kkkjq106ryf8mmlq9vnwgfwh625wa8hfgdn4dm") .unwrap(); - let fetch = Fetch::Tarball(url, Some(exp_nixbase32)); + let fetch = Fetch::Tarball { + url, + exp_nar_sha256: Some(exp_sha256), + }; assert_eq!( "7adgvk5zdfq4pwrhsm3n9lzypb12gw0g-source", @@ -415,30 +712,18 @@ mod tests { mod url_basename { use super::super::*; - - #[test] - fn empty_path() { - assert_eq!(url_basename(""), ""); - } - - #[test] - fn path_on_root() { - assert_eq!(url_basename("/dir"), "dir"); - } - - #[test] - fn relative_path() { - assert_eq!(url_basename("dir/foo"), "foo"); - } - - #[test] - fn root_with_trailing_slash() { - assert_eq!(url_basename("/"), ""); - } - - #[test] - fn trailing_slash() { - assert_eq!(url_basename("/dir/"), "dir"); + use rstest::rstest; + + #[rstest] + #[case::empty_path("", "")] + #[case::path_on_root("/dir", "dir")] + #[case::relative_path("dir/foo", "foo")] + #[case::root_with_trailing_slash("/", "")] + #[case::trailing_slash("/dir/", "dir")] + fn test_url_basename(#[case] url_path: &str, #[case] exp_basename: &str) { + let mut url = Url::parse("http://localhost").expect("invalid url"); + url.set_path(url_path); + assert_eq!(url_basename(&url), exp_basename); } } } diff --git a/tvix/glue/src/fetchurl.rs b/tvix/glue/src/fetchurl.rs new file mode 100644 index 000000000000..9f57868b1991 --- /dev/null +++ b/tvix/glue/src/fetchurl.rs @@ -0,0 +1,82 @@ +//! This contains the code translating from a `builtin:derivation` [Derivation] +//! to a [Fetch]. +use crate::fetchers::Fetch; +use nix_compat::{derivation::Derivation, nixhash::CAHash}; +use tracing::instrument; +use url::Url; + +/// Takes a derivation produced by a call to `builtin:fetchurl` and returns the +/// synthesized [Fetch] for it, as well as the name. +#[instrument] +pub(crate) fn fetchurl_derivation_to_fetch(drv: &Derivation) -> Result<(String, Fetch), Error> { + if drv.builder != "builtin:fetchurl" { + return Err(Error::BuilderInvalid); + } + if !drv.arguments.is_empty() { + return Err(Error::ArgumentsInvalud); + } + if drv.system != "builtin" { + return Err(Error::SystemInvalid); + } + + // ensure this is a fixed-output derivation + if drv.outputs.len() != 1 { + return Err(Error::NoFOD); + } + let out_output = &drv.outputs.get("out").ok_or(Error::NoFOD)?; + let ca_hash = out_output.ca_hash.clone().ok_or(Error::NoFOD)?; + + let name: String = drv + .environment + .get("name") + .ok_or(Error::NameMissing)? + .to_owned() + .try_into() + .map_err(|_| Error::NameInvalid)?; + + let url: Url = std::str::from_utf8(drv.environment.get("url").ok_or(Error::URLMissing)?) + .map_err(|_| Error::URLInvalid)? + .parse() + .map_err(|_| Error::URLInvalid)?; + + match ca_hash { + CAHash::Flat(hash) => { + return Ok(( + name, + Fetch::URL { + url, + exp_hash: Some(hash), + }, + )) + } + CAHash::Nar(hash) => { + if drv.environment.get("executable").map(|v| v.as_slice()) == Some(b"1") { + Ok((name, Fetch::Executable { url, hash })) + } else { + Ok((name, Fetch::NAR { url, hash })) + } + } + // you can't construct derivations containing this + CAHash::Text(_) => panic!("Tvix bug: got CaHash::Text in drv"), + } +} + +#[derive(Debug, thiserror::Error)] +pub(crate) enum Error { + #[error("Invalid builder")] + BuilderInvalid, + #[error("invalid arguments")] + ArgumentsInvalud, + #[error("Invalid system")] + SystemInvalid, + #[error("Derivation is not fixed-output")] + NoFOD, + #[error("Missing URL")] + URLMissing, + #[error("Invalid URL")] + URLInvalid, + #[error("Missing Name")] + NameMissing, + #[error("Name invalid")] + NameInvalid, +} diff --git a/tvix/glue/src/known_paths.rs b/tvix/glue/src/known_paths.rs index c95065592bcf..7934bfe0baa2 100644 --- a/tvix/glue/src/known_paths.rs +++ b/tvix/glue/src/known_paths.rs @@ -25,27 +25,27 @@ pub struct KnownPaths { /// /// Keys are derivation paths, values are a tuple of the "hash derivation /// modulo" and the Derivation struct itself. - derivations: HashMap<StorePath, ([u8; 32], Derivation)>, + derivations: HashMap<StorePath<String>, ([u8; 32], Derivation)>, /// A map from output path to (one) drv path. /// Note that in the case of FODs, multiple drvs can produce the same output /// path. We use one of them. - outputs_to_drvpath: HashMap<StorePath, StorePath>, + outputs_to_drvpath: HashMap<StorePath<String>, StorePath<String>>, /// A map from output path to fetches (and their names). - outputs_to_fetches: HashMap<StorePath, (String, Fetch)>, + outputs_to_fetches: HashMap<StorePath<String>, (String, Fetch)>, } impl KnownPaths { /// Fetch the opaque "hash derivation modulo" for a given derivation path. - pub fn get_hash_derivation_modulo(&self, drv_path: &StorePath) -> Option<&[u8; 32]> { + pub fn get_hash_derivation_modulo(&self, drv_path: &StorePath<String>) -> Option<&[u8; 32]> { self.derivations .get(drv_path) .map(|(hash_derivation_modulo, _derivation)| hash_derivation_modulo) } /// Return a reference to the Derivation for a given drv path. - pub fn get_drv_by_drvpath(&self, drv_path: &StorePath) -> Option<&Derivation> { + pub fn get_drv_by_drvpath(&self, drv_path: &StorePath<String>) -> Option<&Derivation> { self.derivations .get(drv_path) .map(|(_hash_derivation_modulo, derivation)| derivation) @@ -54,7 +54,10 @@ impl KnownPaths { /// Return the drv path of the derivation producing the passed output path. /// Note there can be multiple Derivations producing the same output path in /// flight; this function will only return one of them. - pub fn get_drv_path_for_output_path(&self, output_path: &StorePath) -> Option<&StorePath> { + pub fn get_drv_path_for_output_path( + &self, + output_path: &StorePath<String>, + ) -> Option<&StorePath<String>> { self.outputs_to_drvpath.get(output_path) } @@ -63,7 +66,7 @@ impl KnownPaths { /// be fully calculated. /// All input derivations this refers to must also be inserted to this /// struct. - pub fn add_derivation(&mut self, drv_path: StorePath, drv: Derivation) { + pub fn add_derivation(&mut self, drv_path: StorePath<String>, drv: Derivation) { // check input derivations to have been inserted. #[cfg(debug_assertions)] { @@ -73,7 +76,7 @@ impl KnownPaths { } // compute the hash derivation modulo - let hash_derivation_modulo = drv.derivation_or_fod_hash(|drv_path| { + let hash_derivation_modulo = drv.hash_derivation_modulo(|drv_path| { self.get_hash_derivation_modulo(&drv_path.to_owned()) .unwrap_or_else(|| panic!("{} not found", drv_path)) .to_owned() @@ -124,57 +127,86 @@ impl KnownPaths { /// Return the name and fetch producing the passed output path. /// Note there can also be (multiple) Derivations producing the same output path. - pub fn get_fetch_for_output_path(&self, output_path: &StorePath) -> Option<(String, Fetch)> { + pub fn get_fetch_for_output_path( + &self, + output_path: &StorePath<String>, + ) -> Option<(String, Fetch)> { self.outputs_to_fetches .get(output_path) .map(|(name, fetch)| (name.to_owned(), fetch.to_owned())) } + + /// Returns an iterator over all known derivations and their store path. + pub fn get_derivations(&self) -> impl Iterator<Item = (&StorePath<String>, &Derivation)> { + self.derivations.iter().map(|(k, v)| (k, &v.1)) + } } #[cfg(test)] mod tests { - use nix_compat::{derivation::Derivation, nixbase32, nixhash::NixHash, store_path::StorePath}; - use url::Url; + use std::sync::LazyLock; - use crate::fetchers::Fetch; + use hex_literal::hex; + use nix_compat::{derivation::Derivation, nixbase32, nixhash, store_path::StorePath}; + use url::Url; use super::KnownPaths; - use hex_literal::hex; - use lazy_static::lazy_static; + use crate::fetchers::Fetch; - lazy_static! { - static ref BAR_DRV: Derivation = Derivation::from_aterm_bytes(include_bytes!( + static BAR_DRV: LazyLock<Derivation> = LazyLock::new(|| { + Derivation::from_aterm_bytes(include_bytes!( "tests/ss2p4wmxijn652haqyd7dckxwl4c7hxx-bar.drv" )) - .expect("must parse"); - static ref FOO_DRV: Derivation = Derivation::from_aterm_bytes(include_bytes!( + .expect("must parse") + }); + + static FOO_DRV: LazyLock<Derivation> = LazyLock::new(|| { + Derivation::from_aterm_bytes(include_bytes!( "tests/ch49594n9avinrf8ip0aslidkc4lxkqv-foo.drv" )) - .expect("must parse"); - static ref BAR_DRV_PATH: StorePath = - StorePath::from_bytes(b"ss2p4wmxijn652haqyd7dckxwl4c7hxx-bar.drv").expect("must parse"); - static ref FOO_DRV_PATH: StorePath = - StorePath::from_bytes(b"ch49594n9avinrf8ip0aslidkc4lxkqv-foo.drv").expect("must parse"); - static ref BAR_OUT_PATH: StorePath = - StorePath::from_bytes(b"mp57d33657rf34lzvlbpfa1gjfv5gmpg-bar").expect("must parse"); - static ref FOO_OUT_PATH: StorePath = - StorePath::from_bytes(b"fhaj6gmwns62s6ypkcldbaj2ybvkhx3p-foo").expect("must parse"); - - static ref FETCH_URL : Fetch = Fetch::URL( - Url::parse("https://raw.githubusercontent.com/aaptel/notmuch-extract-patch/f732a53e12a7c91a06755ebfab2007adc9b3063b/notmuch-extract-patch").unwrap(), - Some(NixHash::Sha256(nixbase32::decode_fixed("0nawkl04sj7psw6ikzay7kydj3dhd0fkwghcsf5rzaw4bmp4kbax").unwrap())) - ); - static ref FETCH_URL_OUT_PATH: StorePath = StorePath::from_bytes(b"06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch").unwrap(); + .expect("must parse") + }); - static ref FETCH_TARBALL : Fetch = Fetch::Tarball( - Url::parse("https://github.com/NixOS/nixpkgs/archive/91050ea1e57e50388fa87a3302ba12d188ef723a.tar.gz").unwrap(), - Some(nixbase32::decode_fixed("1hf6cgaci1n186kkkjq106ryf8mmlq9vnwgfwh625wa8hfgdn4dm").unwrap()) - ); - static ref FETCH_TARBALL_OUT_PATH: StorePath = StorePath::from_bytes(b"7adgvk5zdfq4pwrhsm3n9lzypb12gw0g-source").unwrap(); + static BAR_DRV_PATH: LazyLock<StorePath<String>> = LazyLock::new(|| { + StorePath::from_bytes(b"ss2p4wmxijn652haqyd7dckxwl4c7hxx-bar.drv").expect("must parse") + }); + + static FOO_DRV_PATH: LazyLock<StorePath<String>> = LazyLock::new(|| { + StorePath::from_bytes(b"ch49594n9avinrf8ip0aslidkc4lxkqv-foo.drv").expect("must parse") + }); + + static BAR_OUT_PATH: LazyLock<StorePath<String>> = LazyLock::new(|| { + StorePath::from_bytes(b"mp57d33657rf34lzvlbpfa1gjfv5gmpg-bar").expect("must parse") + }); + + static FOO_OUT_PATH: LazyLock<StorePath<String>> = LazyLock::new(|| { + StorePath::from_bytes(b"fhaj6gmwns62s6ypkcldbaj2ybvkhx3p-foo").expect("must parse") + }); + + static FETCH_URL: LazyLock<Fetch> = LazyLock::new(|| { + Fetch::URL { + url: Url::parse("https://raw.githubusercontent.com/aaptel/notmuch-extract-patch/f732a53e12a7c91a06755ebfab2007adc9b3063b/notmuch-extract-patch").unwrap(), + exp_hash: Some(nixhash::from_sri_str("sha256-Xa1Jbl2Eq5+L0ww+Ph1osA3Z/Dxe/RkN1/dITQCdXFk=").unwrap()) + } + }); + + static FETCH_URL_OUT_PATH: LazyLock<StorePath<String>> = LazyLock::new(|| { + StorePath::from_bytes(b"06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch").unwrap() + }); + + static FETCH_TARBALL: LazyLock<Fetch> = LazyLock::new(|| { + Fetch::Tarball { + url: Url::parse("https://github.com/NixOS/nixpkgs/archive/91050ea1e57e50388fa87a3302ba12d188ef723a.tar.gz").unwrap(), + exp_nar_sha256: Some(nixbase32::decode_fixed("1hf6cgaci1n186kkkjq106ryf8mmlq9vnwgfwh625wa8hfgdn4dm").unwrap()) } + }); - /// ensure we don't allow acdding a Derivation that depends on another, - /// not-yet-added Derivation. + static FETCH_TARBALL_OUT_PATH: LazyLock<StorePath<String>> = LazyLock::new(|| { + StorePath::from_bytes(b"7adgvk5zdfq4pwrhsm3n9lzypb12gw0g-source").unwrap() + }); + + /// Ensure that we don't allow adding a derivation that depends on another, + /// not-yet-added derivation. #[test] #[should_panic] fn drv_reject_if_missing_input_drv() { @@ -267,22 +299,22 @@ mod tests { .unwrap() .to_owned() ); + } - // We should be able to get these fetches out, when asking for their out path. - let (got_name, got_fetch) = known_paths - .get_fetch_for_output_path(&FETCH_URL_OUT_PATH) - .expect("must be some"); - - assert_eq!("notmuch-extract-patch", got_name); - assert_eq!(FETCH_URL.clone(), got_fetch); + #[test] + fn get_derivations_working() { + let mut known_paths = KnownPaths::default(); - // … multiple times. - let (got_name, got_fetch) = known_paths - .get_fetch_for_output_path(&FETCH_URL_OUT_PATH) - .expect("must be some"); + // Add BAR_DRV + known_paths.add_derivation(BAR_DRV_PATH.clone(), BAR_DRV.clone()); - assert_eq!("notmuch-extract-patch", got_name); - assert_eq!(FETCH_URL.clone(), got_fetch); + // We should be able to find BAR_DRV_PATH and BAR_DRV as a pair in get_derivations. + assert_eq!( + Some((&BAR_DRV_PATH.clone(), &BAR_DRV.clone())), + known_paths + .get_derivations() + .find(|(s, d)| (*s, *d) == (&BAR_DRV_PATH, &BAR_DRV)) + ); } // TODO: add test panicking about missing digest diff --git a/tvix/glue/src/lib.rs b/tvix/glue/src/lib.rs index 2e5a3be103a1..320d1f6fede2 100644 --- a/tvix/glue/src/lib.rs +++ b/tvix/glue/src/lib.rs @@ -1,23 +1,26 @@ pub mod builtins; pub mod fetchers; pub mod known_paths; -pub mod refscan; pub mod tvix_build; pub mod tvix_io; pub mod tvix_store_io; +mod fetchurl; + #[cfg(test)] mod tests; /// Tell the Evaluator to resolve `<nix>` to the path `/__corepkgs__`, /// which has special handling in [tvix_io::TvixIO]. /// This is used in nixpkgs to import `fetchurl.nix` from `<nix>`. -pub fn configure_nix_path<IO>( - eval: &mut tvix_eval::Evaluation<IO>, +pub fn configure_nix_path<'co, 'ro, 'env, IO>( + eval_builder: tvix_eval::EvaluationBuilder<'co, 'ro, 'env, IO>, nix_search_path: &Option<String>, -) { - eval.nix_path = nix_search_path - .as_ref() - .map(|p| format!("nix=/__corepkgs__:{}", p)) - .or_else(|| Some("nix=/__corepkgs__".to_string())); +) -> tvix_eval::EvaluationBuilder<'co, 'ro, 'env, IO> { + eval_builder.nix_path( + nix_search_path + .as_ref() + .map(|p| format!("nix=/__corepkgs__:{}", p)) + .or_else(|| Some("nix=/__corepkgs__".to_string())), + ) } diff --git a/tvix/glue/src/refscan.rs b/tvix/glue/src/refscan.rs deleted file mode 100644 index 0e0bb6c77828..000000000000 --- a/tvix/glue/src/refscan.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! Simple scanner for non-overlapping, known references of Nix store paths in a -//! given string. -//! -//! This is used for determining build references (see -//! //tvix/eval/docs/build-references.md for more details). -//! -//! The scanner itself is using the Wu-Manber string-matching algorithm, using -//! our fork of the `wu-mamber` crate. - -use std::collections::BTreeSet; -use wu_manber::TwoByteWM; - -pub const STORE_PATH_LEN: usize = "/nix/store/00000000000000000000000000000000".len(); - -/// Represents a "primed" reference scanner with an automaton that knows the set -/// of store paths to scan for. -pub struct ReferenceScanner<P: Ord + AsRef<[u8]>> { - candidates: Vec<P>, - searcher: Option<TwoByteWM>, - matches: Vec<usize>, -} - -impl<P: Clone + Ord + AsRef<[u8]>> ReferenceScanner<P> { - /// Construct a new `ReferenceScanner` that knows how to scan for the given - /// candidate store paths. - pub fn new(candidates: Vec<P>) -> Self { - let searcher = if candidates.is_empty() { - None - } else { - Some(TwoByteWM::new(&candidates)) - }; - - ReferenceScanner { - searcher, - candidates, - matches: Default::default(), - } - } - - /// Scan the given str for all non-overlapping matches and collect them - /// in the scanner. - pub fn scan<S: AsRef<[u8]>>(&mut self, haystack: S) { - if haystack.as_ref().len() < STORE_PATH_LEN { - return; - } - - if let Some(searcher) = &self.searcher { - for m in searcher.find(haystack) { - self.matches.push(m.pat_idx); - } - } - } - - /// Finalise the reference scanner and return the resulting matches. - pub fn finalise(self) -> BTreeSet<P> { - self.matches - .into_iter() - .map(|idx| self.candidates[idx].clone()) - .collect() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - // The actual derivation of `nixpkgs.hello`. - const HELLO_DRV: &str = r#"Derive([("out","/nix/store/33l4p0pn0mybmqzaxfkpppyh7vx1c74p-hello-2.12.1","","")],[("/nix/store/6z1jfnqqgyqr221zgbpm30v91yfj3r45-bash-5.1-p16.drv",["out"]),("/nix/store/ap9g09fxbicj836zm88d56dn3ff4clxl-stdenv-linux.drv",["out"]),("/nix/store/pf80kikyxr63wrw56k00i1kw6ba76qik-hello-2.12.1.tar.gz.drv",["out"])],["/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],"x86_64-linux","/nix/store/4xw8n979xpivdc46a9ndcvyhwgif00hz-bash-5.1-p16/bin/bash",["-e","/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],[("buildInputs",""),("builder","/nix/store/4xw8n979xpivdc46a9ndcvyhwgif00hz-bash-5.1-p16/bin/bash"),("cmakeFlags",""),("configureFlags",""),("depsBuildBuild",""),("depsBuildBuildPropagated",""),("depsBuildTarget",""),("depsBuildTargetPropagated",""),("depsHostHost",""),("depsHostHostPropagated",""),("depsTargetTarget",""),("depsTargetTargetPropagated",""),("doCheck","1"),("doInstallCheck",""),("mesonFlags",""),("name","hello-2.12.1"),("nativeBuildInputs",""),("out","/nix/store/33l4p0pn0mybmqzaxfkpppyh7vx1c74p-hello-2.12.1"),("outputs","out"),("patches",""),("pname","hello"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),("src","/nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz"),("stdenv","/nix/store/cp65c8nk29qq5cl1wyy5qyw103cwmax7-stdenv-linux"),("strictDeps",""),("system","x86_64-linux"),("version","2.12.1")])"#; - - #[test] - fn test_no_patterns() { - let mut scanner: ReferenceScanner<String> = ReferenceScanner::new(vec![]); - - scanner.scan(HELLO_DRV); - - let result = scanner.finalise(); - - assert_eq!(result.len(), 0); - } - - #[test] - fn test_single_match() { - let mut scanner = ReferenceScanner::new(vec![ - "/nix/store/4xw8n979xpivdc46a9ndcvyhwgif00hz-bash-5.1-p16".to_string(), - ]); - scanner.scan(HELLO_DRV); - - let result = scanner.finalise(); - - assert_eq!(result.len(), 1); - assert!(result.contains("/nix/store/4xw8n979xpivdc46a9ndcvyhwgif00hz-bash-5.1-p16")); - } - - #[test] - fn test_multiple_matches() { - let candidates = vec![ - // these exist in the drv: - "/nix/store/33l4p0pn0mybmqzaxfkpppyh7vx1c74p-hello-2.12.1".to_string(), - "/nix/store/pf80kikyxr63wrw56k00i1kw6ba76qik-hello-2.12.1.tar.gz.drv".to_string(), - "/nix/store/cp65c8nk29qq5cl1wyy5qyw103cwmax7-stdenv-linux".to_string(), - // this doesn't: - "/nix/store/fn7zvafq26f0c8b17brs7s95s10ibfzs-emacs-28.2.drv".to_string(), - ]; - - let mut scanner = ReferenceScanner::new(candidates.clone()); - scanner.scan(HELLO_DRV); - - let result = scanner.finalise(); - assert_eq!(result.len(), 3); - - for c in candidates[..3].iter() { - assert!(result.contains(c)); - } - } -} diff --git a/tvix/glue/src/tests/dummy/.keep b/tvix/glue/src/tests/dummy/.keep new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/tvix/glue/src/tests/dummy/.keep diff --git a/tvix/glue/src/tests/empty-file b/tvix/glue/src/tests/empty-file new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/tvix/glue/src/tests/empty-file diff --git a/tvix/glue/src/tests/mod.rs b/tvix/glue/src/tests/mod.rs index e66f484e3dad..dbde42064a77 100644 --- a/tvix/glue/src/tests/mod.rs +++ b/tvix/glue/src/tests/mod.rs @@ -1,19 +1,18 @@ use std::{rc::Rc, sync::Arc}; +use clap::Parser; use pretty_assertions::assert_eq; use std::path::PathBuf; use tvix_build::buildservice::DummyBuildService; -use tvix_castore::{ - blobservice::{BlobService, MemoryBlobService}, - directoryservice::{DirectoryService, MemoryDirectoryService}, -}; -use tvix_eval::{EvalIO, Value}; -use tvix_store::pathinfoservice::{MemoryPathInfoService, PathInfoService}; +use tvix_eval::{EvalIO, EvalMode, Value}; +use tvix_store::utils::{construct_services, ServiceUrlsMemory}; use rstest::rstest; use crate::{ builtins::{add_derivation_builtins, add_fetcher_builtins, add_import_builtins}, + configure_nix_path, + tvix_io::TvixIO, tvix_store_io::TvixStoreIO, }; @@ -34,28 +33,35 @@ fn eval_test(code_path: PathBuf, expect_success: bool) { return; } - let blob_service = Arc::new(MemoryBlobService::default()) as Arc<dyn BlobService>; - let directory_service = - Arc::new(MemoryDirectoryService::default()) as Arc<dyn DirectoryService>; - let path_info_service = Box::new(MemoryPathInfoService::new( - blob_service.clone(), - directory_service.clone(), - )) as Box<dyn PathInfoService>; let tokio_runtime = tokio::runtime::Runtime::new().unwrap(); + let (blob_service, directory_service, path_info_service, nar_calculation_service) = + tokio_runtime + .block_on(async { + construct_services(ServiceUrlsMemory::parse_from(std::iter::empty::<&str>())).await + }) + .unwrap(); let tvix_store_io = Rc::new(TvixStoreIO::new( blob_service, directory_service, - path_info_service.into(), + path_info_service, + nar_calculation_service.into(), Arc::new(DummyBuildService::default()), tokio_runtime.handle().clone(), )); - let mut eval = tvix_eval::Evaluation::new(tvix_store_io.clone() as Rc<dyn EvalIO>, true); + // Wrap with TvixIO, so <nix/fetchurl.nix can be imported. + let mut eval_builder = tvix_eval::Evaluation::builder(Box::new(TvixIO::new( + tvix_store_io.clone() as Rc<dyn EvalIO>, + )) as Box<dyn EvalIO>) + .enable_import() + .mode(EvalMode::Strict); + + eval_builder = add_derivation_builtins(eval_builder, Rc::clone(&tvix_store_io)); + eval_builder = add_fetcher_builtins(eval_builder, Rc::clone(&tvix_store_io)); + eval_builder = add_import_builtins(eval_builder, tvix_store_io); + eval_builder = configure_nix_path(eval_builder, &None); - eval.strict = true; - add_derivation_builtins(&mut eval, tvix_store_io.clone()); - add_fetcher_builtins(&mut eval, tvix_store_io.clone()); - add_import_builtins(&mut eval, tvix_store_io.clone()); + let eval = eval_builder.build(); let result = eval.evaluate(code, Some(code_path.clone())); let failed = match result.value { @@ -144,3 +150,11 @@ fn nix_eval_okay(#[files("src/tests/nix_tests/eval-okay-*.nix")] code_path: Path // ) { // eval_test(code_path, false) // } + +// eval-fail-* tests contain a snippet of Nix code, which is +// expected to fail evaluation. The exact type of failure +// (assertion, parse error, etc) is not currently checked. +#[rstest] +fn eval_fail(#[files("src/tests/tvix_tests/eval-fail-*.nix")] code_path: PathBuf) { + eval_test(code_path, false) +} diff --git a/tvix/glue/src/tests/tvix_tests/eval-fail-fetchtarball-invalid-attrs.nix b/tvix/glue/src/tests/tvix_tests/eval-fail-fetchtarball-invalid-attrs.nix new file mode 100644 index 000000000000..209f58cc9d0c --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-fail-fetchtarball-invalid-attrs.nix @@ -0,0 +1,5 @@ +(builtins.fetchTarball { + url = "https://test.example/owo"; + # Only "sha256" is accepted here. + hash = "sha256-Xa1Jbl2Eq5+L0ww+Ph1osA3Z/Dxe/RkN1/dITQCdXFk="; +}) diff --git a/tvix/glue/src/tests/tvix_tests/eval-fail-fetchtarball-invalid-url.nix b/tvix/glue/src/tests/tvix_tests/eval-fail-fetchtarball-invalid-url.nix new file mode 100644 index 000000000000..32596ddcd5fb --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-fail-fetchtarball-invalid-url.nix @@ -0,0 +1 @@ +(builtins.fetchTarball /dev/null) diff --git a/tvix/glue/src/tests/tvix_tests/eval-fail-fetchurl-invalid-attrs.nix b/tvix/glue/src/tests/tvix_tests/eval-fail-fetchurl-invalid-attrs.nix new file mode 100644 index 000000000000..d3c2bed8018e --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-fail-fetchurl-invalid-attrs.nix @@ -0,0 +1,5 @@ +(builtins.fetchurl { + url = "https://test.example/owo"; + # Only "sha256" is accepted here. + hash = "sha256-Xa1Jbl2Eq5+L0ww+Ph1osA3Z/Dxe/RkN1/dITQCdXFk="; +}) diff --git a/tvix/glue/src/tests/tvix_tests/eval-fail-fetchurl-invalid-url.nix b/tvix/glue/src/tests/tvix_tests/eval-fail-fetchurl-invalid-url.nix new file mode 100644 index 000000000000..dc3f70b998d3 --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-fail-fetchurl-invalid-url.nix @@ -0,0 +1 @@ +(builtins.fetchurl /dev/null) diff --git a/tvix/glue/src/tests/tvix_tests/eval-fail-tofile-wrongctxtype.nix b/tvix/glue/src/tests/tvix_tests/eval-fail-tofile-wrongctxtype.nix new file mode 100644 index 000000000000..60c94818ed25 --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-fail-tofile-wrongctxtype.nix @@ -0,0 +1,3 @@ +# in 'toFile': the file 'foo' cannot refer to derivation outputs, at (string):1:1 +builtins.toFile "foo" "${(builtins.derivation {name = "foo"; builder = ":"; system = ":";})}" + diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.nix b/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.nix index ecd8ab0073d0..e5719e00c3ae 100644 --- a/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.nix +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-context-introspection.nix @@ -71,7 +71,7 @@ in (builtins.hasAttr "allOutputs" (builtins.getContext drv.drvPath)."${builtins.unsafeDiscardStringContext drv.drvPath}") (legit-context == desired-context) # FIXME(raitobezarius): this should not use `builtins.seq`, this is a consequence of excessive laziness of Tvix, I believe. (reconstructed-path == combo-path) - # Those are too slow? + # These still fail with an internal error # (etaRule' "foo") # (etaRule' combo-path) (etaRule "foo") diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-fetchurl.exp b/tvix/glue/src/tests/tvix_tests/eval-okay-fetchurl.exp index 37a04d577c59..50d8e3574bb8 100644 --- a/tvix/glue/src/tests/tvix_tests/eval-okay-fetchurl.exp +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-fetchurl.exp @@ -1 +1 @@ -[ /nix/store/y0r1p1cqmlvm0yqkz3gxvkc1p8kg2sz8-null /nix/store/06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch /nix/store/06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch /nix/store/06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch ] +[ /nix/store/y0r1p1cqmlvm0yqkz3gxvkc1p8kg2sz8-null /nix/store/06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch /nix/store/06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch /nix/store/06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch "/nix/store/06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch" "/nix/store/b40vjphshq4fdgv8s3yrp0bdlafi4920-0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz" "/nix/store/8kx7fdkdbzs4fkfb57xq0cbhs20ymq2n-0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz" "/nix/store/y92hm2xfk1009hrq0ix80j4m5k4j4w21-0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz" ] diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-fetchurl.nix b/tvix/glue/src/tests/tvix_tests/eval-okay-fetchurl.nix index 8a3910152554..a3e9c5486968 100644 --- a/tvix/glue/src/tests/tvix_tests/eval-okay-fetchurl.nix +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-fetchurl.nix @@ -22,4 +22,44 @@ name = "notmuch-extract-patch"; sha256 = "sha256-Xa1Jbl2Eq5+L0ww+Ph1osA3Z/Dxe/RkN1/dITQCdXFk="; }) + + # The following tests use <nix/fetchurl.nix>. + # This is a piece of Nix code producing a "fake derivation" which gets + # handled by a "custom builder" that does the actual fetching. + # We access `.outPath` here, as the current string output of a Derivation + # still differs from the way nix presents it. + # It behaves similar to builtins.fetchurl, except it requires a hash to be + # provided upfront. + # If `unpack` is set to true, it can unpack NAR files (decompressing if + # necessary) + # If `executable` is set to true, it will place the fetched file at the root, + # but make it executable, and the hash is on the NAR representation. + + # Fetch a URL. + (import <nix/fetchurl.nix> { + url = "https://test.example/owo"; + name = "notmuch-extract-patch"; + sha256 = "Xa1Jbl2Eq5+L0ww+Ph1osA3Z/Dxe/RkN1/dITQCdXFk="; + }).outPath + + # Fetch a NAR and unpack it, specifying the sha256 of its NAR representation. + (import <nix/fetchurl.nix> { + url = "https://cache.nixos.org/nar/0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz"; + sha256 = "sha256-oj6yfWKbcEerK8D9GdPJtIAOveNcsH1ztGeSARGypRA="; + unpack = true; + }).outPath + + # Fetch a NAR and unpack it, specifying its *sha1* of its NAR representation. + (import <nix/fetchurl.nix> { + url = "https://cache.nixos.org/nar/0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz"; + hash = "sha1-F/fMsgwkXF8fPCg1v9zPZ4yOFIA="; + unpack = true; + }).outPath + + # Fetch a URL, specifying the *sha1* of a NAR describing it as executable at the root. + (import <nix/fetchurl.nix> { + url = "https://cache.nixos.org/nar/0r8nqa1klm5v17ifc6z96m9wywxkjvgbnqq9pmy0sgqj53wj3n12.nar.xz"; + hash = "sha1-NKNeU1csW5YJ4lCeWH3Z/apppNU="; + executable = true; + }).outPath ] diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-storePath.exp b/tvix/glue/src/tests/tvix_tests/eval-okay-storePath.exp new file mode 100644 index 000000000000..e7d20f6631b1 --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-storePath.exp @@ -0,0 +1 @@ +{ contextMatches = true; hasContext = true; } diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-storePath.nix b/tvix/glue/src/tests/tvix_tests/eval-okay-storePath.nix new file mode 100644 index 000000000000..99205cb9e028 --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-storePath.nix @@ -0,0 +1,9 @@ +let + path = builtins.unsafeDiscardStringContext "${../empty-file}"; + storePath = builtins.storePath path; + context = builtins.getContext storePath; +in +{ + hasContext = builtins.hasContext storePath; + contextMatches = context == { "${path}" = { path = true; }; }; +} diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-storePath2.exp b/tvix/glue/src/tests/tvix_tests/eval-okay-storePath2.exp new file mode 100644 index 000000000000..26a467d2799d --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-storePath2.exp @@ -0,0 +1 @@ +{ plain = "/nix/store/vqsvbisgiqrqa1y0qljigq4ds5h38gym-dummy"; withSubPath = "/nix/store/vqsvbisgiqrqa1y0qljigq4ds5h38gym-dummy/.keep"; } diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-storePath2.nix b/tvix/glue/src/tests/tvix_tests/eval-okay-storePath2.nix new file mode 100644 index 000000000000..2d1fc45871f3 --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-storePath2.nix @@ -0,0 +1,8 @@ +let + path = builtins.unsafeDiscardStringContext "${../dummy}"; + storePath = builtins.storePath path; +in +{ + plain = builtins.storePath path; + withSubPath = builtins.storePath (path + "/.keep"); +} diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-tofile.exp b/tvix/glue/src/tests/tvix_tests/eval-okay-tofile.exp new file mode 100644 index 000000000000..c8e5b8fab5d9 --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-tofile.exp @@ -0,0 +1 @@ +[ "/nix/store/vxjiwkjkn7x4079qvh1jkl5pn05j2aw0-foo" "/nix/store/i7liwr52956m86kxp7dgbcwsk56r27v6-foo" "/nix/store/yw8k7ixk1zvb113p4y0bl3ahjxd5h9sr-foo" { "/nix/store/yw8k7ixk1zvb113p4y0bl3ahjxd5h9sr-foo" = { path = true; }; } ] diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-tofile.nix b/tvix/glue/src/tests/tvix_tests/eval-okay-tofile.nix new file mode 100644 index 000000000000..141bbc38ec11 --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-tofile.nix @@ -0,0 +1,11 @@ +let + noContext = (builtins.toFile "foo" "bar"); + someContext = (builtins.toFile "foo" "bar${noContext}"); + moreContext = (builtins.toFile "foo" "bar${someContext}"); +in +[ + noContext + someContext + moreContext + (builtins.getContext moreContext) +] diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-toxml-context.exp b/tvix/glue/src/tests/tvix_tests/eval-okay-toxml-context.exp new file mode 100644 index 000000000000..e9600ecdad7a --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-toxml-context.exp @@ -0,0 +1 @@ +[ { "/nix/store/y1s2fiq89v2h9vkb38w508ir20dwv6v2-test.drv" = { allOutputs = true; }; } false ] diff --git a/tvix/glue/src/tests/tvix_tests/eval-okay-toxml-context.nix b/tvix/glue/src/tests/tvix_tests/eval-okay-toxml-context.nix new file mode 100644 index 000000000000..352470980383 --- /dev/null +++ b/tvix/glue/src/tests/tvix_tests/eval-okay-toxml-context.nix @@ -0,0 +1,14 @@ +[ + # builtins.toXML retains context where there is. + (builtins.getContext (builtins.toXML { + inherit (derivation { + name = "test"; + builder = "/bin/sh"; + system = "x86_64-linux"; + }) drvPath; + })) + + # this should have no context. + (builtins.hasContext + (builtins.toXML { })) +] diff --git a/tvix/glue/src/tvix_build.rs b/tvix/glue/src/tvix_build.rs index e9eb1725ef3e..fa73224992e6 100644 --- a/tvix/glue/src/tvix_build.rs +++ b/tvix/glue/src/tvix_build.rs @@ -1,16 +1,14 @@ //! This module contains glue code translating from -//! [nix_compat::derivation::Derivation] to [tvix_build::proto::BuildRequest]. +//! [nix_compat::derivation::Derivation] to [tvix_build::buildservice::BuildRequest]. -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::{BTreeMap, HashSet}; +use std::path::PathBuf; use bytes::Bytes; -use nix_compat::{derivation::Derivation, nixbase32}; +use nix_compat::{derivation::Derivation, nixbase32, store_path::StorePath}; use sha2::{Digest, Sha256}; -use tvix_build::proto::{ - build_request::{AdditionalFile, BuildConstraints, EnvVar}, - BuildRequest, -}; -use tvix_castore::proto::{self, node::Node}; +use tvix_build::buildservice::{AdditionalFile, BuildConstraints, BuildRequest, EnvVar}; +use tvix_castore::Node; /// These are the environment variables that Nix sets in its sandbox for every /// build. @@ -29,17 +27,30 @@ const NIX_ENVIRONMENT_VARS: [(&str, &str); 12] = [ ("TMPDIR", "/build"), ]; -/// Takes a [Derivation] and turns it into a [BuildRequest]. +/// Get an iterator of store paths whose nixbase32 hashes will be the needles for refscanning +/// Importantly, the returned order will match the one used by [derivation_to_build_request] +/// so users may use this function to map back from the found needles to a store path +pub(crate) fn get_refscan_needles( + derivation: &Derivation, +) -> impl Iterator<Item = &StorePath<String>> { + derivation + .outputs + .values() + .filter_map(|output| output.path.as_ref()) + .chain(derivation.input_sources.iter()) + .chain(derivation.input_derivations.keys()) +} + +/// Takes a [Derivation] and turns it into a [buildservice::BuildRequest]. /// It assumes the Derivation has been validated. /// It needs two lookup functions: /// - one translating input sources to a castore node /// (`fn_input_sources_to_node`) /// - one translating a tuple of drv path and (a subset of their) output names to /// castore nodes of the selected outpus (`fn_input_drvs_to_output_nodes`). -#[allow(clippy::mutable_key_type)] pub(crate) fn derivation_to_build_request( derivation: &Derivation, - inputs: BTreeSet<Node>, + inputs: BTreeMap<StorePath<String>, Node>, ) -> std::io::Result<BuildRequest> { debug_assert!(derivation.validate(true).is_ok(), "drv must validate"); @@ -48,16 +59,6 @@ pub(crate) fn derivation_to_build_request( command_args.push(derivation.builder.clone()); command_args.extend_from_slice(&derivation.arguments); - // produce output_paths, which is the absolute path of each output (sorted) - let mut output_paths: Vec<String> = derivation - .outputs - .values() - .map(|e| e.path_str()[1..].to_owned()) - .collect(); - - // Sort the outputs. We can use sort_unstable, as these are unique strings. - output_paths.sort_unstable(); - // Produce environment_vars and additional files. // We use a BTreeMap while producing, and only realize the resulting Vec // while populating BuildRequest, so we don't need to worry about ordering. @@ -86,23 +87,41 @@ pub(crate) fn derivation_to_build_request( // TODO: handle __json (structured attrs, provide JSON file and source-able bash script) // Produce constraints. - let constraints = Some(BuildConstraints { - system: derivation.system.clone(), - min_memory: 0, - available_ro_paths: vec![], - // in case this is a fixed-output derivation, allow network access. - network_access: derivation.outputs.len() == 1 - && derivation - .outputs - .get("out") - .expect("invalid derivation") - .is_fixed(), - provide_bin_sh: true, - }); + let mut constraints = HashSet::from([ + BuildConstraints::System(derivation.system.clone()), + BuildConstraints::ProvideBinSh, + ]); + + if derivation.outputs.len() == 1 + && derivation + .outputs + .get("out") + .expect("Tvix bug: Derivation has no out output") + .is_fixed() + { + constraints.insert(BuildConstraints::NetworkAccess); + } - let build_request = BuildRequest { + Ok(BuildRequest { + // Importantly, this must match the order of get_refscan_needles, since users may use that + // function to map back from the found needles to a store path + refscan_needles: get_refscan_needles(derivation) + .map(|path| nixbase32::encode(path.digest())) + .collect(), command_args, - outputs: output_paths, + + outputs: { + // produce output_paths, which is the absolute path of each output (sorted) + let mut output_paths: Vec<PathBuf> = derivation + .outputs + .values() + .map(|e| PathBuf::from(e.path_str()[1..].to_owned())) + .collect(); + + // Sort the outputs. We can use sort_unstable, as these are unique strings. + output_paths.sort_unstable(); + output_paths + }, // Turn this into a sorted-by-key Vec<EnvVar>. environment_vars: environment_vars @@ -111,7 +130,15 @@ pub(crate) fn derivation_to_build_request( .collect(), inputs: inputs .into_iter() - .map(|n| proto::Node { node: Some(n) }) + .map(|(path, node)| { + ( + path.to_string() + .as_str() + .try_into() + .expect("Tvix bug: unable to convert store path basename to PathComponent"), + node, + ) + }) .collect(), inputs_dir: nix_compat::store_path::STORE_DIR[1..].into(), constraints, @@ -119,17 +146,12 @@ pub(crate) fn derivation_to_build_request( scratch_paths: vec!["build".into(), "nix/store".into()], additional_files: additional_files .into_iter() - .map(|(path, contents)| AdditionalFile { path, contents }) + .map(|(path, contents)| AdditionalFile { + path: PathBuf::from(path), + contents, + }) .collect(), - }; - - debug_assert!( - build_request.validate().is_ok(), - "invalid BuildRequest: {}", - build_request.validate().unwrap_err() - ); - - Ok(build_request) + }) } /// handle passAsFile, if set. @@ -192,31 +214,26 @@ fn calculate_pass_as_file_env(k: &str) -> (String, String) { #[cfg(test)] mod test { - use std::collections::BTreeSet; - use bytes::Bytes; - use nix_compat::derivation::Derivation; - use tvix_build::proto::{ - build_request::{AdditionalFile, BuildConstraints, EnvVar}, - BuildRequest, - }; - use tvix_castore::{ - fixtures::DUMMY_DIGEST, - proto::{self, node::Node, DirectoryNode}, - }; + use nix_compat::{derivation::Derivation, store_path::StorePath}; + use std::collections::{BTreeMap, HashSet}; + use std::sync::LazyLock; + use tvix_castore::fixtures::DUMMY_DIGEST; + use tvix_castore::{Node, PathComponent}; + + use tvix_build::buildservice::{AdditionalFile, BuildConstraints, BuildRequest, EnvVar}; use crate::tvix_build::NIX_ENVIRONMENT_VARS; use super::derivation_to_build_request; - use lazy_static::lazy_static; - - lazy_static! { - static ref INPUT_NODE_FOO: Node = Node::Directory(DirectoryNode { - name: Bytes::from("mp57d33657rf34lzvlbpfa1gjfv5gmpg-bar"), - digest: DUMMY_DIGEST.clone().into(), - size: 42, - }); - } + + static INPUT_NODE_FOO_NAME: LazyLock<Bytes> = + LazyLock::new(|| "mp57d33657rf34lzvlbpfa1gjfv5gmpg-bar".into()); + + static INPUT_NODE_FOO: LazyLock<Node> = LazyLock::new(|| Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 42, + }); #[test] fn test_derivation_to_build_request() { @@ -224,9 +241,14 @@ mod test { let derivation = Derivation::from_aterm_bytes(aterm_bytes).expect("must parse"); - let build_request = - derivation_to_build_request(&derivation, BTreeSet::from([INPUT_NODE_FOO.clone()])) - .expect("must succeed"); + let build_request = derivation_to_build_request( + &derivation, + BTreeMap::from([( + StorePath::<String>::from_bytes(&INPUT_NODE_FOO_NAME.clone()).unwrap(), + INPUT_NODE_FOO.clone(), + )]), + ) + .expect("must succeed"); let mut expected_environment_vars = vec![ EnvVar { @@ -263,20 +285,22 @@ mod test { command_args: vec![":".into()], outputs: vec!["nix/store/fhaj6gmwns62s6ypkcldbaj2ybvkhx3p-foo".into()], environment_vars: expected_environment_vars, - inputs: vec![proto::Node { - node: Some(INPUT_NODE_FOO.clone()) - }], + inputs: BTreeMap::from([( + PathComponent::try_from(INPUT_NODE_FOO_NAME.clone()).unwrap(), + INPUT_NODE_FOO.clone() + )]), inputs_dir: "nix/store".into(), - constraints: Some(BuildConstraints { - system: derivation.system.clone(), - min_memory: 0, - network_access: false, - available_ro_paths: vec![], - provide_bin_sh: true, - }), + constraints: HashSet::from([ + BuildConstraints::System(derivation.system.clone()), + BuildConstraints::ProvideBinSh + ]), additional_files: vec![], working_dir: "build".into(), scratch_paths: vec!["build".into(), "nix/store".into()], + refscan_needles: vec![ + "fhaj6gmwns62s6ypkcldbaj2ybvkhx3p".into(), + "ss2p4wmxijn652haqyd7dckxwl4c7hxx".into() + ], }, build_request ); @@ -289,7 +313,7 @@ mod test { let derivation = Derivation::from_aterm_bytes(aterm_bytes).expect("must parse"); let build_request = - derivation_to_build_request(&derivation, BTreeSet::from([])).expect("must succeed"); + derivation_to_build_request(&derivation, BTreeMap::from([])).expect("must succeed"); let mut expected_environment_vars = vec![ EnvVar { @@ -334,18 +358,17 @@ mod test { command_args: vec![":".to_string()], outputs: vec!["nix/store/4q0pg5zpfmznxscq3avycvf9xdvx50n3-bar".into()], environment_vars: expected_environment_vars, - inputs: vec![], + inputs: BTreeMap::new(), inputs_dir: "nix/store".into(), - constraints: Some(BuildConstraints { - system: derivation.system.clone(), - min_memory: 0, - network_access: true, - available_ro_paths: vec![], - provide_bin_sh: true, - }), + constraints: HashSet::from([ + BuildConstraints::System(derivation.system.clone()), + BuildConstraints::NetworkAccess, + BuildConstraints::ProvideBinSh + ]), additional_files: vec![], working_dir: "build".into(), scratch_paths: vec!["build".into(), "nix/store".into()], + refscan_needles: vec!["4q0pg5zpfmznxscq3avycvf9xdvx50n3".into()], }, build_request ); @@ -359,7 +382,7 @@ mod test { let derivation = Derivation::from_aterm_bytes(aterm_bytes).expect("must parse"); let build_request = - derivation_to_build_request(&derivation, BTreeSet::from([])).expect("must succeed"); + derivation_to_build_request(&derivation, BTreeMap::from([])).expect("must succeed"); let mut expected_environment_vars = vec![ // Note how bar and baz are not present in the env anymore, @@ -407,15 +430,12 @@ mod test { command_args: vec![":".to_string()], outputs: vec!["nix/store/pp17lwra2jkx8rha15qabg2q3wij72lj-foo".into()], environment_vars: expected_environment_vars, - inputs: vec![], + inputs: BTreeMap::new(), inputs_dir: "nix/store".into(), - constraints: Some(BuildConstraints { - system: derivation.system.clone(), - min_memory: 0, - network_access: false, - available_ro_paths: vec![], - provide_bin_sh: true, - }), + constraints: HashSet::from([ + BuildConstraints::System(derivation.system.clone()), + BuildConstraints::ProvideBinSh, + ]), additional_files: vec![ // baz env AdditionalFile { @@ -432,6 +452,7 @@ mod test { ], working_dir: "build".into(), scratch_paths: vec!["build".into(), "nix/store".into()], + refscan_needles: vec!["pp17lwra2jkx8rha15qabg2q3wij72lj".into()], }, build_request ); diff --git a/tvix/glue/src/tvix_io.rs b/tvix/glue/src/tvix_io.rs index 0e5f23b99093..323fa8d20ccb 100644 --- a/tvix/glue/src/tvix_io.rs +++ b/tvix/glue/src/tvix_io.rs @@ -1,12 +1,10 @@ //! This module implements a wrapper around tvix-eval's [EvalIO] type, //! adding functionality which is required by tvix-cli: //! -//! 1. Marking plain paths known to the reference scanner. -//! 2. Handling the C++ Nix `__corepkgs__`-hack for nixpkgs bootstrapping. +//! 1. Handling the C++ Nix `__corepkgs__`-hack for nixpkgs bootstrapping. //! //! All uses of [EvalIO] in tvix-cli must make use of this wrapper, -//! otherwise fundamental features like nixpkgs bootstrapping and hash -//! calculation will not work. +//! otherwise nixpkgs bootstrapping will not work. use std::io::{self, Cursor}; use std::path::{Path, PathBuf}; @@ -60,6 +58,10 @@ where self.actual.as_ref().open(path) } + fn file_type(&self, path: &Path) -> io::Result<FileType> { + self.actual.as_ref().file_type(path) + } + fn read_dir(&self, path: &Path) -> io::Result<Vec<(bytes::Bytes, FileType)>> { self.actual.as_ref().read_dir(path) } diff --git a/tvix/glue/src/tvix_store_io.rs b/tvix/glue/src/tvix_store_io.rs index 1f709906de7a..67a88e13c54b 100644 --- a/tvix/glue/src/tvix_store_io.rs +++ b/tvix/glue/src/tvix_store_io.rs @@ -1,33 +1,26 @@ //! This module provides an implementation of EvalIO talking to tvix-store. - -use async_recursion::async_recursion; -use bytes::Bytes; use futures::{StreamExt, TryStreamExt}; -use nix_compat::nixhash::NixHash; -use nix_compat::store_path::StorePathRef; use nix_compat::{nixhash::CAHash, store_path::StorePath}; -use sha2::{Digest, Sha256}; +use std::collections::BTreeMap; use std::{ cell::RefCell, - collections::BTreeSet, io, path::{Path, PathBuf}, sync::Arc, }; use tokio_util::io::SyncIoBridge; -use tracing::{error, info, instrument, warn, Level}; +use tracing::{error, instrument, warn, Level, Span}; +use tracing_indicatif::span_ext::IndicatifSpanExt; use tvix_build::buildservice::BuildService; -use tvix_castore::proto::node::Node; use tvix_eval::{EvalIO, FileType, StdIO}; -use tvix_store::utils::AsyncIoBridge; +use tvix_store::nar::NarCalculationService; use tvix_castore::{ blobservice::BlobService, directoryservice::{self, DirectoryService}, - proto::NamedNode, - B3Digest, + Node, }; -use tvix_store::{pathinfoservice::PathInfoService, proto::PathInfo}; +use tvix_store::pathinfoservice::{PathInfo, PathInfoService}; use crate::fetchers::Fetcher; use crate::known_paths::KnownPaths; @@ -53,16 +46,23 @@ pub struct TvixStoreIO { pub(crate) blob_service: Arc<dyn BlobService>, pub(crate) directory_service: Arc<dyn DirectoryService>, pub(crate) path_info_service: Arc<dyn PathInfoService>, + pub(crate) nar_calculation_service: Arc<dyn NarCalculationService>, + std_io: StdIO, #[allow(dead_code)] build_service: Arc<dyn BuildService>, pub(crate) tokio_handle: tokio::runtime::Handle, - pub(crate) fetcher: - Fetcher<Arc<dyn BlobService>, Arc<dyn DirectoryService>, Arc<dyn PathInfoService>>, + #[allow(clippy::type_complexity)] + pub(crate) fetcher: Fetcher< + Arc<dyn BlobService>, + Arc<dyn DirectoryService>, + Arc<dyn PathInfoService>, + Arc<dyn NarCalculationService>, + >, // Paths known how to produce, by building or fetching. - pub(crate) known_paths: RefCell<KnownPaths>, + pub known_paths: RefCell<KnownPaths>, } impl TvixStoreIO { @@ -70,6 +70,7 @@ impl TvixStoreIO { blob_service: Arc<dyn BlobService>, directory_service: Arc<dyn DirectoryService>, path_info_service: Arc<dyn PathInfoService>, + nar_calculation_service: Arc<dyn NarCalculationService>, build_service: Arc<dyn BuildService>, tokio_handle: tokio::runtime::Handle, ) -> Self { @@ -77,10 +78,16 @@ impl TvixStoreIO { blob_service: blob_service.clone(), directory_service: directory_service.clone(), path_info_service: path_info_service.clone(), + nar_calculation_service: nar_calculation_service.clone(), std_io: StdIO {}, build_service, tokio_handle, - fetcher: Fetcher::new(blob_service, directory_service, path_info_service), + fetcher: Fetcher::new( + blob_service, + directory_service, + path_info_service, + nar_calculation_service, + ), known_paths: Default::default(), } } @@ -92,11 +99,10 @@ impl TvixStoreIO { /// /// In case there is no PathInfo yet, this means we need to build it /// (which currently is stubbed out still). - #[async_recursion(?Send)] - #[instrument(skip(self, store_path), fields(store_path=%store_path), ret(level = Level::TRACE), err)] + #[instrument(skip(self, store_path), fields(store_path=%store_path, indicatif.pb_show=1), ret(level = Level::TRACE), err(level = Level::TRACE))] async fn store_path_to_node( &self, - store_path: &StorePath, + store_path: &StorePath<String>, sub_path: &Path, ) -> io::Result<Option<Node>> { // Find the root node for the store_path. @@ -110,8 +116,8 @@ impl TvixStoreIO { .get(*store_path.digest()) .await? { - // if we have a PathInfo, we know there will be a root_node (due to validation) - Some(path_info) => path_info.node.expect("no node").node.expect("no node"), + // TODO: use stricter typed BuildRequest here. + Some(path_info) => path_info.node, // If there's no PathInfo found, this normally means we have to // trigger the build (and insert into PathInfoService, after // reference scanning). @@ -125,7 +131,8 @@ impl TvixStoreIO { // The store path doesn't exist yet, so we need to fetch or build it. // We check for fetches first, as we might have both native // fetchers and FODs in KnownPaths, and prefer the former. - + // This will also find [Fetch] synthesized from + // `builtin:fetchurl` Derivations. let maybe_fetch = self .known_paths .borrow() @@ -133,7 +140,6 @@ impl TvixStoreIO { match maybe_fetch { Some((name, fetch)) => { - info!(?fetch, "triggering lazy fetch"); let (sp, root_node) = self .fetcher .ingest_and_persist(&name, fetch) @@ -143,9 +149,9 @@ impl TvixStoreIO { })?; debug_assert_eq!( - sp.to_string(), - store_path.to_string(), - "store path returned from fetcher should match" + sp.to_absolute_path(), + store_path.as_ref().to_absolute_path(), + "store path returned from fetcher must match store path we have in fetchers" ); root_node @@ -166,14 +172,15 @@ impl TvixStoreIO { } } }; - - warn!("triggering build"); + let span = Span::current(); + span.pb_start(); + span.pb_set_style(&tvix_tracing::PB_SPINNER_STYLE); + span.pb_set_message(&format!("â³Waiting for inputs {}", &store_path)); // derivation_to_build_request needs castore nodes for all inputs. // Provide them, which means, here is where we recursively build // all dependencies. - #[allow(clippy::mutable_key_type)] - let input_nodes: BTreeSet<Node> = + let mut inputs: BTreeMap<StorePath<String>, Node> = futures::stream::iter(drv.input_derivations.iter()) .map(|(input_drv_path, output_names)| { // look up the derivation object @@ -188,7 +195,7 @@ impl TvixStoreIO { }; // convert output names to actual paths - let output_paths: Vec<StorePath> = output_names + let output_paths: Vec<StorePath<String>> = output_names .iter() .map(|output_name| { input_drv @@ -201,6 +208,7 @@ impl TvixStoreIO { .clone() }) .collect(); + // For each output, ask for the castore node. // We're in a per-derivation context, so if they're // not built yet they'll all get built together. @@ -215,7 +223,7 @@ impl TvixStoreIO { .await?; if let Some(node) = node { - Ok(node) + Ok((output_path, node)) } else { Err(io::Error::other("no node produced")) } @@ -223,16 +231,44 @@ impl TvixStoreIO { ) }) .flatten() - .buffer_unordered(10) // TODO: make configurable + .buffer_unordered( + 1, /* TODO: increase again once we prevent redundant fetches */ + ) // TODO: make configurable + .try_collect() + .await?; + + // FUTUREWORK: merge these who things together + // add input sources + let input_sources: BTreeMap<_, _> = + futures::stream::iter(drv.input_sources.iter()) + .then(|input_source| { + Box::pin({ + let input_source = input_source.clone(); + async move { + let node = self + .store_path_to_node(&input_source, Path::new("")) + .await?; + if let Some(node) = node { + Ok((input_source, node)) + } else { + Err(io::Error::other("no node produced")) + } + } + }) + }) .try_collect() .await?; + inputs.extend(input_sources); + + span.pb_set_message(&format!("🔨Building {}", &store_path)); + // TODO: check if input sources are sufficiently dealth with, // I think yes, they must be imported into the store by other // operations, so dealt with in the Some(…) match arm // synthesize the build request. - let build_request = derivation_to_build_request(&drv, input_nodes)?; + let build_request = derivation_to_build_request(&drv, inputs)?; // create a build let build_result = self @@ -242,43 +278,77 @@ impl TvixStoreIO { .await .map_err(|e| std::io::Error::new(io::ErrorKind::Other, e))?; - // TODO: refscan? + // Maps from the index in refscan_needles to the full store path + // Used to map back to the actual store path from the found needles + // Importantly, this must match the order of the needles generated in derivation_to_build_request + let refscan_needles = + crate::tvix_build::get_refscan_needles(&drv).collect::<Vec<_>>(); // For each output, insert a PathInfo. - for output in &build_result.outputs { - let root_node = output.node.as_ref().expect("invalid root node"); + for ((output, output_needles), drv_output) in build_result + .outputs + .iter() + .zip(build_result.outputs_needles.iter()) + .zip(drv.outputs.iter()) + { + let output_node = output + .clone() + .try_into_anonymous_node() + .expect("invalid node"); + + let output_needles: Vec<_> = output_needles + .needles + .iter() + // Map each output needle index back to the refscan_needle + .map(|idx| { + refscan_needles + .get(*idx as usize) + .ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + "invalid build response", + )) + }) + .collect::<Result<_, std::io::Error>>()?; // calculate the nar representation - let (nar_size, nar_sha256) = - self.path_info_service.calculate_nar(root_node).await?; + let (nar_size, nar_sha256) = self + .nar_calculation_service + .calculate_nar(&output_node) + .await?; // assemble the PathInfo to persist let path_info = PathInfo { - node: Some(tvix_castore::proto::Node { - node: Some(root_node.clone()), - }), - references: vec![], // TODO: refscan - narinfo: Some(tvix_store::proto::NarInfo { - nar_size, - nar_sha256: Bytes::from(nar_sha256.to_vec()), - signatures: vec![], - reference_names: vec![], // TODO: refscan - deriver: Some(tvix_store::proto::StorePath { - name: drv_path + store_path: drv_output + .1 + .path + .as_ref() + .ok_or(std::io::Error::new( + std::io::ErrorKind::Other, + "Tvix bug: missing output store path", + ))? + .to_owned(), + node: output_node, + references: output_needles + .iter() + .map(|s| (**s).to_owned()) + .collect(), + nar_size, + nar_sha256, + signatures: vec![], + deriver: Some( + StorePath::from_name_and_digest_fixed( + drv_path .name() .strip_suffix(".drv") - .expect("missing .drv suffix") - .to_string(), - digest: drv_path.digest().to_vec().into(), - }), - ca: drv.fod_digest().map( - |fod_digest| -> tvix_store::proto::nar_info::Ca { - (&CAHash::Nar(nix_compat::nixhash::NixHash::Sha256( - fod_digest, - ))) - .into() - }, + .expect("missing .drv suffix"), + *drv_path.digest(), + ) + .expect( + "Tvix bug: StorePath without .drv suffix must be valid", ), + ), + ca: drv.fod_digest().map(|fod_digest| { + CAHash::Nar(nix_compat::nixhash::NixHash::Sha256(fod_digest)) }), }; @@ -289,121 +359,39 @@ impl TvixStoreIO { } // find the output for the store path requested + let s = store_path.to_string(); + build_result .outputs .into_iter() - .find(|output_node| { - output_node.node.as_ref().expect("invalid node").get_name() - == store_path.to_string().as_bytes() + .map(|e| e.try_into_name_and_node().expect("invalid node")) + .find(|(output_name, _output_node)| { + output_name.as_ref() == s.as_bytes() }) .expect("build didn't produce the store path") - .node - .expect("invalid node") + .1 } } } }; // now with the root_node and sub_path, descend to the node requested. + // We convert sub_path to the castore model here. + let sub_path = tvix_castore::PathBuf::from_host_path(sub_path, true)?; + directoryservice::descend_to(&self.directory_service, root_node, sub_path) .await .map_err(|e| std::io::Error::new(io::ErrorKind::Other, e)) } - - pub(crate) async fn node_to_path_info( - &self, - name: &str, - path: &Path, - ca: CAHash, - root_node: Node, - ) -> io::Result<(PathInfo, NixHash, StorePath)> { - // Ask the PathInfoService for the NAR size and sha256 - // We always need it no matter what is the actual hash mode - // because the path info construct a narinfo which *always* - // require a SHA256 of the NAR representation and the NAR size. - let (nar_size, nar_sha256) = self - .path_info_service - .as_ref() - .calculate_nar(&root_node) - .await?; - - // Calculate the output path. This might still fail, as some names are illegal. - let output_path = - nix_compat::store_path::build_ca_path(name, &ca, Vec::<String>::new(), false).map_err( - |_| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("invalid name: {}", name), - ) - }, - )?; - - // assemble a new root_node with a name that is derived from the nar hash. - let root_node = root_node.rename(output_path.to_string().into_bytes().into()); - tvix_store::import::log_node(&root_node, path); - - let path_info = - tvix_store::import::derive_nar_ca_path_info(nar_size, nar_sha256, Some(ca), root_node); - - Ok(( - path_info, - NixHash::Sha256(nar_sha256), - output_path.to_owned(), - )) - } - - pub(crate) async fn register_node_in_path_info_service( - &self, - name: &str, - path: &Path, - ca: CAHash, - root_node: Node, - ) -> io::Result<StorePath> { - let (path_info, _, output_path) = self.node_to_path_info(name, path, ca, root_node).await?; - let _path_info = self.path_info_service.as_ref().put(path_info).await?; - - Ok(output_path) - } - - /// Transforms a BLAKE-3 digest into a SHA256 digest - /// by re-hashing the whole file. - pub(crate) async fn blob_to_sha256_hash(&self, blob_digest: B3Digest) -> io::Result<[u8; 32]> { - let mut reader = self - .blob_service - .open_read(&blob_digest) - .await? - .ok_or_else(|| { - io::Error::new( - io::ErrorKind::NotFound, - format!("blob represented by digest: '{}' not found", blob_digest), - ) - })?; - // It is fine to use `AsyncIoBridge` here because hashing is not actually I/O. - let mut hasher = AsyncIoBridge(Sha256::new()); - - tokio::io::copy(&mut reader, &mut hasher).await?; - Ok(hasher.0.finalize().into()) - } - - pub async fn store_path_exists<'a>(&'a self, store_path: StorePathRef<'a>) -> io::Result<bool> { - Ok(self - .path_info_service - .as_ref() - .get(*store_path.digest()) - .await? - .is_some()) - } } impl EvalIO for TvixStoreIO { #[instrument(skip(self), ret(level = Level::TRACE), err)] fn path_exists(&self, path: &Path) -> io::Result<bool> { - if let Ok((store_path, sub_path)) = - StorePath::from_absolute_path_full(&path.to_string_lossy()) - { + if let Ok((store_path, sub_path)) = StorePath::from_absolute_path_full(path) { if self .tokio_handle - .block_on(async { self.store_path_to_node(&store_path, &sub_path).await })? + .block_on(self.store_path_to_node(&store_path, sub_path))? .is_some() { Ok(true) @@ -420,35 +408,21 @@ impl EvalIO for TvixStoreIO { #[instrument(skip(self), err)] fn open(&self, path: &Path) -> io::Result<Box<dyn io::Read>> { - if let Ok((store_path, sub_path)) = - StorePath::from_absolute_path_full(&path.to_string_lossy()) - { + if let Ok((store_path, sub_path)) = StorePath::from_absolute_path_full(path) { if let Some(node) = self .tokio_handle - .block_on(async { self.store_path_to_node(&store_path, &sub_path).await })? + .block_on(async { self.store_path_to_node(&store_path, sub_path).await })? { // depending on the node type, treat open differently match node { - Node::Directory(_) => { + Node::Directory { .. } => { // This would normally be a io::ErrorKind::IsADirectory (still unstable) Err(io::Error::new( io::ErrorKind::Unsupported, format!("tried to open directory at {:?}", path), )) } - Node::File(file_node) => { - let digest: B3Digest = - file_node.digest.clone().try_into().map_err(|_e| { - error!( - file_node = ?file_node, - "invalid digest" - ); - io::Error::new( - io::ErrorKind::InvalidData, - format!("invalid digest length in file node: {:?}", file_node), - ) - })?; - + Node::File { digest, .. } => { self.tokio_handle.block_on(async { let resp = self.blob_service.as_ref().open_read(&digest).await?; match resp { @@ -470,7 +444,7 @@ impl EvalIO for TvixStoreIO { } }) } - Node::Symlink(_symlink_node) => Err(io::Error::new( + Node::Symlink { .. } => Err(io::Error::new( io::ErrorKind::Unsupported, "open for symlinks is unsupported", ))?, @@ -487,37 +461,45 @@ impl EvalIO for TvixStoreIO { } #[instrument(skip(self), ret(level = Level::TRACE), err)] + fn file_type(&self, path: &Path) -> io::Result<FileType> { + if let Ok((store_path, sub_path)) = StorePath::from_absolute_path_full(path) { + if let Some(node) = self + .tokio_handle + .block_on(async { self.store_path_to_node(&store_path, sub_path).await })? + { + match node { + Node::Directory { .. } => Ok(FileType::Directory), + Node::File { .. } => Ok(FileType::Regular), + Node::Symlink { .. } => Ok(FileType::Symlink), + } + } else { + self.std_io.file_type(path) + } + } else { + self.std_io.file_type(path) + } + } + + #[instrument(skip(self), ret(level = Level::TRACE), err)] fn read_dir(&self, path: &Path) -> io::Result<Vec<(bytes::Bytes, FileType)>> { - if let Ok((store_path, sub_path)) = - StorePath::from_absolute_path_full(&path.to_string_lossy()) - { + if let Ok((store_path, sub_path)) = StorePath::from_absolute_path_full(path) { if let Some(node) = self .tokio_handle - .block_on(async { self.store_path_to_node(&store_path, &sub_path).await })? + .block_on(async { self.store_path_to_node(&store_path, sub_path).await })? { match node { - Node::Directory(directory_node) => { + Node::Directory { digest, .. } => { // fetch the Directory itself. - let digest: B3Digest = - directory_node.digest.clone().try_into().map_err(|_e| { - io::Error::new( - io::ErrorKind::InvalidData, - format!( - "invalid digest length in directory node: {:?}", - directory_node - ), - ) - })?; - - if let Some(directory) = self.tokio_handle.block_on(async { - self.directory_service.as_ref().get(&digest).await + if let Some(directory) = self.tokio_handle.block_on({ + let digest = digest.clone(); + async move { self.directory_service.as_ref().get(&digest).await } })? { let mut children: Vec<(bytes::Bytes, FileType)> = Vec::new(); - for node in directory.nodes() { + for (name, node) in directory.into_nodes() { children.push(match node { - Node::Directory(e) => (e.name, FileType::Directory), - Node::File(e) => (e.name, FileType::Regular), - Node::Symlink(e) => (e.name, FileType::Symlink), + Node::Directory { .. } => (name.into(), FileType::Directory), + Node::File { .. } => (name.clone().into(), FileType::Regular), + Node::Symlink { .. } => (name.into(), FileType::Symlink), }) } Ok(children) @@ -534,14 +516,14 @@ impl EvalIO for TvixStoreIO { ))? } } - Node::File(_file_node) => { + Node::File { .. } => { // This would normally be a io::ErrorKind::NotADirectory (still unstable) Err(io::Error::new( io::ErrorKind::Unsupported, "tried to readdir path {:?}, which is a file", ))? } - Node::Symlink(_symlink_node) => Err(io::Error::new( + Node::Symlink { .. } => Err(io::Error::new( io::ErrorKind::Unsupported, "read_dir for symlinks is unsupported", ))?, @@ -556,18 +538,19 @@ impl EvalIO for TvixStoreIO { #[instrument(skip(self), ret(level = Level::TRACE), err)] fn import_path(&self, path: &Path) -> io::Result<PathBuf> { - let output_path = self.tokio_handle.block_on(async { + let path_info = self.tokio_handle.block_on({ tvix_store::import::import_path_as_nar_ca( path, tvix_store::import::path_to_name(path)?, &self.blob_service, &self.directory_service, &self.path_info_service, + &self.nar_calculation_service, ) - .await })?; - Ok(output_path.to_absolute_path().into()) + // From the returned PathInfo, extract the store path and return it. + Ok(path_info.store_path.to_absolute_path().into()) } #[instrument(skip(self), ret(level = Level::TRACE))] @@ -581,14 +564,11 @@ mod tests { use std::{path::Path, rc::Rc, sync::Arc}; use bstr::ByteSlice; + use clap::Parser; use tempfile::TempDir; use tvix_build::buildservice::DummyBuildService; - use tvix_castore::{ - blobservice::{BlobService, MemoryBlobService}, - directoryservice::{DirectoryService, MemoryDirectoryService}, - }; use tvix_eval::{EvalIO, EvaluationResult}; - use tvix_store::pathinfoservice::MemoryPathInfoService; + use tvix_store::utils::{construct_services, ServiceUrlsMemory}; use super::TvixStoreIO; use crate::builtins::{add_derivation_builtins, add_fetcher_builtins, add_import_builtins}; @@ -597,28 +577,30 @@ mod tests { /// Takes care of setting up the evaluator so it knows about the // `derivation` builtin. fn eval(str: &str) -> EvaluationResult { - let blob_service = Arc::new(MemoryBlobService::default()) as Arc<dyn BlobService>; - let directory_service = - Arc::new(MemoryDirectoryService::default()) as Arc<dyn DirectoryService>; - let path_info_service = Arc::new(MemoryPathInfoService::new( - blob_service.clone(), - directory_service.clone(), - )); - - let runtime = tokio::runtime::Runtime::new().unwrap(); + let tokio_runtime = tokio::runtime::Runtime::new().unwrap(); + let (blob_service, directory_service, path_info_service, nar_calculation_service) = + tokio_runtime + .block_on(async { + construct_services(ServiceUrlsMemory::parse_from(std::iter::empty::<&str>())) + .await + }) + .unwrap(); let io = Rc::new(TvixStoreIO::new( - blob_service.clone(), - directory_service.clone(), + blob_service, + directory_service, path_info_service, + nar_calculation_service.into(), Arc::<DummyBuildService>::default(), - runtime.handle().clone(), + tokio_runtime.handle().clone(), )); - let mut eval = tvix_eval::Evaluation::new(io.clone() as Rc<dyn EvalIO>, true); - add_derivation_builtins(&mut eval, io.clone()); - add_fetcher_builtins(&mut eval, io.clone()); - add_import_builtins(&mut eval, io); + let mut eval_builder = + tvix_eval::Evaluation::builder(io.clone() as Rc<dyn EvalIO>).enable_import(); + eval_builder = add_derivation_builtins(eval_builder, Rc::clone(&io)); + eval_builder = add_fetcher_builtins(eval_builder, Rc::clone(&io)); + eval_builder = add_import_builtins(eval_builder, io); + let eval = eval_builder.build(); // run the evaluation itself. eval.evaluate(str, None) diff --git a/tvix/nar-bridge/.gitignore b/tvix/nar-bridge/.gitignore deleted file mode 100644 index d70e1f8120cc..000000000000 --- a/tvix/nar-bridge/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/nar-bridge-http -/nar-bridge-pathinfo diff --git a/tvix/nar-bridge/Cargo.toml b/tvix/nar-bridge/Cargo.toml new file mode 100644 index 000000000000..ac23b597311f --- /dev/null +++ b/tvix/nar-bridge/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "nar-bridge" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum = { workspace = true, features = ["http2"] } +axum-extra = { workspace = true } +axum-range = { workspace = true } +tower = { workspace = true } +tower-http = { workspace = true, features = ["trace"] } +bytes = { workspace = true } +clap = { workspace = true, features = ["derive", "env"] } +data-encoding = { workspace = true } +futures = { workspace = true } +itertools = { workspace = true } +prost = { workspace = true } +nix-compat = { path = "../nix-compat", features = ["async"] } +thiserror = { workspace = true } +tokio = { workspace = true } +tokio-listener = { workspace = true, features = ["axum07", "clap", "multi-listener", "sd_listen"] } +tokio-util = { workspace = true, features = ["io", "io-util", "compat"] } +tonic = { workspace = true, features = ["tls", "tls-roots"] } +tvix-castore = { path = "../castore" } +tvix-store = { path = "../store" } +tvix-tracing = { path = "../tracing", features = ["tonic", "axum"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } +url = { workspace = true } +serde = { workspace = true, features = ["derive"] } +lru = { workspace = true } +parking_lot = { workspace = true } +mimalloc = { workspace = true } + +[build-dependencies] +prost-build = { workspace = true } +tonic-build = { workspace = true } + +[features] +default = ["otlp"] +otlp = ["tvix-tracing/otlp"] + +[dev-dependencies] +hex-literal = { workspace = true } +rstest = { workspace = true } + +[lints] +workspace = true diff --git a/tvix/nar-bridge/README.md b/tvix/nar-bridge/README.md deleted file mode 100644 index b14ee7af7b10..000000000000 --- a/tvix/nar-bridge/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# //tvix/nar-bridge - -This exposes a HTTP Binary cache interface (GET/HEAD/PUT requests) for a `tvix- -store`. - -It can be used to configure a tvix-store as a substitutor for Nix, or to upload -store paths from Nix via `nix copy` into a `tvix-store`. diff --git a/tvix/nar-bridge/cmd/nar-bridge-http/main.go b/tvix/nar-bridge/cmd/nar-bridge-http/main.go deleted file mode 100644 index 171ea7f5bdd0..000000000000 --- a/tvix/nar-bridge/cmd/nar-bridge-http/main.go +++ /dev/null @@ -1,93 +0,0 @@ -package main - -import ( - "context" - "os" - "os/signal" - "runtime/debug" - "time" - - "github.com/alecthomas/kong" - - "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - - castorev1pb "code.tvl.fyi/tvix/castore-go" - narBridgeHttp "code.tvl.fyi/tvix/nar-bridge/pkg/http" - storev1pb "code.tvl.fyi/tvix/store-go" - log "github.com/sirupsen/logrus" -) - -// `help:"Expose a tvix-store gRPC Interface as HTTP NAR/NARinfo"` -var cli struct { - LogLevel string `enum:"trace,debug,info,warn,error,fatal,panic" help:"The log level to log with" default:"info"` - ListenAddr string `name:"listen-addr" help:"The address this service listens on" type:"string" default:"[::]:9000"` //nolint:lll - EnableAccessLog bool `name:"access-log" help:"Enable access logging" type:"bool" default:"true" negatable:""` //nolint:lll - StoreAddr string `name:"store-addr" help:"The address to the tvix-store RPC interface this will connect to" default:"localhost:8000"` //nolint:lll - EnableOtlp bool `name:"otlp" help:"Enable OpenTelemetry for logs, spans, and metrics" default:"true"` //nolint:lll -} - -func main() { - _ = kong.Parse(&cli) - - logLevel, err := log.ParseLevel(cli.LogLevel) - if err != nil { - log.Panic("invalid log level") - return - } - log.SetLevel(logLevel) - - ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) - defer stop() - - if cli.EnableOtlp { - buildInfo, ok := debug.ReadBuildInfo() - if !ok { - log.Fatal("failed to read build info") - } - - shutdown, err := setupOpenTelemetry(ctx, "nar-bridge", buildInfo.Main.Version) - if err != nil { - log.WithError(err).Fatal("failed to setup OpenTelemetry") - } - defer shutdown(context.Background()) - } - - // connect to tvix-store - log.Debugf("Dialing to %v", cli.StoreAddr) - conn, err := grpc.DialContext(ctx, cli.StoreAddr, - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithStatsHandler(otelgrpc.NewClientHandler()), - ) - if err != nil { - log.Fatalf("did not connect: %v", err) - } - defer conn.Close() - - s := narBridgeHttp.New( - castorev1pb.NewDirectoryServiceClient(conn), - castorev1pb.NewBlobServiceClient(conn), - storev1pb.NewPathInfoServiceClient(conn), - cli.EnableAccessLog, - 30, - ) - - log.Printf("Starting nar-bridge-http at %v", cli.ListenAddr) - go s.ListenAndServe(cli.ListenAddr) - - // listen for the interrupt signal. - <-ctx.Done() - - // Restore default behaviour on the interrupt signal - stop() - log.Info("Received Signal, shutting down, press Ctl+C again to force.") - - timeoutCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - if err := s.Shutdown(timeoutCtx); err != nil { - log.WithError(err).Warn("failed to shutdown") - os.Exit(1) - } -} diff --git a/tvix/nar-bridge/cmd/nar-bridge-http/otel.go b/tvix/nar-bridge/cmd/nar-bridge-http/otel.go deleted file mode 100644 index c446c6ec1a14..000000000000 --- a/tvix/nar-bridge/cmd/nar-bridge-http/otel.go +++ /dev/null @@ -1,87 +0,0 @@ -package main - -import ( - "context" - "errors" - - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" - "go.opentelemetry.io/otel/propagation" - "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/resource" - "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.24.0" -) - -func setupOpenTelemetry(ctx context.Context, serviceName, serviceVersion string) (func(context.Context) error, error) { - var shutdownFuncs []func(context.Context) error - shutdown := func(ctx context.Context) error { - var err error - for _, fn := range shutdownFuncs { - err = errors.Join(err, fn(ctx)) - } - shutdownFuncs = nil - return err - } - - res, err := resource.Merge( - resource.Default(), - resource.NewWithAttributes( - semconv.SchemaURL, - semconv.ServiceName(serviceName), - semconv.ServiceVersion(serviceVersion), - ), - ) - if err != nil { - return nil, errors.Join(err, shutdown(ctx)) - } - - prop := propagation.NewCompositeTextMapPropagator( - propagation.TraceContext{}, - propagation.Baggage{}, - ) - otel.SetTextMapPropagator(prop) - - tracerProvider, err := newTraceProvider(ctx, res) - if err != nil { - return nil, errors.Join(err, shutdown(ctx)) - } - shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) - otel.SetTracerProvider(tracerProvider) - - meterProvider, err := newMeterProvider(ctx, res) - if err != nil { - return nil, errors.Join(err, shutdown(ctx)) - } - shutdownFuncs = append(shutdownFuncs, meterProvider.Shutdown) - otel.SetMeterProvider(meterProvider) - - return shutdown, nil -} - -func newTraceProvider(ctx context.Context, res *resource.Resource) (*trace.TracerProvider, error) { - traceExporter, err := otlptracegrpc.New(ctx) - if err != nil { - return nil, err - } - - traceProvider := trace.NewTracerProvider( - trace.WithBatcher(traceExporter), - trace.WithResource(res), - ) - return traceProvider, nil -} - -func newMeterProvider(ctx context.Context, res *resource.Resource) (*metric.MeterProvider, error) { - metricExporter, err := otlpmetricgrpc.New(ctx) - if err != nil { - return nil, err - } - - meterProvider := metric.NewMeterProvider( - metric.WithResource(res), - metric.WithReader(metric.NewPeriodicReader(metricExporter)), - ) - return meterProvider, nil -} diff --git a/tvix/nar-bridge/default.nix b/tvix/nar-bridge/default.nix index c0247f279f32..2f1384e8211f 100644 --- a/tvix/nar-bridge/default.nix +++ b/tvix/nar-bridge/default.nix @@ -1,10 +1,11 @@ -# Target containing just the proto files. +{ depot, lib, ... }: -{ depot, pkgs, lib, ... }: - -pkgs.buildGoModule { - name = "nar-bridge"; - src = depot.third_party.gitignoreSource ./.; - - vendorHash = "sha256-7jugbC5sEGhppjiZgnoLP5A6kQSaHK9vE6cXVZBG22s="; -} +(depot.tvix.crates.workspaceMembers.nar-bridge.build.override { + runTests = true; +}).overrideAttrs (old: rec { + meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { + inherit (old) crateName; + features = [ "otlp" ]; + }); +}) diff --git a/tvix/nar-bridge/go.mod b/tvix/nar-bridge/go.mod deleted file mode 100644 index deb6943e23df..000000000000 --- a/tvix/nar-bridge/go.mod +++ /dev/null @@ -1,54 +0,0 @@ -module code.tvl.fyi/tvix/nar-bridge - -require ( - code.tvl.fyi/tvix/castore-go v0.0.0-20231105151352-990d6ba2175e - code.tvl.fyi/tvix/store-go v0.0.0-20231105203234-f2baad42494f - github.com/alecthomas/kong v0.7.1 - github.com/go-chi/chi v1.5.4 - github.com/go-chi/chi/v5 v5.0.7 - github.com/google/go-cmp v0.6.0 - github.com/multiformats/go-multihash v0.2.1 - github.com/nix-community/go-nix v0.0.0-20231012070617-9b176785e54d - github.com/sirupsen/logrus v1.9.0 - github.com/stretchr/testify v1.8.4 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 - go.opentelemetry.io/otel v1.22.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.45.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 - go.opentelemetry.io/otel/sdk v1.22.0 - go.opentelemetry.io/otel/sdk/metric v1.22.0 - golang.org/x/sync v0.4.0 - google.golang.org/grpc v1.60.1 - google.golang.org/protobuf v1.32.0 - lukechampine.com/blake3 v1.2.1 -) - -require ( - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.1 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect - github.com/minio/sha256-simd v1.0.0 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect - github.com/multiformats/go-varint v0.0.6 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect - go.opentelemetry.io/otel/metric v1.22.0 // indirect - go.opentelemetry.io/otel/trace v1.22.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect - golang.org/x/crypto v0.18.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) - -go 1.19 diff --git a/tvix/nar-bridge/go.sum b/tvix/nar-bridge/go.sum deleted file mode 100644 index 39f77b906128..000000000000 --- a/tvix/nar-bridge/go.sum +++ /dev/null @@ -1,120 +0,0 @@ -cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -code.tvl.fyi/tvix/castore-go v0.0.0-20231105151352-990d6ba2175e h1:Nj+anfyEYeEdhnIo2BG/N1ZwQl1IvI7AH3TbNDLwUOA= -code.tvl.fyi/tvix/castore-go v0.0.0-20231105151352-990d6ba2175e/go.mod h1:+vKbozsa04yy2TWh3kUVU568jaza3Hf0p1jAEoMoCwA= -code.tvl.fyi/tvix/store-go v0.0.0-20231105203234-f2baad42494f h1:bN3K7oSu3IAHXqS3ETHUgpBPHF9+awKKBRLiM8/1tmI= -code.tvl.fyi/tvix/store-go v0.0.0-20231105203234-f2baad42494f/go.mod h1:8jpfSC2rGi6VKaKOqqgmflPVSEpUawuRQFwQpQYCMiA= -github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0= -github.com/alecthomas/kong v0.7.1 h1:azoTh0IOfwlAX3qN9sHWTxACE2oV8Bg2gAwBsMwDQY4= -github.com/alecthomas/kong v0.7.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U= -github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= -github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= -github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= -github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= -github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= -github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= -github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= -github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/nix-community/go-nix v0.0.0-20231012070617-9b176785e54d h1:kwc1ivTuStqa3iBC2M/ojWPor88+YeIbZGeD2SlMYZ0= -github.com/nix-community/go-nix v0.0.0-20231012070617-9b176785e54d/go.mod h1:4ZJah5sYrUSsWXIOJIsQ6iVOQyLO+ffhWXU3gblcO+E= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= -go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.45.0 h1:tfil6di0PoNV7FZdsCS7A5izZoVVQ7AuXtyekbOpG/I= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.45.0/go.mod h1:AKFZIEPOnqB00P63bTjOiah4ZTaRzl1TKwUWpZdYUHI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= -go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= -go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/sdk/metric v1.22.0 h1:ARrRetm1HCVxq0cbnaZQlfwODYJHo3gFL8Z3tSmHBcI= -go.opentelemetry.io/otel/sdk/metric v1.22.0/go.mod h1:KjQGeMIDlBNEOo6HvjhxIec1p/69/kULDcp4gr0oLQQ= -go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= -lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= diff --git a/tvix/nar-bridge/pkg/http/nar_get.go b/tvix/nar-bridge/pkg/http/nar_get.go deleted file mode 100644 index 75797f8da90e..000000000000 --- a/tvix/nar-bridge/pkg/http/nar_get.go +++ /dev/null @@ -1,197 +0,0 @@ -package http - -import ( - "bytes" - "context" - "encoding/base64" - "encoding/hex" - "errors" - "fmt" - "io" - "io/fs" - "net/http" - "sync" - - castorev1pb "code.tvl.fyi/tvix/castore-go" - storev1pb "code.tvl.fyi/tvix/store-go" - "github.com/go-chi/chi/v5" - nixhash "github.com/nix-community/go-nix/pkg/hash" - "github.com/nix-community/go-nix/pkg/nixbase32" - log "github.com/sirupsen/logrus" -) - -const ( - narUrl = "/nar/{narhash:^([" + nixbase32.Alphabet + "]{52})$}.nar" -) - -func renderNar( - ctx context.Context, - log *log.Entry, - directoryServiceClient castorev1pb.DirectoryServiceClient, - blobServiceClient castorev1pb.BlobServiceClient, - narHashDbMu *sync.Mutex, - narHashDb map[string]*narData, - w io.Writer, - narHash *nixhash.Hash, - headOnly bool, -) error { - // look in the lookup table - narHashDbMu.Lock() - narData, found := narHashDb[narHash.SRIString()] - narHashDbMu.Unlock() - - rootNode := narData.rootNode - - // if we didn't find anything, return 404. - if !found { - return fmt.Errorf("narHash not found: %w", fs.ErrNotExist) - } - - // if this was only a head request, we're done. - if headOnly { - return nil - } - - directories := make(map[string]*castorev1pb.Directory) - - // If the root node is a directory, ask the directory service for all directories - if pathInfoDirectory := rootNode.GetDirectory(); pathInfoDirectory != nil { - rootDirectoryDigest := pathInfoDirectory.GetDigest() - log = log.WithField("root_directory", base64.StdEncoding.EncodeToString(rootDirectoryDigest)) - - directoryStream, err := directoryServiceClient.Get(ctx, &castorev1pb.GetDirectoryRequest{ - ByWhat: &castorev1pb.GetDirectoryRequest_Digest{ - Digest: rootDirectoryDigest, - }, - Recursive: true, - }) - if err != nil { - return fmt.Errorf("unable to query directory stream: %w", err) - } - - // For now, we just stream all of these locally and put them into a hashmap, - // which is used in the lookup function below. - for { - directory, err := directoryStream.Recv() - if err != nil { - if err == io.EOF { - break - } - return fmt.Errorf("unable to receive from directory stream: %w", err) - } - - // calculate directory digest - // TODO: do we need to do any more validation? - directoryDgst, err := directory.Digest() - if err != nil { - return fmt.Errorf("unable to calculate directory digest: %w", err) - } - - log.WithField("directory", base64.StdEncoding.EncodeToString(directoryDgst)).Debug("received directory node") - - directories[hex.EncodeToString(directoryDgst)] = directory - } - - } - - // render the NAR file - err := storev1pb.Export( - w, - rootNode, - func(directoryDigest []byte) (*castorev1pb.Directory, error) { - log.WithField("directory", base64.StdEncoding.EncodeToString(directoryDigest)).Debug("Get directory") - directoryRefStr := hex.EncodeToString(directoryDigest) - directory, found := directories[directoryRefStr] - if !found { - return nil, fmt.Errorf( - "directory with hash %v does not exist: %w", - directoryDigest, - fs.ErrNotExist, - ) - } - - return directory, nil - }, - func(blobDigest []byte) (io.ReadCloser, error) { - log.WithField("blob", base64.StdEncoding.EncodeToString(blobDigest)).Debug("Get blob") - resp, err := blobServiceClient.Read(ctx, &castorev1pb.ReadBlobRequest{ - Digest: blobDigest, - }) - if err != nil { - return nil, fmt.Errorf("unable to get blob: %w", err) - } - - // set up a pipe, let a goroutine write, return the reader. - pR, pW := io.Pipe() - - go func() { - for { - chunk, err := resp.Recv() - if errors.Is(err, io.EOF) { - break - } - if err != nil { - pW.CloseWithError(fmt.Errorf("receiving chunk: %w", err)) - return - } - - // write the received chunk to the writer part of the pipe - if _, err := io.Copy(pW, bytes.NewReader(chunk.GetData())); err != nil { - log.WithError(err).Error("writing chunk to pipe") - pW.CloseWithError(fmt.Errorf("writing chunk to pipe: %w", err)) - return - } - } - pW.Close() - - }() - - return io.NopCloser(pR), nil - }, - ) - if err != nil { - return fmt.Errorf("unable to export nar: %w", err) - } - return nil -} - -func registerNarGet(s *Server) { - // produce a handler for rendering NAR files. - genNarHandler := func(isHead bool) func(w http.ResponseWriter, r *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - defer r.Body.Close() - - ctx := r.Context() - - // parse the narhash sent in the request URL - narHash, err := parseNarHashFromUrl(chi.URLParamFromCtx(ctx, "narhash")) - if err != nil { - log.WithError(err).WithField("url", r.URL).Error("unable to decode nar hash from url") - w.WriteHeader(http.StatusBadRequest) - _, err := w.Write([]byte("unable to decode nar hash from url")) - if err != nil { - log.WithError(err).Errorf("unable to write error message to client") - } - - return - } - - log := log.WithField("narhash_url", narHash.SRIString()) - - // TODO: inline more of that function here? - err = renderNar(ctx, log, s.directoryServiceClient, s.blobServiceClient, &s.narDbMu, s.narDb, w, narHash, isHead) - if err != nil { - if errors.Is(err, fs.ErrNotExist) { - w.WriteHeader(http.StatusNotFound) - } else { - log.WithError(err).Warn("unable to render nar") - w.WriteHeader(http.StatusInternalServerError) - } - } - - } - } - - s.handler.Head(narUrl, genNarHandler(true)) - s.handler.Get(narUrl, genNarHandler(false)) -} diff --git a/tvix/nar-bridge/pkg/http/nar_put.go b/tvix/nar-bridge/pkg/http/nar_put.go deleted file mode 100644 index fdfa20f9c396..000000000000 --- a/tvix/nar-bridge/pkg/http/nar_put.go +++ /dev/null @@ -1,141 +0,0 @@ -package http - -import ( - "bufio" - "bytes" - "fmt" - "net/http" - - castorev1pb "code.tvl.fyi/tvix/castore-go" - "code.tvl.fyi/tvix/nar-bridge/pkg/importer" - "github.com/go-chi/chi/v5" - mh "github.com/multiformats/go-multihash/core" - nixhash "github.com/nix-community/go-nix/pkg/hash" - "github.com/sirupsen/logrus" - log "github.com/sirupsen/logrus" -) - -func registerNarPut(s *Server) { - s.handler.Put(narUrl, func(w http.ResponseWriter, r *http.Request) { - defer r.Body.Close() - - ctx := r.Context() - - // parse the narhash sent in the request URL - narHashFromUrl, err := parseNarHashFromUrl(chi.URLParamFromCtx(ctx, "narhash")) - if err != nil { - log.WithError(err).WithField("url", r.URL).Error("unable to decode nar hash from url") - w.WriteHeader(http.StatusBadRequest) - _, err := w.Write([]byte("unable to decode nar hash from url")) - if err != nil { - log.WithError(err).Error("unable to write error message to client") - } - - return - } - - log := log.WithField("narhash_url", narHashFromUrl.SRIString()) - - directoriesUploader := importer.NewDirectoriesUploader(ctx, s.directoryServiceClient) - defer directoriesUploader.Done() //nolint:errcheck - - rootNode, narSize, narSha256, err := importer.Import( - ctx, - // buffer the body by 10MiB - bufio.NewReaderSize(r.Body, 10*1024*1024), - importer.GenBlobUploaderCb(ctx, s.blobServiceClient), - func(directory *castorev1pb.Directory) ([]byte, error) { - return directoriesUploader.Put(directory) - }, - ) - - if err != nil { - log.Errorf("error during NAR import: %v", err) - w.WriteHeader(http.StatusInternalServerError) - _, err := w.Write([]byte(fmt.Sprintf("error during NAR import: %v", err))) - if err != nil { - log.WithError(err).Errorf("unable to write error message to client") - } - - return - } - - log.Debug("closing the stream") - - // Close the directories uploader - directoriesPutResponse, err := directoriesUploader.Done() - if err != nil { - log.WithError(err).Error("error during directory upload") - w.WriteHeader(http.StatusBadRequest) - _, err := w.Write([]byte("error during directory upload")) - if err != nil { - log.WithError(err).Errorf("unable to write error message to client") - } - - return - } - // If we uploaded directories (so directoriesPutResponse doesn't return null), - // the RootDigest field in directoriesPutResponse should match the digest - // returned in the PathInfo struct returned by the `Import` call. - // This check ensures the server-side came up with the same root hash. - - if directoriesPutResponse != nil { - rootDigestPathInfo := rootNode.GetDirectory().GetDigest() - rootDigestDirectoriesPutResponse := directoriesPutResponse.GetRootDigest() - - log := log.WithFields(logrus.Fields{ - "root_digest_pathinfo": rootDigestPathInfo, - "root_digest_directories_put_resp": rootDigestDirectoriesPutResponse, - }) - if !bytes.Equal(rootDigestPathInfo, rootDigestDirectoriesPutResponse) { - log.Errorf("returned root digest doesn't match what's calculated") - - w.WriteHeader(http.StatusBadRequest) - _, err := w.Write([]byte("error in root digest calculation")) - if err != nil { - log.WithError(err).Error("unable to write error message to client") - } - - return - } - } - - // Compare the nar hash specified in the URL with the one that has been - // calculated while processing the NAR file. - narHash, err := nixhash.FromHashTypeAndDigest(mh.SHA2_256, narSha256) - if err != nil { - panic("must parse nixbase32") - } - - if !bytes.Equal(narHashFromUrl.Digest(), narHash.Digest()) { - log := log.WithFields(logrus.Fields{ - "narhash_received_sha256": narHash.SRIString(), - "narsize": narSize, - }) - log.Error("received bytes don't match narhash from URL") - - w.WriteHeader(http.StatusBadRequest) - _, err := w.Write([]byte("received bytes don't match narHash specified in URL")) - if err != nil { - log.WithError(err).Errorf("unable to write error message to client") - } - - return - } - - // Insert the partial pathinfo structs into our lookup map, - // so requesting the NAR file will be possible. - // The same might exist already, but it'll have the same contents (so - // replacing will be a no-op), except maybe the root node Name field value, which - // is safe to ignore (as not part of the NAR). - s.narDbMu.Lock() - s.narDb[narHash.SRIString()] = &narData{ - rootNode: rootNode, - narSize: narSize, - } - s.narDbMu.Unlock() - - // Done! - }) - -} diff --git a/tvix/nar-bridge/pkg/http/narinfo.go b/tvix/nar-bridge/pkg/http/narinfo.go deleted file mode 100644 index e5b99a9505f1..000000000000 --- a/tvix/nar-bridge/pkg/http/narinfo.go +++ /dev/null @@ -1,51 +0,0 @@ -package http - -import ( - "fmt" - - storev1pb "code.tvl.fyi/tvix/store-go" - mh "github.com/multiformats/go-multihash/core" - nixhash "github.com/nix-community/go-nix/pkg/hash" - - "github.com/nix-community/go-nix/pkg/narinfo" - "github.com/nix-community/go-nix/pkg/narinfo/signature" - "github.com/nix-community/go-nix/pkg/nixbase32" -) - -// ToNixNarInfo converts the PathInfo to a narinfo.NarInfo. -func ToNixNarInfo(p *storev1pb.PathInfo) (*narinfo.NarInfo, error) { - // ensure the PathInfo is valid, and extract the StorePath from the node in - // there. - storePath, err := p.Validate() - if err != nil { - return nil, fmt.Errorf("failed to validate PathInfo: %w", err) - } - - // convert the signatures from storev1pb signatures to narinfo signatures - narinfoSignatures := make([]signature.Signature, len(p.GetNarinfo().GetSignatures())) - for i, pathInfoSignature := range p.GetNarinfo().GetSignatures() { - narinfoSignatures[i] = signature.Signature{ - Name: pathInfoSignature.GetName(), - Data: pathInfoSignature.GetData(), - } - } - - // produce nixhash for the narsha256. - narHash, err := nixhash.FromHashTypeAndDigest( - mh.SHA2_256, - p.GetNarinfo().GetNarSha256(), - ) - if err != nil { - return nil, fmt.Errorf("invalid narsha256: %w", err) - } - - return &narinfo.NarInfo{ - StorePath: storePath.Absolute(), - URL: "nar/" + nixbase32.EncodeToString(narHash.Digest()) + ".nar", - Compression: "none", - NarHash: narHash, - NarSize: uint64(p.GetNarinfo().GetNarSize()), - References: p.GetNarinfo().GetReferenceNames(), - Signatures: narinfoSignatures, - }, nil -} diff --git a/tvix/nar-bridge/pkg/http/narinfo_get.go b/tvix/nar-bridge/pkg/http/narinfo_get.go deleted file mode 100644 index 98d85744d895..000000000000 --- a/tvix/nar-bridge/pkg/http/narinfo_get.go +++ /dev/null @@ -1,132 +0,0 @@ -package http - -import ( - "context" - "encoding/base64" - "errors" - "fmt" - "io" - "io/fs" - "net/http" - "strings" - "sync" - - storev1pb "code.tvl.fyi/tvix/store-go" - "github.com/go-chi/chi/v5" - nixhash "github.com/nix-community/go-nix/pkg/hash" - "github.com/nix-community/go-nix/pkg/nixbase32" - log "github.com/sirupsen/logrus" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// renderNarinfo writes narinfo contents to a passed io.Writer, or a returns a -// (wrapped) io.ErrNoExist error if something doesn't exist. -// if headOnly is set to true, only the existence is checked, but no content is -// actually written. -func renderNarinfo( - ctx context.Context, - log *log.Entry, - pathInfoServiceClient storev1pb.PathInfoServiceClient, - narHashToPathInfoMu *sync.Mutex, - narHashToPathInfo map[string]*narData, - outputHash []byte, - w io.Writer, - headOnly bool, -) error { - pathInfo, err := pathInfoServiceClient.Get(ctx, &storev1pb.GetPathInfoRequest{ - ByWhat: &storev1pb.GetPathInfoRequest_ByOutputHash{ - ByOutputHash: outputHash, - }, - }) - if err != nil { - st, ok := status.FromError(err) - if ok { - if st.Code() == codes.NotFound { - return fmt.Errorf("output hash %v not found: %w", base64.StdEncoding.EncodeToString(outputHash), fs.ErrNotExist) - } - return fmt.Errorf("unable to get pathinfo, code %v: %w", st.Code(), err) - } - - return fmt.Errorf("unable to get pathinfo: %w", err) - } - - log = log.WithField("pathInfo", pathInfo) - - if _, err := pathInfo.Validate(); err != nil { - log.WithError(err).Error("unable to validate PathInfo") - - return fmt.Errorf("unable to validate PathInfo: %w", err) - } - - if pathInfo.GetNarinfo() == nil { - log.Error("PathInfo doesn't contain Narinfo field") - - return fmt.Errorf("PathInfo doesn't contain Narinfo field") - } - - // extract the NARHash. This must succeed, as Validate() did succeed. - narHash, err := nixhash.FromHashTypeAndDigest(0x12, pathInfo.GetNarinfo().GetNarSha256()) - if err != nil { - panic("must parse NarHash") - } - - // add things to the lookup table, in case the same process didn't handle the NAR hash yet. - narHashToPathInfoMu.Lock() - narHashToPathInfo[narHash.SRIString()] = &narData{ - rootNode: pathInfo.GetNode(), - narSize: pathInfo.GetNarinfo().GetNarSize(), - } - narHashToPathInfoMu.Unlock() - - if headOnly { - return nil - } - - // convert the PathInfo to NARInfo. - narInfo, err := ToNixNarInfo(pathInfo) - - // Write it out to the client. - _, err = io.Copy(w, strings.NewReader(narInfo.String())) - if err != nil { - return fmt.Errorf("unable to write narinfo to client: %w", err) - } - - return nil -} - -func registerNarinfoGet(s *Server) { - // GET $outHash.narinfo looks up the PathInfo from the tvix-store, - // and then render a .narinfo file to the client. - // It will keep the PathInfo in the lookup map, - // so a subsequent GET /nar/ $narhash.nar request can find it. - s.handler.Get("/{outputhash:^["+nixbase32.Alphabet+"]{32}}.narinfo", func(w http.ResponseWriter, r *http.Request) { - defer r.Body.Close() - - ctx := r.Context() - log := log.WithField("outputhash", chi.URLParamFromCtx(ctx, "outputhash")) - - // parse the output hash sent in the request URL - outputHash, err := nixbase32.DecodeString(chi.URLParamFromCtx(ctx, "outputhash")) - if err != nil { - log.WithError(err).Error("unable to decode output hash from url") - w.WriteHeader(http.StatusBadRequest) - _, err := w.Write([]byte("unable to decode output hash from url")) - if err != nil { - log.WithError(err).Errorf("unable to write error message to client") - } - - return - } - - err = renderNarinfo(ctx, log, s.pathInfoServiceClient, &s.narDbMu, s.narDb, outputHash, w, false) - if err != nil { - if errors.Is(err, fs.ErrNotExist) { - w.WriteHeader(http.StatusNotFound) - } else { - log.WithError(err).Warn("unable to render narinfo") - w.WriteHeader(http.StatusInternalServerError) - } - } - }) -} diff --git a/tvix/nar-bridge/pkg/http/narinfo_put.go b/tvix/nar-bridge/pkg/http/narinfo_put.go deleted file mode 100644 index fd588bec8644..000000000000 --- a/tvix/nar-bridge/pkg/http/narinfo_put.go +++ /dev/null @@ -1,103 +0,0 @@ -package http - -import ( - "net/http" - - "code.tvl.fyi/tvix/nar-bridge/pkg/importer" - "github.com/go-chi/chi/v5" - "github.com/nix-community/go-nix/pkg/narinfo" - "github.com/nix-community/go-nix/pkg/nixbase32" - "github.com/sirupsen/logrus" - log "github.com/sirupsen/logrus" -) - -func registerNarinfoPut(s *Server) { - s.handler.Put("/{outputhash:^["+nixbase32.Alphabet+"]{32}}.narinfo", func(w http.ResponseWriter, r *http.Request) { - defer r.Body.Close() - - ctx := r.Context() - log := log.WithField("outputhash", chi.URLParamFromCtx(ctx, "outputhash")) - - // TODO: decide on merging behaviour. - // Maybe it's fine to add if contents are the same, but more sigs can be added? - // Right now, just replace a .narinfo for a path that already exists. - - // read and parse the .narinfo file - narInfo, err := narinfo.Parse(r.Body) - if err != nil { - log.WithError(err).Error("unable to parse narinfo") - w.WriteHeader(http.StatusBadRequest) - _, err := w.Write([]byte("unable to parse narinfo")) - if err != nil { - log.WithError(err).Errorf("unable to write error message to client") - } - - return - } - - log = log.WithFields(logrus.Fields{ - "narhash": narInfo.NarHash.SRIString(), - "output_path": narInfo.StorePath, - }) - - // look up the narHash in our temporary map - s.narDbMu.Lock() - narData, found := s.narDb[narInfo.NarHash.SRIString()] - s.narDbMu.Unlock() - if !found { - log.Error("unable to find referred NAR") - w.WriteHeader(http.StatusBadRequest) - _, err := w.Write([]byte("unable to find referred NAR")) - if err != nil { - log.WithError(err).Errorf("unable to write error message to client") - } - - return - } - - rootNode := narData.rootNode - - // compare fields with what we computed while receiving the NAR file - - // NarSize needs to match - if narData.narSize != narInfo.NarSize { - log.Error("narsize mismatch") - w.WriteHeader(http.StatusBadRequest) - _, err := w.Write([]byte("unable to parse narinfo")) - if err != nil { - log.WithError(err).Errorf("unable to write error message to client") - } - - return - } - - pathInfo, err := importer.GenPathInfo(rootNode, narInfo) - if err != nil { - log.WithError(err).Error("unable to generate PathInfo") - - w.WriteHeader(http.StatusInternalServerError) - _, err := w.Write([]byte("unable to generate PathInfo")) - if err != nil { - log.WithError(err).Errorf("unable to write error message to client") - } - - return - } - - log.WithField("pathInfo", pathInfo).Debug("inserted new pathInfo") - - receivedPathInfo, err := s.pathInfoServiceClient.Put(ctx, pathInfo) - if err != nil { - log.WithError(err).Error("unable to upload pathinfo to service") - w.WriteHeader(http.StatusInternalServerError) - _, err := w.Write([]byte("unable to upload pathinfo to server")) - if err != nil { - log.WithError(err).Errorf("unable to write error message to client") - } - - return - } - - log.WithField("pathInfo", receivedPathInfo).Debug("got back PathInfo") - }) -} diff --git a/tvix/nar-bridge/pkg/http/server.go b/tvix/nar-bridge/pkg/http/server.go deleted file mode 100644 index fbcb20be18b7..000000000000 --- a/tvix/nar-bridge/pkg/http/server.go +++ /dev/null @@ -1,119 +0,0 @@ -package http - -import ( - "context" - "fmt" - "net" - "net/http" - "strings" - "sync" - "time" - - castorev1pb "code.tvl.fyi/tvix/castore-go" - storev1pb "code.tvl.fyi/tvix/store-go" - "github.com/go-chi/chi/middleware" - "github.com/go-chi/chi/v5" - log "github.com/sirupsen/logrus" - "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" -) - -type Server struct { - srv *http.Server - handler chi.Router - - directoryServiceClient castorev1pb.DirectoryServiceClient - blobServiceClient castorev1pb.BlobServiceClient - pathInfoServiceClient storev1pb.PathInfoServiceClient - - // When uploading NAR files to a HTTP binary cache, the .nar - // files are uploaded before the .narinfo files. - // We need *both* to be able to fully construct a PathInfo object. - // Keep a in-memory map of narhash(es) (in SRI) to (unnamed) root node and nar - // size. - // This is necessary until we can ask a PathInfoService for a node with a given - // narSha256. - narDbMu sync.Mutex - narDb map[string]*narData -} - -type narData struct { - rootNode *castorev1pb.Node - narSize uint64 -} - -func New( - directoryServiceClient castorev1pb.DirectoryServiceClient, - blobServiceClient castorev1pb.BlobServiceClient, - pathInfoServiceClient storev1pb.PathInfoServiceClient, - enableAccessLog bool, - priority int, -) *Server { - r := chi.NewRouter() - r.Use(func(h http.Handler) http.Handler { - return otelhttp.NewHandler(h, "http.request") - }) - - if enableAccessLog { - r.Use(middleware.Logger) - } - - r.Get("/", func(w http.ResponseWriter, r *http.Request) { - _, err := w.Write([]byte("nar-bridge")) - if err != nil { - log.Errorf("Unable to write response: %v", err) - } - }) - - r.Get("/nix-cache-info", func(w http.ResponseWriter, r *http.Request) { - _, err := w.Write([]byte(fmt.Sprintf("StoreDir: /nix/store\nWantMassQuery: 1\nPriority: %d\n", priority))) - if err != nil { - log.Errorf("Unable to write response: %v", err) - } - }) - - s := &Server{ - handler: r, - directoryServiceClient: directoryServiceClient, - blobServiceClient: blobServiceClient, - pathInfoServiceClient: pathInfoServiceClient, - narDb: make(map[string]*narData), - } - - registerNarPut(s) - registerNarinfoPut(s) - - registerNarinfoGet(s) - registerNarGet(s) - - return s -} - -func (s *Server) Shutdown(ctx context.Context) error { - return s.srv.Shutdown(ctx) -} - -// ListenAndServer starts the webserver, and waits for it being closed or -// shutdown, after which it'll return ErrServerClosed. -func (s *Server) ListenAndServe(addr string) error { - s.srv = &http.Server{ - Handler: s.handler, - ReadTimeout: 500 * time.Second, - WriteTimeout: 500 * time.Second, - IdleTimeout: 500 * time.Second, - } - - var listener net.Listener - var err error - - // check addr. If it contains slashes, assume it's a unix domain socket. - if strings.Contains(addr, "/") { - listener, err = net.Listen("unix", addr) - } else { - listener, err = net.Listen("tcp", addr) - } - if err != nil { - return fmt.Errorf("unable to listen on %v: %w", addr, err) - } - - return s.srv.Serve(listener) -} diff --git a/tvix/nar-bridge/pkg/http/util.go b/tvix/nar-bridge/pkg/http/util.go deleted file mode 100644 index 60febea1f430..000000000000 --- a/tvix/nar-bridge/pkg/http/util.go +++ /dev/null @@ -1,24 +0,0 @@ -package http - -import ( - "fmt" - nixhash "github.com/nix-community/go-nix/pkg/hash" -) - -// parseNarHashFromUrl parses a nixbase32 string representing a sha256 NarHash -// and returns a nixhash.Hash when it was able to parse, or an error. -func parseNarHashFromUrl(narHashFromUrl string) (*nixhash.Hash, error) { - // peek at the length. If it's 52 characters, assume sha256, - // if it's something else, this is an error. - l := len(narHashFromUrl) - if l != 52 { - return nil, fmt.Errorf("invalid length of narHash: %v", l) - } - - nixHash, err := nixhash.ParseNixBase32("sha256:" + narHashFromUrl) - if err != nil { - return nil, fmt.Errorf("unable to parse nixbase32 hash: %w", err) - } - - return nixHash, nil -} diff --git a/tvix/nar-bridge/pkg/importer/blob_upload.go b/tvix/nar-bridge/pkg/importer/blob_upload.go deleted file mode 100644 index c1255dd3ad5d..000000000000 --- a/tvix/nar-bridge/pkg/importer/blob_upload.go +++ /dev/null @@ -1,71 +0,0 @@ -package importer - -import ( - "bufio" - "context" - "encoding/base64" - "errors" - "fmt" - "io" - - castorev1pb "code.tvl.fyi/tvix/castore-go" - log "github.com/sirupsen/logrus" -) - -// the size of individual BlobChunk we send when uploading to BlobService. -const chunkSize = 1024 * 1024 - -// this produces a callback function that can be used as blobCb for the -// importer.Import function call. -func GenBlobUploaderCb(ctx context.Context, blobServiceClient castorev1pb.BlobServiceClient) func(io.Reader) ([]byte, error) { - return func(blobReader io.Reader) ([]byte, error) { - // Ensure the blobReader is buffered to at least the chunk size. - blobReader = bufio.NewReaderSize(blobReader, chunkSize) - - putter, err := blobServiceClient.Put(ctx) - if err != nil { - // return error to the importer - return nil, fmt.Errorf("error from blob service: %w", err) - } - - blobSize := 0 - chunk := make([]byte, chunkSize) - - for { - n, err := blobReader.Read(chunk) - if err != nil && !errors.Is(err, io.EOF) { - return nil, fmt.Errorf("unable to read from blobreader: %w", err) - } - - if n != 0 { - log.WithField("chunk_size", n).Debug("sending chunk") - blobSize += n - - // send the blob chunk to the server. The err is only valid in the inner scope - if err := putter.Send(&castorev1pb.BlobChunk{ - Data: chunk[:n], - }); err != nil { - return nil, fmt.Errorf("sending blob chunk: %w", err) - } - } - - // if our read from blobReader returned an EOF, we're done reading - if errors.Is(err, io.EOF) { - break - } - - } - - resp, err := putter.CloseAndRecv() - if err != nil { - return nil, fmt.Errorf("close blob putter: %w", err) - } - - log.WithFields(log.Fields{ - "blob_digest": base64.StdEncoding.EncodeToString(resp.GetDigest()), - "blob_size": blobSize, - }).Debug("uploaded blob") - - return resp.GetDigest(), nil - } -} diff --git a/tvix/nar-bridge/pkg/importer/counting_writer.go b/tvix/nar-bridge/pkg/importer/counting_writer.go deleted file mode 100644 index d003a4b11bfd..000000000000 --- a/tvix/nar-bridge/pkg/importer/counting_writer.go +++ /dev/null @@ -1,21 +0,0 @@ -package importer - -import ( - "io" -) - -// CountingWriter implements io.Writer. -var _ io.Writer = &CountingWriter{} - -type CountingWriter struct { - bytesWritten uint64 -} - -func (cw *CountingWriter) Write(p []byte) (n int, err error) { - cw.bytesWritten += uint64(len(p)) - return len(p), nil -} - -func (cw *CountingWriter) BytesWritten() uint64 { - return cw.bytesWritten -} diff --git a/tvix/nar-bridge/pkg/importer/directory_upload.go b/tvix/nar-bridge/pkg/importer/directory_upload.go deleted file mode 100644 index 117f442fa54f..000000000000 --- a/tvix/nar-bridge/pkg/importer/directory_upload.go +++ /dev/null @@ -1,88 +0,0 @@ -package importer - -import ( - "bytes" - "context" - "encoding/base64" - "fmt" - - castorev1pb "code.tvl.fyi/tvix/castore-go" - log "github.com/sirupsen/logrus" -) - -// DirectoriesUploader opens a Put stream when it receives the first Put() call, -// and then uses the opened stream for subsequent Put() calls. -// When the uploading is finished, a call to Done() will close the stream and -// return the root digest returned from the directoryServiceClient. -type DirectoriesUploader struct { - ctx context.Context - directoryServiceClient castorev1pb.DirectoryServiceClient - directoryServicePutStream castorev1pb.DirectoryService_PutClient - lastDirectoryDigest []byte -} - -func NewDirectoriesUploader(ctx context.Context, directoryServiceClient castorev1pb.DirectoryServiceClient) *DirectoriesUploader { - return &DirectoriesUploader{ - ctx: ctx, - directoryServiceClient: directoryServiceClient, - directoryServicePutStream: nil, - } -} - -func (du *DirectoriesUploader) Put(directory *castorev1pb.Directory) ([]byte, error) { - directoryDigest, err := directory.Digest() - if err != nil { - return nil, fmt.Errorf("failed calculating directory digest: %w", err) - } - - // Send the directory to the directory service - // If the stream hasn't been initialized yet, do it first - if du.directoryServicePutStream == nil { - directoryServicePutStream, err := du.directoryServiceClient.Put(du.ctx) - if err != nil { - return nil, fmt.Errorf("unable to initialize directory service put stream: %v", err) - } - du.directoryServicePutStream = directoryServicePutStream - } - - // send the directory out - err = du.directoryServicePutStream.Send(directory) - if err != nil { - return nil, fmt.Errorf("error sending directory: %w", err) - } - log.WithField("digest", base64.StdEncoding.EncodeToString(directoryDigest)).Debug("uploaded directory") - - // update lastDirectoryDigest - du.lastDirectoryDigest = directoryDigest - - return directoryDigest, nil -} - -// Done closes the stream and returns the response. -// It returns null if closed for a second time. -func (du *DirectoriesUploader) Done() (*castorev1pb.PutDirectoryResponse, error) { - // only close once, and only if we opened. - if du.directoryServicePutStream == nil { - return nil, nil - } - - putDirectoryResponse, err := du.directoryServicePutStream.CloseAndRecv() - if err != nil { - return nil, fmt.Errorf("unable to close directory service put stream: %v", err) - } - - // ensure the response contains the same digest as the one we have in lastDirectoryDigest. - // Otherwise, the backend came up with another digest than we, in which we return an error. - if !bytes.Equal(du.lastDirectoryDigest, putDirectoryResponse.RootDigest) { - return nil, fmt.Errorf( - "backend calculated different root digest as we, expected %s, actual %s", - base64.StdEncoding.EncodeToString(du.lastDirectoryDigest), - base64.StdEncoding.EncodeToString(putDirectoryResponse.RootDigest), - ) - } - - // clear directoryServicePutStream. - du.directoryServicePutStream = nil - - return putDirectoryResponse, nil -} diff --git a/tvix/nar-bridge/pkg/importer/gen_pathinfo.go b/tvix/nar-bridge/pkg/importer/gen_pathinfo.go deleted file mode 100644 index bdc298a9a399..000000000000 --- a/tvix/nar-bridge/pkg/importer/gen_pathinfo.go +++ /dev/null @@ -1,62 +0,0 @@ -package importer - -import ( - castorev1pb "code.tvl.fyi/tvix/castore-go" - storev1pb "code.tvl.fyi/tvix/store-go" - "fmt" - "github.com/nix-community/go-nix/pkg/narinfo" - "github.com/nix-community/go-nix/pkg/storepath" -) - -// GenPathInfo takes a rootNode and narInfo and assembles a PathInfo. -// The rootNode is renamed to match the StorePath in the narInfo. -func GenPathInfo(rootNode *castorev1pb.Node, narInfo *narinfo.NarInfo) (*storev1pb.PathInfo, error) { - // parse the storePath from the .narinfo - storePath, err := storepath.FromAbsolutePath(narInfo.StorePath) - if err != nil { - return nil, fmt.Errorf("unable to parse StorePath: %w", err) - } - - // construct the references, by parsing ReferenceNames and extracting the digest - references := make([][]byte, len(narInfo.References)) - for i, referenceStr := range narInfo.References { - // parse reference as store path - referenceStorePath, err := storepath.FromString(referenceStr) - if err != nil { - return nil, fmt.Errorf("unable to parse reference %s as storepath: %w", referenceStr, err) - } - references[i] = referenceStorePath.Digest - } - - // construct the narInfo.Signatures[*] from pathInfo.Narinfo.Signatures[*] - narinfoSignatures := make([]*storev1pb.NARInfo_Signature, len(narInfo.Signatures)) - for i, narinfoSig := range narInfo.Signatures { - narinfoSignatures[i] = &storev1pb.NARInfo_Signature{ - Name: narinfoSig.Name, - Data: narinfoSig.Data, - } - } - - // assemble the PathInfo. - pathInfo := &storev1pb.PathInfo{ - // embed a new root node with the name set to the store path basename. - Node: castorev1pb.RenamedNode(rootNode, storePath.String()), - References: references, - Narinfo: &storev1pb.NARInfo{ - NarSize: narInfo.NarSize, - NarSha256: narInfo.FileHash.Digest(), - Signatures: narinfoSignatures, - ReferenceNames: narInfo.References, - }, - } - - // run Validate on the PathInfo, more as an additional sanity check our code is sound, - // to make sure we populated everything properly, before returning it. - // Fail hard if we fail validation, this is a code error. - if _, err = pathInfo.Validate(); err != nil { - panic(fmt.Sprintf("PathInfo failed validation: %v", err)) - } - - return pathInfo, nil - -} diff --git a/tvix/nar-bridge/pkg/importer/importer.go b/tvix/nar-bridge/pkg/importer/importer.go deleted file mode 100644 index fce6c5f293da..000000000000 --- a/tvix/nar-bridge/pkg/importer/importer.go +++ /dev/null @@ -1,303 +0,0 @@ -package importer - -import ( - "bytes" - "context" - "crypto/sha256" - "errors" - "fmt" - "io" - "path" - "strings" - - castorev1pb "code.tvl.fyi/tvix/castore-go" - "github.com/nix-community/go-nix/pkg/nar" - "golang.org/x/sync/errgroup" - "lukechampine.com/blake3" -) - -const ( - // asyncUploadThreshold controls when a file is buffered into memory and uploaded - // asynchronously. Files must be smaller than the threshold to be uploaded asynchronously. - asyncUploadThreshold = 1024 * 1024 // 1 MiB - // maxAsyncUploadBufferBytes is the maximum number of async blob uploads allowed to be - // running concurrently at any given time for a simple import operation. - maxConcurrentAsyncUploads = 128 -) - -// An item on the directories stack -type stackItem struct { - path string - directory *castorev1pb.Directory -} - -// Import reads a NAR from a reader, and returns a the root node, -// NAR size and NAR sha256 digest. -func Import( - // a context, to support cancellation - ctx context.Context, - // The reader the data is read from - r io.Reader, - // callback function called with each regular file content - blobCb func(fileReader io.Reader) ([]byte, error), - // callback function called with each finalized directory node - directoryCb func(directory *castorev1pb.Directory) ([]byte, error), -) (*castorev1pb.Node, uint64, []byte, error) { - // We need to wrap the underlying reader a bit. - // - we want to keep track of the number of bytes read in total - // - we calculate the sha256 digest over all data read - // Express these two things in a MultiWriter, and give the NAR reader a - // TeeReader that writes to it. - narCountW := &CountingWriter{} - sha256W := sha256.New() - multiW := io.MultiWriter(narCountW, sha256W) - narReader, err := nar.NewReader(io.TeeReader(r, multiW)) - if err != nil { - return nil, 0, nil, fmt.Errorf("failed to instantiate nar reader: %w", err) - } - defer narReader.Close() - - // If we store a symlink or regular file at the root, these are not nil. - // If they are nil, we instead have a stackDirectory. - var rootSymlink *castorev1pb.SymlinkNode - var rootFile *castorev1pb.FileNode - var stackDirectory *castorev1pb.Directory - - // Keep track of all asynch blob uploads so we can make sure they all succeed - // before returning. - var asyncBlobWg errgroup.Group - asyncBlobWg.SetLimit(maxConcurrentAsyncUploads) - - var stack = []stackItem{} - - // popFromStack is used when we transition to a different directory or - // drain the stack when we reach the end of the NAR. - // It adds the popped element to the element underneath if any, - // and passes it to the directoryCb callback. - // This function may only be called if the stack is not already empty. - popFromStack := func() error { - // Keep the top item, and "resize" the stack slice. - // This will only make the last element unaccessible, but chances are high - // we're re-using that space anyways. - toPop := stack[len(stack)-1] - stack = stack[:len(stack)-1] - - // call the directoryCb - directoryDigest, err := directoryCb(toPop.directory) - if err != nil { - return fmt.Errorf("failed calling directoryCb: %w", err) - } - - // if there's still a parent left on the stack, refer to it from there. - if len(stack) > 0 { - topOfStack := stack[len(stack)-1].directory - topOfStack.Directories = append(topOfStack.Directories, &castorev1pb.DirectoryNode{ - Name: []byte(path.Base(toPop.path)), - Digest: directoryDigest, - Size: toPop.directory.Size(), - }) - } - // Keep track that we have encounter at least one directory - stackDirectory = toPop.directory - return nil - } - - getBasename := func(p string) string { - // extract the basename. In case of "/", replace with empty string. - basename := path.Base(p) - if basename == "/" { - basename = "" - } - return basename - } - - for { - select { - case <-ctx.Done(): - return nil, 0, nil, ctx.Err() - default: - // call narReader.Next() to get the next element - hdr, err := narReader.Next() - - // If this returns an error, it's either EOF (when we're done reading from the NAR), - // or another error. - if err != nil { - // if this returns no EOF, bail out - if !errors.Is(err, io.EOF) { - return nil, 0, nil, fmt.Errorf("failed getting next nar element: %w", err) - } - - // The NAR has been read all the way to the end… - // Make sure we close the nar reader, which might read some final trailers. - if err := narReader.Close(); err != nil { - return nil, 0, nil, fmt.Errorf("unable to close nar reader: %w", err) - } - - // Check the stack. While it's not empty, we need to pop things off the stack. - for len(stack) > 0 { - err := popFromStack() - if err != nil { - return nil, 0, nil, fmt.Errorf("unable to pop from stack: %w", err) - } - } - - // Wait for any pending blob uploads. - err := asyncBlobWg.Wait() - if err != nil { - return nil, 0, nil, fmt.Errorf("async blob upload: %w", err) - } - - // Stack is empty. - // Now either root{File,Symlink,Directory} is not nil, - // and we can return the root node. - narSize := narCountW.BytesWritten() - narSha256 := sha256W.Sum(nil) - - if rootFile != nil { - return &castorev1pb.Node{ - Node: &castorev1pb.Node_File{ - File: rootFile, - }, - }, narSize, narSha256, nil - } else if rootSymlink != nil { - return &castorev1pb.Node{ - Node: &castorev1pb.Node_Symlink{ - Symlink: rootSymlink, - }, - }, narSize, narSha256, nil - } else if stackDirectory != nil { - // calculate directory digest (i.e. after we received all its contents) - dgst, err := stackDirectory.Digest() - if err != nil { - return nil, 0, nil, fmt.Errorf("unable to calculate root directory digest: %w", err) - } - - return &castorev1pb.Node{ - Node: &castorev1pb.Node_Directory{ - Directory: &castorev1pb.DirectoryNode{ - Name: []byte{}, - Digest: dgst, - Size: stackDirectory.Size(), - }, - }, - }, narSize, narSha256, nil - } else { - return nil, 0, nil, fmt.Errorf("no root set") - } - } - - // Check for valid path transitions, pop from stack if needed - // The nar reader already gives us some guarantees about ordering and illegal transitions, - // So we really only need to check if the top-of-stack path is a prefix of the path, - // and if it's not, pop from the stack. We do this repeatedly until the top of the stack is - // the subdirectory the new entry is in, or we hit the root directory. - - // We don't need to worry about the root node case, because we can only finish the root "/" - // If we're at the end of the NAR reader (covered by the EOF check) - for len(stack) > 1 && !strings.HasPrefix(hdr.Path, stack[len(stack)-1].path+"/") { - err := popFromStack() - if err != nil { - return nil, 0, nil, fmt.Errorf("unable to pop from stack: %w", err) - } - } - - if hdr.Type == nar.TypeSymlink { - symlinkNode := &castorev1pb.SymlinkNode{ - Name: []byte(getBasename(hdr.Path)), - Target: []byte(hdr.LinkTarget), - } - if len(stack) > 0 { - topOfStack := stack[len(stack)-1].directory - topOfStack.Symlinks = append(topOfStack.Symlinks, symlinkNode) - } else { - rootSymlink = symlinkNode - } - - } - if hdr.Type == nar.TypeRegular { - uploadBlob := func(r io.Reader) ([]byte, error) { - // wrap reader with a reader counting the number of bytes read - blobCountW := &CountingWriter{} - blobReader := io.TeeReader(r, blobCountW) - - blobDigest, err := blobCb(blobReader) - if err != nil { - return nil, fmt.Errorf("failure from blobCb: %w", err) - } - - // ensure blobCb did read all the way to the end. - // If it didn't, the blobCb function is wrong and we should bail out. - if blobCountW.BytesWritten() != uint64(hdr.Size) { - return nil, fmt.Errorf("blobCb did not read all: %d/%d bytes", blobCountW.BytesWritten(), hdr.Size) - } - - return blobDigest, nil - } - - h := blake3.New(32, nil) - blobReader := io.TeeReader(narReader, io.MultiWriter(h)) - var blobDigest []byte - - // If this file is small enough, read it off the wire immediately and - // upload to the blob service asynchronously. This helps reduce the - // RTT on blob uploads for NARs with many small files. - doAsync := hdr.Size < asyncUploadThreshold - if doAsync { - blobContents, err := io.ReadAll(blobReader) - if err != nil { - return nil, 0, nil, fmt.Errorf("read blob: %w", err) - } - - blobDigest = h.Sum(nil) - - asyncBlobWg.Go(func() error { - blobDigestFromCb, err := uploadBlob(bytes.NewReader(blobContents)) - if err != nil { - return err - } - - if !bytes.Equal(blobDigest, blobDigestFromCb) { - return fmt.Errorf("unexpected digest (got %x, expected %x)", blobDigestFromCb, blobDigest) - } - - return nil - }) - } else { - blobDigestFromCb, err := uploadBlob(blobReader) - if err != nil { - return nil, 0, nil, fmt.Errorf("upload blob: %w", err) - } - - blobDigest = h.Sum(nil) - if !bytes.Equal(blobDigest, blobDigestFromCb) { - return nil, 0, nil, fmt.Errorf("unexpected digest (got %x, expected %x)", blobDigestFromCb, blobDigest) - } - } - - fileNode := &castorev1pb.FileNode{ - Name: []byte(getBasename(hdr.Path)), - Digest: blobDigest, - Size: uint64(hdr.Size), - Executable: hdr.Executable, - } - if len(stack) > 0 { - topOfStack := stack[len(stack)-1].directory - topOfStack.Files = append(topOfStack.Files, fileNode) - } else { - rootFile = fileNode - } - } - if hdr.Type == nar.TypeDirectory { - directory := &castorev1pb.Directory{ - Directories: []*castorev1pb.DirectoryNode{}, - Files: []*castorev1pb.FileNode{}, - Symlinks: []*castorev1pb.SymlinkNode{}, - } - stack = append(stack, stackItem{ - directory: directory, - path: hdr.Path, - }) - } - } - } -} diff --git a/tvix/nar-bridge/pkg/importer/importer_test.go b/tvix/nar-bridge/pkg/importer/importer_test.go deleted file mode 100644 index 8ff63b92576d..000000000000 --- a/tvix/nar-bridge/pkg/importer/importer_test.go +++ /dev/null @@ -1,537 +0,0 @@ -package importer_test - -import ( - "bytes" - "context" - "errors" - "io" - "os" - "testing" - - castorev1pb "code.tvl.fyi/tvix/castore-go" - "code.tvl.fyi/tvix/nar-bridge/pkg/importer" - "github.com/stretchr/testify/require" -) - -func TestSymlink(t *testing.T) { - f, err := os.Open("../../testdata/symlink.nar") - require.NoError(t, err) - - rootNode, narSize, narSha256, err := importer.Import( - context.Background(), - f, - func(blobReader io.Reader) ([]byte, error) { - panic("no file contents expected!") - }, func(directory *castorev1pb.Directory) ([]byte, error) { - panic("no directories expected!") - }, - ) - require.NoError(t, err) - require.Equal(t, &castorev1pb.Node{ - Node: &castorev1pb.Node_Symlink{ - Symlink: &castorev1pb.SymlinkNode{ - Name: []byte(""), - Target: []byte("/nix/store/somewhereelse"), - }, - }, - }, rootNode) - require.Equal(t, []byte{ - 0x09, 0x7d, 0x39, 0x7e, 0x9b, 0x58, 0x26, 0x38, 0x4e, 0xaa, 0x16, 0xc4, 0x57, 0x71, 0x5d, 0x1c, 0x1a, 0x51, 0x67, 0x03, 0x13, 0xea, 0xd0, 0xf5, 0x85, 0x66, 0xe0, 0xb2, 0x32, 0x53, 0x9c, 0xf1, - }, narSha256) - require.Equal(t, uint64(136), narSize) -} - -func TestRegular(t *testing.T) { - f, err := os.Open("../../testdata/onebyteregular.nar") - require.NoError(t, err) - - rootNode, narSize, narSha256, err := importer.Import( - context.Background(), - f, - func(blobReader io.Reader) ([]byte, error) { - contents, err := io.ReadAll(blobReader) - require.NoError(t, err, "reading blobReader should not error") - require.Equal(t, []byte{0x01}, contents, "contents read from blobReader should match expectations") - return mustBlobDigest(bytes.NewBuffer(contents)), nil - }, func(directory *castorev1pb.Directory) ([]byte, error) { - panic("no directories expected!") - }, - ) - - // The blake3 digest of the 0x01 byte. - BLAKE3_DIGEST_0X01 := []byte{ - 0x48, 0xfc, 0x72, 0x1f, 0xbb, 0xc1, 0x72, 0xe0, 0x92, 0x5f, 0xa2, 0x7a, 0xf1, 0x67, 0x1d, - 0xe2, 0x25, 0xba, 0x92, 0x71, 0x34, 0x80, 0x29, 0x98, 0xb1, 0x0a, 0x15, 0x68, 0xa1, 0x88, - 0x65, 0x2b, - } - - require.NoError(t, err) - require.Equal(t, &castorev1pb.Node{ - Node: &castorev1pb.Node_File{ - File: &castorev1pb.FileNode{ - Name: []byte(""), - Digest: BLAKE3_DIGEST_0X01, - Size: 1, - Executable: false, - }, - }, - }, rootNode) - require.Equal(t, []byte{ - 0x73, 0x08, 0x50, 0xa8, 0x11, 0x25, 0x9d, 0xbf, 0x3a, 0x68, 0xdc, 0x2e, 0xe8, 0x7a, 0x79, 0xaa, 0x6c, 0xae, 0x9f, 0x71, 0x37, 0x5e, 0xdf, 0x39, 0x6f, 0x9d, 0x7a, 0x91, 0xfb, 0xe9, 0x13, 0x4d, - }, narSha256) - require.Equal(t, uint64(120), narSize) -} - -func TestEmptyDirectory(t *testing.T) { - f, err := os.Open("../../testdata/emptydirectory.nar") - require.NoError(t, err) - - expectedDirectory := &castorev1pb.Directory{ - Directories: []*castorev1pb.DirectoryNode{}, - Files: []*castorev1pb.FileNode{}, - Symlinks: []*castorev1pb.SymlinkNode{}, - } - rootNode, narSize, narSha256, err := importer.Import( - context.Background(), - f, - func(blobReader io.Reader) ([]byte, error) { - panic("no file contents expected!") - }, func(directory *castorev1pb.Directory) ([]byte, error) { - requireProtoEq(t, expectedDirectory, directory) - return mustDirectoryDigest(directory), nil - }, - ) - require.NoError(t, err) - require.Equal(t, &castorev1pb.Node{ - Node: &castorev1pb.Node_Directory{ - Directory: &castorev1pb.DirectoryNode{ - Name: []byte(""), - Digest: mustDirectoryDigest(expectedDirectory), - Size: expectedDirectory.Size(), - }, - }, - }, rootNode) - require.Equal(t, []byte{ - 0xa5, 0x0a, 0x5a, 0xb6, 0xd9, 0x92, 0xf5, 0x59, 0x8e, 0xdd, 0x92, 0x10, 0x50, 0x59, 0xfa, 0xe9, 0xac, 0xfc, 0x19, 0x29, 0x81, 0xe0, 0x8b, 0xd8, 0x85, 0x34, 0xc2, 0x16, 0x7e, 0x92, 0x52, 0x6a, - }, narSha256) - require.Equal(t, uint64(96), narSize) -} - -func TestFull(t *testing.T) { - f, err := os.Open("../../testdata/nar_1094wph9z4nwlgvsd53abfz8i117ykiv5dwnq9nnhz846s7xqd7d.nar") - require.NoError(t, err) - - expectedDirectoryPaths := []string{ - "/bin", - "/share/man/man1", - "/share/man/man5", - "/share/man/man8", - "/share/man", - "/share", - "/", - } - expectedDirectories := make(map[string]*castorev1pb.Directory, len(expectedDirectoryPaths)) - - // /bin is a leaf directory - expectedDirectories["/bin"] = &castorev1pb.Directory{ - Directories: []*castorev1pb.DirectoryNode{}, - Files: []*castorev1pb.FileNode{ - { - Name: []byte("arp"), - Digest: []byte{ - 0xfb, 0xc4, 0x61, 0x4a, 0x29, 0x27, 0x11, 0xcb, 0xcc, 0xe4, 0x99, 0x81, 0x9c, 0xf0, 0xa9, 0x17, 0xf7, 0xd0, 0x91, 0xbe, 0xea, 0x08, 0xcb, 0x5b, 0xaa, 0x76, 0x76, 0xf5, 0xee, 0x4f, 0x82, 0xbb, - }, - Size: 55288, - Executable: true, - }, - { - Name: []byte("hostname"), - Digest: []byte{ - 0x9c, 0x6a, 0xe4, 0xb5, 0xe4, 0x6c, 0xb5, 0x67, 0x45, 0x0e, 0xaa, 0x2a, 0xd8, 0xdd, 0x9b, 0x38, 0xd7, 0xed, 0x01, 0x02, 0x84, 0xf7, 0x26, 0xe1, 0xc7, 0xf3, 0x1c, 0xeb, 0xaa, 0x8a, 0x01, 0x30, - }, - Size: 17704, - Executable: true, - }, - { - Name: []byte("ifconfig"), - Digest: []byte{ - 0x25, 0xbe, 0x3b, 0x1d, 0xf4, 0x1a, 0x45, 0x42, 0x79, 0x09, 0x2c, 0x2a, 0x83, 0xf0, 0x0b, 0xff, 0xe8, 0xc0, 0x9c, 0x26, 0x98, 0x70, 0x15, 0x4d, 0xa8, 0xca, 0x05, 0xfe, 0x92, 0x68, 0x35, 0x2e, - }, - Size: 72576, - Executable: true, - }, - { - Name: []byte("nameif"), - Digest: []byte{ - 0x8e, 0xaa, 0xc5, 0xdb, 0x71, 0x08, 0x8e, 0xe5, 0xe6, 0x30, 0x1f, 0x2c, 0x3a, 0xf2, 0x42, 0x39, 0x0c, 0x57, 0x15, 0xaf, 0x50, 0xaa, 0x1c, 0xdf, 0x84, 0x22, 0x08, 0x77, 0x03, 0x54, 0x62, 0xb1, - }, - Size: 18776, - Executable: true, - }, - { - Name: []byte("netstat"), - Digest: []byte{ - 0x13, 0x34, 0x7e, 0xdd, 0x2a, 0x9a, 0x17, 0x0b, 0x3f, 0xc7, 0x0a, 0xe4, 0x92, 0x89, 0x25, 0x9f, 0xaa, 0xb5, 0x05, 0x6b, 0x24, 0xa7, 0x91, 0xeb, 0xaf, 0xf9, 0xe9, 0x35, 0x56, 0xaa, 0x2f, 0xb2, - }, - Size: 131784, - Executable: true, - }, - { - Name: []byte("plipconfig"), - Digest: []byte{ - 0x19, 0x7c, 0x80, 0xdc, 0x81, 0xdc, 0xb4, 0xc0, 0x45, 0xe1, 0xf9, 0x76, 0x51, 0x4f, 0x50, 0xbf, 0xa4, 0x69, 0x51, 0x9a, 0xd4, 0xa9, 0xe7, 0xaa, 0xe7, 0x0d, 0x53, 0x32, 0xff, 0x28, 0x40, 0x60, - }, - Size: 13160, - Executable: true, - }, - { - Name: []byte("rarp"), - Digest: []byte{ - 0x08, 0x85, 0xb4, 0x85, 0x03, 0x2b, 0x3c, 0x7a, 0x3e, 0x24, 0x4c, 0xf8, 0xcc, 0x45, 0x01, 0x9e, 0x79, 0x43, 0x8c, 0x6f, 0x5e, 0x32, 0x46, 0x54, 0xb6, 0x68, 0x91, 0x8e, 0xa0, 0xcb, 0x6e, 0x0d, - }, - Size: 30384, - Executable: true, - }, - { - Name: []byte("route"), - Digest: []byte{ - 0x4d, 0x14, 0x20, 0x89, 0x9e, 0x76, 0xf4, 0xe2, 0x92, 0x53, 0xee, 0x9b, 0x78, 0x7d, 0x23, 0x80, 0x6c, 0xff, 0xe6, 0x33, 0xdc, 0x4a, 0x10, 0x29, 0x39, 0x02, 0xa0, 0x60, 0xff, 0xe2, 0xbb, 0xd7, - }, - Size: 61928, - Executable: true, - }, - { - Name: []byte("slattach"), - Digest: []byte{ - 0xfb, 0x25, 0xc3, 0x73, 0xb7, 0xb1, 0x0b, 0x25, 0xcd, 0x7b, 0x62, 0xf6, 0x71, 0x83, 0xfe, 0x36, 0x80, 0xf6, 0x48, 0xc3, 0xdb, 0xd8, 0x0c, 0xfe, 0xb8, 0xd3, 0xda, 0x32, 0x9b, 0x47, 0x4b, 0x05, - }, - Size: 35672, - Executable: true, - }, - }, - Symlinks: []*castorev1pb.SymlinkNode{ - { - Name: []byte("dnsdomainname"), - Target: []byte("hostname"), - }, - { - Name: []byte("domainname"), - Target: []byte("hostname"), - }, - { - Name: []byte("nisdomainname"), - Target: []byte("hostname"), - }, - { - Name: []byte("ypdomainname"), - Target: []byte("hostname"), - }, - }, - } - - // /share/man/man1 is a leaf directory. - // The parser traversed over /sbin, but only added it to / which is still on the stack. - expectedDirectories["/share/man/man1"] = &castorev1pb.Directory{ - Directories: []*castorev1pb.DirectoryNode{}, - Files: []*castorev1pb.FileNode{ - { - Name: []byte("dnsdomainname.1.gz"), - Digest: []byte{ - 0x98, 0x8a, 0xbd, 0xfa, 0x64, 0xd5, 0xb9, 0x27, 0xfe, 0x37, 0x43, 0x56, 0xb3, 0x18, 0xc7, 0x2b, 0xcb, 0xe3, 0x17, 0x1c, 0x17, 0xf4, 0x17, 0xeb, 0x4a, 0xa4, 0x99, 0x64, 0x39, 0xca, 0x2d, 0xee, - }, - Size: 40, - Executable: false, - }, - { - Name: []byte("domainname.1.gz"), - Digest: []byte{ - 0x98, 0x8a, 0xbd, 0xfa, 0x64, 0xd5, 0xb9, 0x27, 0xfe, 0x37, 0x43, 0x56, 0xb3, 0x18, 0xc7, 0x2b, 0xcb, 0xe3, 0x17, 0x1c, 0x17, 0xf4, 0x17, 0xeb, 0x4a, 0xa4, 0x99, 0x64, 0x39, 0xca, 0x2d, 0xee, - }, - Size: 40, - Executable: false, - }, - { - Name: []byte("hostname.1.gz"), - Digest: []byte{ - 0xbf, 0x89, 0xe6, 0x28, 0x00, 0x24, 0x66, 0x79, 0x70, 0x04, 0x38, 0xd6, 0xdd, 0x9d, 0xf6, 0x0e, 0x0d, 0xee, 0x00, 0xf7, 0x64, 0x4f, 0x05, 0x08, 0x9d, 0xf0, 0x36, 0xde, 0x85, 0xf4, 0x75, 0xdb, - }, - Size: 1660, - Executable: false, - }, - { - Name: []byte("nisdomainname.1.gz"), - Digest: []byte{ - 0x98, 0x8a, 0xbd, 0xfa, 0x64, 0xd5, 0xb9, 0x27, 0xfe, 0x37, 0x43, 0x56, 0xb3, 0x18, 0xc7, 0x2b, 0xcb, 0xe3, 0x17, 0x1c, 0x17, 0xf4, 0x17, 0xeb, 0x4a, 0xa4, 0x99, 0x64, 0x39, 0xca, 0x2d, 0xee, - }, - Size: 40, - Executable: false, - }, - { - Name: []byte("ypdomainname.1.gz"), - Digest: []byte{ - 0x98, 0x8a, 0xbd, 0xfa, 0x64, 0xd5, 0xb9, 0x27, 0xfe, 0x37, 0x43, 0x56, 0xb3, 0x18, 0xc7, 0x2b, 0xcb, 0xe3, 0x17, 0x1c, 0x17, 0xf4, 0x17, 0xeb, 0x4a, 0xa4, 0x99, 0x64, 0x39, 0xca, 0x2d, 0xee, - }, - Size: 40, - Executable: false, - }, - }, - Symlinks: []*castorev1pb.SymlinkNode{}, - } - - // /share/man/man5 is a leaf directory - expectedDirectories["/share/man/man5"] = &castorev1pb.Directory{ - Directories: []*castorev1pb.DirectoryNode{}, - Files: []*castorev1pb.FileNode{ - { - Name: []byte("ethers.5.gz"), - Digest: []byte{ - 0x42, 0x63, 0x8c, 0xc4, 0x18, 0x93, 0xcf, 0x60, 0xd6, 0xff, 0x43, 0xbc, 0x16, 0xb4, 0xfd, 0x22, 0xd2, 0xf2, 0x05, 0x0b, 0x52, 0xdc, 0x6a, 0x6b, 0xff, 0x34, 0xe2, 0x6a, 0x38, 0x3a, 0x07, 0xe3, - }, - Size: 563, - Executable: false, - }, - }, - Symlinks: []*castorev1pb.SymlinkNode{}, - } - - // /share/man/man8 is a leaf directory - expectedDirectories["/share/man/man8"] = &castorev1pb.Directory{ - Directories: []*castorev1pb.DirectoryNode{}, - Files: []*castorev1pb.FileNode{ - { - Name: []byte("arp.8.gz"), - Digest: []byte{ - 0xf5, 0x35, 0x4e, 0xf5, 0xf6, 0x44, 0xf7, 0x52, 0x0f, 0x42, 0xa0, 0x26, 0x51, 0xd9, 0x89, 0xf9, 0x68, 0xf2, 0xef, 0xeb, 0xba, 0xe1, 0xf4, 0x55, 0x01, 0x57, 0x77, 0xb7, 0x68, 0x55, 0x92, 0xef, - }, - Size: 2464, - Executable: false, - }, - { - Name: []byte("ifconfig.8.gz"), - Digest: []byte{ - 0x18, 0x65, 0x25, 0x11, 0x32, 0xee, 0x77, 0x91, 0x35, 0x4c, 0x3c, 0x24, 0xdb, 0xaf, 0x66, 0xdb, 0xfc, 0x17, 0x7b, 0xba, 0xe1, 0x3d, 0x05, 0xd2, 0xca, 0x6e, 0x2c, 0xe4, 0xef, 0xb8, 0xa8, 0xbe, - }, - Size: 3382, - Executable: false, - }, - { - Name: []byte("nameif.8.gz"), - Digest: []byte{ - 0x73, 0xc1, 0x27, 0xe8, 0x3b, 0xa8, 0x49, 0xdc, 0x0e, 0xdf, 0x70, 0x5f, 0xaf, 0x06, 0x01, 0x2c, 0x62, 0xe9, 0x18, 0x67, 0x01, 0x94, 0x64, 0x26, 0xca, 0x95, 0x22, 0xc0, 0xdc, 0xe4, 0x42, 0xb6, - }, - Size: 523, - Executable: false, - }, - { - Name: []byte("netstat.8.gz"), - Digest: []byte{ - 0xc0, 0x86, 0x43, 0x4a, 0x43, 0x57, 0xaa, 0x84, 0xa7, 0x24, 0xa0, 0x7c, 0x65, 0x38, 0x46, 0x1c, 0xf2, 0x45, 0xa2, 0xef, 0x12, 0x44, 0x18, 0xba, 0x52, 0x56, 0xe9, 0x8e, 0x6a, 0x0f, 0x70, 0x63, - }, - Size: 4284, - Executable: false, - }, - { - Name: []byte("plipconfig.8.gz"), - Digest: []byte{ - 0x2a, 0xd9, 0x1d, 0xa8, 0x9e, 0x0d, 0x05, 0xd0, 0xb0, 0x49, 0xaa, 0x64, 0xba, 0x29, 0x28, 0xc6, 0x45, 0xe1, 0xbb, 0x5e, 0x72, 0x8d, 0x48, 0x7b, 0x09, 0x4f, 0x0a, 0x82, 0x1e, 0x26, 0x83, 0xab, - }, - Size: 889, - Executable: false, - }, - { - Name: []byte("rarp.8.gz"), - Digest: []byte{ - 0x3d, 0x51, 0xc1, 0xd0, 0x6a, 0x59, 0x1e, 0x6d, 0x9a, 0xf5, 0x06, 0xd2, 0xe7, 0x7d, 0x7d, 0xd0, 0x70, 0x3d, 0x84, 0x64, 0xc3, 0x7d, 0xfb, 0x10, 0x84, 0x3b, 0xe1, 0xa9, 0xdf, 0x46, 0xee, 0x9f, - }, - Size: 1198, - Executable: false, - }, - { - Name: []byte("route.8.gz"), - Digest: []byte{ - 0x2a, 0x5a, 0x4b, 0x4f, 0x91, 0xf2, 0x78, 0xe4, 0xa9, 0x25, 0xb2, 0x7f, 0xa7, 0x2a, 0xc0, 0x8a, 0x4a, 0x65, 0xc9, 0x5f, 0x07, 0xa0, 0x48, 0x44, 0xeb, 0x46, 0xf9, 0xc9, 0xe1, 0x17, 0x96, 0x21, - }, - Size: 3525, - Executable: false, - }, - { - Name: []byte("slattach.8.gz"), - Digest: []byte{ - 0x3f, 0x05, 0x6b, 0x20, 0xe1, 0xe4, 0xf0, 0xba, 0x16, 0x15, 0x66, 0x6b, 0x57, 0x96, 0xe9, 0x9d, 0x83, 0xa8, 0x20, 0xaf, 0x8a, 0xca, 0x16, 0x4d, 0xa2, 0x6d, 0x94, 0x8e, 0xca, 0x91, 0x8f, 0xd4, - }, - Size: 1441, - Executable: false, - }, - }, - Symlinks: []*castorev1pb.SymlinkNode{}, - } - - // /share/man holds /share/man/man{1,5,8}. - expectedDirectories["/share/man"] = &castorev1pb.Directory{ - Directories: []*castorev1pb.DirectoryNode{ - { - Name: []byte("man1"), - Digest: mustDirectoryDigest(expectedDirectories["/share/man/man1"]), - Size: expectedDirectories["/share/man/man1"].Size(), - }, - { - Name: []byte("man5"), - Digest: mustDirectoryDigest(expectedDirectories["/share/man/man5"]), - Size: expectedDirectories["/share/man/man5"].Size(), - }, - { - Name: []byte("man8"), - Digest: mustDirectoryDigest(expectedDirectories["/share/man/man8"]), - Size: expectedDirectories["/share/man/man8"].Size(), - }, - }, - Files: []*castorev1pb.FileNode{}, - Symlinks: []*castorev1pb.SymlinkNode{}, - } - - // /share holds /share/man. - expectedDirectories["/share"] = &castorev1pb.Directory{ - Directories: []*castorev1pb.DirectoryNode{ - { - Name: []byte("man"), - Digest: mustDirectoryDigest(expectedDirectories["/share/man"]), - Size: expectedDirectories["/share/man"].Size(), - }, - }, - Files: []*castorev1pb.FileNode{}, - Symlinks: []*castorev1pb.SymlinkNode{}, - } - - // / holds /bin, /share, and a /sbin symlink. - expectedDirectories["/"] = &castorev1pb.Directory{ - Directories: []*castorev1pb.DirectoryNode{ - { - Name: []byte("bin"), - Digest: mustDirectoryDigest(expectedDirectories["/bin"]), - Size: expectedDirectories["/bin"].Size(), - }, - { - Name: []byte("share"), - Digest: mustDirectoryDigest(expectedDirectories["/share"]), - Size: expectedDirectories["/share"].Size(), - }, - }, - Files: []*castorev1pb.FileNode{}, - Symlinks: []*castorev1pb.SymlinkNode{ - { - Name: []byte("sbin"), - Target: []byte("bin"), - }, - }, - } - // assert we populated the two fixtures properly - require.Equal(t, len(expectedDirectoryPaths), len(expectedDirectories)) - - numDirectoriesReceived := 0 - - rootNode, narSize, narSha256, err := importer.Import( - context.Background(), - f, - func(blobReader io.Reader) ([]byte, error) { - // Don't really bother reading and comparing the contents here, - // We already verify the right digests are produced by comparing the - // directoryCb calls, and TestRegular ensures the reader works. - return mustBlobDigest(blobReader), nil - }, func(directory *castorev1pb.Directory) ([]byte, error) { - // use actualDirectoryOrder to look up the Directory object we expect at this specific invocation. - currentDirectoryPath := expectedDirectoryPaths[numDirectoriesReceived] - - expectedDirectory, found := expectedDirectories[currentDirectoryPath] - require.True(t, found, "must find the current directory") - - requireProtoEq(t, expectedDirectory, directory) - - numDirectoriesReceived += 1 - return mustDirectoryDigest(directory), nil - }, - ) - require.NoError(t, err) - require.Equal(t, &castorev1pb.Node{ - Node: &castorev1pb.Node_Directory{ - Directory: &castorev1pb.DirectoryNode{ - Name: []byte(""), - Digest: mustDirectoryDigest(expectedDirectories["/"]), - Size: expectedDirectories["/"].Size(), - }, - }, - }, rootNode) - require.Equal(t, []byte{ - 0xc6, 0xe1, 0x55, 0xb3, 0x45, 0x6e, 0x30, 0xb7, 0x61, 0x22, 0x63, 0xec, 0x09, 0x50, 0x70, 0x81, 0x1c, 0xaf, 0x8a, 0xbf, 0xd5, 0x9f, 0xaa, 0x72, 0xab, 0x82, 0xa5, 0x92, 0xef, 0xde, 0xb2, 0x53, - }, narSha256) - require.Equal(t, uint64(464152), narSize) -} - -// TestCallbackErrors ensures that errors returned from the callback function -// bubble up to the importer process, and are not ignored. -func TestCallbackErrors(t *testing.T) { - t.Run("callback blob", func(t *testing.T) { - // Pick an example NAR with a regular file. - f, err := os.Open("../../testdata/onebyteregular.nar") - require.NoError(t, err) - - targetErr := errors.New("expected error") - - _, _, _, err = importer.Import( - context.Background(), - f, - func(blobReader io.Reader) ([]byte, error) { - return nil, targetErr - }, func(directory *castorev1pb.Directory) ([]byte, error) { - panic("no directories expected!") - }, - ) - require.ErrorIs(t, err, targetErr) - }) - t.Run("callback directory", func(t *testing.T) { - // Pick an example NAR with a directory node - f, err := os.Open("../../testdata/emptydirectory.nar") - require.NoError(t, err) - - targetErr := errors.New("expected error") - - _, _, _, err = importer.Import( - context.Background(), - f, - func(blobReader io.Reader) ([]byte, error) { - panic("no file contents expected!") - }, func(directory *castorev1pb.Directory) ([]byte, error) { - return nil, targetErr - }, - ) - require.ErrorIs(t, err, targetErr) - }) -} - -// TestPopDirectories is a regression test that ensures we handle the directory -// stack properly. -// -// This test case looks like: -// -// / (dir) -// /test (dir) -// /test/tested (file) -// /tested (file) -// -// We used to have a bug where the second `tested` file would appear as if -// it was in the `/test` dir because it has that dir as a string prefix. -func TestPopDirectories(t *testing.T) { - f, err := os.Open("../../testdata/popdirectories.nar") - require.NoError(t, err) - defer f.Close() - - _, _, _, err = importer.Import( - context.Background(), - f, - func(blobReader io.Reader) ([]byte, error) { return mustBlobDigest(blobReader), nil }, - func(directory *castorev1pb.Directory) ([]byte, error) { - require.NoError(t, directory.Validate(), "directory validation shouldn't error") - return mustDirectoryDigest(directory), nil - }, - ) - require.NoError(t, err) -} diff --git a/tvix/nar-bridge/pkg/importer/roundtrip_test.go b/tvix/nar-bridge/pkg/importer/roundtrip_test.go deleted file mode 100644 index 6d6fcb9ee220..000000000000 --- a/tvix/nar-bridge/pkg/importer/roundtrip_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package importer_test - -import ( - "bytes" - "context" - "encoding/base64" - "fmt" - "io" - "os" - "sync" - "testing" - - castorev1pb "code.tvl.fyi/tvix/castore-go" - "code.tvl.fyi/tvix/nar-bridge/pkg/importer" - storev1pb "code.tvl.fyi/tvix/store-go" - "github.com/stretchr/testify/require" -) - -func TestRoundtrip(t *testing.T) { - // We pipe nar_1094wph9z4nwlgvsd53abfz8i117ykiv5dwnq9nnhz846s7xqd7d.nar to - // storev1pb.Export, and store all the file contents and directory objects - // received in two hashmaps. - // We then feed it to the writer, and test we come up with the same NAR file. - - f, err := os.Open("../../testdata/nar_1094wph9z4nwlgvsd53abfz8i117ykiv5dwnq9nnhz846s7xqd7d.nar") - require.NoError(t, err) - - narContents, err := io.ReadAll(f) - require.NoError(t, err) - - var mu sync.Mutex - blobsMap := make(map[string][]byte, 0) - directoriesMap := make(map[string]*castorev1pb.Directory) - - rootNode, _, _, err := importer.Import( - context.Background(), - bytes.NewBuffer(narContents), - func(blobReader io.Reader) ([]byte, error) { - // read in contents, we need to put it into filesMap later. - contents, err := io.ReadAll(blobReader) - require.NoError(t, err) - - dgst := mustBlobDigest(bytes.NewReader(contents)) - - // put it in filesMap - mu.Lock() - blobsMap[base64.StdEncoding.EncodeToString(dgst)] = contents - mu.Unlock() - - return dgst, nil - }, - func(directory *castorev1pb.Directory) ([]byte, error) { - dgst := mustDirectoryDigest(directory) - - directoriesMap[base64.StdEncoding.EncodeToString(dgst)] = directory - return dgst, nil - }, - ) - - require.NoError(t, err) - - // done populating everything, now actually test the export :-) - var narBuf bytes.Buffer - err = storev1pb.Export( - &narBuf, - rootNode, - func(directoryDgst []byte) (*castorev1pb.Directory, error) { - d, found := directoriesMap[base64.StdEncoding.EncodeToString(directoryDgst)] - if !found { - panic(fmt.Sprintf("directory %v not found", base64.StdEncoding.EncodeToString(directoryDgst))) - } - return d, nil - }, - func(blobDgst []byte) (io.ReadCloser, error) { - blobContents, found := blobsMap[base64.StdEncoding.EncodeToString(blobDgst)] - if !found { - panic(fmt.Sprintf("blob %v not found", base64.StdEncoding.EncodeToString(blobDgst))) - } - return io.NopCloser(bytes.NewReader(blobContents)), nil - }, - ) - - require.NoError(t, err, "exporter shouldn't fail") - require.Equal(t, narContents, narBuf.Bytes()) -} diff --git a/tvix/nar-bridge/pkg/importer/util_test.go b/tvix/nar-bridge/pkg/importer/util_test.go deleted file mode 100644 index 06353cf582e5..000000000000 --- a/tvix/nar-bridge/pkg/importer/util_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package importer_test - -import ( - "io" - "testing" - - castorev1pb "code.tvl.fyi/tvix/castore-go" - "github.com/google/go-cmp/cmp" - "google.golang.org/protobuf/testing/protocmp" - "lukechampine.com/blake3" -) - -func requireProtoEq(t *testing.T, expected interface{}, actual interface{}) { - if diff := cmp.Diff(expected, actual, protocmp.Transform()); diff != "" { - t.Errorf("unexpected difference:\n%v", diff) - } -} - -func mustDirectoryDigest(d *castorev1pb.Directory) []byte { - dgst, err := d.Digest() - if err != nil { - panic(err) - } - return dgst -} - -func mustBlobDigest(r io.Reader) []byte { - hasher := blake3.New(32, nil) - _, err := io.Copy(hasher, r) - if err != nil { - panic(err) - } - return hasher.Sum([]byte{}) -} diff --git a/tvix/nar-bridge/src/bin/nar-bridge.rs b/tvix/nar-bridge/src/bin/nar-bridge.rs new file mode 100644 index 000000000000..48eba0ac44ac --- /dev/null +++ b/tvix/nar-bridge/src/bin/nar-bridge.rs @@ -0,0 +1,92 @@ +use clap::Parser; +use mimalloc::MiMalloc; +use nar_bridge::AppState; +use tower::ServiceBuilder; +use tower_http::trace::{DefaultMakeSpan, TraceLayer}; +use tracing::info; +use tvix_store::utils::ServiceUrlsGrpc; + +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; + +/// Expose the Nix HTTP Binary Cache protocol for a tvix-store. +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Cli { + #[clap(flatten)] + service_addrs: ServiceUrlsGrpc, + + /// The priority to announce at the `nix-cache-info` endpoint. + /// A lower number means it's *more preferred. + #[arg(long, env, default_value_t = 39)] + priority: u64, + + /// The address to listen on. + #[clap(flatten)] + listen_args: tokio_listener::ListenerAddressLFlag, + + #[cfg(feature = "otlp")] + /// Whether to configure OTLP. Set --otlp=false to disable. + #[arg(long, default_missing_value = "true", default_value = "true", num_args(0..=1), require_equals(true), action(clap::ArgAction::Set))] + otlp: bool, +} + +#[tokio::main] +async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { + let cli = Cli::parse(); + + let _tracing_handle = { + #[allow(unused_mut)] + let mut builder = tvix_tracing::TracingBuilder::default(); + #[cfg(feature = "otlp")] + { + if cli.otlp { + builder = builder.enable_otlp("tvix.store"); + } + } + builder.build()? + }; + + // initialize stores + let (blob_service, directory_service, path_info_service, _nar_calculation_service) = + tvix_store::utils::construct_services(cli.service_addrs).await?; + + let state = AppState::new(blob_service, directory_service, path_info_service); + + let app = nar_bridge::gen_router(cli.priority) + .layer( + ServiceBuilder::new() + .layer( + TraceLayer::new_for_http().make_span_with( + DefaultMakeSpan::new() + .level(tracing::Level::INFO) + .include_headers(true), + ), + ) + .map_request(tvix_tracing::propagate::axum::accept_trace), + ) + .with_state(state); + + let listen_address = &cli.listen_args.listen_address.unwrap_or_else(|| { + "[::]:9000" + .parse() + .expect("invalid fallback listen address") + }); + + let listener = tokio_listener::Listener::bind( + listen_address, + &Default::default(), + &cli.listen_args.listener_options, + ) + .await?; + + info!(listen_address=%listen_address, "starting daemon"); + + tokio_listener::axum07::serve( + listener, + app.into_make_service_with_connect_info::<tokio_listener::SomeSocketAddrClonable>(), + ) + .await?; + + Ok(()) +} diff --git a/tvix/nar-bridge/src/lib.rs b/tvix/nar-bridge/src/lib.rs new file mode 100644 index 000000000000..c4a6c8d5f2dc --- /dev/null +++ b/tvix/nar-bridge/src/lib.rs @@ -0,0 +1,85 @@ +use axum::http::StatusCode; +use axum::response::IntoResponse; +use axum::routing::{head, put}; +use axum::{routing::get, Router}; +use lru::LruCache; +use nix_compat::nix_http; +use parking_lot::RwLock; +use std::num::NonZeroUsize; +use std::sync::Arc; +use tvix_castore::blobservice::BlobService; +use tvix_castore::directoryservice::DirectoryService; +use tvix_castore::Node; +use tvix_store::pathinfoservice::PathInfoService; + +mod nar; +mod narinfo; + +/// The capacity of the lookup table from NarHash to [Node]. +/// Should be bigger than the number of concurrent NAR upload. +/// Cannot be [NonZeroUsize] here due to rust-analyzer going bananas. +/// SAFETY: 1000 != 0 +const ROOT_NODES_CACHE_CAPACITY: usize = 1000; + +#[derive(Clone)] +pub struct AppState { + blob_service: Arc<dyn BlobService>, + directory_service: Arc<dyn DirectoryService>, + path_info_service: Arc<dyn PathInfoService>, + + /// Lookup table from NarHash to [Node], necessary to populate the root_node + /// field of the PathInfo when processing the narinfo upload. + root_nodes: Arc<RwLock<LruCache<[u8; 32], Node>>>, +} + +impl AppState { + pub fn new( + blob_service: Arc<dyn BlobService>, + directory_service: Arc<dyn DirectoryService>, + path_info_service: Arc<dyn PathInfoService>, + ) -> Self { + Self { + blob_service, + directory_service, + path_info_service, + root_nodes: Arc::new(RwLock::new(LruCache::new({ + // SAFETY: 1000 != 0 + unsafe { NonZeroUsize::new_unchecked(ROOT_NODES_CACHE_CAPACITY) } + }))), + } + } +} + +pub fn gen_router(priority: u64) -> Router<AppState> { + Router::new() + .route("/", get(root)) + // FUTUREWORK: respond for NARs that we still have in root_nodes (at least HEAD) + // This avoids some unnecessary NAR uploading from multiple concurrent clients, and is cheap. + .route("/nar/:nar_str", get(four_o_four)) + .route("/nar/:nar_str", head(four_o_four)) + .route("/nar/:nar_str", put(nar::put)) + .route("/nar/tvix-castore/:root_node_enc", get(nar::get_head)) + .route("/nar/tvix-castore/:root_node_enc", head(nar::get_head)) + .route("/:narinfo_str", get(narinfo::get)) + .route("/:narinfo_str", head(narinfo::head)) + .route("/:narinfo_str", put(narinfo::put)) + .route("/nix-cache-info", get(move || nix_cache_info(priority))) +} + +async fn root() -> &'static str { + "Hello from nar-bridge" +} + +async fn four_o_four() -> Result<(), StatusCode> { + Err(StatusCode::NOT_FOUND) +} + +async fn nix_cache_info(priority: u64) -> impl IntoResponse { + ( + [("Content-Type", nix_http::MIME_TYPE_CACHE_INFO)], + format!( + "StoreDir: /nix/store\nWantMassQuery: 1\nPriority: {}\n", + priority + ), + ) +} diff --git a/tvix/nar-bridge/src/nar.rs b/tvix/nar-bridge/src/nar.rs new file mode 100644 index 000000000000..abc0d854d7c7 --- /dev/null +++ b/tvix/nar-bridge/src/nar.rs @@ -0,0 +1,177 @@ +use axum::extract::Query; +use axum::http::StatusCode; +use axum::response::Response; +use axum::{body::Body, response::IntoResponse}; +use axum_extra::{headers::Range, TypedHeader}; +use axum_range::{KnownSize, Ranged}; +use bytes::Bytes; +use data_encoding::BASE64URL_NOPAD; +use futures::TryStreamExt; +use nix_compat::{nix_http, nixbase32}; +use serde::Deserialize; +use std::io; +use tokio_util::io::ReaderStream; +use tracing::{instrument, warn, Span}; +use tvix_store::nar::ingest_nar_and_hash; + +use crate::AppState; + +#[derive(Debug, Deserialize)] +pub(crate) struct GetNARParams { + #[serde(rename = "narsize")] + nar_size: u64, +} + +#[instrument(skip(blob_service, directory_service))] +pub async fn get_head( + method: axum::http::Method, + ranges: Option<TypedHeader<Range>>, + axum::extract::Path(root_node_enc): axum::extract::Path<String>, + axum::extract::Query(GetNARParams { nar_size }): Query<GetNARParams>, + axum::extract::State(AppState { + blob_service, + directory_service, + .. + }): axum::extract::State<AppState>, +) -> Result<impl axum::response::IntoResponse, StatusCode> { + use prost::Message; + // b64decode the root node passed *by the user* + let root_node_proto = BASE64URL_NOPAD + .decode(root_node_enc.as_bytes()) + .map_err(|e| { + warn!(err=%e, "unable to decode root node b64"); + StatusCode::NOT_FOUND + })?; + + // check the proto size to be somewhat reasonable before parsing it. + if root_node_proto.len() > 4096 { + warn!("rejected too large root node"); + return Err(StatusCode::BAD_REQUEST); + } + + // parse the proto + let root_node: tvix_castore::proto::Node = Message::decode(Bytes::from(root_node_proto)) + .map_err(|e| { + warn!(err=%e, "unable to decode root node proto"); + StatusCode::NOT_FOUND + })?; + + let root_node = root_node.try_into_anonymous_node().map_err(|e| { + warn!(err=%e, "root node validation failed"); + StatusCode::BAD_REQUEST + })?; + + Ok(( + // headers + [ + ("cache-control", "max-age=31536000, immutable"), + ("content-type", nix_http::MIME_TYPE_NAR), + ], + if method == axum::http::Method::HEAD { + // If this is a HEAD request, construct a response returning back the + // user-provided content-length, but don't actually talk to castore. + Response::builder() + .header("content-length", nar_size) + .body(Body::empty()) + .unwrap() + } else if let Some(TypedHeader(ranges)) = ranges { + // If this is a range request, construct a seekable NAR reader. + let r = + tvix_store::nar::seekable::Reader::new(root_node, blob_service, directory_service) + .await + .map_err(|e| { + warn!(err=%e, "failed to construct seekable nar reader"); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + // ensure the user-supplied nar size was correct, no point returning data otherwise. + if r.stream_len() != nar_size { + warn!( + actual_nar_size = r.stream_len(), + supplied_nar_size = nar_size, + "wrong nar size supplied" + ); + return Err(StatusCode::BAD_REQUEST); + } + Ranged::new(Some(ranges), KnownSize::sized(r, nar_size)).into_response() + } else { + // use the non-seekable codepath if there's no range(s) requested, + // as it uses less memory. + let (w, r) = tokio::io::duplex(1024 * 8); + + // spawn a task rendering the NAR to the client. + tokio::spawn(async move { + if let Err(e) = + tvix_store::nar::write_nar(w, &root_node, blob_service, directory_service).await + { + warn!(err=%e, "failed to write out NAR"); + } + }); + + Response::builder() + .header("content-length", nar_size) + .body(Body::from_stream(ReaderStream::new(r))) + .unwrap() + }, + )) +} + +#[instrument(skip(blob_service, directory_service, request))] +pub async fn put( + axum::extract::Path(nar_str): axum::extract::Path<String>, + axum::extract::State(AppState { + blob_service, + directory_service, + root_nodes, + .. + }): axum::extract::State<AppState>, + request: axum::extract::Request, +) -> Result<&'static str, StatusCode> { + let (nar_hash_expected, compression_suffix) = + nix_http::parse_nar_str(&nar_str).ok_or(StatusCode::UNAUTHORIZED)?; + + // No paths with compression suffix are supported. + if !compression_suffix.is_empty() { + warn!(%compression_suffix, "invalid compression suffix requested"); + return Err(StatusCode::UNAUTHORIZED); + } + + let s = request.into_body().into_data_stream(); + + let mut r = tokio_util::io::StreamReader::new(s.map_err(|e| { + warn!(err=%e, "failed to read request body"); + io::Error::new(io::ErrorKind::BrokenPipe, e.to_string()) + })); + + // ingest the NAR + let (root_node, nar_hash_actual, nar_size) = + ingest_nar_and_hash(blob_service.clone(), directory_service.clone(), &mut r) + .await + .map_err(|e| io::Error::new(io::ErrorKind::Other, e)) + .map_err(|e| { + warn!(err=%e, "failed to ingest nar"); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + let s = Span::current(); + s.record("nar_hash.expected", nixbase32::encode(&nar_hash_expected)); + s.record("nar_size", nar_size); + + if nar_hash_expected != nar_hash_actual { + warn!( + nar_hash.expected = nixbase32::encode(&nar_hash_expected), + nar_hash.actual = nixbase32::encode(&nar_hash_actual), + "nar hash mismatch" + ); + return Err(StatusCode::BAD_REQUEST); + } + + // store mapping of narhash to root node into root_nodes. + // we need it later to populate the root node when accepting the PathInfo. + root_nodes.write().put(nar_hash_actual, root_node); + + Ok("") +} + +// FUTUREWORK: maybe head by narhash. Though not too critical, as we do +// implement HEAD for .narinfo. diff --git a/tvix/nar-bridge/src/narinfo.rs b/tvix/nar-bridge/src/narinfo.rs new file mode 100644 index 000000000000..76fda1d495c5 --- /dev/null +++ b/tvix/nar-bridge/src/narinfo.rs @@ -0,0 +1,153 @@ +use axum::{http::StatusCode, response::IntoResponse}; +use bytes::Bytes; +use nix_compat::{ + narinfo::{NarInfo, Signature}, + nix_http, nixbase32, + store_path::StorePath, +}; +use prost::Message; +use tracing::{instrument, warn, Span}; +use tvix_castore::proto::{self as castorepb}; +use tvix_store::pathinfoservice::PathInfo; + +use crate::AppState; + +/// The size limit for NARInfo uploads nar-bridge receives +const NARINFO_LIMIT: usize = 2 * 1024 * 1024; + +#[instrument(skip(path_info_service))] +pub async fn head( + axum::extract::Path(narinfo_str): axum::extract::Path<String>, + axum::extract::State(AppState { + path_info_service, .. + }): axum::extract::State<AppState>, +) -> Result<impl IntoResponse, StatusCode> { + let digest = nix_http::parse_narinfo_str(&narinfo_str).ok_or(StatusCode::NOT_FOUND)?; + Span::current().record("path_info.digest", &narinfo_str[0..32]); + + if path_info_service + .get(digest) + .await + .map_err(|e| { + warn!(err=%e, "failed to get PathInfo"); + StatusCode::INTERNAL_SERVER_ERROR + })? + .is_some() + { + Ok(([("content-type", nix_http::MIME_TYPE_NARINFO)], "")) + } else { + warn!("PathInfo not found"); + Err(StatusCode::NOT_FOUND) + } +} + +#[instrument(skip(path_info_service))] +pub async fn get( + axum::extract::Path(narinfo_str): axum::extract::Path<String>, + axum::extract::State(AppState { + path_info_service, .. + }): axum::extract::State<AppState>, +) -> Result<impl IntoResponse, StatusCode> { + let digest = nix_http::parse_narinfo_str(&narinfo_str).ok_or(StatusCode::NOT_FOUND)?; + Span::current().record("path_info.digest", &narinfo_str[0..32]); + + // fetch the PathInfo + let path_info = path_info_service + .get(digest) + .await + .map_err(|e| { + warn!(err=%e, "failed to get PathInfo"); + StatusCode::INTERNAL_SERVER_ERROR + })? + .ok_or(StatusCode::NOT_FOUND)?; + + let url = format!( + "nar/tvix-castore/{}?narsize={}", + data_encoding::BASE64URL_NOPAD.encode( + &castorepb::Node::from_name_and_node("".into(), path_info.node.clone()).encode_to_vec() + ), + path_info.nar_size, + ); + + let mut narinfo = path_info.to_narinfo(); + narinfo.url = &url; + + Ok(( + [("content-type", nix_http::MIME_TYPE_NARINFO)], + narinfo.to_string(), + )) +} + +#[instrument(skip(path_info_service, root_nodes, request))] +pub async fn put( + axum::extract::Path(narinfo_str): axum::extract::Path<String>, + axum::extract::State(AppState { + path_info_service, + root_nodes, + .. + }): axum::extract::State<AppState>, + request: axum::extract::Request, +) -> Result<&'static str, StatusCode> { + let _narinfo_digest = nix_http::parse_narinfo_str(&narinfo_str).ok_or(StatusCode::UNAUTHORIZED); + Span::current().record("path_info.digest", &narinfo_str[0..32]); + + let narinfo_bytes: Bytes = axum::body::to_bytes(request.into_body(), NARINFO_LIMIT) + .await + .map_err(|e| { + warn!(err=%e, "unable to fetch body"); + StatusCode::BAD_REQUEST + })?; + + // Parse the narinfo from the body. + let narinfo_str = std::str::from_utf8(narinfo_bytes.as_ref()).map_err(|e| { + warn!(err=%e, "unable decode body as string"); + StatusCode::BAD_REQUEST + })?; + + let narinfo = NarInfo::parse(narinfo_str).map_err(|e| { + warn!(err=%e, "unable to parse narinfo"); + StatusCode::BAD_REQUEST + })?; + + // Extract the NARHash from the PathInfo. + Span::current().record("path_info.nar_info", nixbase32::encode(&narinfo.nar_hash)); + + // Lookup root node with peek, as we don't want to update the LRU list. + // We need to be careful to not hold the RwLock across the await point. + let maybe_root_node: Option<tvix_castore::Node> = + root_nodes.read().peek(&narinfo.nar_hash).cloned(); + + match maybe_root_node { + Some(root_node) => { + // Persist the PathInfo. + path_info_service + .put(PathInfo { + store_path: narinfo.store_path.to_owned(), + node: root_node, + references: narinfo.references.iter().map(StorePath::to_owned).collect(), + nar_sha256: narinfo.nar_hash, + nar_size: narinfo.nar_size, + signatures: narinfo + .signatures + .into_iter() + .map(|s| { + Signature::<String>::new(s.name().to_string(), s.bytes().to_owned()) + }) + .collect(), + deriver: narinfo.deriver.as_ref().map(StorePath::to_owned), + ca: narinfo.ca, + }) + .await + .map_err(|e| { + warn!(err=%e, "failed to persist the PathInfo"); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + Ok("") + } + None => { + warn!("received narinfo with unknown NARHash"); + Err(StatusCode::BAD_REQUEST) + } + } +} diff --git a/tvix/nar-bridge/testdata/emptydirectory.nar b/tvix/nar-bridge/testdata/emptydirectory.nar deleted file mode 100644 index baba55862255..000000000000 --- a/tvix/nar-bridge/testdata/emptydirectory.nar +++ /dev/null Binary files differdiff --git a/tvix/nar-bridge/testdata/nar_1094wph9z4nwlgvsd53abfz8i117ykiv5dwnq9nnhz846s7xqd7d.nar b/tvix/nar-bridge/testdata/nar_1094wph9z4nwlgvsd53abfz8i117ykiv5dwnq9nnhz846s7xqd7d.nar deleted file mode 100644 index 6cb0b16e5d5d..000000000000 --- a/tvix/nar-bridge/testdata/nar_1094wph9z4nwlgvsd53abfz8i117ykiv5dwnq9nnhz846s7xqd7d.nar +++ /dev/null Binary files differdiff --git a/tvix/nar-bridge/testdata/onebyteexecutable.nar b/tvix/nar-bridge/testdata/onebyteexecutable.nar deleted file mode 100644 index 68682196665c..000000000000 --- a/tvix/nar-bridge/testdata/onebyteexecutable.nar +++ /dev/null Binary files differdiff --git a/tvix/nar-bridge/testdata/onebyteregular.nar b/tvix/nar-bridge/testdata/onebyteregular.nar deleted file mode 100644 index b8c94932bf0c..000000000000 --- a/tvix/nar-bridge/testdata/onebyteregular.nar +++ /dev/null Binary files differdiff --git a/tvix/nar-bridge/testdata/popdirectories.nar b/tvix/nar-bridge/testdata/popdirectories.nar deleted file mode 100644 index 74313aca529f..000000000000 --- a/tvix/nar-bridge/testdata/popdirectories.nar +++ /dev/null Binary files differdiff --git a/tvix/nar-bridge/testdata/symlink.nar b/tvix/nar-bridge/testdata/symlink.nar deleted file mode 100644 index 7990e4ad5bc2..000000000000 --- a/tvix/nar-bridge/testdata/symlink.nar +++ /dev/null Binary files differdiff --git a/tvix/nix-compat-derive-tests/Cargo.toml b/tvix/nix-compat-derive-tests/Cargo.toml new file mode 100644 index 000000000000..e69cb10e4fea --- /dev/null +++ b/tvix/nix-compat-derive-tests/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "nix-compat-derive-tests" +version = "0.1.0" +edition = "2021" + +[features] +compile-tests = [] + +[dev-dependencies] +hex-literal = { workspace = true } +pretty_assertions = { workspace = true } +rstest = { workspace = true } +tokio-test = { workspace = true } +trybuild = { workspace = true } +tokio = { workspace = true, features = ["io-util", "macros"] } + +[dev-dependencies.nix-compat] +version = "0.1.0" +path = "../nix-compat" +features = ["test", "wire"] + +[dev-dependencies.nix-compat-derive] +version = "0.1.0" +path = "../nix-compat-derive" diff --git a/tvix/nix-compat-derive-tests/default.nix b/tvix/nix-compat-derive-tests/default.nix new file mode 100644 index 000000000000..cabe9ad13780 --- /dev/null +++ b/tvix/nix-compat-derive-tests/default.nix @@ -0,0 +1,5 @@ +{ depot, ... }: + +depot.tvix.crates.workspaceMembers.nix-compat-derive-tests.build.override { + runTests = true; +} diff --git a/tvix/nix-compat-derive-tests/tests/read_derive.rs b/tvix/nix-compat-derive-tests/tests/read_derive.rs new file mode 100644 index 000000000000..055d70cf046e --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/read_derive.rs @@ -0,0 +1,417 @@ +use std::str::FromStr; + +use nix_compat::nix_daemon::de::mock::{Builder, Error}; +use nix_compat::nix_daemon::de::NixRead; +use nix_compat_derive::NixDeserialize; + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct UnitTest; + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct EmptyTupleTest(); + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct StructTest { + first: u64, + second: String, +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct TupleTest(u64, String); + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct StructVersionTest { + test: u64, + #[nix(version = "20..")] + hello: String, +} + +fn default_test() -> StructVersionTest { + StructVersionTest { + test: 89, + hello: String::from("klomp"), + } +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct TupleVersionTest(u64, #[nix(version = "25..")] String); + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct TupleVersionDefaultTest( + u64, + #[nix(version = "..25", default = "default_test")] StructVersionTest, +); + +#[tokio::test] +async fn read_unit() { + let mut mock = Builder::new().build(); + let v: UnitTest = mock.read_value().await.unwrap(); + assert_eq!(UnitTest, v); +} + +#[tokio::test] +async fn read_empty_tuple() { + let mut mock = Builder::new().build(); + let v: EmptyTupleTest = mock.read_value().await.unwrap(); + assert_eq!(EmptyTupleTest(), v); +} + +#[tokio::test] +async fn read_struct() { + let mut mock = Builder::new().read_number(89).read_slice(b"klomp").build(); + let v: StructTest = mock.read_value().await.unwrap(); + assert_eq!( + StructTest { + first: 89, + second: String::from("klomp"), + }, + v + ); +} + +#[tokio::test] +async fn read_tuple() { + let mut mock = Builder::new().read_number(89).read_slice(b"klomp").build(); + let v: TupleTest = mock.read_value().await.unwrap(); + assert_eq!(TupleTest(89, String::from("klomp")), v); +} + +#[tokio::test] +async fn read_struct_version() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(89) + .read_slice(b"klomp") + .build(); + let v: StructVersionTest = mock.read_value().await.unwrap(); + assert_eq!(default_test(), v); +} + +#[tokio::test] +async fn read_struct_without_version() { + let mut mock = Builder::new().version((1, 19)).read_number(89).build(); + let v: StructVersionTest = mock.read_value().await.unwrap(); + assert_eq!( + StructVersionTest { + test: 89, + hello: String::new(), + }, + v + ); +} + +#[tokio::test] +async fn read_tuple_version() { + let mut mock = Builder::new() + .version((1, 26)) + .read_number(89) + .read_slice(b"klomp") + .build(); + let v: TupleVersionTest = mock.read_value().await.unwrap(); + assert_eq!(TupleVersionTest(89, "klomp".into()), v); +} + +#[tokio::test] +async fn read_tuple_without_version() { + let mut mock = Builder::new().version((1, 19)).read_number(89).build(); + let v: TupleVersionTest = mock.read_value().await.unwrap(); + assert_eq!(TupleVersionTest(89, String::new()), v); +} + +#[tokio::test] +async fn read_complex_1() { + let mut mock = Builder::new() + .version((1, 19)) + .read_number(999) + .read_number(666) + .build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 666, + hello: String::new() + } + ), + v + ); +} + +#[tokio::test] +async fn read_complex_2() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(999) + .read_number(666) + .read_slice(b"The quick brown \xF0\x9F\xA6\x8A jumps over 13 lazy \xF0\x9F\x90\xB6.") + .build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 666, + hello: String::from("The quick brown 🦊 jumps over 13 lazy ðŸ¶.") + } + ), + v + ); +} + +#[tokio::test] +async fn read_complex_3() { + let mut mock = Builder::new().version((1, 25)).read_number(999).build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 89, + hello: String::from("klomp") + } + ), + v + ); +} + +#[tokio::test] +async fn read_complex_4() { + let mut mock = Builder::new().version((1, 26)).read_number(999).build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 89, + hello: String::from("klomp") + } + ), + v + ); +} + +#[tokio::test] +async fn read_field_invalid_data() { + let mut mock = Builder::new() + .read_number(666) + .read_slice(b"The quick brown \xED\xA0\x80 jumped.") + .build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!( + Error::InvalidData("invalid utf-8 sequence of 1 bytes from index 16".into()), + err + ); +} + +#[tokio::test] +async fn read_field_missing_data() { + let mut mock = Builder::new().read_number(666).build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::MissingData("unexpected end-of-file".into()), err); +} + +#[tokio::test] +async fn read_field_no_data() { + let mut mock = Builder::new().build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::MissingData("unexpected end-of-file".into()), err); +} + +#[tokio::test] +async fn read_field_reader_error_first() { + let mut mock = Builder::new() + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[tokio::test] +async fn read_field_reader_error_later() { + let mut mock = Builder::new() + .read_number(999) + .read_bytes_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +#[nix(from_str)] +struct TestFromStr; + +impl FromStr for TestFromStr { + type Err = String; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + if s == "test" { + Ok(TestFromStr) + } else { + Err(s.into()) + } + } +} + +#[tokio::test] +async fn read_from_str() { + let mut mock = Builder::new().read_slice(b"test").build(); + let value = mock.read_value::<TestFromStr>().await.unwrap(); + assert_eq!(TestFromStr, value); +} + +#[tokio::test] +async fn read_from_str_invalid_data() { + let mut mock = Builder::new().read_slice(b"wrong string").build(); + let err = mock.read_value::<TestFromStr>().await.unwrap_err(); + assert_eq!(Error::InvalidData("wrong string".into()), err); +} + +#[tokio::test] +async fn read_from_str_invalid_string() { + let mut mock = Builder::new() + .read_slice(b"The quick brown \xED\xA0\x80 jumped.") + .build(); + let err = mock.read_value::<TestFromStr>().await.unwrap_err(); + assert_eq!( + Error::InvalidData("invalid utf-8 sequence of 1 bytes from index 16".into()), + err + ); +} + +#[tokio::test] +async fn read_from_str_reader_error() { + let mut mock = Builder::new() + .read_bytes_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestFromStr>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +#[nix(try_from = "u64")] +struct TestTryFromU64; + +impl TryFrom<u64> for TestTryFromU64 { + type Error = u64; + + fn try_from(value: u64) -> Result<TestTryFromU64, Self::Error> { + if value == 42 { + Ok(TestTryFromU64) + } else { + Err(value) + } + } +} + +#[tokio::test] +async fn read_try_from_u64() { + let mut mock = Builder::new().read_number(42).build(); + let value = mock.read_value::<TestTryFromU64>().await.unwrap(); + assert_eq!(TestTryFromU64, value); +} + +#[tokio::test] +async fn read_try_from_u64_invalid_data() { + let mut mock = Builder::new().read_number(666).build(); + let err = mock.read_value::<TestTryFromU64>().await.unwrap_err(); + assert_eq!(Error::InvalidData("666".into()), err); +} + +#[tokio::test] +async fn read_try_from_u64_reader_error() { + let mut mock = Builder::new() + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestTryFromU64>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +#[nix(from = "u64")] +struct TestFromU64; + +impl From<u64> for TestFromU64 { + fn from(_value: u64) -> TestFromU64 { + TestFromU64 + } +} + +#[tokio::test] +async fn read_from_u64() { + let mut mock = Builder::new().read_number(42).build(); + let value = mock.read_value::<TestFromU64>().await.unwrap(); + assert_eq!(TestFromU64, value); +} + +#[tokio::test] +async fn read_from_u64_reader_error() { + let mut mock = Builder::new() + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestFromU64>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +enum TestEnum { + #[nix(version = "..=19")] + Pre20(TestTryFromU64), + #[nix(version = "20..")] + Post20(StructVersionTest), +} + +#[tokio::test] +async fn read_enum_19() { + let mut mock = Builder::new().version((1, 19)).read_number(42).build(); + let value = mock.read_value::<TestEnum>().await.unwrap(); + assert_eq!(TestEnum::Pre20(TestTryFromU64), value); +} + +#[tokio::test] +async fn read_enum_20() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(42) + .read_slice(b"klomp") + .build(); + let value = mock.read_value::<TestEnum>().await.unwrap(); + assert_eq!( + TestEnum::Post20(StructVersionTest { + test: 42, + hello: "klomp".into(), + }), + value + ); +} + +#[tokio::test] +async fn read_enum_reader_error() { + let mut mock = Builder::new() + .version((1, 19)) + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestEnum>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[tokio::test] +async fn read_enum_invalid_data_19() { + let mut mock = Builder::new().version((1, 19)).read_number(666).build(); + let err = mock.read_value::<TestEnum>().await.unwrap_err(); + assert_eq!(Error::InvalidData("666".into()), err); +} + +#[tokio::test] +async fn read_enum_invalid_data_20() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(666) + .read_slice(b"The quick brown \xED\xA0\x80 jumped.") + .build(); + let err = mock.read_value::<TestEnum>().await.unwrap_err(); + assert_eq!( + Error::InvalidData("invalid utf-8 sequence of 1 bytes from index 16".into()), + err + ); +} diff --git a/tvix/nix-compat-derive-tests/tests/ui.rs b/tvix/nix-compat-derive-tests/tests/ui.rs new file mode 100644 index 000000000000..6a7bffeaf832 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui.rs @@ -0,0 +1,6 @@ +#[cfg(feature = "compile-tests")] +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.rs new file mode 100644 index 000000000000..f77469679999 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.rs @@ -0,0 +1,10 @@ +use nix_compat_derive::NixDeserialize; + +pub struct BadType; + +#[derive(NixDeserialize)] +pub struct Test { + version: BadType, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.stderr new file mode 100644 index 000000000000..12ffdc83c726 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `BadType: NixDeserialize` is not satisfied + --> tests/ui/deserialize_bad_type.rs:7:14 + | +7 | version: BadType, + | ^^^^^^^ the trait `NixDeserialize` is not implemented for `BadType` + | + = help: the following other types implement trait `NixDeserialize`: + BTreeMap<K, V> + String + Test + Vec<T> + bool + bytes::bytes::Bytes + i64 + u64 + usize +note: required by a bound in `try_read_value` + --> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs + | + | fn try_read_value<V: NixDeserialize>( + | ^^^^^^^^^^^^^^ required by this bound in `NixRead::try_read_value` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.rs new file mode 100644 index 000000000000..ab559f2b81c8 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.rs @@ -0,0 +1,13 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub enum Test { + #[nix(version = "..=10")] + Old, + #[nix(version = "15..=17")] + Legacy, + #[nix(version = "50..")] + NewWay, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.stderr new file mode 100644 index 000000000000..8a46d9439e35 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.stderr @@ -0,0 +1,8 @@ +error[E0004]: non-exhaustive patterns: `11_u8..=14_u8` and `18_u8..=49_u8` not covered + --> tests/ui/deserialize_enum_non_exaustive.rs:3:10 + | +3 | #[derive(NixDeserialize)] + | ^^^^^^^^^^^^^^ patterns `11_u8..=14_u8` and `18_u8..=49_u8` not covered + | + = note: the matched value is of type `u8` + = note: this error originates in the derive macro `NixDeserialize` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.rs new file mode 100644 index 000000000000..913b7c4f7e59 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.rs @@ -0,0 +1,7 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(from = "u64")] +pub struct Test; + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.stderr new file mode 100644 index 000000000000..0124010cf10c --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.stderr @@ -0,0 +1,5 @@ +error[E0277]: the trait bound `Test: From<u64>` is not satisfied + --> tests/ui/deserialize_from_missing.rs:4:14 + | +4 | #[nix(from = "u64")] + | ^^^^^ the trait `From<u64>` is not implemented for `Test` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.rs new file mode 100644 index 000000000000..36cd4b153740 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.rs @@ -0,0 +1,20 @@ +use std::str::FromStr; + +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(from_str)] +pub struct Test; + +impl FromStr for Test { + type Err = (); + fn from_str(s: &str) -> Result<Self, Self::Err> { + if s == "test" { + Ok(Test) + } else { + Err(()) + } + } +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.stderr new file mode 100644 index 000000000000..8283ed5340f3 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.stderr @@ -0,0 +1,13 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> tests/ui/deserialize_from_str_error_not_display.rs:6:7 + | +6 | #[nix(from_str)] + | ^^^^^^^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `invalid_data` + --> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs + | + | fn invalid_data<T: fmt::Display>(msg: T) -> Self { + | ^^^^^^^^^^^^ required by this bound in `Error::invalid_data` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.rs new file mode 100644 index 000000000000..a959db57e640 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.rs @@ -0,0 +1,7 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(from_str)] +pub struct Test; + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.stderr new file mode 100644 index 000000000000..f68f588011fc --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `Test: FromStr` is not satisfied + --> tests/ui/deserialize_from_str_missing.rs:4:7 + | +4 | #[nix(from_str)] + | ^^^^^^^^ the trait `FromStr` is not implemented for `Test` + | + = help: the following other types implement trait `FromStr`: + IpAddr + Ipv4Addr + Ipv6Addr + NonZero<i128> + NonZero<i16> + NonZero<i32> + NonZero<i64> + NonZero<i8> + and $N others diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.rs new file mode 100644 index 000000000000..e9df62845518 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.rs @@ -0,0 +1,12 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Value(String); + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version = "20..")] + version: Value, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.stderr new file mode 100644 index 000000000000..5cc2f5974e4c --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Value: Default` is not satisfied + --> tests/ui/deserialize_missing_default.rs:6:10 + | +6 | #[derive(NixDeserialize)] + | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Value` + | + = note: this error originates in the derive macro `NixDeserialize` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Value` with `#[derive(Default)]` + | +4 + #[derive(Default)] +5 | pub struct Value(String); + | diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.rs new file mode 100644 index 000000000000..4f319c069dca --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.rs @@ -0,0 +1,12 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Value(String); + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version = "20..", default = "Value::make_default")] + version: Value, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.stderr new file mode 100644 index 000000000000..bb9af749128d --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.stderr @@ -0,0 +1,8 @@ +error[E0599]: no function or associated item named `make_default` found for struct `Value` in the current scope + --> tests/ui/deserialize_missing_default_path.rs:8:39 + | +4 | pub struct Value(String); + | ---------------- function or associated item `make_default` not found for this struct +... +8 | #[nix(version = "20..", default = "Value::make_default")] + | ^^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `Value` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.rs new file mode 100644 index 000000000000..cc2ab5bfbc11 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.rs @@ -0,0 +1,15 @@ +use nix_compat_derive::nix_deserialize_remote; + +pub struct Value(String); +impl From<String> for Value { + fn from(s: String) -> Value { + Value(s) + } +} + +nix_deserialize_remote!( + #[nix()] + Value +); + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.stderr new file mode 100644 index 000000000000..a1c18adc6e48 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.stderr @@ -0,0 +1,5 @@ +error: Missing from_str, from or try_from attribute + --> tests/ui/deserialize_remote_missing_attr.rs:10:25 + | +10 | nix_deserialize_remote!(#[nix()] Value); + | ^^^^^^^^^^^^^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.rs new file mode 100644 index 000000000000..7f8ad6bbfc4e --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.rs @@ -0,0 +1,19 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(try_from = "u64")] +pub struct Test; + +impl TryFrom<u64> for Test { + type Error = (); + + fn try_from(value: u64) -> Result<Test, Self::Error> { + if value == 42 { + Ok(Test) + } else { + Err(()) + } + } +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.stderr new file mode 100644 index 000000000000..8e55a3c56189 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.stderr @@ -0,0 +1,13 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> tests/ui/deserialize_try_from_error_not_display.rs:4:18 + | +4 | #[nix(try_from = "u64")] + | ^^^^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `invalid_data` + --> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs + | + | fn invalid_data<T: fmt::Display>(msg: T) -> Self { + | ^^^^^^^^^^^^ required by this bound in `Error::invalid_data` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.rs new file mode 100644 index 000000000000..899095ae3542 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.rs @@ -0,0 +1,7 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(try_from = "u64")] +pub struct Test; + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.stderr new file mode 100644 index 000000000000..9605d1f3378f --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.stderr @@ -0,0 +1,8 @@ +error[E0277]: the trait bound `Test: From<u64>` is not satisfied + --> tests/ui/deserialize_try_from_missing.rs:4:18 + | +4 | #[nix(try_from = "u64")] + | ^^^^^ the trait `From<u64>` is not implemented for `Test`, which is required by `Test: TryFrom<u64>` + | + = note: required for `u64` to implement `Into<Test>` + = note: required for `Test` to implement `TryFrom<u64>` diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.rs new file mode 100644 index 000000000000..d87831cecf51 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(default = 12)] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.stderr new file mode 100644 index 000000000000..acb1bc2a47bc --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.stderr @@ -0,0 +1,5 @@ +error: expected nix attribute default to be string + --> tests/ui/parse_bad_default.rs:5:21 + | +5 | #[nix(default = 12)] + | ^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.rs new file mode 100644 index 000000000000..fbde8ffbc2b0 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(default = "12")] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.stderr new file mode 100644 index 000000000000..7628d4c83bea --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.stderr @@ -0,0 +1,5 @@ +error: expected identifier + --> tests/ui/parse_bad_default_path.rs:5:21 + | +5 | #[nix(default = "12")] + | ^^^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.rs new file mode 100644 index 000000000000..690e76a20fe6 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.stderr new file mode 100644 index 000000000000..da3d2d9aab47 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.stderr @@ -0,0 +1,5 @@ +error: expected attribute arguments in parentheses: #[nix(...)] + --> tests/ui/parse_bad_nix.rs:5:7 + | +5 | #[nix] + | ^^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.rs new file mode 100644 index 000000000000..35b3b05c23e1 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version = 12)] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.stderr new file mode 100644 index 000000000000..48cc817fac9d --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.stderr @@ -0,0 +1,5 @@ +error: expected nix attribute version to be string + --> tests/ui/parse_bad_version.rs:5:21 + | +5 | #[nix(version = 12)] + | ^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.rs new file mode 100644 index 000000000000..9eaa743ed2b6 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version)] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.stderr new file mode 100644 index 000000000000..79f048e11198 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.stderr @@ -0,0 +1,5 @@ +error: expected `=` + --> tests/ui/parse_mising_version.rs:5:18 + | +5 | #[nix(version)] + | ^ diff --git a/tvix/nix-compat-derive/Cargo.toml b/tvix/nix-compat-derive/Cargo.toml new file mode 100644 index 000000000000..da6d6744e650 --- /dev/null +++ b/tvix/nix-compat-derive/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "nix-compat-derive" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = { workspace = true, features = ["proc-macro"] } +quote = { workspace = true, features = ["proc-macro"] } +syn = { version = "2.0.76", features = ["full", "extra-traits"] } + +[dev-dependencies] +hex-literal = { workspace = true } +pretty_assertions = { workspace = true } +rstest = { workspace = true } +tokio-test = { workspace = true } +tokio = { workspace = true, features = ["io-util", "macros"] } + +[dev-dependencies.nix-compat] +path = "../nix-compat" +default-features = false +features = ["async", "wire", "test"] diff --git a/tvix/nix-compat-derive/default.nix b/tvix/nix-compat-derive/default.nix new file mode 100644 index 000000000000..e6636e7f2510 --- /dev/null +++ b/tvix/nix-compat-derive/default.nix @@ -0,0 +1,5 @@ +{ depot, lib, ... }: + +depot.tvix.crates.workspaceMembers.nix-compat-derive.build.override { + runTests = true; +} diff --git a/tvix/nix-compat-derive/src/de.rs b/tvix/nix-compat-derive/src/de.rs new file mode 100644 index 000000000000..ee79ea9d1012 --- /dev/null +++ b/tvix/nix-compat-derive/src/de.rs @@ -0,0 +1,272 @@ +use proc_macro2::{Span, TokenStream}; +use quote::{quote, quote_spanned, ToTokens}; +use syn::spanned::Spanned; +use syn::{DeriveInput, Generics, Path, Type}; + +use crate::internal::attrs::Default; +use crate::internal::inputs::RemoteInput; +use crate::internal::{attrs, Container, Context, Data, Field, Remote, Style, Variant}; + +pub fn expand_nix_deserialize(nnixrs: Path, input: &mut DeriveInput) -> syn::Result<TokenStream> { + let cx = Context::new(); + let cont = Container::from_ast(&cx, nnixrs, input); + cx.check()?; + let cont = cont.unwrap(); + + let ty = cont.ident_type(); + let body = nix_deserialize_body(&cont); + let crate_path = cont.crate_path(); + + Ok(nix_deserialize_impl( + crate_path, + &ty, + &cont.original.generics, + body, + )) +} + +pub fn expand_nix_deserialize_remote( + crate_path: Path, + input: &RemoteInput, +) -> syn::Result<TokenStream> { + let cx = Context::new(); + let remote = Remote::from_ast(&cx, crate_path, input); + cx.check()?; + let remote = remote.unwrap(); + + let crate_path = remote.crate_path(); + let body = nix_deserialize_body_from(crate_path, &remote.attrs).expect("From tokenstream"); + let generics = Generics::default(); + Ok(nix_deserialize_impl(crate_path, remote.ty, &generics, body)) +} + +fn nix_deserialize_impl( + crate_path: &Path, + ty: &Type, + generics: &Generics, + body: TokenStream, +) -> TokenStream { + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + #[automatically_derived] + impl #impl_generics #crate_path::nix_daemon::de::NixDeserialize for #ty #ty_generics + #where_clause + { + #[allow(clippy::manual_async_fn)] + fn try_deserialize<R>(reader: &mut R) -> impl ::std::future::Future<Output=Result<Option<Self>, R::Error>> + Send + '_ + where R: ?Sized + #crate_path::nix_daemon::de::NixRead + Send, + { + #body + } + } + } +} + +fn nix_deserialize_body_from( + crate_path: &syn::Path, + attrs: &attrs::Container, +) -> Option<TokenStream> { + if let Some(span) = attrs.from_str.as_ref() { + Some(nix_deserialize_from_str(crate_path, span.span())) + } else if let Some(type_from) = attrs.type_from.as_ref() { + Some(nix_deserialize_from(type_from)) + } else { + attrs + .type_try_from + .as_ref() + .map(|type_try_from| nix_deserialize_try_from(crate_path, type_try_from)) + } +} + +fn nix_deserialize_body(cont: &Container) -> TokenStream { + if let Some(tokens) = nix_deserialize_body_from(cont.crate_path(), &cont.attrs) { + tokens + } else { + match &cont.data { + Data::Struct(style, fields) => nix_deserialize_struct(*style, fields), + Data::Enum(variants) => nix_deserialize_enum(variants), + } + } +} + +fn nix_deserialize_struct(style: Style, fields: &[Field<'_>]) -> TokenStream { + let read_fields = fields.iter().map(|f| { + let field = f.var_ident(); + let ty = f.ty; + let read_value = quote_spanned! { + ty.span()=> if first__ { + first__ = false; + if let Some(v) = reader.try_read_value::<#ty>().await? { + v + } else { + return Ok(None); + } + } else { + reader.read_value::<#ty>().await? + } + }; + if let Some(version) = f.attrs.version.as_ref() { + let default = match &f.attrs.default { + Default::Default => quote_spanned!(ty.span()=>::std::default::Default::default), + Default::Path(path) => path.to_token_stream(), + _ => panic!("No default for versioned field"), + }; + quote! { + let #field : #ty = if (#version).contains(&reader.version().minor()) { + #read_value + } else { + #default() + }; + } + } else { + quote! { + let #field : #ty = #read_value; + } + } + }); + + let field_names = fields.iter().map(|f| f.var_ident()); + let construct = match style { + Style::Struct => { + quote! { + Self { #(#field_names),* } + } + } + Style::Tuple => { + quote! { + Self(#(#field_names),*) + } + } + Style::Unit => quote!(Self), + }; + quote! { + #[allow(unused_assignments)] + async move { + let mut first__ = true; + #(#read_fields)* + Ok(Some(#construct)) + } + } +} + +fn nix_deserialize_variant(variant: &Variant<'_>) -> TokenStream { + let ident = variant.ident; + let read_fields = variant.fields.iter().map(|f| { + let field = f.var_ident(); + let ty = f.ty; + let read_value = quote_spanned! { + ty.span()=> if first__ { + first__ = false; + if let Some(v) = reader.try_read_value::<#ty>().await? { + v + } else { + return Ok(None); + } + } else { + reader.read_value::<#ty>().await? + } + }; + if let Some(version) = f.attrs.version.as_ref() { + let default = match &f.attrs.default { + Default::Default => quote_spanned!(ty.span()=>::std::default::Default::default), + Default::Path(path) => path.to_token_stream(), + _ => panic!("No default for versioned field"), + }; + quote! { + let #field : #ty = if (#version).contains(&reader.version().minor()) { + #read_value + } else { + #default() + }; + } + } else { + quote! { + let #field : #ty = #read_value; + } + } + }); + let field_names = variant.fields.iter().map(|f| f.var_ident()); + let construct = match variant.style { + Style::Struct => { + quote! { + Self::#ident { #(#field_names),* } + } + } + Style::Tuple => { + quote! { + Self::#ident(#(#field_names),*) + } + } + Style::Unit => quote!(Self::#ident), + }; + let version = &variant.attrs.version; + quote! { + #version => { + #(#read_fields)* + Ok(Some(#construct)) + } + } +} + +fn nix_deserialize_enum(variants: &[Variant<'_>]) -> TokenStream { + let match_variant = variants + .iter() + .map(|variant| nix_deserialize_variant(variant)); + quote! { + #[allow(unused_assignments)] + async move { + let mut first__ = true; + match reader.version().minor() { + #(#match_variant)* + } + } + } +} + +fn nix_deserialize_from(ty: &Type) -> TokenStream { + quote_spanned! { + ty.span() => + async move { + if let Some(value) = reader.try_read_value::<#ty>().await? { + Ok(Some(<Self as ::std::convert::From<#ty>>::from(value))) + } else { + Ok(None) + } + } + } +} + +fn nix_deserialize_try_from(crate_path: &Path, ty: &Type) -> TokenStream { + quote_spanned! { + ty.span() => + async move { + use #crate_path::nix_daemon::de::Error; + if let Some(item) = reader.try_read_value::<#ty>().await? { + <Self as ::std::convert::TryFrom<#ty>>::try_from(item) + .map_err(Error::invalid_data) + .map(Some) + } else { + Ok(None) + } + } + } +} + +fn nix_deserialize_from_str(crate_path: &Path, span: Span) -> TokenStream { + quote_spanned! { + span => + async move { + use #crate_path::nix_daemon::de::Error; + if let Some(buf) = reader.try_read_bytes().await? { + let s = ::std::str::from_utf8(&buf) + .map_err(Error::invalid_data)?; + <Self as ::std::str::FromStr>::from_str(s) + .map_err(Error::invalid_data) + .map(Some) + } else { + Ok(None) + } + } + } +} diff --git a/tvix/nix-compat-derive/src/internal/attrs.rs b/tvix/nix-compat-derive/src/internal/attrs.rs new file mode 100644 index 000000000000..dbc959d1e917 --- /dev/null +++ b/tvix/nix-compat-derive/src/internal/attrs.rs @@ -0,0 +1,358 @@ +use quote::ToTokens; +use syn::meta::ParseNestedMeta; +use syn::parse::Parse; +use syn::{parse_quote, Attribute, Expr, ExprLit, ExprPath, Lit, Token}; + +use super::symbol::{Symbol, CRATE, DEFAULT, FROM, FROM_STR, NIX, TRY_FROM, VERSION}; +use super::Context; + +#[derive(Debug, PartialEq, Eq)] +pub enum Default { + None, + #[allow(clippy::enum_variant_names)] + Default, + Path(ExprPath), +} + +impl Default { + pub fn is_none(&self) -> bool { + matches!(self, Default::None) + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Field { + pub default: Default, + pub version: Option<syn::ExprRange>, +} + +impl Field { + pub fn from_ast(ctx: &Context, attrs: &Vec<Attribute>) -> Field { + let mut version = None; + let mut default = Default::None; + for attr in attrs { + if attr.path() != NIX { + continue; + } + if let Err(err) = attr.parse_nested_meta(|meta| { + if meta.path == VERSION { + version = parse_lit(ctx, &meta, VERSION)?; + } else if meta.path == DEFAULT { + if meta.input.peek(Token![=]) { + if let Some(path) = parse_lit(ctx, &meta, DEFAULT)? { + default = Default::Path(path); + } + } else { + default = Default::Default; + } + } else { + let path = meta.path.to_token_stream().to_string(); + return Err(meta.error(format_args!("unknown nix field attribute '{}'", path))); + } + Ok(()) + }) { + eprintln!("{:?}", err.span().source_text()); + ctx.syn_error(err); + } + } + if version.is_some() && default.is_none() { + default = Default::Default; + } + + Field { default, version } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Variant { + pub version: syn::ExprRange, +} + +impl Variant { + pub fn from_ast(ctx: &Context, attrs: &Vec<Attribute>) -> Variant { + let mut version = parse_quote!(..); + for attr in attrs { + if attr.path() != NIX { + continue; + } + if let Err(err) = attr.parse_nested_meta(|meta| { + if meta.path == VERSION { + if let Some(v) = parse_lit(ctx, &meta, VERSION)? { + version = v; + } + } else { + let path = meta.path.to_token_stream().to_string(); + return Err( + meta.error(format_args!("unknown nix variant attribute '{}'", path)) + ); + } + Ok(()) + }) { + eprintln!("{:?}", err.span().source_text()); + ctx.syn_error(err); + } + } + + Variant { version } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Container { + pub from_str: Option<syn::Path>, + pub type_from: Option<syn::Type>, + pub type_try_from: Option<syn::Type>, + pub crate_path: Option<syn::Path>, +} + +impl Container { + pub fn from_ast(ctx: &Context, attrs: &Vec<Attribute>) -> Container { + let mut type_from = None; + let mut type_try_from = None; + let mut crate_path = None; + let mut from_str = None; + + for attr in attrs { + if attr.path() != NIX { + continue; + } + if let Err(err) = attr.parse_nested_meta(|meta| { + if meta.path == FROM { + type_from = parse_lit(ctx, &meta, FROM)?; + } else if meta.path == TRY_FROM { + type_try_from = parse_lit(ctx, &meta, TRY_FROM)?; + } else if meta.path == FROM_STR { + from_str = Some(meta.path); + } else if meta.path == CRATE { + crate_path = parse_lit(ctx, &meta, CRATE)?; + } else { + let path = meta.path.to_token_stream().to_string(); + return Err( + meta.error(format_args!("unknown nix variant attribute '{}'", path)) + ); + } + Ok(()) + }) { + eprintln!("{:?}", err.span().source_text()); + ctx.syn_error(err); + } + } + + Container { + from_str, + type_from, + type_try_from, + crate_path, + } + } +} + +pub fn get_lit_str( + ctx: &Context, + meta: &ParseNestedMeta, + attr: Symbol, +) -> syn::Result<Option<syn::LitStr>> { + let expr: Expr = meta.value()?.parse()?; + let mut value = &expr; + while let Expr::Group(e) = value { + value = &e.expr; + } + if let Expr::Lit(ExprLit { + lit: Lit::Str(s), .. + }) = value + { + Ok(Some(s.clone())) + } else { + ctx.error_spanned( + expr, + format_args!("expected nix attribute {} to be string", attr), + ); + Ok(None) + } +} + +pub fn parse_lit<T: Parse>( + ctx: &Context, + meta: &ParseNestedMeta, + attr: Symbol, +) -> syn::Result<Option<T>> { + match get_lit_str(ctx, meta, attr)? { + Some(lit) => Ok(Some(lit.parse()?)), + None => Ok(None), + } +} + +#[cfg(test)] +mod test { + use syn::{parse_quote, Attribute}; + + use crate::internal::Context; + + use super::*; + + #[test] + fn parse_field_version() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(version="..34")])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::Default, + version: Some(parse_quote!(..34)), + } + ); + } + + #[test] + fn parse_field_default() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(default)])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::Default, + version: None, + } + ); + } + + #[test] + fn parse_field_default_path() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(default="Default::default")])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::Path(parse_quote!(Default::default)), + version: None, + } + ); + } + + #[test] + fn parse_field_both() { + let attrs: Vec<Attribute> = + vec![parse_quote!(#[nix(version="..", default="Default::default")])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::Path(parse_quote!(Default::default)), + version: Some(parse_quote!(..)), + } + ); + } + + #[test] + fn parse_field_both_rev() { + let attrs: Vec<Attribute> = + vec![parse_quote!(#[nix(default="Default::default", version="..")])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::Path(parse_quote!(Default::default)), + version: Some(parse_quote!(..)), + } + ); + } + + #[test] + fn parse_field_no_attr() { + let attrs: Vec<Attribute> = vec![]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::None, + version: None, + } + ); + } + + #[test] + fn parse_field_no_subattrs() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix()])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::None, + version: None, + } + ); + } + + #[test] + fn parse_variant_version() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(version="..34")])]; + let ctx = Context::new(); + let variant = Variant::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + variant, + Variant { + version: parse_quote!(..34), + } + ); + } + + #[test] + fn parse_variant_no_attr() { + let attrs: Vec<Attribute> = vec![]; + let ctx = Context::new(); + let variant = Variant::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + variant, + Variant { + version: parse_quote!(..), + } + ); + } + + #[test] + fn parse_variant_no_subattrs() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix()])]; + let ctx = Context::new(); + let variant = Variant::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + variant, + Variant { + version: parse_quote!(..), + } + ); + } + + #[test] + fn parse_container_try_from() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(try_from="u64")])]; + let ctx = Context::new(); + let container = Container::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + container, + Container { + from_str: None, + type_from: None, + type_try_from: Some(parse_quote!(u64)), + crate_path: None, + } + ); + } +} diff --git a/tvix/nix-compat-derive/src/internal/ctx.rs b/tvix/nix-compat-derive/src/internal/ctx.rs new file mode 100644 index 000000000000..ba770e044bc2 --- /dev/null +++ b/tvix/nix-compat-derive/src/internal/ctx.rs @@ -0,0 +1,50 @@ +use std::cell::RefCell; +use std::fmt; +use std::thread::panicking; + +use quote::ToTokens; + +pub struct Context { + errors: RefCell<Option<Vec<syn::Error>>>, +} + +impl Context { + pub fn new() -> Context { + Context { + errors: RefCell::new(Some(Vec::new())), + } + } + + pub fn syn_error(&self, error: syn::Error) { + self.errors + .borrow_mut() + .as_mut() + .take() + .unwrap() + .push(error); + } + + pub fn error_spanned<T: ToTokens, D: fmt::Display>(&self, tokens: T, message: D) { + self.syn_error(syn::Error::new_spanned(tokens, message)); + } + + pub fn check(&self) -> syn::Result<()> { + let mut iter = self.errors.borrow_mut().take().unwrap().into_iter(); + let mut err = match iter.next() { + None => return Ok(()), + Some(err) => err, + }; + for next_err in iter { + err.combine(next_err); + } + Err(err) + } +} + +impl Drop for Context { + fn drop(&mut self) { + if self.errors.borrow().is_some() && !panicking() { + panic!("Context dropped without checking errors"); + } + } +} diff --git a/tvix/nix-compat-derive/src/internal/inputs.rs b/tvix/nix-compat-derive/src/internal/inputs.rs new file mode 100644 index 000000000000..097a141a5d7c --- /dev/null +++ b/tvix/nix-compat-derive/src/internal/inputs.rs @@ -0,0 +1,110 @@ +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct RemoteInput { + pub attrs: Vec<syn::Attribute>, + pub ident: syn::Type, +} + +impl syn::parse::Parse for RemoteInput { + fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { + let attrs = input.call(syn::Attribute::parse_outer)?; + + let ident = input.parse::<syn::Type>()?; + Ok(RemoteInput { attrs, ident }) + } +} + +impl quote::ToTokens for RemoteInput { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + fn is_outer(attr: &&syn::Attribute) -> bool { + match attr.style { + syn::AttrStyle::Outer => true, + syn::AttrStyle::Inner(_) => false, + } + } + for attr in self.attrs.iter().filter(is_outer) { + attr.to_tokens(tokens); + } + self.ident.to_tokens(tokens); + } +} + +#[cfg(test)] +mod test { + use syn::parse_quote; + //use syn::parse::Parse; + + use super::*; + + #[test] + fn test_input() { + let p: RemoteInput = parse_quote!(u64); + assert_eq!( + p, + RemoteInput { + attrs: vec![], + ident: parse_quote!(u64), + } + ); + } + + #[test] + fn test_input_attr() { + let p: RemoteInput = parse_quote!( + #[nix] + u64 + ); + assert_eq!( + p, + RemoteInput { + attrs: vec![parse_quote!(#[nix])], + ident: parse_quote!(u64), + } + ); + } + + #[test] + fn test_input_attr_multiple() { + let p: RemoteInput = parse_quote!( + #[nix] + #[hello] + u64 + ); + assert_eq!( + p, + RemoteInput { + attrs: vec![parse_quote!(#[nix]), parse_quote!(#[hello])], + ident: parse_quote!(u64), + } + ); + } + + #[test] + fn test_input_attr_full() { + let p: RemoteInput = parse_quote!( + #[nix(try_from = "u64")] + usize + ); + assert_eq!( + p, + RemoteInput { + attrs: vec![parse_quote!(#[nix(try_from="u64")])], + ident: parse_quote!(usize), + } + ); + } + + #[test] + fn test_input_attr_other() { + let p: RemoteInput = parse_quote!( + #[muh] + u64 + ); + assert_eq!( + p, + RemoteInput { + attrs: vec![parse_quote!(#[muh])], + ident: parse_quote!(u64), + } + ); + } +} diff --git a/tvix/nix-compat-derive/src/internal/mod.rs b/tvix/nix-compat-derive/src/internal/mod.rs new file mode 100644 index 000000000000..20b243221619 --- /dev/null +++ b/tvix/nix-compat-derive/src/internal/mod.rs @@ -0,0 +1,183 @@ +use syn::punctuated::Punctuated; +use syn::spanned::Spanned; +use syn::Token; + +pub mod attrs; +mod ctx; +pub mod inputs; +mod symbol; + +pub use ctx::Context; + +pub struct Field<'a> { + pub member: syn::Member, + pub ty: &'a syn::Type, + pub attrs: attrs::Field, + pub original: &'a syn::Field, +} + +impl<'a> Field<'a> { + pub fn from_ast(ctx: &Context, idx: usize, field: &'a syn::Field) -> Field<'a> { + let attrs = attrs::Field::from_ast(ctx, &field.attrs); + let member = match &field.ident { + Some(id) => syn::Member::Named(id.clone()), + None => syn::Member::Unnamed(idx.into()), + }; + Field { + member, + attrs, + ty: &field.ty, + original: field, + } + } + + pub fn var_ident(&self) -> syn::Ident { + match &self.member { + syn::Member::Named(name) => name.clone(), + syn::Member::Unnamed(idx) => { + syn::Ident::new(&format!("field{}", idx.index), self.original.span()) + } + } + } +} + +pub struct Variant<'a> { + pub ident: &'a syn::Ident, + pub attrs: attrs::Variant, + pub style: Style, + pub fields: Vec<Field<'a>>, + //pub original: &'a syn::Variant, +} + +impl<'a> Variant<'a> { + pub fn from_ast(ctx: &Context, variant: &'a syn::Variant) -> Self { + let attrs = attrs::Variant::from_ast(ctx, &variant.attrs); + let (style, fields) = match &variant.fields { + syn::Fields::Named(fields) => (Style::Struct, fields_ast(ctx, &fields.named)), + syn::Fields::Unnamed(fields) => (Style::Tuple, fields_ast(ctx, &fields.unnamed)), + syn::Fields::Unit => (Style::Unit, Vec::new()), + }; + Variant { + ident: &variant.ident, + attrs, + style, + fields, + //original: variant, + } + } +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] +pub enum Style { + Struct, + Tuple, + Unit, +} + +pub enum Data<'a> { + Enum(Vec<Variant<'a>>), + Struct(Style, Vec<Field<'a>>), +} + +pub struct Container<'a> { + pub ident: &'a syn::Ident, + pub attrs: attrs::Container, + pub data: Data<'a>, + pub crate_path: syn::Path, + pub original: &'a syn::DeriveInput, +} + +impl<'a> Container<'a> { + pub fn from_ast( + ctx: &Context, + crate_path: syn::Path, + input: &'a mut syn::DeriveInput, + ) -> Option<Container<'a>> { + let attrs = attrs::Container::from_ast(ctx, &input.attrs); + let data = match &input.data { + syn::Data::Struct(s) => match &s.fields { + syn::Fields::Named(fields) => { + Data::Struct(Style::Struct, fields_ast(ctx, &fields.named)) + } + syn::Fields::Unnamed(fields) => { + Data::Struct(Style::Tuple, fields_ast(ctx, &fields.unnamed)) + } + syn::Fields::Unit => Data::Struct(Style::Unit, Vec::new()), + }, + syn::Data::Enum(e) => { + let variants = e + .variants + .iter() + .map(|variant| Variant::from_ast(ctx, variant)) + .collect(); + Data::Enum(variants) + } + syn::Data::Union(u) => { + ctx.error_spanned(u.union_token, "Union not supported by nixrs"); + return None; + } + }; + Some(Container { + ident: &input.ident, + attrs, + data, + crate_path, + original: input, + }) + } + + pub fn crate_path(&self) -> &syn::Path { + if let Some(crate_path) = self.attrs.crate_path.as_ref() { + crate_path + } else { + &self.crate_path + } + } + + pub fn ident_type(&self) -> syn::Type { + let path: syn::Path = self.ident.clone().into(); + let tp = syn::TypePath { qself: None, path }; + tp.into() + } +} + +pub struct Remote<'a> { + pub attrs: attrs::Container, + pub ty: &'a syn::Type, + pub crate_path: syn::Path, +} + +impl<'a> Remote<'a> { + pub fn from_ast( + ctx: &Context, + crate_path: syn::Path, + input: &'a inputs::RemoteInput, + ) -> Option<Remote<'a>> { + let attrs = attrs::Container::from_ast(ctx, &input.attrs); + if attrs.from_str.is_none() && attrs.type_from.is_none() && attrs.type_try_from.is_none() { + ctx.error_spanned(input, "Missing from_str, from or try_from attribute"); + return None; + } + Some(Remote { + ty: &input.ident, + attrs, + crate_path, + }) + } + + pub fn crate_path(&self) -> &syn::Path { + if let Some(crate_path) = self.attrs.crate_path.as_ref() { + crate_path + } else { + &self.crate_path + } + } +} + +fn fields_ast<'a>(ctx: &Context, fields: &'a Punctuated<syn::Field, Token![,]>) -> Vec<Field<'a>> { + fields + .iter() + .enumerate() + .map(|(idx, field)| Field::from_ast(ctx, idx, field)) + .collect() +} diff --git a/tvix/nix-compat-derive/src/internal/symbol.rs b/tvix/nix-compat-derive/src/internal/symbol.rs new file mode 100644 index 000000000000..ed3fe304eb5d --- /dev/null +++ b/tvix/nix-compat-derive/src/internal/symbol.rs @@ -0,0 +1,32 @@ +use std::fmt; + +use syn::Path; + +#[derive(Copy, Clone)] +pub struct Symbol(&'static str); + +pub const NIX: Symbol = Symbol("nix"); +pub const VERSION: Symbol = Symbol("version"); +pub const DEFAULT: Symbol = Symbol("default"); +pub const FROM: Symbol = Symbol("from"); +pub const TRY_FROM: Symbol = Symbol("try_from"); +pub const FROM_STR: Symbol = Symbol("from_str"); +pub const CRATE: Symbol = Symbol("crate"); + +impl PartialEq<Symbol> for Path { + fn eq(&self, word: &Symbol) -> bool { + self.is_ident(word.0) + } +} + +impl<'a> PartialEq<Symbol> for &'a Path { + fn eq(&self, word: &Symbol) -> bool { + self.is_ident(word.0) + } +} + +impl fmt::Display for Symbol { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(self.0) + } +} diff --git a/tvix/nix-compat-derive/src/lib.rs b/tvix/nix-compat-derive/src/lib.rs new file mode 100644 index 000000000000..e3faed02ebab --- /dev/null +++ b/tvix/nix-compat-derive/src/lib.rs @@ -0,0 +1,303 @@ +//! # Using derive +//! +//! 1. [Overview](#overview) +//! 3. [Attributes](#attributes) +//! 1. [Container attributes](#container-attributes) +//! 1. [`#[nix(from_str)]`](#nixfrom_str) +//! 2. [`#[nix(from = "FromType")]`](#nixfrom--fromtype) +//! 3. [`#[nix(try_from = "FromType")]`](#nixtry_from--fromtype) +//! 4. [`#[nix(crate = "...")]`](#nixcrate--) +//! 2. [Variant attributes](#variant-attributes) +//! 1. [`#[nix(version = "range")]`](#nixversion--range) +//! 3. [Field attributes](#field-attributes) +//! 1. [`#[nix(version = "range")]`](#nixversion--range-1) +//! 2. [`#[nix(default)]`](#nixdefault) +//! 3. [`#[nix(default = "path")]`](#nixdefault--path) +//! +//! ## Overview +//! +//! This crate contains derive macros and function-like macros for implementing +//! `NixDeserialize` with less boilerplate. +//! +//! ### Examples +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Unnamed(u64, String); +//! ``` +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Fields { +//! number: u64, +//! message: String, +//! }; +//! ``` +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Ignored; +//! ``` +//! +//! ## Attributes +//! +//! To customize the derived trait implementations you can add +//! [attributes](https://doc.rust-lang.org/reference/attributes.html) +//! to containers, fields and variants. +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! #[nix(crate="nix_compat")] // <-- This is a container attribute +//! struct Fields { +//! number: u64, +//! #[nix(version="..20")] // <-- This is a field attribute +//! message: String, +//! }; +//! +//! #[derive(NixDeserialize)] +//! #[nix(crate="nix_compat")] // <-- This is also a container attribute +//! enum E { +//! #[nix(version="..=9")] // <-- This is a variant attribute +//! A(u64), +//! #[nix(version="10..")] // <-- This is also a variant attribute +//! B(String), +//! } +//! ``` +//! +//! ### Container attributes +//! +//! ##### `#[nix(from_str)]` +//! +//! When `from_str` is specified the fields are all ignored and instead a +//! `String` is first deserialized and then `FromStr::from_str` is used +//! to convert this `String` to the container type. +//! +//! This means that the container must implement `FromStr` and the error +//! returned from the `from_str` must implement `Display`. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! #[nix(from_str)] +//! struct MyString(String); +//! impl std::str::FromStr for MyString { +//! type Err = String; +//! fn from_str(s: &str) -> Result<Self, Self::Err> { +//! if s != "bad string" { +//! Ok(MyString(s.to_string())) +//! } else { +//! Err("Got a bad string".to_string()) +//! } +//! } +//! } +//! ``` +//! +//! ##### `#[nix(from = "FromType")]` +//! +//! When `from` is specified the fields are all ignored and instead a +//! value of `FromType` is first deserialized and then `From::from` is +//! used to convert from this value to the container type. +//! +//! This means that the container must implement `From<FromType>` and +//! `FromType` must implement `NixDeserialize`. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! #[nix(from="usize")] +//! struct MyValue(usize); +//! impl From<usize> for MyValue { +//! fn from(val: usize) -> Self { +//! MyValue(val) +//! } +//! } +//! ``` +//! +//! ##### `#[nix(try_from = "FromType")]` +//! +//! With `try_from` a value of `FromType` is first deserialized and then +//! `TryFrom::try_from` is used to convert from this value to the container +//! type. +//! +//! This means that the container must implement `TryFrom<FromType>` and +//! `FromType` must implement `NixDeserialize`. +//! The error returned from `try_from` also needs to implement `Display`. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! #[nix(try_from="usize")] +//! struct WrongAnswer(usize); +//! impl TryFrom<usize> for WrongAnswer { +//! type Error = String; +//! fn try_from(val: usize) -> Result<Self, Self::Error> { +//! if val != 42 { +//! Ok(WrongAnswer(val)) +//! } else { +//! Err("Got the answer to life the universe and everything".to_string()) +//! } +//! } +//! } +//! ``` +//! +//! ##### `#[nix(crate = "...")]` +//! +//! Specify the path to the `nix-compat` crate instance to use when referring +//! to the API in the generated code. This is usually not needed. +//! +//! ### Variant attributes +//! +//! ##### `#[nix(version = "range")]` +//! +//! Specifies the protocol version range where this variant is used. +//! When deriving an enum the `version` attribute is used to select which +//! variant of the enum to deserialize. The range is for minor version and +//! the version ranges of all variants combined must cover all versions +//! without any overlap or the first variant that matches is selected. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! #[derive(NixDeserialize)] +//! enum Testing { +//! #[nix(version="..=18")] +//! OldVersion(u64), +//! #[nix(version="19..")] +//! NewVersion(String), +//! } +//! ``` +//! +//! ### Field attributes +//! +//! ##### `#[nix(version = "range")]` +//! +//! Specifies the protocol version range where this field is included. +//! The range is for minor version. For example `version = "..20"` +//! includes the field in protocol versions `1.0` to `1.19` and skips +//! it in version `1.20` and above. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Field { +//! number: u64, +//! #[nix(version="..20")] +//! messsage: String, +//! } +//! ``` +//! +//! ##### `#[nix(default)]` +//! +//! When a field is skipped because the active protocol version falls +//! outside the range specified in [`#[nix(version = "range")]`](#nixversion--range-1) +//! this attribute indicates that `Default::default()` should be used +//! to get a value for the field. This is also the default +//! when you only specify [`#[nix(version = "range")]`](#nixversion--range-1). +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Field { +//! number: u64, +//! #[nix(version="..20", default)] +//! messsage: String, +//! } +//! ``` +//! +//! ##### `#[nix(default = "path")]` +//! +//! When a field is skipped because the active protocol version falls +//! outside the range specified in [`#[nix(version = "range")]`](#nixversion--range-1) +//! this attribute indicates that the function in `path` should be called to +//! get a default value for the field. The given function must be callable +//! as `fn() -> T`. +//! For example `default = "my_value"` would call `my_value()` and `default = +//! "AType::empty"` would call `AType::empty()`. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Field { +//! number: u64, +//! #[nix(version="..20", default="missing_string")] +//! messsage: String, +//! } +//! +//! fn missing_string() -> String { +//! "missing string".to_string() +//! } +//! ``` + +use internal::inputs::RemoteInput; +use proc_macro::TokenStream; +use syn::{parse_quote, DeriveInput}; + +mod de; +mod internal; + +#[proc_macro_derive(NixDeserialize, attributes(nix))] +pub fn derive_nix_deserialize(item: TokenStream) -> TokenStream { + let mut input = syn::parse_macro_input!(item as DeriveInput); + let nnixrs: syn::Path = parse_quote!(::nix_compat); + de::expand_nix_deserialize(nnixrs, &mut input) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +/// Macro to implement `NixDeserialize` on a type. +/// Sometimes you can't use the deriver to implement `NixDeserialize` +/// (like when dealing with types in Rust standard library) but don't want +/// to implement it yourself. So this macro can be used for those situations +/// where you would derive using `#[nix(from_str)]`, +/// `#[nix(from = "FromType")]` or `#[nix(try_from = "FromType")]` if you +/// could. +/// +/// #### Example +/// +/// ```rust +/// # use nix_compat_derive::nix_deserialize_remote; +/// # +/// struct MyU64(u64); +/// +/// impl From<u64> for MyU64 { +/// fn from(value: u64) -> Self { +/// Self(value) +/// } +/// } +/// +/// nix_deserialize_remote!(#[nix(from="u64")] MyU64); +/// ``` +#[proc_macro] +pub fn nix_deserialize_remote(item: TokenStream) -> TokenStream { + let input = syn::parse_macro_input!(item as RemoteInput); + let crate_path = parse_quote!(::nix_compat); + de::expand_nix_deserialize_remote(crate_path, &input) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} diff --git a/tvix/nix-compat/Cargo.toml b/tvix/nix-compat/Cargo.toml index 876ac3ecadd0..f430a5461829 100644 --- a/tvix/nix-compat/Cargo.toml +++ b/tvix/nix-compat/Cargo.toml @@ -4,48 +4,50 @@ version = "0.1.0" edition = "2021" [features] -# async NAR writer +# async NAR writer. Also needs the `wire` feature. async = ["tokio"] # code emitting low-level packets used in the daemon protocol. -wire = ["tokio", "pin-project-lite"] +wire = ["tokio", "pin-project-lite", "bytes"] +test = [] # Enable all features by default. -default = ["async", "wire"] +default = ["async", "wire", "nix-compat-derive"] [dependencies] -bitflags = "2.4.1" -bstr = { version = "1.6.0", features = ["alloc", "unicode", "serde"] } -data-encoding = "2.3.3" -ed25519 = "2.2.3" -ed25519-dalek = "2.1.0" -enum-primitive-derive = "0.3.0" -glob = "0.3.0" -nom = "7.1.3" -num-traits = "0.2.18" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -sha2 = "0.10.6" -thiserror = "1.0.38" - -[dependencies.tokio] -optional = true -version = "1.32.0" -features = ["io-util", "macros"] - -[dependencies.pin-project-lite] +bitflags = { workspace = true } +bstr = { workspace = true, features = ["alloc", "unicode", "serde"] } +data-encoding = { workspace = true } +ed25519 = { workspace = true } +ed25519-dalek = { workspace = true } +enum-primitive-derive = { workspace = true } +glob = { workspace = true } +mimalloc = { workspace = true } +nom = { workspace = true } +num-traits = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +sha2 = { workspace = true } +thiserror = { workspace = true } +tracing = { workspace = true } +bytes = { workspace = true, optional = true } +tokio = { workspace = true, features = ["io-util", "macros"], optional = true } +pin-project-lite = { workspace = true, optional = true } + +[dependencies.nix-compat-derive] +path = "../nix-compat-derive" optional = true -version = "0.2.13" [dev-dependencies] -criterion = { version = "0.5", features = ["html_reports"] } -futures = { version = "0.3.30", default-features = false, features = ["executor"] } -hex-literal = "0.4.1" -lazy_static = "1.4.0" -pretty_assertions = "1.4.0" -rstest = "0.19.0" -serde_json = "1.0" -tokio-test = "0.4.3" -zstd = "^0.13.0" +criterion = { workspace = true, features = ["html_reports"] } +futures = { workspace = true } +hex-literal = { workspace = true } +mimalloc = { workspace = true } +pretty_assertions = { workspace = true } +rstest = { workspace = true } +serde_json = { workspace = true } +smol_str = { workspace = true } +tokio-test = { workspace = true } +zstd = { workspace = true } [[bench]] name = "derivation_parse_aterm" diff --git a/tvix/nix-compat/benches/derivation_parse_aterm.rs b/tvix/nix-compat/benches/derivation_parse_aterm.rs index 4ace7d4480f4..6557dd17af37 100644 --- a/tvix/nix-compat/benches/derivation_parse_aterm.rs +++ b/tvix/nix-compat/benches/derivation_parse_aterm.rs @@ -1,8 +1,12 @@ use std::path::Path; use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use mimalloc::MiMalloc; use nix_compat::derivation::Derivation; +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; + const RESOURCES_PATHS: &str = "src/derivation/tests/derivation_tests/ok"; fn bench_aterm_parser(c: &mut Criterion) { diff --git a/tvix/nix-compat/benches/narinfo_parse.rs b/tvix/nix-compat/benches/narinfo_parse.rs index 7ffd24d12bc3..ee2665a310d3 100644 --- a/tvix/nix-compat/benches/narinfo_parse.rs +++ b/tvix/nix-compat/benches/narinfo_parse.rs @@ -1,7 +1,12 @@ +use std::sync::LazyLock; +use std::{io, str}; + use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}; -use lazy_static::lazy_static; +use mimalloc::MiMalloc; use nix_compat::narinfo::NarInfo; -use std::{io, str}; + +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; const SAMPLE: &str = r#"StorePath: /nix/store/1pajsq519irjy86vli20bgq1wr1q3pny-banking-0.3.0 URL: nar/0rdn027rxqbl42bv9jxhsipgq2hwqdapvwmdzligmzdmz2p9vybs.nar.xz @@ -15,18 +20,16 @@ Deriver: 2ch8jx910qk6721mp4yqsmvdfgj5c8ir-banking-0.3.0.drv Sig: cache.nixos.org-1:xcL67rBZPcdVZudDLpLeddkBa0KaFTw5A0udnaa0axysjrQ6Nvd9p3BLZ4rhKgl52/cKiU3c6aq60L8+IcE5Dw== "#; -lazy_static! { - static ref CASES: &'static [&'static str] = { - let data = - zstd::decode_all(io::Cursor::new(include_bytes!("../testdata/narinfo.zst"))).unwrap(); - let data = str::from_utf8(Vec::leak(data)).unwrap(); - Vec::leak( - data.split_inclusive("\n\n") - .map(|s| s.strip_suffix('\n').unwrap()) - .collect::<Vec<_>>(), - ) - }; -} +static CASES: LazyLock<&'static [&'static str]> = LazyLock::new(|| { + let data = + zstd::decode_all(io::Cursor::new(include_bytes!("../testdata/narinfo.zst"))).unwrap(); + let data = str::from_utf8(Vec::leak(data)).unwrap(); + Vec::leak( + data.split_inclusive("\n\n") + .map(|s| s.strip_suffix('\n').unwrap()) + .collect::<Vec<_>>(), + ) +}); pub fn parse(c: &mut Criterion) { let mut g = c.benchmark_group("parse"); diff --git a/tvix/nix-compat/build.rs b/tvix/nix-compat/build.rs new file mode 100644 index 000000000000..c66b97016245 --- /dev/null +++ b/tvix/nix-compat/build.rs @@ -0,0 +1,5 @@ +fn main() { + // Pick up new test case files + // https://github.com/la10736/rstest/issues/256 + println!("cargo:rerun-if-changed=src/derivation/tests/derivation_tests") +} diff --git a/tvix/nix-compat/default.nix b/tvix/nix-compat/default.nix index 9df76e12fce1..34938e3d6428 100644 --- a/tvix/nix-compat/default.nix +++ b/tvix/nix-compat/default.nix @@ -1,7 +1,11 @@ -{ depot, ... }: +{ depot, lib, ... }: -depot.tvix.crates.workspaceMembers.nix-compat.build.override { +(depot.tvix.crates.workspaceMembers.nix-compat.build.override { runTests = true; - # make sure we also enable async here, so run the tests behind that feature flag. - features = [ "default" "async" "wire" ]; -} +}).overrideAttrs (old: rec { + meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { + inherit (old) crateName; + features = [ "async" "wire" ]; + }); +}) diff --git a/tvix/nix-compat/src/aterm/mod.rs b/tvix/nix-compat/src/aterm/mod.rs index 8806b6caf2e5..bb3b77bc7399 100644 --- a/tvix/nix-compat/src/aterm/mod.rs +++ b/tvix/nix-compat/src/aterm/mod.rs @@ -2,6 +2,6 @@ mod escape; mod parser; pub(crate) use escape::escape_bytes; -pub(crate) use parser::parse_bstr_field; -pub(crate) use parser::parse_str_list; +pub(crate) use parser::parse_bytes_field; pub(crate) use parser::parse_string_field; +pub(crate) use parser::parse_string_list; diff --git a/tvix/nix-compat/src/aterm/parser.rs b/tvix/nix-compat/src/aterm/parser.rs index a30cb40ab08d..a570573a8700 100644 --- a/tvix/nix-compat/src/aterm/parser.rs +++ b/tvix/nix-compat/src/aterm/parser.rs @@ -11,8 +11,10 @@ use nom::multi::separated_list0; use nom::sequence::delimited; use nom::IResult; -/// Parse a bstr and undo any escaping. -fn parse_escaped_bstr(i: &[u8]) -> IResult<&[u8], BString> { +/// Parse a bstr and undo any escaping (which is why this needs to allocate). +// FUTUREWORK: have a version for fields that are known to not need escaping +// (like store paths), and use &str. +fn parse_escaped_bytes(i: &[u8]) -> IResult<&[u8], BString> { escaped_transform( is_not("\"\\"), '\\', @@ -29,14 +31,14 @@ fn parse_escaped_bstr(i: &[u8]) -> IResult<&[u8], BString> { /// Parse a field in double quotes, undo any escaping, and return the unquoted /// and decoded `Vec<u8>`. -pub(crate) fn parse_bstr_field(i: &[u8]) -> IResult<&[u8], BString> { +pub(crate) fn parse_bytes_field(i: &[u8]) -> IResult<&[u8], BString> { // inside double quotes… delimited( nomchar('\"'), // There is alt(( // …either is a bstr after unescaping - parse_escaped_bstr, + parse_escaped_bytes, // …or an empty string. map(tag(b""), |_| BString::default()), )), @@ -45,8 +47,8 @@ pub(crate) fn parse_bstr_field(i: &[u8]) -> IResult<&[u8], BString> { } /// Parse a field in double quotes, undo any escaping, and return the unquoted -/// and decoded string, if it's a valid string. Or fail parsing if the bytes are -/// no valid UTF-8. +/// and decoded [String], if it's valid UTF-8. +/// Or fail parsing if the bytes are no valid UTF-8. pub(crate) fn parse_string_field(i: &[u8]) -> IResult<&[u8], String> { // inside double quotes… delimited( @@ -54,18 +56,18 @@ pub(crate) fn parse_string_field(i: &[u8]) -> IResult<&[u8], String> { // There is alt(( // either is a String after unescaping - nom::combinator::map_opt(parse_escaped_bstr, |escaped_bstr| { - String::from_utf8(escaped_bstr.into()).ok() + nom::combinator::map_opt(parse_escaped_bytes, |escaped_bytes| { + String::from_utf8(escaped_bytes.into()).ok() }), // or an empty string. - map(tag(b""), |_| String::new()), + map(tag(b""), |_| "".to_string()), )), nomchar('\"'), )(i) } -/// Parse a list of of string fields (enclosed in brackets) -pub(crate) fn parse_str_list(i: &[u8]) -> IResult<&[u8], Vec<String>> { +/// Parse a list of string fields (enclosed in brackets) +pub(crate) fn parse_string_list(i: &[u8]) -> IResult<&[u8], Vec<String>> { // inside brackets delimited( nomchar('['), @@ -89,7 +91,7 @@ mod tests { #[case] expected: &[u8], #[case] exp_rest: &[u8], ) { - let (rest, parsed) = super::parse_bstr_field(input).expect("must parse"); + let (rest, parsed) = super::parse_bytes_field(input).expect("must parse"); assert_eq!(exp_rest, rest, "expected remainder"); assert_eq!(expected, parsed); } @@ -118,7 +120,7 @@ mod tests { #[case::empty_list(b"[]", vec![], b"")] #[case::empty_list_with_rest(b"[]blub", vec![], b"blub")] fn parse_list(#[case] input: &[u8], #[case] expected: Vec<String>, #[case] exp_rest: &[u8]) { - let (rest, parsed) = super::parse_str_list(input).expect("must parse"); + let (rest, parsed) = super::parse_string_list(input).expect("must parse"); assert_eq!(exp_rest, rest, "expected remainder"); assert_eq!(expected, parsed); } diff --git a/tvix/nix-compat/src/bin/drvfmt.rs b/tvix/nix-compat/src/bin/drvfmt.rs index ddc1f0389f26..fca22c2cb2ae 100644 --- a/tvix/nix-compat/src/bin/drvfmt.rs +++ b/tvix/nix-compat/src/bin/drvfmt.rs @@ -3,6 +3,11 @@ use std::{collections::BTreeMap, io::Read}; use nix_compat::derivation::Derivation; use serde_json::json; +use mimalloc::MiMalloc; + +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; + /// construct a serde_json::Value from a Derivation. /// Some environment values can be non-valid UTF-8 strings. /// `serde_json` prints them out really unreadable. diff --git a/tvix/nix-compat/src/derivation/mod.rs b/tvix/nix-compat/src/derivation/mod.rs index 07da127ed038..445e9cb43143 100644 --- a/tvix/nix-compat/src/derivation/mod.rs +++ b/tvix/nix-compat/src/derivation/mod.rs @@ -36,11 +36,11 @@ pub struct Derivation { /// Map from drv path to output names used from this derivation. #[serde(rename = "inputDrvs")] - pub input_derivations: BTreeMap<StorePath, BTreeSet<String>>, + pub input_derivations: BTreeMap<StorePath<String>, BTreeSet<String>>, /// Plain store paths of additional inputs. #[serde(rename = "inputSrcs")] - pub input_sources: BTreeSet<StorePath>, + pub input_sources: BTreeSet<StorePath<String>>, /// Maps output names to Output. pub outputs: BTreeMap<String, Output>, @@ -127,7 +127,10 @@ impl Derivation { /// the `name` with a `.drv` suffix as name, all [Derivation::input_sources] and /// keys of [Derivation::input_derivations] as references, and the ATerm string of /// the [Derivation] as content. - pub fn calculate_derivation_path(&self, name: &str) -> Result<StorePath, DerivationError> { + pub fn calculate_derivation_path( + &self, + name: &str, + ) -> Result<StorePath<String>, DerivationError> { // append .drv to the name let name = &format!("{}.drv", name); @@ -141,7 +144,6 @@ impl Derivation { .collect(); build_text_path(name, self.to_aterm_bytes(), references) - .map(|s| s.to_owned()) .map_err(|_e| DerivationError::InvalidOutputName(name.to_string())) } @@ -188,11 +190,12 @@ impl Derivation { /// `fixed:out:${algo}:${digest}:${fodPath}` string is hashed instead of /// the A-Term. /// - /// If the derivation is not a fixed derivation, it's up to the caller of - /// this function to provide a lookup function to lookup these calculation - /// results of parent derivations at `fn_get_derivation_or_fod_hash` (by - /// drv path). - pub fn derivation_or_fod_hash<F>(&self, fn_get_derivation_or_fod_hash: F) -> [u8; 32] + /// It's up to the caller of this function to provide a (infallible) lookup + /// function to query [hash_derivation_modulo] of direct input derivations, + /// by their [StorePathRef]. + /// It will only be called in case the derivation is not a fixed-output + /// derivation. + pub fn hash_derivation_modulo<F>(&self, fn_lookup_hash_derivation_modulo: F) -> [u8; 32] where F: Fn(&StorePathRef) -> [u8; 32], { @@ -200,16 +203,16 @@ impl Derivation { // Non-Fixed-output derivations return the sha256 digest of the ATerm // notation, but with all input_derivation paths replaced by a recursive // call to this function. - // We use fn_get_derivation_or_fod_hash here, so callers can precompute this. + // We call [fn_lookup_hash_derivation_modulo] rather than recursing + // ourselves, so callers can precompute this. self.fod_digest().unwrap_or({ - // For each input_derivation, look up the - // derivation_or_fod_hash, and replace the derivation path with - // it's HEXLOWER digest. + // For each input_derivation, look up the hash derivation modulo, + // and replace the derivation path in the aterm with it's HEXLOWER digest. let aterm_bytes = self.to_aterm_bytes_with_replacements(&BTreeMap::from_iter( self.input_derivations .iter() .map(|(drv_path, output_names)| { - let hash = fn_get_derivation_or_fod_hash(&drv_path.into()); + let hash = fn_lookup_hash_derivation_modulo(&drv_path.as_ref()); (hash, output_names.to_owned()) }), @@ -226,20 +229,22 @@ impl Derivation { /// and self.environment[$outputName] needs to be an empty string. /// /// Output path calculation requires knowledge of the - /// derivation_or_fod_hash [NixHash], which (in case of non-fixed-output - /// derivations) also requires knowledge of other hash_derivation_modulo - /// [NixHash]es. + /// [hash_derivation_modulo], which (in case of non-fixed-output + /// derivations) also requires knowledge of the [hash_derivation_modulo] of + /// input derivations (recursively). /// - /// We solve this by asking the caller of this function to provide the - /// hash_derivation_modulo of the current Derivation. + /// To avoid recursing and doing unnecessary calculation, we simply + /// ask the caller of this function to provide the result of the + /// [hash_derivation_modulo] call of the current [Derivation], + /// and leave it up to them to calculate it when needed. /// - /// On completion, self.environment[$outputName] and - /// self.outputs[$outputName].path are set to the calculated output path for all + /// On completion, `self.environment[$outputName]` and + /// `self.outputs[$outputName].path` are set to the calculated output path for all /// outputs. pub fn calculate_output_paths( &mut self, name: &str, - derivation_or_fod_hash: &[u8; 32], + hash_derivation_modulo: &[u8; 32], ) -> Result<(), DerivationError> { // The fingerprint and hash differs per output for (output_name, output) in self.outputs.iter_mut() { @@ -250,14 +255,14 @@ impl Derivation { let path_name = output_path_name(name, output_name); - // For fixed output derivation we use the per-output info, otherwise we use the - // derivation hash. - let abs_store_path = if let Some(ref hwm) = output.ca_hash { - build_ca_path(&path_name, hwm, Vec::<String>::new(), false).map_err(|e| { + // For fixed output derivation we use [build_ca_path], otherwise we + // use [build_output_path] with [hash_derivation_modulo]. + let store_path = if let Some(ref hwm) = output.ca_hash { + build_ca_path(&path_name, hwm, Vec::<&str>::new(), false).map_err(|e| { DerivationError::InvalidOutputDerivationPath(output_name.to_string(), e) })? } else { - build_output_path(derivation_or_fod_hash, output_name, &path_name).map_err(|e| { + build_output_path(hash_derivation_modulo, output_name, &path_name).map_err(|e| { DerivationError::InvalidOutputDerivationPath( output_name.to_string(), store_path::BuildStorePathError::InvalidStorePath(e), @@ -265,11 +270,11 @@ impl Derivation { })? }; - output.path = Some(abs_store_path.to_owned()); self.environment.insert( output_name.to_string(), - abs_store_path.to_absolute_path().into(), + store_path.to_absolute_path().into(), ); + output.path = Some(store_path); } Ok(()) diff --git a/tvix/nix-compat/src/derivation/output.rs b/tvix/nix-compat/src/derivation/output.rs index 266617f587f8..0b81ef3c3155 100644 --- a/tvix/nix-compat/src/derivation/output.rs +++ b/tvix/nix-compat/src/derivation/output.rs @@ -1,5 +1,4 @@ use crate::nixhash::CAHash; -use crate::store_path::StorePathRef; use crate::{derivation::OutputError, store_path::StorePath}; use serde::de::Unexpected; use serde::{Deserialize, Serialize}; @@ -10,7 +9,7 @@ use std::borrow::Cow; #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)] pub struct Output { /// Store path of build result. - pub path: Option<StorePath>, + pub path: Option<StorePath<String>>, #[serde(flatten)] pub ca_hash: Option<CAHash>, // we can only represent a subset here. @@ -33,10 +32,10 @@ impl<'de> Deserialize<'de> for Output { &"a string", ))?; - let path = StorePathRef::from_absolute_path(path.as_bytes()) + let path = StorePath::from_absolute_path(path.as_bytes()) .map_err(|_| serde::de::Error::invalid_value(Unexpected::Str(path), &"StorePath"))?; Ok(Self { - path: Some(path.to_owned()), + path: Some(path), ca_hash: CAHash::from_map::<D>(&fields)?, }) } diff --git a/tvix/nix-compat/src/derivation/parse_error.rs b/tvix/nix-compat/src/derivation/parse_error.rs index fc97f1a9883b..f625d9aeb724 100644 --- a/tvix/nix-compat/src/derivation/parse_error.rs +++ b/tvix/nix-compat/src/derivation/parse_error.rs @@ -20,7 +20,7 @@ pub enum ErrorKind { DuplicateInputDerivationOutputName(String, String), #[error("duplicate input source: {0}")] - DuplicateInputSource(StorePath), + DuplicateInputSource(StorePath<String>), #[error("nix hash error: {0}")] NixHashError(nixhash::Error), diff --git a/tvix/nix-compat/src/derivation/parser.rs b/tvix/nix-compat/src/derivation/parser.rs index 2775294960fe..8e9804157da3 100644 --- a/tvix/nix-compat/src/derivation/parser.rs +++ b/tvix/nix-compat/src/derivation/parser.rs @@ -3,7 +3,6 @@ //! //! [ATerm]: http://program-transformation.org/Tools/ATermFormat.html -use bstr::BString; use nom::bytes::complete::tag; use nom::character::complete::char as nomchar; use nom::combinator::{all_consuming, map_res}; @@ -14,7 +13,7 @@ use thiserror; use crate::derivation::parse_error::{into_nomerror, ErrorKind, NomError, NomResult}; use crate::derivation::{write, CAHash, Derivation, Output}; -use crate::store_path::{self, StorePath, StorePathRef}; +use crate::store_path::{self, StorePath}; use crate::{aterm, nixhash}; #[derive(Debug, thiserror::Error)] @@ -73,7 +72,7 @@ fn parse_output(i: &[u8]) -> NomResult<&[u8], (String, Output)> { terminated(aterm::parse_string_field, nomchar(',')), terminated(aterm::parse_string_field, nomchar(',')), terminated(aterm::parse_string_field, nomchar(',')), - aterm::parse_bstr_field, + aterm::parse_bytes_field, ))(i) .map_err(into_nomerror) }, @@ -102,7 +101,7 @@ fn parse_output(i: &[u8]) -> NomResult<&[u8], (String, Output)> { path: if output_path.is_empty() { None } else { - Some(string_to_store_path(i, output_path)?) + Some(string_to_store_path(i, &output_path)?) }, ca_hash: hash_with_mode, }, @@ -132,12 +131,12 @@ fn parse_outputs(i: &[u8]) -> NomResult<&[u8], BTreeMap<String, Output>> { match res { Ok((rst, outputs_lst)) => { - let mut outputs: BTreeMap<String, Output> = BTreeMap::default(); + let mut outputs = BTreeMap::default(); for (output_name, output) in outputs_lst.into_iter() { if outputs.contains_key(&output_name) { return Err(nom::Err::Failure(NomError { input: i, - code: ErrorKind::DuplicateMapKey(output_name), + code: ErrorKind::DuplicateMapKey(output_name.to_string()), })); } outputs.insert(output_name, output); @@ -149,11 +148,13 @@ fn parse_outputs(i: &[u8]) -> NomResult<&[u8], BTreeMap<String, Output>> { } } -fn parse_input_derivations(i: &[u8]) -> NomResult<&[u8], BTreeMap<StorePath, BTreeSet<String>>> { - let (i, input_derivations_list) = parse_kv::<Vec<String>, _>(aterm::parse_str_list)(i)?; +fn parse_input_derivations( + i: &[u8], +) -> NomResult<&[u8], BTreeMap<StorePath<String>, BTreeSet<String>>> { + let (i, input_derivations_list) = parse_kv(aterm::parse_string_list)(i)?; // This is a HashMap of drv paths to a list of output names. - let mut input_derivations: BTreeMap<StorePath, BTreeSet<String>> = BTreeMap::new(); + let mut input_derivations: BTreeMap<StorePath<String>, BTreeSet<_>> = BTreeMap::new(); for (input_derivation, output_names) in input_derivations_list { let mut new_output_names = BTreeSet::new(); @@ -170,7 +171,7 @@ fn parse_input_derivations(i: &[u8]) -> NomResult<&[u8], BTreeMap<StorePath, BTr new_output_names.insert(output_name); } - let input_derivation: StorePath = string_to_store_path(i, input_derivation)?; + let input_derivation = string_to_store_path(i, input_derivation.as_str())?; input_derivations.insert(input_derivation, new_output_names); } @@ -178,16 +179,16 @@ fn parse_input_derivations(i: &[u8]) -> NomResult<&[u8], BTreeMap<StorePath, BTr Ok((i, input_derivations)) } -fn parse_input_sources(i: &[u8]) -> NomResult<&[u8], BTreeSet<StorePath>> { - let (i, input_sources_lst) = aterm::parse_str_list(i).map_err(into_nomerror)?; +fn parse_input_sources(i: &[u8]) -> NomResult<&[u8], BTreeSet<StorePath<String>>> { + let (i, input_sources_lst) = aterm::parse_string_list(i).map_err(into_nomerror)?; let mut input_sources: BTreeSet<_> = BTreeSet::new(); for input_source in input_sources_lst.into_iter() { - let input_source: StorePath = string_to_store_path(i, input_source)?; + let input_source = string_to_store_path(i, input_source.as_str())?; if input_sources.contains(&input_source) { return Err(nom::Err::Failure(NomError { input: i, - code: ErrorKind::DuplicateInputSource(input_source), + code: ErrorKind::DuplicateInputSource(input_source.to_owned()), })); } else { input_sources.insert(input_source); @@ -197,24 +198,27 @@ fn parse_input_sources(i: &[u8]) -> NomResult<&[u8], BTreeSet<StorePath>> { Ok((i, input_sources)) } -fn string_to_store_path( - i: &[u8], - path_str: String, -) -> Result<StorePath, nom::Err<NomError<&[u8]>>> { - #[cfg(debug_assertions)] - let path_str2 = path_str.clone(); - - let path: StorePath = StorePathRef::from_absolute_path(path_str.as_bytes()) - .map_err(|e: store_path::Error| { +fn string_to_store_path<'a, 'i, S>( + i: &'i [u8], + path_str: &'a str, +) -> Result<StorePath<S>, nom::Err<NomError<&'i [u8]>>> +where + S: std::cmp::Eq + + std::fmt::Display + + std::clone::Clone + + std::ops::Deref<Target = str> + + std::convert::From<&'a str>, +{ + let path = + StorePath::from_absolute_path(path_str.as_bytes()).map_err(|e: store_path::Error| { nom::Err::Failure(NomError { input: i, code: e.into(), }) - })? - .to_owned(); + })?; #[cfg(debug_assertions)] - assert_eq!(path_str2, path.to_absolute_path()); + assert_eq!(path_str, path.to_absolute_path()); Ok(path) } @@ -240,9 +244,9 @@ pub fn parse_derivation(i: &[u8]) -> NomResult<&[u8], Derivation> { // // parse builder |i| terminated(aterm::parse_string_field, nomchar(','))(i).map_err(into_nomerror), // // parse arguments - |i| terminated(aterm::parse_str_list, nomchar(','))(i).map_err(into_nomerror), + |i| terminated(aterm::parse_string_list, nomchar(','))(i).map_err(into_nomerror), // parse environment - parse_kv::<BString, _>(aterm::parse_bstr_field), + parse_kv(aterm::parse_bytes_field), )), nomchar(')'), ) @@ -329,6 +333,7 @@ where mod tests { use crate::store_path::StorePathRef; use std::collections::{BTreeMap, BTreeSet}; + use std::sync::LazyLock; use crate::{ derivation::{ @@ -338,49 +343,48 @@ mod tests { }; use bstr::{BString, ByteSlice}; use hex_literal::hex; - use lazy_static::lazy_static; use rstest::rstest; const DIGEST_SHA256: [u8; 32] = hex!("a5ce9c155ed09397614646c9717fc7cd94b1023d7b76b618d409e4fefd6e9d39"); - lazy_static! { - pub static ref NIXHASH_SHA256: NixHash = NixHash::Sha256(DIGEST_SHA256); - static ref EXP_MULTI_OUTPUTS: BTreeMap<String, Output> = { - let mut b = BTreeMap::new(); - b.insert( - "lib".to_string(), - Output { - path: Some( - StorePath::from_bytes( - b"2vixb94v0hy2xc6p7mbnxxcyc095yyia-has-multi-out-lib", - ) + static NIXHASH_SHA256: NixHash = NixHash::Sha256(DIGEST_SHA256); + static EXP_MULTI_OUTPUTS: LazyLock<BTreeMap<String, Output>> = LazyLock::new(|| { + let mut b = BTreeMap::new(); + b.insert( + "lib".to_string(), + Output { + path: Some( + StorePath::from_bytes(b"2vixb94v0hy2xc6p7mbnxxcyc095yyia-has-multi-out-lib") .unwrap(), - ), - ca_hash: None, - }, - ); - b.insert( - "out".to_string(), - Output { - path: Some( - StorePath::from_bytes( - b"55lwldka5nyxa08wnvlizyqw02ihy8ic-has-multi-out".as_bytes(), - ) - .unwrap(), - ), - ca_hash: None, - }, - ); - b - }; - static ref EXP_AB_MAP: BTreeMap<String, BString> = { - let mut b = BTreeMap::new(); - b.insert("a".to_string(), b"1".as_bstr().to_owned()); - b.insert("b".to_string(), b"2".as_bstr().to_owned()); - b - }; - static ref EXP_INPUT_DERIVATIONS_SIMPLE: BTreeMap<StorePath, BTreeSet<String>> = { + ), + ca_hash: None, + }, + ); + b.insert( + "out".to_string(), + Output { + path: Some( + StorePath::from_bytes( + b"55lwldka5nyxa08wnvlizyqw02ihy8ic-has-multi-out".as_bytes(), + ) + .unwrap(), + ), + ca_hash: None, + }, + ); + b + }); + + static EXP_AB_MAP: LazyLock<BTreeMap<String, BString>> = LazyLock::new(|| { + let mut b = BTreeMap::new(); + b.insert("a".to_string(), b"1".into()); + b.insert("b".to_string(), b"2".into()); + b + }); + + static EXP_INPUT_DERIVATIONS_SIMPLE: LazyLock<BTreeMap<StorePath<String>, BTreeSet<String>>> = + LazyLock::new(|| { let mut b = BTreeMap::new(); b.insert( StorePath::from_bytes(b"8bjm87p310sb7r2r0sg4xrynlvg86j8k-hello-2.12.1.tar.gz.drv") @@ -402,21 +406,22 @@ mod tests { }, ); b - }; - static ref EXP_INPUT_DERIVATIONS_SIMPLE_ATERM: String = { - format!( - "[(\"{0}\",[\"out\"]),(\"{1}\",[\"out\",\"lib\"])]", - "/nix/store/8bjm87p310sb7r2r0sg4xrynlvg86j8k-hello-2.12.1.tar.gz.drv", - "/nix/store/p3jc8aw45dza6h52v81j7lk69khckmcj-bash-5.2-p15.drv" - ) - }; - static ref EXP_INPUT_SOURCES_SIMPLE: BTreeSet<String> = { - let mut b = BTreeSet::new(); - b.insert("/nix/store/55lwldka5nyxa08wnvlizyqw02ihy8ic-has-multi-out".to_string()); - b.insert("/nix/store/2vixb94v0hy2xc6p7mbnxxcyc095yyia-has-multi-out-lib".to_string()); - b - }; - } + }); + + static EXP_INPUT_DERIVATIONS_SIMPLE_ATERM: LazyLock<String> = LazyLock::new(|| { + format!( + "[(\"{0}\",[\"out\"]),(\"{1}\",[\"out\",\"lib\"])]", + "/nix/store/8bjm87p310sb7r2r0sg4xrynlvg86j8k-hello-2.12.1.tar.gz.drv", + "/nix/store/p3jc8aw45dza6h52v81j7lk69khckmcj-bash-5.2-p15.drv" + ) + }); + + static EXP_INPUT_SOURCES_SIMPLE: LazyLock<BTreeSet<String>> = LazyLock::new(|| { + let mut b = BTreeSet::new(); + b.insert("/nix/store/55lwldka5nyxa08wnvlizyqw02ihy8ic-has-multi-out".to_string()); + b.insert("/nix/store/2vixb94v0hy2xc6p7mbnxxcyc095yyia-has-multi-out-lib".to_string()); + b + }); /// Ensure parsing KVs works #[rstest] @@ -427,8 +432,8 @@ mod tests { #[case] expected: &BTreeMap<String, BString>, #[case] exp_rest: &[u8], ) { - let (rest, parsed) = super::parse_kv::<BString, _>(crate::aterm::parse_bstr_field)(input) - .expect("must parse"); + let (rest, parsed) = + super::parse_kv(crate::aterm::parse_bytes_field)(input).expect("must parse"); assert_eq!(exp_rest, rest, "expected remainder"); assert_eq!(*expected, parsed); } @@ -437,8 +442,7 @@ mod tests { #[test] fn parse_kv_fail_dup_keys() { let input: &'static [u8] = b"[(\"a\",\"1\"),(\"a\",\"2\")]"; - let e = super::parse_kv::<BString, _>(crate::aterm::parse_bstr_field)(input) - .expect_err("must fail"); + let e = super::parse_kv(crate::aterm::parse_bytes_field)(input).expect_err("must fail"); match e { nom::Err::Failure(e) => { @@ -454,7 +458,7 @@ mod tests { #[case::simple(EXP_INPUT_DERIVATIONS_SIMPLE_ATERM.as_bytes(), &EXP_INPUT_DERIVATIONS_SIMPLE)] fn parse_input_derivations( #[case] input: &'static [u8], - #[case] expected: &BTreeMap<StorePath, BTreeSet<String>>, + #[case] expected: &BTreeMap<StorePath<String>, BTreeSet<String>>, ) { let (rest, parsed) = super::parse_input_derivations(input).expect("must parse"); diff --git a/tvix/nix-compat/src/derivation/tests/mod.rs b/tvix/nix-compat/src/derivation/tests/mod.rs index 63a65356bd8a..48d4e8926ae9 100644 --- a/tvix/nix-compat/src/derivation/tests/mod.rs +++ b/tvix/nix-compat/src/derivation/tests/mod.rs @@ -164,7 +164,7 @@ fn derivation_path(#[case] name: &str, #[case] expected_path: &str) { /// This trims all output paths from a Derivation struct, /// by setting outputs[$outputName].path and environment[$outputName] to the empty string. -fn derivation_with_trimmed_output_paths(derivation: &Derivation) -> Derivation { +fn derivation_without_output_paths(derivation: &Derivation) -> Derivation { let mut trimmed_env = derivation.environment.clone(); let mut trimmed_outputs = derivation.outputs.clone(); @@ -191,13 +191,13 @@ fn derivation_with_trimmed_output_paths(derivation: &Derivation) -> Derivation { #[rstest] #[case::fixed_sha256("0hm2f1psjpcwg8fijsmr4wwxrx59s092-bar.drv", hex!("724f3e3634fce4cbbbd3483287b8798588e80280660b9a63fd13a1bc90485b33"))] #[case::fixed_sha1("ss2p4wmxijn652haqyd7dckxwl4c7hxx-bar.drv", hex!("c79aebd0ce3269393d4a1fde2cbd1d975d879b40f0bf40a48f550edc107fd5df"))] -fn derivation_or_fod_hash(#[case] drv_path: &str, #[case] expected_digest: [u8; 32]) { +fn hash_derivation_modulo_fixed(#[case] drv_path: &str, #[case] expected_digest: [u8; 32]) { // read in the fixture let json_bytes = fs::read(format!("{}/ok/{}.json", RESOURCES_PATHS, drv_path)).expect("unable to read JSON"); let drv: Derivation = serde_json::from_slice(&json_bytes).expect("must deserialize"); - let actual = drv.derivation_or_fod_hash(|_| panic!("must not be called")); + let actual = drv.hash_derivation_modulo(|_| panic!("must not be called")); assert_eq!(expected_digest, actual); } @@ -224,13 +224,13 @@ fn output_paths(#[case] name: &str, #[case] drv_path_str: &str) { ) .expect("must succeed"); - // create a version with trimmed output paths, simulating we constructed - // the struct. - let mut derivation = derivation_with_trimmed_output_paths(&expected_derivation); + // create a version without output paths, simulating we constructed the + // struct. + let mut derivation = derivation_without_output_paths(&expected_derivation); - // calculate the derivation_or_fod_hash of derivation + // calculate the hash_derivation_modulo of Derivation // We don't expect the lookup function to be called for most derivations. - let calculated_derivation_or_fod_hash = derivation.derivation_or_fod_hash(|parent_drv_path| { + let actual_hash_derivation_modulo = derivation.hash_derivation_modulo(|parent_drv_path| { // 4wvvbi4jwn0prsdxb7vs673qa5h9gr7x-foo.drv may lookup /nix/store/0hm2f1psjpcwg8fijsmr4wwxrx59s092-bar.drv // ch49594n9avinrf8ip0aslidkc4lxkqv-foo.drv may lookup /nix/store/ss2p4wmxijn652haqyd7dckxwl4c7hxx-bar.drv if name == "foo" @@ -255,9 +255,9 @@ fn output_paths(#[case] name: &str, #[case] drv_path_str: &str) { let drv: Derivation = serde_json::from_slice(&json_bytes).expect("must deserialize"); - // calculate derivation_or_fod_hash for each parent. + // calculate hash_derivation_modulo for each parent. // This may not trigger subsequent requests, as both parents are FOD. - drv.derivation_or_fod_hash(|_| panic!("must not lookup")) + drv.hash_derivation_modulo(|_| panic!("must not lookup")) } else { // we only expect this to be called in the "foo" testcase, for the "bar derivations" panic!("may only be called for foo testcase on bar derivations"); @@ -265,7 +265,7 @@ fn output_paths(#[case] name: &str, #[case] drv_path_str: &str) { }); derivation - .calculate_output_paths(name, &calculated_derivation_or_fod_hash) + .calculate_output_paths(name, &actual_hash_derivation_modulo) .unwrap(); // The derivation should now look like it was before @@ -343,7 +343,7 @@ fn output_path_construction() { // calculate bar output paths let bar_calc_result = bar_drv.calculate_output_paths( "bar", - &bar_drv.derivation_or_fod_hash(|_| panic!("is FOD, should not lookup")), + &bar_drv.hash_derivation_modulo(|_| panic!("is FOD, should not lookup")), ); assert!(bar_calc_result.is_ok()); @@ -360,8 +360,8 @@ fn output_path_construction() { // now construct foo, which requires bar_drv // Note how we refer to the output path, drv name and replacement_str (with calculated output paths) of bar. let bar_output_path = &bar_drv.outputs.get("out").expect("must exist").path; - let bar_drv_derivation_or_fod_hash = - bar_drv.derivation_or_fod_hash(|_| panic!("is FOD, should not lookup")); + let bar_drv_hash_derivation_modulo = + bar_drv.hash_derivation_modulo(|_| panic!("is FOD, should not lookup")); let bar_drv_path = bar_drv .calculate_derivation_path("bar") @@ -408,11 +408,11 @@ fn output_path_construction() { // calculate foo output paths let foo_calc_result = foo_drv.calculate_output_paths( "foo", - &foo_drv.derivation_or_fod_hash(|drv_path| { + &foo_drv.hash_derivation_modulo(|drv_path| { if drv_path.to_string() != "0hm2f1psjpcwg8fijsmr4wwxrx59s092-bar.drv" { panic!("lookup called with unexpected drv_path: {}", drv_path); } - bar_drv_derivation_or_fod_hash + bar_drv_hash_derivation_modulo }), ); assert!(foo_calc_result.is_ok()); diff --git a/tvix/nix-compat/src/derivation/write.rs b/tvix/nix-compat/src/derivation/write.rs index 735b781574e1..42dadcd76064 100644 --- a/tvix/nix-compat/src/derivation/write.rs +++ b/tvix/nix-compat/src/derivation/write.rs @@ -6,7 +6,7 @@ use crate::aterm::escape_bytes; use crate::derivation::{ca_kind_prefix, output::Output}; use crate::nixbase32; -use crate::store_path::{StorePath, StorePathRef, STORE_DIR_WITH_SLASH}; +use crate::store_path::{StorePath, STORE_DIR_WITH_SLASH}; use bstr::BString; use data_encoding::HEXLOWER; @@ -32,16 +32,12 @@ pub const QUOTE: char = '"'; /// the context a lot. pub(crate) trait AtermWriteable { fn aterm_write(&self, writer: &mut impl Write) -> std::io::Result<()>; - - fn aterm_bytes(&self) -> Vec<u8> { - let mut bytes = Vec::new(); - self.aterm_write(&mut bytes) - .expect("unexpected write errors to Vec"); - bytes - } } -impl AtermWriteable for StorePathRef<'_> { +impl<S> AtermWriteable for StorePath<S> +where + S: std::cmp::Eq + std::ops::Deref<Target = str>, +{ fn aterm_write(&self, writer: &mut impl Write) -> std::io::Result<()> { write_char(writer, QUOTE)?; writer.write_all(STORE_DIR_WITH_SLASH.as_bytes())?; @@ -53,13 +49,6 @@ impl AtermWriteable for StorePathRef<'_> { } } -impl AtermWriteable for StorePath { - fn aterm_write(&self, writer: &mut impl Write) -> std::io::Result<()> { - let r: StorePathRef = self.into(); - r.aterm_write(writer) - } -} - impl AtermWriteable for String { fn aterm_write(&self, writer: &mut impl Write) -> std::io::Result<()> { write_field(writer, self, true) @@ -186,7 +175,7 @@ pub(crate) fn write_input_derivations( pub(crate) fn write_input_sources( writer: &mut impl Write, - input_sources: &BTreeSet<StorePath>, + input_sources: &BTreeSet<StorePath<String>>, ) -> Result<(), io::Error> { write_char(writer, BRACKET_OPEN)?; write_array_elements( diff --git a/tvix/nix-compat/src/lib.rs b/tvix/nix-compat/src/lib.rs index a71ede3eecf0..f30c557889a8 100644 --- a/tvix/nix-compat/src/lib.rs +++ b/tvix/nix-compat/src/lib.rs @@ -1,8 +1,12 @@ +extern crate self as nix_compat; + pub(crate) mod aterm; pub mod derivation; pub mod nar; pub mod narinfo; +pub mod nix_http; pub mod nixbase32; +pub mod nixcpp; pub mod nixhash; pub mod path_info; pub mod store_path; @@ -11,7 +15,7 @@ pub mod store_path; pub mod wire; #[cfg(feature = "wire")] -mod nix_daemon; +pub mod nix_daemon; #[cfg(feature = "wire")] pub use nix_daemon::worker_protocol; #[cfg(feature = "wire")] diff --git a/tvix/nix-compat/src/nar/listing/mod.rs b/tvix/nix-compat/src/nar/listing/mod.rs new file mode 100644 index 000000000000..5a9a3b4d3613 --- /dev/null +++ b/tvix/nix-compat/src/nar/listing/mod.rs @@ -0,0 +1,128 @@ +//! Parser for the Nix archive listing format, aka .ls. +//! +//! LS files are produced by the C++ Nix implementation via `write-nar-listing=1` query parameter +//! passed to a store implementation when transferring store paths. +//! +//! Listing files contains metadata about a file and its offset in the corresponding NAR. +//! +//! NOTE: LS entries does not offer any integrity field to validate the retrieved file at the provided +//! offset. Validating the contents is the caller's responsibility. + +use std::{ + collections::HashMap, + path::{Component, Path}, +}; + +use serde::Deserialize; + +#[cfg(test)] +mod test; + +#[derive(Debug, thiserror::Error)] +pub enum ListingError { + // TODO: add an enum of what component was problematic + // reusing `std::path::Component` is not possible as it contains a lifetime. + /// An unsupported path component can be: + /// - either a Windows prefix (`C:\\`, `\\share\\`) + /// - either a parent directory (`..`) + /// - either a root directory (`/`) + #[error("unsupported path component")] + UnsupportedPathComponent, + #[error("invalid encoding for entry component")] + InvalidEncoding, +} + +#[derive(Debug, Deserialize)] +#[serde(tag = "type", rename_all = "lowercase")] +pub enum ListingEntry { + Regular { + size: u64, + #[serde(default)] + executable: bool, + #[serde(rename = "narOffset")] + nar_offset: u64, + }, + Directory { + // It's tempting to think that the key should be a `Vec<u8>` + // but Nix does not support that and will fail to emit a listing version 1 for any non-UTF8 + // encodeable string. + entries: HashMap<String, ListingEntry>, + }, + Symlink { + target: String, + }, +} + +impl ListingEntry { + /// Given a relative path without `..` component, this will locate, relative to this entry, a + /// deeper entry. + /// + /// If the path is invalid, a listing error [`ListingError`] will be returned. + /// If the entry cannot be found, `None` will be returned. + pub fn locate<P: AsRef<Path>>(&self, path: P) -> Result<Option<&ListingEntry>, ListingError> { + // We perform a simple DFS on the components of the path + // while rejecting dangerous components, e.g. `..` or `/` + // Files and symlinks are *leaves*, i.e. we return them + let mut cur = self; + for component in path.as_ref().components() { + match component { + Component::CurDir => continue, + Component::RootDir | Component::Prefix(_) | Component::ParentDir => { + return Err(ListingError::UnsupportedPathComponent) + } + Component::Normal(file_or_dir_name) => { + if let Self::Directory { entries } = cur { + // As Nix cannot encode non-UTF8 components in the listing (see comment on + // the `Directory` enum variant), invalid encodings path components are + // errors. + let entry_name = file_or_dir_name + .to_str() + .ok_or(ListingError::InvalidEncoding)?; + + if let Some(new_entry) = entries.get(entry_name) { + cur = new_entry; + } else { + return Ok(None); + } + } else { + return Ok(None); + } + } + } + } + + // By construction, we found the node that corresponds to the path traversal. + Ok(Some(cur)) + } +} + +#[derive(Debug)] +pub struct ListingVersion<const V: u8>; + +#[derive(Debug, thiserror::Error)] +#[error("Invalid version: {0}")] +struct ListingVersionError(u8); + +impl<'de, const V: u8> Deserialize<'de> for ListingVersion<V> { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + let value = u8::deserialize(deserializer)?; + if value == V { + Ok(ListingVersion::<V>) + } else { + Err(serde::de::Error::custom(ListingVersionError(value))) + } + } +} + +#[derive(Debug, Deserialize)] +#[serde(untagged)] +#[non_exhaustive] +pub enum Listing { + V1 { + root: ListingEntry, + version: ListingVersion<1>, + }, +} diff --git a/tvix/nix-compat/src/nar/listing/test.rs b/tvix/nix-compat/src/nar/listing/test.rs new file mode 100644 index 000000000000..5b2ac3f166fe --- /dev/null +++ b/tvix/nix-compat/src/nar/listing/test.rs @@ -0,0 +1,59 @@ +use std::{collections::HashMap, path::PathBuf, str::FromStr}; + +use crate::nar; + +#[test] +fn weird_paths() { + let root = nar::listing::ListingEntry::Directory { + entries: HashMap::new(), + }; + + root.locate("../../../../etc/passwd") + .expect_err("Failed to reject `../` fragment in a path during traversal"); + + // Gated on Windows as C:\\ is parsed as `Component::Normal(_)` on Linux. + #[cfg(target_os = "windows")] + root.locate("C:\\\\Windows\\System32") + .expect_err("Failed to reject Windows-style prefixes"); + + root.locate("/etc/passwd") + .expect_err("Failed to reject absolute UNIX paths"); +} + +#[test] +fn nixos_release() { + let listing_bytes = include_bytes!("../tests/nixos-release.ls"); + let listing: nar::listing::Listing = serde_json::from_slice(listing_bytes).unwrap(); + + let nar::listing::Listing::V1 { root, .. } = listing; + assert!(matches!(root, nar::listing::ListingEntry::Directory { .. })); + + let build_products = root + .locate(PathBuf::from_str("nix-support/hydra-build-products").unwrap()) + .expect("Failed to locate a known file in a directory") + .expect("File was unexpectedly not found in the listing"); + + assert!(matches!( + build_products, + nar::listing::ListingEntry::Regular { .. } + )); + + let nonexisting_file = root + .locate(PathBuf::from_str("nix-support/does-not-exist").unwrap()) + .expect("Failed to locate an unknown file in a directory"); + + assert!( + nonexisting_file.is_none(), + "Non-existing file was unexpectedly found in the listing" + ); + + let existing_dir = root + .locate(PathBuf::from_str("nix-support").unwrap()) + .expect("Failed to locate a known directory in a directory") + .expect("Directory was expectedly found in the listing"); + + assert!(matches!( + existing_dir, + nar::listing::ListingEntry::Directory { .. } + )); +} diff --git a/tvix/nix-compat/src/nar/mod.rs b/tvix/nix-compat/src/nar/mod.rs index 058977f4fcd1..d0e8ee8a412f 100644 --- a/tvix/nix-compat/src/nar/mod.rs +++ b/tvix/nix-compat/src/nar/mod.rs @@ -1,4 +1,5 @@ -mod wire; +pub(crate) mod wire; +pub mod listing; pub mod reader; pub mod writer; diff --git a/tvix/nix-compat/src/nar/reader/async/mod.rs b/tvix/nix-compat/src/nar/reader/async/mod.rs new file mode 100644 index 000000000000..0808fba38c47 --- /dev/null +++ b/tvix/nix-compat/src/nar/reader/async/mod.rs @@ -0,0 +1,173 @@ +use std::{ + mem::MaybeUninit, + pin::Pin, + task::{self, Poll}, +}; + +use tokio::io::{self, AsyncBufRead, AsyncRead, ErrorKind::InvalidData}; + +// Required reading for understanding this module. +use crate::{ + nar::{self, wire::PadPar}, + wire::{self, BytesReader}, +}; + +mod read; +#[cfg(test)] +mod test; + +pub type Reader<'a> = dyn AsyncBufRead + Unpin + Send + 'a; + +/// Start reading a NAR file from `reader`. +pub async fn open<'a, 'r>(reader: &'a mut Reader<'r>) -> io::Result<Node<'a, 'r>> { + read::token(reader, &nar::wire::TOK_NAR).await?; + Node::new(reader).await +} + +pub enum Node<'a, 'r: 'a> { + Symlink { + target: Vec<u8>, + }, + File { + executable: bool, + reader: FileReader<'a, 'r>, + }, + Directory(DirReader<'a, 'r>), +} + +impl<'a, 'r: 'a> Node<'a, 'r> { + /// Start reading a [Node], matching the next [wire::Node]. + /// + /// Reading the terminating [wire::TOK_PAR] is done immediately for [Node::Symlink], + /// but is otherwise left to [DirReader] or [BytesReader]. + async fn new(reader: &'a mut Reader<'r>) -> io::Result<Self> { + Ok(match read::tag(reader).await? { + nar::wire::Node::Sym => { + let target = wire::read_bytes(reader, 1..=nar::wire::MAX_TARGET_LEN).await?; + + if target.contains(&0) { + return Err(InvalidData.into()); + } + + read::token(reader, &nar::wire::TOK_PAR).await?; + + Node::Symlink { target } + } + tag @ (nar::wire::Node::Reg | nar::wire::Node::Exe) => Node::File { + executable: tag == nar::wire::Node::Exe, + reader: FileReader { + inner: BytesReader::new_internal(reader, ..).await?, + }, + }, + nar::wire::Node::Dir => Node::Directory(DirReader::new(reader)), + }) + } +} + +/// File contents, readable through the [AsyncRead] trait. +/// +/// It comes with some caveats: +/// * You must always read the entire file, unless you intend to abandon the entire archive reader. +/// * You must abandon the entire archive reader upon the first error. +/// +/// It's fine to read exactly `reader.len()` bytes without ever seeing an explicit EOF. +pub struct FileReader<'a, 'r> { + inner: BytesReader<&'a mut Reader<'r>, PadPar>, +} + +impl<'a, 'r> FileReader<'a, 'r> { + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn len(&self) -> u64 { + self.inner.len() + } +} + +impl<'a, 'r> AsyncRead for FileReader<'a, 'r> { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut task::Context, + buf: &mut io::ReadBuf, + ) -> Poll<io::Result<()>> { + Pin::new(&mut self.get_mut().inner).poll_read(cx, buf) + } +} + +impl<'a, 'r> AsyncBufRead for FileReader<'a, 'r> { + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<io::Result<&[u8]>> { + Pin::new(&mut self.get_mut().inner).poll_fill_buf(cx) + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + Pin::new(&mut self.get_mut().inner).consume(amt) + } +} + +/// A directory iterator, yielding a sequence of [Node]s. +/// It must be fully consumed before reading further from the [DirReader] that produced it, if any. +pub struct DirReader<'a, 'r> { + reader: &'a mut Reader<'r>, + /// Previous directory entry name. + /// We have to hang onto this to enforce name monotonicity. + prev_name: Vec<u8>, +} + +pub struct Entry<'a, 'r> { + pub name: &'a [u8], + pub node: Node<'a, 'r>, +} + +impl<'a, 'r> DirReader<'a, 'r> { + fn new(reader: &'a mut Reader<'r>) -> Self { + Self { + reader, + prev_name: vec![], + } + } + + /// Read the next [Entry] from the directory. + /// + /// We explicitly don't implement [Iterator], since treating this as + /// a regular Rust iterator will surely lead you astray. + /// + /// * You must always consume the entire iterator, unless you abandon the entire archive reader. + /// * You must abandon the entire archive reader on the first error. + /// * You must abandon the directory reader upon the first [None]. + /// * Even if you know the amount of elements up front, you must keep reading until you encounter [None]. + pub async fn next(&mut self) -> io::Result<Option<Entry<'_, 'r>>> { + // COME FROM the previous iteration: if we've already read an entry, + // read its terminating TOK_PAR here. + if !self.prev_name.is_empty() { + read::token(self.reader, &nar::wire::TOK_PAR).await?; + } + + if let nar::wire::Entry::None = read::tag(self.reader).await? { + return Ok(None); + } + + let mut name = [MaybeUninit::uninit(); nar::wire::MAX_NAME_LEN + 1]; + let name = + wire::read_bytes_buf(self.reader, &mut name, 1..=nar::wire::MAX_NAME_LEN).await?; + + if name.contains(&0) || name.contains(&b'/') || name == b"." || name == b".." { + return Err(InvalidData.into()); + } + + // Enforce strict monotonicity of directory entry names. + if &self.prev_name[..] >= name { + return Err(InvalidData.into()); + } + + self.prev_name.clear(); + self.prev_name.extend_from_slice(name); + + read::token(self.reader, &nar::wire::TOK_NOD).await?; + + Ok(Some(Entry { + name: &self.prev_name, + node: Node::new(self.reader).await?, + })) + } +} diff --git a/tvix/nix-compat/src/nar/reader/async/read.rs b/tvix/nix-compat/src/nar/reader/async/read.rs new file mode 100644 index 000000000000..2adf894922c5 --- /dev/null +++ b/tvix/nix-compat/src/nar/reader/async/read.rs @@ -0,0 +1,69 @@ +use tokio::io::{ + self, AsyncReadExt, + ErrorKind::{InvalidData, UnexpectedEof}, +}; + +use crate::nar::wire::Tag; + +use super::Reader; + +/// Consume a known token from the reader. +pub async fn token<const N: usize>(reader: &mut Reader<'_>, token: &[u8; N]) -> io::Result<()> { + let mut buf = [0u8; N]; + + // This implements something similar to [AsyncReadExt::read_exact], but verifies that + // the input data matches the token while we read it. These two slices respectively + // represent the remaining token to be verified, and the remaining input buffer. + let mut token = &token[..]; + let mut buf = &mut buf[..]; + + while !token.is_empty() { + match reader.read(buf).await? { + 0 => { + return Err(UnexpectedEof.into()); + } + n => { + let (t, b); + (t, token) = token.split_at(n); + (b, buf) = buf.split_at_mut(n); + + if t != b { + return Err(InvalidData.into()); + } + } + } + } + + Ok(()) +} + +/// Consume a [Tag] from the reader. +pub async fn tag<T: Tag>(reader: &mut Reader<'_>) -> io::Result<T> { + let mut buf = T::make_buf(); + let buf = buf.as_mut(); + + // first read the known minimum length… + reader.read_exact(&mut buf[..T::MIN]).await?; + + // then decide which tag we're expecting + let tag = T::from_u8(buf[T::OFF]).ok_or(InvalidData)?; + let (head, tail) = tag.as_bytes().split_at(T::MIN); + + // make sure what we've read so far is valid + if buf[..T::MIN] != *head { + return Err(InvalidData.into()); + } + + // …then read the rest, if any + if !tail.is_empty() { + let rest = tail.len(); + reader.read_exact(&mut buf[..rest]).await?; + + // and make sure it's what we expect + if buf[..rest] != *tail { + return Err(InvalidData.into()); + } + } + + Ok(tag) +} diff --git a/tvix/nix-compat/src/nar/reader/async/test.rs b/tvix/nix-compat/src/nar/reader/async/test.rs new file mode 100644 index 000000000000..7bc1f8942f50 --- /dev/null +++ b/tvix/nix-compat/src/nar/reader/async/test.rs @@ -0,0 +1,310 @@ +use tokio::io::AsyncReadExt; + +mod nar { + pub use crate::nar::reader::r#async as reader; +} + +#[tokio::test] +async fn symlink() { + let mut f = std::io::Cursor::new(include_bytes!("../../tests/symlink.nar")); + let node = nar::reader::open(&mut f).await.unwrap(); + + match node { + nar::reader::Node::Symlink { target } => { + assert_eq!( + &b"/nix/store/somewhereelse"[..], + &target, + "target must match" + ); + } + _ => panic!("unexpected type"), + } +} + +#[tokio::test] +async fn file() { + let mut f = std::io::Cursor::new(include_bytes!("../../tests/helloworld.nar")); + let node = nar::reader::open(&mut f).await.unwrap(); + + match node { + nar::reader::Node::File { + executable, + mut reader, + } => { + assert!(!executable); + let mut buf = vec![]; + reader + .read_to_end(&mut buf) + .await + .expect("read must succeed"); + assert_eq!(&b"Hello World!"[..], &buf); + } + _ => panic!("unexpected type"), + } +} + +#[tokio::test] +async fn complicated() { + let mut f = std::io::Cursor::new(include_bytes!("../../tests/complicated.nar")); + let node = nar::reader::open(&mut f).await.unwrap(); + + match node { + nar::reader::Node::Directory(mut dir_reader) => { + // first entry is .keep, an empty regular file. + must_read_file( + ".keep", + dir_reader + .next() + .await + .expect("next must succeed") + .expect("must be some"), + ) + .await; + + // second entry is aa, a symlink to /nix/store/somewhereelse + must_be_symlink( + "aa", + "/nix/store/somewhereelse", + dir_reader + .next() + .await + .expect("next must be some") + .expect("must be some"), + ); + + { + // third entry is a directory called "keep" + let entry = dir_reader + .next() + .await + .expect("next must be some") + .expect("must be some"); + + assert_eq!(b"keep", entry.name); + + match entry.node { + nar::reader::Node::Directory(mut subdir_reader) => { + { + // first entry is .keep, an empty regular file. + let entry = subdir_reader + .next() + .await + .expect("next must succeed") + .expect("must be some"); + + must_read_file(".keep", entry).await; + } + + // we must read the None + assert!( + subdir_reader + .next() + .await + .expect("next must succeed") + .is_none(), + "keep directory contains only .keep" + ); + } + _ => panic!("unexpected type for keep/.keep"), + } + }; + + // reading more entries yields None (and we actually must read until this) + assert!(dir_reader.next().await.expect("must succeed").is_none()); + } + _ => panic!("unexpected type"), + } +} + +#[tokio::test] +#[should_panic] +#[ignore = "TODO: async poisoning"] +async fn file_read_abandoned() { + let mut f = std::io::Cursor::new(include_bytes!("../../tests/complicated.nar")); + let node = nar::reader::open(&mut f).await.unwrap(); + + match node { + nar::reader::Node::Directory(mut dir_reader) => { + // first entry is .keep, an empty regular file. + { + let entry = dir_reader + .next() + .await + .expect("next must succeed") + .expect("must be some"); + + assert_eq!(b".keep", entry.name); + // don't bother to finish reading it. + }; + + // this should panic (not return an error), because we are meant to abandon the archive reader now. + assert!(dir_reader.next().await.expect("must succeed").is_none()); + } + _ => panic!("unexpected type"), + } +} + +#[tokio::test] +#[should_panic] +#[ignore = "TODO: async poisoning"] +async fn dir_read_abandoned() { + let mut f = std::io::Cursor::new(include_bytes!("../../tests/complicated.nar")); + let node = nar::reader::open(&mut f).await.unwrap(); + + match node { + nar::reader::Node::Directory(mut dir_reader) => { + // first entry is .keep, an empty regular file. + must_read_file( + ".keep", + dir_reader + .next() + .await + .expect("next must succeed") + .expect("must be some"), + ) + .await; + + // second entry is aa, a symlink to /nix/store/somewhereelse + must_be_symlink( + "aa", + "/nix/store/somewhereelse", + dir_reader + .next() + .await + .expect("next must be some") + .expect("must be some"), + ); + + { + // third entry is a directory called "keep" + let entry = dir_reader + .next() + .await + .expect("next must be some") + .expect("must be some"); + + assert_eq!(b"keep", entry.name); + + match entry.node { + nar::reader::Node::Directory(_) => { + // don't finish using it, which poisons the archive reader + } + _ => panic!("unexpected type for keep/.keep"), + } + }; + + // this should panic, because we didn't finish reading the child subdirectory + assert!(dir_reader.next().await.expect("must succeed").is_none()); + } + _ => panic!("unexpected type"), + } +} + +#[tokio::test] +#[should_panic] +#[ignore = "TODO: async poisoning"] +async fn dir_read_after_none() { + let mut f = std::io::Cursor::new(include_bytes!("../../tests/complicated.nar")); + let node = nar::reader::open(&mut f).await.unwrap(); + + match node { + nar::reader::Node::Directory(mut dir_reader) => { + // first entry is .keep, an empty regular file. + must_read_file( + ".keep", + dir_reader + .next() + .await + .expect("next must succeed") + .expect("must be some"), + ) + .await; + + // second entry is aa, a symlink to /nix/store/somewhereelse + must_be_symlink( + "aa", + "/nix/store/somewhereelse", + dir_reader + .next() + .await + .expect("next must be some") + .expect("must be some"), + ); + + { + // third entry is a directory called "keep" + let entry = dir_reader + .next() + .await + .expect("next must be some") + .expect("must be some"); + + assert_eq!(b"keep", entry.name); + + match entry.node { + nar::reader::Node::Directory(mut subdir_reader) => { + // first entry is .keep, an empty regular file. + must_read_file( + ".keep", + subdir_reader + .next() + .await + .expect("next must succeed") + .expect("must be some"), + ) + .await; + + // we must read the None + assert!( + subdir_reader + .next() + .await + .expect("next must succeed") + .is_none(), + "keep directory contains only .keep" + ); + } + _ => panic!("unexpected type for keep/.keep"), + } + }; + + // reading more entries yields None (and we actually must read until this) + assert!(dir_reader.next().await.expect("must succeed").is_none()); + + // this should panic, because we already got a none so we're meant to stop. + dir_reader.next().await.unwrap(); + unreachable!() + } + _ => panic!("unexpected type"), + } +} + +async fn must_read_file(name: &'static str, entry: nar::reader::Entry<'_, '_>) { + assert_eq!(name.as_bytes(), entry.name); + + match entry.node { + nar::reader::Node::File { + executable, + mut reader, + } => { + assert!(!executable); + assert_eq!(reader.read(&mut [0]).await.unwrap(), 0); + } + _ => panic!("unexpected type for {}", name), + } +} + +fn must_be_symlink( + name: &'static str, + exp_target: &'static str, + entry: nar::reader::Entry<'_, '_>, +) { + assert_eq!(name.as_bytes(), entry.name); + + match entry.node { + nar::reader::Node::Symlink { target } => { + assert_eq!(exp_target.as_bytes(), &target); + } + _ => panic!("unexpected type for {}", name), + } +} diff --git a/tvix/nix-compat/src/nar/reader/mod.rs b/tvix/nix-compat/src/nar/reader/mod.rs index 75463a6450a5..eef3b10f3c28 100644 --- a/tvix/nix-compat/src/nar/reader/mod.rs +++ b/tvix/nix-compat/src/nar/reader/mod.rs @@ -10,9 +10,15 @@ use std::io::{ Read, Write, }; +#[cfg(not(debug_assertions))] +use std::marker::PhantomData; + // Required reading for understanding this module. use crate::nar::wire; +#[cfg(all(feature = "async", feature = "wire"))] +pub mod r#async; + mod read; #[cfg(test)] mod test; @@ -23,29 +29,21 @@ struct ArchiveReader<'a, 'r> { inner: &'a mut Reader<'r>, /// In debug mode, also track when we need to abandon this archive reader. + /// /// The archive reader must be abandoned when: /// * An error is encountered at any point /// * A file or directory reader is dropped before being read entirely. + /// /// All of these checks vanish in release mode. - #[cfg(debug_assertions)] status: ArchiveReaderStatus<'a>, } -macro_rules! poison { - ($it:expr) => { - #[cfg(debug_assertions)] - { - $it.status.poison(); - } - }; -} - macro_rules! try_or_poison { ($it:expr, $ex:expr) => { match $ex { Ok(x) => x, Err(e) => { - poison!($it); + $it.status.poison(); return Err(e.into()); } } @@ -56,11 +54,7 @@ pub fn open<'a, 'r>(reader: &'a mut Reader<'r>) -> io::Result<Node<'a, 'r>> { read::token(reader, &wire::TOK_NAR)?; Node::new(ArchiveReader { inner: reader, - #[cfg(debug_assertions)] - status: ArchiveReaderStatus::StackTop { - poisoned: false, - ready: true, - }, + status: ArchiveReaderStatus::top(), }) } @@ -80,7 +74,6 @@ impl<'a, 'r> Node<'a, 'r> { /// /// Reading the terminating [wire::TOK_PAR] is done immediately for [Node::Symlink], /// but is otherwise left to [DirReader] or [FileReader]. - #[allow(unused_mut)] // due to debug_assertions code fn new(mut reader: ArchiveReader<'a, 'r>) -> io::Result<Self> { Ok(match read::tag(reader.inner)? { wire::Node::Sym => { @@ -88,15 +81,12 @@ impl<'a, 'r> Node<'a, 'r> { try_or_poison!(reader, read::bytes(reader.inner, wire::MAX_TARGET_LEN)); if target.is_empty() || target.contains(&0) { - poison!(reader); + reader.status.poison(); return Err(InvalidData.into()); } try_or_poison!(reader, read::token(reader.inner, &wire::TOK_PAR)); - #[cfg(debug_assertions)] - { - reader.status.ready_parent(); // Immediately allow reading from parent again - } + reader.status.ready_parent(); // Immediately allow reading from parent again Node::Symlink { target } } @@ -131,17 +121,13 @@ pub struct FileReader<'a, 'r> { impl<'a, 'r> FileReader<'a, 'r> { /// Instantiate a new reader, starting after [wire::TOK_REG] or [wire::TOK_EXE]. /// We handle the terminating [wire::TOK_PAR] on semantic EOF. - #[allow(unused_mut)] // due to debug_assertions code fn new(mut reader: ArchiveReader<'a, 'r>, len: u64) -> io::Result<Self> { // For zero-length files, we have to read the terminating TOK_PAR // immediately, since FileReader::read may never be called; we've // already reached semantic EOF by definition. if len == 0 { read::token(reader.inner, &wire::TOK_PAR)?; - #[cfg(debug_assertions)] - { - reader.status.ready_parent(); - } + reader.status.ready_parent(); } Ok(Self { @@ -175,7 +161,7 @@ impl FileReader<'_, '_> { let mut buf = try_or_poison!(self.reader, self.reader.inner.fill_buf()); if buf.is_empty() { - poison!(self.reader); + self.reader.status.poison(); return Err(UnexpectedEof.into()); } @@ -237,7 +223,7 @@ impl Read for FileReader<'_, '_> { self.len -= n as u64; if n == 0 { - poison!(self.reader); + self.reader.status.poison(); return Err(UnexpectedEof.into()); } @@ -260,18 +246,15 @@ impl FileReader<'_, '_> { try_or_poison!(self.reader, self.reader.inner.read_exact(&mut buf[pad..])); if buf != [0; 8] { - poison!(self.reader); + self.reader.status.poison(); return Err(InvalidData.into()); } } try_or_poison!(self.reader, read::token(self.reader.inner, &wire::TOK_PAR)); - #[cfg(debug_assertions)] - { - // Done with reading this file, allow going back up the chain of readers - self.reader.status.ready_parent(); - } + // Done with reading this file, allow going back up the chain of readers + self.reader.status.ready_parent(); Ok(()) } @@ -283,11 +266,11 @@ pub struct DirReader<'a, 'r> { reader: ArchiveReader<'a, 'r>, /// Previous directory entry name. /// We have to hang onto this to enforce name monotonicity. - prev_name: Option<Vec<u8>>, + prev_name: Vec<u8>, } pub struct Entry<'a, 'r> { - pub name: Vec<u8>, + pub name: &'a [u8], pub node: Node<'a, 'r>, } @@ -295,7 +278,7 @@ impl<'a, 'r> DirReader<'a, 'r> { fn new(reader: ArchiveReader<'a, 'r>) -> Self { Self { reader, - prev_name: None, + prev_name: vec![], } } @@ -314,23 +297,21 @@ impl<'a, 'r> DirReader<'a, 'r> { // COME FROM the previous iteration: if we've already read an entry, // read its terminating TOK_PAR here. - if self.prev_name.is_some() { + if !self.prev_name.is_empty() { try_or_poison!(self.reader, read::token(self.reader.inner, &wire::TOK_PAR)); } // Determine if there are more entries to follow if let wire::Entry::None = try_or_poison!(self.reader, read::tag(self.reader.inner)) { // We've reached the end of this directory. - #[cfg(debug_assertions)] - { - self.reader.status.ready_parent(); - } + self.reader.status.ready_parent(); return Ok(None); } + let mut name = [0; wire::MAX_NAME_LEN + 1]; let name = try_or_poison!( self.reader, - read::bytes(self.reader.inner, wire::MAX_NAME_LEN) + read::bytes_buf(self.reader.inner, &mut name, wire::MAX_NAME_LEN) ); if name.is_empty() @@ -339,29 +320,23 @@ impl<'a, 'r> DirReader<'a, 'r> { || name == b"." || name == b".." { - poison!(self.reader); + self.reader.status.poison(); return Err(InvalidData.into()); } // Enforce strict monotonicity of directory entry names. - match &mut self.prev_name { - None => { - self.prev_name = Some(name.clone()); - } - Some(prev_name) => { - if *prev_name >= name { - poison!(self.reader); - return Err(InvalidData.into()); - } - - name[..].clone_into(prev_name); - } + if &self.prev_name[..] >= name { + self.reader.status.poison(); + return Err(InvalidData.into()); } + self.prev_name.clear(); + self.prev_name.extend_from_slice(name); + try_or_poison!(self.reader, read::token(self.reader.inner, &wire::TOK_NOD)); Ok(Some(Entry { - name, + name: &self.prev_name, // Don't need to worry about poisoning here: Node::new will do it for us if needed node: Node::new(self.reader.child())?, })) @@ -373,12 +348,12 @@ impl<'a, 'r> DirReader<'a, 'r> { /// so we can check they are abandoned when an error occurs /// * Make sure only the most recently created object is read from, and is fully exhausted /// before anything it was created from is used again. -#[cfg(debug_assertions)] enum ArchiveReaderStatus<'a> { - StackTop { - poisoned: bool, - ready: bool, - }, + #[cfg(not(debug_assertions))] + None(PhantomData<&'a ()>), + #[cfg(debug_assertions)] + StackTop { poisoned: bool, ready: bool }, + #[cfg(debug_assertions)] StackChild { poisoned: &'a mut bool, parent_ready: &'a mut bool, @@ -386,12 +361,28 @@ enum ArchiveReaderStatus<'a> { }, } -#[cfg(debug_assertions)] impl ArchiveReaderStatus<'_> { + fn top() -> Self { + #[cfg(debug_assertions)] + { + ArchiveReaderStatus::StackTop { + poisoned: false, + ready: true, + } + } + + #[cfg(not(debug_assertions))] + ArchiveReaderStatus::None(PhantomData) + } + /// Poison all the objects sharing the same reader, to be used when an error occurs fn poison(&mut self) { match self { + #[cfg(not(debug_assertions))] + ArchiveReaderStatus::None(_) => {} + #[cfg(debug_assertions)] ArchiveReaderStatus::StackTop { poisoned: x, .. } => *x = true, + #[cfg(debug_assertions)] ArchiveReaderStatus::StackChild { poisoned: x, .. } => **x = true, } } @@ -399,10 +390,14 @@ impl ArchiveReaderStatus<'_> { /// Mark the parent as ready, allowing it to be used again and preventing this reference to the reader being used again. fn ready_parent(&mut self) { match self { - Self::StackTop { ready, .. } => { + #[cfg(not(debug_assertions))] + ArchiveReaderStatus::None(_) => {} + #[cfg(debug_assertions)] + ArchiveReaderStatus::StackTop { ready, .. } => { *ready = false; } - Self::StackChild { + #[cfg(debug_assertions)] + ArchiveReaderStatus::StackChild { ready, parent_ready, .. @@ -415,15 +410,23 @@ impl ArchiveReaderStatus<'_> { fn poisoned(&self) -> bool { match self { - Self::StackTop { poisoned, .. } => *poisoned, - Self::StackChild { poisoned, .. } => **poisoned, + #[cfg(not(debug_assertions))] + ArchiveReaderStatus::None(_) => false, + #[cfg(debug_assertions)] + ArchiveReaderStatus::StackTop { poisoned, .. } => *poisoned, + #[cfg(debug_assertions)] + ArchiveReaderStatus::StackChild { poisoned, .. } => **poisoned, } } fn ready(&self) -> bool { match self { - Self::StackTop { ready, .. } => *ready, - Self::StackChild { ready, .. } => *ready, + #[cfg(not(debug_assertions))] + ArchiveReaderStatus::None(_) => true, + #[cfg(debug_assertions)] + ArchiveReaderStatus::StackTop { ready, .. } => *ready, + #[cfg(debug_assertions)] + ArchiveReaderStatus::StackChild { ready, .. } => *ready, } } } @@ -434,6 +437,8 @@ impl<'a, 'r> ArchiveReader<'a, 'r> { fn child(&mut self) -> ArchiveReader<'_, 'r> { ArchiveReader { inner: self.inner, + #[cfg(not(debug_assertions))] + status: ArchiveReaderStatus::None(PhantomData), #[cfg(debug_assertions)] status: match &mut self.status { ArchiveReaderStatus::StackTop { poisoned, ready } => { @@ -462,16 +467,13 @@ impl<'a, 'r> ArchiveReader<'a, 'r> { /// Only does anything when debug assertions are on. #[inline(always)] fn check_correct(&self) { - #[cfg(debug_assertions)] - { - debug_assert!( - !self.status.poisoned(), - "Archive reader used after it was meant to be abandoned!" - ); - debug_assert!( - self.status.ready(), - "Non-ready archive reader used! (Should've been reading from something else)" - ) - } + assert!( + !self.status.poisoned(), + "Archive reader used after it was meant to be abandoned!" + ); + assert!( + self.status.ready(), + "Non-ready archive reader used! (Should've been reading from something else)" + ); } } diff --git a/tvix/nix-compat/src/nar/reader/read.rs b/tvix/nix-compat/src/nar/reader/read.rs index 1ce161376424..9938581f2a2e 100644 --- a/tvix/nix-compat/src/nar/reader/read.rs +++ b/tvix/nix-compat/src/nar/reader/read.rs @@ -15,6 +15,38 @@ pub fn u64(reader: &mut Reader) -> io::Result<u64> { Ok(u64::from_le_bytes(buf)) } +/// Consume a byte string from the reader into a provided buffer, +/// returning the data bytes. +pub fn bytes_buf<'a, const N: usize>( + reader: &mut Reader, + buf: &'a mut [u8; N], + max_len: usize, +) -> io::Result<&'a [u8]> { + assert_eq!(N % 8, 0); + assert!(max_len <= N); + + // read the length, and reject excessively large values + let len = self::u64(reader)?; + if len > max_len as u64 { + return Err(InvalidData.into()); + } + // we know the length fits in a usize now + let len = len as usize; + + // read the data and padding into a buffer + let buf_len = (len + 7) & !7; + reader.read_exact(&mut buf[..buf_len])?; + + // verify that the padding is all zeroes + for &b in &buf[len..buf_len] { + if b != 0 { + return Err(InvalidData.into()); + } + } + + Ok(&buf[..len]) +} + /// Consume a byte string of up to `max_len` bytes from the reader. pub fn bytes(reader: &mut Reader, max_len: usize) -> io::Result<Vec<u8>> { assert!(max_len <= isize::MAX as usize); diff --git a/tvix/nix-compat/src/nar/reader/test.rs b/tvix/nix-compat/src/nar/reader/test.rs index 02dc4767c916..63e4fb289ffc 100644 --- a/tvix/nix-compat/src/nar/reader/test.rs +++ b/tvix/nix-compat/src/nar/reader/test.rs @@ -71,7 +71,7 @@ fn complicated() { .expect("next must be some") .expect("must be some"); - assert_eq!(&b"keep"[..], &entry.name); + assert_eq!(b"keep", entry.name); match entry.node { nar::reader::Node::Directory(mut subdir_reader) => { @@ -117,7 +117,7 @@ fn file_read_abandoned() { .expect("next must succeed") .expect("must be some"); - assert_eq!(&b".keep"[..], &entry.name); + assert_eq!(b".keep", entry.name); // don't bother to finish reading it. }; @@ -162,7 +162,7 @@ fn dir_read_abandoned() { .expect("next must be some") .expect("must be some"); - assert_eq!(&b"keep"[..], &entry.name); + assert_eq!(b"keep", entry.name); match entry.node { nar::reader::Node::Directory(_) => { @@ -213,7 +213,7 @@ fn dir_read_after_none() { .expect("next must be some") .expect("must be some"); - assert_eq!(&b"keep"[..], &entry.name); + assert_eq!(b"keep", entry.name); match entry.node { nar::reader::Node::Directory(mut subdir_reader) => { @@ -248,7 +248,7 @@ fn dir_read_after_none() { } fn must_read_file(name: &'static str, entry: nar::reader::Entry<'_, '_>) { - assert_eq!(name.as_bytes(), &entry.name); + assert_eq!(name.as_bytes(), entry.name); match entry.node { nar::reader::Node::File { @@ -267,7 +267,7 @@ fn must_be_symlink( exp_target: &'static str, entry: nar::reader::Entry<'_, '_>, ) { - assert_eq!(name.as_bytes(), &entry.name); + assert_eq!(name.as_bytes(), entry.name); match entry.node { nar::reader::Node::Symlink { target } => { diff --git a/tvix/nix-compat/src/nar/tests/nixos-release.ls b/tvix/nix-compat/src/nar/tests/nixos-release.ls new file mode 100644 index 000000000000..9dd350b7cf86 --- /dev/null +++ b/tvix/nix-compat/src/nar/tests/nixos-release.ls @@ -0,0 +1 @@ +{"root":{"entries":{"iso":{"entries":{"nixos-minimal-new-kernel-no-zfs-24.11pre660688.bee6b69aad74-x86_64-linux.iso":{"narOffset":440,"size":1051721728,"type":"regular"}},"type":"directory"},"nix-support":{"entries":{"hydra-build-products":{"narOffset":1051722544,"size":211,"type":"regular"},"system":{"narOffset":1051722944,"size":13,"type":"regular"}},"type":"directory"}},"type":"directory"},"version":1} \ No newline at end of file diff --git a/tvix/nix-compat/src/nar/wire/mod.rs b/tvix/nix-compat/src/nar/wire/mod.rs index b9e021249543..ddf021bc1fa1 100644 --- a/tvix/nix-compat/src/nar/wire/mod.rs +++ b/tvix/nix-compat/src/nar/wire/mod.rs @@ -39,7 +39,7 @@ //! TOK_NAR ::= "nix-archive-1" "(" "type" //! TOK_SYM ::= "symlink" "target" //! TOK_REG ::= "regular" "contents" -//! TOK_EXE ::= "regular" "executable" "" +//! TOK_EXE ::= "regular" "executable" "" "contents" //! TOK_DIR ::= "directory" //! TOK_ENT ::= "entry" "(" "name" //! TOK_NOD ::= "node" "(" "type" @@ -90,6 +90,23 @@ pub const TOK_DIR: [u8; 24] = *b"\x09\0\0\0\0\0\0\0directory\0\0\0\0\0\0\0"; pub const TOK_ENT: [u8; 48] = *b"\x05\0\0\0\0\0\0\0entry\0\0\0\x01\0\0\0\0\0\0\0(\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0name\0\0\0\0"; pub const TOK_NOD: [u8; 48] = *b"\x04\0\0\0\0\0\0\0node\0\0\0\0\x01\0\0\0\0\0\0\0(\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0type\0\0\0\0"; pub const TOK_PAR: [u8; 16] = *b"\x01\0\0\0\0\0\0\0)\0\0\0\0\0\0\0"; +#[cfg(feature = "async")] +const TOK_PAD_PAR: [u8; 24] = *b"\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0)\0\0\0\0\0\0\0"; + +#[cfg(feature = "async")] +#[derive(Debug)] +pub(crate) enum PadPar {} + +#[cfg(all(feature = "async", feature = "wire"))] +impl crate::wire::reader::Tag for PadPar { + const PATTERN: &'static [u8] = &TOK_PAD_PAR; + + type Buf = [u8; 24]; + + fn make_buf() -> Self::Buf { + [0; 24] + } +} #[test] fn tokens() { @@ -102,6 +119,8 @@ fn tokens() { (&TOK_ENT, &["entry", "(", "name"]), (&TOK_NOD, &["node", "(", "type"]), (&TOK_PAR, &[")"]), + #[cfg(feature = "async")] + (&TOK_PAD_PAR, &["", ")"]), ]; for &(tok, xs) in cases { diff --git a/tvix/nix-compat/src/nar/writer/sync.rs b/tvix/nix-compat/src/nar/writer/sync.rs index 6270129028fa..b441479ac60b 100644 --- a/tvix/nix-compat/src/nar/writer/sync.rs +++ b/tvix/nix-compat/src/nar/writer/sync.rs @@ -35,11 +35,8 @@ use std::io::{ Write, }; -/// Convenience type alias for types implementing [`Write`]. -pub type Writer<'a> = dyn Write + Send + 'a; - /// Create a new NAR, writing the output to the specified writer. -pub fn open<'a, 'w: 'a>(writer: &'a mut Writer<'w>) -> io::Result<Node<'a, 'w>> { +pub fn open<W: Write>(writer: &mut W) -> io::Result<Node<W>> { let mut node = Node { writer }; node.write(&wire::TOK_NAR)?; Ok(node) @@ -49,11 +46,11 @@ pub fn open<'a, 'w: 'a>(writer: &'a mut Writer<'w>) -> io::Result<Node<'a, 'w>> /// /// A NAR can be thought of as a tree of nodes represented by this type. Each /// node can be a file, a symlink or a directory containing other nodes. -pub struct Node<'a, 'w: 'a> { - writer: &'a mut Writer<'w>, +pub struct Node<'a, W: Write> { + writer: &'a mut W, } -impl<'a, 'w> Node<'a, 'w> { +impl<'a, W: Write> Node<'a, W> { fn write(&mut self, data: &[u8]) -> io::Result<()> { self.writer.write_all(data) } @@ -123,12 +120,59 @@ impl<'a, 'w> Node<'a, 'w> { Ok(()) } + /// Make this node a single file but let the user handle the writing of the file contents. + /// The user gets access to a writer to write the file contents to, plus a struct they must + /// invoke a function on to finish writing the NAR file. + /// + /// It is the caller's responsibility to write the correct number of bytes to the writer and + /// invoke [`FileManualWrite::close`], or invalid archives will be produced silently. + /// + /// ```rust + /// # use std::io::BufReader; + /// # use std::io::Write; + /// # + /// # // Output location to write the NAR to. + /// # let mut sink: Vec<u8> = Vec::new(); + /// # + /// # // Instantiate writer for this output location. + /// # let mut nar = nix_compat::nar::writer::open(&mut sink)?; + /// # + /// let contents = "Hello world\n".as_bytes(); + /// let size = contents.len() as u64; + /// let executable = false; + /// + /// let (writer, skip) = nar + /// .file_manual_write(executable, size)?; + /// + /// // Write the contents + /// writer.write_all(&contents)?; + /// + /// // Close the file node + /// skip.close(writer)?; + /// # Ok::<(), std::io::Error>(()) + /// ``` + pub fn file_manual_write( + mut self, + executable: bool, + size: u64, + ) -> io::Result<(&'a mut W, FileManualWrite)> { + self.write(if executable { + &wire::TOK_EXE + } else { + &wire::TOK_REG + })?; + + self.write(&size.to_le_bytes())?; + + Ok((self.writer, FileManualWrite { size })) + } + /// Make this node a directory, the content of which is set using the /// resulting [`Directory`] value. /// /// It is the caller's responsibility to invoke [`Directory::close`], /// or invalid archives will be produced silently. - pub fn directory(mut self) -> io::Result<Directory<'a, 'w>> { + pub fn directory(mut self) -> io::Result<Directory<'a, W>> { self.write(&wire::TOK_DIR)?; Ok(Directory::new(self)) } @@ -145,13 +189,13 @@ fn into_name(_name: &[u8]) -> Name { } /// Content of a NAR node that represents a directory. -pub struct Directory<'a, 'w> { - node: Node<'a, 'w>, +pub struct Directory<'a, W: Write> { + node: Node<'a, W>, prev_name: Option<Name>, } -impl<'a, 'w> Directory<'a, 'w> { - fn new(node: Node<'a, 'w>) -> Self { +impl<'a, W: Write> Directory<'a, W> { + fn new(node: Node<'a, W>) -> Self { Self { node, prev_name: None, @@ -166,7 +210,7 @@ impl<'a, 'w> Directory<'a, 'w> { /// It is the caller's responsibility to ensure that directory entries are /// written in order of ascending name. If this is not ensured, this method /// may panic or silently produce invalid archives. - pub fn entry(&mut self, name: &[u8]) -> io::Result<Node<'_, 'w>> { + pub fn entry(&mut self, name: &[u8]) -> io::Result<Node<'_, W>> { debug_assert!( name.len() <= wire::MAX_NAME_LEN, "name.len() > {}", @@ -222,3 +266,24 @@ impl<'a, 'w> Directory<'a, 'w> { Ok(()) } } + +/// Content of a NAR node that represents a file whose contents are being written out manually. +/// Returned by the `file_manual_write` function. +#[must_use] +pub struct FileManualWrite { + size: u64, +} + +impl FileManualWrite { + /// Finish writing the file structure to the NAR after having manually written the file contents. + /// + /// **Important:** This *must* be called with the writer returned by file_manual_write after + /// the file contents have been manually and fully written. Otherwise the resulting NAR file + /// will be invalid. + pub fn close<W: Write>(self, writer: &mut W) -> io::Result<()> { + let mut node = Node { writer }; + node.pad(self.size)?; + node.write(&wire::TOK_PAR)?; + Ok(()) + } +} diff --git a/tvix/nix-compat/src/narinfo/mod.rs b/tvix/nix-compat/src/narinfo/mod.rs index b1c10bceb200..35146a927b39 100644 --- a/tvix/nix-compat/src/narinfo/mod.rs +++ b/tvix/nix-compat/src/narinfo/mod.rs @@ -27,13 +27,15 @@ use std::{ use crate::{nixbase32, nixhash::CAHash, store_path::StorePathRef}; mod fingerprint; -mod public_keys; mod signature; +mod signing_keys; +mod verifying_keys; pub use fingerprint::fingerprint; - -pub use public_keys::{Error as PubKeyError, PubKey}; -pub use signature::{Error as SignatureError, Signature}; +pub use signature::{Error as SignatureError, Signature, SignatureRef}; +pub use signing_keys::parse_keypair; +pub use signing_keys::{Error as SigningKeyError, SigningKey}; +pub use verifying_keys::{Error as VerifyingKeyError, VerifyingKey}; #[derive(Debug)] pub struct NarInfo<'a> { @@ -49,7 +51,7 @@ pub struct NarInfo<'a> { pub references: Vec<StorePathRef<'a>>, // authenticity /// Ed25519 signature over the path fingerprint - pub signatures: Vec<Signature<'a>>, + pub signatures: Vec<SignatureRef<'a>>, /// Content address (for content-defined paths) pub ca: Option<CAHash>, // derivation metadata @@ -244,7 +246,7 @@ impl<'a> NarInfo<'a> { }; } "Sig" => { - let val = Signature::parse(val) + let val = SignatureRef::parse(val) .map_err(|e| Error::UnableToParseSignature(signatures.len(), e))?; signatures.push(val); @@ -297,6 +299,21 @@ impl<'a> NarInfo<'a> { self.references.iter(), ) } + + /// Adds a signature, using the passed signer to sign. + /// This is generic over algo implementations / providers, + /// so users can bring their own signers. + pub fn add_signature<S>(&mut self, signer: &'a SigningKey<S>) + where + S: ed25519::signature::Signer<ed25519::Signature>, + { + // calculate the fingerprint to sign + let fp = self.fingerprint(); + + let sig = signer.sign(fp.as_bytes()); + + self.signatures.push(sig); + } } impl Display for NarInfo<'_> { @@ -392,10 +409,16 @@ pub enum Error { } #[cfg(test)] +const DUMMY_KEYPAIR: &str = "cache.example.com-1:cCta2MEsRNuYCgWYyeRXLyfoFpKhQJKn8gLMeXWAb7vIpRKKo/3JoxJ24OYa3DxT2JVV38KjK/1ywHWuMe2JEw=="; +#[cfg(test)] +const DUMMY_VERIFYING_KEY: &str = + "cache.example.com-1:yKUSiqP9yaMSduDmGtw8U9iVVd/Coyv9csB1rjHtiRM="; + +#[cfg(test)] mod test { use hex_literal::hex; - use lazy_static::lazy_static; use pretty_assertions::assert_eq; + use std::sync::LazyLock; use std::{io, str}; use crate::{ @@ -405,20 +428,18 @@ mod test { use super::{Flags, NarInfo}; - lazy_static! { - static ref CASES: &'static [&'static str] = { - let data = zstd::decode_all(io::Cursor::new(include_bytes!( - "../../testdata/narinfo.zst" - ))) - .unwrap(); - let data = str::from_utf8(Vec::leak(data)).unwrap(); - Vec::leak( - data.split_inclusive("\n\n") - .map(|s| s.strip_suffix('\n').unwrap()) - .collect::<Vec<_>>(), - ) - }; - } + static CASES: LazyLock<&'static [&'static str]> = LazyLock::new(|| { + let data = zstd::decode_all(io::Cursor::new(include_bytes!( + "../../testdata/narinfo.zst" + ))) + .unwrap(); + let data = str::from_utf8(Vec::leak(data)).unwrap(); + Vec::leak( + data.split_inclusive("\n\n") + .map(|s| s.strip_suffix('\n').unwrap()) + .collect::<Vec<_>>(), + ) + }); #[test] fn roundtrip() { @@ -524,4 +545,46 @@ Sig: cache.nixos.org-1:HhaiY36Uk3XV1JGe9d9xHnzAapqJXprU1YZZzSzxE97jCuO5RR7vlG2kF parsed.nar_hash, ); } + + /// Adds a signature to a NARInfo, using key material parsed from DUMMY_KEYPAIR. + /// It then ensures signature verification with the parsed + /// DUMMY_VERIFYING_KEY succeeds. + #[test] + fn sign() { + let mut narinfo = NarInfo::parse( + r#"StorePath: /nix/store/0vpqfxbkx0ffrnhbws6g9qwhmliksz7f-perl-HTTP-Cookies-6.01 +URL: nar/0i5biw0g01514llhfswxy6xfav8lxxdq1xg6ik7hgsqbpw0f06yi.nar.xz +Compression: xz +FileHash: sha256:0i5biw0g01514llhfswxy6xfav8lxxdq1xg6ik7hgsqbpw0f06yi +FileSize: 7120 +NarHash: sha256:0h1bm4sj1cnfkxgyhvgi8df1qavnnv94sd0v09wcrm971602shfg +NarSize: 22552 +References: +CA: fixed:r:sha1:1ak1ymbmsfx7z8kh09jzkr3a4dvkrfjw +"#, + ) + .expect("should parse"); + + let fp = narinfo.fingerprint(); + + // load our keypair from the fixtures + let (signing_key, _verifying_key) = + super::parse_keypair(super::DUMMY_KEYPAIR).expect("must succeed"); + + // add signature + narinfo.add_signature(&signing_key); + + // ensure the signature is added + let new_sig = narinfo.signatures.last().unwrap(); + assert_eq!(signing_key.name(), *new_sig.name()); + + // verify the new signature against the verifying key + let verifying_key = super::VerifyingKey::parse(super::DUMMY_VERIFYING_KEY) + .expect("parsing dummy verifying key"); + + assert!( + verifying_key.verify(&fp, new_sig), + "expect signature to be valid" + ); + } } diff --git a/tvix/nix-compat/src/narinfo/signature.rs b/tvix/nix-compat/src/narinfo/signature.rs index fd197e771d98..8df77019cd8f 100644 --- a/tvix/nix-compat/src/narinfo/signature.rs +++ b/tvix/nix-compat/src/narinfo/signature.rs @@ -1,21 +1,44 @@ -use std::fmt::{self, Display}; +use std::{ + fmt::{self, Display}, + ops::Deref, +}; use data_encoding::BASE64; -use ed25519_dalek::SIGNATURE_LENGTH; use serde::{Deserialize, Serialize}; +const SIGNATURE_LENGTH: usize = std::mem::size_of::<ed25519::SignatureBytes>(); + #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Signature<'a> { - name: &'a str, - bytes: [u8; SIGNATURE_LENGTH], +pub struct Signature<S> { + name: S, + bytes: ed25519::SignatureBytes, } -impl<'a> Signature<'a> { - pub fn new(name: &'a str, bytes: [u8; SIGNATURE_LENGTH]) -> Self { +/// Type alias of a [Signature] using a `&str` as `name` field. +pub type SignatureRef<'a> = Signature<&'a str>; + +/// Represents the signatures that Nix emits. +/// It consists of a name (an identifier for a public key), and an ed25519 +/// signature (64 bytes). +/// It is generic over the string type that's used for the name, and there's +/// [SignatureRef] as a type alias for one containing &str. +impl<S> Signature<S> +where + S: Deref<Target = str>, +{ + /// Constructs a new [Signature] from a name and public key. + pub fn new(name: S, bytes: ed25519::SignatureBytes) -> Self { Self { name, bytes } } - pub fn parse(input: &'a str) -> Result<Self, Error> { + /// Parses a [Signature] from a string containing the name, a colon, and 64 + /// base64-encoded bytes (plus padding). + /// These strings are commonly seen in the `Signature:` field of a NARInfo + /// file. + pub fn parse<'a>(input: &'a str) -> Result<Self, Error> + where + S: From<&'a str>, + { let (name, bytes64) = input.split_once(':').ok_or(Error::MissingSeparator)?; if name.is_empty() @@ -39,14 +62,19 @@ impl<'a> Signature<'a> { Err(_) => return Err(Error::DecodeError(input.to_string())), } - Ok(Signature { name, bytes }) + Ok(Self { + name: name.into(), + bytes, + }) } - pub fn name(&self) -> &'a str { - self.name + /// Returns the name field of the signature. + pub fn name(&self) -> &S { + &self.name } - pub fn bytes(&self) -> &[u8; SIGNATURE_LENGTH] { + /// Returns the 64 bytes of signatures. + pub fn bytes(&self) -> &ed25519::SignatureBytes { &self.bytes } @@ -56,9 +84,21 @@ impl<'a> Signature<'a> { verifying_key.verify_strict(fingerprint, &signature).is_ok() } + + /// Constructs a [SignatureRef] from this signature. + pub fn as_ref(&self) -> SignatureRef<'_> { + SignatureRef { + name: self.name.deref(), + bytes: self.bytes, + } + } } -impl<'de: 'a, 'a> Deserialize<'de> for Signature<'a> { +impl<'a, 'de, S> Deserialize<'de> for Signature<S> +where + S: Deref<Target = str> + From<&'a str>, + 'de: 'a, +{ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>, @@ -70,10 +110,13 @@ impl<'de: 'a, 'a> Deserialize<'de> for Signature<'a> { } } -impl<'a> Serialize for Signature<'a> { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> +impl<S: Display> Serialize for Signature<S> +where + S: Deref<Target = str>, +{ + fn serialize<SR>(&self, serializer: SR) -> Result<SR::Ok, SR::Error> where - S: serde::Serializer, + SR: serde::Serializer, { let string: String = self.to_string(); @@ -81,7 +124,16 @@ impl<'a> Serialize for Signature<'a> { } } -#[derive(Debug, thiserror::Error)] +impl<S> Display for Signature<S> +where + S: Display, +{ + fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { + write!(w, "{}:{}", self.name, BASE64.encode(&self.bytes)) + } +} + +#[derive(Debug, thiserror::Error, PartialEq, Eq)] pub enum Error { #[error("Invalid name: {0}")] InvalidName(String), @@ -93,43 +145,29 @@ pub enum Error { DecodeError(String), } -impl Display for Signature<'_> { - fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { - write!(w, "{}:{}", self.name, BASE64.encode(&self.bytes)) - } -} - #[cfg(test)] mod test { use data_encoding::BASE64; use ed25519_dalek::VerifyingKey; use hex_literal::hex; - use lazy_static::lazy_static; + use std::sync::LazyLock; use super::Signature; use rstest::rstest; const FINGERPRINT: &str = "1;/nix/store/syd87l2rxw8cbsxmxl853h0r6pdwhwjr-curl-7.82.0-bin;sha256:1b4sb93wp679q4zx9k1ignby1yna3z7c4c2ri3wphylbc2dwsys0;196040;/nix/store/0jqd0rlxzra1rs38rdxl43yh6rxchgc6-curl-7.82.0,/nix/store/6w8g7njm4mck5dmjxws0z1xnrxvl81xa-glibc-2.34-115,/nix/store/j5jxw3iy7bbz4a57fh9g2xm2gxmyal8h-zlib-1.2.12,/nix/store/yxvjs9drzsphm9pcf42a4byzj1kb9m7k-openssl-1.1.1n"; - // The signing key labelled as `cache.nixos.org-1`, - lazy_static! { - static ref PUB_CACHE_NIXOS_ORG_1: VerifyingKey = ed25519_dalek::VerifyingKey::from_bytes( + /// The signing key labelled as `cache.nixos.org-1`, + static PUB_CACHE_NIXOS_ORG_1: LazyLock<VerifyingKey> = LazyLock::new(|| { + ed25519_dalek::VerifyingKey::from_bytes( BASE64 .decode(b"6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=") .unwrap()[..] .try_into() - .unwrap() - ) - .unwrap(); - static ref PUB_TEST_1: VerifyingKey = ed25519_dalek::VerifyingKey::from_bytes( - BASE64 - .decode(b"tLAEn+EeaBUJYqEpTd2yeerr7Ic6+0vWe+aXL/vYUpE=") - .unwrap()[..] - .try_into() - .unwrap() + .unwrap(), ) - .unwrap(); - } + .expect("embedded public key is valid") + }); #[rstest] #[case::valid_cache_nixos_org_1(&PUB_CACHE_NIXOS_ORG_1, &"cache.nixos.org-1:TsTTb3WGTZKphvYdBHXwo6weVILmTytUjLB+vcX89fOjjRicCHmKA4RCPMVLkj6TMJ4GMX3HPVWRdD1hkeKZBQ==", FINGERPRINT, true)] @@ -143,7 +181,7 @@ mod test { #[case] fp: &str, #[case] expect_valid: bool, ) { - let sig = Signature::parse(sig_str).expect("must parse"); + let sig = Signature::<&str>::parse(sig_str).expect("must parse"); assert_eq!(expect_valid, sig.verify(fp.as_bytes(), verifying_key)); } @@ -158,7 +196,7 @@ mod test { "u01BybwQhyI5H1bW1EIWXssMDhDDIvXOG5uh8Qzgdyjz6U1qg6DHhMAvXZOUStIj6X5t4/ufFgR8i3fjf0bMAw==" )] fn parse_fail(#[case] input: &'static str) { - Signature::parse(input).expect_err("must fail"); + Signature::<&str>::parse(input).expect_err("must fail"); } #[test] @@ -177,8 +215,29 @@ mod test { let serialized = serde_json::to_string(&signature_actual).expect("must serialize"); assert_eq!(signature_str_json, &serialized); - let deserialized: Signature<'_> = + let deserialized: Signature<&str> = serde_json::from_str(signature_str_json).expect("must deserialize"); assert_eq!(&signature_actual, &deserialized); } + + /// Construct a [Signature], using different String types for the name field. + #[test] + fn signature_owned() { + let signature1 = Signature::<String>::parse("cache.nixos.org-1:TsTTb3WGTZKphvYdBHXwo6weVILmTytUjLB+vcX89fOjjRicCHmKA4RCPMVLkj6TMJ4GMX3HPVWRdD1hkeKZBQ==").expect("must parse"); + let signature2 = Signature::<smol_str::SmolStr>::parse("cache.nixos.org-1:TsTTb3WGTZKphvYdBHXwo6weVILmTytUjLB+vcX89fOjjRicCHmKA4RCPMVLkj6TMJ4GMX3HPVWRdD1hkeKZBQ==").expect("must parse"); + let signature3 = Signature::<&str>::parse("cache.nixos.org-1:TsTTb3WGTZKphvYdBHXwo6weVILmTytUjLB+vcX89fOjjRicCHmKA4RCPMVLkj6TMJ4GMX3HPVWRdD1hkeKZBQ==").expect("must parse"); + + assert!( + signature1.verify(FINGERPRINT.as_bytes(), &PUB_CACHE_NIXOS_ORG_1), + "must verify" + ); + assert!( + signature2.verify(FINGERPRINT.as_bytes(), &PUB_CACHE_NIXOS_ORG_1), + "must verify" + ); + assert!( + signature3.verify(FINGERPRINT.as_bytes(), &PUB_CACHE_NIXOS_ORG_1), + "must verify" + ); + } } diff --git a/tvix/nix-compat/src/narinfo/signing_keys.rs b/tvix/nix-compat/src/narinfo/signing_keys.rs new file mode 100644 index 000000000000..cf513b7ba475 --- /dev/null +++ b/tvix/nix-compat/src/narinfo/signing_keys.rs @@ -0,0 +1,119 @@ +//! This module provides tooling to parse private key (pairs) produced by Nix +//! and its +//! `nix-store --generate-binary-cache-key name path.secret path.pub` command. +//! It produces `ed25519_dalek` keys, but the `NarInfo::add_signature` function +//! is generic, allowing other signers. + +use data_encoding::BASE64; +use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH}; + +use super::{SignatureRef, VerifyingKey}; + +pub struct SigningKey<S> { + name: String, + signing_key: S, +} + +impl<S> SigningKey<S> +where + S: ed25519::signature::Signer<ed25519::Signature>, +{ + /// Constructs a singing key, using a name and a signing key. + pub fn new(name: String, signing_key: S) -> Self { + Self { name, signing_key } + } + + /// Signs a fingerprint using the internal signing key, returns the [SignatureRef] + pub(crate) fn sign<'a>(&'a self, fp: &[u8]) -> SignatureRef<'a> { + SignatureRef::new(&self.name, self.signing_key.sign(fp).to_bytes()) + } + + pub fn name(&self) -> &str { + &self.name + } +} + +/// Parses a SigningKey / VerifyingKey from a byte slice in the format that Nix uses. +pub fn parse_keypair( + input: &str, +) -> Result<(SigningKey<ed25519_dalek::SigningKey>, VerifyingKey), Error> { + let (name, bytes64) = input.split_once(':').ok_or(Error::MissingSeparator)?; + + if name.is_empty() + || !name + .chars() + .all(|c| char::is_alphanumeric(c) || c == '-' || c == '.') + { + return Err(Error::InvalidName(name.to_string())); + } + + const DECODED_BYTES_LEN: usize = SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH; + if bytes64.len() != BASE64.encode_len(DECODED_BYTES_LEN) { + return Err(Error::InvalidSigningKeyLen(bytes64.len())); + } + + let mut buf = [0; DECODED_BYTES_LEN + 2]; // 64 bytes + 2 bytes padding + let mut bytes = [0; DECODED_BYTES_LEN]; + match BASE64.decode_mut(bytes64.as_bytes(), &mut buf) { + Ok(len) if len == DECODED_BYTES_LEN => { + bytes.copy_from_slice(&buf[..DECODED_BYTES_LEN]); + } + Ok(_) => unreachable!(), + // keeping DecodePartial gets annoying lifetime-wise + Err(_) => return Err(Error::DecodeError(input.to_string())), + } + + let bytes_signing_key: [u8; SECRET_KEY_LENGTH] = { + let mut b = [0u8; SECRET_KEY_LENGTH]; + b.copy_from_slice(&bytes[0..SECRET_KEY_LENGTH]); + b + }; + let bytes_verifying_key: [u8; PUBLIC_KEY_LENGTH] = { + let mut b = [0u8; PUBLIC_KEY_LENGTH]; + b.copy_from_slice(&bytes[SECRET_KEY_LENGTH..]); + b + }; + + let signing_key = SigningKey::new( + name.to_string(), + ed25519_dalek::SigningKey::from_bytes(&bytes_signing_key), + ); + + let verifying_key = VerifyingKey::new( + name.to_string(), + ed25519_dalek::VerifyingKey::from_bytes(&bytes_verifying_key) + .map_err(Error::InvalidVerifyingKey)?, + ); + + Ok((signing_key, verifying_key)) +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Invalid name: {0}")] + InvalidName(String), + #[error("Missing separator")] + MissingSeparator, + #[error("Invalid signing key len: {0}")] + InvalidSigningKeyLen(usize), + #[error("Unable to base64-decode signing key: {0}")] + DecodeError(String), + #[error("VerifyingKey error: {0}")] + InvalidVerifyingKey(ed25519_dalek::SignatureError), +} + +#[cfg(test)] +mod test { + use crate::narinfo::DUMMY_KEYPAIR; + #[test] + fn parse() { + let (_signing_key, _verifying_key) = + super::parse_keypair(DUMMY_KEYPAIR).expect("must succeed"); + } + + #[test] + fn parse_fail() { + assert!(super::parse_keypair("cache.example.com-1:cCta2MEsRNuYCgWYyeRXLyfoFpKhQJKn8gLMeXWAb7vIpRKKo/3JoxJ24OYa3DxT2JVV38KjK/1ywHWuMe2JE").is_err()); + assert!(super::parse_keypair("cache.example.com-1cCta2MEsRNuYCgWYyeRXLyfoFpKhQJKn8gLMeXWAb7vIpRKKo/3JoxJ24OYa3DxT2JVV38KjK/1ywHWuMe2JE").is_err()); + } +} diff --git a/tvix/nix-compat/src/narinfo/public_keys.rs b/tvix/nix-compat/src/narinfo/verifying_keys.rs index 27dd90e096db..67ef2e3a459c 100644 --- a/tvix/nix-compat/src/narinfo/public_keys.rs +++ b/tvix/nix-compat/src/narinfo/verifying_keys.rs @@ -4,21 +4,21 @@ use std::fmt::Display; use data_encoding::BASE64; -use ed25519_dalek::{VerifyingKey, PUBLIC_KEY_LENGTH}; +use ed25519_dalek::PUBLIC_KEY_LENGTH; -use super::Signature; +use super::SignatureRef; /// This represents a ed25519 public key and "name". /// These are normally passed in the `trusted-public-keys` Nix config option, /// and consist of a name and base64-encoded ed25519 pubkey, separated by a `:`. -#[derive(Debug)] -pub struct PubKey { +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct VerifyingKey { name: String, - verifying_key: VerifyingKey, + verifying_key: ed25519_dalek::VerifyingKey, } -impl PubKey { - pub fn new(name: String, verifying_key: VerifyingKey) -> Self { +impl VerifyingKey { + pub fn new(name: String, verifying_key: ed25519_dalek::VerifyingKey) -> Self { Self { name, verifying_key, @@ -37,7 +37,7 @@ impl PubKey { } if bytes64.len() != BASE64.encode_len(PUBLIC_KEY_LENGTH) { - return Err(Error::InvalidPubKeyLen(bytes64.len())); + return Err(Error::InvalidVerifyingKeyLen(bytes64.len())); } let mut buf = [0; PUBLIC_KEY_LENGTH + 1]; @@ -51,7 +51,8 @@ impl PubKey { Err(_) => return Err(Error::DecodeError(input.to_string())), } - let verifying_key = VerifyingKey::from_bytes(&bytes).map_err(Error::InvalidVerifyingKey)?; + let verifying_key = + ed25519_dalek::VerifyingKey::from_bytes(&bytes).map_err(Error::InvalidVerifyingKey)?; Ok(Self { name: name.to_string(), @@ -68,8 +69,8 @@ impl PubKey { /// which means the name in the signature has to match, /// and the signature bytes themselves need to be a valid signature made by /// the signing key identified by [Self::verifying key]. - pub fn verify(&self, fingerprint: &str, signature: &Signature) -> bool { - if self.name() != signature.name() { + pub fn verify(&self, fingerprint: &str, signature: &SignatureRef<'_>) -> bool { + if self.name() != *signature.name() { return false; } @@ -84,14 +85,14 @@ pub enum Error { #[error("Missing separator")] MissingSeparator, #[error("Invalid pubkey len: {0}")] - InvalidPubKeyLen(usize), + InvalidVerifyingKeyLen(usize), #[error("VerifyingKey error: {0}")] InvalidVerifyingKey(ed25519_dalek::SignatureError), #[error("Unable to base64-decode pubkey: {0}")] DecodeError(String), } -impl Display for PubKey { +impl Display for VerifyingKey { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, @@ -108,9 +109,9 @@ mod test { use ed25519_dalek::PUBLIC_KEY_LENGTH; use rstest::rstest; - use crate::narinfo::Signature; + use crate::narinfo::SignatureRef; - use super::PubKey; + use super::VerifyingKey; const FINGERPRINT: &str = "1;/nix/store/syd87l2rxw8cbsxmxl853h0r6pdwhwjr-curl-7.82.0-bin;sha256:1b4sb93wp679q4zx9k1ignby1yna3z7c4c2ri3wphylbc2dwsys0;196040;/nix/store/0jqd0rlxzra1rs38rdxl43yh6rxchgc6-curl-7.82.0,/nix/store/6w8g7njm4mck5dmjxws0z1xnrxvl81xa-glibc-2.34-115,/nix/store/j5jxw3iy7bbz4a57fh9g2xm2gxmyal8h-zlib-1.2.12,/nix/store/yxvjs9drzsphm9pcf42a4byzj1kb9m7k-openssl-1.1.1n"; #[rstest] @@ -122,7 +123,7 @@ mod test { #[case] exp_name: &'static str, #[case] exp_verifying_key_bytes: &[u8; PUBLIC_KEY_LENGTH], ) { - let pubkey = PubKey::parse(input).expect("must parse"); + let pubkey = VerifyingKey::parse(input).expect("must parse"); assert_eq!(exp_name, pubkey.name()); assert_eq!(exp_verifying_key_bytes, pubkey.verifying_key.as_bytes()); } @@ -132,7 +133,7 @@ mod test { #[case::missing_padding("cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY")] #[case::wrong_length("cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDS")] fn parse_fail(#[case] input: &'static str) { - PubKey::parse(input).expect_err("must fail"); + VerifyingKey::parse(input).expect_err("must fail"); } #[rstest] @@ -144,8 +145,8 @@ mod test { #[case] signature_str: &'static str, #[case] expected: bool, ) { - let pubkey = PubKey::parse(pubkey_str).expect("must parse"); - let signature = Signature::parse(signature_str).expect("must parse"); + let pubkey = VerifyingKey::parse(pubkey_str).expect("must parse"); + let signature = SignatureRef::parse(signature_str).expect("must parse"); assert_eq!(expected, pubkey.verify(fingerprint, &signature)); } diff --git a/tvix/nix-compat/src/nix_daemon/de/bytes.rs b/tvix/nix-compat/src/nix_daemon/de/bytes.rs new file mode 100644 index 000000000000..7daced54eef7 --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/bytes.rs @@ -0,0 +1,70 @@ +use bytes::Bytes; + +use super::{Error, NixDeserialize, NixRead}; + +impl NixDeserialize for Bytes { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + reader.try_read_bytes().await + } +} + +impl NixDeserialize for String { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + if let Some(buf) = reader.try_read_bytes().await? { + String::from_utf8(buf.to_vec()) + .map_err(R::Error::invalid_data) + .map(Some) + } else { + Ok(None) + } + } +} + +#[cfg(test)] +mod test { + use std::io; + + use hex_literal::hex; + use rstest::rstest; + use tokio_test::io::Builder; + + use crate::nix_daemon::de::{NixRead, NixReader}; + + #[rstest] + #[case::empty("", &hex!("0000 0000 0000 0000"))] + #[case::one(")", &hex!("0100 0000 0000 0000 2900 0000 0000 0000"))] + #[case::two("it", &hex!("0200 0000 0000 0000 6974 0000 0000 0000"))] + #[case::three("tea", &hex!("0300 0000 0000 0000 7465 6100 0000 0000"))] + #[case::four("were", &hex!("0400 0000 0000 0000 7765 7265 0000 0000"))] + #[case::five("where", &hex!("0500 0000 0000 0000 7768 6572 6500 0000"))] + #[case::six("unwrap", &hex!("0600 0000 0000 0000 756E 7772 6170 0000"))] + #[case::seven("where's", &hex!("0700 0000 0000 0000 7768 6572 6527 7300"))] + #[case::aligned("read_tea", &hex!("0800 0000 0000 0000 7265 6164 5F74 6561"))] + #[case::more_bytes("read_tess", &hex!("0900 0000 0000 0000 7265 6164 5F74 6573 7300 0000 0000 0000"))] + #[case::utf8("The quick brown 🦊 jumps over 13 lazy ðŸ¶.", &hex!("2D00 0000 0000 0000 5468 6520 7175 6963 6b20 6272 6f77 6e20 f09f a68a 206a 756d 7073 206f 7665 7220 3133 206c 617a 7920 f09f 90b6 2e00 0000"))] + #[tokio::test] + async fn test_read_string(#[case] expected: &str, #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: String = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } + + #[tokio::test] + async fn test_read_string_invalid() { + let mock = Builder::new() + .read(&hex!("0300 0000 0000 0000 EDA0 8000 0000 0000")) + .build(); + let mut reader = NixReader::new(mock); + assert_eq!( + io::ErrorKind::InvalidData, + reader.read_value::<String>().await.unwrap_err().kind() + ); + } +} diff --git a/tvix/nix-compat/src/nix_daemon/de/collections.rs b/tvix/nix-compat/src/nix_daemon/de/collections.rs new file mode 100644 index 000000000000..cf79f584506a --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/collections.rs @@ -0,0 +1,105 @@ +use std::{collections::BTreeMap, future::Future}; + +use super::{NixDeserialize, NixRead}; + +#[allow(clippy::manual_async_fn)] +impl<T> NixDeserialize for Vec<T> +where + T: NixDeserialize + Send, +{ + fn try_deserialize<R>( + reader: &mut R, + ) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_ + where + R: ?Sized + NixRead + Send, + { + async move { + if let Some(len) = reader.try_read_value::<usize>().await? { + let mut ret = Vec::with_capacity(len); + for _ in 0..len { + ret.push(reader.read_value().await?); + } + Ok(Some(ret)) + } else { + Ok(None) + } + } + } +} + +#[allow(clippy::manual_async_fn)] +impl<K, V> NixDeserialize for BTreeMap<K, V> +where + K: NixDeserialize + Ord + Send, + V: NixDeserialize + Send, +{ + fn try_deserialize<R>( + reader: &mut R, + ) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_ + where + R: ?Sized + NixRead + Send, + { + async move { + if let Some(len) = reader.try_read_value::<usize>().await? { + let mut ret = BTreeMap::new(); + for _ in 0..len { + let key = reader.read_value().await?; + let value = reader.read_value().await?; + ret.insert(key, value); + } + Ok(Some(ret)) + } else { + Ok(None) + } + } + } +} + +#[cfg(test)] +mod test { + use std::collections::BTreeMap; + use std::fmt; + + use hex_literal::hex; + use rstest::rstest; + use tokio_test::io::Builder; + + use crate::nix_daemon::de::{NixDeserialize, NixRead, NixReader}; + + #[rstest] + #[case::empty(vec![], &hex!("0000 0000 0000 0000"))] + #[case::one(vec![0x29], &hex!("0100 0000 0000 0000 2900 0000 0000 0000"))] + #[case::two(vec![0x7469, 10], &hex!("0200 0000 0000 0000 6974 0000 0000 0000 0A00 0000 0000 0000"))] + #[tokio::test] + async fn test_read_small_vec(#[case] expected: Vec<usize>, #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: Vec<usize> = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } + + fn empty_map() -> BTreeMap<usize, u64> { + BTreeMap::new() + } + macro_rules! map { + ($($key:expr => $value:expr),*) => {{ + let mut ret = BTreeMap::new(); + $(ret.insert($key, $value);)* + ret + }}; + } + + #[rstest] + #[case::empty(empty_map(), &hex!("0000 0000 0000 0000"))] + #[case::one(map![0x7469usize => 10u64], &hex!("0100 0000 0000 0000 6974 0000 0000 0000 0A00 0000 0000 0000"))] + #[tokio::test] + async fn test_read_small_btree_map<E>(#[case] expected: E, #[case] data: &[u8]) + where + E: NixDeserialize + PartialEq + fmt::Debug, + { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: E = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } +} diff --git a/tvix/nix-compat/src/nix_daemon/de/int.rs b/tvix/nix-compat/src/nix_daemon/de/int.rs new file mode 100644 index 000000000000..eecf641cfe99 --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/int.rs @@ -0,0 +1,100 @@ +use super::{Error, NixDeserialize, NixRead}; + +impl NixDeserialize for u64 { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + reader.try_read_number().await + } +} + +impl NixDeserialize for usize { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + if let Some(value) = reader.try_read_number().await? { + value.try_into().map_err(R::Error::invalid_data).map(Some) + } else { + Ok(None) + } + } +} + +impl NixDeserialize for bool { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + Ok(reader.try_read_number().await?.map(|v| v != 0)) + } +} +impl NixDeserialize for i64 { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + Ok(reader.try_read_number().await?.map(|v| v as i64)) + } +} + +#[cfg(test)] +mod test { + use hex_literal::hex; + use rstest::rstest; + use tokio_test::io::Builder; + + use crate::nix_daemon::de::{NixRead, NixReader}; + + #[rstest] + #[case::simple_false(false, &hex!("0000 0000 0000 0000"))] + #[case::simple_true(true, &hex!("0100 0000 0000 0000"))] + #[case::other_true(true, &hex!("1234 5600 0000 0000"))] + #[case::max_true(true, &hex!("FFFF FFFF FFFF FFFF"))] + #[tokio::test] + async fn test_read_bool(#[case] expected: bool, #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: bool = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } + + #[rstest] + #[case::zero(0, &hex!("0000 0000 0000 0000"))] + #[case::one(1, &hex!("0100 0000 0000 0000"))] + #[case::other(0x563412, &hex!("1234 5600 0000 0000"))] + #[case::max_value(u64::MAX, &hex!("FFFF FFFF FFFF FFFF"))] + #[tokio::test] + async fn test_read_u64(#[case] expected: u64, #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: u64 = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } + + #[rstest] + #[case::zero(0, &hex!("0000 0000 0000 0000"))] + #[case::one(1, &hex!("0100 0000 0000 0000"))] + #[case::other(0x563412, &hex!("1234 5600 0000 0000"))] + #[case::max_value(usize::MAX, &usize::MAX.to_le_bytes())] + #[tokio::test] + async fn test_read_usize(#[case] expected: usize, #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: usize = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } + + // FUTUREWORK: Test this on supported hardware + #[tokio::test] + #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] + async fn test_read_usize_overflow() { + let mock = Builder::new().read(&u64::MAX.to_le_bytes()).build(); + let mut reader = NixReader::new(mock); + assert_eq!( + std::io::ErrorKind::InvalidData, + reader.read_value::<usize>().await.unwrap_err().kind() + ); + } +} diff --git a/tvix/nix-compat/src/nix_daemon/de/mock.rs b/tvix/nix-compat/src/nix_daemon/de/mock.rs new file mode 100644 index 000000000000..31cc3a4897ba --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/mock.rs @@ -0,0 +1,261 @@ +use std::collections::VecDeque; +use std::fmt; +use std::io; +use std::thread; + +use bytes::Bytes; +use thiserror::Error; + +use crate::nix_daemon::ProtocolVersion; + +use super::NixRead; + +#[derive(Debug, Error, PartialEq, Eq, Clone)] +pub enum Error { + #[error("custom error '{0}'")] + Custom(String), + #[error("invalid data '{0}'")] + InvalidData(String), + #[error("missing data '{0}'")] + MissingData(String), + #[error("IO error {0} '{1}'")] + IO(io::ErrorKind, String), + #[error("wrong read: expected {0} got {1}")] + WrongRead(OperationType, OperationType), +} + +impl Error { + pub fn expected_read_number() -> Error { + Error::WrongRead(OperationType::ReadNumber, OperationType::ReadBytes) + } + + pub fn expected_read_bytes() -> Error { + Error::WrongRead(OperationType::ReadBytes, OperationType::ReadNumber) + } +} + +impl super::Error for Error { + fn custom<T: fmt::Display>(msg: T) -> Self { + Self::Custom(msg.to_string()) + } + + fn io_error(err: std::io::Error) -> Self { + Self::IO(err.kind(), err.to_string()) + } + + fn invalid_data<T: fmt::Display>(msg: T) -> Self { + Self::InvalidData(msg.to_string()) + } + + fn missing_data<T: fmt::Display>(msg: T) -> Self { + Self::MissingData(msg.to_string()) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum OperationType { + ReadNumber, + ReadBytes, +} + +impl fmt::Display for OperationType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::ReadNumber => write!(f, "read_number"), + Self::ReadBytes => write!(f, "read_bytess"), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum Operation { + ReadNumber(Result<u64, Error>), + ReadBytes(Result<Bytes, Error>), +} + +impl From<Operation> for OperationType { + fn from(value: Operation) -> Self { + match value { + Operation::ReadNumber(_) => OperationType::ReadNumber, + Operation::ReadBytes(_) => OperationType::ReadBytes, + } + } +} + +pub struct Builder { + version: ProtocolVersion, + ops: VecDeque<Operation>, +} + +impl Builder { + pub fn new() -> Builder { + Builder { + version: Default::default(), + ops: VecDeque::new(), + } + } + + pub fn version<V: Into<ProtocolVersion>>(&mut self, version: V) -> &mut Self { + self.version = version.into(); + self + } + + pub fn read_number(&mut self, value: u64) -> &mut Self { + self.ops.push_back(Operation::ReadNumber(Ok(value))); + self + } + + pub fn read_number_error(&mut self, err: Error) -> &mut Self { + self.ops.push_back(Operation::ReadNumber(Err(err))); + self + } + + pub fn read_bytes(&mut self, value: Bytes) -> &mut Self { + self.ops.push_back(Operation::ReadBytes(Ok(value))); + self + } + + pub fn read_slice(&mut self, data: &[u8]) -> &mut Self { + let value = Bytes::copy_from_slice(data); + self.ops.push_back(Operation::ReadBytes(Ok(value))); + self + } + + pub fn read_bytes_error(&mut self, err: Error) -> &mut Self { + self.ops.push_back(Operation::ReadBytes(Err(err))); + self + } + + pub fn build(&mut self) -> Mock { + Mock { + version: self.version, + ops: self.ops.clone(), + } + } +} + +impl Default for Builder { + fn default() -> Self { + Self::new() + } +} + +pub struct Mock { + version: ProtocolVersion, + ops: VecDeque<Operation>, +} + +impl NixRead for Mock { + type Error = Error; + + fn version(&self) -> ProtocolVersion { + self.version + } + + async fn try_read_number(&mut self) -> Result<Option<u64>, Self::Error> { + match self.ops.pop_front() { + Some(Operation::ReadNumber(ret)) => ret.map(Some), + Some(Operation::ReadBytes(_)) => Err(Error::expected_read_bytes()), + None => Ok(None), + } + } + + async fn try_read_bytes_limited( + &mut self, + _limit: std::ops::RangeInclusive<usize>, + ) -> Result<Option<Bytes>, Self::Error> { + match self.ops.pop_front() { + Some(Operation::ReadBytes(ret)) => ret.map(Some), + Some(Operation::ReadNumber(_)) => Err(Error::expected_read_number()), + None => Ok(None), + } + } +} + +impl Drop for Mock { + fn drop(&mut self) { + // No need to panic again + if thread::panicking() { + return; + } + if let Some(op) = self.ops.front() { + panic!("reader dropped with {op:?} operation still unread") + } + } +} + +#[cfg(test)] +mod test { + use bytes::Bytes; + use hex_literal::hex; + + use crate::nix_daemon::de::NixRead; + + use super::{Builder, Error}; + + #[tokio::test] + async fn read_slice() { + let mut mock = Builder::new() + .read_number(10) + .read_slice(&[]) + .read_slice(&hex!("0000 1234 5678 9ABC DEFF")) + .build(); + assert_eq!(10, mock.read_number().await.unwrap()); + assert_eq!(&[] as &[u8], &mock.read_bytes().await.unwrap()[..]); + assert_eq!( + &hex!("0000 1234 5678 9ABC DEFF"), + &mock.read_bytes().await.unwrap()[..] + ); + assert_eq!(None, mock.try_read_number().await.unwrap()); + assert_eq!(None, mock.try_read_bytes().await.unwrap()); + } + + #[tokio::test] + async fn read_bytes() { + let mut mock = Builder::new() + .read_number(10) + .read_bytes(Bytes::from_static(&[])) + .read_bytes(Bytes::from_static(&hex!("0000 1234 5678 9ABC DEFF"))) + .build(); + assert_eq!(10, mock.read_number().await.unwrap()); + assert_eq!(&[] as &[u8], &mock.read_bytes().await.unwrap()[..]); + assert_eq!( + &hex!("0000 1234 5678 9ABC DEFF"), + &mock.read_bytes().await.unwrap()[..] + ); + assert_eq!(None, mock.try_read_number().await.unwrap()); + assert_eq!(None, mock.try_read_bytes().await.unwrap()); + } + + #[tokio::test] + async fn read_number() { + let mut mock = Builder::new().read_number(10).build(); + assert_eq!(10, mock.read_number().await.unwrap()); + assert_eq!(None, mock.try_read_number().await.unwrap()); + assert_eq!(None, mock.try_read_bytes().await.unwrap()); + } + + #[tokio::test] + async fn expect_number() { + let mut mock = Builder::new().read_number(10).build(); + assert_eq!( + Error::expected_read_number(), + mock.read_bytes().await.unwrap_err() + ); + } + + #[tokio::test] + async fn expect_bytes() { + let mut mock = Builder::new().read_slice(&[]).build(); + assert_eq!( + Error::expected_read_bytes(), + mock.read_number().await.unwrap_err() + ); + } + + #[test] + #[should_panic] + fn operations_left() { + let _ = Builder::new().read_number(10).build(); + } +} diff --git a/tvix/nix-compat/src/nix_daemon/de/mod.rs b/tvix/nix-compat/src/nix_daemon/de/mod.rs new file mode 100644 index 000000000000..f85ccd8fea0e --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/mod.rs @@ -0,0 +1,225 @@ +use std::error::Error as StdError; +use std::future::Future; +use std::ops::RangeInclusive; +use std::{fmt, io}; + +use ::bytes::Bytes; + +use super::ProtocolVersion; + +mod bytes; +mod collections; +mod int; +#[cfg(any(test, feature = "test"))] +pub mod mock; +mod reader; + +pub use reader::{NixReader, NixReaderBuilder}; + +/// Like serde the `Error` trait allows `NixRead` implementations to add +/// custom error handling for `NixDeserialize`. +pub trait Error: Sized + StdError { + /// A totally custom non-specific error. + fn custom<T: fmt::Display>(msg: T) -> Self; + + /// Some kind of std::io::Error occured. + fn io_error(err: std::io::Error) -> Self { + Self::custom(format_args!("There was an I/O error {}", err)) + } + + /// The data read from `NixRead` is invalid. + /// This could be that some bytes were supposed to be valid UFT-8 but weren't. + fn invalid_data<T: fmt::Display>(msg: T) -> Self { + Self::custom(msg) + } + + /// Required data is missing. This is mostly like an EOF + fn missing_data<T: fmt::Display>(msg: T) -> Self { + Self::custom(msg) + } +} + +impl Error for io::Error { + fn custom<T: fmt::Display>(msg: T) -> Self { + io::Error::new(io::ErrorKind::Other, msg.to_string()) + } + + fn io_error(err: std::io::Error) -> Self { + err + } + + fn invalid_data<T: fmt::Display>(msg: T) -> Self { + io::Error::new(io::ErrorKind::InvalidData, msg.to_string()) + } + + fn missing_data<T: fmt::Display>(msg: T) -> Self { + io::Error::new(io::ErrorKind::UnexpectedEof, msg.to_string()) + } +} + +/// A reader of data from the Nix daemon protocol. +/// Basically there are two basic types in the Nix daemon protocol +/// u64 and a bytes buffer. Everything else is more or less built on +/// top of these two types. +pub trait NixRead: Send { + type Error: Error + Send; + + /// Some types are serialized differently depending on the version + /// of the protocol and so this can be used for implementing that. + fn version(&self) -> ProtocolVersion; + + /// Read a single u64 from the protocol. + /// This returns an Option to support graceful shutdown. + fn try_read_number( + &mut self, + ) -> impl Future<Output = Result<Option<u64>, Self::Error>> + Send + '_; + + /// Read bytes from the protocol. + /// A size limit on the returned bytes has to be specified. + /// This returns an Option to support graceful shutdown. + fn try_read_bytes_limited( + &mut self, + limit: RangeInclusive<usize>, + ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_; + + /// Read bytes from the protocol without a limit. + /// The default implementation just calls `try_read_bytes_limited` with a + /// limit of `0..=usize::MAX` but other implementations are free to have a + /// reader wide limit. + /// This returns an Option to support graceful shutdown. + fn try_read_bytes( + &mut self, + ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ { + self.try_read_bytes_limited(0..=usize::MAX) + } + + /// Read a single u64 from the protocol. + /// This will return an error if the number could not be read. + fn read_number(&mut self) -> impl Future<Output = Result<u64, Self::Error>> + Send + '_ { + async move { + match self.try_read_number().await? { + Some(v) => Ok(v), + None => Err(Self::Error::missing_data("unexpected end-of-file")), + } + } + } + + /// Read bytes from the protocol. + /// A size limit on the returned bytes has to be specified. + /// This will return an error if the number could not be read. + fn read_bytes_limited( + &mut self, + limit: RangeInclusive<usize>, + ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ { + async move { + match self.try_read_bytes_limited(limit).await? { + Some(v) => Ok(v), + None => Err(Self::Error::missing_data("unexpected end-of-file")), + } + } + } + + /// Read bytes from the protocol. + /// The default implementation just calls `read_bytes_limited` with a + /// limit of `0..=usize::MAX` but other implementations are free to have a + /// reader wide limit. + /// This will return an error if the bytes could not be read. + fn read_bytes(&mut self) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ { + self.read_bytes_limited(0..=usize::MAX) + } + + /// Read a value from the protocol. + /// Uses `NixDeserialize::deserialize` to read a value. + fn read_value<V: NixDeserialize>( + &mut self, + ) -> impl Future<Output = Result<V, Self::Error>> + Send + '_ { + V::deserialize(self) + } + + /// Read a value from the protocol. + /// Uses `NixDeserialize::try_deserialize` to read a value. + /// This returns an Option to support graceful shutdown. + fn try_read_value<V: NixDeserialize>( + &mut self, + ) -> impl Future<Output = Result<Option<V>, Self::Error>> + Send + '_ { + V::try_deserialize(self) + } +} + +impl<T: ?Sized + NixRead> NixRead for &mut T { + type Error = T::Error; + + fn version(&self) -> ProtocolVersion { + (**self).version() + } + + fn try_read_number( + &mut self, + ) -> impl Future<Output = Result<Option<u64>, Self::Error>> + Send + '_ { + (**self).try_read_number() + } + + fn try_read_bytes_limited( + &mut self, + limit: RangeInclusive<usize>, + ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ { + (**self).try_read_bytes_limited(limit) + } + + fn try_read_bytes( + &mut self, + ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ { + (**self).try_read_bytes() + } + + fn read_number(&mut self) -> impl Future<Output = Result<u64, Self::Error>> + Send + '_ { + (**self).read_number() + } + + fn read_bytes_limited( + &mut self, + limit: RangeInclusive<usize>, + ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ { + (**self).read_bytes_limited(limit) + } + + fn read_bytes(&mut self) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ { + (**self).read_bytes() + } + + fn try_read_value<V: NixDeserialize>( + &mut self, + ) -> impl Future<Output = Result<Option<V>, Self::Error>> + Send + '_ { + (**self).try_read_value() + } + + fn read_value<V: NixDeserialize>( + &mut self, + ) -> impl Future<Output = Result<V, Self::Error>> + Send + '_ { + (**self).read_value() + } +} + +/// A data structure that can be deserialized from the Nix daemon +/// worker protocol. +pub trait NixDeserialize: Sized { + /// Read a value from the reader. + /// This returns an Option to support gracefull shutdown. + fn try_deserialize<R>( + reader: &mut R, + ) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_ + where + R: ?Sized + NixRead + Send; + + fn deserialize<R>(reader: &mut R) -> impl Future<Output = Result<Self, R::Error>> + Send + '_ + where + R: ?Sized + NixRead + Send, + { + async move { + match Self::try_deserialize(reader).await? { + Some(v) => Ok(v), + None => Err(R::Error::missing_data("unexpected end-of-file")), + } + } + } +} diff --git a/tvix/nix-compat/src/nix_daemon/de/reader.rs b/tvix/nix-compat/src/nix_daemon/de/reader.rs new file mode 100644 index 000000000000..87c623b2220c --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/reader.rs @@ -0,0 +1,527 @@ +use std::future::poll_fn; +use std::io::{self, Cursor}; +use std::ops::RangeInclusive; +use std::pin::Pin; +use std::task::{ready, Context, Poll}; + +use bytes::{Buf, BufMut, Bytes, BytesMut}; +use pin_project_lite::pin_project; +use tokio::io::{AsyncBufRead, AsyncRead, AsyncReadExt, ReadBuf}; + +use crate::nix_daemon::ProtocolVersion; +use crate::wire::EMPTY_BYTES; + +use super::{Error, NixRead}; + +pub struct NixReaderBuilder { + buf: Option<BytesMut>, + reserved_buf_size: usize, + max_buf_size: usize, + version: ProtocolVersion, +} + +impl Default for NixReaderBuilder { + fn default() -> Self { + Self { + buf: Default::default(), + reserved_buf_size: 8192, + max_buf_size: 8192, + version: Default::default(), + } + } +} + +impl NixReaderBuilder { + pub fn set_buffer(mut self, buf: BytesMut) -> Self { + self.buf = Some(buf); + self + } + + pub fn set_reserved_buf_size(mut self, size: usize) -> Self { + self.reserved_buf_size = size; + self + } + + pub fn set_max_buf_size(mut self, size: usize) -> Self { + self.max_buf_size = size; + self + } + + pub fn set_version(mut self, version: ProtocolVersion) -> Self { + self.version = version; + self + } + + pub fn build<R>(self, reader: R) -> NixReader<R> { + let buf = self.buf.unwrap_or_else(|| BytesMut::with_capacity(0)); + NixReader { + buf, + inner: reader, + reserved_buf_size: self.reserved_buf_size, + max_buf_size: self.max_buf_size, + version: self.version, + } + } +} + +pin_project! { + pub struct NixReader<R> { + #[pin] + inner: R, + buf: BytesMut, + reserved_buf_size: usize, + max_buf_size: usize, + version: ProtocolVersion, + } +} + +impl NixReader<Cursor<Vec<u8>>> { + pub fn builder() -> NixReaderBuilder { + NixReaderBuilder::default() + } +} + +impl<R> NixReader<R> +where + R: AsyncReadExt, +{ + pub fn new(reader: R) -> NixReader<R> { + NixReader::builder().build(reader) + } + + pub fn buffer(&self) -> &[u8] { + &self.buf[..] + } + + #[cfg(test)] + pub(crate) fn buffer_mut(&mut self) -> &mut BytesMut { + &mut self.buf + } + + /// Remaining capacity in internal buffer + pub fn remaining_mut(&self) -> usize { + self.buf.capacity() - self.buf.len() + } + + fn poll_force_fill_buf( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<io::Result<usize>> { + // Ensure that buffer has space for at least reserved_buf_size bytes + if self.remaining_mut() < self.reserved_buf_size { + let me = self.as_mut().project(); + me.buf.reserve(*me.reserved_buf_size); + } + let me = self.project(); + let n = { + let dst = me.buf.spare_capacity_mut(); + let mut buf = ReadBuf::uninit(dst); + let ptr = buf.filled().as_ptr(); + ready!(me.inner.poll_read(cx, &mut buf)?); + + // Ensure the pointer does not change from under us + assert_eq!(ptr, buf.filled().as_ptr()); + buf.filled().len() + }; + + // SAFETY: This is guaranteed to be the number of initialized (and read) + // bytes due to the invariants provided by `ReadBuf::filled`. + unsafe { + me.buf.advance_mut(n); + } + Poll::Ready(Ok(n)) + } +} + +impl<R> NixReader<R> +where + R: AsyncReadExt + Unpin, +{ + async fn force_fill(&mut self) -> io::Result<usize> { + let mut p = Pin::new(self); + let read = poll_fn(|cx| p.as_mut().poll_force_fill_buf(cx)).await?; + Ok(read) + } +} + +impl<R> NixRead for NixReader<R> +where + R: AsyncReadExt + Send + Unpin, +{ + type Error = io::Error; + + fn version(&self) -> ProtocolVersion { + self.version + } + + async fn try_read_number(&mut self) -> Result<Option<u64>, Self::Error> { + let mut buf = [0u8; 8]; + let read = self.read_buf(&mut &mut buf[..]).await?; + if read == 0 { + return Ok(None); + } + if read < 8 { + self.read_exact(&mut buf[read..]).await?; + } + let num = Buf::get_u64_le(&mut &buf[..]); + Ok(Some(num)) + } + + async fn try_read_bytes_limited( + &mut self, + limit: RangeInclusive<usize>, + ) -> Result<Option<Bytes>, Self::Error> { + assert!( + *limit.end() <= self.max_buf_size, + "The limit must be smaller than {}", + self.max_buf_size + ); + match self.try_read_number().await? { + Some(raw_len) => { + // Check that length is in range and convert to usize + let len = raw_len + .try_into() + .ok() + .filter(|v| limit.contains(v)) + .ok_or_else(|| Self::Error::invalid_data("bytes length out of range"))?; + + // Calculate 64bit aligned length and convert to usize + let aligned: usize = raw_len + .checked_add(7) + .map(|v| v & !7) + .ok_or_else(|| Self::Error::invalid_data("bytes length out of range"))? + .try_into() + .map_err(Self::Error::invalid_data)?; + + // Ensure that there is enough space in buffer for contents + if self.buf.len() + self.remaining_mut() < aligned { + self.buf.reserve(aligned - self.buf.len()); + } + while self.buf.len() < aligned { + if self.force_fill().await? == 0 { + return Err(Self::Error::missing_data( + "unexpected end-of-file reading bytes", + )); + } + } + let mut contents = self.buf.split_to(aligned); + + let padding = aligned - len; + // Ensure padding is all zeros + if contents[len..] != EMPTY_BYTES[..padding] { + return Err(Self::Error::invalid_data("non-zero padding")); + } + + contents.truncate(len); + Ok(Some(contents.freeze())) + } + None => Ok(None), + } + } + + fn try_read_bytes( + &mut self, + ) -> impl std::future::Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ { + self.try_read_bytes_limited(0..=self.max_buf_size) + } + + fn read_bytes( + &mut self, + ) -> impl std::future::Future<Output = Result<Bytes, Self::Error>> + Send + '_ { + self.read_bytes_limited(0..=self.max_buf_size) + } +} + +impl<R: AsyncRead> AsyncRead for NixReader<R> { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, + ) -> Poll<io::Result<()>> { + let rem = ready!(self.as_mut().poll_fill_buf(cx))?; + let amt = std::cmp::min(rem.len(), buf.remaining()); + buf.put_slice(&rem[0..amt]); + self.consume(amt); + Poll::Ready(Ok(())) + } +} + +impl<R: AsyncRead> AsyncBufRead for NixReader<R> { + fn poll_fill_buf(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> { + if self.as_ref().project_ref().buf.is_empty() { + ready!(self.as_mut().poll_force_fill_buf(cx))?; + } + let me = self.project(); + Poll::Ready(Ok(&me.buf[..])) + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + let me = self.project(); + me.buf.advance(amt) + } +} + +#[cfg(test)] +mod test { + use std::time::Duration; + + use hex_literal::hex; + use rstest::rstest; + use tokio_test::io::Builder; + + use super::*; + use crate::nix_daemon::de::NixRead; + + #[tokio::test] + async fn test_read_u64() { + let mock = Builder::new().read(&hex!("0100 0000 0000 0000")).build(); + let mut reader = NixReader::new(mock); + + assert_eq!(1, reader.read_number().await.unwrap()); + assert_eq!(hex!(""), reader.buffer()); + + let mut buf = Vec::new(); + reader.read_to_end(&mut buf).await.unwrap(); + assert_eq!(hex!(""), &buf[..]); + } + + #[tokio::test] + async fn test_read_u64_rest() { + let mock = Builder::new() + .read(&hex!("0100 0000 0000 0000 0123 4567 89AB CDEF")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!(1, reader.read_number().await.unwrap()); + assert_eq!(hex!("0123 4567 89AB CDEF"), reader.buffer()); + + let mut buf = Vec::new(); + reader.read_to_end(&mut buf).await.unwrap(); + assert_eq!(hex!("0123 4567 89AB CDEF"), &buf[..]); + } + + #[tokio::test] + async fn test_read_u64_partial() { + let mock = Builder::new() + .read(&hex!("0100 0000")) + .wait(Duration::ZERO) + .read(&hex!("0000 0000 0123 4567 89AB CDEF")) + .wait(Duration::ZERO) + .read(&hex!("0100 0000")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!(1, reader.read_number().await.unwrap()); + assert_eq!(hex!("0123 4567 89AB CDEF"), reader.buffer()); + + let mut buf = Vec::new(); + reader.read_to_end(&mut buf).await.unwrap(); + assert_eq!(hex!("0123 4567 89AB CDEF 0100 0000"), &buf[..]); + } + + #[tokio::test] + async fn test_read_u64_eof() { + let mock = Builder::new().build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.read_number().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_try_read_u64_none() { + let mock = Builder::new().build(); + let mut reader = NixReader::new(mock); + + assert_eq!(None, reader.try_read_number().await.unwrap()); + } + + #[tokio::test] + async fn test_try_read_u64_eof() { + let mock = Builder::new().read(&hex!("0100 0000 0000")).build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.try_read_number().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_try_read_u64_eof2() { + let mock = Builder::new() + .read(&hex!("0100")) + .wait(Duration::ZERO) + .read(&hex!("0000 0000")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.try_read_number().await.unwrap_err().kind() + ); + } + + #[rstest] + #[case::empty(b"", &hex!("0000 0000 0000 0000"))] + #[case::one(b")", &hex!("0100 0000 0000 0000 2900 0000 0000 0000"))] + #[case::two(b"it", &hex!("0200 0000 0000 0000 6974 0000 0000 0000"))] + #[case::three(b"tea", &hex!("0300 0000 0000 0000 7465 6100 0000 0000"))] + #[case::four(b"were", &hex!("0400 0000 0000 0000 7765 7265 0000 0000"))] + #[case::five(b"where", &hex!("0500 0000 0000 0000 7768 6572 6500 0000"))] + #[case::six(b"unwrap", &hex!("0600 0000 0000 0000 756E 7772 6170 0000"))] + #[case::seven(b"where's", &hex!("0700 0000 0000 0000 7768 6572 6527 7300"))] + #[case::aligned(b"read_tea", &hex!("0800 0000 0000 0000 7265 6164 5F74 6561"))] + #[case::more_bytes(b"read_tess", &hex!("0900 0000 0000 0000 7265 6164 5F74 6573 7300 0000 0000 0000"))] + #[tokio::test] + async fn test_read_bytes(#[case] expected: &[u8], #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual = reader.read_bytes().await.unwrap(); + assert_eq!(&actual[..], expected); + } + + #[tokio::test] + async fn test_read_bytes_empty() { + let mock = Builder::new().build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.read_bytes().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_try_read_bytes_none() { + let mock = Builder::new().build(); + let mut reader = NixReader::new(mock); + + assert_eq!(None, reader.try_read_bytes().await.unwrap()); + } + + #[tokio::test] + async fn test_try_read_bytes_missing_data() { + let mock = Builder::new() + .read(&hex!("0500")) + .wait(Duration::ZERO) + .read(&hex!("0000 0000")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.try_read_bytes().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_try_read_bytes_missing_padding() { + let mock = Builder::new() + .read(&hex!("0200 0000 0000 0000")) + .wait(Duration::ZERO) + .read(&hex!("1234")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.try_read_bytes().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_read_bytes_bad_padding() { + let mock = Builder::new() + .read(&hex!("0200 0000 0000 0000")) + .wait(Duration::ZERO) + .read(&hex!("1234 0100 0000 0000")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::InvalidData, + reader.read_bytes().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_read_bytes_limited_out_of_range() { + let mock = Builder::new().read(&hex!("FFFF 0000 0000 0000")).build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::InvalidData, + reader.read_bytes_limited(0..=50).await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_read_bytes_length_overflow() { + let mock = Builder::new().read(&hex!("F9FF FFFF FFFF FFFF")).build(); + let mut reader = NixReader::builder() + .set_max_buf_size(usize::MAX) + .build(mock); + + assert_eq!( + io::ErrorKind::InvalidData, + reader + .read_bytes_limited(0..=usize::MAX) + .await + .unwrap_err() + .kind() + ); + } + + // FUTUREWORK: Test this on supported hardware + #[tokio::test] + #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] + async fn test_bytes_length_conversion_overflow() { + let len = (usize::MAX as u64) + 1; + let mock = Builder::new().read(&len.to_le_bytes()).build(); + let mut reader = NixReader::new(mock); + assert_eq!( + std::io::ErrorKind::InvalidData, + reader.read_value::<usize>().await.unwrap_err().kind() + ); + } + + // FUTUREWORK: Test this on supported hardware + #[tokio::test] + #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] + async fn test_bytes_aligned_length_conversion_overflow() { + let len = (usize::MAX - 6) as u64; + let mock = Builder::new().read(&len.to_le_bytes()).build(); + let mut reader = NixReader::new(mock); + assert_eq!( + std::io::ErrorKind::InvalidData, + reader.read_value::<usize>().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_buffer_resize() { + let mock = Builder::new() + .read(&hex!("0100")) + .read(&hex!("0000 0000 0000")) + .build(); + let mut reader = NixReader::builder().set_reserved_buf_size(8).build(mock); + // buffer has no capacity initially + assert_eq!(0, reader.buffer_mut().capacity()); + + assert_eq!(2, reader.force_fill().await.unwrap()); + + // After first read buffer should have capacity we chose + assert_eq!(8, reader.buffer_mut().capacity()); + + // Because there was only 6 bytes remaining in buffer, + // which is enough to read the last 6 bytes, but we require + // capacity for 8 bytes, it doubled the capacity + assert_eq!(6, reader.force_fill().await.unwrap()); + assert_eq!(16, reader.buffer_mut().capacity()); + + assert_eq!(1, reader.read_number().await.unwrap()); + } +} diff --git a/tvix/nix-compat/src/nix_daemon/mod.rs b/tvix/nix-compat/src/nix_daemon/mod.rs index fe652377d1b4..11413e85fd1b 100644 --- a/tvix/nix-compat/src/nix_daemon/mod.rs +++ b/tvix/nix-compat/src/nix_daemon/mod.rs @@ -2,3 +2,5 @@ pub mod worker_protocol; mod protocol_version; pub use protocol_version::ProtocolVersion; + +pub mod de; diff --git a/tvix/nix-compat/src/nix_daemon/protocol_version.rs b/tvix/nix-compat/src/nix_daemon/protocol_version.rs index 8fd2b085c962..19da28d484dd 100644 --- a/tvix/nix-compat/src/nix_daemon/protocol_version.rs +++ b/tvix/nix-compat/src/nix_daemon/protocol_version.rs @@ -1,3 +1,6 @@ +/// The latest version that is currently supported by nix-compat. +static DEFAULT_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::from_parts(1, 37); + /// Protocol versions are represented as a u16. /// The upper 8 bits are the major version, the lower bits the minor. /// This is not aware of any endianness, use [crate::wire::read_u64] to get an @@ -20,6 +23,12 @@ impl ProtocolVersion { } } +impl Default for ProtocolVersion { + fn default() -> Self { + DEFAULT_PROTOCOL_VERSION + } +} + impl PartialOrd for ProtocolVersion { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { Some(self.cmp(other)) @@ -45,6 +54,13 @@ impl From<u16> for ProtocolVersion { } } +#[cfg(any(test, feature = "test"))] +impl From<(u8, u8)> for ProtocolVersion { + fn from((major, minor): (u8, u8)) -> Self { + Self::from_parts(major, minor) + } +} + impl TryFrom<u64> for ProtocolVersion { type Error = &'static str; diff --git a/tvix/nix-compat/src/nix_daemon/worker_protocol.rs b/tvix/nix-compat/src/nix_daemon/worker_protocol.rs index 58a48d1bdd25..7e3adc0db2ff 100644 --- a/tvix/nix-compat/src/nix_daemon/worker_protocol.rs +++ b/tvix/nix-compat/src/nix_daemon/worker_protocol.rs @@ -15,13 +15,34 @@ static WORKER_MAGIC_1: u64 = 0x6e697863; // "nixc" static WORKER_MAGIC_2: u64 = 0x6478696f; // "dxio" pub static STDERR_LAST: u64 = 0x616c7473; // "alts" +/// | Nix version | Protocol | +/// |-----------------|----------| +/// | 0.11 | 1.02 | +/// | 0.12 | 1.04 | +/// | 0.13 | 1.05 | +/// | 0.14 | 1.05 | +/// | 0.15 | 1.05 | +/// | 0.16 | 1.06 | +/// | 1.0 | 1.10 | +/// | 1.1 | 1.11 | +/// | 1.2 | 1.12 | +/// | 1.3 - 1.5.3 | 1.13 | +/// | 1.6 - 1.10 | 1.14 | +/// | 1.11 - 1.11.16 | 1.15 | +/// | 2.0 - 2.0.4 | 1.20 | +/// | 2.1 - 2.3.18 | 1.21 | +/// | 2.4 - 2.6.1 | 1.32 | +/// | 2.7.0 | 1.33 | +/// | 2.8.0 - 2.14.1 | 1.34 | +/// | 2.15.0 - 2.19.4 | 1.35 | +/// | 2.20.0 - 2.22.0 | 1.37 | static PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::from_parts(1, 37); /// Max length of a Nix setting name/value. In bytes. /// /// This value has been arbitrarily choosen after looking the nix.conf /// manpage. Don't hesitate to increase it if it's too limiting. -pub static MAX_SETTING_SIZE: u64 = 1024; +pub static MAX_SETTING_SIZE: usize = 1024; /// Worker Operation /// @@ -131,30 +152,30 @@ pub async fn read_client_settings<R: AsyncReadExt + Unpin>( r: &mut R, client_version: ProtocolVersion, ) -> std::io::Result<ClientSettings> { - let keep_failed = wire::read_bool(r).await?; - let keep_going = wire::read_bool(r).await?; - let try_fallback = wire::read_bool(r).await?; - let verbosity_uint = wire::read_u64(r).await?; + let keep_failed = r.read_u64_le().await? != 0; + let keep_going = r.read_u64_le().await? != 0; + let try_fallback = r.read_u64_le().await? != 0; + let verbosity_uint = r.read_u64_le().await?; let verbosity = Verbosity::from_u64(verbosity_uint).ok_or_else(|| { Error::new( ErrorKind::InvalidData, format!("Can't convert integer {} to verbosity", verbosity_uint), ) })?; - let max_build_jobs = wire::read_u64(r).await?; - let max_silent_time = wire::read_u64(r).await?; - _ = wire::read_u64(r).await?; // obsolete useBuildHook - let verbose_build = wire::read_bool(r).await?; - _ = wire::read_u64(r).await?; // obsolete logType - _ = wire::read_u64(r).await?; // obsolete printBuildTrace - let build_cores = wire::read_u64(r).await?; - let use_substitutes = wire::read_bool(r).await?; + let max_build_jobs = r.read_u64_le().await?; + let max_silent_time = r.read_u64_le().await?; + _ = r.read_u64_le().await?; // obsolete useBuildHook + let verbose_build = r.read_u64_le().await? != 0; + _ = r.read_u64_le().await?; // obsolete logType + _ = r.read_u64_le().await?; // obsolete printBuildTrace + let build_cores = r.read_u64_le().await?; + let use_substitutes = r.read_u64_le().await? != 0; let mut overrides = HashMap::new(); if client_version.minor() >= 12 { - let num_overrides = wire::read_u64(r).await?; + let num_overrides = r.read_u64_le().await?; for _ in 0..num_overrides { - let name = wire::read_string(r, 0..MAX_SETTING_SIZE).await?; - let value = wire::read_string(r, 0..MAX_SETTING_SIZE).await?; + let name = wire::read_string(r, 0..=MAX_SETTING_SIZE).await?; + let value = wire::read_string(r, 0..=MAX_SETTING_SIZE).await?; overrides.insert(name, value); } } @@ -197,17 +218,17 @@ pub async fn server_handshake_client<'a, RW: 'a>( where &'a mut RW: AsyncReadExt + AsyncWriteExt + Unpin, { - let worker_magic_1 = wire::read_u64(&mut conn).await?; + let worker_magic_1 = conn.read_u64_le().await?; if worker_magic_1 != WORKER_MAGIC_1 { Err(std::io::Error::new( ErrorKind::InvalidData, format!("Incorrect worker magic number received: {}", worker_magic_1), )) } else { - wire::write_u64(&mut conn, WORKER_MAGIC_2).await?; - wire::write_u64(&mut conn, PROTOCOL_VERSION.into()).await?; + conn.write_u64_le(WORKER_MAGIC_2).await?; + conn.write_u64_le(PROTOCOL_VERSION.into()).await?; conn.flush().await?; - let client_version = wire::read_u64(&mut conn).await?; + let client_version = conn.read_u64_le().await?; // Parse into ProtocolVersion. let client_version: ProtocolVersion = client_version .try_into() @@ -220,14 +241,14 @@ where } if client_version.minor() >= 14 { // Obsolete CPU affinity. - let read_affinity = wire::read_u64(&mut conn).await?; + let read_affinity = conn.read_u64_le().await?; if read_affinity != 0 { - let _cpu_affinity = wire::read_u64(&mut conn).await?; + let _cpu_affinity = conn.read_u64_le().await?; }; } if client_version.minor() >= 11 { // Obsolete reserveSpace - let _reserve_space = wire::read_u64(&mut conn).await?; + let _reserve_space = conn.read_u64_le().await?; } if client_version.minor() >= 33 { // Nix version. We're plain lying, we're not Nix, but eh… @@ -245,7 +266,7 @@ where /// Read a worker [Operation] from the wire. pub async fn read_op<R: AsyncReadExt + Unpin>(r: &mut R) -> std::io::Result<Operation> { - let op_number = wire::read_u64(r).await?; + let op_number = r.read_u64_le().await?; Operation::from_u64(op_number).ok_or(Error::new( ErrorKind::InvalidData, format!("Invalid OP number {}", op_number), @@ -278,8 +299,8 @@ where W: AsyncReadExt + AsyncWriteExt + Unpin, { match t { - Trust::Trusted => wire::write_u64(conn, 1).await, - Trust::NotTrusted => wire::write_u64(conn, 2).await, + Trust::Trusted => conn.write_u64_le(1).await, + Trust::NotTrusted => conn.write_u64_le(2).await, } } diff --git a/tvix/nix-compat/src/nix_http/mod.rs b/tvix/nix-compat/src/nix_http/mod.rs new file mode 100644 index 000000000000..89ba147b8071 --- /dev/null +++ b/tvix/nix-compat/src/nix_http/mod.rs @@ -0,0 +1,115 @@ +use tracing::trace; + +use crate::nixbase32; + +/// The mime type used for NAR files, both compressed and uncompressed +pub const MIME_TYPE_NAR: &str = "application/x-nix-nar"; +/// The mime type used for NARInfo files +pub const MIME_TYPE_NARINFO: &str = "text/x-nix-narinfo"; +/// The mime type used for the `nix-cache-info` file +pub const MIME_TYPE_CACHE_INFO: &str = "text/x-nix-cache-info"; + +/// Parses a `14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0k.nar` +/// string and returns the nixbase32-decoded digest, as well as the compression +/// suffix (which might be empty). +pub fn parse_nar_str(s: &str) -> Option<([u8; 32], &str)> { + if !s.is_char_boundary(52) { + trace!("invalid string, no char boundary at 52"); + return None; + } + + let (hash_str, suffix) = s.split_at(52); + + // we know hash_str is 52 bytes, so it's ok to unwrap here. + let hash_str_fixed: [u8; 52] = hash_str.as_bytes().try_into().unwrap(); + + match suffix.strip_prefix(".nar") { + Some(compression_suffix) => match nixbase32::decode_fixed(hash_str_fixed) { + Err(e) => { + trace!(err=%e, "invalid nixbase32 encoding"); + None + } + Ok(digest) => Some((digest, compression_suffix)), + }, + None => { + trace!("no .nar suffix"); + None + } + } +} + +/// Parses a `3mzh8lvgbynm9daj7c82k2sfsfhrsfsy.narinfo` string and returns the +/// nixbase32-decoded digest. +pub fn parse_narinfo_str(s: &str) -> Option<[u8; 20]> { + if !s.is_char_boundary(32) { + trace!("invalid string, no char boundary at 32"); + return None; + } + + match s.split_at(32) { + (hash_str, ".narinfo") => { + // we know this is 32 bytes, so it's ok to unwrap here. + let hash_str_fixed: [u8; 32] = hash_str.as_bytes().try_into().unwrap(); + + match nixbase32::decode_fixed(hash_str_fixed) { + Err(e) => { + trace!(err=%e, "invalid nixbase32 encoding"); + None + } + Ok(digest) => Some(digest), + } + } + _ => { + trace!("invalid string, no .narinfo suffix"); + None + } + } +} + +#[cfg(test)] +mod test { + use super::{parse_nar_str, parse_narinfo_str}; + use hex_literal::hex; + + #[test] + fn parse_nar_str_success() { + assert_eq!( + ( + hex!("13a8cf7ca57f68a9f1752acee36a72a55187d3a954443c112818926f26109d91"), + "" + ), + parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0k.nar").unwrap() + ); + + assert_eq!( + ( + hex!("13a8cf7ca57f68a9f1752acee36a72a55187d3a954443c112818926f26109d91"), + ".xz" + ), + parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0k.nar.xz").unwrap() + ) + } + + #[test] + fn parse_nar_str_failure() { + assert!(parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0").is_none()); + assert!( + parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0🦊.nar").is_none() + ) + } + #[test] + fn parse_narinfo_str_success() { + assert_eq!( + hex!("8a12321522fd91efbd60ebb2481af88580f61600"), + parse_narinfo_str("00bgd045z0d4icpbc2yyz4gx48ak44la.narinfo").unwrap() + ); + } + + #[test] + fn parse_narinfo_str_failure() { + assert!(parse_narinfo_str("00bgd045z0d4icpbc2yyz4gx48ak44la").is_none()); + assert!(parse_narinfo_str("/00bgd045z0d4icpbc2yyz4gx48ak44la").is_none()); + assert!(parse_narinfo_str("000000").is_none()); + assert!(parse_narinfo_str("00bgd045z0d4icpbc2yyz4gx48ak44l🦊.narinfo").is_none()); + } +} diff --git a/tvix/nix-compat/src/nixbase32.rs b/tvix/nix-compat/src/nixbase32.rs index b7ffc1dc2bcd..8d34e4cedce6 100644 --- a/tvix/nix-compat/src/nixbase32.rs +++ b/tvix/nix-compat/src/nixbase32.rs @@ -62,6 +62,12 @@ pub fn decode(input: impl AsRef<[u8]>) -> Result<Vec<u8>, DecodeError> { let input = input.as_ref(); let output_len = decode_len(input.len()); + if input.len() != encode_len(output_len) { + return Err(DecodeError { + position: input.len().min(encode_len(output_len)), + kind: DecodeKind::Length, + }); + } let mut output: Vec<u8> = vec![0x00; output_len]; decode_inner(input, &mut output)?; @@ -163,6 +169,10 @@ mod tests { #[case::invalid_encoding_1("zz", None)] // this is an even more specific example - it'd decode as 00000000 11 #[case::invalid_encoding_2("c0", None)] + // This has an invalid length + #[case::invalid_encoding_3("0", None)] + // This has an invalid length + #[case::invalid_encoding_4("0zz", None)] #[test] fn decode(#[case] enc: &str, #[case] dec: Option<&[u8]>) { match dec { @@ -201,6 +211,11 @@ mod tests { #[test] fn decode_len() { assert_eq!(super::decode_len(0), 0); + assert_eq!(super::decode_len(1), 0); + assert_eq!(super::decode_len(2), 1); + assert_eq!(super::decode_len(3), 1); + assert_eq!(super::decode_len(4), 2); + assert_eq!(super::decode_len(5), 3); assert_eq!(super::decode_len(32), 20); } } diff --git a/tvix/nix-compat/src/nixcpp/conf.rs b/tvix/nix-compat/src/nixcpp/conf.rs new file mode 100644 index 000000000000..68308115f988 --- /dev/null +++ b/tvix/nix-compat/src/nixcpp/conf.rs @@ -0,0 +1,202 @@ +use std::{fmt::Display, str::FromStr}; + +/// Represents configuration as stored in /etc/nix/nix.conf. +/// This list is not exhaustive, feel free to add more. +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct NixConfig<'a> { + pub allowed_users: Option<Vec<&'a str>>, + pub auto_optimise_store: Option<bool>, + pub cores: Option<u64>, + pub max_jobs: Option<u64>, + pub require_sigs: Option<bool>, + pub sandbox: Option<SandboxSetting>, + pub sandbox_fallback: Option<bool>, + pub substituters: Option<Vec<&'a str>>, + pub system_features: Option<Vec<&'a str>>, + pub trusted_public_keys: Option<Vec<crate::narinfo::VerifyingKey>>, + pub trusted_substituters: Option<Vec<&'a str>>, + pub trusted_users: Option<Vec<&'a str>>, + pub extra_platforms: Option<Vec<&'a str>>, + pub extra_sandbox_paths: Option<Vec<&'a str>>, + pub experimental_features: Option<Vec<&'a str>>, + pub builders_use_substitutes: Option<bool>, +} + +impl<'a> NixConfig<'a> { + /// Parses configuration from a file like `/etc/nix/nix.conf`, returning + /// a [NixConfig] with all values contained in there. + /// It does not support parsing multiple config files, merging semantics, + /// and also does not understand `include` and `!include` statements. + pub fn parse(input: &'a str) -> Result<Self, Error> { + let mut out = Self::default(); + + for line in input.lines() { + // strip comments at the end of the line + let line = if let Some((line, _comment)) = line.split_once('#') { + line + } else { + line + }; + + // skip comments and empty lines + if line.trim().is_empty() { + continue; + } + + let (tag, val) = line + .split_once('=') + .ok_or_else(|| Error::InvalidLine(line.to_string()))?; + + // trim whitespace + let tag = tag.trim(); + let val = val.trim(); + + #[inline] + fn parse_val<'a>(this: &mut NixConfig<'a>, tag: &str, val: &'a str) -> Option<()> { + match tag { + "allowed-users" => { + this.allowed_users = Some(val.split_whitespace().collect()); + } + "auto-optimise-store" => { + this.auto_optimise_store = Some(val.parse::<bool>().ok()?); + } + "cores" => { + this.cores = Some(val.parse().ok()?); + } + "max-jobs" => { + this.max_jobs = Some(val.parse().ok()?); + } + "require-sigs" => { + this.require_sigs = Some(val.parse().ok()?); + } + "sandbox" => this.sandbox = Some(val.parse().ok()?), + "sandbox-fallback" => this.sandbox_fallback = Some(val.parse().ok()?), + "substituters" => this.substituters = Some(val.split_whitespace().collect()), + "system-features" => { + this.system_features = Some(val.split_whitespace().collect()) + } + "trusted-public-keys" => { + this.trusted_public_keys = Some( + val.split_whitespace() + .map(crate::narinfo::VerifyingKey::parse) + .collect::<Result<Vec<crate::narinfo::VerifyingKey>, _>>() + .ok()?, + ) + } + "trusted-substituters" => { + this.trusted_substituters = Some(val.split_whitespace().collect()) + } + "trusted-users" => this.trusted_users = Some(val.split_whitespace().collect()), + "extra-platforms" => { + this.extra_platforms = Some(val.split_whitespace().collect()) + } + "extra-sandbox-paths" => { + this.extra_sandbox_paths = Some(val.split_whitespace().collect()) + } + "experimental-features" => { + this.experimental_features = Some(val.split_whitespace().collect()) + } + "builders-use-substitutes" => { + this.builders_use_substitutes = Some(val.parse().ok()?) + } + _ => return None, + } + Some(()) + } + + parse_val(&mut out, tag, val) + .ok_or_else(|| Error::InvalidValue(tag.to_string(), val.to_string()))? + } + + Ok(out) + } +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Invalid line: {0}")] + InvalidLine(String), + #[error("Unrecognized key: {0}")] + UnrecognizedKey(String), + #[error("Invalid value '{1}' for key '{0}'")] + InvalidValue(String, String), +} + +/// Valid values for the Nix 'sandbox' setting +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum SandboxSetting { + True, + False, + Relaxed, +} + +impl Display for SandboxSetting { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SandboxSetting::True => write!(f, "true"), + SandboxSetting::False => write!(f, "false"), + SandboxSetting::Relaxed => write!(f, "relaxed"), + } + } +} + +impl FromStr for SandboxSetting { + type Err = &'static str; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(match s { + "true" => Self::True, + "false" => Self::False, + "relaxed" => Self::Relaxed, + _ => return Err("invalid value"), + }) + } +} + +#[cfg(test)] +mod tests { + use crate::{narinfo::VerifyingKey, nixcpp::conf::SandboxSetting}; + + use super::NixConfig; + + #[test] + pub fn test_parse() { + let config = NixConfig::parse(include_str!("../../testdata/nix.conf")).expect("must parse"); + + assert_eq!( + NixConfig { + allowed_users: Some(vec!["*"]), + auto_optimise_store: Some(false), + cores: Some(0), + max_jobs: Some(8), + require_sigs: Some(true), + sandbox: Some(SandboxSetting::True), + sandbox_fallback: Some(false), + substituters: Some(vec!["https://nix-community.cachix.org", "https://cache.nixos.org/"]), + system_features: Some(vec!["nixos-test", "benchmark", "big-parallel", "kvm"]), + trusted_public_keys: Some(vec![ + VerifyingKey::parse("cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=") + .expect("failed to parse pubkey"), + VerifyingKey::parse("nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=") + .expect("failed to parse pubkey") + ]), + trusted_substituters: Some(vec![]), + trusted_users: Some(vec!["flokli"]), + extra_platforms: Some(vec!["aarch64-linux", "i686-linux"]), + extra_sandbox_paths: Some(vec![ + "/run/binfmt", "/nix/store/swwyxyqpazzvbwx8bv40z7ih144q841f-qemu-aarch64-binfmt-P-x86_64-unknown-linux-musl" + ]), + experimental_features: Some(vec!["nix-command"]), + builders_use_substitutes: Some(true) + }, + config + ); + + // parse a config file using some non-space whitespaces, as well as comments right after the lines. + // ensure it contains the same data as initially parsed. + let other_config = NixConfig::parse(include_str!("../../testdata/other_nix.conf")) + .expect("other config must parse"); + + assert_eq!(config, other_config); + } +} diff --git a/tvix/nix-compat/src/nixcpp/mod.rs b/tvix/nix-compat/src/nixcpp/mod.rs new file mode 100644 index 000000000000..57518de8cc52 --- /dev/null +++ b/tvix/nix-compat/src/nixcpp/mod.rs @@ -0,0 +1,9 @@ +//! Contains code parsing some of the Nixcpp config files etc. +//! left by Nix *on the local disk*. +//! +//! This is only for Nix' own state/config. +//! +//! More "standardized" protocols, like parts of the Nix HTTP Binary Cache +//! protocol live elsewhere. + +pub mod conf; diff --git a/tvix/nix-compat/src/nixhash/ca_hash.rs b/tvix/nix-compat/src/nixhash/ca_hash.rs index 2bf5f966cefe..e6cbaf5b710a 100644 --- a/tvix/nix-compat/src/nixhash/ca_hash.rs +++ b/tvix/nix-compat/src/nixhash/ca_hash.rs @@ -47,12 +47,33 @@ impl CAHash { } } + /// Returns a colon-separated string consisting of mode, recursiveness and + /// hash algo. Used as a prefix in various string representations. + pub fn algo_str(&self) -> &'static str { + match self.mode() { + HashMode::Flat => match self.hash().as_ref() { + NixHash::Md5(_) => "fixed:md5", + NixHash::Sha1(_) => "fixed:sha1", + NixHash::Sha256(_) => "fixed:sha256", + NixHash::Sha512(_) => "fixed:sha512", + }, + HashMode::Nar => match self.hash().as_ref() { + NixHash::Md5(_) => "fixed:r:md5", + NixHash::Sha1(_) => "fixed:r:sha1", + NixHash::Sha256(_) => "fixed:r:sha256", + NixHash::Sha512(_) => "fixed:r:sha512", + }, + HashMode::Text => "text:sha256", + } + } + /// Constructs a [CAHash] from the textual representation, /// which is one of the three: /// - `text:sha256:$nixbase32sha256digest` /// - `fixed:r:$algo:$nixbase32digest` /// - `fixed:$algo:$nixbase32digest` - /// which is the format that's used in the NARInfo for example. + /// + /// These formats are used in NARInfo, for example. pub fn from_nix_hex_str(s: &str) -> Option<Self> { let (tag, s) = s.split_once(':')?; @@ -76,13 +97,11 @@ impl CAHash { /// Formats a [CAHash] in the Nix default hash format, which is the format /// that's used in NARInfos for example. pub fn to_nix_nixbase32_string(&self) -> String { - match self { - CAHash::Flat(nh) => format!("fixed:{}", nh.to_nix_nixbase32_string()), - CAHash::Nar(nh) => format!("fixed:r:{}", nh.to_nix_nixbase32_string()), - CAHash::Text(digest) => { - format!("text:sha256:{}", nixbase32::encode(digest)) - } - } + format!( + "{}:{}", + self.algo_str(), + nixbase32::encode(self.hash().digest_as_bytes()) + ) } /// This takes a serde_json::Map and turns it into this structure. This is necessary to do such @@ -90,11 +109,13 @@ impl CAHash { /// know whether we have a invalid or a missing NixHashWithMode structure in another structure, /// e.g. Output. /// This means we have this combinatorial situation: + /// /// - no hash, no hashAlgo: no [CAHash] so we return Ok(None). /// - present hash, missing hashAlgo: invalid, we will return missing_field /// - missing hash, present hashAlgo: same /// - present hash, present hashAlgo: either we return ourselves or a type/value validation - /// error. + /// error. + /// /// This function is for internal consumption regarding those needs until we have a better /// solution. Now this is said, let's explain how this works. /// diff --git a/tvix/nix-compat/src/store_path/mod.rs b/tvix/nix-compat/src/store_path/mod.rs index ac9f1805e3d1..56c10dc41417 100644 --- a/tvix/nix-compat/src/store_path/mod.rs +++ b/tvix/nix-compat/src/store_path/mod.rs @@ -2,15 +2,13 @@ use crate::nixbase32; use data_encoding::{DecodeError, BASE64}; use serde::{Deserialize, Serialize}; use std::{ - fmt, - path::PathBuf, + fmt::{self, Display}, + ops::Deref, + path::Path, str::{self, FromStr}, }; use thiserror; -#[cfg(target_family = "unix")] -use std::os::unix::ffi::OsStringExt; - mod utils; pub use utils::*; @@ -54,18 +52,27 @@ pub enum Error { /// A [StorePath] does not encode any additional subpath "inside" the store /// path. #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct StorePath { +pub struct StorePath<S> +where + S: std::cmp::Eq + std::cmp::PartialEq, +{ digest: [u8; DIGEST_SIZE], - name: String, + name: S, } +/// Like [StorePath], but without a heap allocation for the name. +/// Used by [StorePath] for parsing. +pub type StorePathRef<'a> = StorePath<&'a str>; -impl StorePath { +impl<S> StorePath<S> +where + S: std::cmp::Eq + Deref<Target = str>, +{ pub fn digest(&self) -> &[u8; DIGEST_SIZE] { &self.digest } - pub fn name(&self) -> &str { - self.name.as_ref() + pub fn name(&self) -> &S { + &self.name } pub fn as_ref(&self) -> StorePathRef<'_> { @@ -74,160 +81,62 @@ impl StorePath { name: &self.name, } } -} - -impl PartialOrd for StorePath { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -/// `StorePath`s are sorted by their reverse digest to match the sorting order -/// of the nixbase32-encoded string. -impl Ord for StorePath { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.as_ref().cmp(&other.as_ref()) - } -} -impl FromStr for StorePath { - type Err = Error; - - /// Construct a [StorePath] by passing the `$digest-$name` string - /// that comes after [STORE_DIR_WITH_SLASH]. - fn from_str(s: &str) -> Result<Self, Self::Err> { - Self::from_bytes(s.as_bytes()) + pub fn to_owned(&self) -> StorePath<String> { + StorePath { + digest: self.digest, + name: self.name.to_string(), + } } -} -impl StorePath { /// Construct a [StorePath] by passing the `$digest-$name` string /// that comes after [STORE_DIR_WITH_SLASH]. - pub fn from_bytes(s: &[u8]) -> Result<StorePath, Error> { - Ok(StorePathRef::from_bytes(s)?.to_owned()) - } - - /// Decompose a string into a [StorePath] and a [PathBuf] containing the - /// rest of the path, or an error. - #[cfg(target_family = "unix")] - pub fn from_absolute_path_full(s: &str) -> Result<(StorePath, PathBuf), Error> { - // strip [STORE_DIR_WITH_SLASH] from s - match s.strip_prefix(STORE_DIR_WITH_SLASH) { - None => Err(Error::MissingStoreDir), - Some(rest) => { - // put rest in a PathBuf - let mut p = PathBuf::new(); - p.push(rest); - - let mut it = p.components(); - - // The first component of the rest must be parse-able as a [StorePath] - if let Some(first_component) = it.next() { - // convert first component to StorePath - let first_component_bytes = first_component.as_os_str().to_owned().into_vec(); - let store_path = StorePath::from_bytes(&first_component_bytes)?; - // collect rest - let rest_buf: PathBuf = it.collect(); - Ok((store_path, rest_buf)) - } else { - Err(Error::InvalidLength) // Well, or missing "/"? - } - } - } - } - - /// Returns an absolute store path string. - /// That is just the string representation, prefixed with the store prefix - /// ([STORE_DIR_WITH_SLASH]), - pub fn to_absolute_path(&self) -> String { - let sp_ref: StorePathRef = self.into(); - sp_ref.to_absolute_path() - } -} - -impl<'de> Deserialize<'de> for StorePath { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where - D: serde::Deserializer<'de>, - { - let r = <StorePathRef<'de> as Deserialize<'de>>::deserialize(deserializer)?; - Ok(r.to_owned()) - } -} - -impl Serialize for StorePath { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + pub fn from_bytes<'a>(s: &'a [u8]) -> Result<Self, Error> where - S: serde::Serializer, + S: From<&'a str>, { - let r: StorePathRef = self.into(); - r.serialize(serializer) - } -} - -/// Like [StorePath], but without a heap allocation for the name. -/// Used by [StorePath] for parsing. -/// -#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)] -pub struct StorePathRef<'a> { - digest: [u8; DIGEST_SIZE], - name: &'a str, -} - -impl<'a> From<&'a StorePath> for StorePathRef<'a> { - fn from(&StorePath { digest, ref name }: &'a StorePath) -> Self { - StorePathRef { - digest, - name: name.as_ref(), + // the whole string needs to be at least: + // + // - 32 characters (encoded hash) + // - 1 dash + // - 1 character for the name + if s.len() < ENCODED_DIGEST_SIZE + 2 { + Err(Error::InvalidLength)? } - } -} -impl<'a> PartialOrd for StorePathRef<'a> { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -/// `StorePathRef`s are sorted by their reverse digest to match the sorting order -/// of the nixbase32-encoded string. -impl<'a> Ord for StorePathRef<'a> { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.digest.iter().rev().cmp(other.digest.iter().rev()) - } -} - -impl<'a> StorePathRef<'a> { - pub fn digest(&self) -> &[u8; DIGEST_SIZE] { - &self.digest - } - - pub fn name(&self) -> &'a str { - self.name - } + let digest = nixbase32::decode_fixed(&s[..ENCODED_DIGEST_SIZE])?; - pub fn to_owned(&self) -> StorePath { - StorePath { - digest: self.digest, - name: self.name.to_owned(), + if s[ENCODED_DIGEST_SIZE] != b'-' { + return Err(Error::MissingDash); } + + Ok(StorePath { + digest, + name: validate_name(&s[ENCODED_DIGEST_SIZE + 1..])?.into(), + }) } /// Construct a [StorePathRef] from a name and digest. /// The name is validated, and the digest checked for size. - pub fn from_name_and_digest(name: &'a str, digest: &[u8]) -> Result<Self, Error> { + pub fn from_name_and_digest<'a>(name: &'a str, digest: &[u8]) -> Result<Self, Error> + where + S: From<&'a str>, + { let digest_fixed = digest.try_into().map_err(|_| Error::InvalidLength)?; Self::from_name_and_digest_fixed(name, digest_fixed) } /// Construct a [StorePathRef] from a name and digest of correct length. /// The name is validated. - pub fn from_name_and_digest_fixed( + pub fn from_name_and_digest_fixed<'a>( name: &'a str, digest: [u8; DIGEST_SIZE], - ) -> Result<Self, Error> { + ) -> Result<Self, Error> + where + S: From<&'a str>, + { Ok(Self { - name: validate_name(name.as_bytes())?, + name: validate_name(name)?.into(), digest, }) } @@ -235,46 +144,87 @@ impl<'a> StorePathRef<'a> { /// Construct a [StorePathRef] from an absolute store path string. /// This is equivalent to calling [StorePathRef::from_bytes], but stripping /// the [STORE_DIR_WITH_SLASH] prefix before. - pub fn from_absolute_path(s: &'a [u8]) -> Result<Self, Error> { + pub fn from_absolute_path<'a>(s: &'a [u8]) -> Result<Self, Error> + where + S: From<&'a str>, + { match s.strip_prefix(STORE_DIR_WITH_SLASH.as_bytes()) { Some(s_stripped) => Self::from_bytes(s_stripped), None => Err(Error::MissingStoreDir), } } - /// Construct a [StorePathRef] by passing the `$digest-$name` string - /// that comes after [STORE_DIR_WITH_SLASH]. - pub fn from_bytes(s: &'a [u8]) -> Result<Self, Error> { - // the whole string needs to be at least: - // - // - 32 characters (encoded hash) - // - 1 dash - // - 1 character for the name - if s.len() < ENCODED_DIGEST_SIZE + 2 { - Err(Error::InvalidLength)? - } + /// Decompose a string into a [StorePath] and a [PathBuf] containing the + /// rest of the path, or an error. + #[cfg(target_family = "unix")] + pub fn from_absolute_path_full<'a, P>(path: &'a P) -> Result<(Self, &'a Path), Error> + where + S: From<&'a str>, + P: AsRef<std::path::Path> + ?Sized, + { + // strip [STORE_DIR_WITH_SLASH] from s + let p = path + .as_ref() + .strip_prefix(STORE_DIR_WITH_SLASH) + .map_err(|_e| Error::MissingStoreDir)?; - let digest = nixbase32::decode_fixed(&s[..ENCODED_DIGEST_SIZE])?; + let mut it = Path::new(p).components(); - if s[ENCODED_DIGEST_SIZE] != b'-' { - return Err(Error::MissingDash); - } + // The first component of the rest must be parse-able as a [StorePath] + let first_component = it.next().ok_or(Error::InvalidLength)?; + let store_path = StorePath::from_bytes(first_component.as_os_str().as_encoded_bytes())?; - Ok(StorePathRef { - digest, - name: validate_name(&s[ENCODED_DIGEST_SIZE + 1..])?, - }) + // collect rest + let rest_buf = it.as_path(); + + Ok((store_path, rest_buf)) } /// Returns an absolute store path string. /// That is just the string representation, prefixed with the store prefix /// ([STORE_DIR_WITH_SLASH]), - pub fn to_absolute_path(&self) -> String { + pub fn to_absolute_path(&self) -> String + where + S: Display, + { format!("{}{}", STORE_DIR_WITH_SLASH, self) } } -impl<'de: 'a, 'a> Deserialize<'de> for StorePathRef<'a> { +impl<S> PartialOrd for StorePath<S> +where + S: std::cmp::PartialEq + std::cmp::Eq, +{ + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + Some(self.cmp(other)) + } +} + +/// `StorePath`s are sorted by their reverse digest to match the sorting order +/// of the nixbase32-encoded string. +impl<S> Ord for StorePath<S> +where + S: std::cmp::PartialEq + std::cmp::Eq, +{ + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.digest.iter().rev().cmp(other.digest.iter().rev()) + } +} + +impl<'a, 'b: 'a> FromStr for StorePath<String> { + type Err = Error; + + /// Construct a [StorePath] by passing the `$digest-$name` string + /// that comes after [STORE_DIR_WITH_SLASH]. + fn from_str(s: &str) -> Result<Self, Self::Err> { + StorePath::<String>::from_bytes(s.as_bytes()) + } +} + +impl<'a, 'de: 'a, S> Deserialize<'de> for StorePath<S> +where + S: std::cmp::Eq + Deref<Target = str> + From<&'a str>, +{ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>, @@ -287,24 +237,26 @@ impl<'de: 'a, 'a> Deserialize<'de> for StorePathRef<'a> { &"store path prefix", ) })?; - StorePathRef::from_bytes(stripped.as_bytes()).map_err(|_| { + StorePath::from_bytes(stripped.as_bytes()).map_err(|_| { serde::de::Error::invalid_value(serde::de::Unexpected::Str(string), &"StorePath") }) } } -impl Serialize for StorePathRef<'_> { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> +impl<S> Serialize for StorePath<S> +where + S: std::cmp::Eq + Deref<Target = str> + Display, +{ + fn serialize<SR>(&self, serializer: SR) -> Result<SR::Ok, SR::Error> where - S: serde::Serializer, + SR: serde::Serializer, { let string: String = self.to_absolute_path(); string.serialize(serializer) } } -/// NAME_CHARS contains `true` for bytes that are valid in store path names, -/// not accounting for '.' being permitted only past the first character. +/// NAME_CHARS contains `true` for bytes that are valid in store path names. static NAME_CHARS: [bool; 256] = { let mut tbl = [false; 256]; let mut c = 0; @@ -332,10 +284,6 @@ pub(crate) fn validate_name(s: &(impl AsRef<[u8]> + ?Sized)) -> Result<&str, Err return Err(Error::InvalidLength); } - if s[0] == b'.' { - return Err(Error::InvalidName(s.to_vec(), 0)); - } - let mut valid = true; for &c in s { valid = valid && NAME_CHARS[c as usize]; @@ -355,13 +303,10 @@ pub(crate) fn validate_name(s: &(impl AsRef<[u8]> + ?Sized)) -> Result<&str, Err Ok(unsafe { str::from_utf8_unchecked(s) }) } -impl fmt::Display for StorePath { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - StorePathRef::from(self).fmt(f) - } -} - -impl fmt::Display for StorePathRef<'_> { +impl<S> fmt::Display for StorePath<S> +where + S: fmt::Display + std::cmp::Eq, +{ /// The string representation of a store path starts with a digest (20 /// bytes), [crate::nixbase32]-encoded, followed by a `-`, /// and ends with the name. @@ -394,12 +339,12 @@ mod tests { fn happy_path() { let example_nix_path_str = "00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432"; - let nixpath = StorePath::from_bytes(example_nix_path_str.as_bytes()) + let nixpath = StorePathRef::from_bytes(example_nix_path_str.as_bytes()) .expect("Error parsing example string"); let expected_digest: [u8; DIGEST_SIZE] = hex!("8a12321522fd91efbd60ebb2481af88580f61600"); - assert_eq!("net-tools-1.60_p20170221182432", nixpath.name); + assert_eq!("net-tools-1.60_p20170221182432", *nixpath.name()); assert_eq!(nixpath.digest, expected_digest); assert_eq!(example_nix_path_str, nixpath.to_string()) @@ -434,8 +379,8 @@ mod tests { if w.len() < 2 { continue; } - let (pa, _) = StorePath::from_absolute_path_full(w[0]).expect("parseable"); - let (pb, _) = StorePath::from_absolute_path_full(w[1]).expect("parseable"); + let (pa, _) = StorePathRef::from_absolute_path_full(w[0]).expect("parseable"); + let (pb, _) = StorePathRef::from_absolute_path_full(w[1]).expect("parseable"); assert_eq!( Ordering::Less, pa.cmp(&pb), @@ -446,43 +391,48 @@ mod tests { } } - /// This is the store path rejected when `nix-store --add`'ing an + /// This is the store path *accepted* when `nix-store --add`'ing an /// empty `.gitignore` file. /// - /// Nix 2.4 accidentally dropped this behaviour, but this is considered a bug. - /// See https://github.com/NixOS/nix/pull/9095. + /// Nix 2.4 accidentally permitted this behaviour, but the revert came + /// too late to beat Hyrum's law. It is now considered permissible. + /// + /// https://github.com/NixOS/nix/pull/9095 (revert) + /// https://github.com/NixOS/nix/pull/9867 (revert-of-revert) #[test] fn starts_with_dot() { - StorePath::from_bytes(b"fli4bwscgna7lpm7v5xgnjxrxh0yc7ra-.gitignore") - .expect_err("must fail"); + StorePathRef::from_bytes(b"fli4bwscgna7lpm7v5xgnjxrxh0yc7ra-.gitignore") + .expect("must succeed"); } #[test] fn empty_name() { - StorePath::from_bytes(b"00bgd045z0d4icpbc2yy-").expect_err("must fail"); + StorePathRef::from_bytes(b"00bgd045z0d4icpbc2yy-").expect_err("must fail"); } #[test] fn excessive_length() { - StorePath::from_bytes(b"00bgd045z0d4icpbc2yy-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + StorePathRef::from_bytes(b"00bgd045z0d4icpbc2yy-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") .expect_err("must fail"); } #[test] fn invalid_hash_length() { - StorePath::from_bytes(b"00bgd045z0d4icpbc2yy-net-tools-1.60_p20170221182432") + StorePathRef::from_bytes(b"00bgd045z0d4icpbc2yy-net-tools-1.60_p20170221182432") .expect_err("must fail"); } #[test] fn invalid_encoding_hash() { - StorePath::from_bytes(b"00bgd045z0d4icpbc2yyz4gx48aku4la-net-tools-1.60_p20170221182432") - .expect_err("must fail"); + StorePathRef::from_bytes( + b"00bgd045z0d4icpbc2yyz4gx48aku4la-net-tools-1.60_p20170221182432", + ) + .expect_err("must fail"); } #[test] fn more_than_just_the_bare_nix_store_path() { - StorePath::from_bytes( + StorePathRef::from_bytes( b"00bgd045z0d4icpbc2yyz4gx48aku4la-net-tools-1.60_p20170221182432/bin/arp", ) .expect_err("must fail"); @@ -490,7 +440,7 @@ mod tests { #[test] fn no_dash_between_hash_and_name() { - StorePath::from_bytes(b"00bgd045z0d4icpbc2yyz4gx48ak44lanet-tools-1.60_p20170221182432") + StorePathRef::from_bytes(b"00bgd045z0d4icpbc2yyz4gx48ak44lanet-tools-1.60_p20170221182432") .expect_err("must fail"); } @@ -539,7 +489,7 @@ mod tests { #[test] fn serialize_owned() { - let nixpath_actual = StorePath::from_bytes( + let nixpath_actual = StorePathRef::from_bytes( b"00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432", ) .expect("can parse"); @@ -583,7 +533,8 @@ mod tests { let store_path_str_json = "\"/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432\""; - let store_path: StorePath = serde_json::from_str(store_path_str_json).expect("valid json"); + let store_path: StorePath<String> = + serde_json::from_str(store_path_str_json).expect("valid json"); assert_eq!( "/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432", @@ -606,7 +557,7 @@ mod tests { StorePath::from_bytes(b"00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432").unwrap(), PathBuf::from("bin/arp/"))] fn from_absolute_path_full( #[case] s: &str, - #[case] exp_store_path: StorePath, + #[case] exp_store_path: StorePath<&str>, #[case] exp_path: PathBuf, ) { let (actual_store_path, actual_path) = @@ -620,15 +571,15 @@ mod tests { fn from_absolute_path_errors() { assert_eq!( Error::InvalidLength, - StorePath::from_absolute_path_full("/nix/store/").expect_err("must fail") + StorePathRef::from_absolute_path_full("/nix/store/").expect_err("must fail") ); assert_eq!( Error::InvalidLength, - StorePath::from_absolute_path_full("/nix/store/foo").expect_err("must fail") + StorePathRef::from_absolute_path_full("/nix/store/foo").expect_err("must fail") ); assert_eq!( Error::MissingStoreDir, - StorePath::from_absolute_path_full( + StorePathRef::from_absolute_path_full( "00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432" ) .expect_err("must fail") diff --git a/tvix/nix-compat/src/store_path/utils.rs b/tvix/nix-compat/src/store_path/utils.rs index d6f390db85c2..a0dc21160e7a 100644 --- a/tvix/nix-compat/src/store_path/utils.rs +++ b/tvix/nix-compat/src/store_path/utils.rs @@ -1,6 +1,6 @@ use crate::nixbase32; use crate::nixhash::{CAHash, NixHash}; -use crate::store_path::{Error, StorePathRef, STORE_DIR}; +use crate::store_path::{Error, StorePath, STORE_DIR}; use data_encoding::HEXLOWER; use sha2::{Digest, Sha256}; use thiserror; @@ -43,11 +43,17 @@ pub fn compress_hash<const OUTPUT_SIZE: usize>(input: &[u8]) -> [u8; OUTPUT_SIZE /// derivation or a literal text file that may contain references. /// If you don't want to have to pass the entire contents, you might want to use /// [build_ca_path] instead. -pub fn build_text_path<S: AsRef<str>, I: IntoIterator<Item = S>, C: AsRef<[u8]>>( - name: &str, +pub fn build_text_path<'a, S, SP, I, C>( + name: &'a str, content: C, references: I, -) -> Result<StorePathRef<'_>, BuildStorePathError> { +) -> Result<StorePath<SP>, BuildStorePathError> +where + S: AsRef<str>, + SP: std::cmp::Eq + std::ops::Deref<Target = str> + std::convert::From<&'a str>, + I: IntoIterator<Item = S>, + C: AsRef<[u8]>, +{ // produce the sha256 digest of the contents let content_digest = Sha256::new_with_prefix(content).finalize().into(); @@ -55,12 +61,17 @@ pub fn build_text_path<S: AsRef<str>, I: IntoIterator<Item = S>, C: AsRef<[u8]>> } /// This builds a store path from a [CAHash] and a list of references. -pub fn build_ca_path<'a, S: AsRef<str>, I: IntoIterator<Item = S>>( +pub fn build_ca_path<'a, S, SP, I>( name: &'a str, ca_hash: &CAHash, references: I, self_reference: bool, -) -> Result<StorePathRef<'a>, BuildStorePathError> { +) -> Result<StorePath<SP>, BuildStorePathError> +where + S: AsRef<str>, + SP: std::cmp::Eq + std::ops::Deref<Target = str> + std::convert::From<&'a str>, + I: IntoIterator<Item = S>, +{ // self references are only allowed for CAHash::Nar(NixHash::Sha256(_)). if self_reference && matches!(ca_hash, CAHash::Nar(NixHash::Sha256(_))) { return Err(BuildStorePathError::InvalidReference()); @@ -108,26 +119,18 @@ pub fn build_ca_path<'a, S: AsRef<str>, I: IntoIterator<Item = S>>( .map_err(BuildStorePathError::InvalidStorePath) } -/// For given NAR sha256 digest and name, return the new [StorePathRef] this -/// would have, or an error, in case the name is invalid. -pub fn build_nar_based_store_path<'a>( - nar_sha256_digest: &[u8; 32], - name: &'a str, -) -> Result<StorePathRef<'a>, BuildStorePathError> { - let nar_hash_with_mode = CAHash::Nar(NixHash::Sha256(nar_sha256_digest.to_owned())); - - build_ca_path(name, &nar_hash_with_mode, Vec::<String>::new(), false) -} - /// This builds an input-addressed store path. /// /// Input-addresed store paths are always derivation outputs, the "input" in question is the /// derivation and its closure. -pub fn build_output_path<'a>( +pub fn build_output_path<'a, SP>( drv_sha256: &[u8; 32], output_name: &str, output_path_name: &'a str, -) -> Result<StorePathRef<'a>, Error> { +) -> Result<StorePath<SP>, Error> +where + SP: std::cmp::Eq + std::ops::Deref<Target = str> + std::convert::From<&'a str>, +{ build_store_path_from_fingerprint_parts( &(String::from("output:") + output_name), drv_sha256, @@ -145,17 +148,20 @@ pub fn build_output_path<'a>( /// bytes. /// Inside a StorePath, that digest is printed nixbase32-encoded /// (32 characters). -fn build_store_path_from_fingerprint_parts<'a>( +fn build_store_path_from_fingerprint_parts<'a, SP>( ty: &str, inner_digest: &[u8; 32], name: &'a str, -) -> Result<StorePathRef<'a>, Error> { +) -> Result<StorePath<SP>, Error> +where + SP: std::cmp::Eq + std::ops::Deref<Target = str> + std::convert::From<&'a str>, +{ let fingerprint = format!( "{ty}:sha256:{}:{STORE_DIR}:{name}", HEXLOWER.encode(inner_digest) ); // name validation happens in here. - StorePathRef::from_name_and_digest_fixed( + StorePath::from_name_and_digest_fixed( name, compress_hash(&Sha256::new_with_prefix(fingerprint).finalize()), ) @@ -207,7 +213,10 @@ mod test { use hex_literal::hex; use super::*; - use crate::nixhash::{CAHash, NixHash}; + use crate::{ + nixhash::{CAHash, NixHash}, + store_path::StorePathRef, + }; #[test] fn build_text_path_with_zero_references() { @@ -216,7 +225,7 @@ mod test { // nix-repl> builtins.toFile "foo" "bar" // "/nix/store/vxjiwkjkn7x4079qvh1jkl5pn05j2aw0-foo" - let store_path = build_text_path("foo", "bar", Vec::<String>::new()) + let store_path: StorePathRef = build_text_path("foo", "bar", Vec::<String>::new()) .expect("build_store_path() should succeed"); assert_eq!( @@ -232,11 +241,11 @@ mod test { // nix-repl> builtins.toFile "baz" "${builtins.toFile "foo" "bar"}" // "/nix/store/5xd714cbfnkz02h2vbsj4fm03x3f15nf-baz" - let inner = build_text_path("foo", "bar", Vec::<String>::new()) + let inner: StorePathRef = build_text_path("foo", "bar", Vec::<String>::new()) .expect("path_with_references() should succeed"); let inner_path = inner.to_absolute_path(); - let outer = build_text_path("baz", &inner_path, vec![inner_path.as_str()]) + let outer: StorePathRef = build_text_path("baz", &inner_path, vec![inner_path.as_str()]) .expect("path_with_references() should succeed"); assert_eq!( @@ -247,7 +256,7 @@ mod test { #[test] fn build_sha1_path() { - let outer = build_ca_path( + let outer: StorePathRef = build_ca_path( "bar", &CAHash::Nar(NixHash::Sha1(hex!( "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" @@ -272,7 +281,7 @@ mod test { // // $ nix store make-content-addressed /nix/store/5xd714cbfnkz02h2vbsj4fm03x3f15nf-baz // rewrote '/nix/store/5xd714cbfnkz02h2vbsj4fm03x3f15nf-baz' to '/nix/store/s89y431zzhmdn3k8r96rvakryddkpv2v-baz' - let outer = build_ca_path( + let outer: StorePathRef = build_ca_path( "baz", &CAHash::Nar(NixHash::Sha256( nixbase32::decode(b"1xqkzcb3909fp07qngljr4wcdnrh1gdam1m2n29i6hhrxlmkgkv1") diff --git a/tvix/nix-compat/src/wire/bytes/mod.rs b/tvix/nix-compat/src/wire/bytes/mod.rs index 0c637e6c3921..74adfb49b6a4 100644 --- a/tvix/nix-compat/src/wire/bytes/mod.rs +++ b/tvix/nix-compat/src/wire/bytes/mod.rs @@ -1,23 +1,24 @@ +#[cfg(feature = "async")] +use std::mem::MaybeUninit; use std::{ io::{Error, ErrorKind}, - ops::RangeBounds, + ops::RangeInclusive, }; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; +#[cfg(feature = "async")] +use tokio::io::ReadBuf; +use tokio::io::{self, AsyncReadExt, AsyncWriteExt}; -mod reader; +pub(crate) mod reader; pub use reader::BytesReader; mod writer; pub use writer::BytesWriter; -use super::primitive; - /// 8 null bytes, used to write out padding. -const EMPTY_BYTES: &[u8; 8] = &[0u8; 8]; +pub(crate) const EMPTY_BYTES: &[u8; 8] = &[0u8; 8]; /// The length of the size field, in bytes is always 8. const LEN_SIZE: usize = 8; -#[allow(dead_code)] /// Read a "bytes wire packet" from the AsyncRead. /// Rejects reading more than `allowed_size` bytes of payload. /// @@ -35,24 +36,26 @@ const LEN_SIZE: usize = 8; /// /// This buffers the entire payload into memory, /// a streaming version is available at [crate::wire::bytes::BytesReader]. -pub async fn read_bytes<R, S>(r: &mut R, allowed_size: S) -> std::io::Result<Vec<u8>> +pub async fn read_bytes<R>(r: &mut R, allowed_size: RangeInclusive<usize>) -> io::Result<Vec<u8>> where - R: AsyncReadExt + Unpin, - S: RangeBounds<u64>, + R: AsyncReadExt + Unpin + ?Sized, { // read the length field - let len = primitive::read_u64(r).await?; - - if !allowed_size.contains(&len) { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "signalled package size not in allowed range", - )); - } + let len = r.read_u64_le().await?; + let len: usize = len + .try_into() + .ok() + .filter(|len| allowed_size.contains(len)) + .ok_or_else(|| { + io::Error::new( + io::ErrorKind::InvalidData, + "signalled package size not in allowed range", + ) + })?; // calculate the total length, including padding. // byte packets are padded to 8 byte blocks each. - let padded_len = padding_len(len) as u64 + (len as u64); + let padded_len = padding_len(len as u64) as u64 + (len as u64); let mut limited_reader = r.take(padded_len); let mut buf = Vec::new(); @@ -61,34 +64,89 @@ where // make sure we got exactly the number of bytes, and not less. if s as u64 != padded_len { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "got less bytes than expected", - )); + return Err(io::ErrorKind::UnexpectedEof.into()); } - let (_content, padding) = buf.split_at(len as usize); + let (_content, padding) = buf.split_at(len); // ensure the padding is all zeroes. - if !padding.iter().all(|e| *e == b'\0') { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, + if padding.iter().any(|&b| b != 0) { + return Err(io::Error::new( + io::ErrorKind::InvalidData, "padding is not all zeroes", )); } // return the data without the padding - buf.truncate(len as usize); + buf.truncate(len); Ok(buf) } +#[cfg(feature = "async")] +pub(crate) async fn read_bytes_buf<'a, const N: usize, R>( + reader: &mut R, + buf: &'a mut [MaybeUninit<u8>; N], + allowed_size: RangeInclusive<usize>, +) -> io::Result<&'a [u8]> +where + R: AsyncReadExt + Unpin + ?Sized, +{ + assert_eq!(N % 8, 0); + assert!(*allowed_size.end() <= N); + + let len = reader.read_u64_le().await?; + let len: usize = len + .try_into() + .ok() + .filter(|len| allowed_size.contains(len)) + .ok_or_else(|| { + io::Error::new( + io::ErrorKind::InvalidData, + "signalled package size not in allowed range", + ) + })?; + + let buf_len = (len + 7) & !7; + let buf = { + let mut read_buf = ReadBuf::uninit(&mut buf[..buf_len]); + + while read_buf.filled().len() < buf_len { + reader.read_buf(&mut read_buf).await?; + } + + // ReadBuf::filled does not pass the underlying buffer's lifetime through, + // so we must make a trip to hell. + // + // SAFETY: `read_buf` is filled up to `buf_len`, and we verify that it is + // still pointing at the same underlying buffer. + unsafe { + assert_eq!(read_buf.filled().as_ptr(), buf.as_ptr() as *const u8); + assume_init_bytes(&buf[..buf_len]) + } + }; + + if buf[len..buf_len].iter().any(|&b| b != 0) { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "padding is not all zeroes", + )); + } + + Ok(&buf[..len]) +} + +/// SAFETY: The bytes have to actually be initialized. +#[cfg(feature = "async")] +unsafe fn assume_init_bytes(slice: &[MaybeUninit<u8>]) -> &[u8] { + &*(slice as *const [MaybeUninit<u8>] as *const [u8]) +} + /// Read a "bytes wire packet" of from the AsyncRead and tries to parse as string. /// Internally uses [read_bytes]. /// Rejects reading more than `allowed_size` bytes of payload. -pub async fn read_string<R, S>(r: &mut R, allowed_size: S) -> std::io::Result<String> +pub async fn read_string<R>(r: &mut R, allowed_size: RangeInclusive<usize>) -> io::Result<String> where R: AsyncReadExt + Unpin, - S: RangeBounds<u64>, { let bytes = read_bytes(r, allowed_size).await?; String::from_utf8(bytes).map_err(|e| Error::new(ErrorKind::InvalidData, e)) @@ -106,9 +164,9 @@ where pub async fn write_bytes<W: AsyncWriteExt + Unpin, B: AsRef<[u8]>>( w: &mut W, b: B, -) -> std::io::Result<()> { +) -> io::Result<()> { // write the size packet. - primitive::write_u64(w, b.as_ref().len() as u64).await?; + w.write_u64_le(b.as_ref().len() as u64).await?; // write the payload w.write_all(b.as_ref()).await?; @@ -122,14 +180,10 @@ pub async fn write_bytes<W: AsyncWriteExt + Unpin, B: AsRef<[u8]>>( } /// Computes the number of bytes we should add to len (a length in -/// bytes) to be alined on 64 bits (8 bytes). +/// bytes) to be aligned on 64 bits (8 bytes). fn padding_len(len: u64) -> u8 { - let modulo = len % 8; - if modulo == 0 { - 0 - } else { - 8 - modulo as u8 - } + let aligned = len.wrapping_add(7) & !7; + aligned.wrapping_sub(len) as u8 } #[cfg(test)] @@ -141,7 +195,7 @@ mod tests { /// The maximum length of bytes packets we're willing to accept in the test /// cases. - const MAX_LEN: u64 = 1024; + const MAX_LEN: usize = 1024; #[tokio::test] async fn test_read_8_bytes() { @@ -152,10 +206,7 @@ mod tests { assert_eq!( &12345678u64.to_le_bytes(), - read_bytes(&mut mock, 0u64..MAX_LEN) - .await - .unwrap() - .as_slice() + read_bytes(&mut mock, 0..=MAX_LEN).await.unwrap().as_slice() ); } @@ -168,10 +219,7 @@ mod tests { assert_eq!( hex!("010203040506070809"), - read_bytes(&mut mock, 0u64..MAX_LEN) - .await - .unwrap() - .as_slice() + read_bytes(&mut mock, 0..=MAX_LEN).await.unwrap().as_slice() ); } @@ -183,10 +231,7 @@ mod tests { assert_eq!( hex!(""), - read_bytes(&mut mock, 0u64..MAX_LEN) - .await - .unwrap() - .as_slice() + read_bytes(&mut mock, 0..=MAX_LEN).await.unwrap().as_slice() ); } @@ -196,7 +241,7 @@ mod tests { async fn test_read_reject_too_large() { let mut mock = Builder::new().read(&100u64.to_le_bytes()).build(); - read_bytes(&mut mock, 10..10) + read_bytes(&mut mock, 10..=10) .await .expect_err("expect this to fail"); } @@ -232,4 +277,9 @@ mod tests { .build(); assert_ok!(write_bytes(&mut mock, &input).await) } + + #[test] + fn padding_len_u64_max() { + assert_eq!(padding_len(u64::MAX), 1); + } } diff --git a/tvix/nix-compat/src/wire/bytes/reader/mod.rs b/tvix/nix-compat/src/wire/bytes/reader/mod.rs index 78615faf0f4c..a6209a6e6dad 100644 --- a/tvix/nix-compat/src/wire/bytes/reader/mod.rs +++ b/tvix/nix-compat/src/wire/bytes/reader/mod.rs @@ -1,12 +1,18 @@ use std::{ + future::Future, io, - ops::{Bound, RangeBounds}, + num::NonZeroU64, + ops::RangeBounds, pin::Pin, task::{self, ready, Poll}, }; -use tokio::io::{AsyncRead, ReadBuf}; +use tokio::io::{AsyncBufRead, AsyncRead, AsyncReadExt, ReadBuf}; -use trailer::TrailerReader; +use trailer::{read_trailer, ReadTrailer, Trailer}; + +#[doc(hidden)] +pub use self::trailer::Pad; +pub(crate) use self::trailer::Tag; mod trailer; /// Reads a "bytes wire packet" from the underlying reader. @@ -14,40 +20,46 @@ mod trailer; /// however this structure provides a [AsyncRead] interface, /// allowing to not having to pass around the entire payload in memory. /// -/// After being constructed with the underlying reader and an allowed size, -/// subsequent requests to poll_read will return payload data until the end -/// of the packet is reached. -/// -/// Internally, it will first read over the size packet, filling payload_size, -/// ensuring it fits allowed_size, then return payload data. +/// It is constructed by reading a size with [BytesReader::new], +/// and yields payload data until the end of the packet is reached. /// /// It will not return the final bytes before all padding has been successfully /// consumed as well, but the full length of the reader must be consumed. /// -/// In case of an error due to size constraints, or in case of not reading -/// all the way to the end (and getting a EOF), the underlying reader is no -/// longer usable and might return garbage. -pub struct BytesReader<R> { - state: State<R>, +/// If the data is not read all the way to the end, or an error is encountered, +/// the underlying reader is no longer usable and might return garbage. +#[derive(Debug)] +#[allow(private_bounds)] +pub struct BytesReader<R, T: Tag = Pad> { + state: State<R, T>, +} + +/// Split the `user_len` into `body_len` and `tail_len`, which are respectively +/// the non-terminal 8-byte blocks, and the ≤8 bytes of user data contained in +/// the trailer block. +#[inline(always)] +fn split_user_len(user_len: NonZeroU64) -> (u64, u8) { + let n = user_len.get() - 1; + let body_len = n & !7; + let tail_len = (n & 7) as u8 + 1; + (body_len, tail_len) } #[derive(Debug)] -enum State<R> { - Size { - reader: Option<R>, - /// Minimum length (inclusive) - user_len_min: u64, - /// Maximum length (inclusive) - user_len_max: u64, - filled: u8, - buf: [u8; 8], - }, +enum State<R, T: Tag> { + /// Full 8-byte blocks are being read and released to the caller. + /// NOTE: The final 8-byte block is *always* part of the trailer. Body { reader: Option<R>, consumed: u64, - user_len: u64, + /// The total length of all user data contained in both the body and trailer. + user_len: NonZeroU64, }, - Trailer(TrailerReader<R>), + /// The trailer is in the process of being read. + ReadTrailer(ReadTrailer<R, T>), + /// The trailer has been fully read and validated, + /// and data can now be released to the caller. + ReleaseTrailer { consumed: u8, data: Trailer }, } impl<R> BytesReader<R> @@ -55,43 +67,61 @@ where R: AsyncRead + Unpin, { /// Constructs a new BytesReader, using the underlying passed reader. - pub fn new<S: RangeBounds<u64>>(reader: R, allowed_size: S) -> Self { - let user_len_min = match allowed_size.start_bound() { - Bound::Included(&n) => n, - Bound::Excluded(&n) => n.saturating_add(1), - Bound::Unbounded => 0, - }; - - let user_len_max = match allowed_size.end_bound() { - Bound::Included(&n) => n, - Bound::Excluded(&n) => n.checked_sub(1).unwrap(), - Bound::Unbounded => u64::MAX, - }; - - Self { - state: State::Size { - reader: Some(reader), - user_len_min, - user_len_max, - filled: 0, - buf: [0; 8], - }, - } + pub async fn new<S: RangeBounds<u64>>(reader: R, allowed_size: S) -> io::Result<Self> { + BytesReader::new_internal(reader, allowed_size).await } +} - /// Construct a new BytesReader with a known, and already-read size. - pub fn with_size(reader: R, size: u64) -> Self { - Self { - state: State::Body { - reader: Some(reader), - consumed: 0, - user_len: size, +#[allow(private_bounds)] +impl<R, T: Tag> BytesReader<R, T> +where + R: AsyncRead + Unpin, +{ + /// Constructs a new BytesReader, using the underlying passed reader. + pub(crate) async fn new_internal<S: RangeBounds<u64>>( + mut reader: R, + allowed_size: S, + ) -> io::Result<Self> { + let size = reader.read_u64_le().await?; + + if !allowed_size.contains(&size) { + return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid size")); + } + + Ok(Self { + state: match NonZeroU64::new(size) { + Some(size) => State::Body { + reader: Some(reader), + consumed: 0, + user_len: size, + }, + None => State::ReleaseTrailer { + consumed: 0, + data: read_trailer::<R, T>(reader, 0).await?, + }, }, + }) + } + + /// Returns whether there is any remaining data to be read. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Remaining data length, ie not including data already read. + pub fn len(&self) -> u64 { + match self.state { + State::Body { + consumed, user_len, .. + } => user_len.get() - consumed, + State::ReadTrailer(ref fut) => fut.len() as u64, + State::ReleaseTrailer { consumed, ref data } => data.len() as u64 - consumed as u64, } } } -impl<R: AsyncRead + Unpin> AsyncRead for BytesReader<R> { +#[allow(private_bounds)] +impl<R: AsyncRead + Unpin, T: Tag> AsyncRead for BytesReader<R, T> { fn poll_read( mut self: Pin<&mut Self>, cx: &mut task::Context, @@ -101,67 +131,26 @@ impl<R: AsyncRead + Unpin> AsyncRead for BytesReader<R> { loop { match this { - State::Size { - reader, - user_len_min, - user_len_max, - filled: 8, - buf, - } => { - let reader = reader.take().unwrap(); - - let data_len = u64::from_le_bytes(*buf); - if data_len < *user_len_min || data_len > *user_len_max { - return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid size")) - .into(); - } - - *this = State::Body { - reader: Some(reader), - consumed: 0, - user_len: data_len, - }; - } - State::Size { - reader, - filled, - buf, - .. - } => { - let reader = reader.as_mut().unwrap(); - - let mut read_buf = ReadBuf::new(&mut buf[..]); - read_buf.advance(*filled as usize); - ready!(Pin::new(reader).poll_read(cx, &mut read_buf))?; - - let new_filled = read_buf.filled().len() as u8; - if *filled == new_filled { - return Err(io::ErrorKind::UnexpectedEof.into()).into(); - } - - *filled = new_filled; - } State::Body { reader, consumed, user_len, } => { - let body_len = *user_len & !7; + let (body_len, tail_len) = split_user_len(*user_len); let remaining = body_len - *consumed; let reader = if remaining == 0 { let reader = reader.take().unwrap(); - let user_len = (*user_len & 7) as u8; - *this = State::Trailer(TrailerReader::new(reader, user_len)); + *this = State::ReadTrailer(read_trailer(reader, tail_len)); continue; } else { - reader.as_mut().unwrap() + Pin::new(reader.as_mut().unwrap()) }; let mut bytes_read = 0; ready!(with_limited(buf, remaining, |buf| { - let ret = Pin::new(reader).poll_read(cx, buf); - bytes_read = buf.initialized().len(); + let ret = reader.poll_read(cx, buf); + bytes_read = buf.filled().len(); ret }))?; @@ -174,9 +163,111 @@ impl<R: AsyncRead + Unpin> AsyncRead for BytesReader<R> { } .into(); } - State::Trailer(reader) => { - return Pin::new(reader).poll_read(cx, buf); + State::ReadTrailer(fut) => { + *this = State::ReleaseTrailer { + consumed: 0, + data: ready!(Pin::new(fut).poll(cx))?, + }; + } + State::ReleaseTrailer { consumed, data } => { + let data = &data[*consumed as usize..]; + let data = &data[..usize::min(data.len(), buf.remaining())]; + + buf.put_slice(data); + *consumed += data.len() as u8; + + return Ok(()).into(); + } + } + } + } +} + +#[allow(private_bounds)] +impl<R: AsyncBufRead + Unpin, T: Tag> AsyncBufRead for BytesReader<R, T> { + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<io::Result<&[u8]>> { + let this = &mut self.get_mut().state; + + loop { + match this { + // This state comes *after* the following case, + // but we can't keep it in logical order because + // that would lengthen the borrow lifetime. + State::Body { + reader, + consumed, + user_len, + } if { + let (body_len, _) = split_user_len(*user_len); + let remaining = body_len - *consumed; + + remaining == 0 + } => + { + let reader = reader.take().unwrap(); + let (_, tail_len) = split_user_len(*user_len); + + *this = State::ReadTrailer(read_trailer(reader, tail_len)); } + State::Body { + reader, + consumed, + user_len, + } => { + let (body_len, _) = split_user_len(*user_len); + let remaining = body_len - *consumed; + + let reader = Pin::new(reader.as_mut().unwrap()); + + match ready!(reader.poll_fill_buf(cx))? { + &[] => { + return Err(io::ErrorKind::UnexpectedEof.into()).into(); + } + mut buf => { + if buf.len() as u64 > remaining { + buf = &buf[..remaining as usize]; + } + + return Ok(buf).into(); + } + } + } + State::ReadTrailer(fut) => { + *this = State::ReleaseTrailer { + consumed: 0, + data: ready!(Pin::new(fut).poll(cx))?, + }; + } + State::ReleaseTrailer { consumed, data } => { + return Ok(&data[*consumed as usize..]).into(); + } + } + } + } + + fn consume(mut self: Pin<&mut Self>, amt: usize) { + match &mut self.state { + State::Body { + reader, + consumed, + user_len, + } => { + let reader = Pin::new(reader.as_mut().unwrap()); + let (body_len, _) = split_user_len(*user_len); + + *consumed = consumed + .checked_add(amt as u64) + .filter(|&consumed| consumed <= body_len) + .expect("consumed out of bounds"); + + reader.consume(amt); + } + State::ReadTrailer(_) => unreachable!(), + State::ReleaseTrailer { consumed, data } => { + *consumed = amt + .checked_add(*consumed as usize) + .filter(|&consumed| consumed <= data.len()) + .expect("consumed out of bounds") as u8; } } } @@ -208,14 +299,14 @@ fn with_limited<R>(buf: &mut ReadBuf, n: u64, f: impl FnOnce(&mut ReadBuf) -> R) #[cfg(test)] mod tests { + use std::sync::LazyLock; use std::time::Duration; use crate::wire::bytes::{padding_len, write_bytes}; use hex_literal::hex; - use lazy_static::lazy_static; use rstest::rstest; - use tokio::io::AsyncReadExt; - use tokio_test::{assert_err, io::Builder}; + use tokio::io::{AsyncReadExt, BufReader}; + use tokio_test::io::Builder; use super::*; @@ -223,9 +314,8 @@ mod tests { /// cases. const MAX_LEN: u64 = 1024; - lazy_static! { - pub static ref LARGE_PAYLOAD: Vec<u8> = (0..255).collect::<Vec<u8>>().repeat(4 * 1024); - } + pub static LARGE_PAYLOAD: LazyLock<Vec<u8>> = + LazyLock::new(|| (0..255).collect::<Vec<u8>>().repeat(4 * 1024)); /// Helper function, calling the (simpler) write_bytes with the payload. /// We use this to create data we want to read from the wire. @@ -249,14 +339,16 @@ mod tests { .read(&produce_packet_bytes(payload).await) .build(); - let mut r = BytesReader::new(&mut mock, ..=LARGE_PAYLOAD.len() as u64); + let mut r = BytesReader::new(&mut mock, ..=LARGE_PAYLOAD.len() as u64) + .await + .unwrap(); let mut buf = Vec::new(); r.read_to_end(&mut buf).await.expect("must succeed"); assert_eq!(payload, &buf[..]); } - /// Read bytes packets of various length, and ensure read_to_end returns the + /// Read bytes packets of various length, and ensure copy_buf reads the /// expected payload. #[rstest] #[case::empty(&[])] // empty bytes packet @@ -265,20 +357,21 @@ mod tests { #[case::size_9b(&hex!("000102030405060708"))] // 9 bytes payload (7 bytes padding) #[case::size_1m(LARGE_PAYLOAD.as_slice())] // larger bytes packet #[tokio::test] - async fn read_payload_correct_known(#[case] payload: &[u8]) { - let packet = produce_packet_bytes(payload).await; - - let size = u64::from_le_bytes({ - let mut buf = [0; 8]; - buf.copy_from_slice(&packet[..8]); - buf - }); + async fn read_payload_correct_readbuf(#[case] payload: &[u8]) { + let mut mock = BufReader::new( + Builder::new() + .read(&produce_packet_bytes(payload).await) + .build(), + ); - let mut mock = Builder::new().read(&packet[8..]).build(); + let mut r = BytesReader::new(&mut mock, ..=LARGE_PAYLOAD.len() as u64) + .await + .unwrap(); - let mut r = BytesReader::with_size(&mut mock, size); let mut buf = Vec::new(); - r.read_to_end(&mut buf).await.expect("must succeed"); + tokio::io::copy_buf(&mut r, &mut buf) + .await + .expect("copy_buf must succeed"); assert_eq!(payload, &buf[..]); } @@ -291,9 +384,13 @@ mod tests { .read(&produce_packet_bytes(payload).await[0..8]) // We stop reading after the size packet .build(); - let mut r = BytesReader::new(&mut mock, ..2048); - let mut buf = Vec::new(); - assert_err!(r.read_to_end(&mut buf).await); + assert_eq!( + BytesReader::new(&mut mock, ..2048) + .await + .unwrap_err() + .kind(), + io::ErrorKind::InvalidData + ); } /// Fail if the bytes packet is smaller than allowed @@ -304,9 +401,54 @@ mod tests { .read(&produce_packet_bytes(payload).await[0..8]) // We stop reading after the size packet .build(); - let mut r = BytesReader::new(&mut mock, 1024..2048); - let mut buf = Vec::new(); - assert_err!(r.read_to_end(&mut buf).await); + assert_eq!( + BytesReader::new(&mut mock, 1024..2048) + .await + .unwrap_err() + .kind(), + io::ErrorKind::InvalidData + ); + } + + /// Read the trailer immediately if there is no payload. + #[cfg(feature = "async")] + #[tokio::test] + async fn read_trailer_immediately() { + use crate::nar::wire::PadPar; + + let mut mock = Builder::new() + .read(&[0; 8]) + .read(&PadPar::PATTERN[8..]) + .build(); + + BytesReader::<_, PadPar>::new_internal(&mut mock, ..) + .await + .unwrap(); + + // The mock reader will panic if dropped without reading all data. + } + + /// Read the trailer even if we only read the exact payload size. + #[cfg(feature = "async")] + #[tokio::test] + async fn read_exact_trailer() { + use crate::nar::wire::PadPar; + + let mut mock = Builder::new() + .read(&16u64.to_le_bytes()) + .read(&[0x55; 16]) + .read(&PadPar::PATTERN[8..]) + .build(); + + let mut reader = BytesReader::<_, PadPar>::new_internal(&mut mock, ..) + .await + .unwrap(); + + let mut buf = [0; 16]; + reader.read_exact(&mut buf).await.unwrap(); + assert_eq!(buf, [0x55; 16]); + + // The mock reader will panic if dropped without reading all data. } /// Fail if the padding is not all zeroes @@ -318,7 +460,7 @@ mod tests { packet_bytes[12] = 0xff; let mut mock = Builder::new().read(&packet_bytes).build(); // We stop reading after the faulty bit - let mut r = BytesReader::new(&mut mock, ..MAX_LEN); + let mut r = BytesReader::new(&mut mock, ..MAX_LEN).await.unwrap(); let mut buf = Vec::new(); r.read_to_end(&mut buf).await.expect_err("must fail"); @@ -335,15 +477,13 @@ mod tests { .read(&produce_packet_bytes(payload).await[..4]) .build(); - let mut r = BytesReader::new(&mut mock, ..MAX_LEN); - let mut buf = [0u8; 1]; - assert_eq!( - r.read_exact(&mut buf).await.expect_err("must fail").kind(), - std::io::ErrorKind::UnexpectedEof + BytesReader::new(&mut mock, ..MAX_LEN) + .await + .expect_err("must fail") + .kind(), + io::ErrorKind::UnexpectedEof ); - - assert_eq!(&[0], &buf, "buffer should stay empty"); } /// Start a 9 bytes payload packet, but have the underlying reader return @@ -357,7 +497,7 @@ mod tests { .read(&produce_packet_bytes(payload).await[..8 + 4]) .build(); - let mut r = BytesReader::new(&mut mock, ..MAX_LEN); + let mut r = BytesReader::new(&mut mock, ..MAX_LEN).await.unwrap(); let mut buf = [0; 9]; r.read_exact(&mut buf[..4]).await.expect("must succeed"); @@ -384,7 +524,7 @@ mod tests { .read(&produce_packet_bytes(payload).await[..offset]) .build(); - let mut r = BytesReader::new(&mut mock, ..MAX_LEN); + let mut r = BytesReader::new(&mut mock, ..MAX_LEN).await.unwrap(); // read_exact of the payload *body* will succeed, but a subsequent read will // return UnexpectedEof error. @@ -411,10 +551,60 @@ mod tests { .read_error(std::io::Error::new(std::io::ErrorKind::Other, "foo")) .build(); - let mut r = BytesReader::new(&mut mock, ..MAX_LEN); - let mut buf = Vec::new(); + // Either length reading or data reading can fail, depending on which test case we're in. + let err: io::Error = async { + let mut r = BytesReader::new(&mut mock, ..MAX_LEN).await?; + let mut buf = Vec::new(); + + r.read_to_end(&mut buf).await?; + + Ok(()) + } + .await + .expect_err("must fail"); + + assert_eq!( + err.kind(), + std::io::ErrorKind::Other, + "error kind must match" + ); + + assert_eq!( + err.into_inner().unwrap().to_string(), + "foo", + "error payload must contain foo" + ); + } + + /// Start a 9 bytes payload packet, but return an error after a certain position. + /// Ensure that error is propagated (AsyncReadBuf case) + #[rstest] + #[case::during_size(4)] + #[case::before_payload(8)] + #[case::during_payload(8 + 4)] + #[case::before_padding(8 + 4)] + #[case::during_padding(8 + 9 + 2)] + #[tokio::test] + async fn propagate_error_from_reader_buffered(#[case] offset: usize) { + let payload = &hex!("FF0102030405060708"); + let mock = Builder::new() + .read(&produce_packet_bytes(payload).await[..offset]) + .read_error(std::io::Error::new(std::io::ErrorKind::Other, "foo")) + .build(); + let mut mock = BufReader::new(mock); + + // Either length reading or data reading can fail, depending on which test case we're in. + let err: io::Error = async { + let mut r = BytesReader::new(&mut mock, ..MAX_LEN).await?; + let mut buf = Vec::new(); + + tokio::io::copy_buf(&mut r, &mut buf).await?; + + Ok(()) + } + .await + .expect_err("must fail"); - let err = r.read_to_end(&mut buf).await.expect_err("must fail"); assert_eq!( err.kind(), std::io::ErrorKind::Other, @@ -438,13 +628,33 @@ mod tests { .read_error(std::io::Error::new(std::io::ErrorKind::Other, "foo")) .build(); - let mut r = BytesReader::new(&mut mock, ..MAX_LEN); + let mut r = BytesReader::new(&mut mock, ..MAX_LEN).await.unwrap(); let mut buf = Vec::new(); r.read_to_end(&mut buf).await.expect("must succeed"); assert_eq!(buf.as_slice(), payload); } + /// If there's an error right after the padding, we don't propagate it, as + /// we're done reading. We just return EOF. + #[tokio::test] + async fn no_error_after_eof_buffered() { + let payload = &hex!("FF0102030405060708"); + let mock = Builder::new() + .read(&produce_packet_bytes(payload).await) + .read_error(std::io::Error::new(std::io::ErrorKind::Other, "foo")) + .build(); + let mut mock = BufReader::new(mock); + + let mut r = BytesReader::new(&mut mock, ..MAX_LEN).await.unwrap(); + let mut buf = Vec::new(); + + tokio::io::copy_buf(&mut r, &mut buf) + .await + .expect("must succeed"); + assert_eq!(buf.as_slice(), payload); + } + /// Introduce various stalls in various places of the packet, to ensure we /// handle these cases properly, too. #[rstest] @@ -462,7 +672,9 @@ mod tests { .read(&produce_packet_bytes(payload).await[offset..]) .build(); - let mut r = BytesReader::new(&mut mock, ..=LARGE_PAYLOAD.len() as u64); + let mut r = BytesReader::new(&mut mock, ..=LARGE_PAYLOAD.len() as u64) + .await + .unwrap(); let mut buf = Vec::new(); r.read_to_end(&mut buf).await.expect("must succeed"); diff --git a/tvix/nix-compat/src/wire/bytes/reader/trailer.rs b/tvix/nix-compat/src/wire/bytes/reader/trailer.rs index 958cead42d8f..3a5bb75e7103 100644 --- a/tvix/nix-compat/src/wire/bytes/reader/trailer.rs +++ b/tvix/nix-compat/src/wire/bytes/reader/trailer.rs @@ -1,4 +1,5 @@ use std::{ + fmt::Debug, future::Future, marker::PhantomData, ops::Deref, @@ -8,11 +9,11 @@ use std::{ use tokio::io::{self, AsyncRead, ReadBuf}; -/// Trailer represents up to 7 bytes of data read as part of the trailer block(s) +/// Trailer represents up to 8 bytes of data read as part of the trailer block(s) #[derive(Debug)] pub(crate) struct Trailer { data_len: u8, - buf: [u8; 7], + buf: [u8; 8], } impl Deref for Trailer { @@ -27,20 +28,20 @@ impl Deref for Trailer { pub(crate) trait Tag { /// The expected suffix /// - /// The first 7 bytes may be ignored, and it must be an 8-byte aligned size. + /// The first 8 bytes may be ignored, and it must be an 8-byte aligned size. const PATTERN: &'static [u8]; /// Suitably sized buffer for reading [Self::PATTERN] /// /// HACK: This is a workaround for const generics limitations. - type Buf: AsRef<[u8]> + AsMut<[u8]> + Unpin; + type Buf: AsRef<[u8]> + AsMut<[u8]> + Debug + Unpin; /// Make an instance of [Self::Buf] fn make_buf() -> Self::Buf; } #[derive(Debug)] -pub(crate) enum Pad {} +pub enum Pad {} impl Tag for Pad { const PATTERN: &'static [u8] = &[0; 8]; @@ -58,7 +59,7 @@ pub(crate) struct ReadTrailer<R, T: Tag> { data_len: u8, filled: u8, buf: T::Buf, - _phantom: PhantomData<*const T>, + _phantom: PhantomData<fn(T) -> T>, } /// read_trailer returns a [Future] that reads a trailer with a given [Tag] from `reader` @@ -66,7 +67,7 @@ pub(crate) fn read_trailer<R: AsyncRead + Unpin, T: Tag>( reader: R, data_len: u8, ) -> ReadTrailer<R, T> { - assert!(data_len < 8, "payload in trailer must be less than 8 bytes"); + assert!(data_len <= 8, "payload in trailer must be <= 8 bytes"); let buf = T::make_buf(); assert_eq!(buf.as_ref().len(), T::PATTERN.len()); @@ -81,10 +82,16 @@ pub(crate) fn read_trailer<R: AsyncRead + Unpin, T: Tag>( } } +impl<R, T: Tag> ReadTrailer<R, T> { + pub fn len(&self) -> u8 { + self.data_len + } +} + impl<R: AsyncRead + Unpin, T: Tag> Future for ReadTrailer<R, T> { type Output = io::Result<Trailer>; - fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> task::Poll<Self::Output> { + fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> { let this = &mut *self; loop { @@ -101,8 +108,8 @@ impl<R: AsyncRead + Unpin, T: Tag> Future for ReadTrailer<R, T> { } if this.filled as usize == T::PATTERN.len() { - let mut buf = [0; 7]; - buf.copy_from_slice(&this.buf.as_ref()[..7]); + let mut buf = [0; 8]; + buf.copy_from_slice(&this.buf.as_ref()[..8]); return Ok(Trailer { data_len: this.data_len, @@ -117,10 +124,9 @@ impl<R: AsyncRead + Unpin, T: Tag> Future for ReadTrailer<R, T> { ready!(Pin::new(&mut this.reader).poll_read(cx, &mut buf))?; this.filled = { - let prev_filled = this.filled; let filled = buf.filled().len() as u8; - if filled == prev_filled { + if filled == this.filled { return Err(io::ErrorKind::UnexpectedEof.into()).into(); } @@ -130,61 +136,9 @@ impl<R: AsyncRead + Unpin, T: Tag> Future for ReadTrailer<R, T> { } } -#[derive(Debug)] -pub(crate) enum TrailerReader<R> { - Reading(ReadTrailer<R, Pad>), - Releasing { off: u8, data: Trailer }, - Done, -} - -impl<R: AsyncRead + Unpin> TrailerReader<R> { - pub fn new(reader: R, data_len: u8) -> Self { - Self::Reading(read_trailer(reader, data_len)) - } -} - -impl<R: AsyncRead + Unpin> AsyncRead for TrailerReader<R> { - fn poll_read( - mut self: Pin<&mut Self>, - cx: &mut task::Context, - user_buf: &mut ReadBuf, - ) -> Poll<io::Result<()>> { - let this = &mut *self; - - loop { - match this { - Self::Reading(fut) => { - *this = Self::Releasing { - off: 0, - data: ready!(Pin::new(fut).poll(cx))?, - }; - } - Self::Releasing { off: 8, .. } => { - *this = Self::Done; - } - Self::Releasing { off, data } => { - assert_ne!(user_buf.remaining(), 0); - - let buf = &data[*off as usize..]; - let buf = &buf[..usize::min(buf.len(), user_buf.remaining())]; - - user_buf.put_slice(buf); - *off += buf.len() as u8; - - break; - } - Self::Done => break, - } - } - - Ok(()).into() - } -} - #[cfg(test)] mod tests { use std::time::Duration; - use tokio::io::AsyncReadExt; use super::*; @@ -196,11 +150,8 @@ mod tests { .read(&[0xef, 0x00]) .build(); - let mut reader = TrailerReader::new(reader, 2); - - let mut buf = vec![]; assert_eq!( - reader.read_to_end(&mut buf).await.unwrap_err().kind(), + read_trailer::<_, Pad>(reader, 2).await.unwrap_err().kind(), io::ErrorKind::UnexpectedEof ); } @@ -214,11 +165,8 @@ mod tests { .wait(Duration::ZERO) .build(); - let mut reader = TrailerReader::new(reader, 2); - - let mut buf = vec![]; assert_eq!( - reader.read_to_end(&mut buf).await.unwrap_err().kind(), + read_trailer::<_, Pad>(reader, 2).await.unwrap_err().kind(), io::ErrorKind::InvalidData ); } @@ -233,21 +181,17 @@ mod tests { .read(&[0x00, 0x00, 0x00, 0x00, 0x00]) .build(); - let mut reader = TrailerReader::new(reader, 2); - - let mut buf = vec![]; - reader.read_to_end(&mut buf).await.unwrap(); - - assert_eq!(buf, &[0xed, 0xef]); + assert_eq!( + &*read_trailer::<_, Pad>(reader, 2).await.unwrap(), + &[0xed, 0xef] + ); } #[tokio::test] async fn no_padding() { - let reader = tokio_test::io::Builder::new().build(); - let mut reader = TrailerReader::new(reader, 0); - - let mut buf = vec![]; - reader.read_to_end(&mut buf).await.unwrap(); - assert!(buf.is_empty()); + assert!(read_trailer::<_, Pad>(io::empty(), 0) + .await + .unwrap() + .is_empty()); } } diff --git a/tvix/nix-compat/src/wire/bytes/writer.rs b/tvix/nix-compat/src/wire/bytes/writer.rs index f5632771e961..8b9b59aa1b85 100644 --- a/tvix/nix-compat/src/wire/bytes/writer.rs +++ b/tvix/nix-compat/src/wire/bytes/writer.rs @@ -232,19 +232,18 @@ where #[cfg(test)] mod tests { + use std::sync::LazyLock; use std::time::Duration; use crate::wire::bytes::write_bytes; use hex_literal::hex; - use lazy_static::lazy_static; use tokio::io::AsyncWriteExt; use tokio_test::{assert_err, assert_ok, io::Builder}; use super::*; - lazy_static! { - pub static ref LARGE_PAYLOAD: Vec<u8> = (0..255).collect::<Vec<u8>>().repeat(4 * 1024); - } + pub static LARGE_PAYLOAD: LazyLock<Vec<u8>> = + LazyLock::new(|| (0..255).collect::<Vec<u8>>().repeat(4 * 1024)); /// Helper function, calling the (simpler) write_bytes with the payload. /// We use this to create data we want to see on the wire. diff --git a/tvix/nix-compat/src/wire/mod.rs b/tvix/nix-compat/src/wire/mod.rs index 65c053d58e21..a197e3a1f451 100644 --- a/tvix/nix-compat/src/wire/mod.rs +++ b/tvix/nix-compat/src/wire/mod.rs @@ -3,6 +3,3 @@ mod bytes; pub use bytes::*; - -mod primitive; -pub use primitive::*; diff --git a/tvix/nix-compat/src/wire/primitive.rs b/tvix/nix-compat/src/wire/primitive.rs deleted file mode 100644 index ee0f5fc4279d..000000000000 --- a/tvix/nix-compat/src/wire/primitive.rs +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-FileCopyrightText: 2023 embr <git@liclac.eu> -// -// SPDX-License-Identifier: EUPL-1.2 - -use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; - -#[allow(dead_code)] -/// Read a u64 from the AsyncRead (little endian). -pub async fn read_u64<R: AsyncReadExt + Unpin>(r: &mut R) -> std::io::Result<u64> { - r.read_u64_le().await -} - -/// Write a u64 to the AsyncWrite (little endian). -pub async fn write_u64<W: AsyncWrite + Unpin>(w: &mut W, v: u64) -> std::io::Result<()> { - w.write_u64_le(v).await -} - -#[allow(dead_code)] -/// Read a boolean from the AsyncRead, encoded as u64 (>0 is true). -pub async fn read_bool<R: AsyncRead + Unpin>(r: &mut R) -> std::io::Result<bool> { - Ok(read_u64(r).await? > 0) -} - -#[allow(dead_code)] -/// Write a boolean to the AsyncWrite, encoded as u64 (>0 is true). -pub async fn write_bool<W: AsyncWrite + Unpin>(w: &mut W, v: bool) -> std::io::Result<()> { - write_u64(w, if v { 1u64 } else { 0u64 }).await -} - -#[cfg(test)] -mod tests { - use super::*; - use tokio_test::io::Builder; - - // Integers. - #[tokio::test] - async fn test_read_u64() { - let mut mock = Builder::new().read(&1234567890u64.to_le_bytes()).build(); - assert_eq!(1234567890u64, read_u64(&mut mock).await.unwrap()); - } - #[tokio::test] - async fn test_write_u64() { - let mut mock = Builder::new().write(&1234567890u64.to_le_bytes()).build(); - write_u64(&mut mock, 1234567890).await.unwrap(); - } - - // Booleans. - #[tokio::test] - async fn test_read_bool_0() { - let mut mock = Builder::new().read(&0u64.to_le_bytes()).build(); - assert!(!read_bool(&mut mock).await.unwrap()); - } - #[tokio::test] - async fn test_read_bool_1() { - let mut mock = Builder::new().read(&1u64.to_le_bytes()).build(); - assert!(read_bool(&mut mock).await.unwrap()); - } - #[tokio::test] - async fn test_read_bool_2() { - let mut mock = Builder::new().read(&2u64.to_le_bytes()).build(); - assert!(read_bool(&mut mock).await.unwrap()); - } - - #[tokio::test] - async fn test_write_bool_false() { - let mut mock = Builder::new().write(&0u64.to_le_bytes()).build(); - write_bool(&mut mock, false).await.unwrap(); - } - #[tokio::test] - async fn test_write_bool_true() { - let mut mock = Builder::new().write(&1u64.to_le_bytes()).build(); - write_bool(&mut mock, true).await.unwrap(); - } -} diff --git a/tvix/nix-compat/testdata/nix.conf b/tvix/nix-compat/testdata/nix.conf new file mode 100644 index 000000000000..1fa089053eb6 --- /dev/null +++ b/tvix/nix-compat/testdata/nix.conf @@ -0,0 +1,20 @@ +# WARNING: this file is generated from the nix.* options in +# your NixOS configuration, typically +# /etc/nixos/configuration.nix. Do not edit it! +allowed-users = * +auto-optimise-store = false +cores = 0 +max-jobs = 8 +require-sigs = true +sandbox = true +sandbox-fallback = false +substituters = https://nix-community.cachix.org https://cache.nixos.org/ +system-features = nixos-test benchmark big-parallel kvm +trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= +trusted-substituters = +trusted-users = flokli +extra-platforms = aarch64-linux i686-linux +extra-sandbox-paths = /run/binfmt /nix/store/swwyxyqpazzvbwx8bv40z7ih144q841f-qemu-aarch64-binfmt-P-x86_64-unknown-linux-musl +experimental-features = nix-command + +builders-use-substitutes = true diff --git a/tvix/nix-compat/testdata/other_nix.conf b/tvix/nix-compat/testdata/other_nix.conf new file mode 100644 index 000000000000..63c4ea2ec78e --- /dev/null +++ b/tvix/nix-compat/testdata/other_nix.conf @@ -0,0 +1,18 @@ +# This file contains some more comments in various places. +allowed-users = * +auto-optimise-store = false +cores = 0 +max-jobs = 8 +require-sigs = true +sandbox=true +sandbox-fallback = false +substituters = https://nix-community.cachix.org https://cache.nixos.org/ #comment # stillcomment +system-features = nixos-test benchmark big-parallel kvm +trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= +trusted-substituters = +trusted-users = flokli +extra-platforms = aarch64-linux i686-linux +extra-sandbox-paths = /run/binfmt /nix/store/swwyxyqpazzvbwx8bv40z7ih144q841f-qemu-aarch64-binfmt-P-x86_64-unknown-linux-musl +experimental-features = nix-command + +builders-use-substitutes = true diff --git a/tvix/nix-daemon/Cargo.toml b/tvix/nix-daemon/Cargo.toml new file mode 100644 index 000000000000..39b34019b424 --- /dev/null +++ b/tvix/nix-daemon/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "nix-daemon" +version = "0.1.0" +edition = "2021" + +[dependencies] +async-trait = "0.1.83" +clap = { workspace = true, features = ["derive", "env"] } +futures = { workspace = true } +mimalloc = { workspace = true } +nix-compat = { path = "../nix-compat" } +tvix-castore = { path = "../castore" } +tvix-store = { path = "../store" } +tvix-tracing = { path = "../tracing" } +tokio = { workspace = true, features = ["fs", "macros", "net", "rt", "rt-multi-thread", "signal"] } +tokio-listener = { workspace = true } +tracing = { workspace = true } + +[lints] +workspace = true + +[features] +default = ["otlp"] +otlp = ["tvix-tracing/otlp"] \ No newline at end of file diff --git a/tvix/nix-daemon/default.nix b/tvix/nix-daemon/default.nix new file mode 100644 index 000000000000..740bc851ea19 --- /dev/null +++ b/tvix/nix-daemon/default.nix @@ -0,0 +1,5 @@ +{ depot, ... }: + +depot.tvix.crates.workspaceMembers.nix-daemon.build.override { + runTests = true; +} diff --git a/tvix/nix-daemon/src/bin/nix-daemon.rs b/tvix/nix-daemon/src/bin/nix-daemon.rs new file mode 100644 index 000000000000..769e968309f8 --- /dev/null +++ b/tvix/nix-daemon/src/bin/nix-daemon.rs @@ -0,0 +1,90 @@ +use clap::Parser; +use mimalloc::MiMalloc; +use std::error::Error; +use tokio::io::AsyncWriteExt; +use tokio_listener::SystemOptions; +use tvix_store::utils::{construct_services, ServiceUrlsGrpc}; + +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; + +/// Run Nix-compatible store daemon backed by tvix. +#[derive(Parser)] +struct Cli { + #[clap(flatten)] + service_addrs: ServiceUrlsGrpc, + + /// The address to listen on. Must be a unix domain socket. + #[clap(flatten)] + listen_args: tokio_listener::ListenerAddressLFlag, + + #[cfg(feature = "otlp")] + /// Whether to configure OTLP. Set --otlp=false to disable. + #[arg(long, default_missing_value = "true", default_value = "true", num_args(0..=1), require_equals(true), action(clap::ArgAction::Set))] + otlp: bool, +} + +#[tokio::main] +async fn main() -> Result<(), Box<dyn Error + Send + Sync>> { + let cli = Cli::parse(); + + let tracing_handle = { + let mut builder = tvix_tracing::TracingBuilder::default(); + builder = builder.enable_progressbar(); + #[cfg(feature = "otlp")] + { + if cli.otlp { + builder = builder.enable_otlp("tvix.daemon"); + } + } + builder.build()? + }; + + tokio::select! { + res = tokio::signal::ctrl_c() => { + res?; + if let Err(e) = tracing_handle.force_shutdown().await { + eprintln!("failed to shutdown tracing: {e}"); + } + Ok(()) + }, + res = run(cli) => { + if let Err(e) = tracing_handle.shutdown().await { + eprintln!("failed to shutdown tracing: {e}"); + } + res + } + } +} + +async fn run(cli: Cli) -> Result<(), Box<dyn std::error::Error + Send + Sync>> { + let (_blob_service, _directory_service, _path_info_service, _nar_calculation_service) = + construct_services(cli.service_addrs).await?; + + let listen_address = cli.listen_args.listen_address.unwrap_or_else(|| { + "/tmp/tvix-daemon.sock" + .parse() + .expect("invalid fallback listen address") + }); + + let mut listener = tokio_listener::Listener::bind( + &listen_address, + &SystemOptions::default(), + &cli.listen_args.listener_options, + ) + .await?; + + while let Ok((mut connection, _)) = listener.accept().await { + tokio::spawn(async move { + let ucred = connection + .try_borrow_unix() + .and_then(|u| u.peer_cred().ok()); + + // For now we just write the connected process credentials into the connection. + let _ = connection + .write_all(format!("Hello {:?}", ucred).as_bytes()) + .await; + }); + } + Ok(()) +} diff --git a/tvix/serde/Cargo.toml b/tvix/serde/Cargo.toml index 5652126ada1d..fc5f08a2ddcd 100644 --- a/tvix/serde/Cargo.toml +++ b/tvix/serde/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" [dependencies] tvix-eval = { path = "../eval" } -serde = { version = "1.0", features = ["derive"] } -bstr = { version = "1.8.0", features = ["serde"] } +serde = { workspace = true, features = ["derive"] } +bstr = { workspace = true, features = ["serde"] } diff --git a/tvix/serde/examples/nixpkgs.rs b/tvix/serde/examples/nixpkgs.rs index ad8c4160b5d0..e3c589dba118 100644 --- a/tvix/serde/examples/nixpkgs.rs +++ b/tvix/serde/examples/nixpkgs.rs @@ -23,8 +23,8 @@ fn main() { } "#; - let result = tvix_serde::from_str_with_config::<Config, _>(code, |eval| { - eval.enable_impure(None); + let result = tvix_serde::from_str_with_config::<Config, _>(code, |eval_builder| { + eval_builder.enable_impure(None) }); match result { diff --git a/tvix/serde/src/de.rs b/tvix/serde/src/de.rs index 428b9e2e8114..0728311c6a13 100644 --- a/tvix/serde/src/de.rs +++ b/tvix/serde/src/de.rs @@ -3,8 +3,7 @@ use bstr::ByteSlice; use serde::de::value::{MapDeserializer, SeqDeserializer}; use serde::de::{self, EnumAccess, VariantAccess}; -pub use tvix_eval::Evaluation; -use tvix_eval::{EvalIO, Value}; +use tvix_eval::{EvalIO, EvalMode, EvaluationBuilder, Value}; use crate::error::Error; @@ -36,7 +35,7 @@ pub fn from_str<'code, T>(src: &'code str) -> Result<T, Error> where T: serde::Deserialize<'code>, { - from_str_with_config(src, |_| /* no extra config */ ()) + from_str_with_config(src, |b| /* no extra config */ b) } /// Evaluate the Nix code in `src`, with extra configuration for the @@ -44,13 +43,12 @@ where pub fn from_str_with_config<'code, T, F>(src: &'code str, config: F) -> Result<T, Error> where T: serde::Deserialize<'code>, - F: FnOnce(&mut Evaluation<Box<dyn EvalIO>>), + F: for<'co, 'ro, 'env> FnOnce( + EvaluationBuilder<'co, 'ro, 'env, Box<dyn EvalIO>>, + ) -> EvaluationBuilder<'co, 'ro, 'env, Box<dyn EvalIO>>, { // First step is to evaluate the Nix code ... - let mut eval = Evaluation::new_pure(); - config(&mut eval); - - eval.strict = true; + let eval = config(EvaluationBuilder::new_pure().mode(EvalMode::Strict)).build(); let result = eval.evaluate(src, None); if !result.errors.is_empty() { diff --git a/tvix/serde/src/de_tests.rs b/tvix/serde/src/de_tests.rs index 1c3acd1c2f52..d62464da9a9f 100644 --- a/tvix/serde/src/de_tests.rs +++ b/tvix/serde/src/de_tests.rs @@ -204,7 +204,7 @@ fn deserialize_enum_all() { fn deserialize_with_config() { let result: String = from_str_with_config("builtins.testWithConfig", |eval| { // Add a literal string builtin that just returns `"ok"`. - eval.src_builtins.push(("testWithConfig", "\"ok\"")); + eval.add_src_builtin("testWithConfig", "\"ok\"") }) .expect("should deserialize"); @@ -236,10 +236,9 @@ mod test_builtins { fn deserialize_with_extra_builtin() { let code = "builtins.prependHello \"world\""; - let result: String = from_str_with_config(code, |eval| { - eval.builtins.append(&mut test_builtins::builtins()); - }) - .expect("should deserialize"); + let result: String = + from_str_with_config(code, |eval| eval.add_builtins(test_builtins::builtins())) + .expect("should deserialize"); assert_eq!(result, "hello world"); } diff --git a/tvix/shell.nix b/tvix/shell.nix index 422f1c8dd40a..7b8e29e9966a 100644 --- a/tvix/shell.nix +++ b/tvix/shell.nix @@ -10,12 +10,18 @@ depot.third_party.sources = import ./sources { }; additionalOverlays = [ (self: super: { - # https://github.com/googleapis/google-cloud-go/pull/9665 - cbtemulator = super.cbtemulator.overrideAttrs (old: { - patches = old.patches or [ ] ++ [ - ./nixpkgs/cbtemulator-uds.patch - ]; - }); + # macFUSE bump containing fix for https://github.com/osxfuse/osxfuse/issues/974 + # https://github.com/NixOS/nixpkgs/pull/320197 + fuse = + if super.stdenv.isDarwin then + super.fuse.overrideAttrs + (old: rec { + version = "4.8.0"; + src = super.fetchurl { + url = "https://github.com/osxfuse/osxfuse/releases/download/macfuse-${version}/macfuse-${version}.dmg"; + hash = "sha256-ucTzO2qdN4QkowMVvC3+4pjEVjbwMsB0xFk+bvQxwtQ="; + }; + }) else super.fuse; }) ]; }) @@ -29,15 +35,17 @@ pkgs.mkShell { pkgs.cargo pkgs.cargo-machete pkgs.cargo-expand - pkgs.cbtemulator + pkgs.cargo-flamegraph pkgs.clippy + pkgs.d2 pkgs.evans pkgs.fuse pkgs.go - pkgs.google-cloud-bigtable-tool pkgs.grpcurl pkgs.hyperfine pkgs.mdbook + pkgs.mdbook-admonish + pkgs.mdbook-d2 pkgs.mdbook-plantuml pkgs.nix_2_3 # b/313 pkgs.pkg-config @@ -46,6 +54,8 @@ pkgs.mkShell { pkgs.rustfmt pkgs.plantuml pkgs.protobuf + ] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ + pkgs.runc ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ # We need these two dependencies in the ambient environment to be able to # `cargo build` on MacOS. @@ -59,6 +69,7 @@ pkgs.mkShell { # should also benchmark with a more static nixpkgs checkout, so nixpkgs # refactorings are not observed as eval perf changes. shellHook = '' + export TVIX_BUILD_SANDBOX_SHELL=${if pkgs.stdenv.isLinux then pkgs.busybox-sandbox-shell + "/bin/busybox" else "/bin/sh"} export TVIX_BENCH_NIX_PATH=nixpkgs=${pkgs.path} ''; } diff --git a/tvix/store-go/pathinfo.pb.go b/tvix/store-go/pathinfo.pb.go index a4915a3c1f25..4941d80a8754 100644 --- a/tvix/store-go/pathinfo.pb.go +++ b/tvix/store-go/pathinfo.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.35.1 // protoc (unknown) // source: tvix/store/protos/pathinfo.proto @@ -118,11 +118,9 @@ type PathInfo struct { func (x *PathInfo) Reset() { *x = PathInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *PathInfo) String() string { @@ -133,7 +131,7 @@ func (*PathInfo) ProtoMessage() {} func (x *PathInfo) ProtoReflect() protoreflect.Message { mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -185,11 +183,9 @@ type StorePath struct { func (x *StorePath) Reset() { *x = StorePath{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *StorePath) String() string { @@ -200,7 +196,7 @@ func (*StorePath) ProtoMessage() {} func (x *StorePath) ProtoReflect() protoreflect.Message { mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -285,11 +281,9 @@ type NARInfo struct { func (x *NARInfo) Reset() { *x = NARInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *NARInfo) String() string { @@ -300,7 +294,7 @@ func (*NARInfo) ProtoMessage() {} func (x *NARInfo) ProtoReflect() protoreflect.Message { mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -369,11 +363,9 @@ type NARInfo_Signature struct { func (x *NARInfo_Signature) Reset() { *x = NARInfo_Signature{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *NARInfo_Signature) String() string { @@ -384,7 +376,7 @@ func (*NARInfo_Signature) ProtoMessage() {} func (x *NARInfo_Signature) ProtoReflect() protoreflect.Message { mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -426,11 +418,9 @@ type NARInfo_CA struct { func (x *NARInfo_CA) Reset() { *x = NARInfo_CA{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *NARInfo_CA) String() string { @@ -441,7 +431,7 @@ func (*NARInfo_CA) ProtoMessage() {} func (x *NARInfo_CA) ProtoReflect() protoreflect.Message { mi := &file_tvix_store_protos_pathinfo_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -545,7 +535,7 @@ func file_tvix_store_protos_pathinfo_proto_rawDescGZIP() []byte { var file_tvix_store_protos_pathinfo_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_tvix_store_protos_pathinfo_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_tvix_store_protos_pathinfo_proto_goTypes = []interface{}{ +var file_tvix_store_protos_pathinfo_proto_goTypes = []any{ (NARInfo_CA_Hash)(0), // 0: tvix.store.v1.NARInfo.CA.Hash (*PathInfo)(nil), // 1: tvix.store.v1.PathInfo (*StorePath)(nil), // 2: tvix.store.v1.StorePath @@ -573,68 +563,6 @@ func file_tvix_store_protos_pathinfo_proto_init() { if File_tvix_store_protos_pathinfo_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_tvix_store_protos_pathinfo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PathInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_store_protos_pathinfo_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StorePath); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_store_protos_pathinfo_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NARInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_store_protos_pathinfo_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NARInfo_Signature); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_store_protos_pathinfo_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NARInfo_CA); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/tvix/store-go/rpc_pathinfo.pb.go b/tvix/store-go/rpc_pathinfo.pb.go index 883ffb3f01ba..35733843059d 100644 --- a/tvix/store-go/rpc_pathinfo.pb.go +++ b/tvix/store-go/rpc_pathinfo.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.35.1 // protoc (unknown) // source: tvix/store/protos/rpc_pathinfo.proto @@ -39,11 +39,9 @@ type GetPathInfoRequest struct { func (x *GetPathInfoRequest) Reset() { *x = GetPathInfoRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GetPathInfoRequest) String() string { @@ -54,7 +52,7 @@ func (*GetPathInfoRequest) ProtoMessage() {} func (x *GetPathInfoRequest) ProtoReflect() protoreflect.Message { mi := &file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -107,11 +105,9 @@ type ListPathInfoRequest struct { func (x *ListPathInfoRequest) Reset() { *x = ListPathInfoRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ListPathInfoRequest) String() string { @@ -122,7 +118,7 @@ func (*ListPathInfoRequest) ProtoMessage() {} func (x *ListPathInfoRequest) ProtoReflect() protoreflect.Message { mi := &file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -154,11 +150,9 @@ type CalculateNARResponse struct { func (x *CalculateNARResponse) Reset() { *x = CalculateNARResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *CalculateNARResponse) String() string { @@ -169,7 +163,7 @@ func (*CalculateNARResponse) ProtoMessage() {} func (x *CalculateNARResponse) ProtoReflect() protoreflect.Message { mi := &file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -256,7 +250,7 @@ func file_tvix_store_protos_rpc_pathinfo_proto_rawDescGZIP() []byte { } var file_tvix_store_protos_rpc_pathinfo_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_tvix_store_protos_rpc_pathinfo_proto_goTypes = []interface{}{ +var file_tvix_store_protos_rpc_pathinfo_proto_goTypes = []any{ (*GetPathInfoRequest)(nil), // 0: tvix.store.v1.GetPathInfoRequest (*ListPathInfoRequest)(nil), // 1: tvix.store.v1.ListPathInfoRequest (*CalculateNARResponse)(nil), // 2: tvix.store.v1.CalculateNARResponse @@ -285,45 +279,7 @@ func file_tvix_store_protos_rpc_pathinfo_proto_init() { return } file_tvix_store_protos_pathinfo_proto_init() - if !protoimpl.UnsafeEnabled { - file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetPathInfoRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListPathInfoRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CalculateNARResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_tvix_store_protos_rpc_pathinfo_proto_msgTypes[0].OneofWrappers = []any{ (*GetPathInfoRequest_ByOutputHash)(nil), } type x struct{} diff --git a/tvix/store/Cargo.toml b/tvix/store/Cargo.toml index b549eeb7f514..865b1f4f61b9 100644 --- a/tvix/store/Cargo.toml +++ b/tvix/store/Cargo.toml @@ -4,65 +4,63 @@ version = "0.1.0" edition = "2021" [dependencies] -anyhow = "1.0.68" -async-stream = "0.3.5" -blake3 = { version = "1.3.1", features = ["rayon", "std"] } -bstr = "1.6.0" -bytes = "1.4.0" -clap = { version = "4.0", features = ["derive", "env"] } -count-write = "0.1.0" -data-encoding = "2.3.3" -futures = "0.3.30" -lazy_static = "1.4.0" +anyhow = { workspace = true } +async-compression = { workspace = true, features = ["tokio", "bzip2", "gzip", "xz", "zstd"] } +async-stream = { workspace = true } +blake3 = { workspace = true, features = ["rayon", "std"] } +bstr = { workspace = true } +bytes = { workspace = true } +clap = { workspace = true, features = ["derive", "env"] } +count-write = { workspace = true } +data-encoding = { workspace = true } +ed25519 = { workspace = true } +ed25519-dalek = { workspace = true } +futures = { workspace = true } nix-compat = { path = "../nix-compat", features = ["async"] } -pin-project-lite = "0.2.13" -prost = "0.12.1" -opentelemetry = { version = "0.21.0", optional = true} -opentelemetry-otlp = { version = "0.14.0", optional = true } -opentelemetry_sdk = { version = "0.21.0", features = ["rt-tokio"], optional = true} -serde = { version = "1.0.197", features = [ "derive" ] } -serde_json = "1.0" -serde_with = "3.7.0" -serde_qs = "0.12.0" -sha2 = "0.10.6" -sled = { version = "0.34.7" } -thiserror = "1.0.38" -tokio = { version = "1.32.0", features = ["fs", "macros", "net", "rt", "rt-multi-thread", "signal"] } -tokio-listener = { version = "0.3.2", features = [ "tonic011" ] } -tokio-stream = { version = "0.1.14", features = ["fs"] } -tokio-util = { version = "0.7.9", features = ["io", "io-util", "compat"] } -tonic = { version = "0.11.0", features = ["tls", "tls-roots"] } -tower = "0.4.13" -tracing = "0.1.37" -tracing-opentelemetry = "0.22.0" -tracing-subscriber = { version = "0.3.16", features = ["env-filter", "json"] } +pin-project-lite = { workspace = true } +prost = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +serde_with = { workspace = true } +serde_qs = { workspace = true } +sha2 = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true, features = ["fs", "macros", "net", "rt", "rt-multi-thread", "signal"] } +tokio-listener = { workspace = true, features = ["clap", "multi-listener", "sd_listen", "tonic012"] } +tokio-stream = { workspace = true, features = ["fs"] } +tokio-util = { workspace = true, features = ["io", "io-util", "compat"] } +tonic = { workspace = true, features = ["tls", "tls-roots"] } +tower = { workspace = true } +tower-http = { workspace = true, features = ["trace"] } tvix-castore = { path = "../castore" } -url = "2.4.0" -walkdir = "2.4.0" -async-recursion = "1.0.5" -reqwest = { version = "0.11.22", features = ["rustls-tls-native-roots", "stream"], default-features = false } -xz2 = "0.1.7" - -[dependencies.tonic-reflection] -optional = true -version = "0.11.0" - -[dependencies.bigtable_rs] -optional = true -# https://github.com/liufuyang/bigtable_rs/pull/72 -git = "https://github.com/flokli/bigtable_rs" -rev = "0af404741dfc40eb9fa99cf4d4140a09c5c20df7" +url = { workspace = true } +walkdir = { workspace = true } +reqwest = { workspace = true, features = ["rustls-tls-native-roots", "stream"] } +reqwest-middleware = { workspace = true } +lru = { workspace = true } +parking_lot = { workspace = true } +tvix-tracing = { path = "../tracing", features = ["tonic", "reqwest"] } +tracing = { workspace = true } +tracing-indicatif = { workspace = true } +hyper-util = { workspace = true } +toml = { version = "0.8.19", optional = true } +tonic-health = { workspace = true } +redb = { workspace = true, features = ["logging"] } +mimalloc = { workspace = true } +tonic-reflection = { workspace = true, optional = true } +bigtable_rs = { workspace = true, optional = true } +auto_impl = "1.2.0" [build-dependencies] -prost-build = "0.12.1" -tonic-build = "0.11.0" +prost-build = { workspace = true } +tonic-build = { workspace = true } [dev-dependencies] -async-process = "2.1.0" -rstest = "0.19.0" -rstest_reuse = "0.6.0" -tempfile = "3.3.0" -tokio-retry = "0.3.0" +async-process = { workspace = true } +rstest = { workspace = true } +rstest_reuse = { workspace = true } +tempfile = { workspace = true } +tokio-retry = { workspace = true } [features] default = ["cloud", "fuse", "otlp", "tonic-reflection"] @@ -71,6 +69,15 @@ cloud = [ "tvix-castore/cloud" ] fuse = ["tvix-castore/fuse"] -otlp = ["dep:opentelemetry", "dep:opentelemetry-otlp", "dep:opentelemetry_sdk"] +otlp = ["tvix-tracing/otlp"] tonic-reflection = ["dep:tonic-reflection", "tvix-castore/tonic-reflection"] +tracy = ["tvix-tracing/tracy"] virtiofs = ["tvix-castore/virtiofs"] +xp-store-composition = ["toml", "tvix-castore/xp-store-composition"] +# Whether to run the integration tests. +# Requires the following packages in $PATH: +# cbtemulator, google-cloud-bigtable-tool +integration = [] + +[lints] +workspace = true diff --git a/tvix/store/build.rs b/tvix/store/build.rs index 809fa29578b5..f3ff05ffc598 100644 --- a/tvix/store/build.rs +++ b/tvix/store/build.rs @@ -12,24 +12,20 @@ fn main() -> Result<()> { builder = builder.file_descriptor_set_path(descriptor_path); }; - // https://github.com/hyperium/tonic/issues/908 - let mut config = prost_build::Config::new(); - config.bytes(["."]); - config.extern_path(".tvix.castore.v1", "::tvix_castore::proto"); - builder .build_server(true) .build_client(true) .emit_rerun_if_changed(false) - .compile_with_config( - config, + .bytes(["."]) + .extern_path(".tvix.castore.v1", "::tvix_castore::proto") + .compile_protos( &[ "tvix/store/protos/pathinfo.proto", "tvix/store/protos/rpc_pathinfo.proto", ], // If we are in running `cargo build` manually, using `../..` works fine, // but in case we run inside a nix build, we need to instead point PROTO_ROOT - // to a sparseTree containing that structure. + // to a custom tree containing that structure. &[match std::env::var_os("PROTO_ROOT") { Some(proto_root) => proto_root.to_str().unwrap().to_owned(), None => "../..".to_string(), diff --git a/tvix/store/default.nix b/tvix/store/default.nix index f30923ac272a..863ddb6de23f 100644 --- a/tvix/store/default.nix +++ b/tvix/store/default.nix @@ -1,4 +1,4 @@ -{ depot, pkgs, ... }: +{ depot, pkgs, lib, ... }: let mkImportCheck = p: expectedPath: { @@ -22,19 +22,35 @@ let }; in -(depot.tvix.crates.workspaceMembers.tvix-store.build.override { +(depot.tvix.crates.workspaceMembers.tvix-store.build.override (old: { runTests = true; testPreRun = '' - export SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt - export PATH="$PATH:${pkgs.lib.makeBinPath [pkgs.cbtemulator pkgs.google-cloud-bigtable-tool]}" + export SSL_CERT_FILE=/dev/null ''; - - # enable some optional features. - features = [ "default" "cloud" ] - # virtiofs feature currently fails to build on Darwin. - ++ pkgs.lib.optional pkgs.stdenv.isLinux "virtiofs"; -}).overrideAttrs (_: { - meta.ci.extraSteps = { - import-docs = (mkImportCheck "tvix/store/docs" ./docs); + features = old.features + # virtiofs feature currently fails to build on Darwin + ++ lib.optional pkgs.stdenv.isLinux "virtiofs"; +})).overrideAttrs (old: rec { + meta.ci = { + targets = [ "integration-tests" ] ++ lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); + extraSteps.import-docs = (mkImportCheck "tvix/docs/src/store" ../docs/src/store); + }; + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { + inherit (old) crateName; + features = ([ "cloud" "fuse" "otlp" "tonic-reflection" "xp-store-composition" ] + # virtiofs feature currently fails to build on Darwin + ++ lib.optional pkgs.stdenv.isLinux "virtiofs"); + override.testPreRun = '' + export SSL_CERT_FILE=/dev/null + ''; + }) // { + integration-tests = depot.tvix.crates.workspaceMembers.${old.crateName}.build.override (old: { + runTests = true; + testPreRun = '' + export SSL_CERT_FILE=/dev/null + export PATH="$PATH:${pkgs.lib.makeBinPath [ pkgs.cbtemulator pkgs.google-cloud-bigtable-tool ]}" + ''; + features = old.features ++ [ "integration" ]; + }); }; }) diff --git a/tvix/store/protos/default.nix b/tvix/store/protos/default.nix index 56345d9338b2..005a2697e5e9 100644 --- a/tvix/store/protos/default.nix +++ b/tvix/store/protos/default.nix @@ -1,17 +1,12 @@ -{ depot, pkgs, ... }: +{ depot, pkgs, lib, ... }: let - protos = depot.nix.sparseTree { - name = "store-protos"; - root = depot.path.origSrc; - paths = [ - # We need to include castore.proto (only), as it's referred. - ../../castore/protos/castore.proto - ./pathinfo.proto - ./rpc_pathinfo.proto - ../../../buf.yaml - ../../../buf.gen.yaml - ]; - }; + protos = lib.sourceByRegex depot.path.origSrc [ + "buf.yaml" + "buf.gen.yaml" + # We need to include castore.proto (only), as it's referred. + "^tvix(/castore(/protos(/castore\.proto)?)?)?$" + "^tvix(/store(/protos(/.*\.proto)?)?)?$" + ]; in depot.nix.readTree.drvTargets { inherit protos; diff --git a/tvix/store/src/bin/tvix-store.rs b/tvix/store/src/bin/tvix-store.rs index 4662cf67d53c..0ae18ec2161a 100644 --- a/tvix/store/src/bin/tvix-store.rs +++ b/tvix/store/src/bin/tvix-store.rs @@ -1,32 +1,32 @@ use clap::Parser; use clap::Subcommand; -use futures::future::try_join_all; use futures::StreamExt; use futures::TryStreamExt; -use nix_compat::path_info::ExportedPathInfo; +use nix_compat::nix_daemon::de::Error; +use nix_compat::nixhash::CAHash; +use nix_compat::nixhash::NixHash; +use nix_compat::{path_info::ExportedPathInfo, store_path::StorePath}; use serde::Deserialize; use serde::Serialize; use std::path::PathBuf; use std::sync::Arc; -use tokio_listener::Listener; -use tokio_listener::SystemOptions; -use tokio_listener::UserOptions; use tonic::transport::Server; -use tracing::info; -use tracing::Level; -use tracing_subscriber::EnvFilter; -use tracing_subscriber::Layer; -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; +use tower::ServiceBuilder; +use tower_http::trace::{DefaultMakeSpan, TraceLayer}; +use tracing::{debug, info, info_span, instrument, warn, Instrument, Level, Span}; +use tracing_indicatif::span_ext::IndicatifSpanExt; use tvix_castore::import::fs::ingest_path; -use tvix_store::proto::NarInfo; -use tvix_store::proto::PathInfo; +use tvix_store::import::path_to_name; +use tvix_store::nar::NarCalculationService; +use tvix_store::utils::{ServiceUrls, ServiceUrlsGrpc}; +use tvix_tracing::TracingHandle; use tvix_castore::proto::blob_service_server::BlobServiceServer; use tvix_castore::proto::directory_service_server::DirectoryServiceServer; use tvix_castore::proto::GRPCBlobServiceWrapper; use tvix_castore::proto::GRPCDirectoryServiceWrapper; -use tvix_store::pathinfoservice::PathInfoService; +use tvix_store::pathinfoservice::{PathInfo, PathInfoService}; use tvix_store::proto::path_info_service_server::PathInfoServiceServer; use tvix_store::proto::GRPCPathInfoServiceWrapper; @@ -36,15 +36,6 @@ use tvix_store::pathinfoservice::make_fs; #[cfg(feature = "fuse")] use tvix_castore::fs::fuse::FuseDaemon; -#[cfg(feature = "otlp")] -use opentelemetry::KeyValue; -#[cfg(feature = "otlp")] -use opentelemetry_sdk::{ - resource::{ResourceDetector, SdkProvidedResourceDetector}, - trace::BatchConfig, - Resource, -}; - #[cfg(feature = "virtiofs")] use tvix_castore::fs::virtiofs::start_virtiofs_daemon; @@ -53,6 +44,11 @@ use tvix_castore::proto::FILE_DESCRIPTOR_SET as CASTORE_FILE_DESCRIPTOR_SET; #[cfg(feature = "tonic-reflection")] use tvix_store::proto::FILE_DESCRIPTOR_SET; +use mimalloc::MiMalloc; + +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; + #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Cli { @@ -60,13 +56,6 @@ struct Cli { #[arg(long, default_missing_value = "true", default_value = "true", num_args(0..=1), require_equals(true), action(clap::ArgAction::Set))] otlp: bool, - /// A global log level to use when printing logs. - /// It's also possible to set `RUST_LOG` according to - /// `tracing_subscriber::filter::EnvFilter`, which will always have - /// priority. - #[arg(long)] - log_level: Option<Level>, - #[command(subcommand)] command: Commands, } @@ -75,47 +64,26 @@ struct Cli { enum Commands { /// Runs the tvix-store daemon. Daemon { - #[arg(long, short = 'l')] - listen_address: Option<String>, - - #[arg(long, env, default_value = "sled:///var/lib/tvix-store/blobs.sled")] - blob_service_addr: String, + /// The address to listen on. + #[clap(flatten)] + listen_args: tokio_listener::ListenerAddressLFlag, - #[arg( - long, - env, - default_value = "sled:///var/lib/tvix-store/directories.sled" - )] - directory_service_addr: String, - - #[arg(long, env, default_value = "sled:///var/lib/tvix-store/pathinfo.sled")] - path_info_service_addr: String, + #[clap(flatten)] + service_addrs: ServiceUrls, }, /// Imports a list of paths into the store, print the store path for each of them. Import { #[clap(value_name = "PATH")] paths: Vec<PathBuf>, - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - blob_service_addr: String, - - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - directory_service_addr: String, - - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - path_info_service_addr: String, + #[clap(flatten)] + service_addrs: ServiceUrlsGrpc, }, /// Copies a list of store paths on the system into tvix-store. Copy { - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - blob_service_addr: String, - - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - directory_service_addr: String, - - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - path_info_service_addr: String, + #[clap(flatten)] + service_addrs: ServiceUrlsGrpc, /// A path pointing to a JSON file produced by the Nix /// `__structuredAttrs` containing reference graph information provided @@ -135,14 +103,8 @@ enum Commands { #[clap(value_name = "PATH")] dest: PathBuf, - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - blob_service_addr: String, - - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - directory_service_addr: String, - - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - path_info_service_addr: String, + #[clap(flatten)] + service_addrs: ServiceUrlsGrpc, /// Number of FUSE threads to spawn. #[arg(long, env, default_value_t = default_threads())] @@ -171,14 +133,8 @@ enum Commands { #[clap(value_name = "PATH")] socket: PathBuf, - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - blob_service_addr: String, - - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - directory_service_addr: String, - - #[arg(long, env, default_value = "grpc+http://[::1]:8000")] - path_info_service_addr: String, + #[clap(flatten)] + service_addrs: ServiceUrlsGrpc, /// Whether to list elements at the root of the mount point. /// This is useful if your PathInfoService doesn't provide an @@ -192,113 +148,44 @@ enum Commands { }, } -#[cfg(all(feature = "fuse", not(target_os = "macos")))] +#[cfg(feature = "fuse")] fn default_threads() -> usize { std::thread::available_parallelism() .map(|threads| threads.into()) .unwrap_or(4) } -// On MacFUSE only a single channel will receive ENODEV when the file system is -// unmounted and so all the other channels will block forever. -// See https://github.com/osxfuse/osxfuse/issues/974 -#[cfg(all(feature = "fuse", target_os = "macos"))] -fn default_threads() -> usize { - 1 -} - -#[tokio::main] -async fn main() -> Result<(), Box<dyn std::error::Error>> { - let cli = Cli::parse(); - - // configure log settings - let level = cli.log_level.unwrap_or(Level::INFO); - - // Set up the tracing subscriber. - let subscriber = tracing_subscriber::registry().with( - tracing_subscriber::fmt::Layer::new() - .with_writer(std::io::stderr) - .compact() - .with_filter( - EnvFilter::builder() - .with_default_directive(level.into()) - .from_env() - .expect("invalid RUST_LOG"), - ), - ); - - // Add the otlp layer (when otlp is enabled, and it's not disabled in the CLI) - // then init the registry. - // If the feature is feature-flagged out, just init without adding the layer. - // It's necessary to do this separately, as every with() call chains the - // layer into the type of the registry. - #[cfg(feature = "otlp")] - { - let subscriber = if cli.otlp { - let tracer = opentelemetry_otlp::new_pipeline() - .tracing() - .with_exporter(opentelemetry_otlp::new_exporter().tonic()) - .with_batch_config(BatchConfig::default()) - .with_trace_config(opentelemetry_sdk::trace::config().with_resource({ - // use SdkProvidedResourceDetector.detect to detect resources, - // but replace the default service name with our default. - // https://github.com/open-telemetry/opentelemetry-rust/issues/1298 - let resources = - SdkProvidedResourceDetector.detect(std::time::Duration::from_secs(0)); - // SdkProvidedResourceDetector currently always sets - // `service.name`, but we don't like its default. - if resources.get("service.name".into()).unwrap() == "unknown_service".into() { - resources.merge(&Resource::new([KeyValue::new( - "service.name", - "tvix.store", - )])) - } else { - resources - } - })) - .install_batch(opentelemetry_sdk::runtime::Tokio)?; - - // Create a tracing layer with the configured tracer - let layer = tracing_opentelemetry::layer().with_tracer(tracer); - - subscriber.with(Some(layer)) - } else { - subscriber.with(None) - }; - - subscriber.try_init()?; - } - - // Init the registry (when otlp is not enabled) - #[cfg(not(feature = "otlp"))] - { - subscriber.try_init()?; - } +#[instrument(skip_all)] +async fn run_cli( + cli: Cli, + tracing_handle: TracingHandle, +) -> Result<(), Box<dyn std::error::Error + Send + Sync>> { match cli.command { Commands::Daemon { - listen_address, - blob_service_addr, - directory_service_addr, - path_info_service_addr, + listen_args, + service_addrs, } => { // initialize stores - let (blob_service, directory_service, path_info_service) = - tvix_store::utils::construct_services( - blob_service_addr, - directory_service_addr, - path_info_service_addr, - ) - .await?; - - let listen_address = listen_address - .unwrap_or_else(|| "[::]:8000".to_string()) - .parse() - .unwrap(); + let (blob_service, directory_service, path_info_service, nar_calculation_service) = + tvix_store::utils::construct_services(service_addrs).await?; + + let mut server = Server::builder().layer( + ServiceBuilder::new() + .layer( + TraceLayer::new_for_grpc().make_span_with( + DefaultMakeSpan::new() + .level(Level::INFO) + .include_headers(true), + ), + ) + .map_request(tvix_tracing::propagate::tonic::accept_trace), + ); - let mut server = Server::builder(); + let (_health_reporter, health_service) = tonic_health::server::health_reporter(); #[allow(unused_mut)] let mut router = server + .add_service(health_service) .add_service(BlobServiceServer::new(GRPCBlobServiceWrapper::new( blob_service, ))) @@ -306,90 +193,161 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { GRPCDirectoryServiceWrapper::new(directory_service), )) .add_service(PathInfoServiceServer::new(GRPCPathInfoServiceWrapper::new( - Arc::from(path_info_service), + path_info_service, + nar_calculation_service, ))); #[cfg(feature = "tonic-reflection")] { - let reflection_svc = tonic_reflection::server::Builder::configure() - .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) - .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) - .build()?; - router = router.add_service(reflection_svc); + router = router.add_service( + tonic_reflection::server::Builder::configure() + .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) + .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) + .build_v1alpha()?, + ); + router = router.add_service( + tonic_reflection::server::Builder::configure() + .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) + .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) + .build_v1()?, + ); } - info!(listen_address=%listen_address, "starting daemon"); + let listen_address = &listen_args.listen_address.unwrap_or_else(|| { + "[::]:8000" + .parse() + .expect("invalid fallback listen address") + }); - let listener = Listener::bind( - &listen_address, - &SystemOptions::default(), - &UserOptions::default(), + let listener = tokio_listener::Listener::bind( + listen_address, + &Default::default(), + &listen_args.listener_options, ) .await?; + info!(listen_address=%listen_address, "starting daemon"); + router.serve_with_incoming(listener).await?; } Commands::Import { paths, - blob_service_addr, - directory_service_addr, - path_info_service_addr, + service_addrs, } => { // FUTUREWORK: allow flat for single files? - let (blob_service, directory_service, path_info_service) = - tvix_store::utils::construct_services( - blob_service_addr, - directory_service_addr, - path_info_service_addr, - ) - .await?; + let (blob_service, directory_service, path_info_service, nar_calculation_service) = + tvix_store::utils::construct_services(service_addrs).await?; - // Arc the PathInfoService, as we clone it . - let path_info_service: Arc<dyn PathInfoService> = path_info_service.into(); + // Arc NarCalculationService, as we clone it . + let nar_calculation_service: Arc<dyn NarCalculationService> = + nar_calculation_service.into(); - let tasks = paths + // For each path passed, construct the name, or bail out if it's invalid. + let paths_and_names = paths .into_iter() - .map(|path| { - tokio::task::spawn({ - let blob_service = blob_service.clone(); - let directory_service = directory_service.clone(); - let path_info_service = path_info_service.clone(); - - async move { - if let Ok(name) = tvix_store::import::path_to_name(&path) { - let resp = tvix_store::import::import_path_as_nar_ca( - &path, - name, - blob_service, - directory_service, - path_info_service, - ) - .await; - if let Ok(output_path) = resp { - // If the import was successful, print the path to stdout. - println!("{}", output_path.to_absolute_path()); - } + .map(|p| match path_to_name(&p) { + Ok(name) => { + let name = name.to_owned(); + Ok((p, name)) + } + Err(e) => Err(e), + }) + .collect::<Result<Vec<_>, _>>()?; + + let imports_span = + info_span!("import paths", "indicatif.pb_show" = tracing::field::Empty); + imports_span.pb_set_message("Importing"); + imports_span.pb_set_length(paths_and_names.len() as u64); + imports_span.pb_set_style(&tvix_tracing::PB_PROGRESS_STYLE); + imports_span.pb_start(); + + futures::stream::iter(paths_and_names) + .map(|(path, name)| { + let blob_service = blob_service.clone(); + let directory_service = directory_service.clone(); + let path_info_service = path_info_service.clone(); + let nar_calculation_service = nar_calculation_service.clone(); + let imports_span = imports_span.clone(); + let tracing_handle = tracing_handle.clone(); + + async move { + let span = Span::current(); + span.pb_set_style(&tvix_tracing::PB_SPINNER_STYLE); + span.pb_set_message(&format!("Ingesting {:?}", path)); + span.pb_start(); + + // Ingest the contents at the given path into castore. + let root_node = ingest_path::<_, _, _, &[u8]>( + blob_service, + directory_service, + &path, + None, + ) + .await + .map_err(std::io::Error::custom)?; + + span.pb_set_message(&format!("NAR Calculation for {:?}", path)); + + // Ask for the NAR size and sha256 + let (nar_size, nar_sha256) = + nar_calculation_service.calculate_nar(&root_node).await?; + + // Calculate the output path. This might still fail, as some names are illegal. + // FUTUREWORK: express the `name` at the type level to be valid and check for this earlier. + let ca = CAHash::Nar(NixHash::Sha256(nar_sha256)); + let output_path: StorePath<String> = + nix_compat::store_path::build_ca_path::<&str, _, _>( + &name, + &ca, + [], + false, + ) + .map_err(|e| { + warn!(err=%e, "unable to build CA path"); + std::io::Error::custom(e) + })?; + + // Construct and insert PathInfo + match path_info_service + .as_ref() + .put(PathInfo { + store_path: output_path.to_owned(), + node: root_node, + // There's no reference scanning on imported paths + references: vec![], + nar_size, + nar_sha256, + signatures: vec![], + deriver: None, + ca: Some(ca), + }) + .await + { + // If the import was successful, print the path to stdout. + Ok(path_info) => { + use std::io::Write; + debug!(store_path=%path_info.store_path.to_absolute_path(), "imported path"); + writeln!(&mut tracing_handle.get_stdout_writer(), "{}", path_info.store_path.to_absolute_path())?; + imports_span.pb_inc(1); + Ok(()) + } + Err(e) => { + warn!(?path, err=%e, "failed to import"); + Err(e) } } - }) + }.instrument(info_span!("import path", "indicatif.pb_show" = tracing::field::Empty)) }) - .collect::<Vec<_>>(); - - try_join_all(tasks).await?; + .buffer_unordered(50) + .try_collect::<()>() + .await?; } Commands::Copy { - blob_service_addr, - directory_service_addr, - path_info_service_addr, + service_addrs, reference_graph_path, } => { - let (blob_service, directory_service, path_info_service) = - tvix_store::utils::construct_services( - blob_service_addr, - directory_service_addr, - path_info_service_addr, - ) - .await?; + let (blob_service, directory_service, path_info_service, _nar_calculation_service) = + tvix_store::utils::construct_services(service_addrs).await?; // Parse the file at reference_graph_path. let reference_graph_json = tokio::fs::read(&reference_graph_path).await?; @@ -403,18 +361,26 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { let reference_graph: ReferenceGraph<'_> = serde_json::from_slice(reference_graph_json.as_slice())?; - // Arc the PathInfoService, as we clone it . - let path_info_service: Arc<dyn PathInfoService> = path_info_service.into(); + let lookups_span = info_span!( + "lookup pathinfos", + "indicatif.pb_show" = tracing::field::Empty + ); + lookups_span.pb_set_length(reference_graph.closure.len() as u64); + lookups_span.pb_set_style(&tvix_tracing::PB_PROGRESS_STYLE); + lookups_span.pb_start(); // From our reference graph, lookup all pathinfos that might exist. let elems: Vec<_> = futures::stream::iter(reference_graph.closure) .map(|elem| { let path_info_service = path_info_service.clone(); async move { - path_info_service + let resp = path_info_service .get(*elem.path.digest()) .await - .map(|resp| (elem, resp)) + .map(|resp| (elem, resp)); + + Span::current().pb_inc(1); + resp } }) .buffer_unordered(50) @@ -439,10 +405,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { async move { // Ingest the given path. - ingest_path( + ingest_path::<_, _, _, &[u8]>( blob_service, directory_service, PathBuf::from(elem.path.to_absolute_path()), + None, ) .await .map(|root_node| (elem, root_node)) @@ -458,22 +425,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { // Create and upload a PathInfo pointing to the root_node, // annotated with information we have from the reference graph. let path_info = PathInfo { - node: Some(tvix_castore::proto::Node { - node: Some(root_node), - }), - references: Vec::from_iter( - elem.references.iter().map(|e| e.digest().to_vec().into()), - ), - narinfo: Some(NarInfo { - nar_size: elem.nar_size, - nar_sha256: elem.nar_sha256.to_vec().into(), - signatures: vec![], - reference_names: Vec::from_iter( - elem.references.iter().map(|e| e.to_string()), - ), - deriver: None, - ca: None, - }), + store_path: elem.path.to_owned(), + node: root_node, + references: elem.references.iter().map(StorePath::to_owned).collect(), + nar_size: elem.nar_size, + nar_sha256: elem.nar_sha256, + signatures: vec![], + deriver: None, + ca: None, }; path_info_service.put(path_info).await?; @@ -482,27 +441,20 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { #[cfg(feature = "fuse")] Commands::Mount { dest, - blob_service_addr, - directory_service_addr, - path_info_service_addr, + service_addrs, list_root, threads, allow_other, show_xattr, } => { - let (blob_service, directory_service, path_info_service) = - tvix_store::utils::construct_services( - blob_service_addr, - directory_service_addr, - path_info_service_addr, - ) - .await?; + let (blob_service, directory_service, path_info_service, _nar_calculation_service) = + tvix_store::utils::construct_services(service_addrs).await?; - let mut fuse_daemon = tokio::task::spawn_blocking(move || { + let fuse_daemon = tokio::task::spawn_blocking(move || { let fs = make_fs( blob_service, directory_service, - Arc::from(path_info_service), + path_info_service, list_root, show_xattr, ); @@ -512,39 +464,38 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { }) .await??; - // grab a handle to unmount the file system, and register a signal - // handler. - tokio::spawn(async move { - tokio::signal::ctrl_c().await.unwrap(); - info!("interrupt received, unmounting…"); - tokio::task::spawn_blocking(move || fuse_daemon.unmount()).await??; - info!("unmount occured, terminating…"); - Ok::<_, std::io::Error>(()) - }) - .await??; + // Wait for a ctrl_c and then call fuse_daemon.unmount(). + tokio::spawn({ + let fuse_daemon = fuse_daemon.clone(); + async move { + tokio::signal::ctrl_c().await.unwrap(); + info!("interrupt received, unmounting…"); + tokio::task::spawn_blocking(move || fuse_daemon.unmount()).await??; + info!("unmount occured, terminating…"); + Ok::<_, std::io::Error>(()) + } + }); + + // Wait for the server to finish, which can either happen through it + // being unmounted externally, or receiving a signal invoking the + // handler above. + tokio::task::spawn_blocking(move || fuse_daemon.wait()).await? } #[cfg(feature = "virtiofs")] Commands::VirtioFs { socket, - blob_service_addr, - directory_service_addr, - path_info_service_addr, + service_addrs, list_root, show_xattr, } => { - let (blob_service, directory_service, path_info_service) = - tvix_store::utils::construct_services( - blob_service_addr, - directory_service_addr, - path_info_service_addr, - ) - .await?; + let (blob_service, directory_service, path_info_service, _nar_calculation_service) = + tvix_store::utils::construct_services(service_addrs).await?; tokio::task::spawn_blocking(move || { let fs = make_fs( blob_service, directory_service, - Arc::from(path_info_service), + path_info_service, list_root, show_xattr, ); @@ -557,3 +508,36 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { }; Ok(()) } + +#[tokio::main] +async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { + let cli = Cli::parse(); + + let tracing_handle = { + let mut builder = tvix_tracing::TracingBuilder::default(); + builder = builder.enable_progressbar(); + #[cfg(feature = "otlp")] + { + if cli.otlp { + builder = builder.enable_otlp("tvix.store"); + } + } + builder.build()? + }; + + tokio::select! { + res = tokio::signal::ctrl_c() => { + res?; + if let Err(e) = tracing_handle.force_shutdown().await { + eprintln!("failed to shutdown tracing: {e}"); + } + Ok(()) + }, + res = run_cli(cli, tracing_handle.clone()) => { + if let Err(e) = tracing_handle.shutdown().await { + eprintln!("failed to shutdown tracing: {e}"); + } + res + } + } +} diff --git a/tvix/store/src/composition.rs b/tvix/store/src/composition.rs new file mode 100644 index 000000000000..063236136fd1 --- /dev/null +++ b/tvix/store/src/composition.rs @@ -0,0 +1,21 @@ +use std::sync::LazyLock; + +pub use tvix_castore::composition::*; + +/// The provided registry of tvix_store, which has all the builtin +/// tvix_castore (BlobStore/DirectoryStore) and tvix_store +/// (PathInfoService) implementations. +pub static REG: LazyLock<&'static Registry> = LazyLock::new(|| { + let mut reg = Default::default(); + add_default_services(&mut reg); + // explicitly leak to get an &'static, so that we gain `&Registry: Send` from `Registry: Sync` + Box::leak(Box::new(reg)) +}); + +/// Register the builtin services of tvix_castore and tvix_store with the given +/// registry. This is useful for creating your own registry with the builtin +/// types _and_ extra third party types. +pub fn add_default_services(reg: &mut Registry) { + tvix_castore::composition::add_default_services(reg); + crate::pathinfoservice::register_pathinfo_services(reg); +} diff --git a/tvix/store/src/import.rs b/tvix/store/src/import.rs index 7b6aeb824ea6..4c1bd51eeb61 100644 --- a/tvix/store/src/import.rs +++ b/tvix/store/src/import.rs @@ -1,8 +1,8 @@ +use bstr::ByteSlice; use std::path::Path; use tracing::{debug, instrument}; use tvix_castore::{ - blobservice::BlobService, directoryservice::DirectoryService, import::fs::ingest_path, - proto::node::Node, B3Digest, + blobservice::BlobService, directoryservice::DirectoryService, import::fs::ingest_path, Node, }; use nix_compat::{ @@ -11,8 +11,9 @@ use nix_compat::{ }; use crate::{ - pathinfoservice::PathInfoService, - proto::{nar_info, NarInfo, PathInfo}, + nar::NarCalculationService, + pathinfoservice::{PathInfo, PathInfoService}, + proto::nar_info, }; impl From<CAHash> for nar_info::Ca { @@ -26,29 +27,29 @@ impl From<CAHash> for nar_info::Ca { } } -pub fn log_node(node: &Node, path: &Path) { +pub fn log_node(name: &[u8], node: &Node, path: &Path) { match node { - Node::Directory(directory_node) => { + Node::Directory { digest, .. } => { debug!( path = ?path, - name = ?directory_node.name, - digest = %B3Digest::try_from(directory_node.digest.clone()).unwrap(), + name = %name.as_bstr(), + digest = %digest, "import successful", ) } - Node::File(file_node) => { + Node::File { digest, .. } => { debug!( path = ?path, - name = ?file_node.name, - digest = %B3Digest::try_from(file_node.digest.clone()).unwrap(), + name = %name.as_bstr(), + digest = %digest, "import successful" ) } - Node::Symlink(symlink_node) => { + Node::Symlink { target } => { debug!( path = ?path, - name = ?symlink_node.name, - target = ?symlink_node.target, + name = %name.as_bstr(), + target = ?target, "import successful" ) } @@ -69,86 +70,63 @@ pub fn path_to_name(path: &Path) -> std::io::Result<&str> { }) } -/// Takes the NAR size, SHA-256 of the NAR representation, the root node and optionally -/// a CA hash information. -/// -/// Returns the path information object for a NAR-style object. -/// -/// This [`PathInfo`] can be further filled for signatures, deriver or verified for the expected -/// hashes. -#[inline] -pub fn derive_nar_ca_path_info( - nar_size: u64, - nar_sha256: [u8; 32], - ca: Option<CAHash>, - root_node: Node, -) -> PathInfo { - // assemble the [crate::proto::PathInfo] object. - PathInfo { - node: Some(tvix_castore::proto::Node { - node: Some(root_node), - }), - // There's no reference scanning on path contents ingested like this. - references: vec![], - narinfo: Some(NarInfo { - nar_size, - nar_sha256: nar_sha256.to_vec().into(), - signatures: vec![], - reference_names: vec![], - deriver: None, - ca: ca.map(|ca_hash| ca_hash.into()), - }), - } -} - -/// Ingest the given path `path` and register the resulting output path in the -/// [`PathInfoService`] as a recursive fixed output NAR. +/// Ingest the contents at the given path `path` into castore, and registers the +/// resulting root node in the passed PathInfoService, using the "NAR sha256 +/// digest" and the passed name for output path calculation. +/// Inserts the PathInfo into the PathInfoService and returns it back to the caller. #[instrument(skip_all, fields(store_name=name, path=?path), err)] -pub async fn import_path_as_nar_ca<BS, DS, PS, P>( +pub async fn import_path_as_nar_ca<BS, DS, PS, NS, P>( path: P, name: &str, blob_service: BS, directory_service: DS, path_info_service: PS, -) -> Result<StorePath, std::io::Error> + nar_calculation_service: NS, +) -> Result<PathInfo, std::io::Error> where P: AsRef<Path> + std::fmt::Debug, BS: BlobService + Clone, - DS: AsRef<dyn DirectoryService>, + DS: DirectoryService, PS: AsRef<dyn PathInfoService>, + NS: NarCalculationService, { - let root_node = ingest_path(blob_service, directory_service, path.as_ref()).await?; + // Ingest the contents at the given path `path` into castore. + let root_node = + ingest_path::<_, _, _, &[u8]>(blob_service, directory_service, path.as_ref(), None) + .await + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - // Ask the PathInfoService for the NAR size and sha256 - let (nar_size, nar_sha256) = path_info_service.as_ref().calculate_nar(&root_node).await?; + // Ask for the NAR size and sha256 + let (nar_size, nar_sha256) = nar_calculation_service.calculate_nar(&root_node).await?; + + let ca = CAHash::Nar(NixHash::Sha256(nar_sha256)); // Calculate the output path. This might still fail, as some names are illegal. // FUTUREWORK: express the `name` at the type level to be valid and move the conversion // at the caller level. - let output_path = store_path::build_nar_based_store_path(&nar_sha256, name).map_err(|_| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("invalid name: {}", name), - ) - })?; - - // assemble a new root_node with a name that is derived from the nar hash. - let root_node = root_node.rename(output_path.to_string().into_bytes().into()); - log_node(&root_node, path.as_ref()); - - let path_info = derive_nar_ca_path_info( - nar_size, - nar_sha256, - Some(CAHash::Nar(NixHash::Sha256(nar_sha256))), - root_node, - ); - - // This new [`PathInfo`] that we get back from there might contain additional signatures or - // information set by the service itself. In this function, we silently swallow it because - // callers doesn't really need it. - let _path_info = path_info_service.as_ref().put(path_info).await?; - - Ok(output_path.to_owned()) + let output_path: StorePath<String> = + store_path::build_ca_path(name, &ca, std::iter::empty::<&str>(), false).map_err(|_| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("invalid name: {}", name), + ) + })?; + + // Insert a PathInfo. On success, return it back to the caller. + Ok(path_info_service + .as_ref() + .put(PathInfo { + store_path: output_path.to_owned(), + node: root_node, + // There's no reference scanning on imported paths + references: vec![], + nar_size, + nar_sha256, + signatures: vec![], + deriver: None, + ca: Some(ca), + }) + .await?) } #[cfg(test)] diff --git a/tvix/store/src/lib.rs b/tvix/store/src/lib.rs index 8c32aaf885e8..e1517609d51c 100644 --- a/tvix/store/src/lib.rs +++ b/tvix/store/src/lib.rs @@ -1,5 +1,7 @@ +pub mod composition; pub mod import; pub mod nar; +pub mod path_info; pub mod pathinfoservice; pub mod proto; pub mod utils; diff --git a/tvix/store/src/nar/import.rs b/tvix/store/src/nar/import.rs index 6f4dcdea5d96..b9a15fe71384 100644 --- a/tvix/store/src/nar/import.rs +++ b/tvix/store/src/nar/import.rs @@ -1,225 +1,168 @@ -use bytes::Bytes; -use nix_compat::nar; -use std::io::{self, BufRead}; -use tokio_util::io::SyncIoBridge; -use tracing::warn; +use nix_compat::nar::reader::r#async as nar_reader; +use sha2::Digest; +use tokio::{ + io::{AsyncBufRead, AsyncRead}, + sync::mpsc, + try_join, +}; use tvix_castore::{ blobservice::BlobService, - directoryservice::{DirectoryPutter, DirectoryService}, - proto::{self as castorepb}, - B3Digest, + directoryservice::DirectoryService, + import::{ + blobs::{self, ConcurrentBlobUploader}, + ingest_entries, IngestionEntry, IngestionError, + }, + Node, PathBuf, }; -/// Accepts a reader providing a NAR. -/// Will traverse it, uploading blobs to the given [BlobService], and -/// directories to the given [DirectoryService]. -/// On success, the root node is returned. -/// This function is not async (because the NAR reader is not) -/// and calls [tokio::task::block_in_place] when interacting with backing -/// services, so make sure to only call this with spawn_blocking. -pub fn read_nar<R, BS, DS>( - r: &mut R, +/// Ingests the contents from a [AsyncRead] providing NAR into the tvix store, +/// interacting with a [BlobService] and [DirectoryService]. +/// Returns the castore root node, as well as the sha256 and size of the NAR +/// contents ingested. +pub async fn ingest_nar_and_hash<R, BS, DS>( blob_service: BS, directory_service: DS, -) -> io::Result<castorepb::node::Node> + r: &mut R, +) -> Result<(Node, [u8; 32], u64), IngestionError<Error>> where - R: BufRead + Send, - BS: AsRef<dyn BlobService>, - DS: AsRef<dyn DirectoryService>, + R: AsyncRead + Unpin + Send, + BS: BlobService + Clone + 'static, + DS: DirectoryService, { - let handle = tokio::runtime::Handle::current(); - - let directory_putter = directory_service.as_ref().put_multiple_start(); - - let node = nix_compat::nar::reader::open(r)?; - let (root_node, mut directory_putter, _) = process_node( - handle.clone(), - "".into(), // this is the root node, it has an empty name - node, - &blob_service, - directory_putter, - )?; - - // In case the root node points to a directory, we need to close - // [directory_putter], and ensure the digest we got back from there matches - // what the root node is pointing to. - if let castorepb::node::Node::Directory(ref directory_node) = root_node { - // Close directory_putter to make sure all directories have been inserted. - let directory_putter_digest = - handle.block_on(handle.spawn(async move { directory_putter.close().await }))??; - let root_directory_node_digest: B3Digest = - directory_node.digest.clone().try_into().unwrap(); - - if directory_putter_digest != root_directory_node_digest { - warn!( - root_directory_node_digest = %root_directory_node_digest, - directory_putter_digest =%directory_putter_digest, - "directory digest mismatch", - ); - return Err(io::Error::new( - io::ErrorKind::Other, - "directory digest mismatch", - )); - } - } - // In case it's not a Directory, [directory_putter] doesn't need to be - // closed (as we didn't end up uploading anything). - // It can just be dropped, as documented in its trait. + let mut nar_hash = sha2::Sha256::new(); + let mut nar_size = 0; - Ok(root_node) -} + // Assemble NarHash and NarSize as we read bytes. + let r = tokio_util::io::InspectReader::new(r, |b| { + nar_size += b.len() as u64; + use std::io::Write; + nar_hash.write_all(b).unwrap(); + }); -/// This is called on a [nar::reader::Node] and returns a [castorepb::node::Node]. -/// It does so by handling all three kinds, and recursing for directories. -/// -/// [DirectoryPutter] is passed around, so a single instance of it can be used, -/// which is sufficient, as this reads through the whole NAR linerarly. -fn process_node<BS>( - handle: tokio::runtime::Handle, - name: bytes::Bytes, - node: nar::reader::Node, - blob_service: BS, - directory_putter: Box<dyn DirectoryPutter>, -) -> io::Result<(castorepb::node::Node, Box<dyn DirectoryPutter>, BS)> -where - BS: AsRef<dyn BlobService>, -{ - Ok(match node { - nar::reader::Node::Symlink { target } => ( - castorepb::node::Node::Symlink(castorepb::SymlinkNode { - name, - target: target.into(), - }), - directory_putter, - blob_service, - ), - nar::reader::Node::File { executable, reader } => ( - castorepb::node::Node::File(process_file_reader( - handle, - name, - reader, - executable, - &blob_service, - )?), - directory_putter, - blob_service, - ), - nar::reader::Node::Directory(dir_reader) => { - let (directory_node, directory_putter, blob_service_back) = - process_dir_reader(handle, name, dir_reader, blob_service, directory_putter)?; - - ( - castorepb::node::Node::Directory(directory_node), - directory_putter, - blob_service_back, - ) - } - }) + // HACK: InspectReader doesn't implement AsyncBufRead. + // See if this can be propagated through and we can then require our input + // reader to be buffered too. + let mut r = tokio::io::BufReader::new(r); + + let root_node = ingest_nar(blob_service, directory_service, &mut r).await?; + + Ok((root_node, nar_hash.finalize().into(), nar_size)) } -/// Given a name and [nar::reader::FileReader], this ingests the file into the -/// passed [BlobService] and returns a [castorepb::FileNode]. -fn process_file_reader<BS>( - handle: tokio::runtime::Handle, - name: Bytes, - mut file_reader: nar::reader::FileReader, - executable: bool, +/// Ingests the contents from a [AsyncRead] providing NAR into the tvix store, +/// interacting with a [BlobService] and [DirectoryService]. +/// It returns the castore root node or an error. +pub async fn ingest_nar<R, BS, DS>( blob_service: BS, -) -> io::Result<castorepb::FileNode> + directory_service: DS, + r: &mut R, +) -> Result<Node, IngestionError<Error>> where - BS: AsRef<dyn BlobService>, + R: AsyncBufRead + Unpin + Send, + BS: BlobService + Clone + 'static, + DS: DirectoryService, { - // store the length. If we read any other length, reading will fail. - let expected_len = file_reader.len(); + // open the NAR for reading. + // The NAR reader emits nodes in DFS preorder. + let root_node = nar_reader::open(r).await.map_err(Error::IO)?; + + let (tx, rx) = mpsc::channel(1); + let rx = tokio_stream::wrappers::ReceiverStream::new(rx); - // prepare writing a new blob. - let blob_writer = handle.block_on(async { blob_service.as_ref().open_write().await }); + let produce = async move { + let mut blob_uploader = ConcurrentBlobUploader::new(blob_service); - // write the blob. - let mut blob_writer = { - let mut dst = SyncIoBridge::new(blob_writer); + let res = produce_nar_inner( + &mut blob_uploader, + root_node, + "root".parse().unwrap(), // HACK: the root node sent to ingest_entries may not be ROOT. + tx.clone(), + ) + .await; + + if let Err(err) = blob_uploader.join().await { + tx.send(Err(err.into())) + .await + .map_err(|e| Error::IO(std::io::Error::new(std::io::ErrorKind::BrokenPipe, e)))?; + } - file_reader.copy(&mut dst)?; - dst.shutdown()?; + tx.send(res) + .await + .map_err(|e| Error::IO(std::io::Error::new(std::io::ErrorKind::BrokenPipe, e)))?; - // return back the blob_writer - dst.into_inner() + Ok(()) }; - // close the blob_writer, retrieve the digest. - let blob_digest = handle.block_on(async { blob_writer.close().await })?; + let consume = ingest_entries(directory_service, rx); - Ok(castorepb::FileNode { - name, - digest: blob_digest.into(), - size: expected_len, - executable, - }) + let (_, node) = try_join!(produce, consume)?; + + Ok(node) } -/// Given a name and [nar::reader::DirReader], this returns a [castorepb::DirectoryNode]. -/// It uses [process_node] to iterate over all children. -/// -/// [DirectoryPutter] is passed around, so a single instance of it can be used, -/// which is sufficient, as this reads through the whole NAR linerarly. -fn process_dir_reader<BS>( - handle: tokio::runtime::Handle, - name: Bytes, - mut dir_reader: nar::reader::DirReader, - blob_service: BS, - directory_putter: Box<dyn DirectoryPutter>, -) -> io::Result<(castorepb::DirectoryNode, Box<dyn DirectoryPutter>, BS)> +async fn produce_nar_inner<BS>( + blob_uploader: &mut ConcurrentBlobUploader<BS>, + node: nar_reader::Node<'_, '_>, + path: PathBuf, + tx: mpsc::Sender<Result<IngestionEntry, Error>>, +) -> Result<IngestionEntry, Error> where - BS: AsRef<dyn BlobService>, + BS: BlobService + Clone + 'static, { - let mut directory = castorepb::Directory::default(); - - let mut directory_putter = directory_putter; - let mut blob_service = blob_service; - while let Some(entry) = dir_reader.next()? { - let (node, directory_putter_back, blob_service_back) = process_node( - handle.clone(), - entry.name.into(), - entry.node, - blob_service, - directory_putter, - )?; - - blob_service = blob_service_back; - directory_putter = directory_putter_back; - - match node { - castorepb::node::Node::Directory(node) => directory.directories.push(node), - castorepb::node::Node::File(node) => directory.files.push(node), - castorepb::node::Node::Symlink(node) => directory.symlinks.push(node), + Ok(match node { + nar_reader::Node::Symlink { target } => IngestionEntry::Symlink { path, target }, + nar_reader::Node::File { + executable, + mut reader, + } => { + let size = reader.len(); + let digest = blob_uploader.upload(&path, size, &mut reader).await?; + + IngestionEntry::Regular { + path, + size, + executable, + digest, + } } - } + nar_reader::Node::Directory(mut dir_reader) => { + while let Some(entry) = dir_reader.next().await? { + let mut path = path.clone(); + + // valid NAR names are valid castore names + path.try_push(entry.name) + .expect("Tvix bug: failed to join name"); + + let entry = Box::pin(produce_nar_inner( + blob_uploader, + entry.node, + path, + tx.clone(), + )) + .await?; + + tx.send(Ok(entry)).await.map_err(|e| { + Error::IO(std::io::Error::new(std::io::ErrorKind::BrokenPipe, e)) + })?; + } + + IngestionEntry::Dir { path } + } + }) +} - // calculate digest and size. - let directory_digest = directory.digest(); - let directory_size = directory.size(); - - // upload the directory. This is a bit more verbose, as we want to get back - // directory_putter for later reuse. - let directory_putter = handle.block_on(handle.spawn(async move { - directory_putter.put(directory).await?; - Ok::<_, io::Error>(directory_putter) - }))??; - - Ok(( - castorepb::DirectoryNode { - name, - digest: directory_digest.into(), - size: directory_size, - }, - directory_putter, - blob_service, - )) +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error(transparent)] + IO(#[from] std::io::Error), + + #[error(transparent)] + BlobUpload(#[from] blobs::Error), } #[cfg(test)] mod test { - use crate::nar::read_nar; + use crate::nar::ingest_nar; use std::io::Cursor; use std::sync::Arc; @@ -231,7 +174,7 @@ mod test { DIRECTORY_COMPLICATED, DIRECTORY_WITH_KEEP, EMPTY_BLOB_DIGEST, HELLOWORLD_BLOB_CONTENTS, HELLOWORLD_BLOB_DIGEST, }; - use tvix_castore::proto as castorepb; + use tvix_castore::{Directory, Node}; use crate::tests::fixtures::{ blob_service, directory_service, NAR_CONTENTS_COMPLICATED, NAR_CONTENTS_HELLOWORLD, @@ -244,25 +187,18 @@ mod test { blob_service: Arc<dyn BlobService>, directory_service: Arc<dyn DirectoryService>, ) { - let handle = tokio::runtime::Handle::current(); - - let root_node = handle - .spawn_blocking(|| { - read_nar( - &mut Cursor::new(&NAR_CONTENTS_SYMLINK.clone()), - blob_service, - directory_service, - ) - }) - .await - .unwrap() - .expect("must parse"); + let root_node = ingest_nar( + blob_service, + directory_service, + &mut Cursor::new(&NAR_CONTENTS_SYMLINK.clone()), + ) + .await + .expect("must parse"); assert_eq!( - castorepb::node::Node::Symlink(castorepb::SymlinkNode { - name: "".into(), // name must be empty - target: "/nix/store/somewhereelse".into(), - }), + Node::Symlink { + target: "/nix/store/somewhereelse".try_into().unwrap() + }, root_node ); } @@ -273,30 +209,20 @@ mod test { blob_service: Arc<dyn BlobService>, directory_service: Arc<dyn DirectoryService>, ) { - let handle = tokio::runtime::Handle::current(); - - let root_node = handle - .spawn_blocking({ - let blob_service = blob_service.clone(); - move || { - read_nar( - &mut Cursor::new(&NAR_CONTENTS_HELLOWORLD.clone()), - blob_service, - directory_service, - ) - } - }) - .await - .unwrap() - .expect("must parse"); + let root_node = ingest_nar( + blob_service.clone(), + directory_service, + &mut Cursor::new(&NAR_CONTENTS_HELLOWORLD.clone()), + ) + .await + .expect("must parse"); assert_eq!( - castorepb::node::Node::File(castorepb::FileNode { - name: "".into(), // name must be empty - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), + Node::File { + digest: HELLOWORLD_BLOB_DIGEST.clone(), size: HELLOWORLD_BLOB_CONTENTS.len() as u64, executable: false, - }), + }, root_node ); @@ -310,30 +236,19 @@ mod test { blob_service: Arc<dyn BlobService>, directory_service: Arc<dyn DirectoryService>, ) { - let handle = tokio::runtime::Handle::current(); - - let root_node = handle - .spawn_blocking({ - let blob_service = blob_service.clone(); - let directory_service = directory_service.clone(); - || { - read_nar( - &mut Cursor::new(&NAR_CONTENTS_COMPLICATED.clone()), - blob_service, - directory_service, - ) - } - }) - .await - .unwrap() - .expect("must parse"); + let root_node = ingest_nar( + blob_service.clone(), + directory_service.clone(), + &mut Cursor::new(&NAR_CONTENTS_COMPLICATED.clone()), + ) + .await + .expect("must parse"); assert_eq!( - castorepb::node::Node::Directory(castorepb::DirectoryNode { - name: "".into(), // name must be empty - digest: DIRECTORY_COMPLICATED.digest().into(), - size: DIRECTORY_COMPLICATED.size(), - }), + Node::Directory { + digest: DIRECTORY_COMPLICATED.digest(), + size: DIRECTORY_COMPLICATED.size() + }, root_node, ); @@ -341,7 +256,7 @@ mod test { assert!(blob_service.has(&EMPTY_BLOB_DIGEST).await.unwrap()); // directoryservice must contain the directories, at least with get_recursive. - let resp: Result<Vec<castorepb::Directory>, _> = directory_service + let resp: Result<Vec<Directory>, _> = directory_service .get_recursive(&DIRECTORY_COMPLICATED.digest()) .collect() .await; diff --git a/tvix/store/src/nar/mod.rs b/tvix/store/src/nar/mod.rs index 49bb92fb0f0f..86505bcb0c07 100644 --- a/tvix/store/src/nar/mod.rs +++ b/tvix/store/src/nar/mod.rs @@ -1,10 +1,36 @@ +use tonic::async_trait; use tvix_castore::B3Digest; mod import; mod renderer; -pub use import::read_nar; +pub mod seekable; +pub use import::ingest_nar; +pub use import::ingest_nar_and_hash; pub use renderer::calculate_size_and_sha256; pub use renderer::write_nar; +pub use renderer::SimpleRenderer; +use tvix_castore::Node; + +#[async_trait] +pub trait NarCalculationService: Send + Sync { + /// Return the nar size and nar sha256 digest for a given root node. + /// This can be used to calculate NAR-based output paths. + async fn calculate_nar(&self, root_node: &Node) + -> Result<(u64, [u8; 32]), tvix_castore::Error>; +} + +#[async_trait] +impl<A> NarCalculationService for A +where + A: AsRef<dyn NarCalculationService> + Send + Sync, +{ + async fn calculate_nar( + &self, + root_node: &Node, + ) -> Result<(u64, [u8; 32]), tvix_castore::Error> { + self.as_ref().calculate_nar(root_node).await + } +} /// Errors that can encounter while rendering NARs. #[derive(Debug, thiserror::Error)] @@ -12,13 +38,13 @@ pub enum RenderError { #[error("failure talking to a backing store client: {0}")] StoreError(#[source] std::io::Error), - #[error("unable to find directory {}, referred from {:?}", .0, .1)] + #[error("unable to find directory {0}, referred from {1:?}")] DirectoryNotFound(B3Digest, bytes::Bytes), - #[error("unable to find blob {}, referred from {:?}", .0, .1)] + #[error("unable to find blob {0}, referred from {1:?}")] BlobNotFound(B3Digest, bytes::Bytes), - #[error("unexpected size in metadata for blob {}, referred from {:?} returned, expected {}, got {}", .0, .1, .2, .3)] + #[error("unexpected size in metadata for blob {0}, referred from {1:?} returned, expected {2}, got {3}")] UnexpectedBlobMeta(B3Digest, bytes::Bytes, u32, u32), #[error("failure using the NAR writer: {0}")] diff --git a/tvix/store/src/nar/renderer.rs b/tvix/store/src/nar/renderer.rs index 0816b8e973c7..07cdc4b1e31f 100644 --- a/tvix/store/src/nar/renderer.rs +++ b/tvix/store/src/nar/renderer.rs @@ -1,21 +1,53 @@ use crate::utils::AsyncIoBridge; -use super::RenderError; -use async_recursion::async_recursion; +use super::{NarCalculationService, RenderError}; use count_write::CountWrite; use nix_compat::nar::writer::r#async as nar_writer; use sha2::{Digest, Sha256}; use tokio::io::{self, AsyncWrite, BufReader}; -use tvix_castore::{ - blobservice::BlobService, - directoryservice::DirectoryService, - proto::{self as castorepb, NamedNode}, -}; +use tonic::async_trait; +use tracing::instrument; +use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService, Node}; + +pub struct SimpleRenderer<BS, DS> { + blob_service: BS, + directory_service: DS, +} + +impl<BS, DS> SimpleRenderer<BS, DS> { + pub fn new(blob_service: BS, directory_service: DS) -> Self { + Self { + blob_service, + directory_service, + } + } +} + +#[async_trait] +impl<BS, DS> NarCalculationService for SimpleRenderer<BS, DS> +where + BS: BlobService + Clone, + DS: DirectoryService + Clone, +{ + async fn calculate_nar( + &self, + root_node: &Node, + ) -> Result<(u64, [u8; 32]), tvix_castore::Error> { + calculate_size_and_sha256( + root_node, + self.blob_service.clone(), + self.directory_service.clone(), + ) + .await + .map_err(|e| tvix_castore::Error::StorageError(format!("failed rendering nar: {}", e))) + } +} /// Invoke [write_nar], and return the size and sha256 digest of the produced /// NAR output. +#[instrument(skip_all)] pub async fn calculate_size_and_sha256<BS, DS>( - root_node: &castorepb::node::Node, + root_node: &Node, blob_service: BS, directory_service: DS, ) -> Result<(u64, [u8; 32]), RenderError> @@ -39,13 +71,13 @@ where Ok((cw.count(), h.finalize().into())) } -/// Accepts a [castorepb::node::Node] pointing to the root of a (store) path, +/// Accepts a [Node] pointing to the root of a (store) path, /// and uses the passed blob_service and directory_service to perform the /// necessary lookups as it traverses the structure. /// The contents in NAR serialization are writen to the passed [AsyncWrite]. pub async fn write_nar<W, BS, DS>( mut w: W, - proto_root_node: &castorepb::node::Node, + root_node: &Node, blob_service: BS, directory_service: DS, ) -> Result<(), RenderError> @@ -61,7 +93,8 @@ where walk_node( nar_root_node, - proto_root_node, + root_node, + b"", blob_service, directory_service, ) @@ -72,10 +105,10 @@ where /// Process an intermediate node in the structure. /// This consumes the node. -#[async_recursion] async fn walk_node<BS, DS>( - nar_node: nar_writer::Node<'async_recursion, '_>, - proto_node: &castorepb::node::Node, + nar_node: nar_writer::Node<'_, '_>, + castore_node: &Node, + name: &[u8], blob_service: BS, directory_service: DS, ) -> Result<(BS, DS), RenderError> @@ -83,24 +116,20 @@ where BS: BlobService + Send, DS: DirectoryService + Send, { - match proto_node { - castorepb::node::Node::Symlink(proto_symlink_node) => { + match castore_node { + Node::Symlink { target, .. } => { nar_node - .symlink(&proto_symlink_node.target) + .symlink(target.as_ref()) .await .map_err(RenderError::NARWriterError)?; } - castorepb::node::Node::File(proto_file_node) => { - let digest_len = proto_file_node.digest.len(); - let digest = proto_file_node.digest.clone().try_into().map_err(|_| { - RenderError::StoreError(io::Error::new( - io::ErrorKind::Other, - format!("invalid digest len {} in file node", digest_len), - )) - })?; - + Node::File { + digest, + size, + executable, + } => { let mut blob_reader = match blob_service - .open_read(&digest) + .open_read(digest) .await .map_err(RenderError::StoreError)? { @@ -112,39 +141,23 @@ where }?; nar_node - .file( - proto_file_node.executable, - proto_file_node.size, - &mut blob_reader, - ) + .file(*executable, *size, &mut blob_reader) .await .map_err(RenderError::NARWriterError)?; } - castorepb::node::Node::Directory(proto_directory_node) => { - let digest_len = proto_directory_node.digest.len(); - let digest = proto_directory_node - .digest - .clone() - .try_into() - .map_err(|_| { - RenderError::StoreError(io::Error::new( - io::ErrorKind::InvalidData, - format!("invalid digest len {} in directory node", digest_len), - )) - })?; - + Node::Directory { digest, .. } => { // look it up with the directory service match directory_service - .get(&digest) + .get(digest) .await .map_err(|e| RenderError::StoreError(e.into()))? { // if it's None, that's an error! None => Err(RenderError::DirectoryNotFound( - digest, - proto_directory_node.name.clone(), + digest.clone(), + bytes::Bytes::copy_from_slice(name), ))?, - Some(proto_directory) => { + Some(directory) => { // start a directory node let mut nar_node_directory = nar_node .directory() @@ -158,15 +171,20 @@ where // for each node in the directory, create a new entry with its name, // and then recurse on that entry. - for proto_node in proto_directory.nodes() { + for (name, node) in directory.nodes() { let child_node = nar_node_directory - .entry(proto_node.get_name()) + .entry(name.as_ref()) .await .map_err(RenderError::NARWriterError)?; - (blob_service, directory_service) = - walk_node(child_node, &proto_node, blob_service, directory_service) - .await?; + (blob_service, directory_service) = Box::pin(walk_node( + child_node, + node, + name.as_ref(), + blob_service, + directory_service, + )) + .await?; } // close the directory diff --git a/tvix/store/src/nar/seekable.rs b/tvix/store/src/nar/seekable.rs new file mode 100644 index 000000000000..951c1dfc0198 --- /dev/null +++ b/tvix/store/src/nar/seekable.rs @@ -0,0 +1,422 @@ +use std::{ + cmp::min, + io, + pin::Pin, + sync::Arc, + task::{Context, Poll}, +}; + +use super::RenderError; + +use bytes::{BufMut, Bytes}; + +use nix_compat::nar::writer::sync as nar_writer; +use tvix_castore::blobservice::{BlobReader, BlobService}; +use tvix_castore::directoryservice::{ + DirectoryGraph, DirectoryService, RootToLeavesValidator, ValidatedDirectoryGraph, +}; +use tvix_castore::Directory; +use tvix_castore::{B3Digest, Node}; + +use futures::future::{BoxFuture, FusedFuture, TryMaybeDone}; +use futures::FutureExt; +use futures::TryStreamExt; + +use tokio::io::AsyncSeekExt; + +#[derive(Debug)] +struct BlobRef { + digest: B3Digest, + size: u64, +} + +#[derive(Debug)] +enum Data { + Literal(Bytes), + Blob(BlobRef), +} + +impl Data { + pub fn len(&self) -> u64 { + match self { + Data::Literal(data) => data.len() as u64, + Data::Blob(BlobRef { size, .. }) => *size, + } + } +} + +pub struct Reader<B: BlobService> { + segments: Vec<(u64, Data)>, + position_bytes: u64, + position_index: usize, + blob_service: Arc<B>, + seeking: bool, + current_blob: TryMaybeDone<BoxFuture<'static, io::Result<Box<dyn BlobReader>>>>, +} + +/// Used during construction. +/// Converts the current buffer (passed as `cur_segment`) into a `Data::Literal` segment and +/// inserts it into `self.segments`. +fn flush_segment(segments: &mut Vec<(u64, Data)>, offset: &mut u64, cur_segment: Vec<u8>) { + let segment_size = cur_segment.len(); + segments.push((*offset, Data::Literal(cur_segment.into()))); + *offset += segment_size as u64; +} + +/// Used during construction. +/// Recursively walks the node and its children, and fills `segments` with the appropriate +/// `Data::Literal` and `Data::Blob` elements. +fn walk_node( + segments: &mut Vec<(u64, Data)>, + offset: &mut u64, + get_directory: &impl Fn(&B3Digest) -> Directory, + node: Node, + // Includes a reference to the current segment's buffer + nar_node: nar_writer::Node<'_, Vec<u8>>, +) -> Result<(), RenderError> { + match node { + tvix_castore::Node::Symlink { target } => { + nar_node + .symlink(target.as_ref()) + .map_err(RenderError::NARWriterError)?; + } + tvix_castore::Node::File { + digest, + size, + executable, + } => { + let (cur_segment, skip) = nar_node + .file_manual_write(executable, size) + .map_err(RenderError::NARWriterError)?; + + // Flush the segment up until the beginning of the blob + flush_segment(segments, offset, std::mem::take(cur_segment)); + + // Insert the blob segment + segments.push((*offset, Data::Blob(BlobRef { digest, size }))); + *offset += size; + + // Close the file node + // We **intentionally** do not write the file contents anywhere. + // Instead we have stored the blob reference in a Data::Blob segment, + // and the poll_read implementation will take care of serving the + // appropriate blob at this offset. + skip.close(cur_segment) + .map_err(RenderError::NARWriterError)?; + } + tvix_castore::Node::Directory { digest, .. } => { + let directory = get_directory(&digest); + + // start a directory node + let mut nar_node_directory = + nar_node.directory().map_err(RenderError::NARWriterError)?; + + // for each node in the directory, create a new entry with its name, + // and then recurse on that entry. + for (name, node) in directory.nodes() { + let child_node = nar_node_directory + .entry(name.as_ref()) + .map_err(RenderError::NARWriterError)?; + + walk_node(segments, offset, get_directory, node.clone(), child_node)?; + } + + // close the directory + nar_node_directory + .close() + .map_err(RenderError::NARWriterError)?; + } + } + Ok(()) +} + +impl<B: BlobService + 'static> Reader<B> { + /// Creates a new seekable NAR renderer for the given castore root node. + /// + /// This function pre-fetches the directory closure using `get_recursive()` and assembles the + /// NAR structure, except the file contents which are stored as 'holes' with references to a blob + /// of a specific BLAKE3 digest and known size. The AsyncRead implementation will then switch + /// between serving the precomputed literal segments, and the appropriate blob for the file + /// contents. + pub async fn new( + root_node: Node, + blob_service: B, + directory_service: impl DirectoryService, + ) -> Result<Self, RenderError> { + let maybe_directory_closure = match &root_node { + // If this is a directory, resolve all subdirectories + Node::Directory { digest, .. } => { + let mut closure = DirectoryGraph::with_order( + RootToLeavesValidator::new_with_root_digest(digest.clone()), + ); + let mut stream = directory_service.get_recursive(digest); + while let Some(dir) = stream + .try_next() + .await + .map_err(|e| RenderError::StoreError(e.into()))? + { + closure.add(dir).map_err(|e| { + RenderError::StoreError( + tvix_castore::Error::StorageError(e.to_string()).into(), + ) + })?; + } + Some(closure.validate().map_err(|e| { + RenderError::StoreError(tvix_castore::Error::StorageError(e.to_string()).into()) + })?) + } + // If the top-level node is a file or a symlink, just pass it on + Node::File { .. } => None, + Node::Symlink { .. } => None, + }; + + Self::new_with_directory_closure(root_node, blob_service, maybe_directory_closure) + } + + /// Creates a new seekable NAR renderer for the given castore root node. + /// This version of the instantiation does not perform any I/O and as such is not async. + /// However it requires all directories to be passed as a ValidatedDirectoryGraph. + /// + /// panics if the directory closure is not the closure of the root node + pub fn new_with_directory_closure( + root_node: Node, + blob_service: B, + directory_closure: Option<ValidatedDirectoryGraph>, + ) -> Result<Self, RenderError> { + let directories = directory_closure + .map(|directory_closure| { + let mut directories: Vec<(B3Digest, Directory)> = vec![]; + for dir in directory_closure.drain_root_to_leaves() { + let digest = dir.digest(); + let pos = directories + .binary_search_by_key(&digest.as_slice(), |(digest, _dir)| { + digest.as_slice() + }) + .expect_err("duplicate directory"); // DirectoryGraph checks this + directories.insert(pos, (digest, dir)); + } + directories + }) + .unwrap_or_default(); + + let mut segments = vec![]; + let mut cur_segment: Vec<u8> = vec![]; + let mut offset = 0; + + let nar_node = nar_writer::open(&mut cur_segment).map_err(RenderError::NARWriterError)?; + + walk_node( + &mut segments, + &mut offset, + &|digest| { + directories + .binary_search_by_key(&digest.as_slice(), |(digest, _dir)| digest.as_slice()) + .map(|pos| directories[pos].clone()) + .expect("missing directory") // DirectoryGraph checks this + .1 + }, + root_node, + nar_node, + )?; + // Flush the final segment + flush_segment(&mut segments, &mut offset, std::mem::take(&mut cur_segment)); + + Ok(Reader { + segments, + position_bytes: 0, + position_index: 0, + blob_service: blob_service.into(), + seeking: false, + current_blob: TryMaybeDone::Gone, + }) + } + + pub fn stream_len(&self) -> u64 { + self.segments + .last() + .map(|&(off, ref data)| off + data.len()) + .expect("no segment found") + } +} + +impl<B: BlobService + 'static> tokio::io::AsyncSeek for Reader<B> { + fn start_seek(mut self: Pin<&mut Self>, pos: io::SeekFrom) -> io::Result<()> { + let stream_len = Reader::stream_len(&self); + + let this = &mut *self; + if this.seeking { + return Err(io::Error::new(io::ErrorKind::Other, "Already seeking")); + } + this.seeking = true; + + // TODO(edef): be sane about overflows + let pos = match pos { + io::SeekFrom::Start(n) => n, + io::SeekFrom::End(n) => (stream_len as i64 + n) as u64, + io::SeekFrom::Current(n) => (this.position_bytes as i64 + n) as u64, + }; + + let prev_position_bytes = this.position_bytes; + let prev_position_index = this.position_index; + + this.position_bytes = min(pos, stream_len); + this.position_index = match this + .segments + .binary_search_by_key(&this.position_bytes, |&(off, _)| off) + { + Ok(idx) => idx, + Err(idx) => idx - 1, + }; + + let Some((offset, Data::Blob(BlobRef { digest, .. }))) = + this.segments.get(this.position_index) + else { + // If not seeking into a blob, we clear the active blob reader and then we're done + this.current_blob = TryMaybeDone::Gone; + return Ok(()); + }; + let offset_in_segment = this.position_bytes - offset; + + if prev_position_bytes == this.position_bytes { + // position has not changed. do nothing + } else if prev_position_index == this.position_index { + // seeking within the same segment, re-use the blob reader + let mut prev = std::mem::replace(&mut this.current_blob, TryMaybeDone::Gone); + this.current_blob = futures::future::try_maybe_done( + (async move { + let mut reader = Pin::new(&mut prev).take_output().unwrap(); + reader.seek(io::SeekFrom::Start(offset_in_segment)).await?; + Ok(reader) + }) + .boxed(), + ); + } else { + // seek to a different segment + let blob_service = this.blob_service.clone(); + let digest = digest.clone(); + this.current_blob = futures::future::try_maybe_done( + (async move { + let mut reader = + blob_service + .open_read(&digest) + .await? + .ok_or(io::Error::new( + io::ErrorKind::NotFound, + RenderError::BlobNotFound(digest.clone(), Default::default()), + ))?; + if offset_in_segment != 0 { + reader.seek(io::SeekFrom::Start(offset_in_segment)).await?; + } + Ok(reader) + }) + .boxed(), + ); + }; + + Ok(()) + } + fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<u64>> { + let this = &mut *self; + + if !this.current_blob.is_terminated() { + futures::ready!(this.current_blob.poll_unpin(cx))?; + } + this.seeking = false; + + Poll::Ready(Ok(this.position_bytes)) + } +} + +impl<B: BlobService + 'static> tokio::io::AsyncRead for Reader<B> { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context, + buf: &mut tokio::io::ReadBuf, + ) -> Poll<io::Result<()>> { + let this = &mut *self; + + let Some(&(offset, ref segment)) = this.segments.get(this.position_index) else { + return Poll::Ready(Ok(())); // EOF + }; + + let prev_read_buf_pos = buf.filled().len(); + match segment { + Data::Literal(data) => { + let offset_in_segment = this.position_bytes - offset; + let offset_in_segment = usize::try_from(offset_in_segment).unwrap(); + let remaining_data = data.len() - offset_in_segment; + let read_size = std::cmp::min(remaining_data, buf.remaining()); + buf.put(&data[offset_in_segment..offset_in_segment + read_size]); + } + Data::Blob(BlobRef { size, .. }) => { + futures::ready!(this.current_blob.poll_unpin(cx))?; + this.seeking = false; + let blob = Pin::new(&mut this.current_blob) + .output_mut() + .expect("missing blob"); + futures::ready!(Pin::new(blob).poll_read(cx, buf))?; + let read_length = buf.filled().len() - prev_read_buf_pos; + let maximum_expected_read_length = (offset + size) - this.position_bytes; + let is_eof = read_length == 0; + let too_much_returned = read_length as u64 > maximum_expected_read_length; + match (is_eof, too_much_returned) { + (true, false) => { + return Poll::Ready(Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + "blob short read", + ))) + } + (false, true) => { + buf.set_filled(prev_read_buf_pos); + return Poll::Ready(Err(io::Error::new( + io::ErrorKind::InvalidInput, + "blob continued to yield data beyond end", + ))); + } + _ => {} + } + } + }; + let new_read_buf_pos = buf.filled().len(); + this.position_bytes += (new_read_buf_pos - prev_read_buf_pos) as u64; + + let prev_position_index = this.position_index; + while { + if let Some(&(offset, ref segment)) = this.segments.get(this.position_index) { + (this.position_bytes - offset) >= segment.len() + } else { + false + } + } { + this.position_index += 1; + } + if prev_position_index != this.position_index { + let Some((_offset, Data::Blob(BlobRef { digest, .. }))) = + this.segments.get(this.position_index) + else { + // If the next segment is not a blob, we clear the active blob reader and then we're done + this.current_blob = TryMaybeDone::Gone; + return Poll::Ready(Ok(())); + }; + + // The next segment is a blob, open the BlobReader + let blob_service = this.blob_service.clone(); + let digest = digest.clone(); + this.current_blob = futures::future::try_maybe_done( + (async move { + let reader = blob_service + .open_read(&digest) + .await? + .ok_or(io::Error::new( + io::ErrorKind::NotFound, + RenderError::BlobNotFound(digest.clone(), Default::default()), + ))?; + Ok(reader) + }) + .boxed(), + ); + } + + Poll::Ready(Ok(())) + } +} diff --git a/tvix/store/src/path_info.rs b/tvix/store/src/path_info.rs new file mode 100644 index 000000000000..487261b4bdcb --- /dev/null +++ b/tvix/store/src/path_info.rs @@ -0,0 +1,87 @@ +use nix_compat::{ + narinfo::{Flags, Signature}, + nixhash::CAHash, + store_path::StorePath, +}; + +/// Holds metadata about a store path, but not its contents. +/// +/// This is somewhat equivalent to the information Nix holds in its SQLite +/// database, or publishes as .narinfo files, except we also embed the +/// [tvix_castore::Node] describing the contents in the castore model. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PathInfo { + /// The store path this is about. + pub store_path: StorePath<String>, + /// The contents in the tvix-castore model. + //// Can be a directory, file or symlink. + pub node: tvix_castore::Node, + /// A list of references. + pub references: Vec<StorePath<String>>, + /// The size of the NAR representation of the contents, in bytes. + pub nar_size: u64, + /// The sha256 digest of the NAR representation of the contents. + pub nar_sha256: [u8; 32], + /// The signatures, usually shown in a .narinfo file. + pub signatures: Vec<Signature<String>>, + /// The StorePath of the .drv file producing this output. + /// The .drv suffix is omitted in its `name` field. + pub deriver: Option<StorePath<String>>, + /// The CA field in the .narinfo. + /// Its textual representations seen in the wild are one of the following: + /// + /// * `fixed:r:sha256:1gcky5hlf5vqfzpyhihydmm54grhc94mcs8w7xr8613qsqb1v2j6` + /// fixed-output derivations using "recursive" `outputHashMode`. + /// * `fixed:sha256:19xqkh72crbcba7flwxyi3n293vav6d7qkzkh2v4zfyi4iia8vj8 fixed-output derivations using "flat" `outputHashMode\` + /// * `text:sha256:19xqkh72crbcba7flwxyi3n293vav6d7qkzkh2v4zfyi4iia8vj8` + /// Text hashing, used for uploaded .drv files and outputs produced by + /// builtins.toFile. + /// + /// Semantically, they can be split into the following components: + /// + /// * "content address prefix". Currently, "fixed" and "text" are supported. + /// * "hash mode". Currently, "flat" and "recursive" are supported. + /// * "hash type". The underlying hash function used. + /// Currently, sha1, md5, sha256, sha512. + /// * "digest". The digest itself. + /// + /// There are some restrictions on the possible combinations. + /// For example, `text` and `fixed:recursive` always imply sha256. + pub ca: Option<CAHash>, +} + +impl PathInfo { + /// Reconstructs a [nix_compat::narinfo::NarInfo<'_>]. + /// + /// It does very little allocation (a Vec each for `signatures` and + /// `references`), the rest points to data owned elsewhere. + /// + /// It can be used to validate Signatures, or render a .narinfo file + /// (after some more fields are populated) + /// + /// Keep in mind this is not able to reconstruct all data present in the + /// NarInfo<'_>, as some of it is not stored at all: + /// - the `system`, `file_hash` and `file_size` fields are set to `None`. + /// - the URL is set to an empty string. + /// - Compression is set to "none" + /// + /// If you want to render it out to a string and be able to parse it back + /// in, at least URL *must* be set again. + pub fn to_narinfo(&self) -> nix_compat::narinfo::NarInfo<'_> { + nix_compat::narinfo::NarInfo { + flags: Flags::empty(), + store_path: self.store_path.as_ref(), + nar_hash: self.nar_sha256, + nar_size: self.nar_size, + references: self.references.iter().map(StorePath::as_ref).collect(), + signatures: self.signatures.iter().map(Signature::as_ref).collect(), + ca: self.ca.clone(), + system: None, + deriver: self.deriver.as_ref().map(StorePath::as_ref), + url: "", + compression: Some("none"), + file_hash: None, + file_size: None, + } + } +} diff --git a/tvix/store/src/pathinfoservice/bigtable.rs b/tvix/store/src/pathinfoservice/bigtable.rs index 6fb52abbfdac..3d8db8e5044a 100644 --- a/tvix/store/src/pathinfoservice/bigtable.rs +++ b/tvix/store/src/pathinfoservice/bigtable.rs @@ -1,24 +1,25 @@ -use super::PathInfoService; +use super::{PathInfo, PathInfoService}; use crate::proto; -use crate::proto::PathInfo; use async_stream::try_stream; use bigtable_rs::{bigtable, google::bigtable::v2 as bigtable_v2}; use bytes::Bytes; use data_encoding::HEXLOWER; use futures::stream::BoxStream; +use nix_compat::nixbase32; use prost::Message; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DurationSeconds}; +use std::sync::Arc; use tonic::async_trait; -use tracing::trace; -use tvix_castore::proto as castorepb; +use tracing::{instrument, trace}; +use tvix_castore::composition::{CompositionContext, ServiceBuilder}; use tvix_castore::Error; /// There should not be more than 10 MiB in a single cell. /// https://cloud.google.com/bigtable/docs/schema-design#cells const CELL_SIZE_LIMIT: u64 = 10 * 1024 * 1024; -/// Provides a [DirectoryService] implementation using +/// Provides a [PathInfoService] implementation using /// [Bigtable](https://cloud.google.com/bigtable/docs/) /// as an underlying K/V store. /// @@ -44,41 +45,6 @@ pub struct BigtablePathInfoService { emulator: std::sync::Arc<(tempfile::TempDir, async_process::Child)>, } -/// Represents configuration of [BigtablePathInfoService]. -/// This currently conflates both connect parameters and data model/client -/// behaviour parameters. -#[serde_as] -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct BigtableParameters { - project_id: String, - instance_name: String, - #[serde(default)] - is_read_only: bool, - #[serde(default = "default_channel_size")] - channel_size: usize, - - #[serde_as(as = "Option<DurationSeconds<String>>")] - #[serde(default = "default_timeout")] - timeout: Option<std::time::Duration>, - table_name: String, - family_name: String, - - #[serde(default = "default_app_profile_id")] - app_profile_id: String, -} - -fn default_app_profile_id() -> String { - "default".to_owned() -} - -fn default_channel_size() -> usize { - 4 -} - -fn default_timeout() -> Option<std::time::Duration> { - Some(std::time::Duration::from_secs(4)) -} - impl BigtablePathInfoService { #[cfg(not(test))] pub async fn connect(params: BigtableParameters) -> Result<Self, bigtable::Error> { @@ -182,6 +148,7 @@ fn derive_pathinfo_key(digest: &[u8; 20]) -> String { #[async_trait] impl PathInfoService for BigtablePathInfoService { + #[instrument(level = "trace", skip_all, fields(path_info.digest = nixbase32::encode(&digest)))] async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error> { let mut client = self.client.clone(); let path_info_key = derive_pathinfo_key(&digest); @@ -264,29 +231,25 @@ impl PathInfoService for BigtablePathInfoService { } // Try to parse the value into a PathInfo message - let path_info = proto::PathInfo::decode(Bytes::from(cell.value)) + let path_info_proto = proto::PathInfo::decode(Bytes::from(cell.value)) .map_err(|e| Error::StorageError(format!("unable to decode pathinfo proto: {}", e)))?; - let store_path = path_info - .validate() - .map_err(|e| Error::StorageError(format!("invalid PathInfo: {}", e)))?; + let path_info = PathInfo::try_from(path_info_proto) + .map_err(|e| Error::StorageError(format!("Invalid path info: {e}")))?; - if store_path.digest() != &digest { + if path_info.store_path.digest() != &digest { return Err(Error::StorageError("PathInfo has unexpected digest".into())); } Ok(Some(path_info)) } + #[instrument(level = "trace", skip_all, fields(path_info.root_node = ?path_info.node))] async fn put(&self, path_info: PathInfo) -> Result<PathInfo, Error> { - let store_path = path_info - .validate() - .map_err(|e| Error::InvalidRequest(format!("pathinfo failed validation: {}", e)))?; - let mut client = self.client.clone(); - let path_info_key = derive_pathinfo_key(store_path.digest()); + let path_info_key = derive_pathinfo_key(path_info.store_path.digest()); - let data = path_info.encode_to_vec(); + let data = proto::PathInfo::from(path_info.clone()).encode_to_vec(); if data.len() as u64 > CELL_SIZE_LIMIT { return Err(Error::StorageError( "PathInfo exceeds cell limit on Bigtable".into(), @@ -330,13 +293,6 @@ impl PathInfoService for BigtablePathInfoService { Ok(path_info) } - async fn calculate_nar( - &self, - _root_node: &castorepb::node::Node, - ) -> Result<(u64, [u8; 32]), Error> { - return Err(Error::StorageError("unimplemented".into())); - } - fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { let mut client = self.client.clone(); @@ -378,16 +334,14 @@ impl PathInfoService for BigtablePathInfoService { } // Try to parse the value into a PathInfo message. - let path_info = proto::PathInfo::decode(Bytes::from(cell.value)) + let path_info_proto = proto::PathInfo::decode(Bytes::from(cell.value)) .map_err(|e| Error::StorageError(format!("unable to decode pathinfo proto: {}", e)))?; - // Validate the containing PathInfo, ensure its StorePath digest - // matches row key. - let store_path = path_info - .validate() - .map_err(|e| Error::StorageError(format!("invalid PathInfo: {}", e)))?; + let path_info = PathInfo::try_from(path_info_proto).map_err(|e| Error::StorageError(format!("Invalid path info: {e}")))?; + + let exp_path_info_key = derive_pathinfo_key(path_info.store_path.digest()); - if store_path.digest().as_slice() != row_key.as_slice() { + if exp_path_info_key.as_bytes() != row_key.as_slice() { Err(Error::StorageError("PathInfo has unexpected digest".into()))? } @@ -399,3 +353,88 @@ impl PathInfoService for BigtablePathInfoService { Box::pin(stream) } } + +/// Represents configuration of [BigtablePathInfoService]. +/// This currently conflates both connect parameters and data model/client +/// behaviour parameters. +#[serde_as] +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +pub struct BigtableParameters { + project_id: String, + instance_name: String, + #[serde(default)] + is_read_only: bool, + #[serde(default = "default_channel_size")] + channel_size: usize, + + #[serde_as(as = "Option<DurationSeconds<String>>")] + #[serde(default = "default_timeout")] + timeout: Option<std::time::Duration>, + table_name: String, + family_name: String, + + #[serde(default = "default_app_profile_id")] + app_profile_id: String, +} + +impl BigtableParameters { + #[cfg(test)] + pub fn default_for_tests() -> Self { + Self { + project_id: "project-1".into(), + instance_name: "instance-1".into(), + is_read_only: false, + channel_size: default_channel_size(), + timeout: default_timeout(), + table_name: "table-1".into(), + family_name: "cf1".into(), + app_profile_id: default_app_profile_id(), + } + } +} + +fn default_app_profile_id() -> String { + "default".to_owned() +} + +fn default_channel_size() -> usize { + 4 +} + +fn default_timeout() -> Option<std::time::Duration> { + Some(std::time::Duration::from_secs(4)) +} + +#[async_trait] +impl ServiceBuilder for BigtableParameters { + type Output = dyn PathInfoService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn PathInfoService>, Box<dyn std::error::Error + Send + Sync>> { + Ok(Arc::new( + BigtablePathInfoService::connect(self.clone()).await?, + )) + } +} + +impl TryFrom<url::Url> for BigtableParameters { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(mut url: url::Url) -> Result<Self, Self::Error> { + // parse the instance name from the hostname. + let instance_name = url + .host_str() + .ok_or_else(|| Error::StorageError("instance name missing".into()))? + .to_string(); + + // … but add it to the query string now, so we just need to parse that. + url.query_pairs_mut() + .append_pair("instance_name", &instance_name); + + let params: BigtableParameters = serde_qs::from_str(url.query().unwrap_or_default()) + .map_err(|e| Error::InvalidRequest(format!("failed to parse parameters: {}", e)))?; + + Ok(params) + } +} diff --git a/tvix/store/src/pathinfoservice/combinators.rs b/tvix/store/src/pathinfoservice/combinators.rs new file mode 100644 index 000000000000..f386fd52dc3c --- /dev/null +++ b/tvix/store/src/pathinfoservice/combinators.rs @@ -0,0 +1,150 @@ +use std::sync::Arc; + +use futures::stream::BoxStream; +use nix_compat::nixbase32; +use tonic::async_trait; +use tracing::{debug, instrument}; +use tvix_castore::composition::{CompositionContext, ServiceBuilder}; +use tvix_castore::Error; + +use super::{PathInfo, PathInfoService}; + +/// Asks near first, if not found, asks far. +/// If found in there, returns it, and *inserts* it into +/// near. +/// There is no negative cache. +/// Inserts and listings are not implemented for now. +pub struct Cache<PS1, PS2> { + near: PS1, + far: PS2, +} + +impl<PS1, PS2> Cache<PS1, PS2> { + pub fn new(near: PS1, far: PS2) -> Self { + Self { near, far } + } +} + +#[async_trait] +impl<PS1, PS2> PathInfoService for Cache<PS1, PS2> +where + PS1: PathInfoService, + PS2: PathInfoService, +{ + #[instrument(level = "trace", skip_all, fields(path_info.digest = nixbase32::encode(&digest)))] + async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error> { + match self.near.get(digest).await? { + Some(path_info) => { + debug!("serving from cache"); + Ok(Some(path_info)) + } + None => { + debug!("not found in near, asking remote…"); + match self.far.get(digest).await? { + None => Ok(None), + Some(path_info) => { + debug!("found in remote, adding to cache"); + self.near.put(path_info.clone()).await?; + Ok(Some(path_info)) + } + } + } + } + } + + async fn put(&self, _path_info: PathInfo) -> Result<PathInfo, Error> { + Err(Error::StorageError("unimplemented".to_string())) + } + + fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { + Box::pin(tokio_stream::once(Err(Error::StorageError( + "unimplemented".to_string(), + )))) + } +} + +#[derive(serde::Deserialize)] +pub struct CacheConfig { + pub near: String, + pub far: String, +} + +impl TryFrom<url::Url> for CacheConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(_url: url::Url) -> Result<Self, Self::Error> { + Err(Error::StorageError( + "Instantiating a CombinedPathInfoService from a url is not supported".into(), + ) + .into()) + } +} + +#[async_trait] +impl ServiceBuilder for CacheConfig { + type Output = dyn PathInfoService; + async fn build<'a>( + &'a self, + _instance_name: &str, + context: &CompositionContext, + ) -> Result<Arc<dyn PathInfoService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + let (near, far) = futures::join!( + context.resolve::<Self::Output>(self.near.clone()), + context.resolve::<Self::Output>(self.far.clone()) + ); + Ok(Arc::new(Cache { + near: near?, + far: far?, + })) + } +} + +#[cfg(test)] +mod test { + use std::num::NonZeroUsize; + + use crate::{ + pathinfoservice::{LruPathInfoService, MemoryPathInfoService, PathInfoService}, + tests::fixtures::PATH_INFO, + }; + + /// Helper function setting up an instance of a "far" and "near" + /// PathInfoService. + async fn create_pathinfoservice() -> super::Cache<LruPathInfoService, MemoryPathInfoService> { + // Create an instance of a "far" PathInfoService. + let far = MemoryPathInfoService::default(); + + // … and an instance of a "near" PathInfoService. + let near = LruPathInfoService::with_capacity(NonZeroUsize::new(1).unwrap()); + + // create a Pathinfoservice combining the two and return it. + super::Cache::new(near, far) + } + + /// Getting from the far backend is gonna insert it into the near one. + #[tokio::test] + async fn test_populate_cache() { + let svc = create_pathinfoservice().await; + + // query the PathInfo, things should not be there. + assert!(svc + .get(*PATH_INFO.store_path.digest()) + .await + .unwrap() + .is_none()); + + // insert it into the far one. + svc.far.put(PATH_INFO.clone()).await.unwrap(); + + // now try getting it again, it should succeed. + assert_eq!( + Some(PATH_INFO.clone()), + svc.get(*PATH_INFO.store_path.digest()).await.unwrap() + ); + + // peek near, it should now be there. + assert_eq!( + Some(PATH_INFO.clone()), + svc.near.get(*PATH_INFO.store_path.digest()).await.unwrap() + ); + } +} diff --git a/tvix/store/src/pathinfoservice/from_addr.rs b/tvix/store/src/pathinfoservice/from_addr.rs index 1ff822ad35ec..683457345c6c 100644 --- a/tvix/store/src/pathinfoservice/from_addr.rs +++ b/tvix/store/src/pathinfoservice/from_addr.rs @@ -1,13 +1,10 @@ -use crate::proto::path_info_service_client::PathInfoServiceClient; +use super::PathInfoService; -use super::{ - GRPCPathInfoService, MemoryPathInfoService, NixHTTPPathInfoService, PathInfoService, - SledPathInfoService, +use crate::composition::{ + with_registry, CompositionContext, DeserializeWithRegistry, ServiceBuilder, REG, }; - -use nix_compat::narinfo; use std::sync::Arc; -use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService, Error}; +use tvix_castore::Error; use url::Url; /// Constructs a new instance of a [PathInfoService] from an URI. @@ -15,10 +12,10 @@ use url::Url; /// The following URIs are supported: /// - `memory:` /// Uses a in-memory implementation. -/// - `sled:` -/// Uses a in-memory sled implementation. -/// - `sled:///absolute/path/to/somewhere` -/// Uses sled, using a path on the disk for persistency. Can be only opened +/// - `redb:` +/// Uses a in-memory redb implementation. +/// - `redb:///absolute/path/to/somewhere` +/// Uses redb, using a path on the disk for persistency. Can be only opened /// from one process at the same time. /// - `nix+https://cache.nixos.org?trusted-public-keys=cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=` /// Exposes the Nix binary cache as a PathInfoService, ingesting NARs into the @@ -34,110 +31,24 @@ use url::Url; /// these also need to be passed in. pub async fn from_addr( uri: &str, - blob_service: Arc<dyn BlobService>, - directory_service: Arc<dyn DirectoryService>, -) -> Result<Box<dyn PathInfoService>, Error> { + context: Option<&CompositionContext<'_>>, +) -> Result<Arc<dyn PathInfoService>, Box<dyn std::error::Error + Send + Sync>> { #[allow(unused_mut)] let mut url = Url::parse(uri).map_err(|e| Error::StorageError(format!("unable to parse url: {}", e)))?; - let path_info_service: Box<dyn PathInfoService> = match url.scheme() { - "memory" => { - // memory doesn't support host or path in the URL. - if url.has_host() || !url.path().is_empty() { - return Err(Error::StorageError("invalid url".to_string())); - } - Box::new(MemoryPathInfoService::new(blob_service, directory_service)) - } - "sled" => { - // sled doesn't support host, and a path can be provided (otherwise - // it'll live in memory only). - if url.has_host() { - return Err(Error::StorageError("no host allowed".to_string())); - } - - if url.path() == "/" { - return Err(Error::StorageError( - "cowardly refusing to open / with sled".to_string(), - )); - } - - // TODO: expose other parameters as URL parameters? - - Box::new(if url.path().is_empty() { - SledPathInfoService::new_temporary(blob_service, directory_service) - .map_err(|e| Error::StorageError(e.to_string()))? - } else { - SledPathInfoService::new(url.path(), blob_service, directory_service) - .map_err(|e| Error::StorageError(e.to_string()))? - }) - } - "nix+http" | "nix+https" => { - // Stringify the URL and remove the nix+ prefix. - // We can't use `url.set_scheme(rest)`, as it disallows - // setting something http(s) that previously wasn't. - let new_url = Url::parse(url.to_string().strip_prefix("nix+").unwrap()).unwrap(); - - let mut nix_http_path_info_service = - NixHTTPPathInfoService::new(new_url, blob_service, directory_service); - - let pairs = &url.query_pairs(); - for (k, v) in pairs.into_iter() { - if k == "trusted-public-keys" { - let pubkey_strs: Vec<_> = v.split_ascii_whitespace().collect(); - - let mut pubkeys: Vec<narinfo::PubKey> = Vec::with_capacity(pubkey_strs.len()); - for pubkey_str in pubkey_strs { - pubkeys.push(narinfo::PubKey::parse(pubkey_str).map_err(|e| { - Error::StorageError(format!("invalid public key: {e}")) - })?); - } - - nix_http_path_info_service.set_public_keys(pubkeys); - } - } - - Box::new(nix_http_path_info_service) - } - scheme if scheme.starts_with("grpc+") => { - // schemes starting with grpc+ go to the GRPCPathInfoService. - // That's normally grpc+unix for unix sockets, and grpc+http(s) for the HTTP counterparts. - // - In the case of unix sockets, there must be a path, but may not be a host. - // - In the case of non-unix sockets, there must be a host, but no path. - // Constructing the channel is handled by tvix_castore::channel::from_url. - let client = - PathInfoServiceClient::new(tvix_castore::tonic::channel_from_url(&url).await?); - Box::new(GRPCPathInfoService::from_client(client)) - } - #[cfg(feature = "cloud")] - "bigtable" => { - use super::bigtable::BigtableParameters; - use super::BigtablePathInfoService; - - // parse the instance name from the hostname. - let instance_name = url - .host_str() - .ok_or_else(|| Error::StorageError("instance name missing".into()))? - .to_string(); - - // … but add it to the query string now, so we just need to parse that. - url.query_pairs_mut() - .append_pair("instance_name", &instance_name); - - let params: BigtableParameters = serde_qs::from_str(url.query().unwrap_or_default()) - .map_err(|e| Error::InvalidRequest(format!("failed to parse parameters: {}", e)))?; - - Box::new( - BigtablePathInfoService::connect(params) - .await - .map_err(|e| Error::StorageError(e.to_string()))?, - ) - } - _ => Err(Error::StorageError(format!( - "unknown scheme: {}", - url.scheme() - )))?, - }; + let path_info_service_config = with_registry(®, || { + <DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>>>::try_from( + url, + ) + })? + .0; + let path_info_service = path_info_service_config + .build( + "anonymous", + context.unwrap_or(&CompositionContext::blank(®)), + ) + .await?; Ok(path_info_service) } @@ -145,35 +56,21 @@ pub async fn from_addr( #[cfg(test)] mod tests { use super::from_addr; - use lazy_static::lazy_static; + use crate::composition::{Composition, DeserializeWithRegistry, ServiceBuilder, REG}; use rstest::rstest; - use std::sync::Arc; + use std::sync::LazyLock; use tempfile::TempDir; - use tvix_castore::{ - blobservice::{BlobService, MemoryBlobService}, - directoryservice::{DirectoryService, MemoryDirectoryService}, - }; + use tvix_castore::blobservice::{BlobService, MemoryBlobServiceConfig}; + use tvix_castore::directoryservice::{DirectoryService, MemoryDirectoryServiceConfig}; - lazy_static! { - static ref TMPDIR_SLED_1: TempDir = TempDir::new().unwrap(); - static ref TMPDIR_SLED_2: TempDir = TempDir::new().unwrap(); - } + static TMPDIR_REDB_1: LazyLock<TempDir> = LazyLock::new(|| TempDir::new().unwrap()); + static TMPDIR_REDB_2: LazyLock<TempDir> = LazyLock::new(|| TempDir::new().unwrap()); // the gRPC tests below don't fail, because we connect lazily. #[rstest] /// This uses a unsupported scheme. #[case::unsupported_scheme("http://foo.example/test", false)] - /// This configures sled in temporary mode. - #[case::sled_temporary("sled://", true)] - /// This configures sled with /, which should fail. - #[case::sled_invalid_root("sled:///", false)] - /// This configures sled with a host, not path, which should fail. - #[case::sled_invalid_host("sled://foo.example", false)] - /// This configures sled with a valid path path, which should succeed. - #[case::sled_valid_path(&format!("sled://{}", &TMPDIR_SLED_1.path().to_str().unwrap()), true)] - /// This configures sled with a host, and a valid path path, which should fail. - #[case::sled_invalid_host_with_valid_path(&format!("sled://foo.example{}", &TMPDIR_SLED_2.path().to_str().unwrap()), false)] /// This correctly sets the scheme, and doesn't set a path. #[case::memory_valid("memory://", true)] /// This sets a memory url host to `foo` @@ -182,6 +79,14 @@ mod tests { #[case::memory_invalid_root_path("memory:///", false)] /// This sets a memory url path to "/foo", which is invalid. #[case::memory_invalid_root_path_foo("memory:///foo", false)] + /// redb with a host, and a valid path path, which should fail. + #[case::redb_invalid_host_with_valid_path(&format!("redb://foo.example{}", &TMPDIR_REDB_1.path().join("bar").to_str().unwrap()), false)] + /// redb with / as path, which should fail. + #[case::redb_invalid_root("redb:///", false)] + /// This configures redb with a valid path, which should succeed. + #[case::redb_valid_path(&format!("redb://{}", &TMPDIR_REDB_2.path().join("foo").to_str().unwrap()), true)] + /// redb using the in-memory backend, which should succeed. + #[case::redb_valid_in_memory("redb://", true)] /// Correct Scheme for the cache.nixos.org binary cache. #[case::correct_nix_https("nix+https://cache.nixos.org", true)] /// Correct Scheme for the cache.nixos.org binary cache (HTTP URL). @@ -208,7 +113,7 @@ mod tests { #[case::grpc_invalid_host_and_path("grpc+http://localhost/some-path", false)] /// A valid example for Bigtable. #[cfg_attr( - feature = "cloud", + all(feature = "cloud", feature = "integration"), case::bigtable_valid( "bigtable://instance-1?project_id=project-1&table_name=table-1&family_name=cf1", true @@ -216,16 +121,24 @@ mod tests { )] /// An invalid example for Bigtable, missing fields #[cfg_attr( - feature = "cloud", + all(feature = "cloud", feature = "integration"), case::bigtable_invalid_missing_fields("bigtable://instance-1", false) )] #[tokio::test] async fn test_from_addr_tokio(#[case] uri_str: &str, #[case] exp_succeed: bool) { - let blob_service: Arc<dyn BlobService> = Arc::from(MemoryBlobService::default()); - let directory_service: Arc<dyn DirectoryService> = - Arc::from(MemoryDirectoryService::default()); - - let resp = from_addr(uri_str, blob_service, directory_service).await; + let mut comp = Composition::new(®); + comp.extend(vec![( + "default".into(), + DeserializeWithRegistry(Box::new(MemoryBlobServiceConfig {}) + as Box<dyn ServiceBuilder<Output = dyn BlobService>>), + )]); + comp.extend(vec![( + "default".into(), + DeserializeWithRegistry(Box::new(MemoryDirectoryServiceConfig {}) + as Box<dyn ServiceBuilder<Output = dyn DirectoryService>>), + )]); + + let resp = from_addr(uri_str, Some(&comp.context())).await; if exp_succeed { resp.expect("should succeed"); diff --git a/tvix/store/src/pathinfoservice/fs/mod.rs b/tvix/store/src/pathinfoservice/fs/mod.rs index aa64b1c01f16..ea30a2f6477c 100644 --- a/tvix/store/src/pathinfoservice/fs/mod.rs +++ b/tvix/store/src/pathinfoservice/fs/mod.rs @@ -1,10 +1,10 @@ use futures::stream::BoxStream; use futures::StreamExt; +use nix_compat::store_path::StorePathRef; use tonic::async_trait; use tvix_castore::fs::{RootNodes, TvixStoreFs}; -use tvix_castore::proto as castorepb; -use tvix_castore::Error; use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService}; +use tvix_castore::{Error, Node, PathComponent}; use super::PathInfoService; @@ -20,9 +20,9 @@ pub fn make_fs<BS, DS, PS>( show_xattr: bool, ) -> TvixStoreFs<BS, DS, RootNodesWrapper<PS>> where - BS: AsRef<dyn BlobService> + Send + Clone + 'static, - DS: AsRef<dyn DirectoryService> + Send + Clone + 'static, - PS: AsRef<dyn PathInfoService> + Send + Sync + Clone + 'static, + BS: BlobService + Send + Clone + 'static, + DS: DirectoryService + Send + Clone + 'static, + PS: PathInfoService + Send + Sync + Clone + 'static, { TvixStoreFs::new( blob_service, @@ -46,35 +46,31 @@ pub struct RootNodesWrapper<T>(pub(crate) T); #[async_trait] impl<T> RootNodes for RootNodesWrapper<T> where - T: AsRef<dyn PathInfoService> + Send + Sync, + T: PathInfoService + Send + Sync, { - async fn get_by_basename(&self, name: &[u8]) -> Result<Option<castorepb::node::Node>, Error> { - let Ok(store_path) = nix_compat::store_path::StorePath::from_bytes(name) else { + async fn get_by_basename(&self, name: &PathComponent) -> Result<Option<Node>, Error> { + let Ok(store_path) = StorePathRef::from_bytes(name.as_ref()) else { return Ok(None); }; Ok(self .0 - .as_ref() .get(*store_path.digest()) .await? - .map(|path_info| { - path_info - .node - .expect("missing root node") - .node - .expect("empty node") - })) + .map(|path_info| path_info.node)) } - fn list(&self) -> BoxStream<Result<castorepb::node::Node, Error>> { - Box::pin(self.0.as_ref().list().map(|result| { + fn list(&self) -> BoxStream<Result<(PathComponent, Node), Error>> { + Box::pin(self.0.list().map(|result| { result.map(|path_info| { - path_info - .node - .expect("missing root node") - .node - .expect("empty node") + let basename = path_info.store_path.to_string(); + ( + basename + .as_str() + .try_into() + .expect("Tvix bug: StorePath must be PathComponent"), + path_info.node, + ) }) })) } diff --git a/tvix/store/src/pathinfoservice/grpc.rs b/tvix/store/src/pathinfoservice/grpc.rs index 1138ebdc198b..453044cba13d 100644 --- a/tvix/store/src/pathinfoservice/grpc.rs +++ b/tvix/store/src/pathinfoservice/grpc.rs @@ -1,33 +1,46 @@ -use super::PathInfoService; -use crate::proto::{self, ListPathInfoRequest, PathInfo}; +use super::{PathInfo, PathInfoService}; +use crate::{ + nar::NarCalculationService, + proto::{self, ListPathInfoRequest}, +}; use async_stream::try_stream; -use data_encoding::BASE64; use futures::stream::BoxStream; -use tonic::{async_trait, transport::Channel, Code}; -use tracing::instrument; -use tvix_castore::{proto as castorepb, Error}; +use nix_compat::nixbase32; +use std::sync::Arc; +use tonic::{async_trait, Code}; +use tracing::{instrument, warn, Span}; +use tracing_indicatif::span_ext::IndicatifSpanExt; +use tvix_castore::composition::{CompositionContext, ServiceBuilder}; +use tvix_castore::Error; +use tvix_castore::Node; /// Connects to a (remote) tvix-store PathInfoService over gRPC. #[derive(Clone)] -pub struct GRPCPathInfoService { +pub struct GRPCPathInfoService<T> { /// The internal reference to a gRPC client. /// Cloning it is cheap, and it internally handles concurrent requests. - grpc_client: proto::path_info_service_client::PathInfoServiceClient<Channel>, + grpc_client: proto::path_info_service_client::PathInfoServiceClient<T>, } -impl GRPCPathInfoService { +impl<T> GRPCPathInfoService<T> { /// construct a [GRPCPathInfoService] from a [proto::path_info_service_client::PathInfoServiceClient]. /// panics if called outside the context of a tokio runtime. pub fn from_client( - grpc_client: proto::path_info_service_client::PathInfoServiceClient<Channel>, + grpc_client: proto::path_info_service_client::PathInfoServiceClient<T>, ) -> Self { Self { grpc_client } } } #[async_trait] -impl PathInfoService for GRPCPathInfoService { - #[instrument(level = "trace", skip_all, fields(path_info.digest = BASE64.encode(&digest)))] +impl<T> PathInfoService for GRPCPathInfoService<T> +where + T: tonic::client::GrpcService<tonic::body::BoxBody> + Send + Sync + Clone + 'static, + T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static, + <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send, + T::Future: Send, +{ + #[instrument(level = "trace", skip_all, fields(path_info.digest = nixbase32::encode(&digest)))] async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error> { let path_info = self .grpc_client @@ -40,15 +53,10 @@ impl PathInfoService for GRPCPathInfoService { .await; match path_info { - Ok(path_info) => { - let path_info = path_info.into_inner(); - - path_info - .validate() - .map_err(|e| Error::StorageError(format!("invalid pathinfo: {}", e)))?; - - Ok(Some(path_info)) - } + Ok(path_info) => Ok(Some( + PathInfo::try_from(path_info.into_inner()) + .map_err(|e| Error::StorageError(format!("Invalid path info: {e}")))?, + )), Err(e) if e.code() == Code::NotFound => Ok(None), Err(e) => Err(Error::StorageError(e.to_string())), } @@ -59,25 +67,64 @@ impl PathInfoService for GRPCPathInfoService { let path_info = self .grpc_client .clone() - .put(path_info) + .put(proto::PathInfo::from(path_info)) .await .map_err(|e| Error::StorageError(e.to_string()))? .into_inner(); + Ok(PathInfo::try_from(path_info) + .map_err(|e| Error::StorageError(format!("Invalid path info: {e}")))?) + } + + #[instrument(level = "trace", skip_all)] + fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { + let mut grpc_client = self.grpc_client.clone(); + + let stream = try_stream! { + let resp = grpc_client.list(ListPathInfoRequest::default()).await; + + let mut stream = resp.map_err(|e| Error::StorageError(e.to_string()))?.into_inner(); - Ok(path_info) + loop { + match stream.message().await { + Ok(Some(path_info)) => yield PathInfo::try_from(path_info).map_err(|e| Error::StorageError(format!("Invalid path info: {e}")))?, + Ok(None) => return, + Err(e) => Err(Error::StorageError(e.to_string()))?, + } + } + }; + + Box::pin(stream) + } + + #[instrument(level = "trace", skip_all)] + fn nar_calculation_service(&self) -> Option<Box<dyn NarCalculationService>> { + Some(Box::new(GRPCPathInfoService { + grpc_client: self.grpc_client.clone(), + }) as Box<dyn NarCalculationService>) } +} + +#[async_trait] +impl<T> NarCalculationService for GRPCPathInfoService<T> +where + T: tonic::client::GrpcService<tonic::body::BoxBody> + Send + Sync + Clone + 'static, + T::ResponseBody: tonic::codegen::Body<Data = tonic::codegen::Bytes> + Send + 'static, + <T::ResponseBody as tonic::codegen::Body>::Error: Into<tonic::codegen::StdError> + Send, + T::Future: Send, +{ + #[instrument(level = "trace", skip_all, fields(root_node = ?root_node, indicatif.pb_show=1))] + async fn calculate_nar(&self, root_node: &Node) -> Result<(u64, [u8; 32]), Error> { + let span = Span::current(); + span.pb_set_message("Waiting for NAR calculation"); + span.pb_start(); - #[instrument(level = "trace", skip_all, fields(root_node = ?root_node))] - async fn calculate_nar( - &self, - root_node: &castorepb::node::Node, - ) -> Result<(u64, [u8; 32]), Error> { let path_info = self .grpc_client .clone() - .calculate_nar(castorepb::Node { - node: Some(root_node.clone()), - }) + .calculate_nar(tvix_castore::proto::Node::from_name_and_node( + "".into(), + root_node.to_owned(), + )) .await .map_err(|e| Error::StorageError(e.to_string()))? .into_inner(); @@ -90,123 +137,55 @@ impl PathInfoService for GRPCPathInfoService { Ok((path_info.nar_size, nar_sha256)) } +} - #[instrument(level = "trace", skip_all)] - fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { - let mut grpc_client = self.grpc_client.clone(); - - let stream = try_stream! { - let resp = grpc_client.list(ListPathInfoRequest::default()).await; - - let mut stream = resp.map_err(|e| Error::StorageError(e.to_string()))?.into_inner(); +#[derive(serde::Deserialize, Debug)] +#[serde(deny_unknown_fields)] +pub struct GRPCPathInfoServiceConfig { + url: String, +} - loop { - match stream.message().await { - Ok(o) => match o { - Some(pathinfo) => { - // validate the pathinfo - if let Err(e) = pathinfo.validate() { - Err(Error::StorageError(format!( - "pathinfo {:?} failed validation: {}", - pathinfo, e - )))?; - } - yield pathinfo - } - None => { - return; - }, - }, - Err(e) => Err(Error::StorageError(e.to_string()))?, - } - } - }; +impl TryFrom<url::Url> for GRPCPathInfoServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + // normally grpc+unix for unix sockets, and grpc+http(s) for the HTTP counterparts. + // - In the case of unix sockets, there must be a path, but may not be a host. + // - In the case of non-unix sockets, there must be a host, but no path. + // Constructing the channel is handled by tvix_castore::channel::from_url. + Ok(GRPCPathInfoServiceConfig { + url: url.to_string(), + }) + } +} - Box::pin(stream) +#[async_trait] +impl ServiceBuilder for GRPCPathInfoServiceConfig { + type Output = dyn PathInfoService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn PathInfoService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + let client = proto::path_info_service_client::PathInfoServiceClient::new( + tvix_castore::tonic::channel_from_url(&self.url.parse()?).await?, + ); + Ok(Arc::new(GRPCPathInfoService::from_client(client))) } } #[cfg(test)] mod tests { - use std::sync::Arc; - use std::time::Duration; - - use rstest::*; - use tempfile::TempDir; - use tokio::net::UnixListener; - use tokio_retry::strategy::ExponentialBackoff; - use tokio_retry::Retry; - use tokio_stream::wrappers::UnixListenerStream; - use tvix_castore::blobservice::BlobService; - use tvix_castore::directoryservice::DirectoryService; - - use crate::pathinfoservice::MemoryPathInfoService; - use crate::proto::path_info_service_client::PathInfoServiceClient; - use crate::proto::GRPCPathInfoServiceWrapper; - use crate::tests::fixtures::{self, blob_service, directory_service}; - - use super::GRPCPathInfoService; - use super::PathInfoService; + use crate::pathinfoservice::tests::make_grpc_path_info_service_client; + use crate::pathinfoservice::PathInfoService; + use crate::tests::fixtures; /// This ensures connecting via gRPC works as expected. - #[rstest] #[tokio::test] - async fn test_valid_unix_path_ping_pong( - blob_service: Arc<dyn BlobService>, - directory_service: Arc<dyn DirectoryService>, - ) { - let tmpdir = TempDir::new().unwrap(); - let socket_path = tmpdir.path().join("daemon"); - - let path_clone = socket_path.clone(); - - // Spin up a server - tokio::spawn(async { - let uds = UnixListener::bind(path_clone).unwrap(); - let uds_stream = UnixListenerStream::new(uds); - - // spin up a new server - let mut server = tonic::transport::Server::builder(); - let router = server.add_service( - crate::proto::path_info_service_server::PathInfoServiceServer::new( - GRPCPathInfoServiceWrapper::new(Box::new(MemoryPathInfoService::new( - blob_service, - directory_service, - )) - as Box<dyn PathInfoService>), - ), - ); - router.serve_with_incoming(uds_stream).await - }); - - // wait for the socket to be created - Retry::spawn( - ExponentialBackoff::from_millis(20).max_delay(Duration::from_secs(10)), - || async { - if socket_path.exists() { - Ok(()) - } else { - Err(()) - } - }, - ) - .await - .expect("failed to wait for socket"); - - // prepare a client - let grpc_client = { - let url = url::Url::parse(&format!("grpc+unix://{}", socket_path.display())) - .expect("must parse"); - let client = PathInfoServiceClient::new( - tvix_castore::tonic::channel_from_url(&url) - .await - .expect("must succeed"), - ); - - GRPCPathInfoService::from_client(client) - }; + async fn test_valid_unix_path_ping_pong() { + let (_blob_service, _directory_service, path_info_service) = + make_grpc_path_info_service_client().await; - let path_info = grpc_client + let path_info = path_info_service .get(fixtures::DUMMY_PATH_DIGEST) .await .expect("must not be error"); diff --git a/tvix/store/src/pathinfoservice/lru.rs b/tvix/store/src/pathinfoservice/lru.rs new file mode 100644 index 000000000000..3055d73c22f9 --- /dev/null +++ b/tvix/store/src/pathinfoservice/lru.rs @@ -0,0 +1,142 @@ +use async_stream::try_stream; +use futures::stream::BoxStream; +use lru::LruCache; +use nix_compat::nixbase32; +use std::num::NonZeroUsize; +use std::sync::Arc; +use tokio::sync::RwLock; +use tonic::async_trait; +use tracing::instrument; + +use tvix_castore::composition::{CompositionContext, ServiceBuilder}; +use tvix_castore::Error; + +use super::{PathInfo, PathInfoService}; + +pub struct LruPathInfoService { + lru: Arc<RwLock<LruCache<[u8; 20], PathInfo>>>, +} + +impl LruPathInfoService { + pub fn with_capacity(capacity: NonZeroUsize) -> Self { + Self { + lru: Arc::new(RwLock::new(LruCache::new(capacity))), + } + } +} + +#[async_trait] +impl PathInfoService for LruPathInfoService { + #[instrument(level = "trace", skip_all, fields(path_info.digest = nixbase32::encode(&digest)))] + async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error> { + Ok(self.lru.write().await.get(&digest).cloned()) + } + + #[instrument(level = "trace", skip_all, fields(path_info.root_node = ?path_info.node))] + async fn put(&self, path_info: PathInfo) -> Result<PathInfo, Error> { + self.lru + .write() + .await + .put(*path_info.store_path.digest(), path_info.clone()); + + Ok(path_info) + } + + fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { + let lru = self.lru.clone(); + Box::pin(try_stream! { + let lru = lru.read().await; + let it = lru.iter(); + + for (_k,v) in it { + yield v.clone() + } + }) + } +} + +#[derive(serde::Deserialize, Debug)] +#[serde(deny_unknown_fields)] +pub struct LruPathInfoServiceConfig { + capacity: NonZeroUsize, +} + +impl TryFrom<url::Url> for LruPathInfoServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(_url: url::Url) -> Result<Self, Self::Error> { + Err(Error::StorageError( + "Instantiating a LruPathInfoService from a url is not supported".into(), + ) + .into()) + } +} + +#[async_trait] +impl ServiceBuilder for LruPathInfoServiceConfig { + type Output = dyn PathInfoService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn PathInfoService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + Ok(Arc::new(LruPathInfoService::with_capacity(self.capacity))) + } +} + +#[cfg(test)] +mod test { + use nix_compat::store_path::StorePath; + use std::{num::NonZeroUsize, sync::LazyLock}; + + use crate::{ + pathinfoservice::{LruPathInfoService, PathInfo, PathInfoService}, + tests::fixtures::PATH_INFO, + }; + static PATHINFO_2: LazyLock<PathInfo> = LazyLock::new(|| { + let mut p = PATH_INFO.clone(); + p.store_path = StorePath::from_name_and_digest_fixed("dummy", [1; 20]).unwrap(); + p + }); + + static PATHINFO_2_DIGEST: LazyLock<[u8; 20]> = + LazyLock::new(|| *PATHINFO_2.store_path.digest()); + + #[tokio::test] + async fn evict() { + let svc = LruPathInfoService::with_capacity(NonZeroUsize::new(1).unwrap()); + + // pathinfo_1 should not be there + assert!(svc + .get(*PATH_INFO.store_path.digest()) + .await + .expect("no error") + .is_none()); + + // insert it + svc.put(PATH_INFO.clone()).await.expect("no error"); + + // now it should be there. + assert_eq!( + Some(PATH_INFO.clone()), + svc.get(*PATH_INFO.store_path.digest()) + .await + .expect("no error") + ); + + // insert pathinfo_2. This will evict pathinfo 1 + svc.put(PATHINFO_2.clone()).await.expect("no error"); + + // now pathinfo 2 should be there. + assert_eq!( + Some(PATHINFO_2.clone()), + svc.get(*PATHINFO_2_DIGEST).await.expect("no error") + ); + + // … but pathinfo 1 not anymore. + assert!(svc + .get(*PATH_INFO.store_path.digest()) + .await + .expect("no error") + .is_none()); + } +} diff --git a/tvix/store/src/pathinfoservice/memory.rs b/tvix/store/src/pathinfoservice/memory.rs index f8435dbbf809..fd013fe9a573 100644 --- a/tvix/store/src/pathinfoservice/memory.rs +++ b/tvix/store/src/pathinfoservice/memory.rs @@ -1,40 +1,24 @@ -use super::PathInfoService; -use crate::{nar::calculate_size_and_sha256, proto::PathInfo}; -use futures::stream::{iter, BoxStream}; -use std::{ - collections::HashMap, - sync::{Arc, RwLock}, -}; +use super::{PathInfo, PathInfoService}; +use async_stream::try_stream; +use futures::stream::BoxStream; +use nix_compat::nixbase32; +use std::{collections::HashMap, sync::Arc}; +use tokio::sync::RwLock; use tonic::async_trait; -use tvix_castore::proto as castorepb; +use tracing::instrument; +use tvix_castore::composition::{CompositionContext, ServiceBuilder}; use tvix_castore::Error; -use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService}; -pub struct MemoryPathInfoService<BS, DS> { +#[derive(Default)] +pub struct MemoryPathInfoService { db: Arc<RwLock<HashMap<[u8; 20], PathInfo>>>, - - blob_service: BS, - directory_service: DS, -} - -impl<BS, DS> MemoryPathInfoService<BS, DS> { - pub fn new(blob_service: BS, directory_service: DS) -> Self { - Self { - db: Default::default(), - blob_service, - directory_service, - } - } } #[async_trait] -impl<BS, DS> PathInfoService for MemoryPathInfoService<BS, DS> -where - BS: AsRef<dyn BlobService> + Send + Sync, - DS: AsRef<dyn DirectoryService> + Send + Sync, -{ +impl PathInfoService for MemoryPathInfoService { + #[instrument(level = "trace", skip_all, fields(path_info.digest = nixbase32::encode(&digest)))] async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error> { - let db = self.db.read().unwrap(); + let db = self.db.read().await; match db.get(&digest) { None => Ok(None), @@ -42,43 +26,52 @@ where } } + #[instrument(level = "trace", skip_all, fields(path_info.root_node = ?path_info.node))] async fn put(&self, path_info: PathInfo) -> Result<PathInfo, Error> { - // Call validate on the received PathInfo message. - match path_info.validate() { - Err(e) => Err(Error::InvalidRequest(format!( - "failed to validate PathInfo: {}", - e - ))), + // This overwrites existing PathInfo objects with the same store path digest. + let mut db = self.db.write().await; + db.insert(*path_info.store_path.digest(), path_info.clone()); - // In case the PathInfo is valid, and we were able to extract a NixPath, store it in the database. - // This overwrites existing PathInfo objects. - Ok(nix_path) => { - let mut db = self.db.write().unwrap(); - db.insert(*nix_path.digest(), path_info.clone()); - - Ok(path_info) - } - } + Ok(path_info) } - async fn calculate_nar( - &self, - root_node: &castorepb::node::Node, - ) -> Result<(u64, [u8; 32]), Error> { - calculate_size_and_sha256(root_node, &self.blob_service, &self.directory_service) - .await - .map_err(|e| Error::StorageError(e.to_string())) + fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { + let db = self.db.clone(); + + Box::pin(try_stream! { + let db = db.read().await; + let it = db.iter(); + + for (_k, v) in it { + yield v.clone() + } + }) } +} - fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { - let db = self.db.read().unwrap(); +#[derive(serde::Deserialize, Debug)] +#[serde(deny_unknown_fields)] +pub struct MemoryPathInfoServiceConfig {} - // Copy all elements into a list. - // This is a bit ugly, because we can't have db escape the lifetime - // of this function, but elements need to be returned owned anyways, and this in- - // memory impl is only for testing purposes anyways. - let items: Vec<_> = db.iter().map(|(_k, v)| Ok(v.clone())).collect(); +impl TryFrom<url::Url> for MemoryPathInfoServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + // memory doesn't support host or path in the URL. + if url.has_host() || !url.path().is_empty() { + return Err(Error::StorageError("invalid url".to_string()).into()); + } + Ok(MemoryPathInfoServiceConfig {}) + } +} - Box::pin(iter(items)) +#[async_trait] +impl ServiceBuilder for MemoryPathInfoServiceConfig { + type Output = dyn PathInfoService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn PathInfoService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + Ok(Arc::new(MemoryPathInfoService::default())) } } diff --git a/tvix/store/src/pathinfoservice/mod.rs b/tvix/store/src/pathinfoservice/mod.rs index c1a482bbb5a8..d31a1e652e3b 100644 --- a/tvix/store/src/pathinfoservice/mod.rs +++ b/tvix/store/src/pathinfoservice/mod.rs @@ -1,8 +1,11 @@ +mod combinators; mod from_addr; mod grpc; +mod lru; mod memory; mod nix_http; -mod sled; +mod redb; +mod signing_wrapper; #[cfg(any(feature = "fuse", feature = "virtiofs"))] mod fs; @@ -10,29 +13,40 @@ mod fs; #[cfg(test)] mod tests; +use auto_impl::auto_impl; use futures::stream::BoxStream; use tonic::async_trait; -use tvix_castore::proto as castorepb; +use tvix_castore::composition::{Registry, ServiceBuilder}; use tvix_castore::Error; -use crate::proto::PathInfo; +use crate::nar::NarCalculationService; +pub use crate::path_info::PathInfo; +pub use self::combinators::{ + Cache as CachePathInfoService, CacheConfig as CachePathInfoServiceConfig, +}; pub use self::from_addr::from_addr; -pub use self::grpc::GRPCPathInfoService; -pub use self::memory::MemoryPathInfoService; -pub use self::nix_http::NixHTTPPathInfoService; -pub use self::sled::SledPathInfoService; +pub use self::grpc::{GRPCPathInfoService, GRPCPathInfoServiceConfig}; +pub use self::lru::{LruPathInfoService, LruPathInfoServiceConfig}; +pub use self::memory::{MemoryPathInfoService, MemoryPathInfoServiceConfig}; +pub use self::nix_http::{NixHTTPPathInfoService, NixHTTPPathInfoServiceConfig}; +pub use self::redb::{RedbPathInfoService, RedbPathInfoServiceConfig}; +pub use self::signing_wrapper::{KeyFileSigningPathInfoServiceConfig, SigningPathInfoService}; + +#[cfg(test)] +pub(crate) use self::signing_wrapper::test_signing_service; #[cfg(feature = "cloud")] mod bigtable; #[cfg(feature = "cloud")] -pub use self::bigtable::BigtablePathInfoService; +pub use self::bigtable::{BigtableParameters, BigtablePathInfoService}; #[cfg(any(feature = "fuse", feature = "virtiofs"))] pub use self::fs::make_fs; /// The base trait all PathInfo services need to implement. #[async_trait] +#[auto_impl(&, &mut, Arc, Box)] pub trait PathInfoService: Send + Sync { /// Retrieve a PathInfo message by the output digest. async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error>; @@ -41,14 +55,6 @@ pub trait PathInfoService: Send + Sync { /// invalid messages. async fn put(&self, path_info: PathInfo) -> Result<PathInfo, Error>; - /// Return the nar size and nar sha256 digest for a given root node. - /// This can be used to calculate NAR-based output paths, - /// and implementations are encouraged to cache it. - async fn calculate_nar( - &self, - root_node: &castorepb::node::Node, - ) -> Result<(u64, [u8; 32]), Error>; - /// Iterate over all PathInfo objects in the store. /// Implementations can decide to disallow listing. /// @@ -57,29 +63,27 @@ pub trait PathInfoService: Send + Sync { /// Rust doesn't support this as a generic in traits yet. This is the same thing that /// [async_trait] generates, but for streams instead of futures. fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>>; -} - -#[async_trait] -impl<A> PathInfoService for A -where - A: AsRef<dyn PathInfoService> + Send + Sync, -{ - async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error> { - self.as_ref().get(digest).await - } - async fn put(&self, path_info: PathInfo) -> Result<PathInfo, Error> { - self.as_ref().put(path_info).await - } - - async fn calculate_nar( - &self, - root_node: &castorepb::node::Node, - ) -> Result<(u64, [u8; 32]), Error> { - self.as_ref().calculate_nar(root_node).await + /// Returns a (more) suitable NarCalculationService. + /// This can be used to offload NAR calculation to the remote side. + fn nar_calculation_service(&self) -> Option<Box<dyn NarCalculationService>> { + None } +} - fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { - self.as_ref().list() +/// Registers the builtin PathInfoService implementations with the registry +pub(crate) fn register_pathinfo_services(reg: &mut Registry) { + reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, CachePathInfoServiceConfig>("cache"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, GRPCPathInfoServiceConfig>("grpc"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, LruPathInfoServiceConfig>("lru"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, MemoryPathInfoServiceConfig>("memory"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, NixHTTPPathInfoServiceConfig>("nix"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, RedbPathInfoServiceConfig>("redb"); + reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, KeyFileSigningPathInfoServiceConfig>("keyfile-signing"); + #[cfg(feature = "cloud")] + { + reg.register::<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>, BigtableParameters>( + "bigtable", + ); } } diff --git a/tvix/store/src/pathinfoservice/nix_http.rs b/tvix/store/src/pathinfoservice/nix_http.rs index bdb0e2c3cba7..29e04aa45867 100644 --- a/tvix/store/src/pathinfoservice/nix_http.rs +++ b/tvix/store/src/pathinfoservice/nix_http.rs @@ -1,23 +1,20 @@ -use std::io::{self, BufRead, Read, Write}; - -use data_encoding::BASE64; +use super::{PathInfo, PathInfoService}; +use crate::nar::ingest_nar_and_hash; use futures::{stream::BoxStream, TryStreamExt}; use nix_compat::{ - narinfo::{self, NarInfo}, + narinfo::{self, NarInfo, Signature}, nixbase32, nixhash::NixHash, + store_path::StorePath, }; use reqwest::StatusCode; -use sha2::{digest::FixedOutput, Digest, Sha256}; +use std::sync::Arc; +use tokio::io::{self, AsyncRead}; use tonic::async_trait; use tracing::{debug, instrument, warn}; -use tvix_castore::{ - blobservice::BlobService, directoryservice::DirectoryService, proto as castorepb, Error, -}; - -use crate::proto::PathInfo; - -use super::PathInfoService; +use tvix_castore::composition::{CompositionContext, ServiceBuilder}; +use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService, Error}; +use url::Url; /// NixHTTPPathInfoService acts as a bridge in between the Nix HTTP Binary cache /// protocol provided by Nix binary caches such as cache.nixos.org, and the Tvix @@ -32,26 +29,27 @@ use super::PathInfoService; /// /// The client is expected to be (indirectly) using the same [BlobService] and /// [DirectoryService], so able to fetch referred Directories and Blobs. -/// [PathInfoService::put] and [PathInfoService::calculate_nar] are not -/// implemented and return an error if called. +/// [PathInfoService::put] is not implemented and returns an error if called. /// TODO: what about reading from nix-cache-info? pub struct NixHTTPPathInfoService<BS, DS> { base_url: url::Url, - http_client: reqwest::Client, + http_client: reqwest_middleware::ClientWithMiddleware, blob_service: BS, directory_service: DS, /// An optional list of [narinfo::PubKey]. /// If set, the .narinfo files received need to have correct signature by at least one of these. - public_keys: Option<Vec<narinfo::PubKey>>, + public_keys: Option<Vec<narinfo::VerifyingKey>>, } impl<BS, DS> NixHTTPPathInfoService<BS, DS> { pub fn new(base_url: url::Url, blob_service: BS, directory_service: DS) -> Self { Self { base_url, - http_client: reqwest::Client::new(), + http_client: reqwest_middleware::ClientBuilder::new(reqwest::Client::new()) + .with(tvix_tracing::propagate::reqwest::tracing_middleware()) + .build(), blob_service, directory_service, @@ -60,7 +58,7 @@ impl<BS, DS> NixHTTPPathInfoService<BS, DS> { } /// Configures [Self] to validate NARInfo fingerprints with the public keys passed. - pub fn set_public_keys(&mut self, public_keys: Vec<narinfo::PubKey>) { + pub fn set_public_keys(&mut self, public_keys: Vec<narinfo::VerifyingKey>) { self.public_keys = Some(public_keys); } } @@ -68,10 +66,10 @@ impl<BS, DS> NixHTTPPathInfoService<BS, DS> { #[async_trait] impl<BS, DS> PathInfoService for NixHTTPPathInfoService<BS, DS> where - BS: AsRef<dyn BlobService> + Send + Sync + Clone + 'static, - DS: AsRef<dyn DirectoryService> + Send + Sync + Clone + 'static, + BS: BlobService + Send + Sync + Clone + 'static, + DS: DirectoryService + Send + Sync + Clone + 'static, { - #[instrument(skip_all, err, fields(path.digest=BASE64.encode(&digest)))] + #[instrument(skip_all, err, fields(path.digest=nixbase32::encode(&digest)))] async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error> { let narinfo_url = self .base_url @@ -138,12 +136,11 @@ where } } - // Convert to a (sparse) PathInfo. We still need to populate the node field, - // and for this we need to download the NAR file. + // To construct the full PathInfo, we also need to populate the node field, + // and for this we need to download the NAR file and ingest it into castore. // FUTUREWORK: Keep some database around mapping from narsha256 to // (unnamed) rootnode, so we can use that (and the name from the // StorePath) and avoid downloading the same NAR a second time. - let pathinfo: PathInfo = (&narinfo).into(); // create a request for the NAR file itself. let nar_url = self.base_url.join(narinfo.url).map_err(|e| { @@ -171,85 +168,77 @@ where ))); } - // get an AsyncRead of the response body. - let async_r = tokio_util::io::StreamReader::new(resp.bytes_stream().map_err(|e| { + // get a reader of the response body. + let r = tokio_util::io::StreamReader::new(resp.bytes_stream().map_err(|e| { let e = e.without_url(); warn!(e=%e, "failed to get response body"); io::Error::new(io::ErrorKind::BrokenPipe, e.to_string()) })); - let sync_r = tokio_util::io::SyncIoBridge::new(async_r); - // handle decompression, by wrapping the reader. - let sync_r: Box<dyn BufRead + Send> = match narinfo.compression { - Some("none") => Box::new(sync_r), - Some("xz") => Box::new(io::BufReader::new(xz2::read::XzDecoder::new(sync_r))), - Some(comp) => { - return Err(Error::InvalidRequest( - format!("unsupported compression: {}", comp).to_string(), - )) - } - None => { - return Err(Error::InvalidRequest( - "unsupported compression: bzip2".to_string(), - )) + // handle decompression, depending on the compression field. + let mut r: Box<dyn AsyncRead + Send + Unpin> = match narinfo.compression { + None => Box::new(r) as Box<dyn AsyncRead + Send + Unpin>, + Some("bzip2") => Box::new(async_compression::tokio::bufread::BzDecoder::new(r)) + as Box<dyn AsyncRead + Send + Unpin>, + Some("gzip") => Box::new(async_compression::tokio::bufread::GzipDecoder::new(r)) + as Box<dyn AsyncRead + Send + Unpin>, + Some("xz") => Box::new(async_compression::tokio::bufread::XzDecoder::new(r)) + as Box<dyn AsyncRead + Send + Unpin>, + Some("zstd") => Box::new(async_compression::tokio::bufread::ZstdDecoder::new(r)) + as Box<dyn AsyncRead + Send + Unpin>, + Some(comp_str) => { + return Err(Error::StorageError(format!( + "unsupported compression: {comp_str}" + ))); } }; - let res = tokio::task::spawn_blocking({ - let blob_service = self.blob_service.clone(); - let directory_service = self.directory_service.clone(); - move || -> io::Result<_> { - // Wrap the reader once more, so we can calculate NarSize and NarHash - let mut sync_r = io::BufReader::new(NarReader::from(sync_r)); - let root_node = crate::nar::read_nar(&mut sync_r, blob_service, directory_service)?; - - let (_, nar_hash, nar_size) = sync_r.into_inner().into_inner(); - - Ok((root_node, nar_hash, nar_size)) - } - }) + let (root_node, nar_hash, nar_size) = ingest_nar_and_hash( + self.blob_service.clone(), + self.directory_service.clone(), + &mut r, + ) .await - .unwrap(); - - match res { - Ok((root_node, nar_hash, nar_size)) => { - // ensure the ingested narhash and narsize do actually match. - if narinfo.nar_size != nar_size { - warn!( - narinfo.nar_size = narinfo.nar_size, - http.nar_size = nar_size, - "NARSize mismatch" - ); - Err(io::Error::new( - io::ErrorKind::InvalidData, - "NarSize mismatch".to_string(), - ))?; - } - if narinfo.nar_hash != nar_hash { - warn!( - narinfo.nar_hash = %NixHash::Sha256(narinfo.nar_hash), - http.nar_hash = %NixHash::Sha256(nar_hash), - "NarHash mismatch" - ); - Err(io::Error::new( - io::ErrorKind::InvalidData, - "NarHash mismatch".to_string(), - ))?; - } - - Ok(Some(PathInfo { - node: Some(castorepb::Node { - // set the name of the root node to the digest-name of the store path. - node: Some( - root_node.rename(narinfo.store_path.to_string().to_owned().into()), - ), - }), - references: pathinfo.references, - narinfo: pathinfo.narinfo, - })) - } - Err(e) => Err(e.into()), + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + + // ensure the ingested narhash and narsize do actually match. + if narinfo.nar_size != nar_size { + warn!( + narinfo.nar_size = narinfo.nar_size, + http.nar_size = nar_size, + "NarSize mismatch" + ); + Err(io::Error::new( + io::ErrorKind::InvalidData, + "NarSize mismatch".to_string(), + ))?; } + if narinfo.nar_hash != nar_hash { + warn!( + narinfo.nar_hash = %NixHash::Sha256(narinfo.nar_hash), + http.nar_hash = %NixHash::Sha256(nar_hash), + "NarHash mismatch" + ); + Err(io::Error::new( + io::ErrorKind::InvalidData, + "NarHash mismatch".to_string(), + ))?; + } + + Ok(Some(PathInfo { + store_path: narinfo.store_path.to_owned(), + node: root_node, + references: narinfo.references.iter().map(StorePath::to_owned).collect(), + nar_size: narinfo.nar_size, + nar_sha256: narinfo.nar_hash, + deriver: narinfo.deriver.as_ref().map(StorePath::to_owned), + signatures: narinfo + .signatures + .into_iter() + .map(|s| Signature::<String>::new(s.name().to_string(), s.bytes().to_owned())) + .collect(), + ca: narinfo.ca, + })) } #[instrument(skip_all, fields(path_info=?_path_info))] @@ -259,16 +248,6 @@ where )) } - #[instrument(skip_all, fields(root_node=?root_node))] - async fn calculate_nar( - &self, - root_node: &castorepb::node::Node, - ) -> Result<(u64, [u8; 32]), Error> { - Err(Error::InvalidRequest( - "calculate_nar not supported for this backend".to_string(), - )) - } - fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { Box::pin(futures::stream::once(async { Err(Error::InvalidRequest( @@ -278,37 +257,86 @@ where } } -/// Small helper reader implementing [std::io::Read]. -/// It can be used to wrap another reader, counts the number of bytes read -/// and the sha256 digest of the contents. -struct NarReader<R: Read> { - r: R, - - sha256: sha2::Sha256, - bytes_read: u64, +#[derive(serde::Deserialize)] +pub struct NixHTTPPathInfoServiceConfig { + base_url: String, + blob_service: String, + directory_service: String, + #[serde(default)] + /// An optional list of [narinfo::PubKey]. + /// If set, the .narinfo files received need to have correct signature by at least one of these. + public_keys: Option<Vec<String>>, } -impl<R: Read> NarReader<R> { - pub fn from(inner: R) -> Self { - Self { - r: inner, - sha256: Sha256::new(), - bytes_read: 0, +impl TryFrom<Url> for NixHTTPPathInfoServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: Url) -> Result<Self, Self::Error> { + // Be careful about the distinction between `None` and `Some(vec![])`! + let mut public_keys: Option<Vec<String>> = None; + for (_, v) in url + .query_pairs() + .into_iter() + .filter(|(k, _)| k == "trusted-public-keys") + { + public_keys + .get_or_insert(Default::default()) + .extend(v.split_ascii_whitespace().map(ToString::to_string)); } - } - /// Returns the (remaining) inner reader, the sha256 digest and the number of bytes read. - pub fn into_inner(self) -> (R, [u8; 32], u64) { - (self.r, self.sha256.finalize_fixed().into(), self.bytes_read) + // FUTUREWORK: move url deserialization to serde? + let blob_service = url + .query_pairs() + .into_iter() + .find(|(k, _)| k == "blob_service") + .map(|(_, v)| v.to_string()) + .unwrap_or("default".to_string()); + let directory_service = url + .query_pairs() + .into_iter() + .find(|(k, _)| k == "directory_service") + .map(|(_, v)| v.to_string()) + .unwrap_or("default".to_string()); + + Ok(NixHTTPPathInfoServiceConfig { + // Stringify the URL and remove the nix+ prefix. + // We can't use `url.set_scheme(rest)`, as it disallows + // setting something http(s) that previously wasn't. + base_url: url.to_string().strip_prefix("nix+").unwrap().to_string(), + blob_service, + directory_service, + public_keys, + }) } } -impl<R: Read> Read for NarReader<R> { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - self.r.read(buf).map(|n| { - self.bytes_read += n as u64; - self.sha256.write_all(&buf[..n]).unwrap(); - n - }) +#[async_trait] +impl ServiceBuilder for NixHTTPPathInfoServiceConfig { + type Output = dyn PathInfoService; + async fn build<'a>( + &'a self, + _instance_name: &str, + context: &CompositionContext, + ) -> Result<Arc<Self::Output>, Box<dyn std::error::Error + Send + Sync + 'static>> { + let (blob_service, directory_service) = futures::join!( + context.resolve::<dyn BlobService>(self.blob_service.clone()), + context.resolve::<dyn DirectoryService>(self.directory_service.clone()) + ); + let mut svc = NixHTTPPathInfoService::new( + Url::parse(&self.base_url)?, + blob_service?, + directory_service?, + ); + if let Some(public_keys) = &self.public_keys { + svc.set_public_keys( + public_keys + .iter() + .map(|pubkey_str| { + narinfo::VerifyingKey::parse(pubkey_str) + .map_err(|e| Error::StorageError(format!("invalid public key: {e}"))) + }) + .collect::<Result<Vec<_>, Error>>()?, + ); + } + Ok(Arc::new(svc)) } } diff --git a/tvix/store/src/pathinfoservice/redb.rs b/tvix/store/src/pathinfoservice/redb.rs new file mode 100644 index 000000000000..6e794e1981f0 --- /dev/null +++ b/tvix/store/src/pathinfoservice/redb.rs @@ -0,0 +1,221 @@ +use super::{PathInfo, PathInfoService}; +use crate::proto; +use data_encoding::BASE64; +use futures::{stream::BoxStream, StreamExt}; +use prost::Message; +use redb::{Database, ReadableTable, TableDefinition}; +use std::{path::PathBuf, sync::Arc}; +use tokio_stream::wrappers::ReceiverStream; +use tonic::async_trait; +use tracing::{instrument, warn}; +use tvix_castore::{ + composition::{CompositionContext, ServiceBuilder}, + Error, +}; + +const PATHINFO_TABLE: TableDefinition<[u8; 20], Vec<u8>> = TableDefinition::new("pathinfo"); + +/// PathInfoService implementation using redb under the hood. +/// redb stores all of its data in a single file with a K/V pointing from a path's output hash to +/// its corresponding protobuf-encoded PathInfo. +pub struct RedbPathInfoService { + // We wrap db in an Arc to be able to move it into spawn_blocking, + // as discussed in https://github.com/cberner/redb/issues/789 + db: Arc<Database>, +} + +impl RedbPathInfoService { + /// Constructs a new instance using the specified file system path for + /// storage. + pub async fn new(path: PathBuf) -> Result<Self, Error> { + if path == PathBuf::from("/") { + return Err(Error::StorageError( + "cowardly refusing to open / with redb".to_string(), + )); + } + + let db = tokio::task::spawn_blocking(|| -> Result<_, redb::Error> { + let db = redb::Database::create(path)?; + create_schema(&db)?; + Ok(db) + }) + .await??; + + Ok(Self { db: Arc::new(db) }) + } + + /// Constructs a new instance using the in-memory backend. + pub fn new_temporary() -> Result<Self, Error> { + let db = + redb::Database::builder().create_with_backend(redb::backends::InMemoryBackend::new())?; + + create_schema(&db)?; + + Ok(Self { db: Arc::new(db) }) + } +} + +/// Ensures all tables are present. +/// Opens a write transaction and calls open_table on PATHINFO_TABLE, which will +/// create it if not present. +fn create_schema(db: &redb::Database) -> Result<(), redb::Error> { + let txn = db.begin_write()?; + txn.open_table(PATHINFO_TABLE)?; + txn.commit()?; + + Ok(()) +} + +#[async_trait] +impl PathInfoService for RedbPathInfoService { + #[instrument(level = "trace", skip_all, fields(path_info.digest = BASE64.encode(&digest)))] + async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error> { + let db = self.db.clone(); + + tokio::task::spawn_blocking({ + move || { + let txn = db.begin_read()?; + let table = txn.open_table(PATHINFO_TABLE)?; + match table.get(digest)? { + Some(pathinfo_bytes) => Ok(Some( + proto::PathInfo::decode(pathinfo_bytes.value().as_slice()) + .map_err(|e| { + warn!(err=%e, "failed to decode stored PathInfo"); + Error::StorageError("failed to decode stored PathInfo".to_string()) + })? + .try_into() + .map_err(|e| Error::StorageError(format!("Invalid path info: {e}")))?, + )), + None => Ok(None), + } + } + }) + .await? + } + + #[instrument(level = "trace", skip_all, fields(path_info.root_node = ?path_info.node))] + async fn put(&self, path_info: PathInfo) -> Result<PathInfo, Error> { + let db = self.db.clone(); + + tokio::task::spawn_blocking({ + let path_info = path_info.clone(); + move || -> Result<(), Error> { + let txn = db.begin_write()?; + { + let mut table = txn.open_table(PATHINFO_TABLE)?; + table + .insert( + *path_info.store_path.digest(), + proto::PathInfo::from(path_info).encode_to_vec(), + ) + .map_err(|e| { + warn!(err=%e, "failed to insert PathInfo"); + Error::StorageError("failed to insert PathInfo".to_string()) + })?; + } + Ok(txn.commit()?) + } + }) + .await??; + + Ok(path_info) + } + + fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { + let db = self.db.clone(); + let (tx, rx) = tokio::sync::mpsc::channel(50); + + // Spawn a blocking task which writes all PathInfos to tx. + tokio::task::spawn_blocking({ + move || -> Result<(), Error> { + let read_txn = db.begin_read()?; + let table = read_txn.open_table(PATHINFO_TABLE)?; + + for elem in table.iter()? { + let elem = elem?; + tokio::runtime::Handle::current() + .block_on(tx.send(Ok({ + let path_info_proto = proto::PathInfo::decode( + elem.1.value().as_slice(), + ) + .map_err(|e| { + warn!(err=%e, "invalid PathInfo"); + Error::StorageError("invalid PathInfo".to_string()) + })?; + PathInfo::try_from(path_info_proto).map_err(|e| { + Error::StorageError(format!("Invalid path info: {e}")) + })? + }))) + .map_err(|e| Error::StorageError(e.to_string()))?; + } + + Ok(()) + } + }); + + ReceiverStream::from(rx).boxed() + } +} + +#[derive(serde::Deserialize)] +#[serde(deny_unknown_fields)] +pub struct RedbPathInfoServiceConfig { + is_temporary: bool, + #[serde(default)] + /// required when is_temporary = false + path: Option<PathBuf>, +} + +impl TryFrom<url::Url> for RedbPathInfoServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(url: url::Url) -> Result<Self, Self::Error> { + // redb doesn't support host, and a path can be provided (otherwise it'll live in memory only) + if url.has_host() { + return Err(Error::StorageError("no host allowed".to_string()).into()); + } + + Ok(if url.path().is_empty() { + RedbPathInfoServiceConfig { + is_temporary: true, + path: None, + } + } else { + RedbPathInfoServiceConfig { + is_temporary: false, + path: Some(url.path().into()), + } + }) + } +} + +#[async_trait] +impl ServiceBuilder for RedbPathInfoServiceConfig { + type Output = dyn PathInfoService; + async fn build<'a>( + &'a self, + _instance_name: &str, + _context: &CompositionContext, + ) -> Result<Arc<dyn PathInfoService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + match self { + RedbPathInfoServiceConfig { + is_temporary: true, + path: None, + } => Ok(Arc::new(RedbPathInfoService::new_temporary()?)), + RedbPathInfoServiceConfig { + is_temporary: true, + path: Some(_), + } => Err( + Error::StorageError("Temporary RedbPathInfoService can not have path".into()) + .into(), + ), + RedbPathInfoServiceConfig { + is_temporary: false, + path: None, + } => Err(Error::StorageError("RedbPathInfoService is missing path".into()).into()), + RedbPathInfoServiceConfig { + is_temporary: false, + path: Some(path), + } => Ok(Arc::new(RedbPathInfoService::new(path.to_owned()).await?)), + } + } +} diff --git a/tvix/store/src/pathinfoservice/signing_wrapper.rs b/tvix/store/src/pathinfoservice/signing_wrapper.rs new file mode 100644 index 000000000000..525e60e416a8 --- /dev/null +++ b/tvix/store/src/pathinfoservice/signing_wrapper.rs @@ -0,0 +1,190 @@ +//! This module provides a [PathInfoService] implementation that signs narinfos + +use super::{PathInfo, PathInfoService}; +use futures::stream::BoxStream; +use std::path::PathBuf; +use std::sync::Arc; +use tonic::async_trait; + +use tvix_castore::composition::{CompositionContext, ServiceBuilder}; + +use tvix_castore::Error; + +use nix_compat::narinfo::{parse_keypair, Signature, SigningKey}; +use nix_compat::nixbase32; +use tracing::instrument; + +#[cfg(test)] +use super::MemoryPathInfoService; + +/// PathInfoService that wraps around an inner [PathInfoService] and when put is called it extracts +/// the underlying narinfo and signs it using a [SigningKey]. For the moment only the +/// [ed25519::signature::Signer<ed25519::Signature>] is available using a keyfile (see +/// [KeyFileSigningPathInfoServiceConfig] for more informations). However the implementation is +/// generic (see [nix_compat::narinfo::SigningKey] documentation). +/// +/// The [PathInfo] with the added signature is then put into the inner [PathInfoService]. +/// +/// The service signs the [PathInfo] **only if it has a narinfo attribute** +pub struct SigningPathInfoService<T, S> { + /// The inner [PathInfoService] + inner: T, + /// The key to sign narinfos + signing_key: Arc<SigningKey<S>>, +} + +impl<T, S> SigningPathInfoService<T, S> { + pub fn new(inner: T, signing_key: Arc<SigningKey<S>>) -> Self { + Self { inner, signing_key } + } +} + +#[async_trait] +impl<T, S> PathInfoService for SigningPathInfoService<T, S> +where + T: PathInfoService, + S: ed25519::signature::Signer<ed25519::Signature> + Sync + Send, +{ + #[instrument(level = "trace", skip_all, fields(path_info.digest = nixbase32::encode(&digest)))] + async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error> { + self.inner.get(digest).await + } + + async fn put(&self, mut path_info: PathInfo) -> Result<PathInfo, Error> { + path_info.signatures.push({ + let mut nar_info = path_info.to_narinfo(); + nar_info.signatures.clear(); + nar_info.add_signature(self.signing_key.as_ref()); + + let s = nar_info + .signatures + .pop() + .expect("Tvix bug: no signature after signing op"); + debug_assert!( + nar_info.signatures.is_empty(), + "Tvix bug: more than one signature appeared" + ); + + Signature::new(s.name().to_string(), *s.bytes()) + }); + self.inner.put(path_info).await + } + + fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { + self.inner.list() + } +} + +/// [ServiceBuilder] implementation that builds a [SigningPathInfoService] that signs narinfos using +/// a keyfile. The keyfile is parsed using [parse_keypair], the expected format is the nix one +/// (`nix-store --generate-binary-cache-key` for more informations). +#[derive(serde::Deserialize)] +pub struct KeyFileSigningPathInfoServiceConfig { + /// Inner [PathInfoService], will be resolved using a [CompositionContext]. + pub inner: String, + /// Path to the keyfile in the nix format. It will be accessed once when building the service + pub keyfile: PathBuf, +} + +impl TryFrom<url::Url> for KeyFileSigningPathInfoServiceConfig { + type Error = Box<dyn std::error::Error + Send + Sync>; + fn try_from(_url: url::Url) -> Result<Self, Self::Error> { + Err(Error::StorageError( + "Instantiating a SigningPathInfoService from a url is not supported".into(), + ) + .into()) + } +} + +#[async_trait] +impl ServiceBuilder for KeyFileSigningPathInfoServiceConfig { + type Output = dyn PathInfoService; + async fn build<'a>( + &'a self, + _instance_name: &str, + context: &CompositionContext, + ) -> Result<Arc<dyn PathInfoService>, Box<dyn std::error::Error + Send + Sync + 'static>> { + let inner = context.resolve::<Self::Output>(self.inner.clone()).await?; + let signing_key = Arc::new( + parse_keypair(tokio::fs::read_to_string(&self.keyfile).await?.trim()) + .map_err(|e| Error::StorageError(e.to_string()))? + .0, + ); + Ok(Arc::new(SigningPathInfoService { inner, signing_key })) + } +} + +#[cfg(test)] +pub(crate) fn test_signing_service() -> Arc<dyn PathInfoService> { + let memory_svc: Arc<dyn PathInfoService> = Arc::new(MemoryPathInfoService::default()); + Arc::new(SigningPathInfoService { + inner: memory_svc, + signing_key: Arc::new( + parse_keypair(DUMMY_KEYPAIR) + .expect("DUMMY_KEYPAIR to be valid") + .0, + ), + }) +} + +#[cfg(test)] +pub const DUMMY_KEYPAIR: &str = "do.not.use:sGPzxuK5WvWPraytx+6sjtaff866sYlfvErE6x0hFEhy5eqe7OVZ8ZMqZ/ME/HaRdKGNGvJkyGKXYTaeA6lR3A=="; +#[cfg(test)] +pub const DUMMY_VERIFYING_KEY: &str = "do.not.use:cuXqnuzlWfGTKmfzBPx2kXShjRryZMhil2E2ngOpUdw="; + +#[cfg(test)] +mod test { + use crate::{pathinfoservice::PathInfoService, tests::fixtures::PATH_INFO}; + use nix_compat::narinfo::VerifyingKey; + + #[tokio::test] + async fn put_and_verify_signature() { + let svc = super::test_signing_service(); + + // Pick a PATH_INFO with 0 signatures… + assert!( + PATH_INFO.signatures.is_empty(), + "PathInfo from fixtures should have no signatures" + ); + + // Asking PathInfoService, it should not be there ... + assert!(svc + .get(*PATH_INFO.store_path.digest()) + .await + .expect("no error") + .is_none()); + + // insert it + svc.put(PATH_INFO.clone()).await.expect("no error"); + + // now it should be there ... + let path_info = svc + .get(*PATH_INFO.store_path.digest()) + .await + .expect("no error") + .unwrap(); + + // Ensure there's a signature now + let new_sig = path_info + .signatures + .last() + .expect("The retrieved narinfo to be signed") + .as_ref(); + + // load our keypair from the fixtures + let (signing_key, _verifying_key) = + super::parse_keypair(super::DUMMY_KEYPAIR).expect("must succeed"); + + // ensure that the new signature is using this key name + assert_eq!(signing_key.name(), *new_sig.name()); + + // verify the new signature against the verifying key + let verifying_key = + VerifyingKey::parse(super::DUMMY_VERIFYING_KEY).expect("parsing dummy verifying key"); + + assert!( + verifying_key.verify(&path_info.to_narinfo().fingerprint(), &new_sig), + "expect signature to be valid" + ); + } +} diff --git a/tvix/store/src/pathinfoservice/sled.rs b/tvix/store/src/pathinfoservice/sled.rs deleted file mode 100644 index 7b6d7fd7abcd..000000000000 --- a/tvix/store/src/pathinfoservice/sled.rs +++ /dev/null @@ -1,140 +0,0 @@ -use super::PathInfoService; -use crate::nar::calculate_size_and_sha256; -use crate::proto::PathInfo; -use futures::stream::iter; -use futures::stream::BoxStream; -use prost::Message; -use std::path::Path; -use tonic::async_trait; -use tracing::warn; -use tvix_castore::proto as castorepb; -use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService, Error}; - -/// SledPathInfoService stores PathInfo in a [sled](https://github.com/spacejam/sled). -/// -/// The PathInfo messages are stored as encoded protos, and keyed by their output hash, -/// as that's currently the only request type available. -pub struct SledPathInfoService<BS, DS> { - db: sled::Db, - - blob_service: BS, - directory_service: DS, -} - -impl<BS, DS> SledPathInfoService<BS, DS> { - pub fn new<P: AsRef<Path>>( - p: P, - blob_service: BS, - directory_service: DS, - ) -> Result<Self, sled::Error> { - let config = sled::Config::default() - .use_compression(false) // is a required parameter - .path(p); - let db = config.open()?; - - Ok(Self { - db, - blob_service, - directory_service, - }) - } - - pub fn new_temporary(blob_service: BS, directory_service: DS) -> Result<Self, sled::Error> { - let config = sled::Config::default().temporary(true); - let db = config.open()?; - - Ok(Self { - db, - blob_service, - directory_service, - }) - } -} - -#[async_trait] -impl<BS, DS> PathInfoService for SledPathInfoService<BS, DS> -where - BS: AsRef<dyn BlobService> + Send + Sync, - DS: AsRef<dyn DirectoryService> + Send + Sync, -{ - async fn get(&self, digest: [u8; 20]) -> Result<Option<PathInfo>, Error> { - match self.db.get(digest) { - Ok(None) => Ok(None), - Ok(Some(data)) => match PathInfo::decode(&*data) { - Ok(path_info) => Ok(Some(path_info)), - Err(e) => { - warn!("failed to decode stored PathInfo: {}", e); - Err(Error::StorageError(format!( - "failed to decode stored PathInfo: {}", - e - ))) - } - }, - Err(e) => { - warn!("failed to retrieve PathInfo: {}", e); - Err(Error::StorageError(format!( - "failed to retrieve PathInfo: {}", - e - ))) - } - } - } - - async fn put(&self, path_info: PathInfo) -> Result<PathInfo, Error> { - // Call validate on the received PathInfo message. - match path_info.validate() { - Err(e) => Err(Error::InvalidRequest(format!( - "failed to validate PathInfo: {}", - e - ))), - // In case the PathInfo is valid, and we were able to extract a NixPath, store it in the database. - // This overwrites existing PathInfo objects. - Ok(nix_path) => match self - .db - .insert(*nix_path.digest(), path_info.encode_to_vec()) - { - Ok(_) => Ok(path_info), - Err(e) => { - warn!("failed to insert PathInfo: {}", e); - Err(Error::StorageError(format! { - "failed to insert PathInfo: {}", e - })) - } - }, - } - } - - async fn calculate_nar( - &self, - root_node: &castorepb::node::Node, - ) -> Result<(u64, [u8; 32]), Error> { - calculate_size_and_sha256(root_node, &self.blob_service, &self.directory_service) - .await - .map_err(|e| Error::StorageError(e.to_string())) - } - - fn list(&self) -> BoxStream<'static, Result<PathInfo, Error>> { - Box::pin(iter(self.db.iter().values().map(|v| match v { - Ok(data) => { - // we retrieved some bytes - match PathInfo::decode(&*data) { - Ok(path_info) => Ok(path_info), - Err(e) => { - warn!("failed to decode stored PathInfo: {}", e); - Err(Error::StorageError(format!( - "failed to decode stored PathInfo: {}", - e - ))) - } - } - } - Err(e) => { - warn!("failed to retrieve PathInfo: {}", e); - Err(Error::StorageError(format!( - "failed to retrieve PathInfo: {}", - e - ))) - } - }))) - } -} diff --git a/tvix/store/src/pathinfoservice/tests/mod.rs b/tvix/store/src/pathinfoservice/tests/mod.rs index c9b9a0637767..12c685c80fad 100644 --- a/tvix/store/src/pathinfoservice/tests/mod.rs +++ b/tvix/store/src/pathinfoservice/tests/mod.rs @@ -2,64 +2,34 @@ //! We use [rstest] and [rstest_reuse] to provide all services we want to test //! against, and then apply this template to all test functions. +use futures::TryStreamExt; use rstest::*; use rstest_reuse::{self, *}; -use std::sync::Arc; -use tvix_castore::proto as castorepb; -use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService}; -use super::PathInfoService; -use crate::proto::PathInfo; -use crate::tests::fixtures::DUMMY_PATH_DIGEST; +use super::{PathInfo, PathInfoService}; +use crate::pathinfoservice::redb::RedbPathInfoService; +use crate::pathinfoservice::MemoryPathInfoService; +use crate::tests::fixtures::{DUMMY_PATH_DIGEST, PATH_INFO}; -mod utils; -use self::utils::make_grpc_path_info_service_client; - -/// Convenience type alias batching all three servives together. -#[allow(clippy::upper_case_acronyms)] -type BSDSPS = ( - Arc<dyn BlobService>, - Arc<dyn DirectoryService>, - Box<dyn PathInfoService>, -); +use crate::pathinfoservice::test_signing_service; -/// Creates a PathInfoService using a new Memory{Blob,Directory}Service. -/// We return a 3-tuple containing all of them, as some tests want to interact -/// with all three. -pub async fn make_path_info_service(uri: &str) -> BSDSPS { - let blob_service: Arc<dyn BlobService> = tvix_castore::blobservice::from_addr("memory://") - .await - .unwrap() - .into(); - let directory_service: Arc<dyn DirectoryService> = - tvix_castore::directoryservice::from_addr("memory://") - .await - .unwrap() - .into(); +mod utils; +pub use self::utils::make_grpc_path_info_service_client; - ( - blob_service.clone(), - directory_service.clone(), - crate::pathinfoservice::from_addr(uri, blob_service, directory_service) - .await - .unwrap(), - ) -} +#[cfg(all(feature = "cloud", feature = "integration"))] +use self::utils::make_bigtable_path_info_service; #[template] #[rstest] -#[case::memory(make_path_info_service("memory://").await)] -#[case::grpc(make_grpc_path_info_service_client().await)] -#[case::sled(make_path_info_service("sled://").await)] -#[cfg_attr(feature = "cloud", case::bigtable(make_path_info_service("bigtable://instance-1?project_id=project-1&table_name=table-1&family_name=cf1").await))] -pub fn path_info_services( - #[case] services: ( - impl BlobService, - impl DirectoryService, - impl PathInfoService, - ), -) { -} +#[case::memory(MemoryPathInfoService::default())] +#[case::grpc({ + let (_, _, svc) = make_grpc_path_info_service_client().await; + svc +})] +#[case::redb(RedbPathInfoService::new_temporary().unwrap())] +#[case::signing(test_signing_service())] +#[cfg_attr(all(feature = "cloud",feature="integration"), case::bigtable(make_bigtable_path_info_service().await))] +pub fn path_info_services(#[case] svc: impl PathInfoService) {} // FUTUREWORK: add more tests rejecting invalid PathInfo messages. // A subset of them should also ensure references to other PathInfos, or @@ -68,9 +38,8 @@ pub fn path_info_services( /// Trying to get a non-existent PathInfo should return Ok(None). #[apply(path_info_services)] #[tokio::test] -async fn not_found(services: BSDSPS) { - let (_, _, path_info_service) = services; - assert!(path_info_service +async fn not_found(svc: impl PathInfoService) { + assert!(svc .get(DUMMY_PATH_DIGEST) .await .expect("must succeed") @@ -80,34 +49,36 @@ async fn not_found(services: BSDSPS) { /// Put a PathInfo into the store, get it back. #[apply(path_info_services)] #[tokio::test] -async fn put_get(services: BSDSPS) { - let (_, _, path_info_service) = services; - - let path_info = PathInfo { - node: Some(castorepb::Node { - node: Some(castorepb::node::Node::Symlink(castorepb::SymlinkNode { - name: "00000000000000000000000000000000-foo".into(), - target: "doesntmatter".into(), - })), - }), - ..Default::default() - }; - +async fn put_get(svc: impl PathInfoService) { // insert - let resp = path_info_service - .put(path_info.clone()) - .await - .expect("must succeed"); + let resp = svc.put(PATH_INFO.clone()).await.expect("must succeed"); - // expect the returned PathInfo to be equal (for now) - // in the future, some stores might add additional fields/signatures. - assert_eq!(path_info, resp); + // expect the returned PathInfo to be equal, + // remove the signatures as the SigningPathInfoService adds them + assert_eq!(*PATH_INFO, strip_signatures(resp)); // get it back - let resp = path_info_service - .get(DUMMY_PATH_DIGEST) - .await - .expect("must succeed"); + let resp = svc.get(DUMMY_PATH_DIGEST).await.expect("must succeed"); + + assert_eq!(Some(PATH_INFO.clone()), resp.map(strip_signatures)); + + // Ensure the listing endpoint works, and returns the same path_info. + // FUTUREWORK: split this, some impls might (rightfully) not support listing + let pathinfos: Vec<PathInfo> = svc.list().try_collect().await.expect("must succeed"); + + // We should get a single pathinfo back, the one we inserted. + assert_eq!( + vec![PATH_INFO.clone()], + pathinfos + .into_iter() + .map(strip_signatures) + .collect::<Vec<_>>() + ); +} - assert_eq!(Some(path_info), resp); +fn strip_signatures(path_info: PathInfo) -> PathInfo { + PathInfo { + signatures: vec![], + ..path_info + } } diff --git a/tvix/store/src/pathinfoservice/tests/utils.rs b/tvix/store/src/pathinfoservice/tests/utils.rs index 31ec57aade73..8b192e303b89 100644 --- a/tvix/store/src/pathinfoservice/tests/utils.rs +++ b/tvix/store/src/pathinfoservice/tests/utils.rs @@ -1,8 +1,11 @@ use std::sync::Arc; +use hyper_util::rt::TokioIo; use tonic::transport::{Endpoint, Server, Uri}; +use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService}; use crate::{ + nar::{NarCalculationService, SimpleRenderer}, pathinfoservice::{GRPCPathInfoService, MemoryPathInfoService, PathInfoService}, proto::{ path_info_service_client::PathInfoServiceClient, @@ -14,7 +17,11 @@ use crate::{ /// Constructs and returns a gRPC PathInfoService. /// We also return memory-based {Blob,Directory}Service, /// as the consumer of this function accepts a 3-tuple. -pub async fn make_grpc_path_info_service_client() -> super::BSDSPS { +pub async fn make_grpc_path_info_service_client() -> ( + impl BlobService, + impl DirectoryService, + GRPCPathInfoService<tonic::transport::Channel>, +) { let (left, right) = tokio::io::duplex(64); let blob_service = blob_service(); @@ -26,12 +33,15 @@ pub async fn make_grpc_path_info_service_client() -> super::BSDSPS { let directory_service = directory_service.clone(); async move { let path_info_service: Arc<dyn PathInfoService> = - Arc::from(MemoryPathInfoService::new(blob_service, directory_service)); + Arc::from(MemoryPathInfoService::default()); + let nar_calculation_service = + Box::new(SimpleRenderer::new(blob_service, directory_service)) + as Box<dyn NarCalculationService>; - // spin up a new DirectoryService + // spin up a new PathInfoService let mut server = Server::builder(); let router = server.add_service(PathInfoServiceServer::new( - GRPCPathInfoServiceWrapper::new(path_info_service), + GRPCPathInfoServiceWrapper::new(path_info_service, nar_calculation_service), )); router @@ -43,18 +53,27 @@ pub async fn make_grpc_path_info_service_client() -> super::BSDSPS { // Create a client, connecting to the right side. The URI is unused. let mut maybe_right = Some(right); - let path_info_service = Box::new(GRPCPathInfoService::from_client( - PathInfoServiceClient::new( - Endpoint::try_from("http://[::]:50051") - .unwrap() - .connect_with_connector(tower::service_fn(move |_: Uri| { - let right = maybe_right.take().unwrap(); - async move { Ok::<_, std::io::Error>(right) } - })) - .await - .unwrap(), - ), + let path_info_service = GRPCPathInfoService::from_client(PathInfoServiceClient::new( + Endpoint::try_from("http://[::]:50051") + .unwrap() + .connect_with_connector(tower::service_fn(move |_: Uri| { + let right = maybe_right.take().unwrap(); + async move { Ok::<_, std::io::Error>(TokioIo::new(right)) } + })) + .await + .unwrap(), )); (blob_service, directory_service, path_info_service) } + +#[cfg(all(feature = "cloud", feature = "integration"))] +pub(crate) async fn make_bigtable_path_info_service( +) -> crate::pathinfoservice::BigtablePathInfoService { + use crate::pathinfoservice::bigtable::BigtableParameters; + use crate::pathinfoservice::BigtablePathInfoService; + + BigtablePathInfoService::connect(BigtableParameters::default_for_tests()) + .await + .unwrap() +} diff --git a/tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs b/tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs index 9f458182274d..4325e79d5077 100644 --- a/tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs +++ b/tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs @@ -1,5 +1,5 @@ -use crate::nar::RenderError; -use crate::pathinfoservice::PathInfoService; +use crate::nar::{NarCalculationService, RenderError}; +use crate::pathinfoservice::{PathInfo, PathInfoService}; use crate::proto; use futures::{stream::BoxStream, TryStreamExt}; use std::ops::Deref; @@ -7,23 +7,26 @@ use tonic::{async_trait, Request, Response, Result, Status}; use tracing::{instrument, warn}; use tvix_castore::proto as castorepb; -pub struct GRPCPathInfoServiceWrapper<PS> { - inner: PS, +pub struct GRPCPathInfoServiceWrapper<PS, NS> { + path_info_service: PS, // FUTUREWORK: allow exposing without allowing listing + nar_calculation_service: NS, } -impl<PS> GRPCPathInfoServiceWrapper<PS> { - pub fn new(path_info_service: PS) -> Self { +impl<PS, NS> GRPCPathInfoServiceWrapper<PS, NS> { + pub fn new(path_info_service: PS, nar_calculation_service: NS) -> Self { Self { - inner: path_info_service, + path_info_service, + nar_calculation_service, } } } #[async_trait] -impl<PS> proto::path_info_service_server::PathInfoService for GRPCPathInfoServiceWrapper<PS> +impl<PS, NS> proto::path_info_service_server::PathInfoService for GRPCPathInfoServiceWrapper<PS, NS> where PS: Deref<Target = dyn PathInfoService> + Send + Sync + 'static, + NS: NarCalculationService + Send + Sync + 'static, { type ListStream = BoxStream<'static, tonic::Result<proto::PathInfo, Status>>; @@ -39,9 +42,9 @@ where .to_vec() .try_into() .map_err(|_e| Status::invalid_argument("invalid output digest length"))?; - match self.inner.get(digest).await { + match self.path_info_service.get(digest).await { Ok(None) => Err(Status::not_found("PathInfo not found")), - Ok(Some(path_info)) => Ok(Response::new(path_info)), + Ok(Some(path_info)) => Ok(Response::new(proto::PathInfo::from(path_info))), Err(e) => { warn!(err = %e, "failed to get PathInfo"); Err(e.into()) @@ -53,12 +56,15 @@ where #[instrument(skip_all)] async fn put(&self, request: Request<proto::PathInfo>) -> Result<Response<proto::PathInfo>> { - let path_info = request.into_inner(); + let path_info_proto = request.into_inner(); + + let path_info = PathInfo::try_from(path_info_proto) + .map_err(|e| Status::invalid_argument(format!("Invalid path info: {e}")))?; // Store the PathInfo in the client. Clients MUST validate the data // they receive, so we don't validate additionally here. - match self.inner.put(path_info).await { - Ok(path_info_new) => Ok(Response::new(path_info_new)), + match self.path_info_service.put(path_info).await { + Ok(path_info_new) => Ok(Response::new(proto::PathInfo::from(path_info_new))), Err(e) => { warn!(err = %e, "failed to put PathInfo"); Err(e.into()) @@ -71,24 +77,22 @@ where &self, request: Request<castorepb::Node>, ) -> Result<Response<proto::CalculateNarResponse>> { - match request.into_inner().node { - None => Err(Status::invalid_argument("no root node sent")), - Some(root_node) => { - if let Err(e) = root_node.validate() { - warn!(err = %e, "invalid root node"); - Err(Status::invalid_argument("invalid root node"))? - } + let root_node = request + .into_inner() + .try_into_anonymous_node() + .map_err(|e| { + warn!(err = %e, "invalid root node"); + Status::invalid_argument("invalid root node") + })?; - match self.inner.calculate_nar(&root_node).await { - Ok((nar_size, nar_sha256)) => Ok(Response::new(proto::CalculateNarResponse { - nar_size, - nar_sha256: nar_sha256.to_vec().into(), - })), - Err(e) => { - warn!(err = %e, "error during NAR calculation"); - Err(e.into()) - } - } + match self.nar_calculation_service.calculate_nar(&root_node).await { + Ok((nar_size, nar_sha256)) => Ok(Response::new(proto::CalculateNarResponse { + nar_size, + nar_sha256: nar_sha256.to_vec().into(), + })), + Err(e) => { + warn!(err = %e, "error during NAR calculation"); + Err(e.into()) } } } @@ -99,8 +103,9 @@ where _request: Request<proto::ListPathInfoRequest>, ) -> Result<Response<Self::ListStream>, Status> { let stream = Box::pin( - self.inner + self.path_info_service .list() + .map_ok(proto::PathInfo::from) .map_err(|e| Status::internal(e.to_string())), ); diff --git a/tvix/store/src/proto/mod.rs b/tvix/store/src/proto/mod.rs index a09839c8bdf9..d9edb81f655d 100644 --- a/tvix/store/src/proto/mod.rs +++ b/tvix/store/src/proto/mod.rs @@ -4,12 +4,12 @@ use bytes::Bytes; use data_encoding::BASE64; // https://github.com/hyperium/tonic/issues/1056 use nix_compat::{ - narinfo::Flags, + narinfo::{Signature, SignatureError}, nixhash::{CAHash, NixHash}, store_path::{self, StorePathRef}, }; use thiserror::Error; -use tvix_castore::proto::{self as castorepb, NamedNode, ValidateNodeError}; +use tvix_castore::DirectoryError; mod grpc_pathinfoservice_wrapper; @@ -17,6 +17,8 @@ pub use grpc_pathinfoservice_wrapper::GRPCPathInfoServiceWrapper; tonic::include_proto!("tvix.store.v1"); +use tvix_castore::proto as castorepb; + #[cfg(feature = "tonic-reflection")] /// Compiled file descriptors for implementing [gRPC /// reflection](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md) with e.g. @@ -39,7 +41,7 @@ pub enum ValidatePathInfoError { /// Node fails validation #[error("Invalid root node: {:?}", .0.to_string())] - InvalidRootNode(ValidateNodeError), + InvalidRootNode(DirectoryError), /// Invalid node name encountered. Root nodes in PathInfos have more strict name requirements #[error("Failed to parse {} as StorePath: {1}", .0.to_str_lossy())] @@ -70,177 +72,18 @@ pub enum ValidatePathInfoError { /// The deriver field is invalid. #[error("deriver field is invalid: {0}")] InvalidDeriverField(store_path::Error), -} - -/// Parses a root node name. -/// -/// On success, this returns the parsed [store_path::StorePathRef]. -/// On error, it returns an error generated from the supplied constructor. -fn parse_node_name_root<E>( - name: &[u8], - err: fn(Vec<u8>, store_path::Error) -> E, -) -> Result<store_path::StorePathRef<'_>, E> { - store_path::StorePathRef::from_bytes(name).map_err(|e| err(name.to_vec(), e)) -} - -impl PathInfo { - /// validate performs some checks on the PathInfo struct, - /// Returning either a [store_path::StorePath] of the root node, or a - /// [ValidatePathInfoError]. - pub fn validate(&self) -> Result<store_path::StorePathRef<'_>, ValidatePathInfoError> { - // ensure the references have the right number of bytes. - for (i, reference) in self.references.iter().enumerate() { - if reference.len() != store_path::DIGEST_SIZE { - return Err(ValidatePathInfoError::InvalidReferenceDigestLen( - i, - reference.len(), - )); - } - } - - // If there is a narinfo field populated… - if let Some(narinfo) = &self.narinfo { - // ensure the nar_sha256 digest has the correct length. - if narinfo.nar_sha256.len() != 32 { - return Err(ValidatePathInfoError::InvalidNarSha256DigestLen( - narinfo.nar_sha256.len(), - )); - } - - // ensure the number of references there matches PathInfo.references count. - if narinfo.reference_names.len() != self.references.len() { - return Err(ValidatePathInfoError::InconsistentNumberOfReferences( - self.references.len(), - narinfo.reference_names.len(), - )); - } - - // parse references in reference_names. - for (i, reference_name_str) in narinfo.reference_names.iter().enumerate() { - // ensure thy parse as (non-absolute) store path - let reference_names_store_path = store_path::StorePath::from_bytes( - reference_name_str.as_bytes(), - ) - .map_err(|_| { - ValidatePathInfoError::InvalidNarinfoReferenceName( - i, - reference_name_str.to_owned(), - ) - })?; - - // ensure their digest matches the one at self.references[i]. - { - // This is safe, because we ensured the proper length earlier already. - let reference_digest = self.references[i].to_vec().try_into().unwrap(); - - if reference_names_store_path.digest() != &reference_digest { - return Err( - ValidatePathInfoError::InconsistentNarinfoReferenceNameDigest( - i, - reference_digest, - *reference_names_store_path.digest(), - ), - ); - } - } - // If the Deriver field is populated, ensure it parses to a - // [store_path::StorePath]. - // We can't check for it to *not* end with .drv, as the .drv files produced by - // recursive Nix end with multiple .drv suffixes, and only one is popped when - // converting to this field. - if let Some(deriver) = &narinfo.deriver { - store_path::StorePathRef::from_name_and_digest(&deriver.name, &deriver.digest) - .map_err(ValidatePathInfoError::InvalidDeriverField)?; - } - } - } + /// The narinfo field is missing + #[error("The narinfo field is missing")] + NarInfoFieldMissing, - // Ensure there is a (root) node present, and it properly parses to a [store_path::StorePath]. - let root_nix_path = match &self.node { - None | Some(castorepb::Node { node: None }) => { - Err(ValidatePathInfoError::NoNodePresent)? - } - Some(castorepb::Node { node: Some(node) }) => { - node.validate() - .map_err(ValidatePathInfoError::InvalidRootNode)?; - // parse the name of the node itself and return - parse_node_name_root(node.get_name(), ValidatePathInfoError::InvalidNodeName)? - } - }; - - // return the root nix path - Ok(root_nix_path) - } + /// The ca field is invalid + #[error("The ca field is invalid: {0}")] + InvalidCaField(ConvertCAError), - /// With self and its store path name, this reconstructs a - /// [nix_compat::narinfo::NarInfo<'_>]. - /// It can be used to validate Signatures, or get back a (sparse) NarInfo - /// struct to prepare writing it out. - /// - /// It assumes self to be validated first, and will only return None if the - /// `narinfo` field is unpopulated. - /// - /// It does very little allocation (a Vec each for `signatures` and - /// `references`), the rest points to data owned elsewhere. - /// - /// Keep in mind this is not able to reconstruct all data present in the - /// NarInfo<'_>, as some of it is not stored at all: - /// - the `system`, `file_hash` and `file_size` fields are set to `None`. - /// - the URL is set to an empty string. - /// - Compression is set to "none" - /// - /// If you want to render it out to a string and be able to parse it back - /// in, at least URL *must* be set again. - pub fn to_narinfo<'a>( - &'a self, - store_path: store_path::StorePathRef<'a>, - ) -> Option<nix_compat::narinfo::NarInfo<'_>> { - let narinfo = &self.narinfo.as_ref()?; - - Some(nix_compat::narinfo::NarInfo { - flags: Flags::empty(), - store_path, - nar_hash: narinfo - .nar_sha256 - .as_ref() - .try_into() - .expect("invalid narhash"), - nar_size: narinfo.nar_size, - references: narinfo - .reference_names - .iter() - .map(|ref_name| { - // This shouldn't pass validation - StorePathRef::from_bytes(ref_name.as_bytes()).expect("invalid reference") - }) - .collect(), - signatures: narinfo - .signatures - .iter() - .map(|sig| { - nix_compat::narinfo::Signature::new( - &sig.name, - // This shouldn't pass validation - sig.data[..].try_into().expect("invalid signature len"), - ) - }) - .collect(), - ca: narinfo - .ca - .as_ref() - .map(|ca| ca.try_into().expect("invalid ca")), - system: None, - deriver: narinfo.deriver.as_ref().map(|deriver| { - StorePathRef::from_name_and_digest(&deriver.name, &deriver.digest) - .expect("invalid deriver") - }), - url: "", - compression: Some("none"), - file_hash: None, - file_size: None, - }) - } + /// The signature at position is invalid + #[error("The signature at position {0} is invalid: {1}")] + InvalidSignature(usize, SignatureError), } /// Errors that can occur when converting from a [nar_info::Ca] to a (stricter) @@ -260,24 +103,19 @@ impl TryFrom<&nar_info::Ca> for nix_compat::nixhash::CAHash { fn try_from(value: &nar_info::Ca) -> Result<Self, Self::Error> { Ok(match value.r#type { - typ if typ == nar_info::ca::Hash::FlatMd5 as i32 => { - Self::Flat(NixHash::Md5(value.digest[..].try_into().map_err(|_| { - ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "FlatMd5") - })?)) - } - typ if typ == nar_info::ca::Hash::FlatSha1 as i32 => { - Self::Flat(NixHash::Sha1(value.digest[..].try_into().map_err( - |_| ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "FlatSha1"), + typ if typ == nar_info::ca::Hash::NarSha256 as i32 => { + Self::Nar(NixHash::Sha256(value.digest[..].try_into().map_err( + |_| ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "NarSha256"), )?)) } - typ if typ == nar_info::ca::Hash::FlatSha256 as i32 => { - Self::Flat(NixHash::Sha256(value.digest[..].try_into().map_err( - |_| ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "FlatSha256"), + typ if typ == nar_info::ca::Hash::NarSha1 as i32 => { + Self::Nar(NixHash::Sha1(value.digest[..].try_into().map_err( + |_| ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "NarSha1"), )?)) } - typ if typ == nar_info::ca::Hash::FlatSha512 as i32 => Self::Flat(NixHash::Sha512( + typ if typ == nar_info::ca::Hash::NarSha512 as i32 => Self::Nar(NixHash::Sha512( Box::new(value.digest[..].try_into().map_err(|_| { - ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "FlatSha512") + ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "NarSha512") })?), )), typ if typ == nar_info::ca::Hash::NarMd5 as i32 => { @@ -285,19 +123,29 @@ impl TryFrom<&nar_info::Ca> for nix_compat::nixhash::CAHash { ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "NarMd5") })?)) } - typ if typ == nar_info::ca::Hash::NarSha1 as i32 => { - Self::Nar(NixHash::Sha1(value.digest[..].try_into().map_err( - |_| ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "NarSha1"), + typ if typ == nar_info::ca::Hash::TextSha256 as i32 => { + Self::Text(value.digest[..].try_into().map_err(|_| { + ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "TextSha256") + })?) + } + typ if typ == nar_info::ca::Hash::FlatSha1 as i32 => { + Self::Flat(NixHash::Sha1(value.digest[..].try_into().map_err( + |_| ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "FlatSha1"), )?)) } - typ if typ == nar_info::ca::Hash::NarSha256 as i32 => { - Self::Nar(NixHash::Sha256(value.digest[..].try_into().map_err( - |_| ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "NarSha256"), + typ if typ == nar_info::ca::Hash::FlatMd5 as i32 => { + Self::Flat(NixHash::Md5(value.digest[..].try_into().map_err(|_| { + ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "FlatMd5") + })?)) + } + typ if typ == nar_info::ca::Hash::FlatSha256 as i32 => { + Self::Flat(NixHash::Sha256(value.digest[..].try_into().map_err( + |_| ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "FlatSha256"), )?)) } - typ if typ == nar_info::ca::Hash::NarSha512 as i32 => Self::Nar(NixHash::Sha512( + typ if typ == nar_info::ca::Hash::FlatSha512 as i32 => Self::Flat(NixHash::Sha512( Box::new(value.digest[..].try_into().map_err(|_| { - ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "NarSha512") + ConvertCAError::InvalidReferenceDigestLen(value.digest.len(), "FlatSha512") })?), )), typ => return Err(ConvertCAError::UnknownHashType(typ)), @@ -330,45 +178,154 @@ impl From<&nix_compat::nixhash::CAHash> for nar_info::Ca { } } -impl From<&nix_compat::narinfo::NarInfo<'_>> for NarInfo { - /// Converts from a NarInfo (returned from the NARInfo parser) to the proto- - /// level NarInfo struct. - fn from(value: &nix_compat::narinfo::NarInfo<'_>) -> Self { - let signatures = value - .signatures - .iter() - .map(|sig| nar_info::Signature { - name: sig.name().to_string(), - data: Bytes::copy_from_slice(sig.bytes()), - }) - .collect(); - - NarInfo { - nar_size: value.nar_size, - nar_sha256: Bytes::copy_from_slice(&value.nar_hash), - signatures, - reference_names: value.references.iter().map(|r| r.to_string()).collect(), - deriver: value.deriver.as_ref().map(|sp| StorePath { - name: sp.name().to_owned(), - digest: Bytes::copy_from_slice(sp.digest()), - }), - ca: value.ca.as_ref().map(|ca| ca.into()), - } - } -} - -impl From<&nix_compat::narinfo::NarInfo<'_>> for PathInfo { - /// Converts from a NarInfo (returned from the NARInfo parser) to a PathInfo - /// struct with the node set to None. - fn from(value: &nix_compat::narinfo::NarInfo<'_>) -> Self { +impl From<crate::pathinfoservice::PathInfo> for PathInfo { + fn from(value: crate::pathinfoservice::PathInfo) -> Self { Self { - node: None, + node: Some(castorepb::Node::from_name_and_node( + value.store_path.to_string().into_bytes().into(), + value.node, + )), references: value .references .iter() - .map(|x| Bytes::copy_from_slice(x.digest())) + .map(|reference| Bytes::copy_from_slice(reference.digest())) .collect(), - narinfo: Some(value.into()), + narinfo: Some(NarInfo { + nar_size: value.nar_size, + nar_sha256: Bytes::copy_from_slice(&value.nar_sha256), + signatures: value + .signatures + .iter() + .map(|sig| nar_info::Signature { + name: sig.name().to_string(), + data: Bytes::copy_from_slice(sig.bytes()), + }) + .collect(), + reference_names: value.references.iter().map(|r| r.to_string()).collect(), + deriver: value.deriver.as_ref().map(|sp| StorePath { + name: (*sp.name()).to_owned(), + digest: Bytes::copy_from_slice(sp.digest()), + }), + ca: value.ca.as_ref().map(|ca| ca.into()), + }), + } + } +} + +impl TryFrom<PathInfo> for crate::pathinfoservice::PathInfo { + type Error = ValidatePathInfoError; + fn try_from(value: PathInfo) -> Result<Self, Self::Error> { + let narinfo = value + .narinfo + .ok_or_else(|| ValidatePathInfoError::NarInfoFieldMissing)?; + + // ensure the references have the right number of bytes. + for (i, reference) in value.references.iter().enumerate() { + if reference.len() != store_path::DIGEST_SIZE { + return Err(ValidatePathInfoError::InvalidReferenceDigestLen( + i, + reference.len(), + )); + } + } + + // ensure the number of references there matches PathInfo.references count. + if narinfo.reference_names.len() != value.references.len() { + return Err(ValidatePathInfoError::InconsistentNumberOfReferences( + value.references.len(), + narinfo.reference_names.len(), + )); } + + // parse references in reference_names. + let mut references = vec![]; + for (i, reference_name_str) in narinfo.reference_names.iter().enumerate() { + // ensure thy parse as (non-absolute) store path + let reference_names_store_path = + StorePathRef::from_bytes(reference_name_str.as_bytes()).map_err(|_| { + ValidatePathInfoError::InvalidNarinfoReferenceName( + i, + reference_name_str.to_owned(), + ) + })?; + + // ensure their digest matches the one at self.references[i]. + { + // This is safe, because we ensured the proper length earlier already. + let reference_digest = value.references[i].to_vec().try_into().unwrap(); + + if reference_names_store_path.digest() != &reference_digest { + return Err( + ValidatePathInfoError::InconsistentNarinfoReferenceNameDigest( + i, + reference_digest, + *reference_names_store_path.digest(), + ), + ); + } else { + references.push(reference_names_store_path.to_owned()); + } + } + } + + let nar_sha256_length = narinfo.nar_sha256.len(); + + // split value.node into the name and node components + let (name, node) = value + .node + .ok_or_else(|| ValidatePathInfoError::NoNodePresent)? + .try_into_name_and_node() + .map_err(ValidatePathInfoError::InvalidRootNode)?; + + Ok(Self { + // value.node has a valid name according to the castore model but might not parse to a + // [StorePath] + store_path: nix_compat::store_path::StorePath::from_bytes(name.as_ref()).map_err( + |err| ValidatePathInfoError::InvalidNodeName(name.as_ref().to_vec(), err), + )?, + node, + references, + nar_size: narinfo.nar_size, + nar_sha256: narinfo.nar_sha256.to_vec()[..] + .try_into() + .map_err(|_| ValidatePathInfoError::InvalidNarSha256DigestLen(nar_sha256_length))?, + // If the Deriver field is populated, ensure it parses to a + // [StorePath]. + // We can't check for it to *not* end with .drv, as the .drv files produced by + // recursive Nix end with multiple .drv suffixes, and only one is popped when + // converting to this field. + deriver: narinfo + .deriver + .map(|deriver| { + nix_compat::store_path::StorePath::from_name_and_digest( + &deriver.name, + &deriver.digest, + ) + .map_err(ValidatePathInfoError::InvalidDeriverField) + }) + .transpose()?, + signatures: narinfo + .signatures + .into_iter() + .enumerate() + .map(|(i, signature)| { + signature.data.to_vec()[..] + .try_into() + .map_err(|_| { + ValidatePathInfoError::InvalidSignature( + i, + SignatureError::InvalidSignatureLen(signature.data.len()), + ) + }) + .map(|signature_data| Signature::new(signature.name, signature_data)) + }) + .collect::<Result<Vec<_>, ValidatePathInfoError>>()?, + ca: narinfo + .ca + .as_ref() + .map(TryFrom::try_from) + .transpose() + .map_err(ValidatePathInfoError::InvalidCaField)?, + }) } } diff --git a/tvix/store/src/proto/tests/pathinfo.rs b/tvix/store/src/proto/tests/pathinfo.rs index 4d0834878d7c..edda64045f8e 100644 --- a/tvix/store/src/proto/tests/pathinfo.rs +++ b/tvix/store/src/proto/tests/pathinfo.rs @@ -1,272 +1,228 @@ -use crate::proto::{nar_info::Signature, NarInfo, PathInfo, ValidatePathInfoError}; -use crate::tests::fixtures::*; +use std::sync::LazyLock; + +use crate::pathinfoservice::PathInfo; +use crate::proto::{self, ValidatePathInfoError}; +use crate::tests::fixtures::{DUMMY_PATH, DUMMY_PATH_DIGEST, DUMMY_PATH_STR}; use bytes::Bytes; -use data_encoding::BASE64; -use nix_compat::nixbase32; -use nix_compat::store_path::{self, StorePathRef}; +use nix_compat::store_path; use rstest::rstest; +use tvix_castore::fixtures::DUMMY_DIGEST; use tvix_castore::proto as castorepb; +use tvix_castore::{DirectoryError, ValidateNodeError}; + +/// A valid PathInfo message +/// The references in `narinfo.reference_names` aligns with what's in +/// `references`. +static PROTO_PATH_INFO: LazyLock<proto::PathInfo> = LazyLock::new(|| proto::PathInfo { + node: Some(castorepb::Node { + node: Some(castorepb::node::Node::Directory(castorepb::DirectoryNode { + name: DUMMY_PATH_STR.into(), + digest: DUMMY_DIGEST.clone().into(), + size: 0, + })), + }), + references: vec![DUMMY_PATH_DIGEST.as_slice().into()], + narinfo: Some(proto::NarInfo { + nar_size: 0, + nar_sha256: DUMMY_DIGEST.clone().into(), + signatures: vec![], + reference_names: vec![DUMMY_PATH_STR.to_string()], + deriver: None, + ca: Some(proto::nar_info::Ca { + r#type: proto::nar_info::ca::Hash::NarSha256.into(), + digest: DUMMY_DIGEST.clone().into(), + }), + }), +}); -#[rstest] -#[case::no_node(None, Err(ValidatePathInfoError::NoNodePresent))] -#[case::no_node_2(Some(castorepb::Node { node: None}), Err(ValidatePathInfoError::NoNodePresent))] +#[test] +fn convert_valid() { + let path_info = PROTO_PATH_INFO.clone(); + PathInfo::try_from(path_info).expect("must succeed"); +} -fn validate_pathinfo( - #[case] node: Option<castorepb::Node>, - #[case] exp_result: Result<StorePathRef, ValidatePathInfoError>, -) { - // construct the PathInfo object - let p = PathInfo { - node, - ..Default::default() - }; +/// Create a PathInfo with a correct deriver field and ensure it succeeds. +#[test] +fn convert_valid_deriver() { + let mut path_info = PROTO_PATH_INFO.clone(); - assert_eq!(exp_result, p.validate()); + // add a valid deriver + let narinfo = path_info.narinfo.as_mut().unwrap(); + narinfo.deriver = Some(crate::proto::StorePath { + name: DUMMY_PATH.name().to_string(), + digest: Bytes::from(DUMMY_PATH_DIGEST.as_slice()), + }); - let err = p.validate().expect_err("validation should fail"); - assert!(matches!(err, ValidatePathInfoError::NoNodePresent)); + let path_info = PathInfo::try_from(path_info).expect("must succeed"); + assert_eq!(DUMMY_PATH.clone(), path_info.deriver.unwrap()) } #[rstest] -#[case::ok(castorepb::DirectoryNode { - name: DUMMY_PATH.into(), - digest: DUMMY_DIGEST.clone().into(), - size: 0, -}, Ok(StorePathRef::from_bytes(DUMMY_PATH.as_bytes()).unwrap()))] -#[case::invalid_digest_length(castorepb::DirectoryNode { - name: DUMMY_PATH.into(), - digest: Bytes::new(), - size: 0, -}, Err(ValidatePathInfoError::InvalidRootNode(castorepb::ValidateNodeError::InvalidDigestLen(0))))] -#[case::invalid_node_name_no_storepath(castorepb::DirectoryNode { - name: "invalid".into(), - digest: DUMMY_DIGEST.clone().into(), - size: 0, -}, Err(ValidatePathInfoError::InvalidNodeName( - "invalid".into(), - store_path::Error::InvalidLength -)))] -fn validate_directory( - #[case] directory_node: castorepb::DirectoryNode, - #[case] exp_result: Result<StorePathRef, ValidatePathInfoError>, +#[case::no_node(None, ValidatePathInfoError::NoNodePresent)] +#[case::no_node_2(Some(castorepb::Node { node: None}), ValidatePathInfoError::InvalidRootNode(DirectoryError::NoNodeSet))] +fn convert_pathinfo_wrong_nodes( + #[case] node: Option<castorepb::Node>, + #[case] exp_err: ValidatePathInfoError, ) { // construct the PathInfo object - let p = PathInfo { - node: Some(castorepb::Node { - node: Some(castorepb::node::Node::Directory(directory_node)), - }), - ..Default::default() - }; - assert_eq!(exp_result, p.validate()); + let mut path_info = PROTO_PATH_INFO.clone(); + path_info.node = node; + + assert_eq!( + exp_err, + PathInfo::try_from(path_info).expect_err("must fail") + ); } +/// Constructs a [proto::PathInfo] with root nodes that have wrong data in +/// various places, causing the conversion to [PathInfo] to fail. #[rstest] -#[case::ok( - castorepb::FileNode { - name: DUMMY_PATH.into(), +#[case::directory_invalid_digest_length( + castorepb::node::Node::Directory(castorepb::DirectoryNode { + name: DUMMY_PATH_STR.into(), + digest: Bytes::new(), + size: 0, + }), + ValidatePathInfoError::InvalidRootNode(DirectoryError::InvalidNode(DUMMY_PATH_STR.into(), ValidateNodeError::InvalidDigestLen(0))) +)] +#[case::directory_invalid_node_name_no_storepath( + castorepb::node::Node::Directory(castorepb::DirectoryNode { + name: "invalid".into(), digest: DUMMY_DIGEST.clone().into(), size: 0, - executable: false, - }, - Ok(StorePathRef::from_bytes(DUMMY_PATH.as_bytes()).unwrap()) + }), + ValidatePathInfoError::InvalidNodeName("invalid".into(), store_path::Error::InvalidLength) )] -#[case::invalid_digest_len( - castorepb::FileNode { - name: DUMMY_PATH.into(), +#[case::file_invalid_digest_len( + castorepb::node::Node::File(castorepb::FileNode { + name: DUMMY_PATH_STR.into(), digest: Bytes::new(), ..Default::default() - }, - Err(ValidatePathInfoError::InvalidRootNode(castorepb::ValidateNodeError::InvalidDigestLen(0))) + }), + ValidatePathInfoError::InvalidRootNode(DirectoryError::InvalidNode(DUMMY_PATH_STR.into(), ValidateNodeError::InvalidDigestLen(0))) )] -#[case::invalid_node_name( - castorepb::FileNode { +#[case::file_invalid_node_name( + castorepb::node::Node::File(castorepb::FileNode { name: "invalid".into(), digest: DUMMY_DIGEST.clone().into(), ..Default::default() - }, - Err(ValidatePathInfoError::InvalidNodeName( + }), + ValidatePathInfoError::InvalidNodeName( "invalid".into(), store_path::Error::InvalidLength - )) -)] -fn validate_file( - #[case] file_node: castorepb::FileNode, - #[case] exp_result: Result<StorePathRef, ValidatePathInfoError>, -) { - // construct the PathInfo object - let p = PathInfo { - node: Some(castorepb::Node { - node: Some(castorepb::node::Node::File(file_node)), - }), - ..Default::default() - }; - assert_eq!(exp_result, p.validate()); -} - -#[rstest] -#[case::ok( - castorepb::SymlinkNode { - name: DUMMY_PATH.into(), - target: "foo".into(), - }, - Ok(StorePathRef::from_bytes(DUMMY_PATH.as_bytes()).unwrap()) + ) )] -#[case::invalid_node_name( - castorepb::SymlinkNode { +#[case::symlink_invalid_node_name( + castorepb::node::Node::Symlink(castorepb::SymlinkNode { name: "invalid".into(), target: "foo".into(), - }, - Err(ValidatePathInfoError::InvalidNodeName( + }), + ValidatePathInfoError::InvalidNodeName( "invalid".into(), store_path::Error::InvalidLength - )) + ) )] -fn validate_symlink( - #[case] symlink_node: castorepb::SymlinkNode, - #[case] exp_result: Result<StorePathRef, ValidatePathInfoError>, -) { - // construct the PathInfo object - let p = PathInfo { - node: Some(castorepb::Node { - node: Some(castorepb::node::Node::Symlink(symlink_node)), - }), - ..Default::default() - }; - assert_eq!(exp_result, p.validate()); -} +fn convert_fail_node(#[case] node: castorepb::node::Node, #[case] exp_err: ValidatePathInfoError) { + // construct the proto::PathInfo object + let mut p = PROTO_PATH_INFO.clone(); + p.node = Some(castorepb::Node { node: Some(node) }); -/// Ensure parsing a correct PathInfo without narinfo populated succeeds. -#[test] -fn validate_references_without_narinfo_ok() { - assert!(PATH_INFO_WITHOUT_NARINFO.validate().is_ok()); + assert_eq!(exp_err, PathInfo::try_from(p).expect_err("must fail")); } -/// Ensure parsing a correct PathInfo with narinfo populated succeeds. +/// Ensure a PathInfo without narinfo populated fails converting! #[test] -fn validate_references_with_narinfo_ok() { - assert!(PATH_INFO_WITH_NARINFO.validate().is_ok()); +fn convert_without_narinfo_fail() { + let mut path_info = PROTO_PATH_INFO.clone(); + path_info.narinfo = None; + + assert_eq!( + ValidatePathInfoError::NarInfoFieldMissing, + PathInfo::try_from(path_info).expect_err("must fail"), + ); } /// Create a PathInfo with a wrong digest length in narinfo.nar_sha256, and -/// ensure validation fails. +/// ensure conversion fails. #[test] -fn validate_wrong_nar_sha256() { - let mut path_info = PATH_INFO_WITH_NARINFO.clone(); +fn convert_wrong_nar_sha256() { + let mut path_info = PROTO_PATH_INFO.clone(); path_info.narinfo.as_mut().unwrap().nar_sha256 = vec![0xbe, 0xef].into(); - match path_info.validate().expect_err("must_fail") { - ValidatePathInfoError::InvalidNarSha256DigestLen(2) => {} - e => panic!("unexpected error: {:?}", e), - }; + assert_eq!( + ValidatePathInfoError::InvalidNarSha256DigestLen(2), + PathInfo::try_from(path_info).expect_err("must fail") + ); } /// Create a PathInfo with a wrong count of narinfo.reference_names, /// and ensure validation fails. #[test] -fn validate_inconsistent_num_refs_fail() { - let mut path_info = PATH_INFO_WITH_NARINFO.clone(); +fn convert_inconsistent_num_refs_fail() { + let mut path_info = PROTO_PATH_INFO.clone(); path_info.narinfo.as_mut().unwrap().reference_names = vec![]; - match path_info.validate().expect_err("must_fail") { - ValidatePathInfoError::InconsistentNumberOfReferences(1, 0) => {} - e => panic!("unexpected error: {:?}", e), - }; + assert_eq!( + ValidatePathInfoError::InconsistentNumberOfReferences(1, 0), + PathInfo::try_from(path_info).expect_err("must fail") + ); } /// Create a PathInfo with a wrong digest length in references. #[test] -fn validate_invalid_reference_digest_len() { - let mut path_info = PATH_INFO_WITHOUT_NARINFO.clone(); +fn convert_invalid_reference_digest_len() { + let mut path_info = PROTO_PATH_INFO.clone(); path_info.references.push(vec![0xff, 0xff].into()); - match path_info.validate().expect_err("must fail") { + assert_eq!( ValidatePathInfoError::InvalidReferenceDigestLen( 1, // position 2, // unexpected digest len - ) => {} - e => panic!("unexpected error: {:?}", e), - }; + ), + PathInfo::try_from(path_info).expect_err("must fail") + ); } /// Create a PathInfo with a narinfo.reference_name[1] that is no valid store path. #[test] -fn validate_invalid_narinfo_reference_name() { - let mut path_info = PATH_INFO_WITH_NARINFO.clone(); +fn convert_invalid_narinfo_reference_name() { + let mut path_info = PROTO_PATH_INFO.clone(); // This is invalid, as the store prefix is not part of reference_names. path_info.narinfo.as_mut().unwrap().reference_names[0] = "/nix/store/00000000000000000000000000000000-dummy".to_string(); - match path_info.validate().expect_err("must fail") { - ValidatePathInfoError::InvalidNarinfoReferenceName(0, reference_name) => { - assert_eq!( - "/nix/store/00000000000000000000000000000000-dummy", - reference_name - ); - } - e => panic!("unexpected error: {:?}", e), - } + assert_eq!( + ValidatePathInfoError::InvalidNarinfoReferenceName( + 0, + "/nix/store/00000000000000000000000000000000-dummy".to_string() + ), + PathInfo::try_from(path_info).expect_err("must fail") + ); } /// Create a PathInfo with a narinfo.reference_name[0] that doesn't match references[0]. #[test] -fn validate_inconsistent_narinfo_reference_name_digest() { - let mut path_info = PATH_INFO_WITH_NARINFO.clone(); +fn convert_inconsistent_narinfo_reference_name_digest() { + let mut path_info = PROTO_PATH_INFO.clone(); // mutate the first reference, they were all zeroes before path_info.references[0] = vec![0xff; store_path::DIGEST_SIZE].into(); - match path_info.validate().expect_err("must fail") { - ValidatePathInfoError::InconsistentNarinfoReferenceNameDigest(0, e_expected, e_actual) => { - assert_eq!(path_info.references[0][..], e_expected[..]); - assert_eq!(DUMMY_PATH_DIGEST, e_actual); - } - e => panic!("unexpected error: {:?}", e), - } -} - -/// Create a node with an empty symlink target, and ensure it fails validation. -#[test] -fn validate_symlink_empty_target_invalid() { - let node = castorepb::node::Node::Symlink(castorepb::SymlinkNode { - name: "foo".into(), - target: "".into(), - }); - - node.validate().expect_err("must fail validation"); -} - -/// Create a node with a symlink target including null bytes, and ensure it -/// fails validation. -#[test] -fn validate_symlink_target_null_byte_invalid() { - let node = castorepb::node::Node::Symlink(castorepb::SymlinkNode { - name: "foo".into(), - target: "foo\0".into(), - }); - - node.validate().expect_err("must fail validation"); -} - -/// Create a PathInfo with a correct deriver field and ensure it succeeds. -#[test] -fn validate_valid_deriver() { - let mut path_info = PATH_INFO_WITH_NARINFO.clone(); - - // add a valid deriver - let narinfo = path_info.narinfo.as_mut().unwrap(); - narinfo.deriver = Some(crate::proto::StorePath { - name: "foo".to_string(), - digest: Bytes::from(DUMMY_PATH_DIGEST.as_slice()), - }); - - path_info.validate().expect("must validate"); + assert_eq!( + ValidatePathInfoError::InconsistentNarinfoReferenceNameDigest( + 0, + path_info.references[0][..].try_into().unwrap(), + DUMMY_PATH_DIGEST + ), + PathInfo::try_from(path_info).expect_err("must fail") + ) } /// Create a PathInfo with a broken deriver field and ensure it fails. #[test] -fn validate_invalid_deriver() { - let mut path_info = PATH_INFO_WITH_NARINFO.clone(); +fn convert_invalid_deriver() { + let mut path_info = PROTO_PATH_INFO.clone(); // add a broken deriver (invalid digest) let narinfo = path_info.narinfo.as_mut().unwrap(); @@ -275,157 +231,8 @@ fn validate_invalid_deriver() { digest: vec![].into(), }); - match path_info.validate().expect_err("must fail validation") { - ValidatePathInfoError::InvalidDeriverField(_) => {} - e => panic!("unexpected error: {:?}", e), - } -} - -#[test] -fn from_nixcompat_narinfo() { - let narinfo_parsed = nix_compat::narinfo::NarInfo::parse( - r#"StorePath: /nix/store/s66mzxpvicwk07gjbjfw9izjfa797vsw-hello-2.12.1 -URL: nar/1nhgq6wcggx0plpy4991h3ginj6hipsdslv4fd4zml1n707j26yq.nar.xz -Compression: xz -FileHash: sha256:1nhgq6wcggx0plpy4991h3ginj6hipsdslv4fd4zml1n707j26yq -FileSize: 50088 -NarHash: sha256:0yzhigwjl6bws649vcs2asa4lbs8hg93hyix187gc7s7a74w5h80 -NarSize: 226488 -References: 3n58xw4373jp0ljirf06d8077j15pc4j-glibc-2.37-8 s66mzxpvicwk07gjbjfw9izjfa797vsw-hello-2.12.1 -Deriver: ib3sh3pcz10wsmavxvkdbayhqivbghlq-hello-2.12.1.drv -Sig: cache.nixos.org-1:8ijECciSFzWHwwGVOIVYdp2fOIOJAfmzGHPQVwpktfTQJF6kMPPDre7UtFw3o+VqenC5P8RikKOAAfN7CvPEAg=="#).expect("must parse"); - assert_eq!( - PathInfo { - node: None, - references: vec![ - Bytes::copy_from_slice(&nixbase32::decode_fixed::<20>("3n58xw4373jp0ljirf06d8077j15pc4j").unwrap()), - Bytes::copy_from_slice(&nixbase32::decode_fixed::<20>("s66mzxpvicwk07gjbjfw9izjfa797vsw").unwrap()), - ], - narinfo: Some( - NarInfo { - nar_size: 226488, - nar_sha256: Bytes::copy_from_slice( - &nixbase32::decode_fixed::<32>("0yzhigwjl6bws649vcs2asa4lbs8hg93hyix187gc7s7a74w5h80".as_bytes()) - .unwrap() - ), - signatures: vec![Signature { - name: "cache.nixos.org-1".to_string(), - data: BASE64.decode("8ijECciSFzWHwwGVOIVYdp2fOIOJAfmzGHPQVwpktfTQJF6kMPPDre7UtFw3o+VqenC5P8RikKOAAfN7CvPEAg==".as_bytes()).unwrap().into(), - }], - reference_names: vec![ - "3n58xw4373jp0ljirf06d8077j15pc4j-glibc-2.37-8".to_string(), - "s66mzxpvicwk07gjbjfw9izjfa797vsw-hello-2.12.1".to_string() - ], - deriver: Some(crate::proto::StorePath { - digest: Bytes::copy_from_slice(&nixbase32::decode_fixed::<20>("ib3sh3pcz10wsmavxvkdbayhqivbghlq").unwrap()), - name: "hello-2.12.1".to_string(), - }), - ca: None, - } - ) - }, - (&narinfo_parsed).into(), - ); -} - -#[test] -fn from_nixcompat_narinfo_fod() { - let narinfo_parsed = nix_compat::narinfo::NarInfo::parse( - r#"StorePath: /nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz -URL: nar/1zjrhzhaizsrlsvdkqfl073vivmxcqnzkff4s50i0cdf541ary1r.nar.xz -Compression: xz -FileHash: sha256:1zjrhzhaizsrlsvdkqfl073vivmxcqnzkff4s50i0cdf541ary1r -FileSize: 1033524 -NarHash: sha256:1lvqpbk2k1sb39z8jfxixf7p7v8sj4z6mmpa44nnmff3w1y6h8lh -NarSize: 1033416 -References: -Deriver: dyivpmlaq2km6c11i0s6bi6mbsx0ylqf-hello-2.12.1.tar.gz.drv -Sig: cache.nixos.org-1:ywnIG629nQZQhEr6/HLDrLT/mUEp5J1LC6NmWSlJRWL/nM7oGItJQUYWGLvYGhSQvHrhIuvMpjNmBNh/WWqCDg== -CA: fixed:sha256:086vqwk2wl8zfs47sq2xpjc9k066ilmb8z6dn0q6ymwjzlm196cd"# - ).expect("must parse"); - - assert_eq!( - PathInfo { - node: None, - references: vec![], - narinfo: Some( - NarInfo { - nar_size: 1033416, - nar_sha256: Bytes::copy_from_slice( - &nixbase32::decode_fixed::<32>( - "1lvqpbk2k1sb39z8jfxixf7p7v8sj4z6mmpa44nnmff3w1y6h8lh" - ) - .unwrap() - ), - signatures: vec![Signature { - name: "cache.nixos.org-1".to_string(), - data: BASE64 - .decode("ywnIG629nQZQhEr6/HLDrLT/mUEp5J1LC6NmWSlJRWL/nM7oGItJQUYWGLvYGhSQvHrhIuvMpjNmBNh/WWqCDg==".as_bytes()) - .unwrap() - .into(), - }], - reference_names: vec![], - deriver: Some(crate::proto::StorePath { - digest: Bytes::copy_from_slice( - &nixbase32::decode_fixed::<20>("dyivpmlaq2km6c11i0s6bi6mbsx0ylqf").unwrap() - ), - name: "hello-2.12.1.tar.gz".to_string(), - }), - ca: Some(crate::proto::nar_info::Ca { - r#type: crate::proto::nar_info::ca::Hash::FlatSha256.into(), - digest: Bytes::copy_from_slice( - &nixbase32::decode_fixed::<32>( - "086vqwk2wl8zfs47sq2xpjc9k066ilmb8z6dn0q6ymwjzlm196cd" - ) - .unwrap() - ) - }), - } - ), - }, - (&narinfo_parsed).into() - ); -} - -/// Exercise .as_narinfo() on a PathInfo and ensure important fields are preserved.. -#[test] -fn as_narinfo() { - let narinfo_parsed = nix_compat::narinfo::NarInfo::parse( - r#"StorePath: /nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz -URL: nar/1zjrhzhaizsrlsvdkqfl073vivmxcqnzkff4s50i0cdf541ary1r.nar.xz -Compression: xz -FileHash: sha256:1zjrhzhaizsrlsvdkqfl073vivmxcqnzkff4s50i0cdf541ary1r -FileSize: 1033524 -NarHash: sha256:1lvqpbk2k1sb39z8jfxixf7p7v8sj4z6mmpa44nnmff3w1y6h8lh -NarSize: 1033416 -References: -Deriver: dyivpmlaq2km6c11i0s6bi6mbsx0ylqf-hello-2.12.1.tar.gz.drv -Sig: cache.nixos.org-1:ywnIG629nQZQhEr6/HLDrLT/mUEp5J1LC6NmWSlJRWL/nM7oGItJQUYWGLvYGhSQvHrhIuvMpjNmBNh/WWqCDg== -CA: fixed:sha256:086vqwk2wl8zfs47sq2xpjc9k066ilmb8z6dn0q6ymwjzlm196cd"# - ).expect("must parse"); - - let path_info: PathInfo = (&narinfo_parsed).into(); - - let mut narinfo_returned = path_info - .to_narinfo( - StorePathRef::from_bytes(b"pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz") - .expect("invalid storepath"), - ) - .expect("must be some"); - narinfo_returned.url = "some.nar"; - - assert_eq!( - r#"StorePath: /nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz -URL: some.nar -Compression: none -NarHash: sha256:1lvqpbk2k1sb39z8jfxixf7p7v8sj4z6mmpa44nnmff3w1y6h8lh -NarSize: 1033416 -References: -Deriver: dyivpmlaq2km6c11i0s6bi6mbsx0ylqf-hello-2.12.1.tar.gz.drv -Sig: cache.nixos.org-1:ywnIG629nQZQhEr6/HLDrLT/mUEp5J1LC6NmWSlJRWL/nM7oGItJQUYWGLvYGhSQvHrhIuvMpjNmBNh/WWqCDg== -CA: fixed:sha256:086vqwk2wl8zfs47sq2xpjc9k066ilmb8z6dn0q6ymwjzlm196cd -"#, - narinfo_returned.to_string(), - ); + ValidatePathInfoError::InvalidDeriverField(store_path::Error::InvalidLength), + PathInfo::try_from(path_info).expect_err("must fail") + ) } diff --git a/tvix/store/src/tests/fixtures.rs b/tvix/store/src/tests/fixtures.rs index 1c8359a2c0c7..48edbcb7c232 100644 --- a/tvix/store/src/tests/fixtures.rs +++ b/tvix/store/src/tests/fixtures.rs @@ -1,56 +1,92 @@ -use lazy_static::lazy_static; -use rstest::*; -use std::sync::Arc; -pub use tvix_castore::fixtures::*; +use crate::pathinfoservice::PathInfo; +use nix_compat::nixhash::{CAHash, NixHash}; +use nix_compat::store_path::StorePath; +use rstest::{self, *}; +use rstest_reuse::*; +use std::io; +use std::sync::{Arc, LazyLock}; +use tvix_castore::fixtures::{ + DIRECTORY_COMPLICATED, DIRECTORY_WITH_KEEP, DUMMY_DIGEST, EMPTY_BLOB_CONTENTS, + EMPTY_BLOB_DIGEST, HELLOWORLD_BLOB_CONTENTS, HELLOWORLD_BLOB_DIGEST, +}; use tvix_castore::{ blobservice::{BlobService, MemoryBlobService}, directoryservice::{DirectoryService, MemoryDirectoryService}, - proto as castorepb, -}; - -use crate::proto::{ - nar_info::{ca, Ca}, - NarInfo, PathInfo, + Node, }; -pub const DUMMY_PATH: &str = "00000000000000000000000000000000-dummy"; +pub const DUMMY_PATH_STR: &str = "00000000000000000000000000000000-dummy"; pub const DUMMY_PATH_DIGEST: [u8; 20] = [0; 20]; -lazy_static! { - /// The NAR representation of a symlink pointing to `/nix/store/somewhereelse` - pub static ref NAR_CONTENTS_SYMLINK: Vec<u8> = vec![ - 13, 0, 0, 0, 0, 0, 0, 0, b'n', b'i', b'x', b'-', b'a', b'r', b'c', b'h', b'i', b'v', b'e', b'-', b'1', 0, - 0, 0, // "nix-archive-1" +pub static DUMMY_PATH: LazyLock<StorePath<String>> = + LazyLock::new(|| StorePath::from_name_and_digest_fixed("dummy", DUMMY_PATH_DIGEST).unwrap()); + +pub static CASTORE_NODE_SYMLINK: LazyLock<Node> = LazyLock::new(|| Node::Symlink { + target: "/nix/store/somewhereelse".try_into().unwrap(), +}); + +/// The NAR representation of a symlink pointing to `/nix/store/somewhereelse` +pub static NAR_CONTENTS_SYMLINK: LazyLock<Vec<u8>> = LazyLock::new(|| { + vec![ + 13, 0, 0, 0, 0, 0, 0, 0, b'n', b'i', b'x', b'-', b'a', b'r', b'c', b'h', b'i', b'v', b'e', + b'-', b'1', 0, 0, 0, // "nix-archive-1" 1, 0, 0, 0, 0, 0, 0, 0, b'(', 0, 0, 0, 0, 0, 0, 0, // "(" 4, 0, 0, 0, 0, 0, 0, 0, b't', b'y', b'p', b'e', 0, 0, 0, 0, // "type" 7, 0, 0, 0, 0, 0, 0, 0, b's', b'y', b'm', b'l', b'i', b'n', b'k', 0, // "symlink" 6, 0, 0, 0, 0, 0, 0, 0, b't', b'a', b'r', b'g', b'e', b't', 0, 0, // target - 24, 0, 0, 0, 0, 0, 0, 0, b'/', b'n', b'i', b'x', b'/', b's', b't', b'o', b'r', b'e', b'/', b's', b'o', - b'm', b'e', b'w', b'h', b'e', b'r', b'e', b'e', b'l', b's', + 24, 0, 0, 0, 0, 0, 0, 0, b'/', b'n', b'i', b'x', b'/', b's', b't', b'o', b'r', b'e', b'/', + b's', b'o', b'm', b'e', b'w', b'h', b'e', b'r', b'e', b'e', b'l', b's', b'e', // "/nix/store/somewhereelse" - 1, 0, 0, 0, 0, 0, 0, 0, b')', 0, 0, 0, 0, 0, 0, 0 // ")" - ]; + 1, 0, 0, 0, 0, 0, 0, 0, b')', 0, 0, 0, 0, 0, 0, 0, // ")" + ] +}); + +pub static CASTORE_NODE_HELLOWORLD: LazyLock<Node> = LazyLock::new(|| Node::File { + digest: HELLOWORLD_BLOB_DIGEST.clone(), + size: HELLOWORLD_BLOB_CONTENTS.len() as u64, + executable: false, +}); - /// The NAR representation of a regular file with the contents "Hello World!" - pub static ref NAR_CONTENTS_HELLOWORLD: Vec<u8> = vec![ - 13, 0, 0, 0, 0, 0, 0, 0, b'n', b'i', b'x', b'-', b'a', b'r', b'c', b'h', b'i', b'v', b'e', b'-', b'1', 0, - 0, 0, // "nix-archive-1" +/// The NAR representation of a regular file with the contents "Hello World!" +pub static NAR_CONTENTS_HELLOWORLD: LazyLock<Vec<u8>> = LazyLock::new(|| { + vec![ + 13, 0, 0, 0, 0, 0, 0, 0, b'n', b'i', b'x', b'-', b'a', b'r', b'c', b'h', b'i', b'v', b'e', + b'-', b'1', 0, 0, 0, // "nix-archive-1" 1, 0, 0, 0, 0, 0, 0, 0, b'(', 0, 0, 0, 0, 0, 0, 0, // "(" 4, 0, 0, 0, 0, 0, 0, 0, b't', b'y', b'p', b'e', 0, 0, 0, 0, // "type" 7, 0, 0, 0, 0, 0, 0, 0, b'r', b'e', b'g', b'u', b'l', b'a', b'r', 0, // "regular" 8, 0, 0, 0, 0, 0, 0, 0, b'c', b'o', b'n', b't', b'e', b'n', b't', b's', // "contents" - 12, 0, 0, 0, 0, 0, 0, 0, b'H', b'e', b'l', b'l', b'o', b' ', b'W', b'o', b'r', b'l', b'd', b'!', 0, 0, - 0, 0, // "Hello World!" - 1, 0, 0, 0, 0, 0, 0, 0, b')', 0, 0, 0, 0, 0, 0, 0 // ")" - ]; + 12, 0, 0, 0, 0, 0, 0, 0, b'H', b'e', b'l', b'l', b'o', b' ', b'W', b'o', b'r', b'l', b'd', + b'!', 0, 0, 0, 0, // "Hello World!" + 1, 0, 0, 0, 0, 0, 0, 0, b')', 0, 0, 0, 0, 0, 0, 0, // ")" + ] +}); + +pub static CASTORE_NODE_TOO_BIG: LazyLock<Node> = LazyLock::new(|| Node::File { + digest: HELLOWORLD_BLOB_DIGEST.clone(), + size: 42, // <- note the wrong size here! + executable: false, +}); +pub static CASTORE_NODE_TOO_SMALL: LazyLock<Node> = LazyLock::new(|| Node::File { + digest: HELLOWORLD_BLOB_DIGEST.clone(), + size: 2, // <- note the wrong size here! + executable: false, +}); + +pub static CASTORE_NODE_COMPLICATED: LazyLock<Node> = LazyLock::new(|| Node::Directory { + digest: DIRECTORY_COMPLICATED.digest(), + size: DIRECTORY_COMPLICATED.size(), +}); - /// The NAR representation of a more complicated directory structure. - pub static ref NAR_CONTENTS_COMPLICATED: Vec<u8> = vec![ - 13, 0, 0, 0, 0, 0, 0, 0, b'n', b'i', b'x', b'-', b'a', b'r', b'c', b'h', b'i', b'v', b'e', b'-', b'1', 0, - 0, 0, // "nix-archive-1" +/// The NAR representation of a more complicated directory structure. +pub static NAR_CONTENTS_COMPLICATED: LazyLock<Vec<u8>> = LazyLock::new(|| { + vec![ + 13, 0, 0, 0, 0, 0, 0, 0, b'n', b'i', b'x', b'-', b'a', b'r', b'c', b'h', b'i', b'v', b'e', + b'-', b'1', 0, 0, 0, // "nix-archive-1" 1, 0, 0, 0, 0, 0, 0, 0, b'(', 0, 0, 0, 0, 0, 0, 0, // "(" 4, 0, 0, 0, 0, 0, 0, 0, b't', b'y', b'p', b'e', 0, 0, 0, 0, // "type" - 9, 0, 0, 0, 0, 0, 0, 0, b'd', b'i', b'r', b'e', b'c', b't', b'o', b'r', b'y', 0, 0, 0, 0, 0, 0, 0, // "directory" + 9, 0, 0, 0, 0, 0, 0, 0, b'd', b'i', b'r', b'e', b'c', b't', b'o', b'r', b'y', 0, 0, 0, 0, + 0, 0, 0, // "directory" 5, 0, 0, 0, 0, 0, 0, 0, b'e', b'n', b't', b'r', b'y', 0, 0, 0, // "entry" 1, 0, 0, 0, 0, 0, 0, 0, b'(', 0, 0, 0, 0, 0, 0, 0, // "(" 4, 0, 0, 0, 0, 0, 0, 0, b'n', b'a', b'm', b'e', 0, 0, 0, 0, // "name" @@ -72,8 +108,8 @@ lazy_static! { 4, 0, 0, 0, 0, 0, 0, 0, b't', b'y', b'p', b'e', 0, 0, 0, 0, // "type" 7, 0, 0, 0, 0, 0, 0, 0, b's', b'y', b'm', b'l', b'i', b'n', b'k', 0, // "symlink" 6, 0, 0, 0, 0, 0, 0, 0, b't', b'a', b'r', b'g', b'e', b't', 0, 0, // target - 24, 0, 0, 0, 0, 0, 0, 0, b'/', b'n', b'i', b'x', b'/', b's', b't', b'o', b'r', b'e', b'/', b's', b'o', - b'm', b'e', b'w', b'h', b'e', b'r', b'e', b'e', b'l', b's', + 24, 0, 0, 0, 0, 0, 0, 0, b'/', b'n', b'i', b'x', b'/', b's', b't', b'o', b'r', b'e', b'/', + b's', b'o', b'm', b'e', b'w', b'h', b'e', b'r', b'e', b'e', b'l', b's', b'e', // "/nix/store/somewhereelse" 1, 0, 0, 0, 0, 0, 0, 0, b')', 0, 0, 0, 0, 0, 0, 0, // ")" 1, 0, 0, 0, 0, 0, 0, 0, b')', 0, 0, 0, 0, 0, 0, 0, // ")" @@ -84,7 +120,8 @@ lazy_static! { 4, 0, 0, 0, 0, 0, 0, 0, b'n', b'o', b'd', b'e', 0, 0, 0, 0, // "node" 1, 0, 0, 0, 0, 0, 0, 0, b'(', 0, 0, 0, 0, 0, 0, 0, // "(" 4, 0, 0, 0, 0, 0, 0, 0, b't', b'y', b'p', b'e', 0, 0, 0, 0, // "type" - 9, 0, 0, 0, 0, 0, 0, 0, b'd', b'i', b'r', b'e', b'c', b't', b'o', b'r', b'y', 0, 0, 0, 0, 0, 0, 0, // "directory" + 9, 0, 0, 0, 0, 0, 0, 0, b'd', b'i', b'r', b'e', b'c', b't', b'o', b'r', b'y', 0, 0, 0, 0, + 0, 0, 0, // "directory" 5, 0, 0, 0, 0, 0, 0, 0, b'e', b'n', b't', b'r', b'y', 0, 0, 0, // "entry" 1, 0, 0, 0, 0, 0, 0, 0, b'(', 0, 0, 0, 0, 0, 0, 0, // "(" 4, 0, 0, 0, 0, 0, 0, 0, b'n', b'a', b'm', b'e', 0, 0, 0, 0, // "name" @@ -100,36 +137,23 @@ lazy_static! { 1, 0, 0, 0, 0, 0, 0, 0, b')', 0, 0, 0, 0, 0, 0, 0, // ")" 1, 0, 0, 0, 0, 0, 0, 0, b')', 0, 0, 0, 0, 0, 0, 0, // ")" 1, 0, 0, 0, 0, 0, 0, 0, b')', 0, 0, 0, 0, 0, 0, 0, // ")" - ]; + ] +}); - /// A PathInfo message without .narinfo populated. - pub static ref PATH_INFO_WITHOUT_NARINFO : PathInfo = PathInfo { - node: Some(castorepb::Node { - node: Some(castorepb::node::Node::Directory(castorepb::DirectoryNode { - name: DUMMY_PATH.into(), - digest: DUMMY_DIGEST.clone().into(), - size: 0, - })), - }), - references: vec![DUMMY_PATH_DIGEST.as_slice().into()], - narinfo: None, - }; - - /// A PathInfo message with .narinfo populated. - /// The references in `narinfo.reference_names` aligns with what's in - /// `references`. - pub static ref PATH_INFO_WITH_NARINFO : PathInfo = PathInfo { - narinfo: Some(NarInfo { - nar_size: 0, - nar_sha256: DUMMY_DIGEST.clone().into(), - signatures: vec![], - reference_names: vec![DUMMY_PATH.to_string()], - deriver: None, - ca: Some(Ca { r#type: ca::Hash::NarSha256.into(), digest: DUMMY_DIGEST.clone().into() }) - }), - ..PATH_INFO_WITHOUT_NARINFO.clone() - }; -} +/// A PathInfo message +pub static PATH_INFO: LazyLock<PathInfo> = LazyLock::new(|| PathInfo { + store_path: DUMMY_PATH.clone(), + node: tvix_castore::Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 0, + }, + references: vec![DUMMY_PATH.clone()], + nar_sha256: [0; 32], + nar_size: 0, + signatures: vec![], + deriver: None, + ca: Some(CAHash::Nar(NixHash::Sha256([0; 32]))), +}); #[fixture] pub(crate) fn blob_service() -> Arc<dyn BlobService> { @@ -137,6 +161,46 @@ pub(crate) fn blob_service() -> Arc<dyn BlobService> { } #[fixture] +pub(crate) async fn blob_service_with_contents() -> Arc<dyn BlobService> { + let blob_service = Arc::from(MemoryBlobService::default()); + for (blob_contents, blob_digest) in [ + (EMPTY_BLOB_CONTENTS, &*EMPTY_BLOB_DIGEST), + (HELLOWORLD_BLOB_CONTENTS, &*HELLOWORLD_BLOB_DIGEST), + ] { + // put all data into the stores. + // insert blob into the store + let mut writer = blob_service.open_write().await; + tokio::io::copy(&mut io::Cursor::new(blob_contents), &mut writer) + .await + .unwrap(); + assert_eq!(blob_digest.clone(), writer.close().await.unwrap()); + } + blob_service +} + +#[fixture] pub(crate) fn directory_service() -> Arc<dyn DirectoryService> { Arc::from(MemoryDirectoryService::default()) } + +#[fixture] +pub(crate) async fn directory_service_with_contents() -> Arc<dyn DirectoryService> { + let directory_service = Arc::from(MemoryDirectoryService::default()); + for directory in [&*DIRECTORY_WITH_KEEP, &*DIRECTORY_COMPLICATED] { + directory_service.put(directory.clone()).await.unwrap(); + } + directory_service +} + +#[template] +#[rstest] +#[case::symlink (&*CASTORE_NODE_SYMLINK, Ok(Ok(&*NAR_CONTENTS_SYMLINK)))] +#[case::helloworld (&*CASTORE_NODE_HELLOWORLD, Ok(Ok(&*NAR_CONTENTS_HELLOWORLD)))] +#[case::too_big (&*CASTORE_NODE_TOO_BIG, Ok(Err(io::ErrorKind::UnexpectedEof)))] +#[case::too_small (&*CASTORE_NODE_TOO_SMALL, Ok(Err(io::ErrorKind::InvalidInput)))] +#[case::complicated(&*CASTORE_NODE_COMPLICATED, Ok(Ok(&*NAR_CONTENTS_COMPLICATED)))] +fn castore_fixtures_template( + #[case] test_input: &Node, + #[case] test_output: Result<Result<&Vec<u8>, io::ErrorKind>, crate::nar::RenderError>, +) { +} diff --git a/tvix/store/src/tests/mod.rs b/tvix/store/src/tests/mod.rs index 1e7fc3f6b451..c7e6fee0cc6c 100644 --- a/tvix/store/src/tests/mod.rs +++ b/tvix/store/src/tests/mod.rs @@ -1,2 +1,3 @@ pub mod fixtures; mod nar_renderer; +mod nar_renderer_seekable; diff --git a/tvix/store/src/tests/nar_renderer.rs b/tvix/store/src/tests/nar_renderer.rs index 8bfb5a72bb2f..6314ba6ccc49 100644 --- a/tvix/store/src/tests/nar_renderer.rs +++ b/tvix/store/src/tests/nar_renderer.rs @@ -1,40 +1,13 @@ -use crate::nar::calculate_size_and_sha256; use crate::nar::write_nar; -use crate::tests::fixtures::blob_service; -use crate::tests::fixtures::directory_service; use crate::tests::fixtures::*; use rstest::*; -use sha2::{Digest, Sha256}; +use rstest_reuse::*; use std::io; use std::sync::Arc; use tokio::io::sink; use tvix_castore::blobservice::BlobService; use tvix_castore::directoryservice::DirectoryService; -use tvix_castore::proto as castorepb; - -#[rstest] -#[tokio::test] -async fn single_symlink( - blob_service: Arc<dyn BlobService>, - directory_service: Arc<dyn DirectoryService>, -) { - let mut buf: Vec<u8> = vec![]; - - write_nar( - &mut buf, - &castorepb::node::Node::Symlink(castorepb::SymlinkNode { - name: "doesntmatter".into(), - target: "/nix/store/somewhereelse".into(), - }), - // don't put anything in the stores, as we don't actually do any requests. - blob_service, - directory_service, - ) - .await - .expect("must succeed"); - - assert_eq!(buf, NAR_CONTENTS_SYMLINK.to_vec()); -} +use tvix_castore::Node; /// Make sure the NARRenderer fails if a referred blob doesn't exist. #[rstest] @@ -45,12 +18,7 @@ async fn single_file_missing_blob( ) { let e = write_nar( sink(), - &castorepb::node::Node::File(castorepb::FileNode { - name: "doesntmatter".into(), - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), - size: HELLOWORLD_BLOB_CONTENTS.len() as u64, - executable: false, - }), + &CASTORE_NODE_HELLOWORLD, // the blobservice is empty intentionally, to provoke the error. blob_service, directory_service, @@ -66,163 +34,44 @@ async fn single_file_missing_blob( } } -/// Make sure the NAR Renderer fails if the returned blob meta has another size -/// than specified in the proto node. -#[rstest] -#[tokio::test] -async fn single_file_wrong_blob_size( - blob_service: Arc<dyn BlobService>, - directory_service: Arc<dyn DirectoryService>, -) { - // insert blob into the store - let mut writer = blob_service.open_write().await; - tokio::io::copy( - &mut io::Cursor::new(HELLOWORLD_BLOB_CONTENTS.to_vec()), - &mut writer, - ) - .await - .unwrap(); - assert_eq!( - HELLOWORLD_BLOB_DIGEST.clone(), - writer.close().await.unwrap() - ); - - // Test with a root FileNode of a too big size - let e = write_nar( - sink(), - &castorepb::node::Node::File(castorepb::FileNode { - name: "doesntmatter".into(), - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), - size: 42, // <- note the wrong size here! - executable: false, - }), - blob_service.clone(), - directory_service.clone(), - ) - .await - .expect_err("must fail"); - - match e { - crate::nar::RenderError::NARWriterError(e) => { - assert_eq!(io::ErrorKind::UnexpectedEof, e.kind()); - } - _ => panic!("unexpected error: {:?}", e), - } - - // Test with a root FileNode of a too small size - let e = write_nar( - sink(), - &castorepb::node::Node::File(castorepb::FileNode { - name: "doesntmatter".into(), - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), - size: 2, // <- note the wrong size here! - executable: false, - }), - blob_service, - directory_service, - ) - .await - .expect_err("must fail"); - - match e { - crate::nar::RenderError::NARWriterError(e) => { - assert_eq!(io::ErrorKind::InvalidInput, e.kind()); - } - _ => panic!("unexpected error: {:?}", e), - } -} - -#[rstest] -#[tokio::test] -async fn single_file( - blob_service: Arc<dyn BlobService>, - directory_service: Arc<dyn DirectoryService>, -) { - // insert blob into the store - let mut writer = blob_service.open_write().await; - tokio::io::copy(&mut io::Cursor::new(HELLOWORLD_BLOB_CONTENTS), &mut writer) - .await - .unwrap(); - - assert_eq!( - HELLOWORLD_BLOB_DIGEST.clone(), - writer.close().await.unwrap() - ); - - let mut buf: Vec<u8> = vec![]; - - write_nar( - &mut buf, - &castorepb::node::Node::File(castorepb::FileNode { - name: "doesntmatter".into(), - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), - size: HELLOWORLD_BLOB_CONTENTS.len() as u64, - executable: false, - }), - blob_service, - directory_service, - ) - .await - .expect("must succeed"); - - assert_eq!(buf, NAR_CONTENTS_HELLOWORLD.to_vec()); -} - -#[rstest] +#[apply(castore_fixtures_template)] #[tokio::test] -async fn test_complicated( - blob_service: Arc<dyn BlobService>, - directory_service: Arc<dyn DirectoryService>, +async fn seekable( + #[future] blob_service_with_contents: Arc<dyn BlobService>, + #[future] directory_service_with_contents: Arc<dyn DirectoryService>, + #[case] test_input: &Node, + #[case] test_output: Result<Result<&Vec<u8>, io::ErrorKind>, crate::nar::RenderError>, ) { - // put all data into the stores. - // insert blob into the store - let mut writer = blob_service.open_write().await; - tokio::io::copy(&mut io::Cursor::new(EMPTY_BLOB_CONTENTS), &mut writer) - .await - .unwrap(); - assert_eq!(EMPTY_BLOB_DIGEST.clone(), writer.close().await.unwrap()); - - // insert directories - directory_service - .put(DIRECTORY_WITH_KEEP.clone()) - .await - .unwrap(); - directory_service - .put(DIRECTORY_COMPLICATED.clone()) - .await - .unwrap(); + let blob_service = blob_service_with_contents.await; + let directory_service = directory_service_with_contents.await; let mut buf: Vec<u8> = vec![]; - - write_nar( + let read_result = write_nar( &mut buf, - &castorepb::node::Node::Directory(castorepb::DirectoryNode { - name: "doesntmatter".into(), - digest: DIRECTORY_COMPLICATED.digest().into(), - size: DIRECTORY_COMPLICATED.size(), - }), - blob_service.clone(), - directory_service.clone(), - ) - .await - .expect("must succeed"); - - assert_eq!(buf, NAR_CONTENTS_COMPLICATED.to_vec()); - - // ensure calculate_nar does return the correct sha256 digest and sum. - let (nar_size, nar_digest) = calculate_size_and_sha256( - &castorepb::node::Node::Directory(castorepb::DirectoryNode { - name: "doesntmatter".into(), - digest: DIRECTORY_COMPLICATED.digest().into(), - size: DIRECTORY_COMPLICATED.size(), - }), + test_input, + // don't put anything in the stores, as we don't actually do any requests. blob_service, directory_service, ) - .await - .expect("must succeed"); + .await; - assert_eq!(NAR_CONTENTS_COMPLICATED.len() as u64, nar_size); - let d = Sha256::digest(NAR_CONTENTS_COMPLICATED.clone()); - assert_eq!(d.as_slice(), nar_digest); + match (read_result, test_output) { + (Ok(_), Err(_)) => panic!("creating reader should have failed but succeeded"), + (Ok(_), Ok(Err(_))) => panic!("creating reader should have failed but succeeded"), + (Err(err), Ok(Ok(_))) => { + panic!("creating reader should have succeeded but failed: {}", err) + } + (Err(reader_err), Err(expected_err)) => { + assert_eq!(format!("{}", reader_err), format!("{}", expected_err)); + } + (Err(reader_err), Ok(Err(expected_err))) => { + let crate::nar::RenderError::NARWriterError(e) = reader_err else { + panic!("expected nar writer error") + }; + assert_eq!(e.kind(), expected_err); + } + (Ok(_n), Ok(Ok(expected_read_result))) => { + assert_eq!(buf, expected_read_result.to_vec()); + } + } } diff --git a/tvix/store/src/tests/nar_renderer_seekable.rs b/tvix/store/src/tests/nar_renderer_seekable.rs new file mode 100644 index 000000000000..233b95d0b036 --- /dev/null +++ b/tvix/store/src/tests/nar_renderer_seekable.rs @@ -0,0 +1,111 @@ +use crate::nar::seekable::Reader; +use crate::tests::fixtures::blob_service_with_contents as blob_service; +use crate::tests::fixtures::directory_service_with_contents as directory_service; +use crate::tests::fixtures::*; +use rstest::*; +use rstest_reuse::*; +use std::io; +use std::pin::Pin; +use std::sync::Arc; +use tokio::io::{AsyncReadExt, AsyncSeek, AsyncSeekExt}; +use tvix_castore::blobservice::BlobService; +use tvix_castore::directoryservice::DirectoryService; +use tvix_castore::Node; + +#[apply(castore_fixtures_template)] +#[tokio::test] +async fn read_to_end( + #[future] blob_service: Arc<dyn BlobService>, + #[future] directory_service: Arc<dyn DirectoryService>, + #[case] test_input: &Node, + #[case] test_output: Result<Result<&Vec<u8>, io::ErrorKind>, crate::nar::RenderError>, +) { + let reader_result = Reader::new( + test_input.clone(), + // don't put anything in the stores, as we don't actually do any requests. + blob_service.await, + directory_service.await, + ) + .await; + + match (reader_result, test_output) { + (Ok(_), Err(_)) => panic!("creating reader should have failed but succeeded"), + (Err(err), Ok(_)) => panic!("creating reader should have succeeded but failed: {}", err), + (Err(reader_err), Err(expected_err)) => { + assert_eq!(format!("{}", reader_err), format!("{}", expected_err)); + } + (Ok(mut reader), Ok(expected_read_result)) => { + let mut buf: Vec<u8> = vec![]; + let read_result = reader.read_to_end(&mut buf).await; + + match (read_result, expected_read_result) { + (Ok(_), Err(_)) => panic!("read_to_end should have failed but succeeded"), + (Err(err), Ok(_)) => { + panic!("read_to_end should have succeeded but failed: {}", err) + } + (Err(read_err), Err(expected_read_err)) => { + assert_eq!(read_err.kind(), expected_read_err); + } + (Ok(_n), Ok(expected_read_result)) => { + assert_eq!(buf, expected_read_result.to_vec()); + } + } + } + } +} + +#[rstest] +#[tokio::test] +/// Check that the Reader does not allow starting a seek while another seek is running +/// If this is not prevented, it might lead to futures piling up on the heap +async fn seek_twice( + #[future] blob_service: Arc<dyn BlobService>, + #[future] directory_service: Arc<dyn DirectoryService>, +) { + let mut reader = Reader::new( + CASTORE_NODE_COMPLICATED.clone(), + // don't put anything in the stores, as we don't actually do any requests. + blob_service.await, + directory_service.await, + ) + .await + .expect("must succeed"); + + Pin::new(&mut reader) + .start_seek(io::SeekFrom::Start(1)) + .expect("must succeed"); + let seek_err = Pin::new(&mut reader) + .start_seek(io::SeekFrom::Start(2)) + .expect_err("must fail"); + + assert_eq!(seek_err.kind(), io::ErrorKind::Other); + assert_eq!(seek_err.to_string(), "Already seeking".to_string()); +} + +#[rstest] +#[tokio::test] +async fn seek( + #[future] blob_service: Arc<dyn BlobService>, + #[future] directory_service: Arc<dyn DirectoryService>, +) { + let mut reader = Reader::new( + CASTORE_NODE_HELLOWORLD.clone(), + // don't put anything in the stores, as we don't actually do any requests. + blob_service.await, + directory_service.await, + ) + .await + .expect("must succeed"); + + let mut buf = [0u8; 10]; + + for position in [ + io::SeekFrom::Start(0x65), // Just before the file contents + io::SeekFrom::Start(0x68), // Seek back the file contents + io::SeekFrom::Start(0x70), // Just before the end of the file contents + ] { + let n = reader.seek(position).await.expect("seek") as usize; + reader.read_exact(&mut buf).await.expect("read_exact"); + assert_eq!(NAR_CONTENTS_HELLOWORLD[n..n + 10], buf); + } +} diff --git a/tvix/store/src/utils.rs b/tvix/store/src/utils.rs index 0b171377bde1..86ec367b66ad 100644 --- a/tvix/store/src/utils.rs +++ b/tvix/store/src/utils.rs @@ -1,42 +1,221 @@ -use std::sync::Arc; use std::{ + collections::HashMap, pin::Pin, + sync::Arc, task::{self, Poll}, }; use tokio::io::{self, AsyncWrite}; -use tvix_castore::{ - blobservice::{self, BlobService}, - directoryservice::{self, DirectoryService}, +use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService}; +use url::Url; + +use crate::composition::{ + with_registry, Composition, DeserializeWithRegistry, ServiceBuilder, REG, }; +use crate::nar::{NarCalculationService, SimpleRenderer}; +use crate::pathinfoservice::PathInfoService; + +#[derive(serde::Deserialize, Default)] +pub struct CompositionConfigs { + pub blobservices: + HashMap<String, DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = dyn BlobService>>>>, + pub directoryservices: HashMap< + String, + DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = dyn DirectoryService>>>, + >, + pub pathinfoservices: HashMap< + String, + DeserializeWithRegistry<Box<dyn ServiceBuilder<Output = dyn PathInfoService>>>, + >, +} + +/// Provides a set clap arguments to configure tvix-[ca]store services. +/// +/// This particular variant has defaults tailored for usecases accessing data +/// directly locally, like the `tvix-store daemon` command. +#[derive(clap::Parser, Clone)] +pub struct ServiceUrls { + #[arg( + long, + env, + default_value = "objectstore+file:///var/lib/tvix-store/blobs.object_store" + )] + blob_service_addr: String, + + #[arg( + long, + env, + default_value = "redb:///var/lib/tvix-store/directories.redb" + )] + directory_service_addr: String, + + #[arg(long, env, default_value = "redb:///var/lib/tvix-store/pathinfo.redb")] + path_info_service_addr: String, + + /// Path to a TOML file describing the way the services should be composed + /// Experimental because the format is not final. + /// If specified, the other service addrs are ignored. + #[cfg(feature = "xp-store-composition")] + #[arg(long, env)] + experimental_store_composition: Option<String>, +} + +/// Provides a set clap arguments to configure tvix-[ca]store services. +/// +/// This particular variant has defaults tailored for usecases accessing data +/// from another running tvix daemon, via gRPC. +#[derive(clap::Parser, Clone)] +pub struct ServiceUrlsGrpc { + #[arg(long, env, default_value = "grpc+http://[::1]:8000")] + blob_service_addr: String, + + #[arg(long, env, default_value = "grpc+http://[::1]:8000")] + directory_service_addr: String, -use crate::pathinfoservice::{self, PathInfoService}; + #[arg(long, env, default_value = "grpc+http://[::1]:8000")] + path_info_service_addr: String, -/// Construct the three store handles from their addrs. + #[cfg(feature = "xp-store-composition")] + #[arg(long, env)] + experimental_store_composition: Option<String>, +} + +/// Provides a set clap arguments to configure tvix-[ca]store services. +/// +/// This particular variant has defaults tailored for usecases keeping all data +/// in memory. +/// It's currently used in tvix-cli, as we don't really care about persistency +/// there yet, and using something else here might make some perf output harder +/// to interpret. +#[derive(clap::Parser, Clone)] +pub struct ServiceUrlsMemory { + #[arg(long, env, default_value = "memory://")] + blob_service_addr: String, + + #[arg(long, env, default_value = "memory://")] + directory_service_addr: String, + + #[arg(long, env, default_value = "memory://")] + path_info_service_addr: String, + + #[cfg(feature = "xp-store-composition")] + #[arg(long, env)] + experimental_store_composition: Option<String>, +} + +impl From<ServiceUrlsGrpc> for ServiceUrls { + fn from(urls: ServiceUrlsGrpc) -> ServiceUrls { + ServiceUrls { + blob_service_addr: urls.blob_service_addr, + directory_service_addr: urls.directory_service_addr, + path_info_service_addr: urls.path_info_service_addr, + #[cfg(feature = "xp-store-composition")] + experimental_store_composition: urls.experimental_store_composition, + } + } +} + +impl From<ServiceUrlsMemory> for ServiceUrls { + fn from(urls: ServiceUrlsMemory) -> ServiceUrls { + ServiceUrls { + blob_service_addr: urls.blob_service_addr, + directory_service_addr: urls.directory_service_addr, + path_info_service_addr: urls.path_info_service_addr, + #[cfg(feature = "xp-store-composition")] + experimental_store_composition: urls.experimental_store_composition, + } + } +} + +pub async fn addrs_to_configs( + urls: impl Into<ServiceUrls>, +) -> Result<CompositionConfigs, Box<dyn std::error::Error + Send + Sync>> { + let urls: ServiceUrls = urls.into(); + + #[cfg(feature = "xp-store-composition")] + if let Some(conf_path) = urls.experimental_store_composition { + let conf_text = tokio::fs::read_to_string(conf_path).await?; + return Ok(with_registry(®, || toml::from_str(&conf_text))?); + } + + let mut configs: CompositionConfigs = Default::default(); + + let blob_service_url = Url::parse(&urls.blob_service_addr)?; + let directory_service_url = Url::parse(&urls.directory_service_addr)?; + let path_info_service_url = Url::parse(&urls.path_info_service_addr)?; + + configs.blobservices.insert( + "default".into(), + with_registry(®, || blob_service_url.try_into())?, + ); + configs.directoryservices.insert( + "default".into(), + with_registry(®, || directory_service_url.try_into())?, + ); + configs.pathinfoservices.insert( + "default".into(), + with_registry(®, || path_info_service_url.try_into())?, + ); + + Ok(configs) +} + +/// Construct the store handles from their addrs. pub async fn construct_services( - blob_service_addr: impl AsRef<str>, - directory_service_addr: impl AsRef<str>, - path_info_service_addr: impl AsRef<str>, -) -> std::io::Result<( - Arc<dyn BlobService>, - Arc<dyn DirectoryService>, - Box<dyn PathInfoService>, -)> { - let blob_service: Arc<dyn BlobService> = blobservice::from_addr(blob_service_addr.as_ref()) - .await? - .into(); - let directory_service: Arc<dyn DirectoryService> = - directoryservice::from_addr(directory_service_addr.as_ref()) - .await? - .into(); - let path_info_service = pathinfoservice::from_addr( - path_info_service_addr.as_ref(), - blob_service.clone(), - directory_service.clone(), - ) - .await?; - - Ok((blob_service, directory_service, path_info_service)) + urls: impl Into<ServiceUrls>, +) -> Result< + ( + Arc<dyn BlobService>, + Arc<dyn DirectoryService>, + Arc<dyn PathInfoService>, + Box<dyn NarCalculationService>, + ), + Box<dyn std::error::Error + Send + Sync>, +> { + let configs = addrs_to_configs(urls).await?; + construct_services_from_configs(configs).await +} + +/// Construct the store handles from their addrs. +pub async fn construct_services_from_configs( + configs: CompositionConfigs, +) -> Result< + ( + Arc<dyn BlobService>, + Arc<dyn DirectoryService>, + Arc<dyn PathInfoService>, + Box<dyn NarCalculationService>, + ), + Box<dyn std::error::Error + Send + Sync>, +> { + let mut comp = Composition::new(®); + + comp.extend(configs.blobservices); + comp.extend(configs.directoryservices); + comp.extend(configs.pathinfoservices); + + let blob_service: Arc<dyn BlobService> = comp.build("default").await?; + let directory_service: Arc<dyn DirectoryService> = comp.build("default").await?; + let path_info_service: Arc<dyn PathInfoService> = comp.build("default").await?; + + // HACK: The grpc client also implements NarCalculationService, and we + // really want to use it (otherwise we'd need to fetch everything again for hashing). + // Until we revamped store composition and config, detect this special case here. + let nar_calculation_service: Box<dyn NarCalculationService> = path_info_service + .nar_calculation_service() + .unwrap_or_else(|| { + Box::new(SimpleRenderer::new( + blob_service.clone(), + directory_service.clone(), + )) + }); + + Ok(( + blob_service, + directory_service, + path_info_service, + nar_calculation_service, + )) } /// The inverse of [tokio_util::io::SyncIoBridge]. diff --git a/tvix/tools/crunch-v2/default.nix b/tvix/tools/crunch-v2/default.nix deleted file mode 100644 index 689e86be6559..000000000000 --- a/tvix/tools/crunch-v2/default.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ pkgs, ... }: - -let - crates = import ./Cargo.nix { - inherit pkgs; - nixpkgs = pkgs.path; - - defaultCrateOverrides = pkgs.defaultCrateOverrides // { - crunch-v2 = prev: { - nativeBuildInputs = (prev.nativeBuildInputs or [ ]) ++ [ pkgs.buildPackages.protobuf ]; - }; - }; - }; -in -crates.rootCrate.build diff --git a/tvix/tools/narinfo2parquet/default.nix b/tvix/tools/narinfo2parquet/default.nix deleted file mode 100644 index 5a84d7f64287..000000000000 --- a/tvix/tools/narinfo2parquet/default.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ pkgs, ... }: - -(pkgs.callPackage ./Cargo.nix { }).rootCrate.build diff --git a/tvix/tools/turbofetch/default.nix b/tvix/tools/turbofetch/default.nix deleted file mode 100644 index bd70f6a5e694..000000000000 --- a/tvix/tools/turbofetch/default.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ lib, pkgs, ... }: - -(pkgs.callPackage ./Cargo.nix { - defaultCrateOverrides = pkgs.defaultCrateOverrides // { - - ring = prev: { - links = ''ring_core_${lib.replaceStrings ["."] ["_"] prev.version}''; - }; - }; -}).rootCrate.build.override { - runTests = true; -} diff --git a/tvix/tools/weave/default.nix b/tvix/tools/weave/default.nix deleted file mode 100644 index 5a84d7f64287..000000000000 --- a/tvix/tools/weave/default.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ pkgs, ... }: - -(pkgs.callPackage ./Cargo.nix { }).rootCrate.build diff --git a/tvix/tools/weave/src/bin/swizzle.rs b/tvix/tools/weave/src/bin/swizzle.rs deleted file mode 100644 index 68c18581268a..000000000000 --- a/tvix/tools/weave/src/bin/swizzle.rs +++ /dev/null @@ -1,114 +0,0 @@ -//! Swizzle reads a `narinfo.parquet` file, usually produced by `narinfo2parquet`. -//! -//! It swizzles the reference list, ie it converts the references from absolute, -//! global identifiers (store path hashes) to indices into the `store_path_hash` -//! column (ie, row numbers), so that we can later walk the reference graph -//! efficiently. -//! -//! Path hashes are represented as non-null, 20-byte `Binary` values. -//! The indices are represented as 32-bit unsigned integers, with in-band nulls -//! represented by [INDEX_NULL] (the all-1 bit pattern), to permit swizzling -//! partial datasets. -//! -//! In essence, it converts from names to pointers, so that `weave` can simply -//! chase pointers to trace the live set. This replaces an `O(log(n))` lookup -//! with `O(1)` indexing, and produces a much denser representation that actually -//! fits in memory. -//! -//! The in-memory representation is at least 80% smaller, and the indices compress -//! well in Parquet due to both temporal locality of reference and the power law -//! distribution of reference "popularity". -//! -//! Only two columns are read from `narinfo.parquet`: -//! -//! * `store_path_hash :: PathHash` -//! * `references :: List[PathHash]` -//! -//! Output is written to `narinfo-references.parquet` in the form of a single -//! `List[u32]` column, `reference_idxs`. -//! -//! This file is inherently bound to the corresponding `narinfo.parquet`, -//! since it essentially contains pointers into this file. - -use anyhow::Result; -use hashbrown::HashTable; -use polars::prelude::*; -use rayon::prelude::*; -use std::fs::File; -use tokio::runtime::Runtime; - -use weave::{as_fixed_binary, hash64, load_ph_array, DONE, INDEX_NULL}; - -fn main() -> Result<()> { - let ph_array = load_ph_array()?; - - // TODO(edef): re-parallelise this - // We originally parallelised on chunks, but ph_array is only a single chunk, due to how Parquet loading works. - // TODO(edef): outline the 64-bit hash prefix? it's an indirection, but it saves ~2G of memory - eprint!("… build index\r"); - let ph_map: HashTable<(u64, u32)> = { - let mut ph_map = HashTable::with_capacity(ph_array.len()); - - for (offset, item) in ph_array.iter().enumerate() { - let offset = offset as u32; - let hash = hash64(item); - ph_map.insert_unique(hash, (hash, offset), |&(hash, _)| hash); - } - - ph_map - }; - eprintln!("{DONE}"); - - eprint!("… swizzle references\r"); - let mut pq = ParquetReader::new(File::open("narinfo.parquet")?) - .with_columns(Some(vec!["references".into()])) - .batched(1 << 16)?; - - let mut reference_idxs = - Series::new_empty("reference_idxs", &DataType::List(DataType::UInt32.into())); - - let mut bounce = vec![]; - let runtime = Runtime::new()?; - while let Some(batches) = runtime.block_on(pq.next_batches(48))? { - batches - .into_par_iter() - .map(|df| -> ListChunked { - df.column("references") - .unwrap() - .list() - .unwrap() - .apply_to_inner(&|series: Series| -> PolarsResult<Series> { - let series = series.binary()?; - let mut out: Vec<u32> = Vec::with_capacity(series.len()); - - out.extend(as_fixed_binary::<20>(series).flat_map(|xs| xs).map(|key| { - let hash = hash64(&key); - ph_map - .find(hash, |&(candidate_hash, candidate_index)| { - candidate_hash == hash - && &ph_array[candidate_index as usize] == key - }) - .map(|&(_, index)| index) - .unwrap_or(INDEX_NULL) - })); - - Ok(Series::from_vec("reference_idxs", out)) - }) - .unwrap() - }) - .collect_into_vec(&mut bounce); - - for batch in bounce.drain(..) { - reference_idxs.append(&batch.into_series())?; - } - } - eprintln!("{DONE}"); - - eprint!("… writing output\r"); - ParquetWriter::new(File::create("narinfo-references.parquet")?).finish(&mut df! { - "reference_idxs" => reference_idxs, - }?)?; - eprintln!("{DONE}"); - - Ok(()) -} diff --git a/tvix/tools/weave/src/bytes.rs b/tvix/tools/weave/src/bytes.rs deleted file mode 100644 index c6dc2ebb4492..000000000000 --- a/tvix/tools/weave/src/bytes.rs +++ /dev/null @@ -1,27 +0,0 @@ -use owning_ref::{OwningRef, StableAddress}; -use polars::export::arrow::buffer::Buffer; -use std::ops::Deref; - -/// An shared `[[u8; N]]` backed by a Polars [Buffer]. -pub type FixedBytes<const N: usize> = OwningRef<Bytes, [[u8; N]]>; - -/// Wrapper struct to make [Buffer] implement [StableAddress]. -/// TODO(edef): upstream the `impl` -pub struct Bytes(pub Buffer<u8>); - -/// SAFETY: [Buffer] is always an Arc+Vec indirection. -unsafe impl StableAddress for Bytes {} - -impl Bytes { - pub fn map<U: ?Sized>(self, f: impl FnOnce(&[u8]) -> &U) -> OwningRef<Self, U> { - OwningRef::new(self).map(f) - } -} - -impl Deref for Bytes { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &*self.0 - } -} diff --git a/tvix/tools/weave/src/main.rs b/tvix/tools/weave/src/main.rs deleted file mode 100644 index e8a1990a0df3..000000000000 --- a/tvix/tools/weave/src/main.rs +++ /dev/null @@ -1,216 +0,0 @@ -//! Weave resolves a list of roots from `nixpkgs.roots` against `narinfo.parquet`, -//! and then uses the reference graph from the accompanying `narinfo-references.parquet` -//! produced by `swizzle` to collect the closure of the roots. -//! -//! They are written to `live_idxs.parquet`, which only has one column, representing -//! the row numbers in `narinfo.parquet` corresponding to live paths. - -use anyhow::Result; -use hashbrown::{hash_table, HashTable}; -use nix_compat::nixbase32; -use rayon::prelude::*; -use std::{ - collections::{BTreeMap, HashSet}, - fs::{self, File}, - ops::Index, - sync::atomic::{AtomicU32, Ordering}, -}; - -use polars::{ - datatypes::StaticArray, - export::arrow::{array::UInt32Array, offset::OffsetsBuffer}, - prelude::*, -}; - -use weave::{hash64, DONE, INDEX_NULL}; - -fn main() -> Result<()> { - eprint!("… parse roots\r"); - let roots: PathSet32 = { - let mut roots = Vec::new(); - fs::read("nixpkgs.roots")? - .par_chunks_exact(32 + 1) - .map(|e| nixbase32::decode_fixed::<20>(&e[0..32]).unwrap()) - .collect_into_vec(&mut roots); - - roots.iter().collect() - }; - eprintln!("{DONE}"); - - { - let ph_array = weave::load_ph_array()?; - - eprint!("… resolve roots\r"); - ph_array.par_iter().enumerate().for_each(|(idx, h)| { - if let Some(idx_slot) = roots.find(h) { - idx_slot - .compare_exchange(INDEX_NULL, idx as u32, Ordering::SeqCst, Ordering::SeqCst) - .expect("duplicate entry"); - } - }); - eprintln!("{DONE}"); - } - - let mut todo = HashSet::with_capacity(roots.len()); - { - let mut unknown_roots = 0usize; - for (_, idx) in roots.table { - let idx = idx.into_inner(); - if idx == INDEX_NULL { - unknown_roots += 1; - continue; - } - todo.insert(idx); - } - println!("skipping {unknown_roots} unknown roots"); - } - - eprint!("… load reference_idxs\r"); - let ri_array = ParquetReader::new(File::open("narinfo-references.parquet")?) - .finish()? - .column("reference_idxs")? - .list()? - .clone(); - - let ri_array = { - ChunkedList::new(ri_array.downcast_iter().map(|chunk| { - ( - chunk.offsets(), - chunk - .values() - .as_any() - .downcast_ref::<UInt32Array>() - .unwrap() - .as_slice() - .unwrap(), - ) - })) - }; - eprintln!("{DONE}"); - - let mut seen = todo.clone(); - while !todo.is_empty() { - println!("todo: {} seen: {}", todo.len(), seen.len()); - - todo = todo - .par_iter() - .flat_map(|&parent| { - if parent == INDEX_NULL { - return vec![]; - } - - ri_array[parent as usize] - .iter() - .cloned() - .filter(|child| !seen.contains(child)) - .collect::<Vec<u32>>() - }) - .collect(); - - for &index in &todo { - seen.insert(index); - } - } - - println!("done: {} paths", seen.len()); - - if seen.remove(&INDEX_NULL) { - println!("WARNING: missing edges"); - } - - eprint!("… gathering live set\r"); - let mut seen: Vec<u32> = seen.into_iter().collect(); - seen.par_sort(); - eprintln!("{DONE}"); - - eprint!("… writing output\r"); - ParquetWriter::new(File::create("live_idxs.parquet")?).finish(&mut df! { - "live_idx" => seen, - }?)?; - eprintln!("{DONE}"); - - Ok(()) -} - -struct PathSet32 { - table: HashTable<([u8; 20], AtomicU32)>, -} - -impl PathSet32 { - fn with_capacity(capacity: usize) -> Self { - Self { - table: HashTable::with_capacity(capacity), - } - } - - fn insert(&mut self, value: &[u8; 20]) -> bool { - let hash = hash64(value); - - match self - .table - .entry(hash, |(x, _)| x == value, |(x, _)| hash64(x)) - { - hash_table::Entry::Occupied(_) => false, - hash_table::Entry::Vacant(entry) => { - entry.insert((*value, AtomicU32::new(INDEX_NULL))); - true - } - } - } - - fn find(&self, value: &[u8; 20]) -> Option<&AtomicU32> { - let hash = hash64(value); - self.table - .find(hash, |(x, _)| x == value) - .as_ref() - .map(|(_, x)| x) - } - - fn len(&self) -> usize { - self.table.len() - } -} - -impl<'a> FromIterator<&'a [u8; 20]> for PathSet32 { - fn from_iter<T: IntoIterator<Item = &'a [u8; 20]>>(iter: T) -> Self { - let iter = iter.into_iter(); - let mut this = Self::with_capacity(iter.size_hint().0); - - for item in iter { - this.insert(item); - } - - this - } -} - -struct ChunkedList<'a, T> { - by_offset: BTreeMap<usize, (&'a OffsetsBuffer<i64>, &'a [T])>, -} - -impl<'a, T> ChunkedList<'a, T> { - fn new(chunks: impl IntoIterator<Item = (&'a OffsetsBuffer<i64>, &'a [T])>) -> Self { - let mut next_offset = 0usize; - ChunkedList { - by_offset: chunks - .into_iter() - .map(|(offsets, values)| { - let offset = next_offset; - next_offset = next_offset.checked_add(offsets.len_proxy()).unwrap(); - - (offset, (offsets, values)) - }) - .collect(), - } - } -} - -impl<'a, T> Index<usize> for ChunkedList<'a, T> { - type Output = [T]; - - fn index(&self, index: usize) -> &Self::Output { - let (&base, &(offsets, values)) = self.by_offset.range(..=index).next_back().unwrap(); - let (start, end) = offsets.start_end(index - base); - &values[start..end] - } -} diff --git a/tvix/tracing/Cargo.toml b/tvix/tracing/Cargo.toml new file mode 100644 index 000000000000..f1621a472f2c --- /dev/null +++ b/tvix/tracing/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "tvix-tracing" +version = "0.1.0" +edition = "2021" + +[dependencies] +tracing = { workspace = true, features = ["max_level_trace", "release_max_level_debug"] } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +indicatif = { workspace = true } +tracing-indicatif = { workspace = true } +tokio = { workspace = true, features = ["sync", "rt"] } +thiserror = { workspace = true } + +tracing-opentelemetry = { workspace = true, optional = true } +opentelemetry = { workspace = true, optional = true } +opentelemetry-otlp = { workspace = true, optional = true } +opentelemetry_sdk = { workspace = true, features = ["rt-tokio"], optional = true } +tracing-tracy = { workspace = true, features = ["flush-on-exit"], optional = true } +opentelemetry-http = { workspace = true, optional = true } + +tonic = { workspace = true, optional = true } +http = { workspace = true, optional = true } + +reqwest-tracing = { workspace = true, optional = true } + +axum = { workspace = true, optional = true } + +[features] +default = [] +otlp = [ + "dep:tracing-opentelemetry", + "dep:opentelemetry", + "dep:opentelemetry-otlp", + "dep:opentelemetry_sdk", + "dep:opentelemetry-http", + "reqwest-tracing?/opentelemetry_0_22", +] +tracy = [ + "dep:tracing-tracy" +] +tonic = [ + "dep:tonic", + "dep:http", +] +reqwest = [ + "dep:reqwest-tracing", +] +axum = [ + "dep:axum", +] + +[lints] +workspace = true diff --git a/tvix/tracing/default.nix b/tvix/tracing/default.nix new file mode 100644 index 000000000000..b519d0ffc0b3 --- /dev/null +++ b/tvix/tracing/default.nix @@ -0,0 +1,11 @@ +{ depot, lib, ... }: + +(depot.tvix.crates.workspaceMembers.tvix-tracing.build.override { + runTests = true; +}).overrideAttrs (old: rec { + meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { + inherit (old) crateName; + features = [ "otlp" "tracy" "tonic" "reqwest" "axum" ]; + }); +}) diff --git a/tvix/tracing/src/lib.rs b/tvix/tracing/src/lib.rs new file mode 100644 index 000000000000..41f294cf499a --- /dev/null +++ b/tvix/tracing/src/lib.rs @@ -0,0 +1,323 @@ +use indicatif::ProgressStyle; +use std::sync::LazyLock; +use tokio::sync::{mpsc, oneshot}; +use tracing::level_filters::LevelFilter; +use tracing_indicatif::{ + filter::IndicatifFilter, util::FilteredFormatFields, writer, IndicatifLayer, IndicatifWriter, +}; +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer}; + +#[cfg(feature = "otlp")] +use opentelemetry::{ + trace::{Tracer, TracerProvider}, + KeyValue, +}; +#[cfg(feature = "otlp")] +use opentelemetry_sdk::{ + propagation::TraceContextPropagator, + resource::{ResourceDetector, SdkProvidedResourceDetector}, + trace::BatchConfigBuilder, + Resource, +}; +#[cfg(feature = "tracy")] +use tracing_tracy::TracyLayer; + +pub mod propagate; + +pub static PB_PROGRESS_STYLE: LazyLock<ProgressStyle> = LazyLock::new(|| { + ProgressStyle::with_template( + "{span_child_prefix} {wide_msg} {bar:10} ({elapsed}) {pos:>7}/{len:7}", + ) + .expect("invalid progress template") +}); +pub static PB_TRANSFER_STYLE: LazyLock<ProgressStyle> = LazyLock::new(|| { + ProgressStyle::with_template( + "{span_child_prefix} {wide_msg} {binary_bytes:>7}/{binary_total_bytes:7}@{decimal_bytes_per_sec} ({elapsed}) {bar:10} " + ) + .expect("invalid progress template") +}); +pub static PB_SPINNER_STYLE: LazyLock<ProgressStyle> = LazyLock::new(|| { + ProgressStyle::with_template( + "{span_child_prefix}{spinner} {wide_msg} ({elapsed}) {pos:>7}/{len:7}", + ) + .expect("invalid progress template") +}); + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Init(#[from] tracing_subscriber::util::TryInitError), + + #[error(transparent)] + MpscSend(#[from] mpsc::error::SendError<Option<oneshot::Sender<()>>>), + + #[error(transparent)] + OneshotRecv(#[from] oneshot::error::RecvError), +} + +#[derive(Clone)] +pub struct TracingHandle { + tx: Option<mpsc::Sender<Option<oneshot::Sender<()>>>>, + + stdout_writer: IndicatifWriter<writer::Stdout>, + stderr_writer: IndicatifWriter<writer::Stderr>, +} + +impl TracingHandle { + /// Returns a writer for [std::io::Stdout] that ensures its output will not be clobbered by + /// active progress bars. + /// + /// Instead of `println!(...)` prefer `writeln!(handle.get_stdout_writer(), ...)` + pub fn get_stdout_writer(&self) -> IndicatifWriter<writer::Stdout> { + // clone is fine here because its only a wrapper over an `Arc` + self.stdout_writer.clone() + } + + /// Returns a writer for [std::io::Stderr] that ensures its output will not be clobbered by + /// active progress bars. + /// + /// Instead of `println!(...)` prefer `writeln!(handle.get_stderr_writer(), ...)`. + pub fn get_stderr_writer(&self) -> IndicatifWriter<writer::Stderr> { + // clone is fine here because its only a wrapper over an `Arc` + self.stderr_writer.clone() + } + + /// This will flush possible attached tracing providers, e.g. otlp exported, if enabled. + /// If there is none enabled this will result in a noop. + /// + /// It will not wait until the flush is complete, but you can pass in an oneshot::Sender which + /// will receive a message once the flush is completed. + pub async fn flush(&self, msg: Option<oneshot::Sender<()>>) -> Result<(), Error> { + if let Some(tx) = &self.tx { + Ok(tx.send(msg).await?) + } else { + // If we have a message passed in we need to notify the receiver + if let Some(tx) = msg { + let _ = tx.send(()); + } + Ok(()) + } + } + + /// This will flush all all attached tracing providers and will wait until the flush is completed. + /// If no tracing providers like otlp are attached then this will be a noop. + /// + /// This should only be called on a regular shutdown. + /// If you correctly need to shutdown tracing on ctrl_c use [force_shutdown](#method.force_shutdown) + /// otherwise you will get otlp errors. + pub async fn shutdown(&self) -> Result<(), Error> { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.flush(Some(tx)).await?; + rx.await?; + Ok(()) + } + + /// This will flush all all attached tracing providers and will wait until the flush is completed. + /// After this it will do some other necessary cleanup. + /// If no tracing providers like otlp are attached then this will be a noop. + /// + /// This should only be used if the tool received an ctrl_c otherwise you will get otlp errors. + /// If you need to shutdown tracing on a regular exit, you should use the [shutdown](#method.shutdown) + /// method. + pub async fn force_shutdown(&self) -> Result<(), Error> { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.flush(Some(tx)).await?; + rx.await?; + + #[cfg(feature = "otlp")] + { + // Because of a bug within otlp we currently have to use spawn_blocking otherwise + // calling `shutdown_tracer_provider` can block forever. See + // https://github.com/open-telemetry/opentelemetry-rust/issues/1395#issuecomment-1953280335 + // + // This still throws an error, if the tool exits regularly: "OpenTelemetry trace error + // occurred. oneshot canceled", but not having this leads to errors if we cancel with + // ctrl_c. + // So this should right now only be used on ctrl_c, for a regular exit use the + // [shutdown](#shutdown) method + let _ = tokio::task::spawn_blocking(move || { + opentelemetry::global::shutdown_tracer_provider(); + }) + .await; + } + + Ok(()) + } +} + +#[derive(Default)] +pub struct TracingBuilder { + progess_bar: bool, + + #[cfg(feature = "otlp")] + service_name: Option<&'static str>, +} + +impl TracingBuilder { + #[cfg(feature = "otlp")] + /// Enable otlp by setting a custom service_name + pub fn enable_otlp(mut self, service_name: &'static str) -> TracingBuilder { + self.service_name = Some(service_name); + self + } + + /// Enable progress bar layer, default is disabled + pub fn enable_progressbar(mut self) -> TracingBuilder { + self.progess_bar = true; + self + } + + /// This will setup tracing based on the configuration passed in. + /// It will setup a stderr writer output layer and configure EnvFilter to honor RUST_LOG. + /// The EnvFilter will be applied to all configured layers, also otlp. + /// + /// It will also configure otlp if the feature is enabled and a service_name was provided. It + /// will then correctly setup a channel which is later used for flushing the provider. + pub fn build(self) -> Result<TracingHandle, Error> { + // Set up the tracing subscriber. + let indicatif_layer = IndicatifLayer::new().with_progress_style(PB_SPINNER_STYLE.clone()); + let stdout_writer = indicatif_layer.get_stdout_writer(); + let stderr_writer = indicatif_layer.get_stderr_writer(); + let subscriber = tracing_subscriber::registry() + .with( + EnvFilter::builder() + .with_default_directive(LevelFilter::INFO.into()) + .from_env() + .expect("invalid RUST_LOG"), + ) + .with( + tracing_subscriber::fmt::Layer::new() + .fmt_fields(FilteredFormatFields::new( + tracing_subscriber::fmt::format::DefaultFields::new(), + |field| field.name() != "indicatif.pb_show", + )) + .with_writer(indicatif_layer.get_stderr_writer()) + .compact(), + ) + .with((self.progess_bar).then(|| { + indicatif_layer.with_filter( + // only show progress for spans with indicatif.pb_show field being set + IndicatifFilter::new(false), + ) + })); + + // Setup otlp if a service_name is configured + #[cfg(feature = "otlp")] + { + if let Some(service_name) = self.service_name { + // register a text map propagator for trace propagation + opentelemetry::global::set_text_map_propagator(TraceContextPropagator::new()); + + let (tracer, tx) = gen_otlp_tracer(service_name.to_string()); + // Create a tracing layer with the configured tracer + let layer = tracing_opentelemetry::layer().with_tracer(tracer); + + #[cfg(feature = "tracy")] + { + subscriber + .with(TracyLayer::default()) + .with(Some(layer)) + .try_init()?; + } + + #[cfg(not(feature = "tracy"))] + { + subscriber.with(Some(layer)).try_init()?; + } + return Ok(TracingHandle { + tx: Some(tx), + stdout_writer, + stderr_writer, + }); + } + } + #[cfg(feature = "tracy")] + { + subscriber.with(TracyLayer::default()).try_init()?; + } + #[cfg(not(feature = "tracy"))] + { + subscriber.try_init()?; + } + + Ok(TracingHandle { + tx: None, + stdout_writer, + stderr_writer, + }) + } +} + +/// Returns an OTLP tracer, and the TX part of a channel, which can be used +/// to request flushes (and signal back the completion of the flush). +#[cfg(feature = "otlp")] +fn gen_otlp_tracer( + service_name: String, +) -> ( + impl Tracer + tracing_opentelemetry::PreSampledTracer, + mpsc::Sender<Option<oneshot::Sender<()>>>, +) { + let tracer_provider = opentelemetry_otlp::new_pipeline() + .tracing() + .with_exporter(opentelemetry_otlp::new_exporter().tonic()) + .with_batch_config( + BatchConfigBuilder::default() + // the default values for `max_export_batch_size` is set to 512, which we will fill + // pretty quickly, which will then result in an export. We want to make sure that + // the export is only done once the schedule is met and not as soon as 512 spans + // are collected. + .with_max_export_batch_size(4096) + // analog to default config `max_export_batch_size * 4` + .with_max_queue_size(4096 * 4) + // only force an export to the otlp collector every 10 seconds to reduce the amount + // of error messages if an otlp collector is not available + .with_scheduled_delay(std::time::Duration::from_secs(10)) + .build(), + ) + .with_trace_config(opentelemetry_sdk::trace::Config::default().with_resource({ + // use SdkProvidedResourceDetector.detect to detect resources, + // but replace the default service name with our default. + // https://github.com/open-telemetry/opentelemetry-rust/issues/1298 + let resources = SdkProvidedResourceDetector.detect(std::time::Duration::from_secs(0)); + // SdkProvidedResourceDetector currently always sets + // `service.name`, but we don't like its default. + if resources.get("service.name".into()).unwrap() == "unknown_service".into() { + resources.merge(&Resource::new([KeyValue::new( + "service.name", + service_name, + )])) + } else { + resources + } + })) + .install_batch(opentelemetry_sdk::runtime::Tokio) + .expect("Failed to install batch exporter using Tokio"); + + // Trace provider is need for later use like flushing the provider. + // Needs to be kept around for each message to rx we need to handle. + let tracer = tracer_provider.tracer("tvix"); + + // Set up a channel for flushing trace providers later + let (tx, mut rx) = mpsc::channel::<Option<oneshot::Sender<()>>>(16); + + // Spawning a task that listens on rx for any message. Once we receive a message we + // correctly call flush on the tracer_provider. + tokio::spawn(async move { + while let Some(m) = rx.recv().await { + // Because of a bug within otlp we currently have to use spawn_blocking + // otherwise will calling `force_flush` block forever, especially if the + // tool was closed with ctrl_c. See + // https://github.com/open-telemetry/opentelemetry-rust/issues/1395#issuecomment-1953280335 + let _ = tokio::task::spawn_blocking({ + let tracer_provider = tracer_provider.clone(); + move || tracer_provider.force_flush() + }) + .await; + if let Some(tx) = m { + let _ = tx.send(()); + } + } + }); + + (tracer, tx) +} diff --git a/tvix/tracing/src/propagate/axum.rs b/tvix/tracing/src/propagate/axum.rs new file mode 100644 index 000000000000..6d012f449762 --- /dev/null +++ b/tvix/tracing/src/propagate/axum.rs @@ -0,0 +1,48 @@ +#[cfg(feature = "otlp")] +use opentelemetry::{global, propagation::Extractor}; +#[cfg(feature = "otlp")] +use tracing_opentelemetry::OpenTelemetrySpanExt; + +// TODO: accept_trace can be shared with tonic, as soon as tonic upstream has a release with +// support for axum07. Latest master already has support for axum07 but there is not release yet: +// https://github.com/hyperium/tonic/pull/1740 + +/// Trace context propagation: associate the current span with the otlp trace of the given request, +/// if any and valid. This only sets the parent trace if the otlp feature is also enabled. +pub fn accept_trace<B>(request: axum::http::Request<B>) -> axum::http::Request<B> { + // we only extract and set a parent trace if otlp feature is enabled, otherwise this feature is + // an noop and we return the request as is + #[cfg(feature = "otlp")] + { + // Current context, if no or invalid data is received. + let parent_context = global::get_text_map_propagator(|propagator| { + propagator.extract(&HeaderExtractor(request.headers())) + }); + tracing::Span::current().set_parent(parent_context); + } + request +} + +/// Helper for extracting headers from HTTP Requests. This is used for OpenTelemetry context +/// propagation over HTTP. +#[cfg(feature = "otlp")] +struct HeaderExtractor<'a>(&'a axum::http::HeaderMap); + +#[cfg(feature = "otlp")] +impl<'a> Extractor for HeaderExtractor<'a> { + /// Get a value for a key from the HeaderMap. If the value is not valid ASCII, returns None. + fn get(&self, key: &str) -> Option<&str> { + self.0.get(key).and_then(|v| { + let s = v.to_str(); + if let Err(ref error) = s { + tracing::warn!(%error, ?v, "cannot convert header value to ASCII") + }; + s.ok() + }) + } + + /// Collect all the keys from the HeaderMap. + fn keys(&self) -> Vec<&str> { + self.0.keys().map(|k| k.as_str()).collect() + } +} diff --git a/tvix/tracing/src/propagate/mod.rs b/tvix/tracing/src/propagate/mod.rs new file mode 100644 index 000000000000..2e56a832e5b7 --- /dev/null +++ b/tvix/tracing/src/propagate/mod.rs @@ -0,0 +1,8 @@ +#[cfg(feature = "tonic")] +pub mod tonic; + +#[cfg(feature = "reqwest")] +pub mod reqwest; + +#[cfg(feature = "axum")] +pub mod axum; diff --git a/tvix/tracing/src/propagate/reqwest.rs b/tvix/tracing/src/propagate/reqwest.rs new file mode 100644 index 000000000000..e2afb3e948c7 --- /dev/null +++ b/tvix/tracing/src/propagate/reqwest.rs @@ -0,0 +1,13 @@ +use reqwest_tracing::{SpanBackendWithUrl, TracingMiddleware}; + +/// Returns a new tracing middleware which can be used with reqwest_middleware. +/// It will then write the `traceparent` in the header on the request and additionally records the +/// `url` into `http.url`. +/// +/// If otlp feature is disabled, this will not insert a `traceparent` into the header. It will +/// basically function as a noop. +/// +/// `traceparent` => https://www.w3.org/TR/trace-context/#trace-context-http-headers-format +pub fn tracing_middleware() -> TracingMiddleware<SpanBackendWithUrl> { + TracingMiddleware::<SpanBackendWithUrl>::new() +} diff --git a/tvix/tracing/src/propagate/tonic.rs b/tvix/tracing/src/propagate/tonic.rs new file mode 100644 index 000000000000..75455c056617 --- /dev/null +++ b/tvix/tracing/src/propagate/tonic.rs @@ -0,0 +1,57 @@ +#[cfg(feature = "otlp")] +use opentelemetry::{global, propagation::Injector}; +#[cfg(feature = "otlp")] +use opentelemetry_http::HeaderExtractor; +#[cfg(feature = "otlp")] +use tracing_opentelemetry::OpenTelemetrySpanExt; + +/// Trace context propagation: associate the current span with the otlp trace of the given request, +/// if any and valid. This only sets the parent trace if the otlp feature is also enabled. +pub fn accept_trace<B>(request: http::Request<B>) -> http::Request<B> { + // we only extract and set a parent trace if otlp feature is enabled, otherwise this feature is + // an noop and we return the request as is + #[cfg(feature = "otlp")] + { + // Current context, if no or invalid data is received. + let parent_context = global::get_text_map_propagator(|propagator| { + propagator.extract(&HeaderExtractor(request.headers())) + }); + tracing::Span::current().set_parent(parent_context); + } + request +} + +#[cfg(feature = "otlp")] +struct MetadataInjector<'a>(&'a mut tonic::metadata::MetadataMap); + +#[cfg(feature = "otlp")] +impl Injector for MetadataInjector<'_> { + fn set(&mut self, key: &str, value: String) { + use tonic::metadata::{MetadataKey, MetadataValue}; + use tracing::warn; + + match MetadataKey::from_bytes(key.as_bytes()) { + Ok(key) => match MetadataValue::try_from(&value) { + Ok(value) => { + self.0.insert(key, value); + } + Err(error) => warn!(value, error = format!("{error:#}"), "parse metadata value"), + }, + Err(error) => warn!(key, error = format!("{error:#}"), "parse metadata key"), + } + } +} + +/// Trace context propagation: send the trace context by injecting it into the metadata of the given +/// request. This only injects the current span if the otlp feature is also enabled. +#[allow(unused_mut)] +pub fn send_trace<T>(mut request: tonic::Request<T>) -> Result<tonic::Request<T>, tonic::Status> { + #[cfg(feature = "otlp")] + { + global::get_text_map_propagator(|propagator| { + let context = tracing::Span::current().context(); + propagator.inject_context(&context, &mut MetadataInjector(request.metadata_mut())) + }); + } + Ok(request) +} diff --git a/tvix/utils.nix b/tvix/utils.nix new file mode 100644 index 000000000000..f140728cad19 --- /dev/null +++ b/tvix/utils.nix @@ -0,0 +1,161 @@ +{ pkgs, lib, depot, ... }: + +{ + mkFeaturePowerset = { crateName, features, override ? { } }: + let + powerset = xs: + let + addElement = set: element: + set ++ map (e: [ element ] ++ e) set; + in + lib.foldl' addElement [ [ ] ] xs; + in + lib.listToAttrs (map + (featuresPowerset: { + name = if featuresPowerset != [ ] then "with-features-${lib.concatStringsSep "-" featuresPowerset}" else "no-features"; + value = depot.tvix.crates.workspaceMembers.${crateName}.build.override (old: { + runTests = true; + features = featuresPowerset; + } // (if lib.isFunction override then override old else override) + ); + }) + (powerset features)); + + # Filters the given source, only keeping files related to the build, preventing unnecessary rebuilds. + # Includes src in the root, all other .rs files and optionally Cargo specific files. + # Additional files to be included can be specified in extraFileset. + filterRustCrateSrc = + { root # The original src + , extraFileset ? null # Additional filesets to include (e.g. fileFilter for proto files) + , cargoSupport ? false + }: + lib.fileset.toSource { + inherit root; + fileset = lib.fileset.intersection + (lib.fileset.fromSource root) # We build our final fileset from the original src + (lib.fileset.unions ([ + (lib.fileset.maybeMissing (root + "/src")) # src may be missing if the crate just has tests for example + (lib.fileset.fileFilter (f: f.hasExt "rs") root) + ] ++ lib.optionals cargoSupport [ + (lib.fileset.fileFilter (f: f.name == "Cargo.toml") root) + (lib.fileset.maybeMissing (root + "/Cargo.lock")) + ] ++ lib.optional (extraFileset != null) extraFileset)); + }; + + # A function which takes a pkgs instance and returns an overriden defaultCrateOverrides with support for tvix crates. + # This can be used throughout the rest of the repo. + defaultCrateOverridesForPkgs = pkgs: + let + commonDarwinDeps = with pkgs.darwin.apple_sdk.frameworks; [ + Security + SystemConfiguration + ]; + in + pkgs.defaultCrateOverrides // { + nar-bridge = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + + nix-compat = prev: { + src = depot.tvix.utils.filterRustCrateSrc rec { + root = prev.src.origSrc; + extraFileset = root + "/testdata"; + }; + }; + + nix-compat-derive = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + + nix-compat-derive-tests = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + + tvix-build = prev: { + src = depot.tvix.utils.filterRustCrateSrc rec { + root = prev.src.origSrc; + extraFileset = lib.fileset.fileFilter (f: f.hasExt "proto") root; + }; + PROTO_ROOT = depot.tvix.build.protos.protos; + nativeBuildInputs = [ pkgs.protobuf ]; + buildInputs = lib.optional pkgs.stdenv.isDarwin commonDarwinDeps; + TVIX_BUILD_SANDBOX_SHELL = if pkgs.stdenv.isLinux then pkgs.pkgsStatic.busybox + "/bin/sh" else "/bin/sh"; + }; + + tvix-castore = prev: { + src = depot.tvix.utils.filterRustCrateSrc rec { + root = prev.src.origSrc; + extraFileset = lib.fileset.fileFilter (f: f.hasExt "proto") root; + }; + PROTO_ROOT = depot.tvix.castore.protos.protos; + nativeBuildInputs = [ pkgs.protobuf ]; + }; + + tvix-cli = prev: { + src = depot.tvix.utils.filterRustCrateSrc rec { + root = prev.src.origSrc; + extraFileset = root + "/tests"; + }; + buildInputs = lib.optional pkgs.stdenv.isDarwin commonDarwinDeps; + }; + + tvix-store = prev: { + src = depot.tvix.utils.filterRustCrateSrc rec { + root = prev.src.origSrc; + extraFileset = lib.fileset.fileFilter (f: f.hasExt "proto") root; + }; + PROTO_ROOT = depot.tvix.store.protos.protos; + nativeBuildInputs = [ pkgs.protobuf ]; + # fuse-backend-rs uses DiskArbitration framework to handle mount/unmount on Darwin + buildInputs = lib.optional pkgs.stdenv.isDarwin (commonDarwinDeps ++ pkgs.darwin.apple_sdk.frameworks.DiskArbitration); + }; + + tvix-eval-builtin-macros = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + + tvix-eval = prev: { + src = depot.tvix.utils.filterRustCrateSrc rec { + root = prev.src.origSrc; + extraFileset = root + "/proptest-regressions"; + }; + }; + + tvix-glue = prev: { + src = depot.tvix.utils.filterRustCrateSrc { + root = prev.src.origSrc; + }; + }; + + tvix-serde = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + + tvix-tracing = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + }; + + # This creates an extraStep in CI to check whether the Cargo.nix file is up-to-date. + mkCrate2nixCheck = + path: # The path to the Cargo.nix to be checked. + let + relCrateRoot = lib.removePrefix "./" (builtins.dirOf (lib.path.removePrefix depot.path.origSrc path)); + in + { + label = "crate2nix check for ${relCrateRoot}"; + needsOutput = true; + alwaysRun = true; + command = pkgs.writeShellScript "crate2nix-check-for-${lib.replaceStrings [ "/" ] ["-"] relCrateRoot}" '' + (cd $(git rev-parse --show-toplevel)/${relCrateRoot} && + ${depot.tools.crate2nix-generate}/bin/crate2nix-generate && + if [[ -n "$(git status --porcelain -unormal Cargo.nix)" ]]; then + echo "----------------------------------------------------------------------------------------------------" + echo "Cargo.nix needs to be updated, run 'mg run //tools/crate2nix-generate' in ${relCrateRoot}" + echo "----------------------------------------------------------------------------------------------------" + exit 1 + fi + ) + ''; + }; +} diff --git a/tvix/verify-lang-tests/default.nix b/tvix/verify-lang-tests/default.nix index 772c1c532078..e6de1c1f455c 100644 --- a/tvix/verify-lang-tests/default.nix +++ b/tvix/verify-lang-tests/default.nix @@ -9,7 +9,9 @@ let testRoot = ../eval/src/tests; - inherit (pkgs.buildPackages) nix nix_latest; + inherit (pkgs.nixVersions) nix_2_3; + # The latest Nix version we've verified to work for our testing suite. + nix_latest_verified = pkgs.nixVersions.nix_2_24; parseTest = dir: baseName: let @@ -44,50 +46,54 @@ let # C++ Nix can't TCO "eval-okay-tail-call-1.nix" = true; # Ordering change after 2.3 - "eval-okay-xml.nix" = [ nix ]; + "eval-okay-xml.nix" = [ nix_2_3 ]; # Missing builtins in Nix 2.3 - "eval-okay-ceil.nix" = [ nix ]; - "eval-okay-floor-ceil.nix" = [ nix ]; - "eval-okay-floor.nix" = [ nix ]; - "eval-okay-groupBy.nix" = [ nix ]; - "eval-okay-zipAttrsWith.nix" = [ nix ]; - "eval-okay-builtins-group-by-propagate-catchable.nix" = [ nix ]; + "eval-okay-ceil.nix" = [ nix_2_3 ]; + "eval-okay-floor-ceil.nix" = [ nix_2_3 ]; + "eval-okay-floor.nix" = [ nix_2_3 ]; + "eval-okay-groupBy.nix" = [ nix_2_3 ]; + "eval-okay-zipAttrsWith.nix" = [ nix_2_3 ]; + "eval-okay-builtins-group-by-propagate-catchable.nix" = [ nix_2_3 ]; # Comparable lists are not in Nix 2.3 - "eval-okay-sort.nix" = [ nix ]; - "eval-okay-compare-lists.nix" = [ nix ]; - "eval-okay-value-pointer-compare.nix" = [ nix ]; - "eval-okay-builtins-genericClosure-pointer-equality.nix" = [ nix ]; - "eval-okay-list-comparison.nix" = [ nix ]; + "eval-okay-sort.nix" = [ nix_2_3 ]; + "eval-okay-compare-lists.nix" = [ nix_2_3 ]; + "eval-okay-value-pointer-compare.nix" = [ nix_2_3 ]; + "eval-okay-builtins-genericClosure-pointer-equality.nix" = [ nix_2_3 ]; + "eval-okay-list-comparison.nix" = [ nix_2_3 ]; # getAttrPos gains support for functionArgs-returned sets after 2.3 - "eval-okay-getattrpos-functionargs.nix" = [ nix ]; + "eval-okay-getattrpos-functionargs.nix" = [ nix_2_3 ]; # groupBy appeared (long) after 2.3 - "eval-okay-builtins-groupby-thunk.nix" = [ nix ]; + "eval-okay-builtins-groupby-thunk.nix" = [ nix_2_3 ]; # import is no longer considered a curried primop in Nix > 2.3 - "eval-okay-import-display.nix" = [ nix ]; + "eval-okay-import-display.nix" = [ nix_2_3 ]; # Cycle detection and formatting changed sometime after Nix 2.3 - "eval-okay-cycle-display-cpp-nix-2.13.nix" = [ nix ]; + "eval-okay-cycle-display-cpp-nix-2.13.nix" = [ nix_2_3 ]; # builtins.replaceStrings becomes lazier in Nix 2.16 - "eval-okay-replacestrings.nix" = [ nix ]; - # builtins.readFileType is added in Nix 2.15 - "eval-okay-readFileType.nix" = [ nix ]; + "eval-okay-replacestrings.nix" = [ nix_2_3 ]; + # builtins.readFileType is added in Nix 2.14 + "eval-okay-readFileType.nix" = [ nix_2_3 ]; # builtins.fromTOML gains support for timestamps in Nix 2.16 - "eval-okay-fromTOML-timestamps.nix" = [ nix ]; + "eval-okay-fromTOML-timestamps.nix" = [ nix_2_3 ]; # identifier formatting changed in Nix 2.17 due to cppnix commit # b72bc4a972fe568744d98b89d63adcd504cb586c - "eval-okay-identifier-formatting.nix" = [ nix ]; + "eval-okay-identifier-formatting.nix" = [ nix_2_3 ]; # Differing strictness in the function argument for some builtins in Nix 2.18 # https://github.com/NixOS/nix/issues/9779 - "eval-okay-builtins-map-propagate-catchable.nix" = [ nix_latest ]; - "eval-okay-builtins-gen-list-propagate-catchable.nix" = [ nix_latest ]; + "eval-okay-builtins-map-propagate-catchable.nix" = [ nix_latest_verified ]; + "eval-okay-builtins-gen-list-propagate-catchable.nix" = [ nix_latest_verified ]; "eval-okay-builtins-replace-strings-propagate-catchable.nix" = - [ nix_latest ]; - "eval-okay-builtins-map-function-strictness.nix" = [ nix_latest ]; - "eval-okay-builtins-genList-function-strictness.nix" = [ nix_latest ]; + [ nix_latest_verified ]; + "eval-okay-builtins-map-function-strictness.nix" = [ nix_latest_verified ]; + "eval-okay-builtins-genList-function-strictness.nix" = [ nix_latest_verified ]; # TODO(sterni): support diffing working directory and home relative paths # like C++ Nix test suite (using string replacement). "eval-okay-path-antiquotation.nix" = true; + + # The output of dirOf (and maybe other filesystem builtins) have changed in Nix 2.23 + # when they switched to using std::filesystem, https://github.com/NixOS/nix/pull/10658. + "eval-okay-dirof.nix" = [ nix_latest_verified ]; }; runCppNixLangTests = cpp-nix: @@ -219,8 +225,11 @@ let }; in - depot.nix.readTree.drvTargets { - "nix-2.3" = runCppNixLangTests nix; - "nix-${lib.versions.majorMinor nix_latest.version}" = runCppNixLangTests nix_latest; + "nix-${lib.versions.majorMinor nix_2_3.version}" = runCppNixLangTests nix_2_3; + "nix-${lib.versions.majorMinor nix_latest_verified.version}" = lib.warnIf (lib.versionOlder nix_latest_verified.version pkgs.nixVersions.latest.version) + "The latest verified Nix version is out of date, consider updating the value of `nix_latest_verified` and verifying that the tests still pass." + runCppNixLangTests + nix_latest_verified; } + diff --git a/tvix/website/landing-en.md b/tvix/website/landing-en.md index 61a011dee93e..f677f20f2fff 100644 --- a/tvix/website/landing-en.md +++ b/tvix/website/landing-en.md @@ -15,7 +15,7 @@ There are several projects within Tvix, such as: * `//tvix/castore` - subtree storage/transfer in a content-addressed fashion * `//tvix/cli` - preliminary REPL & CLI implementation for Tvix * `//tvix/eval` - an implementation of the Nix programming language -* `//tvix/nar-bridge` - a HTTP webserver providing a Nix HTTP Binary Cache interface in front of a tvix-store +* `//tvix/nar-bridge[-go]` - a HTTP webserver providing a Nix HTTP Binary Cache interface in front of a tvix-store * `//tvix/nix-compat` - a Rust library for compatibility with C++ Nix, features like encodings and hashing schemes and formats * `//tvix/serde` - a Rust library for using the Nix language for app configuration * `//tvix/store` - a "filesystem" linking Nix store paths and metadata with the content-addressed layer diff --git a/users/Profpatsch/.gitignore b/users/Profpatsch/.gitignore index c33954f53a06..b13922700be1 100644 --- a/users/Profpatsch/.gitignore +++ b/users/Profpatsch/.gitignore @@ -1 +1,6 @@ dist-newstyle/ +result-* + +/node-modules/ +# ignore all package-locks (for now?) +package-lock.json diff --git a/users/Profpatsch/.hlint.yaml b/users/Profpatsch/.hlint.yaml index f00f78c5259d..12b7c61b7094 100644 --- a/users/Profpatsch/.hlint.yaml +++ b/users/Profpatsch/.hlint.yaml @@ -34,6 +34,8 @@ - ignore: { name: Use tuple-section } - ignore: { name: Use forM_ } - ignore: { name: Functor law } +- ignore: { name: Use maybe } + # fst and snd are usually a code smell and should be explicit matches, _naming the ignored side. - ignore: { name: Use fst } - ignore: { name: Use snd } diff --git a/users/Profpatsch/.prettierrc b/users/Profpatsch/.prettierrc new file mode 100644 index 000000000000..e97f84abaf62 --- /dev/null +++ b/users/Profpatsch/.prettierrc @@ -0,0 +1,8 @@ +{ + "trailingComma": "all", + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "printWidth": 90, + "arrowParens": "avoid" +} diff --git a/users/Profpatsch/.vscode/launch.json b/users/Profpatsch/.vscode/launch.json index baa087d437d1..dca6a4dc617c 100644 --- a/users/Profpatsch/.vscode/launch.json +++ b/users/Profpatsch/.vscode/launch.json @@ -5,6 +5,15 @@ "version": "0.2.0", "configurations": [ { + "name": "node: Attach to running process", + "port": 9229, + "request": "attach", + "skipFiles": [ + "<node_internals>/**" + ], + "type": "node" + }, + { "name": "run declib", "type": "node", "cwd": "${workspaceFolder}/declib", @@ -13,6 +22,32 @@ "runtimeArgs": [ "run", ], + }, + { + "type": "node", + "name": "Run tap-bpm", + "skipFiles": [ + "<node_internals>/**" + ], + "request": "launch", + "program": "${workspaceFolder}/lyric/dist/index.js", + "preLaunchTask": "ninja build lyric", + "outFiles": [ + "${workspaceFolder}/lyric/dist/**/*.js" + ], + "args": [ + "tap-bpm" + ] + }, + { + "preLaunchTask": "npm build lyric extension", + "name": "Launch lyric vscode Extension", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}/lyric/extension", + "${workspaceFolder}/lyric/extension" + ] } ] } diff --git a/users/Profpatsch/README.md b/users/Profpatsch/README.md index 5bb74cd7580f..0f2147e9afc1 100644 --- a/users/Profpatsch/README.md +++ b/users/Profpatsch/README.md @@ -2,7 +2,7 @@ Welcome, Welcome. -Welcome to my user dir, where we optimize f*** around, in order to optimize finding out. +Welcome to my user dir, where we optimize f\*\*\*ing around, in order to optimize finding out. ![fafo graph](./fafo.jpg) diff --git a/users/Profpatsch/advent-of-code/2020/01/main.py b/users/Profpatsch/advent-of-code/2020/01/main.py deleted file mode 100644 index e636017a54d5..000000000000 --- a/users/Profpatsch/advent-of-code/2020/01/main.py +++ /dev/null @@ -1,22 +0,0 @@ -import sys - -l = [] -with open('./input', 'r') as f: - for line in f: - l.append(int(line)) - -s = set(l) - -res=None -for el in s: - for el2 in s: - if (2020-(el+el2)) in s: - res=(el, el2, 2020-(el+el2)) - break - -if res == None: - sys.exit("could not find a number that adds to 2020") - -print(res) - -print(res[0] * res[1] * res[2]) diff --git a/users/Profpatsch/advent-of-code/2020/02/main.py b/users/Profpatsch/advent-of-code/2020/02/main.py deleted file mode 100644 index e3b27c382a21..000000000000 --- a/users/Profpatsch/advent-of-code/2020/02/main.py +++ /dev/null @@ -1,77 +0,0 @@ -import sys - -def parse(line): - a = line.split(sep=" ", maxsplit=1) - assert len(a) == 2 - fromto = a[0].split(sep="-") - assert len(fromto) == 2 - (from_, to) = (int(fromto[0]), int(fromto[1])) - charpass = a[1].split(sep=": ") - assert len(charpass) == 2 - char = charpass[0] - assert len(char) == 1 - pass_ = charpass[1] - assert pass_.endswith("\n") - pass_ = pass_[:-1] - return { - "from": from_, - "to": to, - "char": char, - "pass": pass_ - } - -def char_in_pass(char, pass_): - return pass_.count(char) - -def validate_01(entry): - no = char_in_pass(entry["char"], entry["pass"]) - if no < entry["from"]: - return { "too-small": entry } - elif no > entry["to"]: - return { "too-big": entry } - else: - return { "ok": entry } - -def char_at_pos(char, pos, pass_): - assert pos <= len(pass_) - return pass_[pos-1] == char - -def validate_02(entry): - one = char_at_pos(entry["char"], entry["from"], entry["pass"]) - two = char_at_pos(entry["char"], entry["to"], entry["pass"]) - if one and two: - return { "both": entry } - elif one: - return { "one": entry } - elif two: - return { "two": entry } - else: - return { "none": entry } - - -res01 = [] -res02 = [] -with open("./input", 'r') as f: - for line in f: - p = parse(line) - res01.append(validate_01(p)) - res02.append(validate_02(p)) - -count01=0 -for r in res01: - print(r) - if r.get("ok", False): - count01=count01+1 - -count02=0 -for r in res02: - print(r) - if r.get("one", False): - count02=count02+1 - elif r.get("two", False): - count02=count02+1 - else: - pass - -print("count 1: {}".format(count01)) -print("count 2: {}".format(count02)) diff --git a/users/Profpatsch/advent-of-code/2020/03/main.py b/users/Profpatsch/advent-of-code/2020/03/main.py deleted file mode 100644 index 4d6baf946c3e..000000000000 --- a/users/Profpatsch/advent-of-code/2020/03/main.py +++ /dev/null @@ -1,66 +0,0 @@ -import itertools -import math - -def tree_line(init): - return { - "init-len": len(init), - "known": '', - "rest": itertools.repeat(init) - } - -def tree_line_at(pos, tree_line): - needed = (pos + 1) - len(tree_line["known"]) - # internally advance the tree line to the position requested - if needed > 0: - tree_line["known"] = tree_line["known"] \ - + ''.join( - itertools.islice( - tree_line["rest"], - 1+math.floor(needed / tree_line["init-len"]))) - # print(tree_line) - return tree_line["known"][pos] == '#' - -def tree_at(linepos, pos, trees): - return tree_line_at(pos, trees[linepos]) - -def slope_positions(trees, right, down): - line = 0 - pos = 0 - while line < len(trees): - yield (line, pos) - line = line + down - pos = pos + right - -trees = [] -with open("./input", 'r') as f: - for line in f: - line = line.rstrip() - trees.append(tree_line(line)) - -# print(list(itertools.islice(trees[0], 5))) -# print(list(map( -# lambda x: tree_at(0, x, trees), -# range(100) -# ))) -# print(list(slope_positions(trees, right=3, down=1))) - -def count_slope_positions(trees, slope): - count = 0 - for (line, pos) in slope: - if tree_at(line, pos, trees): - count = count + 1 - return count - -print( - count_slope_positions(trees, slope_positions(trees, right=1, down=1)) - * - count_slope_positions(trees, slope_positions(trees, right=3, down=1)) - * - count_slope_positions(trees, slope_positions(trees, right=5, down=1)) - * - count_slope_positions(trees, slope_positions(trees, right=7, down=1)) - * - count_slope_positions(trees, slope_positions(trees, right=1, down=2)) -) - -# I realized I could have just used a modulo instead … diff --git a/users/Profpatsch/advent-of-code/2020/04/main.py b/users/Profpatsch/advent-of-code/2020/04/main.py deleted file mode 100644 index 36bbed7146d6..000000000000 --- a/users/Profpatsch/advent-of-code/2020/04/main.py +++ /dev/null @@ -1,104 +0,0 @@ -import sys -import itertools -import re -import pprint - -def get_entry(fd): - def to_dict(keyval): - res = {} - for (k, v) in keyval: - assert k not in res - res[k] = v - return res - - res = [] - for line in fd: - if line == "\n": - yield to_dict(res) - res = [] - else: - line = line.rstrip() - items = line.split(" ") - for i in items: - res.append(i.split(":", maxsplit=2)) - -def val_hgt(hgt): - m = re.fullmatch(r'([0-9]+)(cm|in)', hgt) - if m: - (i, what) = m.group(1,2) - i = int(i) - if what == "cm": - return i >= 150 and i <= 193 - elif what == "in": - return i >= 59 and i <= 76 - else: - return False - -required_fields = [ - { "name": "byr", - "check": lambda s: int(s) >= 1920 and int(s) <= 2002 - }, - { "name": "iyr", - "check": lambda s: int(s) >= 2010 and int(s) <= 2020 - }, - { "name": "eyr", - "check": lambda s: int(s) >= 2020 and int(s) <= 2030, - }, - { "name": "hgt", - "check": lambda s: val_hgt(s) - }, - { "name": "hcl", - "check": lambda s: re.fullmatch(r'#[0-9a-f]{6}', s) - }, - { "name": "ecl", - "check": lambda s: re.fullmatch(r'amb|blu|brn|gry|grn|hzl|oth', s) - }, - { "name": "pid", - "check": lambda s: re.fullmatch(r'[0-9]{9}', s) - }, - # we should treat it as not required - # "cid" -] - -required_dict = {} -for f in required_fields: - required_dict[f["name"]] = f - -def validate(keyval): - if keyval[0] not in required_dict: - return { "ok": keyval } - if required_dict[keyval[0]]["check"](keyval[1]): - return { "ok": keyval } - else: - return { "validation": keyval } - -def all_fields(entry): - missing = [] - for r in required_dict: - if r not in e: - missing.append(r) - if missing == []: - return { "ok": entry } - else: - return { "missing": missing } - -count=0 -for e in get_entry(sys.stdin): - a = all_fields(e) - if a.get("ok", False): - res = {} - bad = False - for keyval in e.items(): - r = validate(keyval) - if r.get("validation", False): - bad = True - res[keyval[0]] = r - if bad: - pprint.pprint({ "validation": res }) - else: - pprint.pprint({ "ok": e }) - count = count+1 - else: - pprint.pprint(a) - -print(count) diff --git a/users/Profpatsch/cabal.project b/users/Profpatsch/cabal.project index 26b618696923..aa8df174ac9b 100644 --- a/users/Profpatsch/cabal.project +++ b/users/Profpatsch/cabal.project @@ -5,7 +5,6 @@ packages: ./arglib/arglib-netencode.cabal ./execline/exec-helpers.cabal ./htmx-experiment/htmx-experiment.cabal - ./mailbox-org/mailbox-org.cabal ./cas-serve/cas-serve.cabal ./jbovlaste-sqlite/jbovlaste-sqlite.cabal ./whatcd-resolver/whatcd-resolver.cabal diff --git a/users/Profpatsch/eslint.config.mjs b/users/Profpatsch/eslint.config.mjs new file mode 100644 index 000000000000..0f6d19723794 --- /dev/null +++ b/users/Profpatsch/eslint.config.mjs @@ -0,0 +1,80 @@ +import tseslint from 'typescript-eslint'; +import tsplugin from '@typescript-eslint/eslint-plugin'; +import parser from '@typescript-eslint/parser'; + +let recommended = { ...tseslint.configs.eslintRecommended }; + +let set = tseslint.config(recommended, { + languageOptions: { + parser: parser, + parserOptions: { + projectService: true, + }, + }, + plugins: { '@typescript-eslint': tsplugin }, + rules: { + 'prettier/prettier': 'off', + 'prefer-const': 'warn', + '@typescript-eslint/ban-ts-comment': 'warn', + 'no-array-constructor': 'off', + '@typescript-eslint/no-array-constructor': 'warn', + '@typescript-eslint/no-duplicate-enum-values': 'warn', + '@typescript-eslint/no-empty-object-type': 'warn', + '@typescript-eslint/no-explicit-any': 'warn', + '@typescript-eslint/no-extra-non-null-assertion': 'warn', + '@typescript-eslint/no-misused-new': 'warn', + '@typescript-eslint/no-namespace': 'warn', + '@typescript-eslint/no-non-null-asserted-optional-chain': 'warn', + '@typescript-eslint/no-require-imports': 'warn', + '@typescript-eslint/no-this-alias': 'warn', + '@typescript-eslint/no-unnecessary-type-constraint': 'warn', + '@typescript-eslint/no-unsafe-declaration-merging': 'warn', + '@typescript-eslint/no-unsafe-function-type': 'warn', + '@typescript-eslint/strict-boolean-expressions': ['warn'], + 'no-unused-expressions': 'off', + '@typescript-eslint/no-unused-expressions': 'warn', + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], + '@typescript-eslint/no-wrapper-object-types': 'warn', + '@typescript-eslint/prefer-as-const': 'warn', + '@typescript-eslint/prefer-namespace-keyword': 'warn', + '@typescript-eslint/triple-slash-reference': 'warn', + + '@typescript-eslint/await-thenable': 'warn', + 'no-array-constructor': 'off', + '@typescript-eslint/no-array-delete': 'warn', + '@typescript-eslint/no-base-to-string': 'warn', + '@typescript-eslint/no-duplicate-type-constituents': 'warn', + '@typescript-eslint/no-floating-promises': 'warn', + '@typescript-eslint/no-for-in-array': 'warn', + 'no-implied-eval': 'off', + '@typescript-eslint/no-implied-eval': 'warn', + '@typescript-eslint/no-misused-promises': 'warn', + '@typescript-eslint/no-redundant-type-constituents': 'warn', + '@typescript-eslint/no-unnecessary-type-assertion': 'warn', + '@typescript-eslint/no-unsafe-argument': 'warn', + '@typescript-eslint/no-unsafe-assignment': 'warn', + '@typescript-eslint/no-unsafe-call': 'warn', + '@typescript-eslint/no-unsafe-enum-comparison': 'warn', + '@typescript-eslint/no-unsafe-member-access': 'warn', + '@typescript-eslint/no-unsafe-return': 'warn', + '@typescript-eslint/no-unsafe-unary-minus': 'warn', + 'no-throw-literal': 'off', + '@typescript-eslint/only-throw-error': 'warn', + 'prefer-promise-reject-errors': 'off', + '@typescript-eslint/prefer-promise-reject-errors': 'warn', + 'require-await': 'off', + '@typescript-eslint/require-await': 'warn', + '@typescript-eslint/restrict-plus-operands': 'warn', + '@typescript-eslint/restrict-template-expressions': 'warn', + '@typescript-eslint/unbound-method': 'warn', + }, +}); + +// override files for each set +const files = ['src/**/*.ts', 'src/**/*.tsx']; +for (let s of set) { + s.files = files; +} + +export default set; diff --git a/users/Profpatsch/git-db/default.nix b/users/Profpatsch/git-db/default.nix deleted file mode 100644 index ad5d927677bf..000000000000 --- a/users/Profpatsch/git-db/default.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ depot, pkgs, lib, ... }: - -depot.nix.writers.rustSimple -{ - name = "git-db"; - dependencies = [ - depot.third_party.rust-crates.git2 - ]; -} - (builtins.readFile ./git-db.rs) diff --git a/users/Profpatsch/git-db/git-db.rs b/users/Profpatsch/git-db/git-db.rs deleted file mode 100644 index c8019bf03661..000000000000 --- a/users/Profpatsch/git-db/git-db.rs +++ /dev/null @@ -1,90 +0,0 @@ -extern crate git2; -use std::os::unix::ffi::OsStrExt; -use std::path::PathBuf; - -const DEFAULT_BRANCH: &str = "refs/heads/main"; - -fn main() { - let git_db_dir = std::env::var_os("GIT_DB_DIR").expect("set GIT_DB_DIR"); - let git_db = PathBuf::from(git_db_dir).join("git"); - - std::fs::create_dir_all(&git_db).unwrap(); - - let repo = git2::Repository::init_opts( - &git_db, - git2::RepositoryInitOptions::new() - .bare(true) - .mkpath(true) - .description("git-db database") - .initial_head(DEFAULT_BRANCH), - ) - .expect(&format!( - "unable to create or open bare git repo at {}", - &git_db.display() - )); - - let mut index = repo.index().expect("cannot get the git index file"); - eprintln!("{:#?}", index.version()); - index.clear().expect("could not clean the index"); - - let now = std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .expect("unable to get system time"); - - let now_git_time = git2::IndexTime::new( - now.as_secs() as i32, // lol - u32::from(now.subsec_nanos()), - ); - - let data = "hi, it’s me".as_bytes(); - - index - .add_frombuffer( - &git2::IndexEntry { - mtime: now_git_time, - ctime: now_git_time, - // don’t make sense - dev: 0, - ino: 0, - mode: /*libc::S_ISREG*/ 0b1000 << (3+9) | /* read write for owner */ 0o644, - uid: 0, - gid: 0, - file_size: data.len() as u32, // lol again - id: git2::Oid::zero(), - flags: 0, - flags_extended: 0, - path: "hi.txt".as_bytes().to_owned(), - }, - data, - ) - .expect("could not add data to index"); - - let oid = index.write_tree().expect("could not write index tree"); - - let to_add_tree = repo - .find_tree(oid) - .expect("we just created this tree, where did it go?"); - - let parent_commits = match repo.find_reference(DEFAULT_BRANCH) { - Ok(ref_) => vec![ref_.peel_to_commit().expect(&format!( - "reference {} does not point to a commit", - DEFAULT_BRANCH - ))], - Err(err) => match err.code() { - // no commit exists yet - git2::ErrorCode::NotFound => vec![], - _ => panic!("could not read latest commit from {}", DEFAULT_BRANCH), - }, - }; - repo.commit( - Some(DEFAULT_BRANCH), - &git2::Signature::now("Mr. Authorboy", "author@example.com").unwrap(), - &git2::Signature::now("Mr. Commiterboy", "committer@example.com").unwrap(), - "This is my first commit!\n\ - \n\ - I wonder if it supports extended commit descriptions?\n", - &to_add_tree, - &parent_commits.iter().collect::<Vec<_>>()[..], - ) - .expect("could not commit the index we just wrote"); -} diff --git a/users/Profpatsch/hie.yaml b/users/Profpatsch/hie.yaml index 1b5ae942ad56..3b67e11b974a 100644 --- a/users/Profpatsch/hie.yaml +++ b/users/Profpatsch/hie.yaml @@ -14,10 +14,6 @@ cradle: component: "lib:htmx-experiment" - path: "./htmx-experiment/Main.hs" component: "htmx-experiment:exe:htmx-experiment" - - path: "./mailbox-org/src" - component: "lib:mailbox-org" - - path: "./mailbox-org/MailboxOrg.hs" - component: "mailbox-org:exe:mailbox-org" - path: "./cas-serve/CasServe.hs" component: "cas-serve:exe:cas-serve" - path: "./jbovlaste-sqlite/JbovlasteSqlite.hs" diff --git a/users/Profpatsch/ini/default.nix b/users/Profpatsch/ini/default.nix deleted file mode 100644 index e1a7a1a7b6b7..000000000000 --- a/users/Profpatsch/ini/default.nix +++ /dev/null @@ -1,6 +0,0 @@ -{ depot, ... }: -{ - externs = { - renderIni = depot.users.Profpatsch.toINI { }; - }; -} diff --git a/users/Profpatsch/ini/ini.dhall b/users/Profpatsch/ini/ini.dhall deleted file mode 100644 index f2efbc0af4f1..000000000000 --- a/users/Profpatsch/ini/ini.dhall +++ /dev/null @@ -1,36 +0,0 @@ -let lib = ../dhall/lib.dhall - -let NameVal = λ(T : Type) → { name : Text, value : T } - -let ValueList = λ(T : Type) → List (NameVal T) - -let Section = ValueList Text - -let Sections = ValueList Section - -let Ini = { globalSection : Section, sections : Sections } - -let - -- Takes to INI files and merges their global sections and their section lists, - -- without duplicating by section name. - appendInis = - λ(inis : List Ini) → - { globalSection = - lib.List/concat - (NameVal Text) - (lib.List/map Ini Section (λ(i : Ini) → i.globalSection) inis) - , sections = - lib.List/concat - (NameVal Section) - (lib.List/map Ini Sections (λ(i : Ini) → i.sections) inis) - } - : Ini - -let - -- Signatures of functions that are input via FFI. - Externs = - { -- given a dsl of functions to create an Ini, render the ini file - renderIni : Ini → Text - } - -in { NameVal, ValueList, Section, Sections, Ini, appendInis, Externs } diff --git a/users/Profpatsch/lyric/.gitignore b/users/Profpatsch/lyric/.gitignore new file mode 100644 index 000000000000..226235d62b9d --- /dev/null +++ b/users/Profpatsch/lyric/.gitignore @@ -0,0 +1,6 @@ +/dist/ +/.ninja/ +/node_modules/ + +# ignore for now +/package-lock.json diff --git a/users/Profpatsch/lyric/.prettierrc b/users/Profpatsch/lyric/.prettierrc new file mode 120000 index 000000000000..5b5fb8c8b256 --- /dev/null +++ b/users/Profpatsch/lyric/.prettierrc @@ -0,0 +1 @@ +../.prettierrc \ No newline at end of file diff --git a/users/Profpatsch/lyric/build.ninja b/users/Profpatsch/lyric/build.ninja new file mode 100644 index 000000000000..a5752bef5002 --- /dev/null +++ b/users/Profpatsch/lyric/build.ninja @@ -0,0 +1,17 @@ +builddir = .ninja + +outdir = ./dist +jsdir = $outdir/js + +rule tsc + command = node_modules/.bin/tsc + +build $outdir/index.js: tsc | src/index.ts tsconfig.json + +rule run + command = node $in + +build run: run $outdir/index.js + +build run-tap-bpm: run $outdir/index.js tap-bpm + pool = console diff --git a/users/Profpatsch/lyric/default.nix b/users/Profpatsch/lyric/default.nix new file mode 100644 index 000000000000..c20f28b18742 --- /dev/null +++ b/users/Profpatsch/lyric/default.nix @@ -0,0 +1,92 @@ +{ pkgs, depot, lib, ... }: + +let + bins = depot.nix.getBins pkgs.sqlite-utils [ "sqlite-utils" ] + // depot.nix.getBins pkgs.jq [ "jq" ]; + + mpv-script = pkgs.writeTextFile { + name = "lyric.lua"; + text = + lib.replaceStrings + [ "@get_subtitles_command@" ] + [ (toString lyric-to-temp-file) ] + (builtins.readFile ./lyric-mpv-script.lua); + derivationArgs.passthru.scriptName = "lyric.lua"; + }; + + lyric-to-temp-file = depot.nix.writeExecline "lyric-to-temp-file" { readNArgs = 1; } [ + "backtick" + "-E" + "cache" + [ depot.users.Profpatsch.xdg-cache-home ] + "if" + [ "mkdir" "-p" "\${cache}/lyric/as-files" ] + "if" + [ + "redirfd" + "-w" + "1" + "\${cache}/lyric/as-files/\${1}.lrc" + lyric + "$1" + ] + "printf" + "\${cache}/lyric/as-files/\${1}.lrc" + ]; + + # Display lyrics for the given search string; + # search string can contain a substring of band name, album name, song title + # + # Use the database dump from https://lrclib.net/db-dumps and place it in ~/.cache/lyric/lrclib-db-dump.sqlite3 + lyric = + + (depot.nix.writeExecline "lyric" { readNArgs = 1; } [ + "backtick" + "-E" + "cache" + [ depot.users.Profpatsch.xdg-cache-home ] + "pipeline" + [ + bins.sqlite-utils + "query" + "\${cache}/lyric/lrclib-db-dump.sqlite3" + '' + select + synced_lyrics, + has_synced_lyrics, + plain_lyrics + from + tracks_fts(:searchstring) tf + join tracks t on t.rowid = tf.rowid + join lyrics l on t.rowid = l.track_id + order by + has_synced_lyrics desc, t.id + limit + 1 + '' + "--param" + "searchstring" + "$1" + ] + bins.jq + "-r" + '' + if .[0] == null + then "" + else + .[0] + | if .has_synced_lyrics == 1 + then .synced_lyrics + else .plain_lyrics + end + end + '' + ]); + + +in +{ + inherit + lyric + mpv-script; +} diff --git a/users/Profpatsch/lyric/eslint.config.mjs b/users/Profpatsch/lyric/eslint.config.mjs new file mode 100644 index 000000000000..60ee4ab9b8c2 --- /dev/null +++ b/users/Profpatsch/lyric/eslint.config.mjs @@ -0,0 +1,3 @@ +import config from '../eslint.config.mjs'; + +export default config; diff --git a/users/Profpatsch/lyric/extension/.gitignore b/users/Profpatsch/lyric/extension/.gitignore new file mode 100644 index 000000000000..d2405ad640c3 --- /dev/null +++ b/users/Profpatsch/lyric/extension/.gitignore @@ -0,0 +1,5 @@ +/node_modules/ +/out/ + +# ignore for now +/package-lock.json diff --git a/users/Profpatsch/lyric/extension/.prettierrc b/users/Profpatsch/lyric/extension/.prettierrc new file mode 120000 index 000000000000..73b7c6b3dec9 --- /dev/null +++ b/users/Profpatsch/lyric/extension/.prettierrc @@ -0,0 +1 @@ +../../.prettierrc \ No newline at end of file diff --git a/users/Profpatsch/lyric/extension/LICENSE b/users/Profpatsch/lyric/extension/LICENSE new file mode 100644 index 000000000000..4292032e6223 --- /dev/null +++ b/users/Profpatsch/lyric/extension/LICENSE @@ -0,0 +1 @@ +same as toplevel diff --git a/users/Profpatsch/lyric/extension/eslint.config.mjs b/users/Profpatsch/lyric/extension/eslint.config.mjs new file mode 100644 index 000000000000..9d3eef2c30d8 --- /dev/null +++ b/users/Profpatsch/lyric/extension/eslint.config.mjs @@ -0,0 +1,3 @@ +import config from '../../eslint.config.mjs'; + +export default config; diff --git a/users/Profpatsch/lyric/extension/package.json b/users/Profpatsch/lyric/extension/package.json new file mode 100644 index 000000000000..73bf53e812fc --- /dev/null +++ b/users/Profpatsch/lyric/extension/package.json @@ -0,0 +1,87 @@ +{ + "name": "profpatsch-jump-to-lrc-position", + "displayName": "Jump to .lrc Position in mpv", + "description": "Reads a timestamp from the current file and pipes it to a mpv socket", + "version": "0.0.1", + "engines": { + "vscode": "^1.75.0" + }, + "categories": [ + "Other" + ], + "main": "./out/extension.js", + "activationEvents": [ + "onLanguage:lrc" + ], + "contributes": { + "commands": [ + { + "command": "extension.jumpToLrcPosition", + "title": "Jump to .lrc Position", + "category": "LRC" + }, + { + "command": "extension.shiftLyricsDown", + "title": "Shift Lyrics Down from Current Line", + "category": "LRC" + }, + { + "command": "extension.shiftLyricsUp", + "title": "Shift Lyrics Up from Current Line", + "category": "LRC" + }, + { + "command": "extension.tapBpm", + "title": "Add bpm header by tapping to the song", + "category": "LRC" + }, + { + "command": "extension.quantizeToEigthNote", + "title": "Quantize timestamps to nearest eighth note", + "category": "LRC" + }, + { + "command": "extension.fineTuneTimestampDown100MsAndPlay", + "title": "Remove 100 ms from current timestamp and play from shortly before the change", + "category": "LRC" + }, + { + "command": "extension.fineTuneTimestampUp100MsAndPlay", + "title": "Add 100 ms to current timestamp and play from shortly before the change", + "category": "LRC" + }, + { + "command": "extension.uploadLyricsToLrclibDotNet", + "title": "Upload Lyrics to lrclib.net", + "category": "LRC" + } + ], + "languages": [ + { + "id": "lrc", + "extensions": [ + ".lrc" + ], + "aliases": [ + "Lyric file" + ] + } + ] + }, + "scripts": { + "vscode:prepublish": "npm run compile", + "compile": "tsc", + "install-extension": "vsce package --allow-missing-repository --out ./jump-to-lrc-position.vsix && code --install-extension ./jump-to-lrc-position.vsix" + }, + "devDependencies": { + "vscode": "^1.1.37", + "@eslint/js": "^9.10.0", + "@types/eslint__js": "^8.42.3", + "@types/node": "^22.5.5", + "@typescript-eslint/parser": "^8.7.0", + "eslint": "^9.10.0", + "globals": "^15.9.0", + "typescript": "^5.6.2", + "typescript-eslint": "^8.6.0" + } +} diff --git a/users/Profpatsch/lyric/extension/src/extension.ts b/users/Profpatsch/lyric/extension/src/extension.ts new file mode 100644 index 000000000000..35f76f3fe0b4 --- /dev/null +++ b/users/Profpatsch/lyric/extension/src/extension.ts @@ -0,0 +1,864 @@ +import * as vscode from 'vscode'; +import * as net from 'net'; +import { adjustTimestampToEighthNote, bpmToEighthNoteDuration } from './quantize-lrc'; +import { publishLyrics, PublishRequest } from './upload-lrc'; + +const channel_global = vscode.window.createOutputChannel('LRC'); + +export function activate(context: vscode.ExtensionContext) { + context.subscriptions.push(...registerCheckLineTimestamp(context)); + context.subscriptions.push( + vscode.commands.registerCommand('extension.jumpToLrcPosition', jumpToLrcPosition), + vscode.commands.registerCommand('extension.shiftLyricsDown', shiftLyricsDown), + vscode.commands.registerCommand('extension.shiftLyricsUp', shiftLyricsUp), + vscode.commands.registerCommand('extension.tapBpm', tapBpm), + vscode.commands.registerCommand('extension.quantizeToEigthNote', quantizeToEigthNote), + vscode.commands.registerCommand( + 'extension.fineTuneTimestampDown100MsAndPlay', + fineTuneTimestampAndPlay(-100), + ), + vscode.commands.registerCommand( + 'extension.fineTuneTimestampUp100MsAndPlay', + fineTuneTimestampAndPlay(100), + ), + vscode.commands.registerCommand( + 'extension.uploadLyricsToLrclibDotNet', + uploadToLrclibDotNet, + ), + ); +} + +/** + * Jumps to the position in the lyric file corresponding to the current cursor position in the active text editor. + * Sends a command to a socket to seek to the specified position in mpv at the socket path `~/tmp/mpv-socket`. + * @remarks + * This function requires the following dependencies: + * - `vscode` module for accessing the active text editor and displaying messages. + * - `net` module for creating a socket connection. + * @throws {Error} If there is an error sending the command to the socket. + */ +function jumpToLrcPosition() { + const editor = vscode.window.activeTextEditor; + + if (!editor) { + vscode.window.showErrorMessage('No active editor found.'); + return; + } + + const ext = new Ext(editor.document); + const position = editor.selection.active; + const res = ext.getTimestampFromLine(position.line); + + if (!res) { + return; + } + const { milliseconds, seconds } = res; + + // Prepare JSON command to send to the socket + const seekCommand = { + command: ['seek', seconds, 'absolute'], + }; + const reloadSubtitlesCommand = { + command: ['sub-reload'], + }; + + const socket = new net.Socket(); + + const socketPath = process.env.HOME + '/tmp/mpv-socket'; + socket.connect(socketPath, () => { + socket.write(JSON.stringify(seekCommand)); + socket.write('\n'); + socket.write(JSON.stringify(reloadSubtitlesCommand)); + socket.write('\n'); + vscode.window.showInformationMessage( + `Sent command to jump to [${formatTimestamp(milliseconds)}] and sync subtitles.`, + ); + socket.end(); + }); + + socket.on('error', err => { + vscode.window.showErrorMessage(`Failed to send command: ${err.message}`); + }); +} + +/** + * Shifts the lyrics down by one line starting from the current cursor position in the active text editor. + * @remarks + * This function requires the following dependencies: + * - `vscode` module for accessing the active text editor and displaying messages. + */ +async function shiftLyricsDown() { + const editor = vscode.window.activeTextEditor; + + if (!editor) { + vscode.window.showErrorMessage('No active editor found.'); + return; + } + + const ext = new Ext(editor.document); + + const getLine = (line: number) => ({ + number: line, + range: editor.document.lineAt(line), + }); + + // get the document range from the beginning of the current line to the end of the file + const documentRange = new vscode.Range( + getLine(editor.selection.active.line).range.range.start, + editor.document.lineAt(editor.document.lineCount - 1).range.end, + ); + + let newLines: string = ''; + // iterate through all lines under the current line, save the lyric text from the current line, and replace it with the lyric text from the previous line + let previousLineText = ''; + for ( + // get the current line range + let line = getLine(editor.selection.active.line); + line.number < editor.document.lineCount - 1; + // next line as position from line number + line = getLine(line.number + 1) + ) { + const timestamp = ext.getTimestampFromLine(line.number); + if (timestamp === undefined) { + newLines += line.range.text + '\n'; + continue; + } + newLines += `[${formatTimestamp(timestamp.milliseconds)}]` + previousLineText + '\n'; + previousLineText = timestamp.text; + } + // replace documentRange with newLines + await editor.edit(editBuilder => { + editBuilder.replace(documentRange, newLines); + }); +} + +/** + * Shifts the lyrics up by one line starting from the current cursor position in the active text editor. + * @remarks + * This function requires the following dependencies: + * - `vscode` module for accessing the active text editor and displaying messages. + */ +async function shiftLyricsUp() { + const editor = vscode.window.activeTextEditor; + + if (!editor) { + vscode.window.showErrorMessage('No active editor found.'); + return; + } + + const ext = new Ext(editor.document); + + const getLine = (line: number) => ({ + number: line, + range: editor.document.lineAt(line), + }); + + // get the document range from the beginning of the current line to the end of the file + const documentRange = new vscode.Range( + getLine(editor.selection.active.line).range.range.start, + editor.document.lineAt(editor.document.lineCount - 1).range.end, + ); + + let newLines: string = ''; + // iterate through all lines under the current line, save the lyric text from the current line, and replace it with the lyric text from the next line + for ( + // get the current line range + let line = getLine(editor.selection.active.line); + line.number < editor.document.lineCount - 2; + // next line as position from line number + line = getLine(line.number + 1) + ) { + const nextLineText = + ext.getTimestampFromLine(line.number + 1)?.text ?? + ext.document.lineAt(line.number + 1).text; + const timestamp = ext.getTimestampFromLine(line.number); + if (timestamp === undefined) { + continue; + } + newLines += `[${formatTimestamp(timestamp.milliseconds)}]` + nextLineText + '\n'; + } + // replace documentRange with newLines + await editor.edit(editBuilder => { + editBuilder.replace(documentRange, newLines); + }); +} + +/** + * Tap the BPM of the track and write it to the header of the active text editor. + * @remarks + * This function requires the following dependencies: + * - `vscode` module for accessing the active text editor and displaying messages. + */ +async function tapBpm() { + const editor = vscode.window.activeTextEditor; + + if (!editor) { + vscode.window.showErrorMessage('No active editor found.'); + return; + } + + const ext = new Ext(editor.document); + const startBpm = ext.findBpmHeader(); + + const bpm = await timeInputBpm(startBpm); + + if (bpm === undefined) { + return; + } + + await ext.writeHeader('bpm', bpm.toString()); +} + +/** first ask the user for the BPM of the track, then quantize the timestamps in the active text editor to the closest eighth note based on the given BPM */ +async function quantizeToEigthNote() { + const editor = vscode.window.activeTextEditor; + + if (!editor) { + vscode.window.showErrorMessage('No active editor found.'); + return; + } + + const ext = new Ext(editor.document); + + const startBpm = ext.findBpmHeader(); + const bpm = await timeInputBpm(startBpm); + + if (bpm === undefined) { + return; + } + + await ext.writeHeader('bpm', bpm.toString()); + + const getLine = (line: number) => ({ + number: line, + range: editor.document.lineAt(line), + }); + + const documentRange = new vscode.Range( + getLine(0).range.range.start, + editor.document.lineAt(editor.document.lineCount - 1).range.end, + ); + + const eighthNoteDuration = bpmToEighthNoteDuration(bpm); + + let newLines: string = ''; + for ( + let line = getLine(0); + line.number < editor.document.lineCount - 1; + line = getLine(line.number + 1) + ) { + const timestamp = ext.getTimestampFromLine(line.number); + if (timestamp === undefined) { + newLines += line.range.text + '\n'; + continue; + } + const adjustedMs = adjustTimestampToEighthNote( + timestamp.milliseconds, + eighthNoteDuration, + ); + newLines += `[${formatTimestamp(adjustedMs)}]${timestamp.text}\n`; + } + + await editor.edit(editBuilder => { + editBuilder.replace(documentRange, newLines); + }); +} + +/** fine tune the timestamp of the current line by the given amount (in milliseconds) and play the track at slightly before the new timestamp */ +function fineTuneTimestampAndPlay(amountMs: number) { + return async () => { + const editor = vscode.window.activeTextEditor; + + if (!editor) { + vscode.window.showErrorMessage('No active editor found.'); + return; + } + + const ext = new Ext(editor.document); + + const position = editor.selection.active; + const res = ext.getTimestampFromLine(position.line); + + if (!res) { + return; + } + const { milliseconds } = res; + + const newMs = milliseconds + amountMs; + + // adjust the timestamp + const documentRange = editor.document.lineAt(position.line).range; + await editor.edit(editBuilder => { + editBuilder.replace(documentRange, `[${formatTimestamp(newMs)}]${res.text}`); + }); + + const PLAY_BEFORE_TIMESTAMP_MS = 2000; + const seekCommand = { + command: ['seek', (newMs - PLAY_BEFORE_TIMESTAMP_MS) / 1000, 'absolute'], + }; + const reloadSubtitlesCommand = { + command: ['sub-reload'], + }; + + const socket = new net.Socket(); + + const socketPath = process.env.HOME + '/tmp/mpv-socket'; + socket.connect(socketPath, () => { + socket.write(JSON.stringify(seekCommand)); + socket.write('\n'); + socket.write(JSON.stringify(reloadSubtitlesCommand)); + socket.write('\n'); + vscode.window.showInformationMessage( + `Sent command to jump to [${formatTimestamp(newMs)}] and sync subtitles.`, + ); + socket.end(); + }); + + socket.on('error', err => { + vscode.window.showErrorMessage(`Failed to send command: ${err.message}`); + }); + }; +} + +// convert the given bpm to miliseconds +function bpmToMs(bpm: number) { + return Math.floor((60 / bpm) * 1000); +} + +// Show input boxes in a loop, and record the time between each input, averaging the last 5 inputs over a sliding window, then calculate the BPM of the average +async function timeInputBpm(startBpm?: number) { + const startBpmMs = bpmToMs(startBpm ?? 120); + const timeDifferences: number[] = [ + startBpmMs, + startBpmMs, + startBpmMs, + startBpmMs, + startBpmMs, + ]; + // assign a weight to the time differences, so that the most recent time differences have more weight + const weights = [0.1, 0.1, 0.2, 0.3, 0.3]; + + const calculateBPM = () => { + // use a weighted average here + let avg = 0; + for (let i = 0; i < timeDifferences.length; i++) { + avg += timeDifferences[i] * weights[i]; + } + + return Math.floor(60000 / avg); + }; + + let lastPressTime = Date.now(); + let firstLoop = true; + while (true) { + const res = await vscode.window.showInputBox({ + prompt: `Press enter to record BPM (current BPM: ${calculateBPM()}), enter the final BPM once you know, or press esc to finish`, + placeHolder: 'BPM', + value: startBpm !== undefined && firstLoop ? startBpm.toString() : undefined, + }); + firstLoop = false; + if (res === undefined) { + return undefined; + } + if (res !== '') { + const resBpm = parseInt(res, 10); + if (isNaN(resBpm)) { + vscode.window.showErrorMessage('Invalid BPM'); + continue; + } + return resBpm; + } + + const now = Date.now(); + const timeDiff = now - lastPressTime; + // Add the time difference to the array (limit to last 5 key presses) + timeDifferences.shift(); // Remove the oldest time difference + timeDifferences.push(timeDiff); + + lastPressTime = now; + } +} + +/** + * Uploads the lyrics in the active text editor to the LrclibDotNet API. + * @remarks + * This function requires the following dependencies: + * - `vscode` module for accessing the active text editor and displaying messages. + * - `fetch` module for making HTTP requests. + * @throws {Error} If there is an HTTP error. + */ +async function uploadToLrclibDotNet() { + const editor = vscode.window.activeTextEditor; + + if (!editor) { + vscode.window.showErrorMessage('No active editor found.'); + return; + } + + const ext = new Ext(editor.document); + + const title = ext.findHeader('ti')?.value; + const artist = ext.findHeader('ar')?.value; + const album = ext.findHeader('al')?.value; + const lengthString = ext.findHeader('length')?.value; + + if ( + title === undefined || + artist === undefined || + album === undefined || + lengthString === undefined + ) { + vscode.window.showErrorMessage( + 'Missing required headers: title, artist, album, length', + ); + return; + } + // parse length as mm:ss + const [minutes, seconds] = lengthString?.split(':') ?? []; + if ( + !minutes || + !seconds || + isNaN(parseInt(minutes, 10)) || + isNaN(parseInt(seconds, 10)) + ) { + vscode.window.showErrorMessage('Invalid length header, expected format: mm:ss'); + return; + } + const length = parseInt(minutes, 10) * 60 + parseInt(seconds, 10); + + const syncedLyrics = ext.getLyricsPart(); + const plainLyrics = plainLyricsFromLyrics(syncedLyrics); + + // open a html preview with the lyrics saying + // + // Uploading these lyrics to lrclib.net: + // <metadata as table> + // Lyrics: + // ```<lyrics>``` + // Plain lyrics: + // ```<plainLyrics>``` + // + // Is this ok? + // <button to upload> + + const previewTitle = 'Lyric Preview'; + const metadataTable = ` + <table> + <tr> + <th>Title</th> + <td>${title}</td> + </tr> + <tr> + <th>Artist</th> + <td>${artist}</td> + </tr> + <tr> + <th>Album</th> + <td>${album}</td> + </tr> + <tr> + <th>Length</th> + <td>${lengthString}</td> + </tr> + </table> + `; + const previewContent = ` + <p>Uploading these lyrics to lrclib.net:</p> + ${metadataTable} + <p>Lyrics:</p> + <pre>${syncedLyrics}</pre> + <p>Plain lyrics:</p> + <pre>${plainLyrics}</pre> + <p>Is this ok?</p> + <button>Upload</button> + `; + + const panel = vscode.window.createWebviewPanel( + 'lyricPreview', + previewTitle, + vscode.ViewColumn.One, + { enableScripts: true }, + ); + panel.webview.html = ` + <!DOCTYPE html> + <html lang="en"> + <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Markdown Preview</title> + </head> + <body> + ${previewContent} + </body> + <script> + const vscode = acquireVsCodeApi(); + document.querySelector('button').addEventListener('click', () => { + vscode.postMessage({ command: 'upload' }); + }); + </script> + </html> + `; + let isDisposed = false; + panel.onDidDispose(() => { + isDisposed = true; + }); + + await new Promise((resolve, _reject) => { + panel.webview.onDidReceiveMessage((message: { command: string }) => { + if (isDisposed) { + return; + } + if (message.command === 'upload') { + panel.dispose(); + resolve(true); + } + }); + }); + + const toUpload: PublishRequest = { + trackName: title, + artistName: artist, + albumName: album, + duration: length, + plainLyrics: plainLyrics, + syncedLyrics: syncedLyrics, + }; + + // log the data to our extension output buffer + channel_global.appendLine('Uploading lyrics to LrclibDotNet'); + const json = JSON.stringify(toUpload, null, 2); + channel_global.appendLine(json); + + const res = await publishLyrics(toUpload); + + if (res) { + vscode.window.showInformationMessage('Lyrics successfully uploaded.'); + channel_global.appendLine('Lyrics successfully uploaded.'); + } else { + vscode.window.showErrorMessage('Failed to upload lyrics.'); + channel_global.appendLine('Failed to upload lyrics.'); + } +} + +// If the difference to the timestamp on the next line is larger than 10 seconds (for 120 BPM), underline the next line and show a warning message on hover +export function registerCheckLineTimestamp(_context: vscode.ExtensionContext) { + const changesToCheck: Set<vscode.TextDocument> = new Set(); + const everSeen = new Set<vscode.TextDocument>(); + + return [ + vscode.workspace.onDidChangeTextDocument(e => { + changesToCheck.add(e.document); + if (vscode.window.activeTextEditor?.document === e.document) { + doEditorChecks(vscode.window.activeTextEditor.document, everSeen, changesToCheck); + } + }), + vscode.workspace.onDidOpenTextDocument(e => { + changesToCheck.add(e); + everSeen.add(e); + if (vscode.window.activeTextEditor?.document === e) { + doEditorChecks(vscode.window.activeTextEditor.document, everSeen, changesToCheck); + } + }), + + vscode.window.onDidChangeActiveTextEditor(editor => { + if (editor) { + doEditorChecks(editor.document, everSeen, changesToCheck); + } + }), + vscode.window.onDidChangeVisibleTextEditors(editors => { + for (const editor of editors) { + doEditorChecks(editor.document, everSeen, changesToCheck); + } + }), + ]; +} + +function doEditorChecks( + document: vscode.TextDocument, + everSeen: Set<vscode.TextDocument>, + changesToCheck: Set<vscode.TextDocument>, +) { + const ext = new Ext(document); + + if (!everSeen.has(document)) { + changesToCheck.add(document); + everSeen.add(document); + } + + if (!changesToCheck.has(document)) { + return; + } + changesToCheck.delete(document); + + const from = 0; + const to = document.lineCount - 1; + for (let line = from; line <= to; line++) { + const warnings: string[] = []; + const timeDiff = timeDifferenceTooLarge(ext, line); + if (timeDiff !== undefined) { + warnings.push(timeDiff); + } + const nextTimestampSmaller = nextLineTimestampSmallerThanCurrent(ext, line); + if (nextTimestampSmaller !== undefined) { + warnings.push(nextTimestampSmaller); + } + for (const warning of warnings) { + global_manageWarnings.setWarning(document, line, warning); + } + // unset any warnings if this doesn’t apply anymore + if (warnings.length === 0) { + global_manageWarnings.setWarning(document, line); + } + } +} + +/** Warn if the difference to the timestamp on the next line is larger than + * * 10 seconds at 120 BPM + * * 5 seconds at 240 BPM + * * 20 seconds at 60 BPM + * * etc + */ +function timeDifferenceTooLarge(ext: Ext, line: number): string | undefined { + const bpm = ext.findBpmHeader() ?? 120; + const maxTimeDifference = 10000 * (120 / bpm); + const timeDifference = ext.getTimeDifferenceToNextLineTimestamp( + new vscode.Position(line, 0), + ); + if ( + !timeDifference || + timeDifference.thisLineIsEmpty || + timeDifference.difference <= maxTimeDifference + ) { + return; + } + return `Time difference to next line is ${formatTimestamp( + timeDifference.difference, + )}, should there be silence here? At ${bpm} BPM, we assume anything more than ${( + maxTimeDifference / 1000 + ).toFixed(2)} seconds is a mistake.`; +} + +/** Warn if the timestamp on the next line is smaller or equal to the current timestamp */ +function nextLineTimestampSmallerThanCurrent(ext: Ext, line: number): string | undefined { + const timeDifference = ext.getTimeDifferenceToNextLineTimestamp( + new vscode.Position(line, 0), + ); + if (!timeDifference) { + return; + } + if (timeDifference.difference == 0) { + return `The timestamp to the next line is not increasing`; + } + if (timeDifference.difference < 0) { + return `The timestamp to the next line is decreasing`; + } +} + +class Ext { + constructor(public document: vscode.TextDocument) {} + + getTimeDifferenceToNextLineTimestamp(position: vscode.Position) { + const thisLineTimestamp = this.getTimestampFromLine(position.line); + const nextLineTimestamp = this.getTimestampFromLine(position.line + 1); + if (!thisLineTimestamp || !nextLineTimestamp) { + return; + } + return { + difference: nextLineTimestamp.milliseconds - thisLineTimestamp.milliseconds, + thisLineIsEmpty: thisLineTimestamp.text.trim() === '', + }; + } + + /** + * Retrieves the timestamp and text from the line at the given position in the active text editor. + * + * @param position - The position of the line in the editor. + * @returns An object containing the milliseconds, seconds, and text extracted from the line. + */ + getTimestampFromLine(line: number) { + const lineText = this.document.lineAt(line).text; + return this.getTimestampFromLineText(lineText); + } + + getTimestampFromLineText(lineText: string) { + // Extract timestamp [mm:ss.ms] from the current line + const match = lineText.match(/\[(\d+:\d+\.\d+)\](.*)/); + if (!match) { + return; + } + const [, timestamp, text] = match; + const milliseconds = parseTimestamp(timestamp); + const seconds = milliseconds / 1000; + return { milliseconds, seconds, text }; + } + + // Find a header line of the format + // [header:value] + // at the beginning of the lrc file (before the first empty line) + findHeader(headerName: string) { + for (let line = 0; line < this.document.lineCount; line++) { + const text = this.document.lineAt(line).text; + if (text.trim() === '') { + return; + } + const match = text.match(/^\[(\w+):(.*)\]$/); + if (match && match[1] === headerName) { + return { key: match[1], value: match[2], line: line }; + } + } + } + + /** Find the bpm header and return the bpm as number, if any */ + findBpmHeader() { + const startBpmStr = this.findHeader('bpm')?.value; + let bpm; + if (startBpmStr !== undefined) { + bpm = parseInt(startBpmStr, 10); + if (isNaN(bpm)) { + bpm = undefined; + } + } + return bpm; + } + + // check if the given line is a header line + isHeaderLine(line: string) { + return ( + line.trim() !== '' && + line.match(/^\[(\w+):(.*)\]$/) !== null && + line.match(/^\[\d\d:\d\d.\d+\]/) === null + ); + } + + // write the given header to the lrc file, if the header already exists, update the value + async writeHeader(headerName: string, value: string) { + const header = this.findHeader(headerName); + const editor = findActiveEditor(this.document); + if (!editor) { + return; + } + if (header) { + const lineRange = this.document.lineAt(header.line).range; + await editor.edit(editBuilder => { + editBuilder.replace(lineRange, `[${headerName}: ${value}]`); + }); + } else { + // insert before the first timestamp line if no header is found, or after the last header if there are multiple headers + let insertLine = 0; + let extraNewline = ''; + for (let line = 0; line < this.document.lineCount; line++) { + const text = this.document.lineAt(line).text; + // check if header + if (this.isHeaderLine(text)) { + insertLine = line + 1; + } else if (text.trim() === '') { + insertLine = line; + break; + } else { + insertLine = line; + if (line == 0) { + extraNewline = '\n'; + } + break; + } + } + await editor.edit(editBuilder => { + editBuilder.insert( + new vscode.Position(insertLine, 0), + `[${headerName}: ${value}]\n${extraNewline}`, + ); + }); + } + } + + // get the lyrics part of the lrc file (after the headers) + getLyricsPart() { + const first = this.document.lineAt(0).text; + let line = 0; + if (this.isHeaderLine(first)) { + // skip all headers (until the first empty line) + for (; line < this.document.lineCount; line++) { + const text = this.document.lineAt(line).text; + if (text.trim() === '') { + line++; + break; + } + } + } + + // get the range from the current line to the end of the file + const documentRange = new vscode.Range( + new vscode.Position(line, 0), + this.document.lineAt(this.document.lineCount - 1).range.end, + ); + return this.document.getText(documentRange); + } +} + +// find an active editor that has the given document opened +function findActiveEditor(document: vscode.TextDocument) { + return vscode.window.visibleTextEditors.find(editor => editor.document === document); +} + +function plainLyricsFromLyrics(lyrics: string) { + // remove the timestamp from the beginning of every line + return ( + lyrics + .replace(/\[\d\d:\d\d\.\d\d\]\s?/gm, '') + // remove empty lines + .replace(/\n{2,}/g, '\n') + ); +} + +function parseTimestamp(timestamp: string): number { + // Parse [mm:ss.ms] format into milliseconds + const [min, sec] = timestamp.split(':'); + + const minutes = parseInt(min, 10); + const seconds = parseFloat(sec); + + return minutes * 60 * 1000 + seconds * 1000; +} + +function formatTimestamp(ms: number): string { + // Format milliseconds back into [mm:ss.ms] + const minutes = Math.floor(ms / 60000); + ms %= 60000; + const seconds = (ms / 1000).toFixed(2); + + return `${String(minutes).padStart(2, '0')}:${seconds.padStart(5, '0')}`; +} + +class ManageWarnings { + private warnings: Map<number, string> = new Map(); + private diagnostics: vscode.DiagnosticCollection; + + constructor() { + this.diagnostics = vscode.languages.createDiagnosticCollection(); + } + + /** Set a warning message on a line in a document, if null then unset */ + setWarning(document: vscode.TextDocument, line: number, message?: string) { + if (message !== undefined) { + this.warnings.set(line, message); + } else { + this.warnings.delete(line); + } + this.updateDiagnostics(document); + } + + private updateDiagnostics(document: vscode.TextDocument) { + const mkWarning = (line: number, message: string) => { + const lineRange = document.lineAt(line).range; + return new vscode.Diagnostic(lineRange, message, vscode.DiagnosticSeverity.Warning); + }; + const diagnostics: vscode.Diagnostic[] = []; + for (const [line, message] of this.warnings) { + diagnostics.push(mkWarning(line, message)); + } + this.diagnostics.delete(document.uri); + this.diagnostics.set(document.uri, diagnostics); + } +} + +const global_manageWarnings = new ManageWarnings(); diff --git a/users/Profpatsch/lyric/extension/src/quantize-lrc.ts b/users/Profpatsch/lyric/extension/src/quantize-lrc.ts new file mode 100644 index 000000000000..83c31348e26e --- /dev/null +++ b/users/Profpatsch/lyric/extension/src/quantize-lrc.ts @@ -0,0 +1,82 @@ +export function bpmToEighthNoteDuration(bpm: number): number { + // Convert BPM to eighth-note duration in milliseconds + const quarterNoteDuration = (60 / bpm) * 1000; // in ms + const eighthNoteDuration = quarterNoteDuration / 2; + return eighthNoteDuration; +} + +function parseTimestamp(timestamp: string): number { + // Parse [mm:ss.ms] format into milliseconds + const [min, sec] = timestamp.split(':'); + + const minutes = parseInt(min, 10); + const seconds = parseFloat(sec); + + return minutes * 60 * 1000 + seconds * 1000; +} + +function formatTimestamp(ms: number): string { + // Format milliseconds back into [mm:ss.ms] + const minutes = Math.floor(ms / 60000); + ms %= 60000; + const seconds = (ms / 1000).toFixed(2); + + return `${String(minutes).padStart(2, '0')}:${seconds}`; +} + +export function adjustTimestampToEighthNote( + timestampMs: number, + eighthNoteDuration: number, +): number { + // Find the closest multiple of the eighth-note duration + return Math.round(timestampMs / eighthNoteDuration) * eighthNoteDuration; +} + +function adjustTimestamps(bpm: number, timestamps: string[]): string[] { + const eighthNoteDuration = bpmToEighthNoteDuration(bpm); + + return timestamps.map(timestamp => { + const timestampMs = parseTimestamp(timestamp); + const adjustedMs = adjustTimestampToEighthNote(timestampMs, eighthNoteDuration); + return formatTimestamp(adjustedMs); + }); +} + +// Parse a .lrc file into an array of objects with timestamp and text +// Then adjust the timestamps to the closest eighth note +// Finally, format the adjusted timestamps back into [mm:ss.ms] format and put them back into the lrc object +// +// Example .lrc file: +// [01:15.66] And the reviewers bewail +// [01:18.18] There'll be no encore +// [01:21.65] 'Cause you're not begging for more +// [01:25.00] +// [01:34.64] She may seem self-righteous and holier-than-thou +// [01:39.77] She may sound like she has all the answers +// [01:45.20] But beyond she may feel just a bit anyhow +function parseLrc(lrc: string): { timestamp: string; text: string }[] { + return lrc + .trimEnd() + .split('\n') + .map(line => { + const match = line.match(/\[(\d+:\d+\.\d+)\](.*)/); + const [, timestamp, text] = match!; + return { timestamp, text }; + }); +} + +function formatLrc(lrc: { timestamp: string; text: string }[]): string { + return lrc.map(({ timestamp, text }) => `[${timestamp}] ${text}`).join('\n'); +} + +function adjustLrc(lrc: string, bpm: number): string { + const lrcArray = parseLrc(lrc); + const timestamps = lrcArray.map(({ timestamp }) => timestamp); + const adjustedTimestamps = adjustTimestamps(bpm, timestamps); + + lrcArray.forEach((line, i) => { + line.timestamp = adjustedTimestamps[i]; + }); + + return formatLrc(lrcArray); +} diff --git a/users/Profpatsch/lyric/extension/src/upload-lrc.ts b/users/Profpatsch/lyric/extension/src/upload-lrc.ts new file mode 100644 index 000000000000..8627e382726b --- /dev/null +++ b/users/Profpatsch/lyric/extension/src/upload-lrc.ts @@ -0,0 +1,117 @@ +import * as crypto from 'crypto'; + +const USER_AGENT = + 'lyric tool (source: https://code.tvl.fyi/tree/users/Profpatsch/lyric, contact: https://mastodon.xyz/@Profpatsch)'; + +// Helper function to convert a hex string to a Buffer +function hexToBytes(hex: string): Buffer { + return Buffer.from(hex, 'hex'); +} + +// Function to verify the nonce +function verifyNonce(result: Buffer, target: Buffer): boolean { + if (result.length !== target.length) { + return false; + } + + for (let i = 0; i < result.length - 1; i++) { + if (result[i] > target[i]) { + return false; + } else if (result[i] < target[i]) { + break; + } + } + + return true; +} + +// Function to solve the challenge +function solveChallenge(prefix: string, targetHex: string): string { + let nonce = 0; + let hashed: Buffer; + const target = hexToBytes(targetHex); + + while (true) { + const input = `${prefix}${nonce}`; + hashed = crypto.createHash('sha256').update(input).digest(); + + if (verifyNonce(hashed, target)) { + break; + } else { + nonce += 1; + } + } + + return nonce.toString(); +} + +async function getUploadNonce() { + try { + const response = await fetch('https://lrclib.net/api/request-challenge', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'User-Agent': USER_AGENT, + 'Lrclib-Client': USER_AGENT, + }, + }); + + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + + const challengeData = (await response.json()) as { prefix: string; target: string }; + + return { + prefix: challengeData.prefix, + nonce: solveChallenge(challengeData.prefix, challengeData.target), + }; + } catch (error) { + console.error('Error fetching the challenge:', error); + } +} + +// Interface for the request body +/** + * Represents a request to publish a track with its associated information. + */ +export interface PublishRequest { + trackName: string; + artistName: string; + albumName: string; + /** In seconds? Milliseconds? mm:ss? */ + duration: number; + plainLyrics: string; + syncedLyrics: string; +} + +// Function to publish lyrics using the solved challenge +export async function publishLyrics( + requestBody: PublishRequest, +): Promise<true | undefined> { + const challenge = await getUploadNonce(); + if (!challenge) { + return; + } + const publishToken = `${challenge.prefix}:${challenge.nonce}`; + + const response = await fetch('https://lrclib.net/api/publish', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'User-Agent': USER_AGENT, + 'Lrclib-Client': USER_AGENT, + 'X-Publish-Token': publishToken, + }, + body: JSON.stringify(requestBody), + }); + + if (response.status === 201) { + console.log('Lyrics successfully published.'); + return true; + } else { + const errorResponse = (await response.json()) as { [key: string]: string }; + console.error('Failed to publish lyrics:', errorResponse); + return; + } +} diff --git a/users/Profpatsch/lyric/extension/tsconfig.json b/users/Profpatsch/lyric/extension/tsconfig.json new file mode 100644 index 000000000000..44a5195795da --- /dev/null +++ b/users/Profpatsch/lyric/extension/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "commonjs", + "lib": [ + "ES6" + ], + "outDir": "./out", + "rootDir": "./src", + "strict": true, + "sourceMap": true, + "esModuleInterop": true, + "skipLibCheck": true + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules", + ".vscode-test" + ] +} diff --git a/users/Profpatsch/lyric/lyric-mpv-script.lua b/users/Profpatsch/lyric/lyric-mpv-script.lua new file mode 100644 index 000000000000..ba05c7c449f6 --- /dev/null +++ b/users/Profpatsch/lyric/lyric-mpv-script.lua @@ -0,0 +1,66 @@ +-- get_lrc_subtitles.lua + +-- Function to remove Unicode symbol characters +function remove_symbols(str) + -- This pattern matches anything that is not a letter, digit, or whitespace + return str:gsub("[%p%c%z]", "") -- remove punctuation, control, and zero-width characters +end + +-- Asynchronous callback function to handle the result of the 'get_subtitles' command +function handle_subtitle_result(success, result) + if not success or result.status ~= 0 then + mp.msg.error("Failed to get subtitles") + mp.msg.error("Exit code: " .. tostring(result.exit_code)) + if result.stderr then + mp.msg.error("Error: " .. result.stderr) + end + return + end + + -- Extract the output from the external command + local subtitle_file = result.stdout:match("^%s*(.-)%s*$") -- trim any extra whitespace + + -- If no subtitle file was returned, stop + if not subtitle_file or subtitle_file == "" then + mp.msg.warn("No subtitle file found") + return + end + + -- Load the subtitle file in MPV + mp.commandv("sub-add", subtitle_file) + mp.msg.info("Loaded subtitle file: " .. subtitle_file) +end + +-- Function to load the LRC subtitle file +function load_lrc_subtitles() + -- Retrieve metadata for the currently playing file + local artist = mp.get_property("metadata/by-key/artist") + local album = mp.get_property("metadata/by-key/album") + local title = mp.get_property("metadata/by-key/title") + + -- If any metadata is missing, print a warning and stop + if not artist or not album or not title then + mp.msg.warn("Artist, album, or title metadata is missing") + return + end + + -- Concatenate the metadata + local query = string.format("%s %s %s", artist, album, title) + + -- Remove Unicode symbols from the query string + query = remove_symbols(query) + + -- Create the command array + local cmd = {"@get_subtitles_command@", query} + + -- Run the external command asynchronously to get the subtitle file + mp.command_native_async({ + name = "subprocess", + args = cmd, + capture_stdout = true, + capture_stderr = true + }, handle_subtitle_result) +end + +-- Register the event that triggers when a file is loaded +mp.register_event("file-loaded", load_lrc_subtitles) diff --git a/users/Profpatsch/lyric/lyric-timing-mpv-script.lua b/users/Profpatsch/lyric/lyric-timing-mpv-script.lua new file mode 100644 index 000000000000..dd74d334414c --- /dev/null +++ b/users/Profpatsch/lyric/lyric-timing-mpv-script.lua @@ -0,0 +1,68 @@ +-- This function formats the current timestamp in the [mm:ss.ms] format +function format_timestamp(seconds) + local minutes = math.floor(seconds / 60) + local seconds = seconds % 60 + return string.format("[%02d:%05.2f]", minutes, seconds) +end + +-- Get the user’s cache directory +local cache_dir = os.getenv("XDG_CACHE_HOME") or os.getenv("HOME") .. "/.cache" + +-- This function writes the timestamp to the LRC file +function write_timestamp_to_lrc() + local filename = mp.get_property("path") + if not filename then + mp.msg.warn("No file currently playing.") + return + end + + -- Extract metadata for artist, title, and album + local artist = mp.get_property("metadata/by-key/ARTIST", "Unknown Artist") + local title = mp.get_property("metadata/by-key/TITLE", "Unknown Title") + local album = mp.get_property("metadata/by-key/ALBUM", "Unknown Album") + + -- Construct the lrc dir + local dir = cache_dir .. "/lyric/timed" + local lrc_filename = string.format("%s/%s - %s - %s.lrc", dir, artist, album, title) + + -- Get current playback time + local current_time = mp.get_property_number("time-pos", 0) + local formatted_time = format_timestamp(current_time) + + -- If the file does not exist, or is empty, create it and add metadata in the following format: + -- [ar: Chubby Checker oppure Beatles, The] + -- [al: Hits Of The 60's - Vol. 2 – Oldies] + -- [ti: Let's Twist Again] + -- [au: Written by Kal Mann / Dave Appell, 1961] + -- [length: 2:23] + local file = io.open(lrc_filename, "r+") + if not file then + file = io.open(lrc_filename, "w+") + end + + -- read the file and check whether it only contains whitespace + local content = file:read("*all") + if content:match("^%s*$") then + file:write("[ar: " .. artist .. "]\n") + file:write("[al: " .. album .. "]\n") + file:write("[ti: " .. title .. "]\n") + local duration = mp.get_property_number("duration", 0) + local formatted_duration = string.format("%02d:%02d", math.floor(duration / 60), duration % 60) + file:write("[length: " .. formatted_duration .. "]\n") + file:write("\n") + end + file:close() + + -- Append the timestamp to the LRC file + local file = io.open(lrc_filename, "a") + if file then + file:write(formatted_time .. "\n") + file:close() + mp.msg.info("Timestamp " .. formatted_time .. " added to " .. lrc_filename) + else + mp.msg.error("Failed to open " .. lrc_filename) + end +end + +-- Bind Ctrl+l to the function that writes the timestamp +mp.add_key_binding("Ctrl+l", "insert_timestamp", write_timestamp_to_lrc) diff --git a/users/Profpatsch/lyric/package.json b/users/Profpatsch/lyric/package.json new file mode 100644 index 000000000000..4621d087e0fd --- /dev/null +++ b/users/Profpatsch/lyric/package.json @@ -0,0 +1,23 @@ +{ + "name": "lyric", + "version": "1.0.0", + "main": "dist/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "type": "module", + "license": "GPL-3.0-or-later", + "description": "", + "dependencies": {}, + "devDependencies": { + "@eslint/js": "^9.10.0", + "@types/eslint__js": "^8.42.3", + "@types/node": "^22.5.5", + "@typescript-eslint/parser": "^8.7.0", + "eslint": "^9.10.0", + "globals": "^15.9.0", + "typescript": "^5.6.2", + "typescript-eslint": "^8.6.0" + } +} diff --git a/users/Profpatsch/lyric/src/index.ts b/users/Profpatsch/lyric/src/index.ts new file mode 100644 index 000000000000..9501fa57b347 --- /dev/null +++ b/users/Profpatsch/lyric/src/index.ts @@ -0,0 +1,16 @@ +import { tapBpm } from './tap-bpm.js'; + +function main() { + // subcommand for tap-bpm + if (process.argv[2] === 'tap-bpm') { + tapBpm(); + } +} + +main(); + +// sleep in a loop to block nodejs +console.log('Blocking event loop...'); +while (true) { + await new Promise(resolve => setTimeout(resolve, 1000)); +} diff --git a/users/Profpatsch/lyric/src/tap-bpm.ts b/users/Profpatsch/lyric/src/tap-bpm.ts new file mode 100644 index 000000000000..b3c727df5608 --- /dev/null +++ b/users/Profpatsch/lyric/src/tap-bpm.ts @@ -0,0 +1,72 @@ +// create a node command line listener that allows the user to press any key , and averages the distances between the key presses to determine the BPM (with a window of 4 key presses). If the user presses q, the program should exit and print the final BPM. + +// Import the necessary modules +import * as readline from 'readline'; + +export function tapBpm() { + // Set up readline interface to listen for keypresses + readline.emitKeypressEvents(process.stdin); + process.stdin.setRawMode(true); + // accept SIGINT on stdin + + // Array to store the time differences between the last 4 key presses + const timeDifferences: number[] = []; + let lastPressTime: number | null = null; + + // Function to calculate BPM based on average time between keypresses + function calculateBPM() { + if (timeDifferences.length < 1) { + return 0; + } + const averageTimeDiff = + timeDifferences.reduce((acc, curr) => acc + curr, 0) / timeDifferences.length; + return (60 * 1000) / averageTimeDiff; + } + + // Handle the SIGINT (Ctrl+C) event manually + process.on('SIGINT', () => { + console.log('\nExiting via SIGINT (Ctrl+C)... Final BPM:', calculateBPM().toFixed(2)); + process.exit(); + }); + + // Listen for keypress events + process.stdin.on('keypress', (str, key: { name: string; sequence: string }) => { + // Exit if 'q' is pressed + if (key.name === 'q') { + console.log('Exiting... Final BPM:', calculateBPM().toFixed(2)); + process.exit(); + } + + // Handle Ctrl+C (SIGINT) + if (key.sequence === '\u0003') { + // '\u0003' is the raw code for Ctrl+C + console.log('\nExiting via Ctrl+C... Final BPM:', calculateBPM().toFixed(2)); + process.exit(); + } + + // Capture the current time of the keypress + const currentTime = Date.now(); + + // If it's not the first keypress, calculate the time difference + if (lastPressTime !== null) { + const timeDiff = currentTime - lastPressTime; + + // Add the time difference to the array (limit to last 10 key presses) + if (timeDifferences.length >= 10) { + timeDifferences.shift(); // Remove the oldest time difference + } + timeDifferences.push(timeDiff); + + // Calculate and display the BPM + const bpm = calculateBPM(); + console.log('Current BPM:', bpm.toFixed(2)); + } else { + console.log('Waiting for more key presses to calculate BPM...'); + } + + // Update the lastPressTime to the current time + lastPressTime = currentTime; + }); + + console.log('Press any key to calculate BPM, press "q" to quit.'); +} diff --git a/users/Profpatsch/lyric/tsconfig.json b/users/Profpatsch/lyric/tsconfig.json new file mode 100644 index 000000000000..26a6a0a82db6 --- /dev/null +++ b/users/Profpatsch/lyric/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2017", + "module": "ESNext", + "outDir": "dist", + "strict": true, + "skipLibCheck": true, + "sourceMap": true, + "esModuleInterop": true + }, + "include": [ + "src/**/*.ts", + ], + "exclude": [ + "node_modules" + ] +} diff --git a/users/Profpatsch/my-prelude/default.nix b/users/Profpatsch/my-prelude/default.nix index e44511541642..a851fdcb0a5f 100644 --- a/users/Profpatsch/my-prelude/default.nix +++ b/users/Profpatsch/my-prelude/default.nix @@ -7,6 +7,9 @@ pkgs.haskellPackages.mkDerivation { src = depot.users.Profpatsch.exactSource ./. [ ./my-prelude.cabal ./src/Aeson.hs + ./src/Json.hs + ./src/Json/Enc.hs + ./src/Arg.hs ./src/AtLeast.hs ./src/MyPrelude.hs ./src/Test.hs diff --git a/users/Profpatsch/my-prelude/my-prelude.cabal b/users/Profpatsch/my-prelude/my-prelude.cabal index 95a8399f370f..ba64f1c3fc27 100644 --- a/users/Profpatsch/my-prelude/my-prelude.cabal +++ b/users/Profpatsch/my-prelude/my-prelude.cabal @@ -59,7 +59,10 @@ library exposed-modules: MyPrelude Aeson + Arg AtLeast + Json + Json.Enc Test Postgres.Decoder Postgres.MonadPostgres @@ -84,6 +87,7 @@ library , pa-field-parser , aeson , aeson-better-errors + , base64-bytestring , bytestring , containers , foldl diff --git a/users/Profpatsch/my-prelude/src/Arg.hs b/users/Profpatsch/my-prelude/src/Arg.hs new file mode 100644 index 000000000000..a6ffa90924b2 --- /dev/null +++ b/users/Profpatsch/my-prelude/src/Arg.hs @@ -0,0 +1,34 @@ +module Arg where + +import Data.String (IsString) +import GHC.Exts (IsList) +import GHC.TypeLits (Symbol) + +-- | Wrap a function argument into this helper to give it a better description for the caller without disturbing the callsite too much. +-- +-- This has instances for IsString and Num, meaning if the caller is usually a string or number literal, it should Just Work. +-- +-- e.g. +-- +-- @ +-- myFoo :: Arg "used as the name in error message" Text -> IO () +-- myFoo (Arg name) = … +-- @ +-- +-- Will display the description in the inferred type of the callsite. +-- +-- Due to IsString you can call @myFoo@ like +-- +-- @myFoo "name in error"@ +-- +-- This is mostly intended for literals, if you want to wrap arbitrary data, use @Label@. +newtype Arg (description :: Symbol) a = Arg {unArg :: a} + deriving newtype + ( Show, + Eq, + IsString, + IsList, + Num, + Monoid, + Semigroup + ) diff --git a/users/Profpatsch/my-prelude/src/Json.hs b/users/Profpatsch/my-prelude/src/Json.hs new file mode 100644 index 000000000000..3738ec6adfff --- /dev/null +++ b/users/Profpatsch/my-prelude/src/Json.hs @@ -0,0 +1,258 @@ +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE UndecidableInstances #-} + +module Json where + +import Data.Aeson (FromJSON (parseJSON), ToJSON (toEncoding, toJSON), Value (..), withObject) +import Data.Aeson qualified as Json +import Data.Aeson.BetterErrors qualified as Json +import Data.Aeson.Types qualified +import Data.Error.Tree +import Data.Map.Strict qualified as Map +import Data.Maybe (catMaybes) +import Data.Set (Set) +import Data.Set qualified as Set +import Data.Text qualified as Text +import Data.Time (UTCTime) +import Data.Vector qualified as Vector +import FieldParser (FieldParser) +import FieldParser qualified as Field +import Label +import PossehlAnalyticsPrelude + +-- | Use a "Data.Aeson.BetterErrors" parser to implement 'FromJSON'’s 'parseJSON' method. +-- +-- @ +-- instance FromJSON Foo where +-- parseJSON = Json.toParseJSON parseFoo +-- @ +toParseJSON :: + -- | the error type is 'Error', if you need 'ErrorTree' use 'toParseJSONErrorTree' + Json.Parse Error a -> + Value -> + Data.Aeson.Types.Parser a +toParseJSON = Json.toAesonParser prettyError + +-- | Use a "Data.Aeson.BetterErrors" parser to implement 'FromJSON'’s 'parseJSON' method. +-- +-- @ +-- instance FromJSON Foo where +-- parseJSON = Json.toParseJSON parseFoo +-- @ +toParseJSONErrorTree :: + -- | the error type is 'ErrorTree', if you need 'Error' use 'toParseJSON' + Json.Parse ErrorTree a -> + Value -> + Data.Aeson.Types.Parser a +toParseJSONErrorTree = Json.toAesonParser prettyErrorTree + +-- | Convert a 'Json.ParseError' to a corresponding 'ErrorTree' +-- +-- TODO: build a different version of 'Json.displayError' so that we can nest 'ErrorTree' as well +parseErrorTree :: Error -> Json.ParseError ErrorTree -> ErrorTree +parseErrorTree contextMsg errs = + errs + & Json.displayError prettyErrorTree + & Text.intercalate "\n" + & newError + -- We nest this here because the json errors is multiline, so the result looks like + -- + -- @ + -- contextMsg + -- \| + -- `- At the path: ["foo"]["bar"] + -- Type mismatch: + -- Expected a value of type object + -- Got: true + -- @ + & singleError + & nestedError contextMsg + +-- | Lift the parser error to an error tree +asErrorTree :: (Functor m) => Json.ParseT Error m a -> Json.ParseT ErrorTree m a +asErrorTree = Json.mapError singleError + +-- | Parse the json array into a 'Set'. +asArraySet :: + (Ord a, Monad m) => + Json.ParseT err m a -> + Json.ParseT err m (Set a) +asArraySet inner = Set.fromList <$> Json.eachInArray inner + +-- | Parse the json object into a 'Map'. +asObjectMap :: + (Monad m) => + Json.ParseT err m a -> + Json.ParseT err m (Map Text a) +asObjectMap inner = Map.fromList <$> Json.eachInObject inner + +-- | Parse as json array and count the number of elements in the array. +countArrayElements :: (Monad m) => Json.ParseT Error m Natural +countArrayElements = Field.toJsonParser ((jsonArray <&> Vector.length) >>> Field.integralToNatural) + where + -- I don’t want to add this to the FieldParser module, cause users should not be dealing with arrays manually. + jsonArray :: FieldParser Json.Value (Vector Json.Value) + jsonArray = Field.FieldParser $ \case + Json.Array vec -> Right vec + _ -> Left "Not a json array" + +-- | Parse as json number and convert it to a 'Double'. Throws an error if the number does not fit into a 'Double'. +asDouble :: (Monad m) => Json.ParseT Error m Double +asDouble = + Field.toJsonParser + ( Field.jsonNumber + >>> Field.boundedScientificRealFloat @Double + ) + +asInt :: (Monad m) => Json.ParseT Error m Int +asInt = + Field.toJsonParser + ( Field.jsonNumber + >>> Field.boundedScientificIntegral @Int "Cannot parse into Int" + ) + +-- | Json string containing a UTC timestamp, +-- @yyyy-mm-ddThh:mm:ss[.sss]Z@ (ISO 8601:2004(E) sec. 4.3.2 extended format) +asUtcTime :: (Monad m) => Json.ParseT Error m UTCTime +asUtcTime = Field.toJsonParser (Field.jsonString >>> Field.utcTime) + +-- | Json string containing a UTC timestamp. +-- | Accepts multiple timezone formats. +-- Do not use this if you can force the input to use the `Z` UTC notation (e.g. in a CSV), use 'utcTime' instead. +-- +-- Accepts +-- +-- * UTC timestamps: @yyyy-mm-ddThh:mm:ss[.sss]Z@ +-- * timestamps with time zone: @yyyy-mm-ddThh:mm:ss[.sss]±hh:mm@ +-- +-- ( both ISO 8601:2004(E) sec. 4.3.2 extended format) +-- +-- The time zone of the second kind of timestamp is taken into account, but normalized to UTC (it’s not preserved what the original time zone was) +asUtcTimeLenient :: (Monad m) => Json.ParseT Error m UTCTime +asUtcTimeLenient = Field.toJsonParser (Field.jsonString >>> Field.utcTimeLenient) + +-- | Parse a key from the object, à la 'Json.key', return a labelled value. +-- +-- We don’t provide a version that infers the json object key, +-- since that conflates internal naming with the external API, which is dangerous. +-- +-- @@ +-- do +-- txt <- keyLabel @"myLabel" "jsonKeyName" Json.asText +-- pure (txt :: Label "myLabel" Text) +-- @@ +keyLabel :: + forall label err m a. + (Monad m) => + Text -> + Json.ParseT err m a -> + Json.ParseT err m (Label label a) +keyLabel = do + keyLabel' (Proxy @label) + +-- | Parse a key from the object, à la 'Json.key', return a labelled value. +-- Version of 'keyLabel' that requires a proxy. +-- +-- @@ +-- do +-- txt <- keyLabel' (Proxy @"myLabel") "jsonKeyName" Json.asText +-- pure (txt :: Label "myLabel" Text) +-- @@ +keyLabel' :: + forall label err m a. + (Monad m) => + Proxy label -> + Text -> + Json.ParseT err m a -> + Json.ParseT err m (Label label a) +keyLabel' Proxy key parser = label @label <$> Json.key key parser + +-- | Parse an optional key from the object, à la 'Json.keyMay', return a labelled value. +-- +-- We don’t provide a version that infers the json object key, +-- since that conflates internal naming with the external API, which is dangerous. +-- +-- @@ +-- do +-- txt <- keyLabelMay @"myLabel" "jsonKeyName" Json.asText +-- pure (txt :: Label "myLabel" (Maybe Text)) +-- @@ +keyLabelMay :: + forall label err m a. + (Monad m) => + Text -> + Json.ParseT err m a -> + Json.ParseT err m (Label label (Maybe a)) +keyLabelMay = do + keyLabelMay' (Proxy @label) + +-- | Parse an optional key from the object, à la 'Json.keyMay', return a labelled value. +-- Version of 'keyLabelMay' that requires a proxy. +-- +-- @@ +-- do +-- txt <- keyLabelMay' (Proxy @"myLabel") "jsonKeyName" Json.asText +-- pure (txt :: Label "myLabel" (Maybe Text)) +-- @@ +keyLabelMay' :: + forall label err m a. + (Monad m) => + Proxy label -> + Text -> + Json.ParseT err m a -> + Json.ParseT err m (Label label (Maybe a)) +keyLabelMay' Proxy key parser = label @label <$> Json.keyMay key parser + +-- NOTE: keyRenamed Test in "Json.JsonTest", due to import cycles. + +-- | Like 'Json.key', but allows a list of keys that are tried in order. +-- +-- This is intended for renaming keys in an object. +-- The first key is the most up-to-date version of a key, the others are for backward-compatibility. +-- +-- If a key (new or old) exists, the inner parser will always be executed for that key. +keyRenamed :: (Monad m) => NonEmpty Text -> Json.ParseT err m a -> Json.ParseT err m a +keyRenamed (newKey :| oldKeys) inner = + keyRenamedTryOldKeys oldKeys inner >>= \case + Nothing -> Json.key newKey inner + Just parse -> parse + +-- | Like 'Json.keyMay', but allows a list of keys that are tried in order. +-- +-- This is intended for renaming keys in an object. +-- The first key is the most up-to-date version of a key, the others are for backward-compatibility. +-- +-- If a key (new or old) exists, the inner parser will always be executed for that key. +keyRenamedMay :: (Monad m) => NonEmpty Text -> Json.ParseT err m a -> Json.ParseT err m (Maybe a) +keyRenamedMay (newKey :| oldKeys) inner = + keyRenamedTryOldKeys oldKeys inner >>= \case + Nothing -> Json.keyMay newKey inner + Just parse -> Just <$> parse + +-- | Helper function for 'keyRenamed' and 'keyRenamedMay' that returns the parser for the first old key that exists, if any. +keyRenamedTryOldKeys :: (Monad m) => [Text] -> Json.ParseT err m a -> Json.ParseT err m (Maybe (Json.ParseT err m a)) +keyRenamedTryOldKeys oldKeys inner = do + oldKeys & traverse tryOld <&> catMaybes <&> nonEmpty <&> \case + Nothing -> Nothing + Just (old :| _moreOld) -> Just old + where + tryOld key = + Json.keyMay key (pure ()) <&> \case + Just () -> Just $ Json.key key inner + Nothing -> Nothing + +-- | A simple type isomorphic to `()` that that transforms to an empty json object and parses +data EmptyObject = EmptyObject + deriving stock (Show, Eq) + +instance FromJSON EmptyObject where + -- allow any fields, as long as its an object + parseJSON = withObject "EmptyObject" (\_ -> pure EmptyObject) + +instance ToJSON EmptyObject where + toJSON EmptyObject = Object mempty + toEncoding EmptyObject = toEncoding $ Object mempty + +-- | Create a json array from a list of json values. +mkJsonArray :: [Value] -> Value +mkJsonArray xs = xs & Vector.fromList & Array diff --git a/users/Profpatsch/my-prelude/src/Json/Enc.hs b/users/Profpatsch/my-prelude/src/Json/Enc.hs new file mode 100644 index 000000000000..c7cd6e4635e0 --- /dev/null +++ b/users/Profpatsch/my-prelude/src/Json/Enc.hs @@ -0,0 +1,272 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE QuasiQuotes #-} + +module Json.Enc where + +import Data.Aeson (Encoding, Value (..)) +import Data.Aeson qualified as Json +import Data.Aeson.Encode.Pretty qualified as Aeson.Pretty +import Data.Aeson.Encoding qualified as AesonEnc +import Data.Aeson.Encoding qualified as Json.Enc +import Data.Aeson.Encoding qualified as Json.Encoding +import Data.Aeson.Key qualified as Key +import Data.Aeson.KeyMap (KeyMap) +import Data.Aeson.KeyMap qualified as KeyMap +import Data.ByteString.Base64 qualified as Base64 +import Data.ByteString.Lazy qualified as LazyBytes +import Data.Containers.ListUtils (nubOrdOn) +import Data.Int (Int64) +import Data.List qualified as List +import Data.Map.Strict qualified as Map +import Data.Scientific +import Data.String (IsString (fromString)) +import Data.Text.Lazy qualified as Lazy +import Data.Text.Lazy.Builder qualified as Text.Builder +import Data.Time qualified as Time +import Data.Time.Format.ISO8601 qualified as ISO8601 +import GHC.TypeLits (KnownSymbol, Symbol, symbolVal) +import PossehlAnalyticsPrelude + +-- | A JSON encoder. +-- +-- It is faster than going through 'Value', because 'Encoding' is just a wrapper around a @Bytes.Builder@. +-- But the @aeson@ interface for 'Encoding' is extremely bad, so let’s build a better one. +newtype Enc = Enc {unEnc :: Encoding} + deriving (Num, Fractional) via (NumLiteralOnly "Enc" Enc) + +instance Show Enc where + show e = e.unEnc & Json.Encoding.encodingToLazyByteString & bytesToTextUtf8UnsafeLazy & show + +-- | You can create an @Enc any@ that renders a json string value with @OverloadedStrings@. +instance IsString Enc where + fromString = Enc . AesonEnc.string + +-- | You can create an @Enc any@ that renders a json number value with an integer literal. +instance IntegerLiteral Enc where + integerLiteral = Enc . AesonEnc.integer + +-- | You can create an @Enc any@ that renders a json number value with an floating point literal. +-- +-- __ATTN__: Bear in mind that this will crash on repeating rationals, so only use for literals in code! +instance RationalLiteral Enc where + rationalLiteral r = Enc $ AesonEnc.scientific (r & fromRational @Scientific) + +-- | Convert an 'Enc' to a strict UTF8-bytestring which is valid JSON (minified). +encToBytesUtf8 :: Enc -> ByteString +encToBytesUtf8 enc = enc & encToBytesUtf8Lazy & toStrictBytes + +-- | Convert an 'Enc' to a lazy UTF8-bytestring which is valid JSON (minified). +encToBytesUtf8Lazy :: Enc -> LazyBytes.ByteString +encToBytesUtf8Lazy enc = enc.unEnc & Json.Enc.encodingToLazyByteString + +-- | Convert an 'Enc' to a strict Text which is valid JSON (prettyfied). +-- +-- __ATTN__: will re-parse the json through 'Json.Value', so only use for user-interactions like pretty-printing. +encToTextPretty :: Enc -> Text +encToTextPretty enc = + enc + & encToTextPrettyLazy + & toStrict + +-- | Convert an 'Enc' to a lazy Text which is valid JSON (prettyfied). +-- +-- __ATTN__: will re-parse the json through 'Json.Value', so only use for user-interactions like pretty-printing. +encToTextPrettyLazy :: Enc -> Lazy.Text +encToTextPrettyLazy enc = + enc + & encToBytesUtf8Lazy + & Json.decode @Json.Value + & annotate "the json parser can’t parse json encodings??" + & unwrapError + & Aeson.Pretty.encodePrettyToTextBuilder + & Text.Builder.toLazyText + +-- | Embed a 'Json.Encoding' verbatim (it’s a valid JSON value) +encoding :: Encoding -> Enc +encoding = Enc + +-- | Encode a 'Json.Value' verbatim (it’s a valid JSON value) +value :: Value -> Enc +value = Enc . AesonEnc.value + +-- | Encode an empty json list +emptyArray :: Enc +emptyArray = Enc AesonEnc.emptyArray_ + +-- | Encode an empty json dict +emptyObject :: Enc +emptyObject = Enc AesonEnc.emptyObject_ + +-- | Encode a 'Text' as a json string +text :: Text -> Enc +text = Enc . AesonEnc.text + +-- | Encode a lazy 'Text' as a json string +lazyText :: Lazy.Text -> Enc +lazyText = Enc . AesonEnc.lazyText + +-- | Encode a 'ByteString' as a base64-encoded json string +base64Bytes :: ByteString -> Enc +base64Bytes = Enc . AesonEnc.text . bytesToTextUtf8Unsafe . Base64.encode + +-- | Encode a 'Text' as a base64-encoded json string +base64 :: Text -> Enc +base64 = Enc . AesonEnc.text . bytesToTextUtf8Unsafe . Base64.encode . textToBytesUtf8 + +-- | Encode a 'Prelude.String' as a json string +string :: String -> Enc +string = Enc . AesonEnc.string + +-- | Encode as json @null@ if 'Nothing', else use the given encoder for @Just a@ +nullOr :: (a -> Enc) -> Maybe a -> Enc +nullOr inner = \case + Nothing -> Enc AesonEnc.null_ + Just a -> inner a + +-- | Encode a list as a json list +list :: (a -> Enc) -> [a] -> Enc +list f = Enc . AesonEnc.list (\a -> (f a).unEnc) + +-- | Encode a 'NonEmpty' as a json list. +nonEmpty :: (a -> Enc) -> NonEmpty a -> Enc +nonEmpty f = list f . toList + +-- | Encode the given list of keys and their encoders as json dict. +-- +-- If the list contains the same key multiple times, the first value in the list is retained: +-- +-- @ +-- (object [ ("foo", 42), ("foo", 23) ]) +-- ~= "{\"foo\":42}" +-- @ +object :: (Foldable t) => t (Text, Enc) -> Enc +object m = + Enc $ + AesonEnc.dict + AesonEnc.text + (\recEnc -> recEnc.unEnc) + (\f -> List.foldr (\(k, v) -> f k v)) + (nubOrdOn fst $ toList m) + +-- | A tag/value encoder; See 'choice' +data Choice = Choice Text Enc + +-- | Encode a sum type as a @Choice@, an object with a @tag@/@value@ pair, +-- which is the conventional json sum type representation in our codebase. +-- +-- @ +-- foo :: Maybe Text -> Enc +-- foo = choice $ \case +-- Nothing -> Choice "no" emptyObject () +-- Just t -> Choice "yes" text t +-- +-- ex = foo Nothing == "{\"tag\": \"no\", \"value\": {}}" +-- ex2 = foo (Just "hi") == "{\"tag\": \"yes\", \"value\": \"hi\"}" +-- @ +choice :: (from -> Choice) -> from -> Enc +choice f from = case f from of + Choice key encA -> singleChoice key encA + +-- | Like 'choice', but simply encode a single possibility into a @tag/value@ object. +-- This can be useful, but if you want to match on an enum, use 'choice' instead. +singleChoice :: Text -> Enc -> Enc +singleChoice key encA = + Enc $ + AesonEnc.pairs $ + mconcat + [ AesonEnc.pair "tag" (AesonEnc.text key), + AesonEnc.pair "value" encA.unEnc + ] + +-- | Encode a 'Map' as a json dict +-- +-- We can’t really set the key to anything but text (We don’t keep the tag of 'Encoding') +-- so instead we allow anything that’s coercible from text as map key (i.e. newtypes). +map :: forall k v. (Coercible k Text) => (v -> Enc) -> Map k v -> Enc +map valEnc m = + Enc $ + AesonEnc.dict + (AesonEnc.text . coerce @k @Text) + (\v -> (valEnc v).unEnc) + Map.foldrWithKey + m + +-- | Encode a 'KeyMap' as a json dict +keyMap :: (v -> Enc) -> KeyMap v -> Enc +keyMap valEnc m = + Enc $ + AesonEnc.dict + (AesonEnc.text . Key.toText) + (\v -> (valEnc v).unEnc) + KeyMap.foldrWithKey + m + +-- | Encode 'Json.Null' +null :: Enc +null = Enc AesonEnc.null_ + +-- | Encode a 'Prelude.Bool' as a json boolean +bool :: Bool -> Enc +bool = Enc . AesonEnc.bool + +-- | Encode an 'Integer' as a json number. +-- TODO: is it okay to just encode an arbitrarily-sized integer into json? +integer :: Integer -> Enc +integer = Enc . AesonEnc.integer + +-- | Encode a 'Scientific' as a json number. +scientific :: Scientific -> Enc +scientific = Enc . AesonEnc.scientific + +-- | Encode a 'Natural' as a json number. +natural :: Natural -> Enc +natural = integer . toInteger @Natural + +-- | Encode an 'Int' as a json number. +int :: Int -> Enc +int = Enc . AesonEnc.int + +-- | Encode an 'Int64' as a json number. +int64 :: Int64 -> Enc +int64 = Enc . AesonEnc.int64 + +-- | Encode 'Time.UTCTime' as a json string, as an ISO8601 timestamp with timezone (@yyyy-mm-ddThh:mm:ss[.sss]Z@) +utcTime :: Time.UTCTime -> Enc +utcTime = + text . stringToText . ISO8601.iso8601Show @Time.UTCTime + +-- | Implement this class if you want your type to only implement the part of 'Num' +-- that allows creating them from Integer-literals, then derive Num via 'NumLiteralOnly': +-- +-- @ +-- data Foo = Foo Integer +-- deriving (Num) via (NumLiteralOnly "Foo" Foo) +-- +-- instance IntegerLiteral Foo where +-- integerLiteral i = Foo i +-- @ +class IntegerLiteral a where + integerLiteral :: Integer -> a + +-- | The same as 'IntegerLiteral' but for floating point literals. +class RationalLiteral a where + rationalLiteral :: Rational -> a + +-- | Helper class for @deriving (Num) via …@, implements only literal syntax for integer and floating point numbers, +-- and throws descriptive runtime errors for any other methods in 'Num'. +-- +-- See 'IntegerLiteral' and 'RationalLiteral' for examples. +newtype NumLiteralOnly (sym :: Symbol) num = NumLiteralOnly num + +instance (IntegerLiteral num, KnownSymbol sym) => Num (NumLiteralOnly sym num) where + fromInteger = NumLiteralOnly . integerLiteral + (+) = error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to add (+) (NumLiteralOnly)|] + (*) = error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to multiply (*) (NumLiteralOnly)|] + (-) = error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to subtract (-) (NumLiteralOnly)|] + abs = error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to use `abs` (NumLiteralOnly)|] + signum = error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to use `signum` (NumLiteralOnly)|] + +instance (IntegerLiteral num, RationalLiteral num, KnownSymbol sym) => Fractional (NumLiteralOnly sym num) where + fromRational = NumLiteralOnly . rationalLiteral + recip = error [fmt|Only use as rational literal allowed for {symbolVal (Proxy @sym)}, you tried to use `recip` (NumLiteralOnly)|] + (/) = error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to divide (/) (NumLiteralOnly)|] diff --git a/users/Profpatsch/my-prelude/src/Postgres/Decoder.hs b/users/Profpatsch/my-prelude/src/Postgres/Decoder.hs index 008b89b4ba3d..92fe5cc7d2fe 100644 --- a/users/Profpatsch/my-prelude/src/Postgres/Decoder.hs +++ b/users/Profpatsch/my-prelude/src/Postgres/Decoder.hs @@ -8,6 +8,8 @@ import Data.Typeable (Typeable) import Database.PostgreSQL.Simple (Binary (fromBinary)) import Database.PostgreSQL.Simple.FromField qualified as PG import Database.PostgreSQL.Simple.FromRow qualified as PG +import FieldParser (FieldParser) +import FieldParser qualified as Field import Json qualified import Label import PossehlAnalyticsPrelude @@ -24,12 +26,65 @@ bytea = fromField @(Binary ByteString) <&> (.fromBinary) byteaMay :: Decoder (Maybe ByteString) byteaMay = fromField @(Maybe (Binary ByteString)) <&> fmap (.fromBinary) +-- | Parse a `text` field. +text :: Decoder Text +text = fromField @Text + +-- | Parse a nullable `text` field. +textMay :: Decoder (Maybe Text) +textMay = fromField @(Maybe Text) + +-- | Parse a `text` field, and then use a 'FieldParser' to convert the result further. +textParse :: (Typeable to) => FieldParser Text to -> Decoder to +textParse = parse @Text + +-- | Parse a nullable `text` field, and then use a 'FieldParser' to convert the result further. +textParseMay :: (Typeable to) => FieldParser Text to -> Decoder (Maybe to) +textParseMay = parseMay @Text + +-- | Parse a type implementing 'FromField', and then use a 'FieldParser' to convert the result further. +parse :: + forall from to. + ( PG.FromField from, + Typeable to + ) => + FieldParser from to -> + Decoder to +parse parser = Decoder $ PG.fieldWith $ \field bytes -> do + val <- PG.fromField @from field bytes + case Field.runFieldParser parser val of + Left err -> + PG.returnError + PG.ConversionFailed + field + (err & prettyError & textToString) + Right a -> pure a + +-- | Parse a nullable type implementing 'FromField', and then use a 'FieldParser' to convert the result further. +parseMay :: + forall from to. + ( PG.FromField from, + Typeable to + ) => + FieldParser from to -> + Decoder (Maybe to) +parseMay parser = Decoder $ PG.fieldWith $ \field bytes -> do + val <- PG.fromField @(Maybe from) field bytes + case Field.runFieldParser parser <$> val of + Nothing -> pure Nothing + Just (Left err) -> + PG.returnError + PG.ConversionFailed + field + (err & prettyError & textToString) + Just (Right a) -> pure (Just a) + -- | Turn any type that implements 'PG.fromField' into a 'Decoder'. Use type applications to prevent accidental conversions: -- -- @ -- fromField @Text :: Decoder Text -- @ -fromField :: PG.FromField a => Decoder a +fromField :: (PG.FromField a) => Decoder a fromField = Decoder $ PG.fieldWith PG.fromField -- | Turn any type that implements 'PG.fromField' into a 'Decoder' and wrap the result into the given 'Label'. Use type applications to prevent accidental conversions: @@ -37,7 +92,7 @@ fromField = Decoder $ PG.fieldWith PG.fromField -- @ -- fromField @"myField" @Text :: Decoder (Label "myField" Text) -- @ -fromFieldLabel :: forall lbl a. PG.FromField a => Decoder (Label lbl a) +fromFieldLabel :: forall lbl a. (PG.FromField a) => Decoder (Label lbl a) fromFieldLabel = label @lbl <$> fromField -- | Parse fields out of a json value returned from the database. @@ -55,7 +110,7 @@ fromFieldLabel = label @lbl <$> fromField -- -- Also note: `->>` will coerce the json value to @text@, regardless of the content. -- So the JSON object @{"foo": {}}"@ would be returned as the text: @"{\"foo\": {}}"@. -json :: Typeable a => Json.ParseT ErrorTree Identity a -> Decoder a +json :: (Typeable a) => Json.ParseT ErrorTree Identity a -> Decoder a json parser = Decoder $ PG.fieldWith $ \field bytes -> do val <- PG.fromField @Json.Value field bytes case Json.parseValue parser val of @@ -81,7 +136,7 @@ json parser = Decoder $ PG.fieldWith $ \field bytes -> do -- -- Also note: `->>` will coerce the json value to @text@, regardless of the content. -- So the JSON object @{"foo": {}}"@ would be returned as the text: @"{\"foo\": {}}"@. -jsonMay :: Typeable a => Json.ParseT ErrorTree Identity a -> Decoder (Maybe a) +jsonMay :: (Typeable a) => Json.ParseT ErrorTree Identity a -> Decoder (Maybe a) jsonMay parser = Decoder $ PG.fieldWith $ \field bytes -> do val <- PG.fromField @(Maybe Json.Value) field bytes case Json.parseValue parser <$> val of diff --git a/users/Profpatsch/my-prelude/src/Postgres/MonadPostgres.hs b/users/Profpatsch/my-prelude/src/Postgres/MonadPostgres.hs index f83a6d7fcf51..87928678a052 100644 --- a/users/Profpatsch/my-prelude/src/Postgres/MonadPostgres.hs +++ b/users/Profpatsch/my-prelude/src/Postgres/MonadPostgres.hs @@ -5,13 +5,20 @@ module Postgres.MonadPostgres where +import Arg import AtLeast (AtLeast) import Control.Exception + ( Exception (displayException), + Handler (Handler), + catches, + try, + ) import Control.Foldl qualified as Fold import Control.Monad.Logger.CallStack (MonadLogger, logDebug, logWarn) import Control.Monad.Reader (MonadReader (ask), ReaderT (..)) import Control.Monad.Trans.Resource import Data.Aeson (FromJSON) +import Data.ByteString qualified as ByteString import Data.Error.Tree import Data.HashMap.Strict qualified as HashMap import Data.Int (Int64) @@ -27,19 +34,25 @@ import Database.PostgreSQL.Simple qualified as Postgres import Database.PostgreSQL.Simple.FromRow qualified as PG import Database.PostgreSQL.Simple.ToField (ToField) import Database.PostgreSQL.Simple.ToRow (ToRow (toRow)) -import Database.PostgreSQL.Simple.Types (Query (..)) +import Database.PostgreSQL.Simple.Types (PGArray (PGArray), Query (..)) +import GHC.IO.Handle (Handle) import GHC.Records (getField) import Label +import Language.Haskell.TH.Quote (QuasiQuoter) +import OpenTelemetry.Trace.Core (NewEvent (newEventName)) import OpenTelemetry.Trace.Core qualified as Otel hiding (inSpan, inSpan') import OpenTelemetry.Trace.Monad qualified as Otel import PossehlAnalyticsPrelude import Postgres.Decoder import Postgres.Decoder qualified as Dec import Pretty (showPretty) +import PyF qualified import Seconds import System.Exit (ExitCode (..)) import Tool -import UnliftIO (MonadUnliftIO (withRunInIO)) +import UnliftIO (MonadUnliftIO (withRunInIO), bracket, hClose, mask_) +import UnliftIO.Concurrent (forkIO) +import UnliftIO.Process (ProcessHandle) import UnliftIO.Process qualified as Process import UnliftIO.Resource qualified as Resource import Prelude hiding (init, span) @@ -129,6 +142,10 @@ class (Monad m) => MonadPostgres (m :: Type -> Type) where -- Only handlers should run transactions. runTransaction :: Transaction m a -> m a +-- | Quasi-Quoter for multi-line SQL literals. Trims leading whitespace up to the least-indented line. +sql :: QuasiQuoter +sql = PyF.fmtTrim + -- | Run a query, passing parameters. Prefer 'queryWith' if possible. query :: forall m params r. @@ -353,20 +370,19 @@ addErrorInformation msg io = -- print the query that was run and the query parameters, -- then rethrow inside an 'Error'. handlePGException :: - forall a params tools m. + forall a params m. ( ToRow params, MonadUnliftIO m, - MonadLogger m, - HasField "pgFormat" tools Tool + MonadLogger m ) => - tools -> + PrettyPrintDatabaseQueries -> Text -> Query -> -- | Depending on whether we used `format` or `formatMany`. Either params (NonEmpty params) -> IO a -> Transaction m a -handlePGException tools queryType query' params io = do +handlePGException prettyQuery queryType query' params io = do withRunInIO $ \unliftIO -> io `catches` [ Handler $ unliftIO . logQueryException @SqlError, @@ -380,13 +396,14 @@ handlePGException tools queryType query' params io = do throwErr err = liftIO $ throwAsError $ prettyErrorTree $ nestedMultiError "A Postgres query failed" err logQueryException :: (Exception e) => e -> Transaction m a logQueryException exc = do - formattedQuery <- case params of - Left one -> pgFormatQuery' tools query' one - Right many -> pgFormatQueryMany' tools query' many + formattedQuery <- + case params of + Left one -> pgFormatQuery' prettyQuery query' one + Right many -> pgFormatQueryMany' prettyQuery query' many throwErr ( singleError [fmt|Query Type: {queryType}|] :| [ nestedError "Exception" (exc & showPretty & newError & singleError), - nestedError "Query" (formattedQuery & newError & singleError) + nestedError "Query" (formattedQuery & bytesToTextUtf8Lenient & newError & singleError) ] ) logFormatException :: FormatError -> Transaction m a @@ -405,6 +422,104 @@ withPGTransaction connPool f = connPool (\conn -> Postgres.withTransaction conn (f conn)) +-- | `pg_formatter` is a perl script that does not support any kind of streaming. +-- Thus we initialize a pool with a bunch of these scripts running, waiting for input. This way we can have somewhat fast SQL formatting. +-- +-- Call `initPgFormatPool` to initialize, then use `runPgFormat` to format some sql. +data PgFormatPool = PgFormatPool + { pool :: Pool PgFormatProcess, + pgFormat :: Tool + } + +data PgFormatProcess = PgFormatProcess + { stdinHdl :: Handle, + stdoutHdl :: Handle, + stderrHdl :: Handle, + procHdl :: ProcessHandle, + startedAt :: Otel.Timestamp + } + +initPgFormatPool :: (HasField "pgFormat" tools Tool) => tools -> IO PgFormatPool +initPgFormatPool tools = do + pool <- + Pool.newPool + ( Pool.defaultPoolConfig + (pgFormatStartCommandWaitForInput tools) + ( \pgFmt -> do + Process.terminateProcess pgFmt.procHdl + -- make sure we don’t leave any zombies + _ <- forkIO $ do + _ <- Process.waitForProcess pgFmt.procHdl + pure () + pure () + ) + -- unused resource time + 100 + -- number of resources + 10 + ) + + -- fill the pool with resources + let go = + Pool.tryWithResource pool (\_ -> go) >>= \case + Nothing -> pure () + Just () -> pure () + _ <- go + pure (PgFormatPool {pool, pgFormat = tools.pgFormat}) + +destroyPgFormatPool :: PgFormatPool -> IO () +destroyPgFormatPool pool = Pool.destroyAllResources pool.pool + +-- | Get the oldest resource from the pool, or stop if you find a resource that’s older than `cutoffPointMs`. +takeOldestResource :: PgFormatPool -> Arg "cutoffPointMs" Integer -> IO (PgFormatProcess, Pool.LocalPool PgFormatProcess) +takeOldestResource pool cutoffPointMs = do + now <- Otel.getTimestamp + mask_ $ do + a <- Pool.takeResource pool.pool + (putBack, res) <- go now [] a + -- make sure we don’t leak any resources we didn’t use in the end + for_ putBack $ \(x, xLocal) -> Pool.putResource xLocal x + pure res + where + mkMs ts = (ts & Otel.timestampNanoseconds & toInteger) `div` 1000_000 + go now putBack a@(a', _) = + if abs (mkMs now - mkMs a'.startedAt) > cutoffPointMs.unArg + then pure (putBack, a) + else + Pool.tryTakeResource pool.pool >>= \case + Nothing -> pure (putBack, a) + Just b@(b', _) -> do + if a'.startedAt < b'.startedAt + then go now (b : putBack) a + else go now (a : putBack) b + +-- | Format the given SQL with pg_formatter. Will use the pool of already running formatters to speed up execution. +runPgFormat :: PgFormatPool -> ByteString -> IO (T3 "exitCode" ExitCode "formatted" ByteString "stderr" ByteString) +runPgFormat pool sqlStatement = do + bracket + (takeOldestResource pool 200) + ( \(a, localPool) -> do + -- we always destroy the resource, because the process exited + Pool.destroyResource pool.pool localPool a + -- create a new process to keep the pool “warm†+ new <- pgFormatStartCommandWaitForInput pool + Pool.putResource localPool new + ) + ( \(pgFmt, _localPool) -> do + ByteString.hPut pgFmt.stdinHdl sqlStatement + -- close stdin to make pg_formatter format (it exits …) + -- issue: https://github.com/darold/pgFormatter/issues/333 + hClose pgFmt.stdinHdl + formatted <- ByteString.hGetContents pgFmt.stdoutHdl + errs <- ByteString.hGetContents pgFmt.stderrHdl + exitCode <- Process.waitForProcess pgFmt.procHdl + pure $ + T3 + (label @"exitCode" exitCode) + (label @"formatted" formatted) + (label @"stderr" errs) + ) + runPGTransactionImpl :: (MonadUnliftIO m) => m (Pool Postgres.Connection) -> @@ -418,55 +533,52 @@ runPGTransactionImpl zoom (Transaction transaction) = do unliftIO $ runReaderT transaction conn executeImpl :: - (ToRow params, MonadUnliftIO m, MonadLogger m, HasField "pgFormat" tools Tool, Otel.MonadTracer m) => - m tools -> - m DebugLogDatabaseQueries -> + (ToRow params, MonadUnliftIO m, MonadLogger m, Otel.MonadTracer m) => + m (DebugLogDatabaseQueries, PrettyPrintDatabaseQueries) -> Query -> params -> Transaction m (Label "numberOfRowsAffected" Natural) {-# INLINE executeImpl #-} -executeImpl zoomTools zoomDebugLogDatabaseQueries qry params = +executeImpl zoomDbOptions qry params = Otel.inSpan' "Postgres Query (execute)" Otel.defaultSpanArguments $ \span -> do - tools <- lift @Transaction zoomTools - logDatabaseQueries <- lift @Transaction zoomDebugLogDatabaseQueries - traceQueryIfEnabled tools span logDatabaseQueries qry (HasSingleParam params) + (logDatabaseQueries, prettyQuery) <- lift @Transaction zoomDbOptions + traceQueryIfEnabled span logDatabaseQueries prettyQuery qry (HasSingleParam params) conn <- Transaction ask PG.execute conn qry params - & handlePGException tools "execute" qry (Left params) + & handlePGException prettyQuery "execute" qry (Left params) >>= toNumberOfRowsAffected "executeImpl" executeImpl_ :: - (MonadUnliftIO m, MonadLogger m, HasField "pgFormat" tools Tool, Otel.MonadTracer m) => - m tools -> - m DebugLogDatabaseQueries -> + ( MonadUnliftIO m, + MonadLogger m, + Otel.MonadTracer m + ) => + m (DebugLogDatabaseQueries, PrettyPrintDatabaseQueries) -> Query -> Transaction m (Label "numberOfRowsAffected" Natural) {-# INLINE executeImpl_ #-} -executeImpl_ zoomTools zoomDebugLogDatabaseQueries qry = +executeImpl_ zoomDbOptions qry = Otel.inSpan' "Postgres Query (execute)" Otel.defaultSpanArguments $ \span -> do - tools <- lift @Transaction zoomTools - logDatabaseQueries <- lift @Transaction zoomDebugLogDatabaseQueries - traceQueryIfEnabled @() tools span logDatabaseQueries qry HasNoParams + (logDatabaseQueries, prettyQuery) <- lift @Transaction zoomDbOptions + traceQueryIfEnabled @() span logDatabaseQueries prettyQuery qry HasNoParams conn <- Transaction ask PG.execute_ conn qry - & handlePGException tools "execute_" qry (Left ()) + & handlePGException prettyQuery "execute_" qry (Left ()) >>= toNumberOfRowsAffected "executeImpl_" executeManyImpl :: - (ToRow params, MonadUnliftIO m, MonadLogger m, HasField "pgFormat" tools Tool, Otel.MonadTracer m) => - m tools -> - m DebugLogDatabaseQueries -> + (ToRow params, MonadUnliftIO m, MonadLogger m, Otel.MonadTracer m) => + m (DebugLogDatabaseQueries, PrettyPrintDatabaseQueries) -> Query -> NonEmpty params -> Transaction m (Label "numberOfRowsAffected" Natural) -executeManyImpl zoomTools zoomDebugLogDatabaseQueries qry params = - Otel.inSpan' "Postgres Query (execute)" Otel.defaultSpanArguments $ \span -> do - tools <- lift @Transaction zoomTools - logDatabaseQueries <- lift @Transaction zoomDebugLogDatabaseQueries - traceQueryIfEnabled tools span logDatabaseQueries qry (HasMultiParams params) +executeManyImpl zoomDbOptions qry params = + Otel.inSpan' "Postgres Query (executeMany)" Otel.defaultSpanArguments $ \span -> do + (logDatabaseQueries, prettyQuery) <- lift @Transaction zoomDbOptions + traceQueryIfEnabled span logDatabaseQueries prettyQuery qry (HasMultiParams params) conn <- Transaction ask PG.executeMany conn qry (params & toList) - & handlePGException tools "executeMany" qry (Right params) + & handlePGException prettyQuery "executeMany" qry (Right params) >>= toNumberOfRowsAffected "executeManyImpl" toNumberOfRowsAffected :: (MonadIO m) => Text -> Int64 -> m (Label "numberOfRowsAffected" Natural) @@ -480,32 +592,32 @@ toNumberOfRowsAffected functionName i64 = <&> label @"numberOfRowsAffected" executeManyReturningWithImpl :: - (ToRow params, MonadUnliftIO m, MonadLogger m, HasField "pgFormat" tools Tool, Otel.MonadTracer m) => - m tools -> - m DebugLogDatabaseQueries -> + ( ToRow params, + MonadUnliftIO m, + MonadLogger m, + Otel.MonadTracer m + ) => + m (DebugLogDatabaseQueries, PrettyPrintDatabaseQueries) -> Query -> NonEmpty params -> Decoder r -> Transaction m [r] {-# INLINE executeManyReturningWithImpl #-} -executeManyReturningWithImpl zoomTools zoomDebugLogDatabaseQueries qry params (Decoder fromRow) = do - Otel.inSpan' "Postgres Query (execute)" Otel.defaultSpanArguments $ \span -> do - tools <- lift @Transaction zoomTools - logDatabaseQueries <- lift @Transaction zoomDebugLogDatabaseQueries - traceQueryIfEnabled tools span logDatabaseQueries qry (HasMultiParams params) +executeManyReturningWithImpl zoomDbOptions qry params (Decoder fromRow) = do + Otel.inSpan' "Postgres Query (executeManyReturning)" Otel.defaultSpanArguments $ \span -> do + (logDatabaseQueries, prettyQuery) <- lift @Transaction zoomDbOptions + traceQueryIfEnabled span logDatabaseQueries prettyQuery qry (HasMultiParams params) conn <- Transaction ask PG.returningWith fromRow conn qry (params & toList) - & handlePGException tools "executeManyReturning" qry (Right params) + & handlePGException prettyQuery "executeManyReturning" qry (Right params) foldRowsWithAccImpl :: ( ToRow params, MonadUnliftIO m, MonadLogger m, - HasField "pgFormat" tools Tool, Otel.MonadTracer m ) => - m tools -> - m DebugLogDatabaseQueries -> + m (DebugLogDatabaseQueries, PrettyPrintDatabaseQueries) -> Query -> params -> Decoder row -> @@ -513,11 +625,10 @@ foldRowsWithAccImpl :: (a -> row -> Transaction m a) -> Transaction m a {-# INLINE foldRowsWithAccImpl #-} -foldRowsWithAccImpl zoomTools zoomDebugLogDatabaseQueries qry params (Decoder rowParser) accumulator f = do +foldRowsWithAccImpl zoomDbOptions qry params (Decoder rowParser) accumulator f = do Otel.inSpan' "Postgres Query (foldRowsWithAcc)" Otel.defaultSpanArguments $ \span -> do - tools <- lift @Transaction zoomTools - logDatabaseQueries <- lift @Transaction zoomDebugLogDatabaseQueries - traceQueryIfEnabled tools span logDatabaseQueries qry (HasSingleParam params) + (logDatabaseQueries, prettyQuery) <- lift @Transaction zoomDbOptions + traceQueryIfEnabled span logDatabaseQueries prettyQuery qry (HasSingleParam params) conn <- Transaction ask withRunInIO ( \runInIO -> @@ -530,17 +641,18 @@ foldRowsWithAccImpl zoomTools zoomDebugLogDatabaseQueries qry params (Decoder ro params accumulator (\acc row -> runInIO $ f acc row) - & handlePGException tools "fold" qry (Left params) + & handlePGException prettyQuery "fold" qry (Left params) & runInIO ) pgFormatQueryNoParams' :: - (MonadIO m, MonadLogger m, HasField "pgFormat" tools Tool) => - tools -> + (MonadIO m, MonadLogger m) => + PrettyPrintDatabaseQueries -> Query -> - Transaction m Text -pgFormatQueryNoParams' tools q = - lift $ pgFormatQueryByteString tools q.fromQuery + Transaction m ByteString +pgFormatQueryNoParams' prettyQuery q = case prettyQuery of + DontPrettyPrintDatabaseQueries -> pure q.fromQuery + PrettyPrintDatabaseQueries pool -> lift $ pgFormatQueryByteString pool q.fromQuery pgFormatQuery :: (ToRow params, MonadIO m) => @@ -571,40 +683,36 @@ queryWithImpl :: ( ToRow params, MonadUnliftIO m, MonadLogger m, - HasField "pgFormat" tools Tool, Otel.MonadTracer m ) => - m tools -> - m DebugLogDatabaseQueries -> + m (DebugLogDatabaseQueries, PrettyPrintDatabaseQueries) -> Query -> params -> Decoder r -> Transaction m [r] {-# INLINE queryWithImpl #-} -queryWithImpl zoomTools zoomDebugLogDatabaseQueries qry params (Decoder fromRow) = do - Otel.inSpan' "Postgres Query (execute)" Otel.defaultSpanArguments $ \span -> do - tools <- lift @Transaction zoomTools - logDatabaseQueries <- lift @Transaction zoomDebugLogDatabaseQueries - traceQueryIfEnabled tools span logDatabaseQueries qry (HasSingleParam params) +queryWithImpl zoomDbOptions qry params (Decoder fromRow) = do + Otel.inSpan' "Postgres Query (queryWith)" Otel.defaultSpanArguments $ \span -> do + (logDatabaseQueries, prettyQuery) <- lift @Transaction zoomDbOptions + traceQueryIfEnabled span logDatabaseQueries prettyQuery qry (HasSingleParam params) conn <- Transaction ask PG.queryWith fromRow conn qry params - & handlePGException tools "query" qry (Left params) + & handlePGException prettyQuery "query" qry (Left params) queryWithImpl_ :: ( MonadUnliftIO m, - MonadLogger m, - HasField "pgFormat" tools Tool + MonadLogger m ) => - m tools -> + m PrettyPrintDatabaseQueries -> Query -> Decoder r -> Transaction m [r] {-# INLINE queryWithImpl_ #-} -queryWithImpl_ zoomTools qry (Decoder fromRow) = do - tools <- lift @Transaction zoomTools +queryWithImpl_ zoomDbOptions qry (Decoder fromRow) = do + prettyQuery <- lift @Transaction zoomDbOptions conn <- Transaction ask liftIO (PG.queryWith_ fromRow conn qry) - & handlePGException tools "query" qry (Left ()) + & handlePGException prettyQuery "query" qry (Left ()) data SingleRowError = SingleRowError { -- | How many columns were actually returned by the query @@ -618,30 +726,32 @@ instance Exception SingleRowError where pgFormatQuery' :: ( MonadIO m, ToRow params, - MonadLogger m, - HasField "pgFormat" tools Tool + MonadLogger m ) => - tools -> + PrettyPrintDatabaseQueries -> Query -> params -> - Transaction m Text -pgFormatQuery' tools q p = - pgFormatQuery q p - >>= lift . pgFormatQueryByteString tools + Transaction m ByteString +pgFormatQuery' prettyQuery q p = case prettyQuery of + DontPrettyPrintDatabaseQueries -> pgFormatQuery q p + PrettyPrintDatabaseQueries pool -> + pgFormatQuery q p + >>= lift . pgFormatQueryByteString pool pgFormatQueryMany' :: ( MonadIO m, ToRow params, - MonadLogger m, - HasField "pgFormat" tools Tool + MonadLogger m ) => - tools -> + PrettyPrintDatabaseQueries -> Query -> NonEmpty params -> - Transaction m Text -pgFormatQueryMany' tools q p = - pgFormatQueryMany q p - >>= lift . pgFormatQueryByteString tools + Transaction m ByteString +pgFormatQueryMany' prettyQuery q p = case prettyQuery of + DontPrettyPrintDatabaseQueries -> pgFormatQueryMany q p + PrettyPrintDatabaseQueries pool -> + pgFormatQueryMany q p + >>= lift . pgFormatQueryByteString pool -- | Read the executable name "pg_format" postgresToolsParser :: ToolParserT IO (Label "pgFormat" Tool) @@ -649,34 +759,58 @@ postgresToolsParser = label @"pgFormat" <$> readTool "pg_format" pgFormatQueryByteString :: ( MonadIO m, - MonadLogger m, - HasField "pgFormat" tools Tool + MonadLogger m ) => - tools -> + PgFormatPool -> ByteString -> - m Text -pgFormatQueryByteString tools queryBytes = do + m ByteString +pgFormatQueryByteString pool queryBytes = do + res <- + liftIO $ + runPgFormat + pool + (queryBytes) + case res.exitCode of + ExitSuccess -> pure (res.formatted) + ExitFailure status -> do + logWarn [fmt|pg_format failed with status {status} while formatting the query, using original query string. Is there a syntax error?|] + logDebug + ( prettyErrorTree + ( nestedMultiError + "pg_format output" + ( nestedError "stdout" (singleError (res.formatted & bytesToTextUtf8Lenient & newError)) + :| [(nestedError "stderr" (singleError (res.stderr & bytesToTextUtf8Lenient & newError)))] + ) + ) + ) + logDebug [fmt|pg_format stdout: stderr|] + pure (queryBytes) + +pgFormatStartCommandWaitForInput :: + ( MonadIO m, + HasField "pgFormat" tools Tool, + MonadFail m + ) => + tools -> + m PgFormatProcess +pgFormatStartCommandWaitForInput tools = do do - (exitCode, stdout, stderr) <- - Process.readProcessWithExitCode - tools.pgFormat.toolPath - ["-"] - (queryBytes & bytesToTextUtf8Lenient & textToString) - case exitCode of - ExitSuccess -> pure (stdout & stringToText) - ExitFailure status -> do - logWarn [fmt|pg_format failed with status {status} while formatting the query, using original query string. Is there a syntax error?|] - logDebug - ( prettyErrorTree - ( nestedMultiError - "pg_format output" - ( nestedError "stdout" (singleError (stdout & stringToText & newError)) - :| [(nestedError "stderr" (singleError (stderr & stringToText & newError)))] - ) - ) + startedAt <- Otel.getTimestamp + (Just stdinHdl, Just stdoutHdl, Just stderrHdl, procHdl) <- + Process.createProcess + ( ( Process.proc + tools.pgFormat.toolPath + [ "--no-rcfile", + "-" + ] ) - logDebug [fmt|pg_format stdout: stderr|] - pure (queryBytes & bytesToTextUtf8Lenient) + { Process.std_in = Process.CreatePipe, + Process.std_out = Process.CreatePipe, + Process.std_err = Process.CreatePipe + } + ) + + pure PgFormatProcess {..} data DebugLogDatabaseQueries = -- | Do not log the database queries @@ -687,6 +821,17 @@ data DebugLogDatabaseQueries LogDatabaseQueriesAndExplain deriving stock (Show, Enum, Bounded) +-- | Whether to pipe database queries thru `pg_format` before logging them. This takes a long (long! 200ms+) time per query, so should only be used in debugging environments where speed is not an issue. +data PrettyPrintDatabaseQueries + = -- | Do not pretty-print database querios + DontPrettyPrintDatabaseQueries + | -- | Pretty-print database queries, slow + PrettyPrintDatabaseQueries PgFormatPool + +instance Show PrettyPrintDatabaseQueries where + show DontPrettyPrintDatabaseQueries = "DontPrettyPrintDatabaseQueries" + show (PrettyPrintDatabaseQueries _) = "PrettyPrintDatabaseQueries" + data HasQueryParams param = HasNoParams | HasSingleParam param @@ -697,43 +842,47 @@ traceQueryIfEnabled :: ( ToRow params, MonadUnliftIO m, MonadLogger m, - HasField "pgFormat" tools Tool, Otel.MonadTracer m ) => - tools -> Otel.Span -> DebugLogDatabaseQueries -> + PrettyPrintDatabaseQueries -> Query -> HasQueryParams params -> Transaction m () -traceQueryIfEnabled tools span logDatabaseQueries qry params = do +traceQueryIfEnabled span logDatabaseQueries prettyQuery qry params = do -- In case we have query logging enabled, we want to do that - let formattedQuery = case params of - HasNoParams -> pgFormatQueryNoParams' tools qry - HasSingleParam p -> pgFormatQuery' tools qry p - HasMultiParams ps -> pgFormatQueryMany' tools qry ps + let formattedQuery = + withEvent + span + "Query Format start" + "Query Format end" + $ case params of + HasNoParams -> pgFormatQueryNoParams' prettyQuery qry + HasSingleParam p -> pgFormatQuery' prettyQuery qry p + HasMultiParams ps -> pgFormatQueryMany' prettyQuery qry ps + let doLog errs = Otel.addAttributes span $ HashMap.fromList - $ ( ("_.postgres.query", Otel.toAttribute @Text errs.query) + $ ( ("_.postgres.query", Otel.toAttribute @Text (errs.query & bytesToTextUtf8Lenient)) : ( errs.explain - & foldMap - ( \ex -> - [("_.postgres.explain", Otel.toAttribute @Text ex)] - ) + & \case + Nothing -> [] + Just ex -> [("_.postgres.explain", Otel.toAttribute @Text ex)] ) ) let doExplain = do q <- formattedQuery Otel.inSpan "Postgres EXPLAIN Query" Otel.defaultSpanArguments $ do queryWithImpl_ - (pure tools) + (pure prettyQuery) ( "EXPLAIN " <> ( -- TODO: this is not nice, but the only way to get the `executeMany` form to work with this -- because we need the query with all elements already interpolated. - Query (q & textToBytesUtf8) + Query q ) ) (Dec.fromField @Text) @@ -750,6 +899,101 @@ traceQueryIfEnabled tools span logDatabaseQueries qry params = do ex <- doExplain doLog (T2 (label @"query" q) (label @"explain" (Just ex))) +-- | Add a start and end event to the span, and figure out how long the difference was. +-- +-- This is more lightweight than starting an extra span for timing things. +withEvent :: (MonadIO f) => Otel.Span -> Text -> Text -> f b -> f b +withEvent span start end act = do + let mkMs ts = (ts & Otel.timestampNanoseconds & toInteger) `div` 1000_000 + s <- Otel.getTimestamp + Otel.addEvent + span + ( Otel.NewEvent + { newEventName = start, + newEventAttributes = mempty, + newEventTimestamp = Just s + } + ) + res <- act + e <- Otel.getTimestamp + let tookMs = + (mkMs e - mkMs s) + -- should be small enough + & fromInteger @Int + Otel.addEvent + span + ( Otel.NewEvent + { newEventName = end, + newEventAttributes = HashMap.fromList [("took ms", Otel.toAttribute tookMs)], + newEventTimestamp = Just e + } + ) + pure res + +unzipPGArray :: + forall l1 t1 l2 t2 r. + ( HasField l1 r t1, + HasField l2 r t2 + ) => + [r] -> + (PGArray t1, PGArray t2) +{-# INLINEABLE unzipPGArray #-} +unzipPGArray xs = + ( PGArray $ getField @l1 <$> xs, + PGArray $ getField @l2 <$> xs + ) + +unzip3PGArray :: + forall l1 t1 l2 t2 l3 t3 r. + ( HasField l1 r t1, + HasField l2 r t2, + HasField l3 r t3 + ) => + [r] -> + (PGArray t1, PGArray t2, PGArray t3) +{-# INLINEABLE unzip3PGArray #-} +unzip3PGArray xs = + ( PGArray $ getField @l1 <$> xs, + PGArray $ getField @l2 <$> xs, + PGArray $ getField @l3 <$> xs + ) + +unzip4PGArray :: + forall l1 t1 l2 t2 l3 t3 l4 t4 r. + ( HasField l1 r t1, + HasField l2 r t2, + HasField l3 r t3, + HasField l4 r t4 + ) => + [r] -> + (PGArray t1, PGArray t2, PGArray t3, PGArray t4) +{-# INLINEABLE unzip4PGArray #-} +unzip4PGArray xs = + ( PGArray $ getField @l1 <$> xs, + PGArray $ getField @l2 <$> xs, + PGArray $ getField @l3 <$> xs, + PGArray $ getField @l4 <$> xs + ) + +unzip5PGArray :: + forall l1 t1 l2 t2 l3 t3 l4 t4 l5 t5 r. + ( HasField l1 r t1, + HasField l2 r t2, + HasField l3 r t3, + HasField l4 r t4, + HasField l5 r t5 + ) => + [r] -> + (PGArray t1, PGArray t2, PGArray t3, PGArray t4, PGArray t5) +{-# INLINEABLE unzip5PGArray #-} +unzip5PGArray xs = + ( PGArray $ getField @l1 <$> xs, + PGArray $ getField @l2 <$> xs, + PGArray $ getField @l3 <$> xs, + PGArray $ getField @l4 <$> xs, + PGArray $ getField @l5 <$> xs + ) + instance (ToField t1) => ToRow (Label l1 t1) where toRow t2 = toRow $ PG.Only $ getField @l1 t2 diff --git a/users/Profpatsch/my-prelude/src/Pretty.hs b/users/Profpatsch/my-prelude/src/Pretty.hs index d9d4ce132b11..6711ea951a48 100644 --- a/users/Profpatsch/my-prelude/src/Pretty.hs +++ b/users/Profpatsch/my-prelude/src/Pretty.hs @@ -8,6 +8,7 @@ module Pretty printShowedStringPretty, -- constructors hidden prettyErrs, + prettyErrsNoColor, message, messageString, pretty, @@ -19,6 +20,7 @@ where import Data.Aeson qualified as Json import Data.Aeson.Encode.Pretty qualified as Aeson.Pretty import Data.List qualified as List +import Data.String (IsString (fromString)) import Data.Text.Lazy.Builder qualified as Text.Builder import Language.Haskell.HsColour ( Output (TTYg), @@ -62,7 +64,6 @@ showPrettyJson val = & toStrict -- | Display a list of 'Err's as a colored error message --- and abort the test. prettyErrs :: [Err] -> String prettyErrs errs = res where @@ -74,6 +75,15 @@ prettyErrs errs = res prettyShowString :: String -> String prettyShowString = hscolour' . nicify +-- | Display a list of 'Err's as a plain-colored error message +prettyErrsNoColor :: [Err] -> String +prettyErrsNoColor errs = res + where + res = List.intercalate "\n" $ map one errs + one = \case + ErrMsg s -> s + ErrPrettyString s -> nicify s + -- | Small DSL for pretty-printing errors data Err = -- | Message to display in the error @@ -81,6 +91,9 @@ data Err | -- | Pretty print a String that was produced by 'show' ErrPrettyString String +instance IsString Err where + fromString s = ErrMsg s + -- | Plain message to display, as 'Text' message :: Text -> Err message = ErrMsg . textToString diff --git a/users/Profpatsch/nix-home/default.nix b/users/Profpatsch/nix-home/default.nix index ee154c549a6b..6d5de19aedcd 100644 --- a/users/Profpatsch/nix-home/default.nix +++ b/users/Profpatsch/nix-home/default.nix @@ -158,7 +158,6 @@ let name = "scripts/lw"; path = depot.users.Profpatsch.lorri-wait-for-eval; } - ] ++ (lib.pipe depot.users.Profpatsch.aliases [ diff --git a/users/Profpatsch/openlab-tools/default.nix b/users/Profpatsch/openlab-tools/default.nix index 82641989f7a0..0c5a70a9a668 100644 --- a/users/Profpatsch/openlab-tools/default.nix +++ b/users/Profpatsch/openlab-tools/default.nix @@ -18,7 +18,6 @@ let depot.users.Profpatsch.my-webstuff pkgs.haskellPackages.pa-prelude pkgs.haskellPackages.pa-label - pkgs.haskellPackages.pa-json pkgs.haskellPackages.pa-error-tree pkgs.haskellPackages.pa-field-parser pkgs.haskellPackages.pa-run-command diff --git a/users/Profpatsch/openlab-tools/openlab-tools.cabal b/users/Profpatsch/openlab-tools/openlab-tools.cabal index b7d217e051a9..e8f7e8bc1db3 100644 --- a/users/Profpatsch/openlab-tools/openlab-tools.cabal +++ b/users/Profpatsch/openlab-tools/openlab-tools.cabal @@ -67,7 +67,6 @@ library pa-prelude, pa-error-tree, pa-label, - pa-json, pa-field-parser, pa-run-command, aeson-better-errors, diff --git a/users/Profpatsch/openlab-tools/src/OpenlabTools.hs b/users/Profpatsch/openlab-tools/src/OpenlabTools.hs index 9fe51aba1885..7ba52c30229d 100644 --- a/users/Profpatsch/openlab-tools/src/OpenlabTools.hs +++ b/users/Profpatsch/openlab-tools/src/OpenlabTools.hs @@ -151,12 +151,12 @@ runApp = withTracer $ \tracer -> do ) ] if - -- If the last cache update is newer or equal to the requested version, we can tell the browser it’s fine - | Just modifiedSince <- req'.ifModifiedSince, - modifiedSince >= new.lastModified -> - pure $ Wai.responseLBS Http.status304 cacheToHeaders "" - | otherwise -> - pure $ h cacheToHeaders (new.result & toLazyBytes) + -- If the last cache update is newer or equal to the requested version, we can tell the browser it’s fine + | Just modifiedSince <- req'.ifModifiedSince, + modifiedSince >= new.lastModified -> + pure $ Wai.responseLBS Http.status304 cacheToHeaders "" + | otherwise -> + pure $ h cacheToHeaders (new.result & toLazyBytes) ) } ] @@ -198,7 +198,7 @@ runApp = withTracer $ \tracer -> do (Parse.maybe $ Parse.fieldParser parseHeaderTime) & rmap (fmap mkSecondTime) -parseRequest :: (MonadThrow f, MonadIO f) => Otel.Span -> Parse from a -> from -> f a +parseRequest :: (MonadThrow f) => Otel.Span -> Parse from a -> from -> f a parseRequest span parser req = Parse.runParse "Unable to parse the HTTP request" parser req & assertM span id @@ -220,9 +220,9 @@ heatmap = do t & firstSection (match (Soup.TagOpen ("") [("class", "heatmap")])) >>= firstSection (match (Soup.TagOpen "table" [])) - <&> getTable - <&> (<> htmlToTags [hsx|<figcaption>source: <a href={mapallSpaceOla} target="_blank">mapall.space</a></figcaption>|]) - <&> wrapTagStream (T2 (label @"el" "figure") (label @"attrs" [])) + <&> getTable + <&> (<> htmlToTags [hsx|<figcaption>source: <a href={mapallSpaceOla} target="_blank">mapall.space</a></figcaption>|]) + <&> wrapTagStream (T2 (label @"el" "figure") (label @"attrs" [])) -- get the table from opening tag to closing tag (allowing nested tables) getTable = go 0 @@ -310,8 +310,8 @@ runHandlers runApplication handlers = do inSpan :: (MonadUnliftIO m, Otel.MonadTracer m) => Text -> m a -> m a inSpan name = Otel.inSpan name Otel.defaultSpanArguments -inSpan' :: (MonadUnliftIO m, Otel.MonadTracer m) => Text -> (Otel.Span -> m a) -> m a --- inSpan' name = Otel.inSpan' name Otel.defaultSpanArguments +inSpan' :: Text -> (Otel.Span -> m a) -> m a +-- inSpan' name = Otel.inSpan' name Otel.defaultSpanArguments inSpan' _name act = act (error "todo telemetry disabled") zipT2 :: @@ -379,17 +379,17 @@ httpJson opts span parser req = do <&> Wai.parseContentType <&> (\(ct, _mimeAttributes) -> ct) if - | statusCode == 200, - Just ct <- contentType, - ct == opts'.contentType -> - Right $ (resp & Http.responseBody) - | statusCode == 200, - Just otherType <- contentType -> - Left [fmt|Server returned a non-json body, with content-type "{otherType}"|] - | statusCode == 200, - Nothing <- contentType -> - Left [fmt|Server returned a body with unspecified content type|] - | code <- statusCode -> Left [fmt|Server returned an non-200 error code, code {code}: {resp & showPretty}|] + | statusCode == 200, + Just ct <- contentType, + ct == opts'.contentType -> + Right $ (resp & Http.responseBody) + | statusCode == 200, + Just otherType <- contentType -> + Left [fmt|Server returned a non-json body, with content-type "{otherType}"|] + | statusCode == 200, + Nothing <- contentType -> + Left [fmt|Server returned a body with unspecified content type|] + | code <- statusCode -> Left $ singleError [fmt|Server returned an non-200 error code, code {code}: {[pretty resp] & prettyErrsNoColor}|] ) >>= assertM span @@ -398,7 +398,7 @@ httpJson opts span parser req = do & first (Json.parseErrorTree "could not parse redacted response") ) -assertM :: (MonadThrow f, MonadIO f) => Otel.Span -> (t -> Either ErrorTree a) -> t -> f a +assertM :: (MonadThrow f) => Otel.Span -> (t -> Either ErrorTree a) -> t -> f a assertM span f v = case f v of Right a -> pure a Left err -> appThrowTree span err @@ -419,7 +419,7 @@ data Cache a = Cache lastModified :: !SecondTime, result :: !a } - deriving (Show) + deriving stock (Show) newCache :: Text -> a -> IO (TVar (Cache a)) newCache name result = do @@ -528,8 +528,8 @@ recordException span dat = liftIO $ do .. } -appThrowTree :: (MonadThrow m, MonadIO m) => Otel.Span -> ErrorTree -> m a -appThrowTree span exc = do +appThrowTree :: (MonadThrow m) => Otel.Span -> ErrorTree -> m a +appThrowTree _span exc = do let msg = prettyErrorTree exc -- recordException -- span @@ -539,7 +539,7 @@ appThrowTree span exc = do -- ) throwM $ AppException msg -orAppThrowTree :: (MonadThrow m, MonadIO m) => Otel.Span -> Either ErrorTree a -> m a +orAppThrowTree :: (MonadThrow m) => Otel.Span -> Either ErrorTree a -> m a orAppThrowTree span = \case Left err -> appThrowTree span err Right a -> pure a diff --git a/users/Profpatsch/package.json b/users/Profpatsch/package.json new file mode 100644 index 000000000000..42bbc52ebfdf --- /dev/null +++ b/users/Profpatsch/package.json @@ -0,0 +1,17 @@ +{ + "name": "profpatsch", + "version": "1.0.0", + "description": "Welcome, Welcome.", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "MIT", + "devDependencies": { + "@eslint/js": "^9.11.1", + "@types/eslint__js": "^8.42.3", + "@typescript-eslint/parser": "^8.8.0", + "eslint": "^9.11.1", + "typescript-eslint": "^8.8.0" + } +} diff --git a/users/Profpatsch/ical-smolify/IcalSmolify.hs b/users/Profpatsch/parked/ical-smolify/IcalSmolify.hs index 77264d16937e..77264d16937e 100644 --- a/users/Profpatsch/ical-smolify/IcalSmolify.hs +++ b/users/Profpatsch/parked/ical-smolify/IcalSmolify.hs diff --git a/users/Profpatsch/ical-smolify/README.md b/users/Profpatsch/parked/ical-smolify/README.md index 86c166d3c179..86c166d3c179 100644 --- a/users/Profpatsch/ical-smolify/README.md +++ b/users/Profpatsch/parked/ical-smolify/README.md diff --git a/users/Profpatsch/ical-smolify/default.nix b/users/Profpatsch/parked/ical-smolify/default.nix.inactive index bf766db0e974..bf766db0e974 100644 --- a/users/Profpatsch/ical-smolify/default.nix +++ b/users/Profpatsch/parked/ical-smolify/default.nix.inactive diff --git a/users/Profpatsch/ical-smolify/ical-smolify.cabal b/users/Profpatsch/parked/ical-smolify/ical-smolify.cabal index d7a46c581df2..d7a46c581df2 100644 --- a/users/Profpatsch/ical-smolify/ical-smolify.cabal +++ b/users/Profpatsch/parked/ical-smolify/ical-smolify.cabal diff --git a/users/Profpatsch/mailbox-org/MailboxOrg.hs b/users/Profpatsch/parked/mailbox-org/MailboxOrg.hs index 6c5820080c76..6c5820080c76 100644 --- a/users/Profpatsch/mailbox-org/MailboxOrg.hs +++ b/users/Profpatsch/parked/mailbox-org/MailboxOrg.hs diff --git a/users/Profpatsch/mailbox-org/README.md b/users/Profpatsch/parked/mailbox-org/README.md index b84e7b59c130..b84e7b59c130 100644 --- a/users/Profpatsch/mailbox-org/README.md +++ b/users/Profpatsch/parked/mailbox-org/README.md diff --git a/users/Profpatsch/mailbox-org/default.nix b/users/Profpatsch/parked/mailbox-org/default.nix.inactive index 73bd28292dcc..73bd28292dcc 100644 --- a/users/Profpatsch/mailbox-org/default.nix +++ b/users/Profpatsch/parked/mailbox-org/default.nix.inactive diff --git a/users/Profpatsch/mailbox-org/mailbox-org.cabal b/users/Profpatsch/parked/mailbox-org/mailbox-org.cabal index a1b041447bbb..a1b041447bbb 100644 --- a/users/Profpatsch/mailbox-org/mailbox-org.cabal +++ b/users/Profpatsch/parked/mailbox-org/mailbox-org.cabal diff --git a/users/Profpatsch/mailbox-org/src/AesonQQ.hs b/users/Profpatsch/parked/mailbox-org/src/AesonQQ.hs index 2ac3d533aeaa..2ac3d533aeaa 100644 --- a/users/Profpatsch/mailbox-org/src/AesonQQ.hs +++ b/users/Profpatsch/parked/mailbox-org/src/AesonQQ.hs diff --git a/users/Profpatsch/reverse-haskell-deps/README.md b/users/Profpatsch/parked/reverse-haskell-deps/README.md index efc288cae4a9..efc288cae4a9 100644 --- a/users/Profpatsch/reverse-haskell-deps/README.md +++ b/users/Profpatsch/parked/reverse-haskell-deps/README.md diff --git a/users/Profpatsch/reverse-haskell-deps/ReverseHaskellDeps.hs b/users/Profpatsch/parked/reverse-haskell-deps/ReverseHaskellDeps.hs index 0e18ce8a6b37..0e18ce8a6b37 100644 --- a/users/Profpatsch/reverse-haskell-deps/ReverseHaskellDeps.hs +++ b/users/Profpatsch/parked/reverse-haskell-deps/ReverseHaskellDeps.hs diff --git a/users/Profpatsch/reverse-haskell-deps/default.nix b/users/Profpatsch/parked/reverse-haskell-deps/default.nix.inactive index b0a44420d793..b0a44420d793 100644 --- a/users/Profpatsch/reverse-haskell-deps/default.nix +++ b/users/Profpatsch/parked/reverse-haskell-deps/default.nix.inactive diff --git a/users/Profpatsch/reverse-haskell-deps/reverse-haskell-deps.cabal b/users/Profpatsch/parked/reverse-haskell-deps/reverse-haskell-deps.cabal index 4792f52adf25..4792f52adf25 100644 --- a/users/Profpatsch/reverse-haskell-deps/reverse-haskell-deps.cabal +++ b/users/Profpatsch/parked/reverse-haskell-deps/reverse-haskell-deps.cabal diff --git a/users/Profpatsch/sync-abfall-ics-aichach-friedberg/README.md b/users/Profpatsch/parked/sync-abfall-ics-aichach-friedberg/README.md index e0a6aa2fb83b..e0a6aa2fb83b 100644 --- a/users/Profpatsch/sync-abfall-ics-aichach-friedberg/README.md +++ b/users/Profpatsch/parked/sync-abfall-ics-aichach-friedberg/README.md diff --git a/users/Profpatsch/sync-abfall-ics-aichach-friedberg/default.nix b/users/Profpatsch/parked/sync-abfall-ics-aichach-friedberg/default.nix.inactive index 739274cb6f1b..739274cb6f1b 100644 --- a/users/Profpatsch/sync-abfall-ics-aichach-friedberg/default.nix +++ b/users/Profpatsch/parked/sync-abfall-ics-aichach-friedberg/default.nix.inactive diff --git a/users/Profpatsch/sync-abfall-ics-aichach-friedberg/ics-to-caldav.dhall b/users/Profpatsch/parked/sync-abfall-ics-aichach-friedberg/ics-to-caldav.dhall index 2a7ac84979d2..2a7ac84979d2 100644 --- a/users/Profpatsch/sync-abfall-ics-aichach-friedberg/ics-to-caldav.dhall +++ b/users/Profpatsch/parked/sync-abfall-ics-aichach-friedberg/ics-to-caldav.dhall diff --git a/users/Profpatsch/sync-abfall-ics-aichach-friedberg/sync-ics-to-dir.py b/users/Profpatsch/parked/sync-abfall-ics-aichach-friedberg/sync-ics-to-dir.py index 4af3b9fb85ab..4af3b9fb85ab 100644 --- a/users/Profpatsch/sync-abfall-ics-aichach-friedberg/sync-ics-to-dir.py +++ b/users/Profpatsch/parked/sync-abfall-ics-aichach-friedberg/sync-ics-to-dir.py diff --git a/users/Profpatsch/shell.nix b/users/Profpatsch/shell.nix index b5095d476fea..ec3326fe867a 100644 --- a/users/Profpatsch/shell.nix +++ b/users/Profpatsch/shell.nix @@ -45,7 +45,7 @@ pkgs.mkShell { h.unix h.tagsoup h.attoparsec - h.iCalendar + # h.iCalendar h.case-insensitive h.hscolour h.nicify-lib diff --git a/users/Profpatsch/whatcd-resolver/.gitignore b/users/Profpatsch/whatcd-resolver/.gitignore new file mode 100644 index 000000000000..f9c4bdf8b808 --- /dev/null +++ b/users/Profpatsch/whatcd-resolver/.gitignore @@ -0,0 +1 @@ +/.ninja/ diff --git a/users/Profpatsch/whatcd-resolver/default.nix b/users/Profpatsch/whatcd-resolver/default.nix index 27468507ac5a..f679a065227a 100644 --- a/users/Profpatsch/whatcd-resolver/default.nix +++ b/users/Profpatsch/whatcd-resolver/default.nix @@ -25,7 +25,6 @@ let depot.users.Profpatsch.my-webstuff pkgs.haskellPackages.pa-prelude pkgs.haskellPackages.pa-label - pkgs.haskellPackages.pa-json pkgs.haskellPackages.pa-error-tree pkgs.haskellPackages.pa-field-parser pkgs.haskellPackages.pa-run-command diff --git a/users/Profpatsch/whatcd-resolver/services/jaeger/run b/users/Profpatsch/whatcd-resolver/services/jaeger/run index 41332f8bb61b..7800d88287d5 100755 --- a/users/Profpatsch/whatcd-resolver/services/jaeger/run +++ b/users/Profpatsch/whatcd-resolver/services/jaeger/run @@ -1,3 +1,3 @@ #!/usr/bin/env execlineb importas -i DEPOT_ROOT DEPOT_ROOT -nix-run { $DEPOT_ROOT -A users.Profpatsch.jaeger -kK --builders '' } +nix-run { $DEPOT_ROOT -A users.Profpatsch.jaeger -kK } diff --git a/users/Profpatsch/whatcd-resolver/src/AppT.hs b/users/Profpatsch/whatcd-resolver/src/AppT.hs index 7afd430745f6..8550d4aa713e 100644 --- a/users/Profpatsch/whatcd-resolver/src/AppT.hs +++ b/users/Profpatsch/whatcd-resolver/src/AppT.hs @@ -9,36 +9,52 @@ import Data.Error.Tree import Data.HashMap.Strict (HashMap) import Data.HashMap.Strict qualified as HashMap import Data.Pool (Pool) +import Data.String (IsString (fromString)) import Data.Text qualified as Text import Database.PostgreSQL.Simple qualified as Postgres +import FieldParser (FieldParser) +import FieldParser qualified as Field import GHC.Stack qualified +import Json.Enc +import Json.Enc qualified as Enc import Label import OpenTelemetry.Trace qualified as Otel hiding (getTracer, inSpan, inSpan') import OpenTelemetry.Trace.Core qualified as Otel hiding (inSpan, inSpan') import OpenTelemetry.Trace.Monad qualified as Otel import PossehlAnalyticsPrelude import Postgres.MonadPostgres +import Pretty qualified import System.IO qualified as IO -import Tool (Tool) import UnliftIO import Prelude hiding (span) data Context = Context - { config :: Label "logDatabaseQueries" DebugLogDatabaseQueries, + { pgConfig :: + T2 + "logDatabaseQueries" + DebugLogDatabaseQueries + "prettyPrintDatabaseQueries" + PrettyPrintDatabaseQueries, + pgConnPool :: (Pool Postgres.Connection), tracer :: Otel.Tracer, - pgFormat :: Tool, - pgConnPool :: Pool Postgres.Connection, - transmissionSessionId :: MVar ByteString + transmissionSessionId :: IORef (Maybe ByteString), + redactedApiKey :: ByteString } newtype AppT m a = AppT {unAppT :: ReaderT Context m a} deriving newtype (Functor, Applicative, Monad, MonadIO, MonadUnliftIO, MonadThrow) -data AppException = AppException Text - deriving stock (Show) +data AppException + = AppExceptionTree ErrorTree + | AppExceptionPretty [Pretty.Err] deriving anyclass (Exception) --- * Logging & Opentelemetry +instance IsString AppException where + fromString s = AppExceptionTree (fromString s) + +instance Show AppException where + showsPrec _ (AppExceptionTree t) = ("AppException: " ++) . ((textToString $ prettyErrorTree t) ++) + showsPrec _ (AppExceptionPretty t) = ("AppException: " ++) . ((Pretty.prettyErrsNoColor t) ++) instance (MonadIO m) => MonadLogger (AppT m) where monadLoggerLog loc src lvl msg = liftIO $ Logger.defaultOutput IO.stderr loc src lvl (Logger.toLogStr msg) @@ -66,42 +82,72 @@ addAttribute span key a = Otel.addAttribute span ("_." <> key) a addAttributes :: (MonadIO m) => Otel.Span -> HashMap Text Otel.Attribute -> m () addAttributes span attrs = Otel.addAttributes span $ attrs & HashMap.mapKeys ("_." <>) -appThrowTreeNewSpan :: (MonadThrow m, MonadOtel m) => Text -> ErrorTree -> m a -appThrowTreeNewSpan spanName exc = inSpan' spanName $ \span -> do - let msg = prettyErrorTree exc +addEventSimple :: (MonadIO m) => Otel.Span -> Text -> m () +addEventSimple span name = + Otel.addEvent + span + Otel.NewEvent + { Otel.newEventName = name, + Otel.newEventTimestamp = Nothing, + Otel.newEventAttributes = mempty + } + +-- | Create an otel attribute from a json encoder +jsonAttribute :: Enc -> Otel.Attribute +jsonAttribute e = e & Enc.encToTextPretty & Otel.toAttribute + +parseOrThrow :: (MonadThrow m, MonadIO m) => Otel.Span -> FieldParser from to -> from -> m to +parseOrThrow span fp f = + f & Field.runFieldParser fp & \case + Left err -> appThrow span (AppExceptionTree $ singleError err) + Right a -> pure a + +orThrowAppErrorNewSpan :: (MonadThrow m, MonadOtel m) => Text -> Either AppException a -> m a +orThrowAppErrorNewSpan msg = \case + Left err -> appThrowNewSpan msg err + Right a -> pure a + +appThrowNewSpan :: (MonadThrow m, MonadOtel m) => Text -> AppException -> m a +appThrowNewSpan spanName exc = inSpan' spanName $ \span -> do + let msg = case exc of + AppExceptionTree e -> prettyErrorTree e + AppExceptionPretty p -> Pretty.prettyErrsNoColor p & stringToText recordException span ( T2 (label @"type_" "AppException") (label @"message" msg) ) - throwM $ AppException msg + throwM $ exc -appThrowTree :: (MonadThrow m, MonadIO m) => Otel.Span -> ErrorTree -> m a -appThrowTree span exc = do - let msg = prettyErrorTree exc +appThrow :: (MonadThrow m, MonadIO m) => Otel.Span -> AppException -> m a +appThrow span exc = do + let msg = case exc of + AppExceptionTree e -> prettyErrorTree e + AppExceptionPretty p -> Pretty.prettyErrsNoColor p & stringToText recordException span ( T2 (label @"type_" "AppException") (label @"message" msg) ) - throwM $ AppException msg + throwM $ exc -orAppThrowTree :: (MonadThrow m, MonadIO m) => Otel.Span -> Either ErrorTree a -> m a -orAppThrowTree span = \case - Left err -> appThrowTree span err +orAppThrow :: (MonadThrow m, MonadIO m) => Otel.Span -> Either AppException a -> m a +orAppThrow span = \case + Left err -> appThrow span err Right a -> pure a -assertM :: (MonadThrow f, MonadIO f) => Otel.Span -> (t -> Either ErrorTree a) -> t -> f a +-- | If action returns a Left, throw an AppException +assertM :: (MonadThrow f, MonadIO f) => Otel.Span -> (t -> Either AppException a) -> t -> f a assertM span f v = case f v of Right a -> pure a - Left err -> appThrowTree span err + Left err -> appThrow span err -assertMNewSpan :: (MonadThrow f, MonadOtel f) => Text -> (t -> Either ErrorTree a) -> t -> f a +assertMNewSpan :: (MonadThrow f, MonadOtel f) => Text -> (t -> Either AppException a) -> t -> f a assertMNewSpan spanName f v = case f v of Right a -> pure a - Left err -> appThrowTreeNewSpan spanName err + Left err -> appThrowNewSpan spanName err -- | A specialized variant of @addEvent@ that records attributes conforming to -- the OpenTelemetry specification's @@ -126,7 +172,7 @@ recordException span dat = liftIO $ do HashMap.fromList [ ("exception.type", Otel.toAttribute @Text dat.type_), ("exception.message", Otel.toAttribute @Text dat.message), - ("exception.stacktrace", Otel.toAttribute @Text $ Text.unlines $ map stringToText callStack) + ("exception.stacktrace", Otel.toAttribute @Text $ Text.unlines $ Prelude.map stringToText callStack) ], .. } @@ -134,15 +180,25 @@ recordException span dat = liftIO $ do -- * Postgres instance (MonadThrow m, MonadUnliftIO m) => MonadPostgres (AppT m) where - execute = executeImpl (AppT ask) (AppT $ asks (.config.logDatabaseQueries)) - executeMany = executeManyImpl (AppT ask) (AppT $ asks (.config.logDatabaseQueries)) - executeManyReturningWith = executeManyReturningWithImpl (AppT ask) (AppT $ asks (.config.logDatabaseQueries)) - queryWith = queryWithImpl (AppT ask) (AppT $ asks (.config.logDatabaseQueries)) - queryWith_ = queryWithImpl_ (AppT ask) + execute = executeImpl dbConfig + executeMany = executeManyImpl dbConfig + executeManyReturningWith = executeManyReturningWithImpl dbConfig + queryWith = queryWithImpl dbConfig + queryWith_ = queryWithImpl_ (dbConfig <&> snd) - foldRowsWithAcc = foldRowsWithAccImpl (AppT ask) (AppT $ asks (.config.logDatabaseQueries)) + foldRowsWithAcc = foldRowsWithAccImpl dbConfig runTransaction = runPGTransaction +dbConfig :: (Monad m) => AppT m (DebugLogDatabaseQueries, PrettyPrintDatabaseQueries) +dbConfig = + AppT $ + asks + ( \c -> + ( c.pgConfig.logDatabaseQueries, + c.pgConfig.prettyPrintDatabaseQueries + ) + ) + runPGTransaction :: (MonadUnliftIO m) => Transaction (AppT m) a -> AppT m a runPGTransaction (Transaction transaction) = do pool <- AppT ask <&> (.pgConnPool) diff --git a/users/Profpatsch/whatcd-resolver/src/Http.hs b/users/Profpatsch/whatcd-resolver/src/Http.hs index 4fdbb306ad18..14ce191d520e 100644 --- a/users/Profpatsch/whatcd-resolver/src/Http.hs +++ b/users/Profpatsch/whatcd-resolver/src/Http.hs @@ -4,29 +4,39 @@ module Http ( doRequestJson, RequestOptions (..), mkRequestOptions, - setRequestMethod, - setRequestBodyLBS, - setRequestHeader, - getResponseStatus, - getResponseHeader, - getResponseBody, + httpJson, + Http.httpBS, + Http.Request, + Http.setRequestMethod, + Http.setQueryString, + Http.setRequestBodyLBS, + Http.setRequestHeader, + Http.getResponseStatus, + Http.getResponseHeader, + Http.getResponseHeaders, + Http.getResponseBody, ) where import AppT +import Data.Aeson.BetterErrors qualified as Json import Data.CaseInsensitive (CI (original)) import Data.Char qualified as Char -import Data.Int (Int64) +import Data.Error.Tree import Data.List qualified as List import Data.Text qualified as Text -import Data.Text.Lazy qualified as Lazy.Text import Data.Text.Punycode qualified as Punycode +import Json qualified import Json.Enc qualified as Enc +import Label import MyPrelude import Network.HTTP.Client -import Network.HTTP.Simple -import OpenTelemetry.Attributes qualified as Otel +import Network.HTTP.Client qualified as Http +import Network.HTTP.Simple qualified as Http +import Network.HTTP.Types.Status (Status (..)) +import Network.Wai.Parse qualified as Wai import Optional +import Pretty import Prelude hiding (span) data RequestOptions = RequestOptions @@ -34,7 +44,7 @@ data RequestOptions = RequestOptions host :: Text, port :: Optional Int, path :: Optional [Text], - headers :: Optional [Header], + headers :: Optional [Http.Header], usePlainHttp :: Optional Bool } @@ -49,26 +59,71 @@ mkRequestOptions opts = usePlainHttp = defaults } +httpJson :: + ( MonadThrow m, + MonadOtel m + ) => + (Optional (Label "contentType" ByteString)) -> + Json.Parse ErrorTree b -> + Http.Request -> + m b +httpJson opts parser req = inSpan' "HTTP Request (JSON)" $ \span -> do + let opts' = opts.withDefault (label @"contentType" "application/json") + Http.httpBS req + >>= assertM + span + ( \resp -> do + let statusCode = resp & Http.responseStatus & (.statusCode) + contentType = + resp + & Http.responseHeaders + & List.lookup "content-type" + <&> Wai.parseContentType + <&> (\(ct, _mimeAttributes) -> ct) + if + | statusCode == 200, + Just ct <- contentType, + ct == opts'.contentType -> + Right $ (resp & Http.responseBody) + | statusCode == 200, + Just otherType <- contentType -> + Left [fmt|Server returned a non-json body, with content-type "{otherType}"|] + | statusCode == 200, + Nothing <- contentType -> + Left [fmt|Server returned a body with unspecified content type|] + | code <- statusCode -> Left $ AppExceptionPretty [[fmt|Server returned an non-200 error code, code {code}:|], pretty resp] + ) + >>= assertM + span + ( \body -> + Json.parseStrict parser body + & first (AppExceptionTree . Json.parseErrorTree "could not parse HTTP response") + ) + doRequestJson :: (MonadOtel m) => RequestOptions -> Enc.Enc -> m (Response ByteString) doRequestJson opts val = inSpan' "HTTP Request (JSON)" $ \span -> do - let x = requestToXhCommandLine opts val - let attrs = [100, 200 .. fromIntegral @Int @Int64 (x & Text.length)] - for_ attrs $ \n -> do - addAttribute span [fmt|request.xh.{n}|] (Lazy.Text.repeat 'x' & Lazy.Text.take n & toStrict & Otel.TextAttribute) addAttribute span "request.xh" (requestToXhCommandLine opts val) - defaultRequest {secure = not (opts & optsUsePlainHttp)} - & setRequestHost (opts & optsHost) - & setRequestPort (opts & optsPort) - -- TODO: is this automatically escaped by the library? - & setRequestPath (opts & optsPath) - & setRequestHeaders (opts & optsHeaders) - & setRequestMethod opts.method - & setRequestBodyLBS (Enc.encToBytesUtf8Lazy val) - & httpBS + resp <- + defaultRequest {secure = not (opts & optsUsePlainHttp)} + & Http.setRequestHost (opts & optsHost) + & Http.setRequestPort (opts & optsPort) + -- TODO: is this automatically escaped by the library? + & Http.setRequestPath (opts & optsPath) + & Http.setRequestHeaders (opts & optsHeaders) + & Http.setRequestMethod opts.method + & Http.setRequestBodyLBS (Enc.encToBytesUtf8Lazy val) + & Http.httpBS + let code = resp & Http.getResponseStatus & (.statusCode) + let msg = resp & Http.getResponseStatus & (.statusMessage) & bytesToTextUtf8Lenient + addAttribute + span + "request.response.status" + ([fmt|{code} {msg}|] :: Text) + pure resp optsHost :: RequestOptions -> ByteString optsHost opts = @@ -85,7 +140,7 @@ optsPort opts = opts.port.withDefault (if opts & optsUsePlainHttp then 80 else 4 optsPath :: RequestOptions -> ByteString optsPath opts = opts.path.withDefault [] & Text.intercalate "/" & ("/" <>) & textToBytesUtf8 -optsHeaders :: RequestOptions -> [Header] +optsHeaders :: RequestOptions -> [Http.Header] optsHeaders opts = opts.headers.withDefault [] -- | Create a string that can be pasted on the command line to invoke the same HTTP request via the `xh` tool (curl but nicer syntax) diff --git a/users/Profpatsch/whatcd-resolver/src/JsonLd.hs b/users/Profpatsch/whatcd-resolver/src/JsonLd.hs index 16b1ab991b16..db2fb9434554 100644 --- a/users/Profpatsch/whatcd-resolver/src/JsonLd.hs +++ b/users/Profpatsch/whatcd-resolver/src/JsonLd.hs @@ -3,7 +3,6 @@ module JsonLd where import AppT -import Control.Monad.Reader import Data.Aeson qualified as Json import Data.Aeson.BetterErrors qualified as Json import Data.ByteString.Builder qualified as Builder @@ -12,16 +11,14 @@ import Data.Map.Strict qualified as Map import Data.Set (Set) import Data.Set qualified as Set import Html qualified +import Http import IHP.HSX.QQ (hsx) import Json qualified import Label import MyPrelude -import Network.HTTP.Client.Conduit qualified as Http -import Network.HTTP.Simple qualified as Http import Network.HTTP.Types.URI qualified as Url import Network.URI (URI) import Optional -import Redacted import Text.Blaze.Html (Html) import Prelude hiding (span) diff --git a/users/Profpatsch/whatcd-resolver/src/Redacted.hs b/users/Profpatsch/whatcd-resolver/src/Redacted.hs index 4369c184087a..7bf9e8c2ce27 100644 --- a/users/Profpatsch/whatcd-resolver/src/Redacted.hs +++ b/users/Profpatsch/whatcd-resolver/src/Redacted.hs @@ -3,6 +3,7 @@ module Redacted where import AppT +import Arg import Control.Monad.Logger.CallStack import Control.Monad.Reader import Data.Aeson qualified as Json @@ -11,14 +12,12 @@ import Data.Aeson.KeyMap qualified as KeyMap import Data.Error.Tree import Data.List qualified as List import Database.PostgreSQL.Simple (Binary (Binary), Only (..)) -import Database.PostgreSQL.Simple.SqlQQ (sql) import Database.PostgreSQL.Simple.Types (PGArray (PGArray)) import FieldParser qualified as Field +import Http qualified import Json qualified import Label import MyPrelude -import Network.HTTP.Client.Conduit qualified as Http -import Network.HTTP.Simple qualified as Http import Network.HTTP.Types import Network.Wai.Parse qualified as Wai import OpenTelemetry.Trace qualified as Otel hiding (getTracer, inSpan, inSpan') @@ -26,11 +25,16 @@ import Optional import Postgres.Decoder qualified as Dec import Postgres.MonadPostgres import Pretty -import RunCommand (runCommandExpect0) import Prelude hiding (span) +class MonadRedacted m where + getRedactedApiKey :: m ByteString + +instance (MonadIO m) => MonadRedacted (AppT m) where + getRedactedApiKey = AppT (asks (.redactedApiKey)) + redactedSearch :: - (MonadLogger m, MonadThrow m, MonadOtel m) => + (MonadThrow m, MonadOtel m, MonadRedacted m) => [(ByteString, ByteString)] -> Json.Parse ErrorTree a -> m a @@ -47,7 +51,8 @@ redactedGetTorrentFile :: ( MonadLogger m, MonadThrow m, HasField "torrentId" dat Int, - MonadOtel m + MonadOtel m, + MonadRedacted m ) => dat -> m ByteString @@ -67,14 +72,10 @@ redactedGetTorrentFile dat = inSpan' "Redacted Get Torrent File" $ \span -> do ) httpTorrent span req --- fix --- ( \io -> do --- logInfo "delay" --- liftIO $ threadDelay 10_000_000 --- io --- ) +mkRedactedTorrentLink :: Arg "torrentGroupId" Int -> Text +mkRedactedTorrentLink torrentId = [fmt|https://redacted.ch/torrents.php?id={torrentId.unArg}|] -exampleSearch :: (MonadThrow m, MonadLogger m, MonadPostgres m, MonadOtel m) => m (Transaction m ()) +exampleSearch :: (MonadThrow m, MonadLogger m, MonadPostgres m, MonadOtel m, MonadRedacted m) => m (Transaction m ()) exampleSearch = do t1 <- redactedSearchAndInsert @@ -111,7 +112,8 @@ redactedSearchAndInsert :: ( MonadLogger m, MonadPostgres m, MonadThrow m, - MonadOtel m + MonadOtel m, + MonadRedacted m ) => [(ByteString, ByteString)] -> m (Transaction m ()) @@ -273,31 +275,35 @@ redactedSearchAndInsert extraArguments = do , torrent_id , full_json_result) |] - ( [ ( dat.torrentGroupIdPg :: Int, - group.torrentId :: Int, - group.fullJsonResult :: Json.Value - ) + ( [ T3 + (getLabel @"torrentGroupIdPg" dat) + (getLabel @"torrentId" group) + (getLabel @"fullJsonResult" group) | dat <- dats, group <- dat.torrents ] & unzip3PGArray + @"torrentGroupIdPg" + @Int + @"torrentId" + @Int + @"fullJsonResult" + @Json.Value ) pure () -unzip3PGArray :: [(a1, a2, a3)] -> (PGArray a1, PGArray a2, PGArray a3) -unzip3PGArray xs = xs & unzip3 & \(a, b, c) -> (PGArray a, PGArray b, PGArray c) - redactedGetTorrentFileAndInsert :: ( HasField "torrentId" r Int, MonadPostgres m, MonadThrow m, MonadLogger m, - MonadOtel m + MonadOtel m, + MonadRedacted m ) => r -> Transaction m (Label "torrentFile" ByteString) redactedGetTorrentFileAndInsert dat = inSpan' "Redacted Get Torrent File and Insert" $ \span -> do - bytes <- redactedGetTorrentFile dat + bytes <- lift $ redactedGetTorrentFile dat execute [sql| UPDATE redacted.torrents_json @@ -354,15 +360,21 @@ assertOneUpdated :: m () assertOneUpdated span name x = case x.numberOfRowsAffected of 1 -> pure () - n -> appThrowTree span ([fmt|{name :: Text}: Expected to update exactly one row, but updated {n :: Natural} row(s)|]) + n -> appThrow span ([fmt|{name :: Text}: Expected to update exactly one row, but updated {n :: Natural} row(s)|]) data TorrentData transmissionInfo = TorrentData { groupId :: Int, torrentId :: Int, seedingWeight :: Int, - torrentJson :: Json.Value, - torrentGroupJson :: T3 "artist" Text "groupName" Text "groupYear" Int, - torrentStatus :: TorrentStatus transmissionInfo + artists :: [T2 "artistId" Int "artistName" Text], + torrentGroupJson :: TorrentGroupJson, + torrentStatus :: TorrentStatus transmissionInfo, + torrentFormat :: Text + } + +data TorrentGroupJson = TorrentGroupJson + { groupName :: Text, + groupYear :: Natural } data TorrentStatus transmissionInfo @@ -381,42 +393,76 @@ getTorrentById dat = do (Dec.json Json.asValue) >>= ensureSingleRow +data GetBestTorrentsFilter = GetBestTorrentsFilter + { onlyDownloaded :: Bool, + onlyArtist :: Maybe (Label "artistRedactedId" Natural) + } + -- | Find the best torrent for each torrent group (based on the seeding_weight) -getBestTorrents :: (MonadPostgres m) => Transaction m [TorrentData ()] -getBestTorrents = do +getBestTorrents :: + (MonadPostgres m) => + GetBestTorrentsFilter -> + Transaction m [TorrentData ()] +getBestTorrents opts = do queryWith [sql| - SELECT * FROM ( - SELECT DISTINCT ON (group_id) - tg.group_id, - t.torrent_id, - seeding_weight, - t.full_json_result AS torrent_json, - tg.full_json_result AS torrent_group_json, - t.torrent_file IS NOT NULL, - t.transmission_torrent_hash - FROM redacted.torrents t - JOIN redacted.torrent_groups tg ON tg.id = t.torrent_group - ORDER BY group_id, seeding_weight DESC - ) as _ + WITH filtered_torrents AS ( + SELECT DISTINCT ON (torrent_group) + id + FROM + redacted.torrents + WHERE + -- onlyDownloaded + ((NOT ?::bool) OR torrent_file IS NOT NULL) + -- filter by artist id + AND + (?::bool OR (to_jsonb(?::int) <@ (jsonb_path_query_array(full_json_result, '$.artists[*].id')))) + ORDER BY + torrent_group, + -- prefer torrents which we already downloaded + torrent_file, + seeding_weight DESC + ) + SELECT + tg.group_id, + t.torrent_id, + t.seeding_weight, + t.full_json_result->'artists' AS artists, + tg.full_json_result->>'groupName' AS group_name, + tg.full_json_result->>'groupYear' AS group_year, + t.torrent_file IS NOT NULL AS has_torrent_file, + t.transmission_torrent_hash, + t.full_json_result->>'encoding' AS torrent_format + FROM filtered_torrents f + JOIN redacted.torrents t ON t.id = f.id + JOIN redacted.torrent_groups tg ON tg.id = t.torrent_group ORDER BY seeding_weight DESC |] - () + ( do + let (onlyArtistB, onlyArtistId) = case opts.onlyArtist of + Nothing -> (True, 0) + Just a -> (False, a.artistRedactedId) + ( opts.onlyDownloaded :: Bool, + onlyArtistB :: Bool, + onlyArtistId & fromIntegral @Natural @Int + ) + ) ( do groupId <- Dec.fromField @Int torrentId <- Dec.fromField @Int seedingWeight <- Dec.fromField @Int - torrentJson <- Dec.json Json.asValue - torrentGroupJson <- - ( Dec.json $ do - artist <- Json.keyLabel @"artist" "artist" Json.asText - groupName <- Json.keyLabel @"groupName" "groupName" Json.asText - groupYear <- Json.keyLabel @"groupYear" "groupYear" (Json.asIntegral @_ @Int) - pure $ T3 artist groupName groupYear - ) + artists <- Dec.json $ + Json.eachInArray $ do + id_ <- Json.keyLabel @"artistId" "id" (Json.asIntegral @_ @Int) + name <- Json.keyLabel @"artistName" "name" Json.asText + pure $ T2 id_ name + torrentGroupJson <- do + groupName <- Dec.text + groupYear <- Dec.textParse Field.decimalNatural + pure $ TorrentGroupJson {..} hasTorrentFile <- Dec.fromField @Bool - transmissionTorrentHash <- - Dec.fromField @(Maybe Text) + transmissionTorrentHash <- Dec.fromField @(Maybe Text) + torrentFormat <- Dec.text pure $ TorrentData { torrentStatus = @@ -426,6 +472,13 @@ getBestTorrents = do | Just hash <- transmissionTorrentHash -> InTransmission $ T2 (label @"torrentHash" hash) (label @"transmissionInfo" ()), + torrentFormat = case torrentFormat of + "Lossless" -> "flac" + "V0 (VBR)" -> "V0" + "V2 (VBR)" -> "V2" + "320" -> "320" + "256" -> "256" + o -> o, .. } ) @@ -433,15 +486,14 @@ getBestTorrents = do -- | Do a request to the redacted API. If you know what that is, you know how to find the API docs. mkRedactedApiRequest :: ( MonadThrow m, - MonadIO m, - MonadLogger m, HasField "action" p ByteString, - HasField "actionArgs" p [(ByteString, Maybe ByteString)] + HasField "actionArgs" p [(ByteString, Maybe ByteString)], + MonadRedacted m ) => p -> m Http.Request mkRedactedApiRequest dat = do - authKey <- runCommandExpect0 "pass" ["internet/redacted/api-keys/whatcd-resolver"] + authKey <- getRedactedApiKey pure $ [fmt|https://redacted.ch/ajax.php|] & Http.setRequestMethod "GET" @@ -460,73 +512,32 @@ httpTorrent span req = >>= assertM span ( \resp -> do - let statusCode = resp & Http.responseStatus & (.statusCode) + let statusCode = resp & Http.getResponseStatus & (.statusCode) contentType = resp - & Http.responseHeaders + & Http.getResponseHeaders & List.lookup "content-type" <&> Wai.parseContentType <&> (\(ct, _mimeAttributes) -> ct) if | statusCode == 200, Just "application/x-bittorrent" <- contentType -> - Right $ (resp & Http.responseBody) + Right $ (resp & Http.getResponseBody) | statusCode == 200, Just otherType <- contentType -> Left [fmt|Redacted returned a non-torrent body, with content-type "{otherType}"|] | statusCode == 200, Nothing <- contentType -> Left [fmt|Redacted returned a body with unspecified content type|] - | code <- statusCode -> Left [fmt|Redacted returned an non-200 error code, code {code}: {resp & showPretty}|] - ) - -httpJson :: - ( MonadThrow m, - MonadOtel m - ) => - (Optional (Label "contentType" ByteString)) -> - Json.Parse ErrorTree b -> - Http.Request -> - m b -httpJson opts parser req = inSpan' "HTTP Request (JSON)" $ \span -> do - let opts' = opts.withDefault (label @"contentType" "application/json") - Http.httpBS req - >>= assertM - span - ( \resp -> do - let statusCode = resp & Http.responseStatus & (.statusCode) - contentType = - resp - & Http.responseHeaders - & List.lookup "content-type" - <&> Wai.parseContentType - <&> (\(ct, _mimeAttributes) -> ct) - if - | statusCode == 200, - Just ct <- contentType, - ct == opts'.contentType -> - Right $ (resp & Http.responseBody) - | statusCode == 200, - Just otherType <- contentType -> - Left [fmt|Server returned a non-json body, with content-type "{otherType}"|] - | statusCode == 200, - Nothing <- contentType -> - Left [fmt|Server returned a body with unspecified content type|] - | code <- statusCode -> Left [fmt|Server returned an non-200 error code, code {code}: {resp & showPretty}|] - ) - >>= assertM - span - ( \body -> - Json.parseStrict parser body - & first (Json.parseErrorTree "could not parse redacted response") + | code <- statusCode -> Left $ AppExceptionPretty [[fmt|Redacted returned an non-200 error code, code {code}|], pretty resp] ) redactedApiRequestJson :: ( MonadThrow m, - MonadLogger m, HasField "action" p ByteString, HasField "actionArgs" p [(ByteString, Maybe ByteString)], - MonadOtel m + MonadOtel m, + MonadRedacted m ) => p -> Json.Parse ErrorTree a -> @@ -534,4 +545,4 @@ redactedApiRequestJson :: redactedApiRequestJson dat parser = do mkRedactedApiRequest dat - >>= httpJson defaults parser + >>= Http.httpJson defaults parser diff --git a/users/Profpatsch/whatcd-resolver/src/Transmission.hs b/users/Profpatsch/whatcd-resolver/src/Transmission.hs index 66dbeb9ce749..3238780af70f 100644 --- a/users/Profpatsch/whatcd-resolver/src/Transmission.hs +++ b/users/Profpatsch/whatcd-resolver/src/Transmission.hs @@ -25,6 +25,7 @@ import Json.Enc qualified as Enc import Label import MyPrelude import Network.HTTP.Types +import OpenTelemetry.Attributes (ToAttribute (toAttribute)) import OpenTelemetry.Trace qualified as Otel hiding (getTracer, inSpan, inSpan') import Optional import Postgres.MonadPostgres @@ -48,18 +49,20 @@ scientificPercentage = | otherwise -> Right $ Percentage $ ceiling (f * 100) ) --- | Fetch the current status from transmission, and remove the tranmission hash from our database --- iff it does not exist in transmission anymore +-- | Fetch the current status from transmission, +-- and remove the transmission hash and torrent file from our database iff it does not exist in transmission anymore getAndUpdateTransmissionTorrentsStatus :: ( MonadTransmission m, MonadThrow m, MonadLogger m, MonadPostgres m, - MonadOtel m + MonadOtel m, + HasField "groupId" info Int, + HasField "torrentId" info Int ) => - Map (Label "torrentHash" Text) () -> - (Transaction m (Map (Label "torrentHash" Text) (Label "percentDone" Percentage))) -getAndUpdateTransmissionTorrentsStatus knownTorrents = do + Map (Label "torrentHash" Text) info -> + (Transaction m (Label "knownTorrentsStale" Bool, (Map (Label "torrentHash" Text) (Label "percentDone" Percentage)))) +getAndUpdateTransmissionTorrentsStatus knownTorrents = inSpan' "getAndUpdateTransmissionTorrentsStatus" $ \span -> do let fields = ["hashString", "percentDone"] actualTorrents <- lift @Transaction $ @@ -76,14 +79,36 @@ getAndUpdateTransmissionTorrentsStatus knownTorrents = do ) <&> Map.fromList let toDelete = Map.difference knownTorrents actualTorrents - execute - [fmt| - UPDATE redacted.torrents_json - SET transmission_torrent_hash = NULL - WHERE transmission_torrent_hash = ANY (?::text[]) - |] - $ Only (toDelete & Map.keys <&> (.torrentHash) & PGArray :: PGArray Text) - pure actualTorrents + if + | Map.null toDelete -> do + addEventSimple span "We know about all transmission hashes." + pure (label @"knownTorrentsStale" False, actualTorrents) + | otherwise -> inSpan' "Delete outdated transmission hashes" $ \span' -> do + addAttribute + span' + "db.delete-transmission-hashes" + ( toDelete + & Map.toList + & Enc.list + ( \(k, v) -> + Enc.object + [ ("torrentHash", Enc.text k.torrentHash), + ("groupId", Enc.int v.groupId), + ("torrentId", Enc.int v.torrentId) + ] + ) + & jsonAttribute + ) + _ <- + execute + [fmt| + UPDATE redacted.torrents_json + SET transmission_torrent_hash = NULL, + torrent_file = NULL + WHERE transmission_torrent_hash = ANY (?::text[]) + |] + $ Only (toDelete & Map.keys <&> (.torrentHash) & PGArray :: PGArray Text) + pure (label @"knownTorrentsStale" True, actualTorrents) getTransmissionTorrentsTable :: (MonadTransmission m, MonadThrow m, MonadLogger m, MonadOtel m) => m Html @@ -204,9 +229,9 @@ doTransmissionRequest' req = inSpan' "Transmission Request" $ \span -> do transmissionConnectionConfig req case resp.result of - TransmissionResponseFailure err -> appThrowTree span (nestedError "Transmission RPC error" $ singleError $ newError err) + TransmissionResponseFailure err -> appThrow span (AppExceptionTree $ nestedError "Transmission RPC error" $ singleError $ newError err) TransmissionResponseSuccess -> case resp.arguments of - Nothing -> appThrowTree span "Transmission RPC error: No `arguments` field in response" + Nothing -> appThrow span "Transmission RPC error: No `arguments` field in response" Just out -> pure out -- | Contact the transmission RPC, and do the CSRF protection dance. @@ -226,7 +251,7 @@ doTransmissionRequest :: (TransmissionRequest, Json.Parse Error output) -> m (TransmissionResponse output) doTransmissionRequest span dat (req, parser) = do - sessionId <- getTransmissionId + sessionId <- getCurrentTransmissionSessionId let textArg t = (Enc.text t, Otel.toAttribute @Text t) let encArg enc = (enc, Otel.toAttribute @Text $ enc & Enc.encToTextPretty) let intArg i = (Enc.int i, Otel.toAttribute @Int i) @@ -257,7 +282,7 @@ doTransmissionRequest span dat (req, parser) = do (body <&> second fst & Enc.object) -- Implement the CSRF protection thingy case resp & Http.getResponseStatus & (.statusCode) of - 409 -> do + 409 -> inSpan' "New Transmission Session ID" $ \span' -> do tid <- resp & Http.getResponseHeader "X-Transmission-Session-Id" @@ -266,9 +291,21 @@ doTransmissionRequest span dat (req, parser) = do & unwrapIOError & liftIO <&> NonEmpty.head - setTransmissionId tid + + addAttributes span' $ + HashMap.fromList + [ ("transmission.new_session_id", tid & bytesToTextUtf8Lenient & toAttribute), + ("transmission.old_session_id", sessionId <&> bytesToTextUtf8Lenient & fromMaybe "<none yet>" & toAttribute) + ] + + updateTransmissionSessionId tid + doTransmissionRequest span dat (req, parser) - 200 -> + 200 -> do + addAttributes span $ + HashMap.fromList + [ ("transmission.valid_session_id", sessionId <&> bytesToTextUtf8Lenient & fromMaybe "<none yet>" & toAttribute) + ] resp & Http.getResponseBody & Json.parseStrict @@ -292,15 +329,15 @@ doTransmissionRequest span dat (req, parser) = do case Json.eitherDecodeStrict' @Json.Value (resp & Http.getResponseBody) of Left _err -> pure () Right val -> logInfo [fmt|failing transmission response: {showPrettyJson val}|] - appThrowTree span err - _ -> liftIO $ unwrapIOError $ Left [fmt|Non-200 response: {showPretty resp}|] + appThrow span (AppExceptionTree err) + _ -> appThrow span $ AppExceptionPretty [[fmt|Non-200 response:|], pretty resp] class MonadTransmission m where - getTransmissionId :: m (Maybe ByteString) - setTransmissionId :: ByteString -> m () + getCurrentTransmissionSessionId :: m (Maybe ByteString) + updateTransmissionSessionId :: ByteString -> m () instance (MonadIO m) => MonadTransmission (AppT m) where - getTransmissionId = AppT (asks (.transmissionSessionId)) >>= tryTakeMVar - setTransmissionId t = do + getCurrentTransmissionSessionId = AppT (asks (.transmissionSessionId)) >>= readIORef + updateTransmissionSessionId t = do var <- AppT $ asks (.transmissionSessionId) - putMVar var t + writeIORef var (Just t) diff --git a/users/Profpatsch/whatcd-resolver/src/WhatcdResolver.hs b/users/Profpatsch/whatcd-resolver/src/WhatcdResolver.hs index f1902bac8c3d..c8850e70a121 100644 --- a/users/Profpatsch/whatcd-resolver/src/WhatcdResolver.hs +++ b/users/Profpatsch/whatcd-resolver/src/WhatcdResolver.hs @@ -1,8 +1,10 @@ +{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE QuasiQuotes #-} module WhatcdResolver where import AppT +import Arg import Control.Category qualified as Cat import Control.Monad.Catch.Pure (runCatch) import Control.Monad.Logger.CallStack @@ -10,19 +12,20 @@ import Control.Monad.Reader import Data.Aeson qualified as Json import Data.Aeson.BetterErrors qualified as Json import Data.Aeson.KeyMap qualified as KeyMap +import Data.Error.Tree import Data.HashMap.Strict qualified as HashMap import Data.List qualified as List import Data.Map.Strict qualified as Map import Data.Pool qualified as Pool import Data.Text qualified as Text import Database.PostgreSQL.Simple qualified as Postgres -import Database.PostgreSQL.Simple.SqlQQ (sql) import Database.PostgreSQL.Simple.Types (PGArray (PGArray)) import Database.Postgres.Temp qualified as TmpPg import FieldParser (FieldParser, FieldParser' (..)) import FieldParser qualified as Field import Html qualified import IHP.HSX.QQ (hsx) +import IHP.HSX.ToHtml (ToHtml) import Json qualified import Json.Enc (Enc) import Json.Enc qualified as Enc @@ -36,11 +39,9 @@ import Network.HTTP.Types import Network.HTTP.Types qualified as Http import Network.URI (URI) import Network.URI qualified -import Network.URI qualified as URI import Network.Wai (ResponseReceived) import Network.Wai qualified as Wai import Network.Wai.Handler.Warp qualified as Warp -import Network.Wai.Parse qualified as Wai import OpenTelemetry.Attributes qualified as Otel import OpenTelemetry.Trace qualified as Otel hiding (getTracer, inSpan, inSpan') import OpenTelemetry.Trace.Monad qualified as Otel @@ -50,12 +51,12 @@ import Postgres.Decoder qualified as Dec import Postgres.MonadPostgres import Pretty import Redacted +import RunCommand (runCommandExpect0) import System.Directory qualified as Dir import System.Directory qualified as Xdg import System.Environment qualified as Env import System.FilePath ((</>)) import Text.Blaze.Html (Html) -import Text.Blaze.Html.Renderer.Pretty qualified as Html.Pretty import Text.Blaze.Html.Renderer.Utf8 qualified as Html import Text.Blaze.Html5 qualified as Html import Tool (readTool, readTools) @@ -77,7 +78,6 @@ main = htmlUi :: AppT IO () htmlUi = do - let debug = True uniqueRunId <- runTransaction $ querySingleRowWith @@ -87,18 +87,21 @@ htmlUi = do () (Dec.fromField @Text) - withRunInIO $ \runInIO -> Warp.run 9093 $ \req respond -> do + withRunInIO $ \runInIO -> Warp.run 9093 $ \req respondOrig -> do let catchAppException act = try act >>= \case Right a -> pure a - Left (AppException err) -> do - runInIO (logError err) - respond (Wai.responseLBS Http.status500 [] "") + Left (AppExceptionTree err) -> do + runInIO (logError (prettyErrorTree err)) + respondOrig (Wai.responseLBS Http.status500 [] "") + Left (AppExceptionPretty err) -> do + runInIO (logError (err & Pretty.prettyErrsNoColor & stringToText)) + respondOrig (Wai.responseLBS Http.status500 [] "") catchAppException $ do let mp span parser = Multipart.parseMultipartOrThrow - (appThrowTree span) + (appThrow span . AppExceptionTree) parser req @@ -108,20 +111,17 @@ htmlUi = do ( do label @"torrentId" <$> Multipart.field "torrent-id" ((Field.utf8 >>> Field.signedDecimal >>> Field.bounded @Int "int")) ) - let parseQueryArgs span parser = - Parse.runParse "Unable to find the right request query arguments" (lmap Wai.queryString parser) req - & assertM span id let parseQueryArgsNewSpan spanName parser = Parse.runParse "Unable to find the right request query arguments" (lmap Wai.queryString parser) req - & assertMNewSpan spanName id + & assertMNewSpan spanName (first AppExceptionTree) let handlers :: Handlers (AppT IO) handlers respond = Map.fromList - [ ("", respond.h (mainHtml uniqueRunId)), + [ ("", respond.html (mainHtml uniqueRunId)), ( "snips/redacted/search", - respond.h $ + respond.html $ \span -> do dat <- mp @@ -132,12 +132,12 @@ htmlUi = do snipsRedactedSearch dat ), ( "snips/redacted/torrentDataJson", - respond.h $ \span -> do + respond.html $ \span -> do dat <- torrentIdMp span Html.mkVal <$> (runTransaction $ getTorrentById dat) ), ( "snips/redacted/getTorrentFile", - respond.h $ \span -> do + respond.htmlOrReferer $ \span -> do dat <- torrentIdMp span runTransaction $ do inserted <- redactedGetTorrentFileAndInsert dat @@ -157,13 +157,13 @@ htmlUi = do ), -- TODO: this is bad duplication?? ( "snips/redacted/startTorrentFile", - respond.h $ \span -> do + respond.html $ \span -> do dat <- torrentIdMp span runTransaction $ do file <- getTorrentFileById dat <&> annotate [fmt|No torrent file for torrentId "{dat.torrentId}"|] - >>= orAppThrowTree span + >>= orAppThrow span running <- lift @Transaction $ @@ -180,7 +180,7 @@ htmlUi = do "Starting" ), ( "snips/transmission/getTorrentState", - respond.h $ \span -> do + respond.html $ \span -> do dat <- mp span $ label @"torrentHash" <$> Multipart.field "torrent-hash" Field.utf8 status <- doTransmissionRequest' @@ -199,17 +199,29 @@ htmlUi = do Just _torrent -> [hsx|Running|] ), ( "snips/jsonld/render", - respond.h $ \span -> do - qry <- - parseQueryArgs - span - ( label @"target" - <$> ( (singleQueryArgument "target" Field.utf8 >>> textToURI) - & Parse.andParse uriToHttpClientRequest - ) - ) - jsonld <- httpGetJsonLd (qry.target) - pure $ renderJsonld jsonld + do + let HandlerResponses {htmlWithQueryArgs} = respond + htmlWithQueryArgs + ( label @"target" + <$> ( (singleQueryArgument "target" Field.utf8 >>> textToURI) + & Parse.andParse uriToHttpClientRequest + ) + ) + ( \qry _span -> do + jsonld <- httpGetJsonLd (qry.target) + pure $ renderJsonld jsonld + ) + ), + ( "artist", + do + let HandlerResponses {htmlWithQueryArgs} = respond + + htmlWithQueryArgs + ( label @"artistRedactedId" + <$> (singleQueryArgument "redacted_id" (Field.utf8 >>> Field.decimalNatural)) + ) + $ \qry _span -> do + artistPage qry ), ( "autorefresh", respond.plain $ do @@ -233,32 +245,81 @@ htmlUi = do ] runInIO $ runHandlers - debug - (\respond -> respond.h $ (mainHtml uniqueRunId)) + (\respond -> respond.html $ (mainHtml uniqueRunId)) handlers req - respond + respondOrig where everySecond :: Text -> Enc -> Html -> Html everySecond call extraData innerHtml = [hsx|<div hx-trigger="every 1s" hx-swap="outerHTML" hx-post={call} hx-vals={Enc.encToBytesUtf8 extraData}>{innerHtml}</div>|] mainHtml :: Text -> Otel.Span -> AppT IO Html mainHtml uniqueRunId _span = runTransaction $ do - jsonld <- - httpGetJsonLd - ( URI.parseURI "https://musicbrainz.org/work/92000fd4-d304-406d-aeb4-6bdbeed318ec" & annotate "not an URI" & unwrapError, - "https://musicbrainz.org/work/92000fd4-d304-406d-aeb4-6bdbeed318ec" - ) - <&> renderJsonld - bestTorrentsTable <- getBestTorrentsTable + -- jsonld <- + -- httpGetJsonLd + -- ( URI.parseURI "https://musicbrainz.org/work/92000fd4-d304-406d-aeb4-6bdbeed318ec" & annotate "not an URI" & unwrapError, + -- "https://musicbrainz.org/work/92000fd4-d304-406d-aeb4-6bdbeed318ec" + -- ) + -- <&> renderJsonld + bestTorrentsTable <- getBestTorrentsTable Nothing -- transmissionTorrentsTable <- lift @Transaction getTransmissionTorrentsTable pure $ - Html.docTypeHtml + htmlPageChrome + "whatcd-resolver" [hsx| + <form + hx-post="/snips/redacted/search" + hx-target="#redacted-search-results"> + <label for="redacted-search">Redacted Search</label> + <input + id="redacted-search" + type="text" + name="redacted-search" /> + <button type="submit" hx-disabled-elt="this">Search</button> + <div class="htmx-indicator">Search running!</div> + </form> + <div id="redacted-search-results"> + {bestTorrentsTable} + </div> + <!-- refresh the page if the uniqueRunId is different --> + <input + hidden + type="text" + id="autorefresh" + name="hasItBeenRestarted" + value={uniqueRunId} + hx-get="/autorefresh" + hx-trigger="every 5s" + hx-swap="none" + /> + |] + +-- | Reload the current page (via the Referer header) if the browser has Javascript disabled (and thus htmx does not work). This should make post requests work out of the box. +htmxOrReferer :: Wai.Request -> Wai.Response -> Wai.Response +htmxOrReferer req act = do + let fnd h = req & Wai.requestHeaders & List.find (\(hdr, _) -> hdr == h) + let referer = fnd "Referer" + if + | Just _ <- fnd "Hx-Request" -> act + | Nothing <- referer -> act + | Just (_, rfr) <- referer -> do + Wai.responseLBS seeOther303 [("Location", rfr)] "" + +htmlPageChrome :: (ToHtml a) => Text -> a -> Html +htmlPageChrome title body = + Html.docTypeHtml $ + [hsx| <head> - <title>whatcd-resolver</title> + <!-- TODO: set nice page title for each page --> + <title>{title}</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> + <!-- + prevent favicon request, based on answers in + https://stackoverflow.com/questions/1321878/how-to-prevent-favicon-ico-requests + TODO: create favicon + --> + <link rel="icon" href="data:,"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script> <script src="https://unpkg.com/htmx.org@1.9.2" integrity="sha384-L6OqL9pRWyyFU3+/bjdSri+iIphTN/bvYyM37tICVyOJkWZLpP2vGn6VUEXgzg6h" crossorigin="anonymous"></script> @@ -271,73 +332,103 @@ htmlUi = do </style> </head> <body> - {jsonld} - <form - hx-post="/snips/redacted/search" - hx-target="#redacted-search-results"> - <label for="redacted-search">Redacted Search</label> - <input - id="redacted-search" - type="text" - name="redacted-search" /> - <button type="submit" hx-disabled-elt="this">Search</button> - <div class="htmx-indicator">Search running!</div> - </form> - <div id="redacted-search-results"> - {bestTorrentsTable} - </div> - <!-- refresh the page if the uniqueRunId is different --> - <input - hidden - type="text" - id="autorefresh" - name="hasItBeenRestarted" - value={uniqueRunId} - hx-get="/autorefresh" - hx-trigger="every 5s" - hx-swap="none" - /> + {body} </body> |] +artistPage :: + ( HasField "artistRedactedId" dat Natural, + MonadPostgres m, + MonadOtel m, + MonadLogger m, + MonadThrow m, + MonadTransmission m + ) => + dat -> + m Html +artistPage dat = runTransaction $ do + fresh <- getBestTorrentsData (Just $ getLabel @"artistRedactedId" dat) + let artistName = fresh & findMaybe (\t -> t.artists & findMaybe (\a -> if a.artistId == (dat.artistRedactedId & fromIntegral @Natural @Int) then Just a.artistName else Nothing)) + let torrents = mkBestTorrentsTable fresh + pure $ + htmlPageChrome + ( case artistName of + Nothing -> "whatcd-resolver" + Just a -> [fmt|{a} - Artist Page - whatcd-resolver|] + ) + [hsx| + Artist ID: {dat.artistRedactedId} + + {torrents} + |] + type Handlers m = HandlerResponses m -> Map Text (m ResponseReceived) -type HandlerResponses m = T2 "h" ((Otel.Span -> m Html) -> m ResponseReceived) "plain" (m Wai.Response -> m ResponseReceived) +data HandlerResponses m = HandlerResponses + { -- | render html + html :: (Otel.Span -> m Html) -> m ResponseReceived, + -- | render html after parsing some query arguments + htmlWithQueryArgs :: forall a. (Parse Query a -> (a -> Otel.Span -> m Html) -> m ResponseReceived), + -- | render html or reload the page via the Referer header if no htmx + htmlOrReferer :: (Otel.Span -> m Html) -> m ResponseReceived, + -- | render a plain wai response + plain :: (m Wai.Response -> m ResponseReceived) + } runHandlers :: (MonadOtel m) => - Bool -> (HandlerResponses m -> m ResponseReceived) -> (HandlerResponses m -> Map Text (m ResponseReceived)) -> Wai.Request -> (Wai.Response -> IO ResponseReceived) -> m ResponseReceived -runHandlers debug defaultHandler handlers req respond = withRunInIO $ \runInIO -> do - let renderHtml = - if debug - then Html.Pretty.renderHtml >>> stringToText >>> textToBytesUtf8 >>> toLazyBytes - else Html.renderHtml - let hh route act = +runHandlers defaultHandler handlers req respond = withRunInIO $ \runInIO -> do + let path = req & Wai.pathInfo & Text.intercalate "/" + let html' resp act = Otel.inSpan' - [fmt|Route {route }|] + [fmt|Route /{path}|] ( Otel.defaultSpanArguments { Otel.attributes = HashMap.fromList - [ ("server.path", Otel.toAttribute @Text route) + [ ("_.server.path", Otel.toAttribute @Text path), + ("_.server.query_args", Otel.toAttribute @Text (req.rawQueryString & bytesToTextUtf8Lenient)) ] } ) ( \span -> do - res <- act span - liftIO $ respond . Wai.responseLBS Http.ok200 ([("Content-Type", "text/html")] <> res.extraHeaders) . renderHtml $ res.html + res <- act span <&> (\h -> T2 (label @"html" h) (label @"extraHeaders" [])) + addEventSimple span "Got Html result, rendering…" + liftIO $ respond (resp res) ) - let h route act = hh route (\span -> act span <&> (\html -> T2 (label @"html" html) (label @"extraHeaders" []))) + let htmlResp res = Wai.responseLBS Http.ok200 ([("Content-Type", "text/html")] <> res.extraHeaders) . Html.renderHtml $ res.html + let html = html' htmlResp + let htmlOrReferer = html' $ \res -> htmxOrReferer req (htmlResp res) - let path = (req & Wai.pathInfo & Text.intercalate "/") let handlerResponses = - ( T2 - (label @"h" (h path)) - (label @"plain" (\m -> liftIO $ runInIO m >>= respond)) + ( HandlerResponses + { plain = (\m -> liftIO $ runInIO m >>= respond), + html, + htmlWithQueryArgs = \parser act -> + case req & Parse.runParse "Unable to find the right request query arguments" (lmap Wai.queryString parser) of + Right a -> html (act a) + Left err -> + html + ( \span -> do + recordException + span + ( T2 + (label @"type_" "Query Parse Exception") + (label @"message" (prettyErrorTree err)) + ) + + pure + [hsx| + <h1>Error:</h1> + <pre>{err & prettyErrorTree}</pre> + |] + ), + htmlOrReferer + } ) let handler = (handlers handlerResponses) @@ -363,6 +454,24 @@ singleQueryArgument field inner = ) >>> Parse.fieldParser inner +singleQueryArgumentMay :: Text -> FieldParser ByteString to -> Parse Http.Query (Maybe to) +singleQueryArgumentMay field inner = + Parse.mkParsePushContext + field + ( \(ctx, qry) -> case qry + & mapMaybe + ( \(k, v) -> + if k == (field & textToBytesUtf8) + then Just v + else Nothing + ) of + [] -> Right Nothing + [Nothing] -> Left [fmt|Expected one query argument with a value, but "{field}" was a query flag|] + [Just one] -> Right (Just one) + more -> Left [fmt|More than one value for query argument "{field}": {show more}, at {ctx & Parse.showContext}|] + ) + >>> Parse.maybe (Parse.fieldParser inner) + -- | Make sure we can parse the given Text into an URI. textToURI :: Parse Text URI textToURI = @@ -405,7 +514,8 @@ snipsRedactedSearch :: HasField "searchstr" r ByteString, MonadThrow m, MonadTransmission m, - MonadOtel m + MonadOtel m, + MonadRedacted m ) => r -> m Html @@ -417,7 +527,11 @@ snipsRedactedSearch dat = do ] runTransaction $ do t - getBestTorrentsTable + getBestTorrentsTable (Nothing :: Maybe (Label "artistRedactedId" Natural)) + +data ArtistFilter = ArtistFilter + { onlyArtist :: Maybe (Label "artistId" Text) + } getBestTorrentsTable :: ( MonadTransmission m, @@ -426,55 +540,113 @@ getBestTorrentsTable :: MonadPostgres m, MonadOtel m ) => + Maybe (Label "artistRedactedId" Natural) -> Transaction m Html -getBestTorrentsTable = do - bestStale :: [TorrentData ()] <- getBestTorrents - actual <- +getBestTorrentsTable dat = do + fresh <- getBestTorrentsData dat + pure $ mkBestTorrentsTable fresh + +doIfJust :: (Applicative f) => (a -> f ()) -> Maybe a -> f () +doIfJust = traverse_ + +getBestTorrentsData :: + ( MonadTransmission m, + MonadThrow m, + MonadLogger m, + MonadPostgres m, + MonadOtel m + ) => + Maybe (Label "artistRedactedId" Natural) -> + Transaction m [TorrentData (Label "percentDone" Percentage)] +getBestTorrentsData artistFilter = inSpan' "get torrents table data" $ \span -> do + artistFilter & doIfJust (\a -> addAttribute span "artist-filter.redacted-id" (a.artistRedactedId & showToText & Otel.toAttribute)) + let getBest = getBestTorrents GetBestTorrentsFilter {onlyArtist = artistFilter, onlyDownloaded = False} + bestStale :: [TorrentData ()] <- getBest + (statusInfo, transmissionStatus) <- getAndUpdateTransmissionTorrentsStatus ( bestStale & mapMaybe ( \td -> case td.torrentStatus of - InTransmission h -> Just h + InTransmission h -> Just (getLabel @"torrentHash" h, td) _ -> Nothing ) - <&> (\t -> (getLabel @"torrentHash" t, t.transmissionInfo)) & Map.fromList ) - let fresh = - bestStale - -- we have to update the status of every torrent that’s not in tranmission anymore - -- TODO I feel like it’s easier (& more correct?) to just do the database request again … - <&> ( \td -> case td.torrentStatus of - InTransmission info -> - case actual & Map.lookup (getLabel @"torrentHash" info) of - -- TODO this is also pretty dumb, cause it assumes that we have the torrent file if it was in transmission before, - -- which is an internal factum that is established in getBestTorrents (and might change later) - Nothing -> td {torrentStatus = NotInTransmissionYet} - Just transmissionInfo -> td {torrentStatus = InTransmission (T2 (getLabel @"torrentHash" info) (label @"transmissionInfo" transmissionInfo))} - NotInTransmissionYet -> td {torrentStatus = NotInTransmissionYet} - NoTorrentFileYet -> td {torrentStatus = NoTorrentFileYet} - ) + bestBest <- + -- Instead of serving a stale table when a torrent gets deleted, fetch + -- the whole view again. This is a little wasteful, but torrents + -- shouldn’t get deleted very often, so it’s fine. + -- Re-evaluate invariant if this happens too often. + if statusInfo.knownTorrentsStale + then inSpan' "Fetch torrents table data again" $ + \span' -> do + addEventSimple span' "The transmission torrent list was out of date, refetching torrent list." + getBest + else pure bestStale + pure $ + bestBest + -- we have to update the status of every torrent that’s not in tranmission anymore + -- TODO I feel like it’s easier (& more correct?) to just do the database request again … + <&> ( \td -> case td.torrentStatus of + InTransmission info -> + case transmissionStatus & Map.lookup (getLabel @"torrentHash" info) of + -- TODO this is also pretty dumb, cause it assumes that we have the torrent file if it was in transmission before, + -- which is an internal factum that is established in getBestTorrents (and might change later) + Nothing -> td {torrentStatus = NotInTransmissionYet} + Just transmissionInfo -> td {torrentStatus = InTransmission (T2 (getLabel @"torrentHash" info) (label @"transmissionInfo" transmissionInfo))} + NotInTransmissionYet -> td {torrentStatus = NotInTransmissionYet} + NoTorrentFileYet -> td {torrentStatus = NoTorrentFileYet} + ) + +mkBestTorrentsTable :: [TorrentData (Label "percentDone" Percentage)] -> Html +mkBestTorrentsTable fresh = do let localTorrent b = case b.torrentStatus of - NoTorrentFileYet -> [hsx|<button hx-post="snips/redacted/getTorrentFile" hx-swap="outerHTML" hx-vals={Enc.encToBytesUtf8 $ Enc.object [("torrent-id", Enc.int b.torrentId)]}>Upload Torrent</button>|] + NoTorrentFileYet -> + [hsx| + <form method="post"> + <input type="hidden" name="torrent-id" value={b.torrentId & show} /> + <button + formaction="snips/redacted/getTorrentFile" + hx-post="snips/redacted/getTorrentFile" + hx-swap="outerHTML" + hx-vals={Enc.encToBytesUtf8 $ Enc.object [("torrent-id", Enc.int b.torrentId)]}>Upload Torrent</button> + </form> + |] InTransmission info -> [hsx|{info.transmissionInfo.percentDone.unPercentage}% done|] NotInTransmissionYet -> [hsx|<button hx-post="snips/redacted/startTorrentFile" hx-swap="outerHTML" hx-vals={Enc.encToBytesUtf8 $ Enc.object [("torrent-id", Enc.int b.torrentId)]}>Start Torrent</button>|] let bestRows = fresh & foldMap ( \b -> do + let artists = + b.artists + <&> ( \a -> + T2 + (label @"url" [fmt|/artist?redacted_id={a.artistId}|]) + (label @"content" $ Html.toHtml @Text a.artistName) + ) + & mkLinkList + [hsx| <tr> <td>{localTorrent b}</td> <td>{Html.toHtml @Int b.groupId}</td> - <td>{Html.toHtml @Text b.torrentGroupJson.artist}</td> - <td>{Html.toHtml @Text b.torrentGroupJson.groupName}</td> + <td> + {artists} + </td> + <td> + <a href={mkRedactedTorrentLink (Arg b.groupId)} target="_blank"> + {Html.toHtml @Text b.torrentGroupJson.groupName} + </a> + </td> + <td>{Html.toHtml @Natural b.torrentGroupJson.groupYear}</td> <td>{Html.toHtml @Int b.seedingWeight}</td> + <td>{Html.toHtml @Text b.torrentFormat}</td> <td><details hx-trigger="toggle once" hx-post="snips/redacted/torrentDataJson" hx-vals={Enc.encToBytesUtf8 $ Enc.object [("torrent-id", Enc.int b.torrentId)]}></details></td> </tr> |] ) - pure $ - [hsx| + [hsx| <table class="table"> <thead> <tr> @@ -482,9 +654,10 @@ getBestTorrentsTable = do <th>Group ID</th> <th>Artist</th> <th>Name</th> + <th>Year</th> <th>Weight</th> + <th>Format</th> <th>Torrent</th> - <th>Torrent Group</th> </tr> </thead> <tbody> @@ -493,6 +666,15 @@ getBestTorrentsTable = do </table> |] +mkLinkList :: [T2 "url" Text "content" Html] -> Html +mkLinkList xs = + xs + <&> ( \x -> do + [hsx|<a href={x.url}>{x.content}</a>|] + ) + & List.intersperse ", " + & mconcat + getTransmissionTorrentsTable :: (MonadTransmission m, MonadThrow m, MonadLogger m, MonadOtel m) => m Html getTransmissionTorrentsTable = do @@ -528,7 +710,7 @@ assertOneUpdated :: m () assertOneUpdated span name x = case x.numberOfRowsAffected of 1 -> pure () - n -> appThrowTree span ([fmt|{name :: Text}: Expected to update exactly one row, but updated {n :: Natural} row(s)|]) + n -> appThrow span ([fmt|{name :: Text}: Expected to update exactly one row, but updated {n :: Natural} row(s)|]) migrate :: ( MonadPostgres m, @@ -556,76 +738,86 @@ migrate = inSpan "Database Migration" $ do UNIQUE(torrent_id) ); + CREATE INDEX IF NOT EXISTS redacted_torrents_json_torrent_group_fk ON redacted.torrents_json (torrent_group); + + ALTER TABLE redacted.torrents_json ADD COLUMN IF NOT EXISTS torrent_file bytea NULL; ALTER TABLE redacted.torrents_json ADD COLUMN IF NOT EXISTS transmission_torrent_hash text NULL; - -- inflect out values of the full json + -- the seeding weight is used to find the best torrent in a group. + CREATE OR REPLACE FUNCTION calc_seeding_weight(full_json_result jsonb) RETURNS int AS $$ + BEGIN + RETURN + -- three times seeders plus one times snatches + (3 * (full_json_result->'seeders')::integer + + (full_json_result->'snatches')::integer + ) + -- prefer remasters by multiplying them with 3 + * (CASE + WHEN full_json_result->>'remasterTitle' ILIKE '%remaster%' + THEN 3 + ELSE 1 + END) + -- slightly push mp3 V0, to make sure it’s preferred over 320 CBR + * (CASE + WHEN full_json_result->>'encoding' ILIKE '%v0%' + THEN 2 + ELSE 1 + END) + -- remove 24bit torrents from the result (wayyy too big) + * (CASE + WHEN full_json_result->>'encoding' ILIKE '%24bit%' + THEN 0 + ELSE 1 + END) + -- discount FLACS, so we only use them when there’s no mp3 alternative (to save space) + / (CASE + WHEN full_json_result->>'encoding' ILIKE '%lossless%' + THEN 5 + ELSE 1 + END) + ; + END; + $$ LANGUAGE plpgsql IMMUTABLE; + + ALTER TABLE redacted.torrents_json + ADD COLUMN IF NOT EXISTS seeding_weight int GENERATED ALWAYS AS (calc_seeding_weight(full_json_result)) STORED; + + -- inflect out values of the full json CREATE OR REPLACE VIEW redacted.torrents AS SELECT t.id, t.torrent_id, t.torrent_group, -- the seeding weight is used to find the best torrent in a group. - ( ((full_json_result->'seeders')::integer*3 - + (full_json_result->'snatches')::integer - ) - -- prefer remasters by multiplying them with 3 - * (CASE - WHEN full_json_result->>'remasterTitle' ILIKE '%remaster%' - THEN 3 - ELSE 1 - END) - ) - AS seeding_weight, + t.seeding_weight, t.full_json_result, t.torrent_file, t.transmission_torrent_hash FROM redacted.torrents_json t; + CREATE INDEX IF NOT EXISTS torrents_json_seeding ON redacted.torrents_json(((full_json_result->'seeding')::integer)); CREATE INDEX IF NOT EXISTS torrents_json_snatches ON redacted.torrents_json(((full_json_result->'snatches')::integer)); |] () -httpTorrent :: - ( MonadIO m, - MonadThrow m - ) => - Otel.Span -> - Http.Request -> - m ByteString -httpTorrent span req = - Http.httpBS req - >>= assertM - span - ( \resp -> do - let statusCode = resp & Http.responseStatus & (.statusCode) - contentType = - resp - & Http.responseHeaders - & List.lookup "content-type" - <&> Wai.parseContentType - <&> (\(ct, _mimeAttributes) -> ct) - if - | statusCode == 200, - Just "application/x-bittorrent" <- contentType -> - Right $ (resp & Http.responseBody) - | statusCode == 200, - Just otherType <- contentType -> - Left [fmt|Redacted returned a non-torrent body, with content-type "{otherType}"|] - | statusCode == 200, - Nothing <- contentType -> - Left [fmt|Redacted returned a body with unspecified content type|] - | code <- statusCode -> Left [fmt|Redacted returned an non-200 error code, code {code}: {resp & showPretty}|] - ) - runAppWith :: AppT IO a -> IO (Either TmpPg.StartError a) runAppWith appT = withTracer $ \tracer -> withDb $ \db -> do - pgFormat <- readTools (label @"toolsEnvVar" "WHATCD_RESOLVER_TOOLS") (readTool "pg_format") - let config = label @"logDatabaseQueries" LogDatabaseQueries + tool <- readTools (label @"toolsEnvVar" "WHATCD_RESOLVER_TOOLS") (readTool "pg_format") + prettyPrintDatabaseQueries <- + Env.lookupEnv "WHATCD_RESOLVER_PRETTY_PRINT_DATABASE_QUERIES" >>= \case + Nothing -> pure DontPrettyPrintDatabaseQueries + Just _ -> do + pgFormat <- initPgFormatPool (label @"pgFormat" tool) + pure $ PrettyPrintDatabaseQueries pgFormat + let pgConfig = + T2 + (label @"logDatabaseQueries" LogDatabaseQueries) + (label @"prettyPrintDatabaseQueries" prettyPrintDatabaseQueries) pgConnPool <- Pool.newPool $ Pool.defaultPoolConfig @@ -633,12 +825,29 @@ runAppWith appT = withTracer $ \tracer -> withDb $ \db -> do {- resource destruction -} Postgres.close {- unusedResourceOpenTime -} 10 {- max resources across all stripes -} 20 - transmissionSessionId <- newEmptyMVar + transmissionSessionId <- newIORef Nothing + redactedApiKey <- + Env.lookupEnv "WHATCD_RESOLVER_REDACTED_API_KEY" >>= \case + Just k -> pure (k & stringToBytesUtf8) + Nothing -> runStderrLoggingT $ do + logInfo "WHATCD_RESOLVER_REDACTED_API_KEY was not set, trying pass" + runCommandExpect0 "pass" ["internet/redacted/api-keys/whatcd-resolver"] let newAppT = do - logInfo [fmt|Running with config: {showPretty config}|] + logInfo [fmt|Running with config: {showPretty pgConfig}|] logInfo [fmt|Connected to database at {db & TmpPg.toDataDirectory} on socket {db & TmpPg.toConnectionString}|] appT runReaderT newAppT.unAppT Context {..} + `catch` ( \case + AppExceptionPretty p -> throwM $ EscapedException (p & Pretty.prettyErrs) + AppExceptionTree t -> throwM $ EscapedException (t & prettyErrorTree & textToString) + ) + +-- | Just a silly wrapper so that correctly format any 'AppException' that would escape the runAppWith scope. +newtype EscapedException = EscapedException String + deriving anyclass (Exception) + +instance Show EscapedException where + show (EscapedException s) = s withTracer :: (Otel.Tracer -> IO c) -> IO c withTracer f = do diff --git a/users/Profpatsch/whatcd-resolver/whatcd-resolver.cabal b/users/Profpatsch/whatcd-resolver/whatcd-resolver.cabal index a9bd04827b83..de89a339bb7a 100644 --- a/users/Profpatsch/whatcd-resolver/whatcd-resolver.cabal +++ b/users/Profpatsch/whatcd-resolver/whatcd-resolver.cabal @@ -80,7 +80,6 @@ library pa-prelude, pa-error-tree, pa-label, - pa-json, pa-field-parser, pa-run-command, aeson-better-errors, @@ -119,3 +118,7 @@ executable whatcd-resolver build-depends: base >=4.15 && <5, whatcd-resolver + + ghc-options: + -threaded + diff --git a/users/Profpatsch/xdg-cache-home.nix b/users/Profpatsch/xdg-cache-home.nix new file mode 100644 index 000000000000..6dc02b7f1d66 --- /dev/null +++ b/users/Profpatsch/xdg-cache-home.nix @@ -0,0 +1,14 @@ +{ depot, pkgs, lib, ... }: +depot.nix.writeExecline "xdg-cache-home" { } [ + "if" + "-n" + [ + "printenv" + "XDG_CACHE_HOME" + ] + "importas" + "HOME" + "HOME" + "echo" + "\${HOME}/.cache" +] diff --git a/users/amjoseph/OWNERS b/users/amjoseph/OWNERS new file mode 100644 index 000000000000..a99992be6093 --- /dev/null +++ b/users/amjoseph/OWNERS @@ -0,0 +1,3 @@ +set noparent + +amjoseph diff --git a/users/amjoseph/keys.nix b/users/amjoseph/keys.nix new file mode 100644 index 000000000000..8cc2f24369b1 --- /dev/null +++ b/users/amjoseph/keys.nix @@ -0,0 +1,22 @@ +{ ... }: + +let + # Long-term, air-gapped PGP key. This key is used only for signing other + # keys. It is a minor hassle for me to access this key. + airgap = "F0B74D717CDE8412A3E0D4D5F29AC8080DA8E1E0"; + + # Stored in an HSM. Signed by the above key. + current = "D930411B675A011EB9590713DC4AB809B13BE76D"; + + # Chat protocols that depend on DNS, WebPKI, or E.164 are lame. This is not. + ricochet = "emhxygy5mezcovm5a6q5hze5eqfqgieww56eh4ttwmrolwqmzgb6qiyd"; + + # This ssh key is for depot. Please don't use it elsewhere, except to give + # me the ability to set a system-specific key elsewhere. Not currently + # stored in an HSM, but I'm working on that. + ssh-for-depot = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOE5e0HrwQTI5KOaU12J0AJG5zDpWn4g/U+oFXz7SkbD"; + +in +{ + all = [ ssh-for-depot ]; +} diff --git a/users/aspen/pkgs/cargo-hakari.nix b/users/aspen/pkgs/cargo-hakari.nix deleted file mode 100644 index b6f4e7e40007..000000000000 --- a/users/aspen/pkgs/cargo-hakari.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ pkgs, ... }: - -with pkgs; - -rustPlatform.buildRustPackage rec { - pname = "cargo-hakari"; - version = "0.9.13"; - - src = fetchFromGitHub { - owner = "facebookincubator"; - repo = "cargo-guppy"; - rev = "cargo-hakari-${version}"; - sha256 = "11ds2zryxdd6rvszkpphb0xnfg7rqisg6kixrwyiydjrm5rdjg9d"; - }; - - cargoSha256 = "0b2hjyak5v4m3g5zjk2q8bdb4iv3015qw1rmhpclv4cv48lcmdbb"; - - buildAndTestSubdir = "tools/cargo-hakari"; - - nativeBuildInputs = [ - pkg-config - ]; - - buildInputs = [ - openssl - ]; -} diff --git a/users/aspen/pkgs/cargo-nextest.nix b/users/aspen/pkgs/cargo-nextest.nix deleted file mode 100644 index dbf3bd7eef19..000000000000 --- a/users/aspen/pkgs/cargo-nextest.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ pkgs, ... }: - -with pkgs; - -rustPlatform.buildRustPackage rec { - pname = "cargo-nextest"; - version = "0.9.36"; - - src = fetchFromGitHub { - owner = "nextest-rs"; - repo = "nextest"; - rev = "cargo-nextest-${version}"; - sha256 = "1g40r38bqmdhc0dy07pj27vkc64d3fw6v5z2vwn82xld2h9dg7w2"; - }; - - cargoSha256 = "1g862azgkn3xk3v3chs8hv1b1prj1pq2vfzbhcx6ir9l00kv6gcv"; - - cargoTestFlags = [ - "--" - "--skip" - "tests_integration::test_relocated_run" - "--skip" - "tests_integration::test_run" - "--skip" - "tests_integration::test_run_after_build" - ]; -} diff --git a/users/aspen/secrets/bbbg.age b/users/aspen/secrets/bbbg.age index ebc0df233898..379441b74f5c 100644 --- a/users/aspen/secrets/bbbg.age +++ b/users/aspen/secrets/bbbg.age Binary files differdiff --git a/users/aspen/secrets/buildkite-ssh-key.age b/users/aspen/secrets/buildkite-ssh-key.age index d9587f11df4b..61ad416385c6 100644 --- a/users/aspen/secrets/buildkite-ssh-key.age +++ b/users/aspen/secrets/buildkite-ssh-key.age Binary files differdiff --git a/users/aspen/secrets/buildkite-token.age b/users/aspen/secrets/buildkite-token.age index 320ee06c0937..5bd4923de34f 100644 --- a/users/aspen/secrets/buildkite-token.age +++ b/users/aspen/secrets/buildkite-token.age Binary files differdiff --git a/users/aspen/secrets/cloudflare.age b/users/aspen/secrets/cloudflare.age index 4f42ee782165..c94fef706c4c 100644 --- a/users/aspen/secrets/cloudflare.age +++ b/users/aspen/secrets/cloudflare.age @@ -1,9 +1,9 @@ age-encryption.org/v1 --> ssh-ed25519 CpJBgQ AVkUs8tuzVlDq3FH/zRrBr5f4KR05fONM6iCluq6hyM -feS2cxFowSWfDdUQjtmIiMc5338n805yownSZ/ZWfS8 --> ssh-ed25519 LfBFbQ F67irB+DYQ8WMhaFcO+3o0O0lJsf+tWFZ9cSGSuHgA8 -EKS4zRGUEgeldjxdx4sIsnorWHoeTlXa9LJtNf9lkAM --> QvY:XSvC-grease 04 -pBnXsOF6qugcSBp+pw ---- +g65NbIxu6bVVerS93kYZpEO5ssUZfCD+sZMzOjDUdU -RîTÀmaF[BʺøÕ0ƒa_&Ë•=3dlzRVi´6-9á:þü³¿U.EÈà… üª —JΙŒß÷ÆÛA·-€qྟ÷·Ð|¡™Ð}}a=žHº+]m™tÀ¯Rø–à%9\˜õJt€š|1B¿ \ No newline at end of file +-> ssh-ed25519 CpJBgQ 5lJGEVwg5v6612p4iOoO+ShR5kLiQAG/7m2f6R6KLRc +CvFJQChj9IssFIIvVCh6/qRPfdvLx72rf3aXBD4EAEo +-> ssh-ed25519 LfBFbQ uqcGghDi2DOAJPD/7udNpdyU4NccMJSdh8mdhzEKNyU +zT+oVqOOUvTGU8fl0X/kARGESerZfUEjW3F1g6ASlxk +-> ssh-ed25519 GeE7sQ Ehb6kwx8irEbfeFy4gzK/oWmIZRdt/MEbPysJHVRsBA +grBUiZAB9Iu37LEhNU8VBvf3jMjiO+QJfJn9dnZ3DI8 +--- Zb/3hWF4WXpQlGJ+0eB4P9ZI6uCdUv5s5n7BnEaKfZM +1^¥ä9ùŸ]ïýጶtëˆeÞ«¿½)Gr¾6.\#·å&âÒH&xh½âM{D®iê^^ì¸-kª–ë5åêѽh©*æjn)¶ÎãºVæ„ÉÞšºG {•gÿò ze¨äYü…Ih]²GÊ \ No newline at end of file diff --git a/users/aspen/secrets/ddclient-password.age b/users/aspen/secrets/ddclient-password.age index 8d25e3b539bd..3bbc2e51ffd3 100644 --- a/users/aspen/secrets/ddclient-password.age +++ b/users/aspen/secrets/ddclient-password.age Binary files differdiff --git a/users/aspen/secrets/secrets.nix b/users/aspen/secrets/secrets.nix index 5bfb1c3eb08c..76126f811d02 100644 --- a/users/aspen/secrets/secrets.nix +++ b/users/aspen/secrets/secrets.nix @@ -7,8 +7,8 @@ in { "bbbg.age".publicKeys = [ grfn mugwump bbbg ]; - "cloudflare.age".publicKeys = [ grfn mugwump ]; - "ddclient-password.age".publicKeys = [ grfn mugwump ]; + "cloudflare.age".publicKeys = [ grfn mugwump ogopogo ]; + "ddclient-password.age".publicKeys = [ grfn ogopogo ]; "buildkite-ssh-key.age".publicKeys = [ grfn mugwump ogopogo ]; "buildkite-token.age".publicKeys = [ grfn mugwump ogopogo ]; "windtunnel-bot-github-token.age".publicKeys = [ grfn mugwump ogopogo ]; diff --git a/users/aspen/secrets/windtunnel-bot-github-token.age b/users/aspen/secrets/windtunnel-bot-github-token.age index daae99958276..39fd7cb3a476 100644 --- a/users/aspen/secrets/windtunnel-bot-github-token.age +++ b/users/aspen/secrets/windtunnel-bot-github-token.age @@ -1,11 +1,9 @@ age-encryption.org/v1 --> ssh-ed25519 CpJBgQ YaZ2VHyXofn2qnxRrOYO4yPPu77BEPFq/cbnfa+5WAA -VgJQoyJVxirvASD0aDsuzmbNJdIP0kpHa5b72Ri7kr8 --> ssh-ed25519 LfBFbQ cXXW3kQzZL7sU4heujIJGzvfpbX0toL2AgsJl5AZPEg -mhkKn69c/QeCJhYAFgx/MsHrIrXim3OcjkZ/rrckVLs --> ssh-ed25519 GeE7sQ /XcP3pWg+aKF1F0sPu6RpYv3Rfj2J/QI0yjg3Wgfjm0 -d+rsgbMlDJx0VrjD4/nO4UcM10hcrLxcPA3QlY1t7sQ --> "0?-grease k}d?h6 |v -7mV6AFUdCMCrkmLVQaWJPQ ---- I9Ls9AWMkSFCKw7y4pLoTkeGw7h5iROwXLuUm0nfuj8 -~‚v‰8‚&‚ü£¹3\²Òý.»%$¼›Éº°³tòóˆØQ©ˆÀ¨á”Åé¼Íœ}ˆ—ó,BEÇh w96”çö?ÓU \ No newline at end of file +-> ssh-ed25519 CpJBgQ PiY6IidA+GRbpjL91BVe9UdejWvi02SRcijiMOjXcm4 +XegOhgjdEdzXtz31PsGVyOZ10gH6P82Q1/txZcSxjIY +-> ssh-ed25519 LfBFbQ uqRF0nKMk1GrK+6pEBdmyHKu2ewDFlWwlKC+myey4gc +dgnX4eprSolXxCDNoVmGzGK9xLEmtmeg/cJihD4/8sU +-> ssh-ed25519 GeE7sQ ikAIyFR/qH1a+aa5mumiiDwa5o5aLsQeJKwQwMzgs1M +8htzhM5t2VnjRBrC+VrL23f9chlQjVGzjxMaFB7Arrs +--- Qm16HTo5wGUBKS0ly3OZDWp2etLyDS/zlxOHxPjS8PI +ƒ¤7¦–NY6Âk|‡p2·'–˜&Õ=‚m£Çq`5ÿT¸ ëNÕ9ÖNϵÖÏ)RVºU-é•)¡¼M‰¢(%pœ \ No newline at end of file diff --git a/users/aspen/system/home/machines/lusca.nix b/users/aspen/system/home/machines/lusca.nix index fc5f606639d6..2e2604e70036 100644 --- a/users/aspen/system/home/machines/lusca.nix +++ b/users/aspen/system/home/machines/lusca.nix @@ -1,14 +1,13 @@ { pkgs, lib, config, ... }: -let - inherit (builtins) pathExists; -in -{ +let inherit (builtins) pathExists; +in { imports = [ ../platforms/linux.nix ../modules/common.nix ../modules/email.nix + ../modules/depot-inbox.nix ../modules/desktop.nix ] ++ (lib.optional (pathExists ../modules/private.nix) ../modules/private.nix); @@ -28,7 +27,18 @@ in programs.alacritty.settings.font.size = lib.mkForce 5.5; - home.packages = with pkgs; [ discord steam tdesktop slack ]; + home.packages = with pkgs; [ + discord + steam + tdesktop + slack + (makeDesktopItem { + name = "Ogopogo Emacs"; + desktopName = "Ogopogo Emacs"; + icon = "emacs"; + exec = "ssh -Y ogopogo emacs"; + }) + ]; xsession.windowManager.i3.config.keybindings.XF86AudioMedia = "exec lock"; } diff --git a/users/aspen/system/home/machines/ogopogo.nix b/users/aspen/system/home/machines/ogopogo.nix index 37396a5aa1be..38dace208411 100644 --- a/users/aspen/system/home/machines/ogopogo.nix +++ b/users/aspen/system/home/machines/ogopogo.nix @@ -13,7 +13,7 @@ in ../modules/games.nix ../modules/obs.nix ../modules/development/agda.nix - ../modules/development/readyset.nix + # ../modules/development/readyset.nix ../modules/development/ocaml.nix ] ++ (lib.optional (pathExists ../modules/private.nix) ../modules/private.nix); diff --git a/users/aspen/system/home/machines/roswell.nix b/users/aspen/system/home/machines/roswell.nix index 135477b12ddf..514f19caff17 100644 --- a/users/aspen/system/home/machines/roswell.nix +++ b/users/aspen/system/home/machines/roswell.nix @@ -11,7 +11,7 @@ in ../modules/development.nix ../modules/emacs.nix ../modules/vim.nix - ../modules/development/readyset.nix + # ../modules/development/readyset.nix ../modules/tmux.nix ] ++ (lib.optional (pathExists ../modules/private.nix) ../modules/private.nix); @@ -34,7 +34,7 @@ in openssl # Nix things - nixfmt + nixfmt-classic nix-prefetch-github nixpkgs-review cachix diff --git a/users/aspen/system/home/machines/yeren.nix b/users/aspen/system/home/machines/yeren.nix index 9a7a561b5e62..54e79f950bce 100644 --- a/users/aspen/system/home/machines/yeren.nix +++ b/users/aspen/system/home/machines/yeren.nix @@ -11,7 +11,7 @@ in ../modules/common.nix ../modules/desktop.nix ../modules/development/agda.nix - ../modules/development/readyset.nix + # ../modules/development/readyset.nix ../modules/development/ocaml.nix ] ++ (lib.optional (pathExists ../modules/private.nix) ../modules/private.nix); diff --git a/users/aspen/system/home/modules/common.nix b/users/aspen/system/home/modules/common.nix index b51ae1c7db7e..5117187d6b98 100644 --- a/users/aspen/system/home/modules/common.nix +++ b/users/aspen/system/home/modules/common.nix @@ -43,7 +43,7 @@ openssl # Nix things - nixfmt + nixfmt-classic nix-prefetch-github nixpkgs-review cachix diff --git a/users/aspen/system/home/modules/depot-inbox.nix b/users/aspen/system/home/modules/depot-inbox.nix new file mode 100644 index 000000000000..0694e6db2855 --- /dev/null +++ b/users/aspen/system/home/modules/depot-inbox.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +let + depot = config.lib.depot; +in + +{ + systemd.user = { + services.sync-depot-public-inbox = { + Service.ExecStart = pkgs.writeShellScript "sync-depot-public-inbox" '' + ${depot.tools.fetch-depot-inbox}/bin/fetch-depot-inbox \ + /home/aspen/mail/tvl/ + ${pkgs.notmuch}/bin/notmuch new + ''; + }; + + timers.sync-depot-public-inbox = { + Unit.Description = "Sync the depot public inbox"; + Timer = { + OnCalendar = "*:*"; + Unit = "sync-depot-public-inbox.service"; + }; + Install.WantedBy = [ "timers.target" ]; + }; + }; +} diff --git a/users/aspen/system/home/modules/development.nix b/users/aspen/system/home/modules/development.nix index ca6ef131a37f..0da6d9cbaf94 100644 --- a/users/aspen/system/home/modules/development.nix +++ b/users/aspen/system/home/modules/development.nix @@ -68,9 +68,7 @@ with lib; nodePackages.prettier ] ++ optionals (stdenv.isLinux) [ - # TODO(aspen): replace with stable again once the current julia debacle - # is resolved upstream, see https://github.com/NixOS/nixpkgs/pull/121114 - julia_16-bin + julia-stable-bin valgrind linuxPackages.perf diff --git a/users/aspen/system/home/modules/development/rust.nix b/users/aspen/system/home/modules/development/rust.nix index c4b20f231546..3c81e2398010 100644 --- a/users/aspen/system/home/modules/development/rust.nix +++ b/users/aspen/system/home/modules/development/rust.nix @@ -10,16 +10,16 @@ with lib; home.packages = with pkgs; [ rustup + + cargo-bloat cargo-edit cargo-expand + cargo-hakari + cargo-nextest cargo-udeps - cargo-bloat sccache evcxr - depot.users.aspen.pkgs.cargo-hakari - depot.users.aspen.pkgs.cargo-nextest - # benchmarking+profiling cargo-criterion cargo-flamegraph diff --git a/users/aspen/system/home/modules/email.nix b/users/aspen/system/home/modules/email.nix index cb92c40cee89..a43e3ab5a68d 100644 --- a/users/aspen/system/home/modules/email.nix +++ b/users/aspen/system/home/modules/email.nix @@ -16,7 +16,7 @@ let personal = { primary = true; address = "root@gws.fyi"; - aliases = [ "aspen@gws.fyi" "aspen@gws.fyi" ]; + aliases = [ "aspen@gws.fyi" ]; passEntry = "root-gws-msmtp"; }; }; diff --git a/users/aspen/system/system/iso.nix b/users/aspen/system/system/iso.nix index ef5d3ed78bb0..9fa8e7ec7e3b 100644 --- a/users/aspen/system/system/iso.nix +++ b/users/aspen/system/system/iso.nix @@ -11,10 +11,6 @@ let networking.useDHCP = false; networking.firewall.enable = false; networking.wireless.enable = lib.mkForce false; - - # TODO(aspen): enabling this (in the minimal profile) fails the iso build, - # since gtk+3 needs to be built which fails due to cairo without xlibs - environment.noXlibs = false; }; in (depot.third_party.nixos { diff --git a/users/aspen/system/system/machines/lusca.nix b/users/aspen/system/system/machines/lusca.nix index 782d504aa90b..4a9202187dd0 100644 --- a/users/aspen/system/system/machines/lusca.nix +++ b/users/aspen/system/system/machines/lusca.nix @@ -10,6 +10,7 @@ ../modules/sound.nix ../modules/tvl.nix ../modules/development.nix + ../modules/prometheus-exporter.nix ]; networking.hostName = "lusca"; @@ -130,7 +131,7 @@ hardware.sensor.iio.enable = true; - hardware.opengl.driSupport32Bit = true; + hardware.graphics.enable32Bit = true; # TPM security.tpm2 = { diff --git a/users/aspen/system/system/machines/mugwump.nix b/users/aspen/system/system/machines/mugwump.nix index 4cfa11713495..4b72a247601f 100644 --- a/users/aspen/system/system/machines/mugwump.nix +++ b/users/aspen/system/system/machines/mugwump.nix @@ -9,7 +9,6 @@ with lib; (depot.path.origSrc + "/ops/modules/prometheus-fail2ban-exporter.nix") (depot.path.origSrc + "/users/aspen/xanthous/server/module.nix") (depot.third_party.agenix.src + "/modules/age.nix") - depot.third_party.ddclient.module ]; networking.hostName = "mugwump"; @@ -83,7 +82,6 @@ with lib; in { cloudflare.file = secret "cloudflare"; - ddclient-password.file = secret "ddclient-password"; buildkite-ssh-key = { file = secret "buildkite-ssh-key"; @@ -119,161 +117,9 @@ with lib; }; }; - services.grafana = { - enable = true; - dataDir = "/var/lib/grafana"; - - settings = { - server = { - http_port = 3000; - root_url = "https://metrics.gws.fyi"; - domain = "metrics.gws.fyi"; - }; - analytics.reporting_enabled = false; - }; - - provision = { - enable = true; - datasources.settings.datasources = [{ - name = "Prometheus"; - type = "prometheus"; - url = "http://localhost:9090"; - }]; - }; - }; - security.acme.defaults.email = "root@gws.fyi"; security.acme.acceptTerms = true; - services.nginx = { - enable = true; - statusPage = true; - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedTlsSettings = true; - recommendedProxySettings = true; - - virtualHosts = { - "metrics.gws.fyi" = { - enableACME = true; - forceSSL = true; - locations."/" = { - proxyPass = "http://localhost:${toString config.services.grafana.settings.server.http_port}"; - }; - }; - }; - }; - - services.deprecated-ddclient = { - package = depot.third_party.ddclient; - enable = true; - domains = [ "home.gws.fyi" ]; - interval = "1d"; - zone = "gws.fyi"; - protocol = "cloudflare"; - username = "root@gws.fyi"; - passwordFile = config.age.secretsDir + "/ddclient-password"; - quiet = true; - }; - - security.acme.certs."metrics.gws.fyi" = { - dnsProvider = "cloudflare"; - credentialsFile = config.age.secretsDir + "/cloudflare"; - webroot = mkForce null; - }; - - services.prometheus = { - enable = true; - exporters = { - node = { - enable = true; - openFirewall = false; - - enabledCollectors = [ - "processes" - "systemd" - "tcpstat" - "wifi" - ]; - }; - - nginx = { - enable = true; - openFirewall = true; - sslVerify = false; - constLabels = [ "host=mugwump" ]; - }; - - blackbox = { - enable = true; - openFirewall = true; - configFile = pkgs.writeText "blackbox-exporter.yaml" (builtins.toJSON { - modules = { - https_2xx = { - prober = "http"; - http = { - method = "GET"; - fail_if_ssl = false; - fail_if_not_ssl = true; - preferred_ip_protocol = "ip4"; - }; - }; - }; - }); - }; - }; - - scrapeConfigs = [ - { - job_name = "node"; - scrape_interval = "5s"; - static_configs = [{ - targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ]; - }]; - } - { - job_name = "nginx"; - scrape_interval = "5s"; - static_configs = [{ - targets = [ "localhost:${toString config.services.prometheus.exporters.nginx.port}" ]; - }]; - } - { - job_name = "xanthous_server"; - scrape_interval = "1s"; - static_configs = [{ - targets = [ "localhost:${toString config.services.xanthous-server.metricsPort}" ]; - }]; - } - { - job_name = "blackbox"; - metrics_path = "/probe"; - params.module = [ "https_2xx" ]; - scrape_interval = "5s"; - static_configs = [{ - targets = [ - "https://gws.fyi" - "https://windtunnel.ci" - "https://app.windtunnel.ci" - "https://metrics.gws.fyi" - ]; - }]; - relabel_configs = [{ - source_labels = [ "__address__" ]; - target_label = "__param_target"; - } - { - source_labels = [ "__param_target" ]; - target_label = "instance"; - } - { - target_label = "__address__"; - replacement = "localhost:${toString config.services.prometheus.exporters.blackbox.port}"; - }]; - } - ]; - }; - services.xanthous-server.enable = true; virtualisation.docker = { diff --git a/users/aspen/system/system/machines/ogopogo.nix b/users/aspen/system/system/machines/ogopogo.nix index e80a0906dbf8..3d41a839e17b 100644 --- a/users/aspen/system/system/machines/ogopogo.nix +++ b/users/aspen/system/system/machines/ogopogo.nix @@ -11,6 +11,8 @@ ../modules/tvl.nix ../modules/development.nix ../modules/wireshark.nix + ../modules/metrics.nix + ../modules/prometheus-exporter.nix ]; networking.hostName = "ogopogo"; @@ -77,12 +79,13 @@ videoDrivers = [ "nvidia" ]; dpi = 100; }; - hardware.opengl.enable = true; + hardware.graphics.enable = true; services.picom = { enable = true; vSync = true; }; - hardware.opengl.driSupport32Bit = true; + hardware.graphics.enable32Bit = true; + hardware.nvidia.open = true; services.postgresql = { enable = true; @@ -90,18 +93,32 @@ authentication = "host all all 0.0.0.0/0 md5"; dataDir = "/data/postgresql"; package = pkgs.postgresql_15; - port = 5431; settings = { wal_level = "logical"; }; }; - nix.settings.substituters = [ "ssh://grfn@172.16.0.5" ]; - nix.settings.trusted-substituters = [ "ssh://grfn@172.16.0.5" ]; - programs.ssh.knownHosts.mugwump = { - extraHostNames = [ "172.16.0.5" ]; - publicKeyFile = pkgs.writeText "mugwump.pub" '' - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFE2fxPgWO+zeQoLBTgsgxP7Vg7QNHlrQ+Rb3fHFTomB - ''; + # ddclient + age.secrets = + let + secret = name: depot.users.aspen.secrets."${name}.age"; + in + { + ddclient-password.file = secret "ddclient-password"; + }; + + services.ddclient = { + enable = true; + domains = [ "home.gws.fyi" ]; + interval = "1d"; + zone = "gws.fyi"; + protocol = "cloudflare"; + username = "root@gws.fyi"; + passwordFile = config.age.secretsDir + "/ddclient-password"; + quiet = true; + } + # TODO(aspen): Remove when upgrading past 4.0.0 + // lib.optionalAttrs (lib.versionOlder pkgs.ddclient.version "4.0.0") { + ssl = false; }; } diff --git a/users/aspen/system/system/machines/yeren.nix b/users/aspen/system/system/machines/yeren.nix index 653f0cd44cd5..4b563df635aa 100644 --- a/users/aspen/system/system/machines/yeren.nix +++ b/users/aspen/system/system/machines/yeren.nix @@ -93,7 +93,7 @@ sof-firmware ]; - hardware.opengl.extraPackages = with pkgs; [ + hardware.graphics.extraPackages = with pkgs; [ vaapiIntel vaapiVdpau libvdpau-va-gl @@ -118,7 +118,7 @@ lightdm-greeter.fprintAuth = true; }; - hardware.opengl.driSupport32Bit = true; + hardware.graphics.enable32Bit = true; hardware.pulseaudio.extraConfig = '' load-module module-remap-source source_name=KompleteAudio6_1 source_properties=device.description=KompleteAudio6Input1 master=alsa_input.usb-Native_Instruments_Komplete_Audio_6_458E0FFD-00.multichannel-input remix=no channels=1 master_channel_map=front-left channel_map=mono diff --git a/users/aspen/system/system/modules/containers.nix b/users/aspen/system/system/modules/containers.nix new file mode 100644 index 000000000000..587e7426b582 --- /dev/null +++ b/users/aspen/system/system/modules/containers.nix @@ -0,0 +1,12 @@ +{ config, lib, pkgs, ... }: + +{ + virtualisation.podman = { + enable = true; + defaultNetwork.settings = { dns_enabled = true; }; + dockerCompat = true; + dockerSocket.enable = true; + }; + + users.users.aspen.extraGroups = [ "docker" ]; +} diff --git a/users/aspen/system/system/modules/development.nix b/users/aspen/system/system/modules/development.nix index bd5e326b2ea6..6e96ae3c8e7f 100644 --- a/users/aspen/system/system/modules/development.nix +++ b/users/aspen/system/system/modules/development.nix @@ -1,8 +1,9 @@ { config, lib, pkgs, ... }: { - virtualisation.docker.enable = true; - users.users.aspen.extraGroups = [ "docker" ]; + imports = [ + ./containers.nix + ]; security.pam.loginLimits = [ { diff --git a/users/aspen/system/system/modules/laptop.nix b/users/aspen/system/system/modules/laptop.nix index 89c880973d80..57b2bc5a45a9 100644 --- a/users/aspen/system/system/modules/laptop.nix +++ b/users/aspen/system/system/modules/laptop.nix @@ -20,4 +20,6 @@ criticalPowerAction = "Hibernate"; percentageAction = 3; }; + + services.libinput.touchpad.naturalScrolling = true; } diff --git a/users/aspen/system/system/modules/metrics.nix b/users/aspen/system/system/modules/metrics.nix new file mode 100644 index 000000000000..0abfb27eeeb5 --- /dev/null +++ b/users/aspen/system/system/modules/metrics.nix @@ -0,0 +1,197 @@ +{ depot, config, lib, pkgs, ... }: + +with lib; + +let + nodesToScrape = [ + "ogopogo" + # "dobharchu" + "mugwump" + # "yeren" + "lusca" + ]; + + nodesRunningNginx = [ + "ogopogo" + "mugwump" + ]; + + nodesRunningPostgres = [ + "ogopogo" + ]; + + blackboxTargets = [ + "https://gws.fyi" + "https://windtunnel.ci" + "https://app.windtunnel.ci" + "https://metrics.gws.fyi" + ]; +in +{ + imports = [ + (depot.third_party.agenix.src + "/modules/age.nix") + ]; + + config = { + services.postgresql = { + ensureUsers = [{ + name = config.services.grafana.settings.database.user; + ensureDBOwnership = true; + }]; + + ensureDatabases = [ + config.services.grafana.settings.database.name + ]; + }; + + services.grafana = { + enable = true; + dataDir = "/var/lib/grafana"; + + settings = { + server = { + http_port = 3000; + root_url = "https://metrics.gws.fyi"; + domain = "metrics.gws.fyi"; + }; + analytics.reporting_enabled = false; + + database = { + type = "postgres"; + user = "grafana"; + name = "grafana"; + host = "/run/postgresql"; + }; + }; + + provision = { + enable = true; + datasources.settings.datasources = [{ + name = "Prometheus"; + type = "prometheus"; + url = "http://localhost:9090"; + }]; + }; + }; + + security.acme.defaults.email = "root@gws.fyi"; + security.acme.acceptTerms = true; + + services.nginx = { + enable = true; + statusPage = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedTlsSettings = true; + recommendedProxySettings = true; + + virtualHosts = { + "metrics.gws.fyi" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://localhost:${toString config.services.grafana.settings.server.http_port}"; + }; + }; + }; + }; + + age.secrets = { + cloudflare.file = depot.users.aspen.secrets."cloudflare.age"; + }; + + security.acme.certs."metrics.gws.fyi" = { + dnsProvider = "cloudflare"; + credentialsFile = config.age.secretsDir + "/cloudflare"; + webroot = mkForce null; + }; + + services.prometheus = { + enable = true; + retentionTime = "30d"; + exporters = { + blackbox = { + enable = true; + openFirewall = true; + configFile = pkgs.writeText "blackbox-exporter.yaml" (builtins.toJSON { + modules = { + https_2xx = { + prober = "http"; + http = { + method = "GET"; + fail_if_ssl = false; + fail_if_not_ssl = true; + preferred_ip_protocol = "ip4"; + }; + }; + }; + }); + }; + }; + + scrapeConfigs = [ + { + job_name = "node"; + scrape_interval = "5s"; + static_configs = + map + (node: { + targets = [ "${node}:${toString config.services.prometheus.exporters.node.port}" ]; + labels.node = node; + }) + nodesToScrape; + } + { + job_name = "nginx"; + scrape_interval = "5s"; + static_configs = + map + (node: { + targets = [ "${node}:${toString config.services.prometheus.exporters.nginx.port}" ]; + labels.node = node; + }) + nodesRunningNginx; + } + { + job_name = "postgres"; + scrape_interval = "5s"; + static_configs = + map + (node: { + targets = [ "${node}:${toString config.services.prometheus.exporters.postgres.port}" ]; + labels.node = node; + }) + nodesRunningPostgres; + } + { + job_name = "blackbox"; + metrics_path = "/probe"; + params.module = [ "https_2xx" ]; + scrape_interval = "5s"; + static_configs = [{ + targets = [ + "https://gws.fyi" + "https://windtunnel.ci" + "https://app.windtunnel.ci" + "https://metrics.gws.fyi" + ]; + }]; + relabel_configs = [ + { + source_labels = [ "__address__" ]; + target_label = "__param_target"; + } + { + source_labels = [ "__param_target" ]; + target_label = "instance"; + } + { + target_label = "__address__"; + replacement = "localhost:${toString config.services.prometheus.exporters.blackbox.port}"; + } + ]; + } + ]; + }; + }; +} diff --git a/users/aspen/system/system/modules/prometheus-exporter.nix b/users/aspen/system/system/modules/prometheus-exporter.nix new file mode 100644 index 000000000000..2916fc70ef96 --- /dev/null +++ b/users/aspen/system/system/modules/prometheus-exporter.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + services.prometheus.exporters = { + node = { + enable = true; + openFirewall = false; + + enabledCollectors = [ + "processes" + "systemd" + "tcpstat" + "wifi" + ]; + }; + + nginx = mkIf config.services.nginx.enable { + enable = true; + openFirewall = true; + sslVerify = false; + constLabels = [ "host=${config.networking.hostName}" ]; + }; + + postgres = mkIf config.services.postgresql.enable { + enable = true; + runAsLocalSuperUser = true; + }; + }; +} diff --git a/users/aspen/system/system/modules/sound.nix b/users/aspen/system/system/modules/sound.nix index 07a67a1ec43b..c97e19f9b2f8 100644 --- a/users/aspen/system/system/modules/sound.nix +++ b/users/aspen/system/system/modules/sound.nix @@ -2,8 +2,8 @@ { # Enable sound. - sound.enable = true; hardware.pulseaudio.enable = true; + services.pipewire.enable = false; environment.systemPackages = with pkgs; [ pulseaudio-ctl diff --git a/users/aspen/system/system/modules/xserver.nix b/users/aspen/system/system/modules/xserver.nix index f78edb207e9d..fca49ab9cca0 100644 --- a/users/aspen/system/system/modules/xserver.nix +++ b/users/aspen/system/system/modules/xserver.nix @@ -5,12 +5,11 @@ enable = true; xkb.layout = "us"; - libinput.enable = true; - - displayManager = { - defaultSession = "none+i3"; - }; windowManager.i3.enable = true; }; + + services.displayManager.defaultSession = "none+i3"; + + services.libinput.enable = true; } diff --git a/users/aspen/web/index.org b/users/aspen/web/index.org index 4be79fd79772..109f3a77a08c 100644 --- a/users/aspen/web/index.org +++ b/users/aspen/web/index.org @@ -11,22 +11,36 @@ my name is aspen smith and i'm a software engineer and musician. * work -most recently, i worked on database internals at [[https://readyset.io/][readyset]], an incrementally +i'm currently a software engineer at jane street. + +previously, i worked on database internals at [[https://readyset.io/][readyset]], an incrementally maintained, partially stateful materialized view maintenance system for sql that's wire-compatible with postgresql and mysql, based on [[https://github.com/mit-pdos/noria][noria]]. * projects -- [[https://windtunnel.ci/][windtunnel]], a continuous benchmarking software-as-a-service currently accepting early alpha users (send me an email if you want to try it out!) -- [[https://cs.tvl.fyi/depot/-/tree/users/aspen/achilles][achilles]], a compiler for (what I plan to become) a dependently typed, low-level functional programming language targeting LLVM -- [[https://github.com/glittershark/org-clubhouse][org-clubhouse]], an emacs package for lightweight integration between [[https://orgmode.org/][org-mode]] and [[https://clubhouse.io/][the clubhouse project management tool]] -- [[https://cs.tvl.fyi/depot/-/tree/users/aspen/xanthous][xanthous]], a terminal roguelike in haskell that I work on intermittently and exclusively for fun +- [[https://windtunnel.ci/][windtunnel]], a continuous benchmarking software-as-a-service currently + accepting early alpha users (send me an email if you want to try it out!) +- [[https://tvix.dev/][tvix]], a project to reimplement nix in rust with a focus on better performance, + maintainability, and extensibility. i'm a committer to the project, and mostly + focus on the implementation of the language evaluator. +- [[https://cs.tvl.fyi/depot/-/tree/users/aspen/achilles][achilles]], a compiler for (what I plan to become) a dependently typed, + low-level functional programming language targeting LLVM +- [[https://cs.tvl.fyi/depot/-/tree/users/aspen/xanthous][xanthous]], a terminal roguelike in haskell that I work on intermittently and + exclusively for fun * music - https://sacrosanct.bandcamp.com/, a post-rock project with a [[https://bandcamp.com/h34rken][friend of mine]] - [[https://soundcloud.com/missingggg][my current soundcloud]], releasing instrumental music under the name *missing* - i play bass in [[https://goodcry.band][good cry]], a rock band based in brooklyn +- my friend [[https://tasshin.com/][tasshin]] and i wrote, recorded and made music videos for 6 songs + together: + - [[https://www.youtube.com/watch?v=uX11-ClOf5k&list=PLXcbtcE8U1zcQsIWV7uzz-fUm2o9ggSbW&index=5][u're welcome bro]] + - [[https://www.youtube.com/watch?v=i1ZNdzkkJe4&list=PLXcbtcE8U1zcQsIWV7uzz-fUm2o9ggSbW&index=4]["cool"]] + - [[https://www.youtube.com/watch?v=5GOciie5Pjk&list=PLXcbtcE8U1zcQsIWV7uzz-fUm2o9ggSbW&index=3][being love]] + - [[https://www.youtube.com/watch?v=ew-rhBQmGpY&list=PLXcbtcE8U1zcQsIWV7uzz-fUm2o9ggSbW&index=2][gonna]] + - [[https://www.youtube.com/watch?v=GJBTaH2EozQ&list=PLXcbtcE8U1zcQsIWV7uzz-fUm2o9ggSbW&index=1][love like there's no tomorrow]] - you can also find a log of all the music I listen to [[https://www.last.fm/user/wildgriffin45][on last.fm]] * contact diff --git a/users/aspen/web/orgExportHTML.nix b/users/aspen/web/orgExportHTML.nix index aac4e32e7ac5..3a8e35f22d17 100644 --- a/users/aspen/web/orgExportHTML.nix +++ b/users/aspen/web/orgExportHTML.nix @@ -51,7 +51,7 @@ runCommand outName { inherit src; } '' --kill rm file.org substitute file.html "$2" \ - --replace '<title>‎</title>' "" + --replace-quiet '<title>‎</title>' "" rm file.html } diff --git a/users/azahi/OWNERS b/users/azahi/OWNERS new file mode 100644 index 000000000000..73bc1ebcc3af --- /dev/null +++ b/users/azahi/OWNERS @@ -0,0 +1,3 @@ +set noparent + +azahi diff --git a/users/azahi/pkgs/bruh/default.nix b/users/azahi/pkgs/bruh/default.nix new file mode 100644 index 000000000000..5eecf94b6203 --- /dev/null +++ b/users/azahi/pkgs/bruh/default.nix @@ -0,0 +1,42 @@ +{ pkgs +, lib +, ... +}: + +let + inherit (pkgs) + alsa-utils + fetchFromGitHub + stdenv + ; +in + +stdenv.mkDerivation (finalAttrs: { + pname = "bruh"; + version = "2.1"; + + src = + with finalAttrs; + fetchFromGitHub { + owner = "kejpies"; + repo = pname; + rev = version; + hash = "sha256-Uw6Qes0IZkkfBchFnvnX9l1ZG5T5pyExmV7yUJLPOJ0="; + }; + + postPatch = '' + substituteInPlace bruh.c \ + --replace-fail "aplay" "${alsa-utils}/bin/aplay" + ''; + + makeFlags = [ "PREFIX=$(out)" ]; + + meta = with lib; { + description = "Bruh sound, but as a program"; + inherit (finalAttrs.src.meta) homepage; + license = licenses.gpl3Only; + platforms = platforms.linux; + maintainers = with maintainers; [ azahi ]; + mainProgram = "bruh"; + }; +}) diff --git a/users/edef/.gitignore b/users/edef/.gitignore new file mode 100644 index 000000000000..ef4fcfc3471d --- /dev/null +++ b/users/edef/.gitignore @@ -0,0 +1,3 @@ +result-* +result +target diff --git a/tvix/tools/crunch-v2/.gitignore b/users/edef/crunch-v2/.gitignore index 4bed5da93fb2..4bed5da93fb2 100644 --- a/tvix/tools/crunch-v2/.gitignore +++ b/users/edef/crunch-v2/.gitignore diff --git a/tvix/tools/crunch-v2/Cargo.lock b/users/edef/crunch-v2/Cargo.lock index cff5509d0b06..d7959aeee154 100644 --- a/tvix/tools/crunch-v2/Cargo.lock +++ b/users/edef/crunch-v2/Cargo.lock @@ -4,24 +4,24 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", @@ -32,9 +32,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -77,47 +77,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.11" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -125,18 +126,18 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" dependencies = [ "backtrace", ] [[package]] name = "argminmax" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202108b46429b765ef483f8a24d5c46f48c14acfdacc086dd4ab6dddf6bcdbd2" +checksum = "52424b59d69d69d5056d508b260553afd91c57e21849579cd1f50ee8b8b88eaa" dependencies = [ "num-traits", ] @@ -149,15 +150,15 @@ checksum = "bf7d0a018de4f6aa429b9d33d69edf69072b1c5b1cb8d3e4a5f7ef898fc3eb76" [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "arrow-format" @@ -171,9 +172,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -182,24 +183,24 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] @@ -213,29 +214,29 @@ dependencies = [ [[package]] name = "atoi_simd" -version = "0.15.3" +version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc41b65e01b6851bdcd2d741824e6b310d571396bf3915e31e4792034ee65126" +checksum = "9ae037714f313c1353189ead58ef9eec30a8e8dc101b2622d461418fd59e28a9" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] @@ -246,9 +247,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -264,15 +265,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "blake3" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" dependencies = [ "arrayref", "arrayvec", @@ -301,9 +302,9 @@ dependencies = [ [[package]] name = "brotli" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -322,9 +323,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "regex-automata", @@ -333,28 +334,28 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.5.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] @@ -365,9 +366,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "bzip2" @@ -392,12 +393,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -408,22 +410,22 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", "serde", - "windows-targets 0.48.5", + "windows-targets", ] [[package]] name = "clap" -version = "4.4.18" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -431,9 +433,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -443,58 +445,58 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "console" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.45.0", + "windows-sys 0.52.0", ] [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -502,80 +504,70 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunch-v2" @@ -627,16 +619,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -650,20 +641,20 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", @@ -711,9 +702,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "ed25519" @@ -727,9 +718,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", @@ -741,9 +732,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "encode_unicode" @@ -752,15 +743,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] +name = "enum-primitive-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c" +dependencies = [ + "num-traits", + "quote", + "syn 2.0.79", +] + +[[package]] name = "enum_dispatch" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] @@ -771,12 +773,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -805,15 +807,15 @@ checksum = "a71061d097bfa9a5a4d2efdec57990d9a88745020b365191d37e48541a1628f2" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fiat-crypto" -version = "0.2.5" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "fixedbitset" @@ -823,9 +825,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -855,9 +857,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -870,9 +872,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -880,15 +882,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -897,38 +899,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -963,9 +965,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "js-sys", @@ -976,9 +978,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -988,9 +990,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.22" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -1007,9 +1009,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -1017,16 +1019,28 @@ dependencies = [ ] [[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1046,18 +1060,18 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1066,9 +1080,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -1077,9 +1091,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1089,9 +1103,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -1104,7 +1118,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -1128,9 +1142,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1151,19 +1165,19 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.0", ] [[package]] name = "indicatif" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" dependencies = [ "console", "instant", @@ -1174,57 +1188,63 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] [[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] name = "itertools" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "f0b21006cd1874ae9e650973c565615676dc4a274c965bb0a73796dac838ce4f" [[package]] name = "libm" @@ -1233,27 +1253,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] +name = "libmimalloc-sys" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] + +[[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "libc", - "redox_syscall 0.4.1", ] [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1261,25 +1290,24 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lz4" -version = "1.24.0" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +checksum = "4d1febb2b4a79ddd1980eede06a8f7902197960aa0383ffcfdd62fe723036725" dependencies = [ - "libc", "lz4-sys", ] [[package]] name = "lz4-sys" -version = "1.9.4" +version = "1.11.1+lz4-1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" dependencies = [ "cc", "libc", @@ -1309,9 +1337,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -1323,12 +1351,12 @@ dependencies = [ ] [[package]] -name = "memoffset" -version = "0.9.0" +name = "mimalloc" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" dependencies = [ - "autocfg", + "libmimalloc-sys", ] [[package]] @@ -1339,35 +1367,36 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.9" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "multiversion" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2c7b9d7fe61760ce5ea19532ead98541f6b4c495d87247aff9826445cf6872a" +checksum = "c4851161a11d3ad0bf9402d90ffc3967bf231768bfd7aeb61755ad06dbf1a142" dependencies = [ "multiversion-macros", "target-features", @@ -1375,9 +1404,9 @@ dependencies = [ [[package]] name = "multiversion-macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a83d8500ed06d68877e9de1dde76c1dbb83885dcdbda4ef44ccbc3fbda2ac8" +checksum = "79a74ddee9e0c27d2578323c13905793e91622148f138ba29738f9dddb835e90" dependencies = [ "proc-macro2", "quote", @@ -1389,17 +1418,34 @@ dependencies = [ name = "nix-compat" version = "0.1.0" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "bstr", + "bytes", "data-encoding", "ed25519", "ed25519-dalek", + "enum-primitive-derive", "glob", + "mimalloc", + "nix-compat-derive", "nom", + "num-traits", + "pin-project-lite", "serde", "serde_json", "sha2 0.10.8", "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "nix-compat-derive" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", ] [[package]] @@ -1432,25 +1478,15 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] [[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] name = "number_prefix" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1458,24 +1494,24 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.1" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl-probe" @@ -1496,12 +1532,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.9", + "parking_lot_core 0.9.10", ] [[package]] @@ -1520,15 +1556,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.7", "smallvec", - "windows-targets 0.48.5", + "windows-targets", ] [[package]] @@ -1543,15 +1579,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", "indexmap", @@ -1559,9 +1595,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1581,9 +1617,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "planus" @@ -1595,12 +1631,6 @@ dependencies = [ ] [[package]] -name = "platforms" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" - -[[package]] name = "polars" version = "0.35.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1633,7 +1663,7 @@ dependencies = [ "foreign_vec", "futures", "getrandom", - "hashbrown", + "hashbrown 0.14.5", "itoa", "lz4", "multiversion", @@ -1655,11 +1685,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae73d5b8e55decde670caba1cc82b61f14bfb9a72503198f0997d657a98dcfd6" dependencies = [ "ahash", - "bitflags 2.4.1", + "bitflags 2.6.0", "bytemuck", "chrono", "either", - "hashbrown", + "hashbrown 0.14.5", "indexmap", "num-traits", "once_cell", @@ -1724,7 +1754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3555f759705be6dd0d3762d16a0b8787b2dc4da73b57465f3b2bf1a070ba8f20" dependencies = [ "ahash", - "bitflags 2.4.1", + "bitflags 2.6.0", "glob", "once_cell", "polars-arrow", @@ -1750,7 +1780,7 @@ dependencies = [ "argminmax", "bytemuck", "either", - "hashbrown", + "hashbrown 0.14.5", "indexmap", "memchr", "num-traits", @@ -1772,7 +1802,7 @@ checksum = "146010e4b7dd4d2d0e58ddc762f6361f77d7a0385c54471199370c17164f67dd" dependencies = [ "ahash", "async-stream", - "base64 0.21.5", + "base64 0.21.7", "brotli", "ethnum", "flate2", @@ -1799,7 +1829,7 @@ dependencies = [ "crossbeam-channel", "crossbeam-queue", "enum_dispatch", - "hashbrown", + "hashbrown 0.14.5", "num-traits", "polars-arrow", "polars-core", @@ -1892,7 +1922,7 @@ checksum = "da6ce68169fe61d46958c8eab7447360f30f2f23f6e24a0ce703a14b0a3cfbfc" dependencies = [ "ahash", "bytemuck", - "hashbrown", + "hashbrown 0.14.5", "indexmap", "num-traits", "once_cell", @@ -1905,40 +1935,43 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.5.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "prettyplease" -version = "0.2.15" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.12.2" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5a410fc7882af66deb8d01d01737353cf3ad6204c408177ba494291a626312" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", "prost-derive", @@ -1946,12 +1979,12 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.12.2" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa3d084c8704911bfefb2771be2f9b6c5c0da7343a71e0021ee3c665cada738" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck", + "heck 0.5.0", "itertools", "log", "multimap", @@ -1961,38 +1994,37 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.39", + "syn 2.0.79", "tempfile", - "which", ] [[package]] name = "prost-derive" -version = "0.12.2" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065717a5dfaca4a83d2fe57db3487b311365200000551d7a364e715dbf4346bc" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "prost-types" -version = "0.12.2" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8339f32236f590281e2f6368276441394fcd1b2133b549cc895d0ae80f2f9a52" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ "prost", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2039,9 +2071,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -2049,9 +2081,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -2068,18 +2100,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -2088,9 +2120,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", @@ -2100,9 +2132,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -2111,9 +2143,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ring" @@ -2132,16 +2164,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.5" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin 0.9.8", "untrusted 0.9.0", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2228,30 +2261,30 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.24" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2284,28 +2317,28 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -2320,17 +2353,17 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.5", + "ring 0.17.8", "untrusted 0.9.0", ] [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -2339,9 +2372,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -2349,9 +2382,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "seq-macro" @@ -2361,31 +2394,32 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.192" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -2417,24 +2451,24 @@ dependencies = [ [[package]] name = "sha2-asm" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27ba7066011e3fb30d808b51affff34f0a66d3a03a58edd787c6e420e40e44e" +checksum = "b845214d6175804686b2bd482bcffe96651bb2d1200742b712003504a2dac1ab" dependencies = [ "cc", ] [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -2450,9 +2484,9 @@ dependencies = [ [[package]] name = "simdutf8" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "slab" @@ -2481,9 +2515,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smartstring" @@ -2498,28 +2532,18 @@ dependencies = [ [[package]] name = "snap" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "socket2" -version = "0.4.10" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2536,9 +2560,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", @@ -2582,9 +2606,9 @@ checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum_macros" @@ -2592,11 +2616,11 @@ version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] @@ -2618,9 +2642,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -2629,9 +2653,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.29.10" +version = "0.29.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a18d114d420ada3a891e6bc8e96a2023402203296a47cdd65083377dad18ba5" +checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" dependencies = [ "cfg-if", "core-foundation-sys", @@ -2643,71 +2667,70 @@ dependencies = [ [[package]] name = "target-features" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb5fa503293557c5158bd215fdc225695e567a77e453f5d4452a50a193969bd" +checksum = "c1bbb9f3c5c463a01705937a24fdabc5047929ac764b2d5b9cf681c1f5041ed5" [[package]] name = "tempfile" -version = "3.8.1" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "once_cell", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "tokio" -version = "1.34.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] @@ -2723,23 +2746,22 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -2748,10 +2770,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] [[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] name = "tracing-core" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2762,9 +2796,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" @@ -2774,15 +2808,15 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "untrusted" @@ -2798,15 +2832,15 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "want" @@ -2825,34 +2859,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2860,28 +2895,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "web-sys" -version = "0.3.65" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -2893,23 +2928,11 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.5", + "ring 0.17.8", "untrusted 0.9.0", ] [[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2933,29 +2956,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets", ] [[package]] @@ -2964,191 +2969,93 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets", ] [[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "xml-rs" -version = "0.8.19" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" [[package]] name = "xxhash-rust" -version = "0.8.7" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9828b178da53440fa9c766a3d2f73f7cf5d0ac1fe3980c1e5018d899fd19e07b" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" [[package]] name = "xz2" @@ -3161,53 +3068,54 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.26" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.26" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zstd" -version = "0.13.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.0.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/tvix/tools/crunch-v2/Cargo.nix b/users/edef/crunch-v2/Cargo.nix index 35c09ecee711..6bd2be6b113c 100644 --- a/tvix/tools/crunch-v2/Cargo.nix +++ b/users/edef/crunch-v2/Cargo.nix @@ -1,4 +1,4 @@ -# This file was @generated by crate2nix 0.13.0 with the command: +# This file was @generated by crate2nix 0.14.1 with the command: # "generate" "--all-features" # See https://github.com/kolloch/crate2nix for more info. @@ -13,6 +13,8 @@ , rootFeatures ? [ "default" ] # If true, throw errors instead of issueing deprecation warnings. , strictDeprecation ? false + # Elements to add to the `-C target-feature=` argument passed to `rustc` + # (separated by `,`, prefixed with `+`). # Used for conditional compilation based on CPU feature detection. , targetFeatures ? [ ] # Whether to perform release builds: longer compile times, faster binaries. @@ -83,9 +85,10 @@ rec { crates = { "addr2line" = rec { crateName = "addr2line"; - version = "0.21.0"; + version = "0.24.2"; edition = "2018"; - sha256 = "1jx0k3iwyqr8klqbzk6kjvr496yd94aspis10vwsj5wy7gib4c4a"; + crateBin = [ ]; + sha256 = "1hd1i57zxgz08j6h5qrhsnm2fi0bcqvsh389fw400xm3arz2ggnz"; dependencies = [ { name = "gimli"; @@ -95,28 +98,29 @@ rec { } ]; features = { + "all" = [ "bin" ]; "alloc" = [ "dep:alloc" ]; + "bin" = [ "loader" "rustc-demangle" "cpp_demangle" "fallible-iterator" "smallvec" "dep:clap" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; "cpp_demangle" = [ "dep:cpp_demangle" ]; - "default" = [ "rustc-demangle" "cpp_demangle" "std-object" "fallible-iterator" "smallvec" "memmap2" ]; + "default" = [ "rustc-demangle" "cpp_demangle" "loader" "fallible-iterator" "smallvec" ]; "fallible-iterator" = [ "dep:fallible-iterator" ]; - "memmap2" = [ "dep:memmap2" ]; - "object" = [ "dep:object" ]; + "loader" = [ "std" "dep:object" "dep:memmap2" "dep:typed-arena" ]; "rustc-demangle" = [ "dep:rustc-demangle" ]; "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "gimli/rustc-dep-of-std" ]; "smallvec" = [ "dep:smallvec" ]; "std" = [ "gimli/std" ]; - "std-object" = [ "std" "object" "object/std" "object/compression" "gimli/endian-reader" ]; }; }; - "adler" = rec { - crateName = "adler"; - version = "1.0.2"; - edition = "2015"; - sha256 = "1zim79cvzd5yrkzl3nyfx0avijwgk9fqv3yrscdy1cc79ih02qpj"; + "adler2" = rec { + crateName = "adler2"; + version = "2.0.0"; + edition = "2021"; + sha256 = "09r6drylvgy8vv8k20lnbvwq8gp09h7smfn6h1rxsy15pgh629si"; authors = [ "Jonas Schievink <jonasschievink@gmail.com>" + "oyvindln <oyvindln@users.noreply.github.com>" ]; features = { "compiler_builtins" = [ "dep:compiler_builtins" ]; @@ -127,9 +131,9 @@ rec { }; "ahash" = rec { crateName = "ahash"; - version = "0.8.6"; + version = "0.8.11"; edition = "2018"; - sha256 = "0yn9i8nc6mmv28ig9w3dga571q09vg9f1f650mi5z8phx42r6hli"; + sha256 = "04chdfkls5xmhp1d48gnjsmglbqibizs3bpbj6rsj604m10si7g8"; authors = [ "Tom Kaitchuck <Tom.Kaitchuck@gmail.com>" ]; @@ -148,7 +152,7 @@ rec { packageId = "once_cell"; usesDefaultFeatures = false; target = { target, features }: (!(("arm" == target."arch" or null) && ("none" == target."os" or null))); - features = [ "unstable" "alloc" ]; + features = [ "alloc" ]; } { name = "zerocopy"; @@ -176,9 +180,9 @@ rec { }; "aho-corasick" = rec { crateName = "aho-corasick"; - version = "1.1.2"; + version = "1.1.3"; edition = "2021"; - sha256 = "1w510wnixvlgimkx1zjbvlxh6xps2vjgfqgwf5a6adlbjp5rv5mj"; + sha256 = "05mrpkvdgp5d20y2p989f187ry9diliijgwrs254fs9s1m1x6q4f"; libName = "aho_corasick"; authors = [ "Andrew Gallant <jamslam@gmail.com>" @@ -197,7 +201,7 @@ rec { "perf-literal" = [ "dep:memchr" ]; "std" = [ "memchr?/std" ]; }; - resolvedDefaultFeatures = [ "default" "perf-literal" "std" ]; + resolvedDefaultFeatures = [ "perf-literal" "std" ]; }; "alloc-no-stdlib" = rec { crateName = "alloc-no-stdlib"; @@ -205,6 +209,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1cy6r2sfv5y5cigv86vms7n5nlwhx1rbyxwcraqnmm1rxiib2yyc"; + libName = "alloc_no_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -216,6 +221,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1kkfbld20ab4165p29v172h8g0wvq8i06z8vnng14whw0isq5ywl"; + libName = "alloc_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -229,9 +235,10 @@ rec { }; "allocator-api2" = rec { crateName = "allocator-api2"; - version = "0.2.16"; + version = "0.2.18"; edition = "2018"; - sha256 = "1iayppgq4wqbfbfcqmsbwgamj0s65012sskfvyx07pxavk3gyhh9"; + sha256 = "0kr6lfnxvnj164j1x38g97qjlhb7akppqzvgfs0697140ixbav2w"; + libName = "allocator_api2"; authors = [ "Zakarum <zaq.dev@icloud.com>" ]; @@ -247,6 +254,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9"; + libName = "android_tzdata"; authors = [ "RumovZ" ]; @@ -270,9 +278,9 @@ rec { }; "anstream" = rec { crateName = "anstream"; - version = "0.6.11"; + version = "0.6.15"; edition = "2021"; - sha256 = "19dndamalavhjwp4i74k8hdijcixb7gsfa6ycwyc1r8xn6y1wbkf"; + sha256 = "09nm4qj34kiwgzczdvj14x7hgsb235g4sqsay3xsz7zqn4d5rqb4"; dependencies = [ { name = "anstyle"; @@ -298,6 +306,10 @@ rec { packageId = "colorchoice"; } { + name = "is_terminal_polyfill"; + packageId = "is_terminal_polyfill"; + } + { name = "utf8parse"; packageId = "utf8parse"; } @@ -311,9 +323,9 @@ rec { }; "anstyle" = rec { crateName = "anstyle"; - version = "1.0.4"; + version = "1.0.8"; edition = "2021"; - sha256 = "11yxw02b6parn29s757z96rgiqbn8qy0fk9a3p3bhczm85dhfybh"; + sha256 = "1cfmkza63xpn1kkz844mgjwm9miaiz4jkyczmwxzivcsypk1vv0v"; features = { "default" = [ "std" ]; }; @@ -321,9 +333,10 @@ rec { }; "anstyle-parse" = rec { crateName = "anstyle-parse"; - version = "0.2.3"; + version = "0.2.5"; edition = "2021"; - sha256 = "134jhzrz89labrdwxxnjxqjdg06qvaflj1wkfnmyapwyldfwcnn7"; + sha256 = "1jy12rvgbldflnb2x7mcww9dcffw1mx22nyv6p3n7d62h0gdwizb"; + libName = "anstyle_parse"; dependencies = [ { name = "utf8parse"; @@ -340,9 +353,10 @@ rec { }; "anstyle-query" = rec { crateName = "anstyle-query"; - version = "1.0.2"; + version = "1.1.1"; edition = "2021"; - sha256 = "0j3na4b1nma39g4x7cwvj009awxckjf3z2vkwhldgka44hqj72g2"; + sha256 = "0aj22iy4pzk6mz745sfrm1ym14r0y892jhcrbs8nkj7nqx9gqdkd"; + libName = "anstyle_query"; dependencies = [ { name = "windows-sys"; @@ -355,9 +369,10 @@ rec { }; "anstyle-wincon" = rec { crateName = "anstyle-wincon"; - version = "3.0.2"; + version = "3.0.4"; edition = "2021"; - sha256 = "19v0fv400bmp4niqpzxnhg83vz12mmqv7l2l8vi80qcdxj0lpm8w"; + sha256 = "1y2pkvsrdxbcwircahb4wimans2pzmwwxad7ikdhj5lpdqdlxxsv"; + libName = "anstyle_wincon"; dependencies = [ { name = "anstyle"; @@ -374,9 +389,9 @@ rec { }; "anyhow" = rec { crateName = "anyhow"; - version = "1.0.75"; + version = "1.0.89"; edition = "2018"; - sha256 = "1rmcjkim91c5mw7h9wn8nv0k6x118yz0xg0z1q18svgn42mqqrm4"; + sha256 = "1xh1vg89n56h6nqikcmgbpmkixjds33492klrp9m96xrbmhgizc6"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -395,9 +410,9 @@ rec { }; "argminmax" = rec { crateName = "argminmax"; - version = "0.6.1"; + version = "0.6.2"; edition = "2021"; - sha256 = "1lnvpkvdsvdbsinhik6srx5c2j3gqkaj92iz93pnbdr9cjs0h890"; + sha256 = "1alfp2wfh3pms6f5fj8qw9birndgac2jd2shdl2xascxsrclnhjj"; authors = [ "Jeroen Van Der Donckt" ]; @@ -422,13 +437,14 @@ rec { version = "0.2.0"; edition = "2021"; sha256 = "0xpbqf7qkvzplpjd7f0wbcf2n1v9vygdccwxkd1amxp4il0hlzdz"; + libName = "array_init_cursor"; }; "arrayref" = rec { crateName = "arrayref"; - version = "0.3.7"; + version = "0.3.9"; edition = "2015"; - sha256 = "0ia5ndyxqkzdymqr4ls53jdmajf09adjimg5kvw65kkprg930jbb"; + sha256 = "1jzyp0nvp10dmahaq9a2rnxqdd5wxgbvp8xaibps3zai8c9fi8kn"; authors = [ "David Roundy <roundyd@physics.oregonstate.edu>" ]; @@ -436,13 +452,14 @@ rec { }; "arrayvec" = rec { crateName = "arrayvec"; - version = "0.7.4"; + version = "0.7.6"; edition = "2018"; - sha256 = "04b7n722jij0v3fnm3qk072d5ysc2q30rl9fz33zpfhzah30mlwn"; + sha256 = "0l1fz4ccgv6pm609rif37sl5nv5k6lbzi7kkppgzqzh1vwix20kw"; authors = [ "bluss" ]; features = { + "borsh" = [ "dep:borsh" ]; "default" = [ "std" ]; "serde" = [ "dep:serde" ]; "zeroize" = [ "dep:zeroize" ]; @@ -453,6 +470,7 @@ rec { version = "0.8.1"; edition = "2018"; sha256 = "1irj67p6c224dzw86jr7j3z9r5zfid52gy6ml8rdqk4r2si4x207"; + libName = "arrow_format"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" ]; @@ -485,9 +503,10 @@ rec { }; "async-stream" = rec { crateName = "async-stream"; - version = "0.3.5"; - edition = "2018"; - sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + version = "0.3.6"; + edition = "2021"; + sha256 = "0xl4zqncrdmw2g6241wgr11dxdg4h7byy6bz3l6si03qyfk72nhb"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -509,10 +528,11 @@ rec { }; "async-stream-impl" = rec { crateName = "async-stream-impl"; - version = "0.3.5"; - edition = "2018"; - sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; + version = "0.3.6"; + edition = "2021"; + sha256 = "0kaplfb5axsvf1gfs2gk6c4zx6zcsns0yf3ssk7iwni7bphlvhn7"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -527,7 +547,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" "visit-mut" ]; } ]; @@ -535,10 +555,11 @@ rec { }; "async-trait" = rec { crateName = "async-trait"; - version = "0.1.74"; + version = "0.1.83"; edition = "2021"; - sha256 = "1ydhbsqjqqa6bxbv0kgys2wq2vi3jpwjy57dk162ajwppgqkfrd6"; + sha256 = "1p8q8gm4fv2fdka8hwy2w3f8df7p5inixqi7rlmbnky3wmysw73j"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -553,8 +574,9 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; - features = [ "full" "visit-mut" ]; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "proc-macro" "visit-mut" ]; } ]; @@ -582,9 +604,9 @@ rec { }; "atoi_simd" = rec { crateName = "atoi_simd"; - version = "0.15.3"; + version = "0.15.6"; edition = "2018"; - sha256 = "09jiwr7074j73viiafdzjq9mf39idd784hfpsbf1p1dn05gbchgw"; + sha256 = "1a98kvaqyhb1shi2c6qhvklahc7ckvpmibcy319i6g1i9xqkgq4s"; authors = [ "Dmitry Rodionov <gh@rdmtr.com>" ]; @@ -596,9 +618,9 @@ rec { }; "autocfg" = rec { crateName = "autocfg"; - version = "1.1.0"; + version = "1.4.0"; edition = "2015"; - sha256 = "1ylp3cb47ylzabimazvbz9ms6ap784zhb6syaz6c1jqpmcmq0s6l"; + sha256 = "09lz3by90d2hphbq56znag9v87gfpd9gb8nr82hll8z6x2nhprdc"; authors = [ "Josh Stone <cuviper@gmail.com>" ]; @@ -606,9 +628,9 @@ rec { }; "backtrace" = rec { crateName = "backtrace"; - version = "0.3.69"; - edition = "2018"; - sha256 = "0dsq23dhw4pfndkx2nsa1ml2g31idm7ss7ljxp8d57avygivg290"; + version = "0.3.74"; + edition = "2021"; + sha256 = "06pfif7nwx66qf2zaanc2fcq7m64i91ki9imw9xd3bnz5hrwp0ld"; authors = [ "The Rust Project Developers" ]; @@ -640,28 +662,23 @@ rec { packageId = "object"; usesDefaultFeatures = false; target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); - features = [ "read_core" "elf" "macho" "pe" "unaligned" "archive" ]; + features = [ "read_core" "elf" "macho" "pe" "xcoff" "unaligned" "archive" ]; } { name = "rustc-demangle"; packageId = "rustc-demangle"; } - ]; - buildDependencies = [ { - name = "cc"; - packageId = "cc"; + name = "windows-targets"; + packageId = "windows-targets"; + target = { target, features }: (target."windows" or false); } ]; features = { "cpp_demangle" = [ "dep:cpp_demangle" ]; "default" = [ "std" ]; - "rustc-serialize" = [ "dep:rustc-serialize" ]; "serde" = [ "dep:serde" ]; - "serialize-rustc" = [ "rustc-serialize" ]; "serialize-serde" = [ "serde" ]; - "verify-winapi" = [ "winapi/dbghelp" "winapi/handleapi" "winapi/libloaderapi" "winapi/memoryapi" "winapi/minwindef" "winapi/processthreadsapi" "winapi/synchapi" "winapi/tlhelp32" "winapi/winbase" "winapi/winnt" ]; - "winapi" = [ "dep:winapi" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; @@ -679,11 +696,11 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "base64 0.21.5" = rec { + "base64 0.21.7" = rec { crateName = "base64"; - version = "0.21.5"; + version = "0.21.7"; edition = "2018"; - sha256 = "1y8x2xs9nszj5ix7gg4ycn5a6wy7ca74zxwqri3bdqzdjha6lqrm"; + sha256 = "0rw52yvsk75kar9wgqfwgb414kvil1gn7mqkrhn9zf1537mpsacx"; authors = [ "Alice Maz <alice@alicemaz.com>" "Marshall Pierce <marshall@mpierce.org>" @@ -722,11 +739,11 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "bitflags 2.4.1" = rec { + "bitflags 2.6.0" = rec { crateName = "bitflags"; - version = "2.4.1"; + version = "2.6.0"; edition = "2021"; - sha256 = "01ryy3kd671b0ll4bhdvhsz67vwz1lz53fz504injrd7wpv64xrj"; + sha256 = "1pkidwzn3hnxlsl8zizh0bncgbjnw7c41cx7bby26ncbzmiznj5h"; authors = [ "The Rust Project Developers" ]; @@ -742,9 +759,9 @@ rec { }; "blake3" = rec { crateName = "blake3"; - version = "1.5.0"; + version = "1.5.4"; edition = "2021"; - sha256 = "11ysh12zcqq6xkjxh5cbrmnwzalprm3z552i5ff7wm5za9hz0c82"; + sha256 = "1xy6gp8yfcpvzwrhbx5iksxxwf6hsix403klizgr1s6qgwj3686q"; authors = [ "Jack O'Connor <oconnor663@gmail.com>" "Samuel Neves" @@ -776,11 +793,10 @@ rec { ]; features = { "default" = [ "std" ]; - "digest" = [ "dep:digest" ]; "mmap" = [ "std" "dep:memmap2" ]; - "rayon" = [ "dep:rayon" "std" ]; + "rayon" = [ "dep:rayon-core" "std" ]; "serde" = [ "dep:serde" ]; - "traits-preview" = [ "digest" ]; + "traits-preview" = [ "dep:digest" ]; "zeroize" = [ "dep:zeroize" "arrayvec/zeroize" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; @@ -790,6 +806,7 @@ rec { version = "0.10.4"; edition = "2018"; sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -806,6 +823,7 @@ rec { version = "0.9.0"; edition = "2018"; sha256 = "1r4pf90s7d7lj1wdjhlnqa26vvbm6pnc33z138lxpnp9srpi2lj1"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -821,10 +839,10 @@ rec { }; "brotli" = rec { crateName = "brotli"; - version = "3.4.0"; + version = "3.5.0"; edition = "2015"; crateBin = [ ]; - sha256 = "03qhcq09a6f8y4gm0bmsn7jrq5804cwpkcx3fyay1g7lgsj78q2i"; + sha256 = "14f34ml3i8qbnh4hhlv5r6j10bkx420gspsl1cgznl1wqrdx4h6n"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" "The Brotli Authors" @@ -863,6 +881,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "0kyyh9701dwqzwvn2frff4ww0zibikqd1s1xvl7n1pfpc3z4lbjf"; + libName = "brotli_decompressor"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" "The Brotli Authors" @@ -888,9 +907,9 @@ rec { }; "bstr" = rec { crateName = "bstr"; - version = "1.8.0"; + version = "1.10.0"; edition = "2021"; - sha256 = "0313sqdf0a40vhpnrlkf54zhr76rmlyxzhx00sq8822shfl36bsl"; + sha256 = "036wwrchd5gq3q4k6w1j2bfl2bk2ff8c0dsa9y7w7aw7nf7knwj0"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -925,22 +944,23 @@ rec { }; "bumpalo" = rec { crateName = "bumpalo"; - version = "3.14.0"; + version = "3.16.0"; edition = "2021"; - sha256 = "1v4arnv9kwk54v5d0qqpv4vyw2sgr660nk0w3apzixi1cm3yfc3z"; + sha256 = "0b015qb4knwanbdlp1x48pkb4pm57b8gidbhhhxr900q2wb6fabr"; authors = [ "Nick Fitzgerald <fitzgen@gmail.com>" ]; features = { "allocator-api2" = [ "dep:allocator-api2" ]; + "serde" = [ "dep:serde" ]; }; resolvedDefaultFeatures = [ "default" ]; }; "bytemuck" = rec { crateName = "bytemuck"; - version = "1.14.0"; + version = "1.19.0"; edition = "2018"; - sha256 = "1ik1ma5n3bg700skkzhx50zjk7kj7mbsphi773if17l04pn2hk9p"; + sha256 = "0ka96agz9kqmsd71q7xpr08bnh2g8x4hivxqpnks0674h5dj2d43"; authors = [ "Lokathor <zefria@gmail.com>" ]; @@ -955,14 +975,15 @@ rec { "bytemuck_derive" = [ "dep:bytemuck_derive" ]; "derive" = [ "bytemuck_derive" ]; "extern_crate_std" = [ "extern_crate_alloc" ]; + "latest_stable_rust" = [ "aarch64_simd" "align_offset" "const_zeroed" "derive" "min_const_generics" "must_cast" "track_caller" "wasm_simd" "zeroable_atomics" "zeroable_maybe_uninit" ]; }; resolvedDefaultFeatures = [ "bytemuck_derive" "derive" "extern_crate_alloc" ]; }; "bytemuck_derive" = rec { crateName = "bytemuck_derive"; - version = "1.5.0"; + version = "1.8.0"; edition = "2018"; - sha256 = "1cgj75df2v32l4fmvnp25xxkkz4lp6hz76f7hfhd55wgbzmvfnln"; + sha256 = "1v5r33dgl12rqbvh440fdjxmxxr49qpzmg6vpw5jzdbcjk6w7z5w"; procMacro = true; authors = [ "Lokathor <zefria@gmail.com>" @@ -978,7 +999,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; } ]; @@ -998,9 +1019,9 @@ rec { }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.7.2"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "1wzs7l57iwqmrszdpr2mmqf1b1hgvpxafc30imxhnry0zfl9m3a2"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -1067,10 +1088,9 @@ rec { }; "cc" = rec { crateName = "cc"; - version = "1.0.83"; + version = "1.1.30"; edition = "2018"; - crateBin = [ ]; - sha256 = "1l643zidlb5iy1dskc5ggqs4wqa29a02f44piczqc8zcnsq4y5zi"; + sha256 = "0icr3vn2r5scpgylbplffd5mh7jcdivqh9dfgsxymnc13fk06s5i"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -1079,25 +1099,31 @@ rec { name = "jobserver"; packageId = "jobserver"; optional = true; + usesDefaultFeatures = false; } { name = "libc"; packageId = "libc"; + optional = true; usesDefaultFeatures = false; target = { target, features }: (target."unix" or false); } + { + name = "shlex"; + packageId = "shlex"; + } ]; features = { - "jobserver" = [ "dep:jobserver" ]; - "parallel" = [ "jobserver" ]; + "parallel" = [ "dep:libc" "dep:jobserver" ]; }; - resolvedDefaultFeatures = [ "jobserver" "parallel" ]; + resolvedDefaultFeatures = [ "parallel" ]; }; "cfg-if" = rec { crateName = "cfg-if"; version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -1109,9 +1135,9 @@ rec { }; "chrono" = rec { crateName = "chrono"; - version = "0.4.31"; + version = "0.4.38"; edition = "2021"; - sha256 = "0f6vg67pipm8cziad2yms6a639pssnvysk1m05dd9crymmdnhb3z"; + sha256 = "009l8vc5p8750vn02z30mblg4pv2qhkbfizhfwmzc6vpy5nr67x2"; dependencies = [ { name = "android-tzdata"; @@ -1139,7 +1165,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets 0.48.5"; + packageId = "windows-targets"; optional = true; target = { target, features }: (target."windows" or false); } @@ -1147,28 +1173,33 @@ rec { features = { "android-tzdata" = [ "dep:android-tzdata" ]; "arbitrary" = [ "dep:arbitrary" ]; - "clock" = [ "std" "winapi" "iana-time-zone" "android-tzdata" ]; + "clock" = [ "winapi" "iana-time-zone" "android-tzdata" "now" ]; "default" = [ "clock" "std" "oldtime" "wasmbind" ]; "iana-time-zone" = [ "dep:iana-time-zone" ]; "js-sys" = [ "dep:js-sys" ]; + "now" = [ "std" ]; "pure-rust-locales" = [ "dep:pure-rust-locales" ]; - "rkyv" = [ "dep:rkyv" ]; - "rustc-serialize" = [ "dep:rustc-serialize" ]; + "rkyv" = [ "dep:rkyv" "rkyv/size_32" ]; + "rkyv-16" = [ "dep:rkyv" "rkyv?/size_16" ]; + "rkyv-32" = [ "dep:rkyv" "rkyv?/size_32" ]; + "rkyv-64" = [ "dep:rkyv" "rkyv?/size_64" ]; + "rkyv-validation" = [ "rkyv?/validation" ]; "serde" = [ "dep:serde" ]; - "unstable-locales" = [ "pure-rust-locales" "alloc" ]; + "std" = [ "alloc" ]; + "unstable-locales" = [ "pure-rust-locales" ]; "wasm-bindgen" = [ "dep:wasm-bindgen" ]; "wasmbind" = [ "wasm-bindgen" "js-sys" ]; "winapi" = [ "windows-targets" ]; "windows-targets" = [ "dep:windows-targets" ]; }; - resolvedDefaultFeatures = [ "android-tzdata" "clock" "iana-time-zone" "serde" "std" "winapi" "windows-targets" ]; + resolvedDefaultFeatures = [ "alloc" "android-tzdata" "clock" "iana-time-zone" "now" "serde" "std" "winapi" "windows-targets" ]; }; "clap" = rec { crateName = "clap"; - version = "4.4.18"; + version = "4.5.20"; edition = "2021"; crateBin = [ ]; - sha256 = "0p46h346y8nval6gwzh27if3icbi9dwl95fg5ir36ihrqip8smqy"; + sha256 = "1s37v23gcxkjy4800qgnkxkpliz68vslpr5sgn1xar56hmnkfzxr"; dependencies = [ { name = "clap_builder"; @@ -1196,6 +1227,7 @@ rec { "suggestions" = [ "clap_builder/suggestions" ]; "unicode" = [ "clap_builder/unicode" ]; "unstable-doc" = [ "clap_builder/unstable-doc" "derive" ]; + "unstable-ext" = [ "clap_builder/unstable-ext" ]; "unstable-styles" = [ "clap_builder/unstable-styles" ]; "unstable-v5" = [ "clap_builder/unstable-v5" "clap_derive?/unstable-v5" "deprecated" ]; "usage" = [ "clap_builder/usage" ]; @@ -1205,9 +1237,9 @@ rec { }; "clap_builder" = rec { crateName = "clap_builder"; - version = "4.4.18"; + version = "4.5.20"; edition = "2021"; - sha256 = "1iyif47075caa4x1p3ygk18b07lb4xl4k48w4c061i2hxi0dzx2d"; + sha256 = "0m6w10l2f65h3ch0d53lql6p26xxrh20ffipra9ysjsfsjmq1g0r"; dependencies = [ { name = "anstream"; @@ -1235,7 +1267,7 @@ rec { "std" = [ "anstyle/std" ]; "suggestions" = [ "dep:strsim" "error-context" ]; "unicode" = [ "dep:unicode-width" "dep:unicase" ]; - "unstable-doc" = [ "cargo" "wrap_help" "env" "unicode" "string" ]; + "unstable-doc" = [ "cargo" "wrap_help" "env" "unicode" "string" "unstable-ext" ]; "unstable-styles" = [ "color" ]; "unstable-v5" = [ "deprecated" ]; "wrap_help" = [ "help" "dep:terminal_size" ]; @@ -1244,14 +1276,14 @@ rec { }; "clap_derive" = rec { crateName = "clap_derive"; - version = "4.4.7"; + version = "4.5.18"; edition = "2021"; - sha256 = "0hk4hcxl56qwqsf4hmf7c0gr19r9fbxk0ah2bgkr36pmmaph966g"; + sha256 = "1ardb26bvcpg72q9myr7yir3a8c83gx7vxk1cccabsd9n73s1ija"; procMacro = true; dependencies = [ { name = "heck"; - packageId = "heck"; + packageId = "heck 0.5.0"; } { name = "proc-macro2"; @@ -1263,7 +1295,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -1275,23 +1307,23 @@ rec { }; "clap_lex" = rec { crateName = "clap_lex"; - version = "0.6.0"; + version = "0.7.2"; edition = "2021"; - sha256 = "1l8bragdvim7mva9flvd159dskn2bdkpl0jqrr41wnjfn8pcfbvh"; + sha256 = "15zcrc2fa6ycdzaihxghf48180bnvzsivhf0fmah24bnnaf76qhl"; }; "colorchoice" = rec { crateName = "colorchoice"; - version = "1.0.0"; + version = "1.0.2"; edition = "2021"; - sha256 = "1ix7w85kwvyybwi2jdkl3yva2r2bvdcc3ka2grjfzfgrapqimgxc"; + sha256 = "1h18ph538y8yjmbpaf8li98l0ifms2xmh3rax9666c5qfjfi3zfk"; }; "console" = rec { crateName = "console"; - version = "0.15.7"; + version = "0.15.8"; edition = "2018"; - sha256 = "1y6cbwadid5g4fyn4xq9c0s7mfavqqfg6prs9p3gvphfqw6f09n9"; + sha256 = "1sz4nl9nz8pkmapqni6py7jxzi7nzqjxzb3ya4kxvmkb0zy867qf"; authors = [ "Armin Ronacher <armin.ronacher@active-4.com>" ]; @@ -1316,7 +1348,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.45.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_System_Console" "Win32_Storage_FileSystem" "Win32_UI_Input_KeyboardAndMouse" ]; } @@ -1330,9 +1362,10 @@ rec { }; "const-oid" = rec { crateName = "const-oid"; - version = "0.9.5"; + version = "0.9.6"; edition = "2021"; - sha256 = "0vxb4d25mgk8y0phay7j078limx2553716ixsr1x5605k31j5h98"; + sha256 = "1y0jnqaq7p2wvspnx7qj76m7hjcqpz73qzvr9l2p9n2s51vr6if2"; + libName = "const_oid"; authors = [ "RustCrypto Developers" ]; @@ -1342,9 +1375,9 @@ rec { }; "constant_time_eq" = rec { crateName = "constant_time_eq"; - version = "0.3.0"; + version = "0.3.1"; edition = "2021"; - sha256 = "1hl0y8frzlhpr58rh8rlg4bm53ax09ikj2i5fk7gpyphvhq4s57p"; + sha256 = "19nwwczii762pwlsm7bpizgjg8hkg1kqi32b2g4rglijklsbhx3w"; authors = [ "Cesar Eduardo Barros <cesarb@cesarb.eti.br>" ]; @@ -1352,9 +1385,10 @@ rec { }; "core-foundation" = rec { crateName = "core-foundation"; - version = "0.9.3"; - edition = "2015"; - sha256 = "0ii1ihpjb30fk38gdikm5wqlkmyr8k46fh4k2r8sagz5dng7ljhr"; + version = "0.9.4"; + edition = "2018"; + sha256 = "13zvbbj07yk3b61b8fhwfzhy35535a583irf23vlcg59j7h9bqci"; + libName = "core_foundation"; authors = [ "The Servo Project Developers" ]; @@ -1362,6 +1396,7 @@ rec { { name = "core-foundation-sys"; packageId = "core-foundation-sys"; + usesDefaultFeatures = false; } { name = "libc"; @@ -1370,28 +1405,35 @@ rec { ]; features = { "chrono" = [ "dep:chrono" ]; + "default" = [ "link" ]; + "link" = [ "core-foundation-sys/link" ]; "mac_os_10_7_support" = [ "core-foundation-sys/mac_os_10_7_support" ]; "mac_os_10_8_features" = [ "core-foundation-sys/mac_os_10_8_features" ]; "uuid" = [ "dep:uuid" ]; "with-chrono" = [ "chrono" ]; "with-uuid" = [ "uuid" ]; }; + resolvedDefaultFeatures = [ "default" "link" ]; }; "core-foundation-sys" = rec { crateName = "core-foundation-sys"; - version = "0.8.4"; - edition = "2015"; - sha256 = "1yhf471qj6snnm2mcswai47vsbc9w30y4abmdp4crb4av87sb5p4"; + version = "0.8.7"; + edition = "2018"; + sha256 = "12w8j73lazxmr1z0h98hf3z623kl8ms7g07jch7n4p8f9nwlhdkp"; + libName = "core_foundation_sys"; authors = [ "The Servo Project Developers" ]; - features = { }; + features = { + "default" = [ "link" ]; + }; + resolvedDefaultFeatures = [ "default" "link" ]; }; "cpufeatures" = rec { crateName = "cpufeatures"; - version = "0.2.11"; + version = "0.2.14"; edition = "2018"; - sha256 = "1l0gzsyy576n017g9bf0vkv5hhg9cpz1h1libxyfdlzcgbh0yhnf"; + sha256 = "1q3qd9qkw94vs7n5i0y3zz2cqgzcxvdgyb54ryngwmjhfbgrg1k0"; authors = [ "RustCrypto Developers" ]; @@ -1399,7 +1441,7 @@ rec { { name = "libc"; packageId = "libc"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-linux-android"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-linux-android"); } { name = "libc"; @@ -1421,9 +1463,9 @@ rec { }; "crc32fast" = rec { crateName = "crc32fast"; - version = "1.3.2"; + version = "1.4.2"; edition = "2015"; - sha256 = "03c8f29yx293yf43xar946xbls1g60c207m9drf8ilqhr25vsh5m"; + sha256 = "1czp7vif73b8xslr3c9yxysmh9ws2r8824qda7j47ffs9pcnjxx9"; authors = [ "Sam Rijs <srijs@airpost.net>" "Alex Crichton <alex@alexcrichton.com>" @@ -1441,89 +1483,59 @@ rec { }; "crossbeam-channel" = rec { crateName = "crossbeam-channel"; - version = "0.5.8"; - edition = "2018"; - sha256 = "004jz4wxp9k26z657i7rsh9s7586dklx2c5aqf1n3w1dgzvjng53"; + version = "0.5.13"; + edition = "2021"; + sha256 = "1wkx45r34v7g3wyi3lg2wz536lrrrab4h4hh741shfhr8rlhsj1k"; + libName = "crossbeam_channel"; dependencies = [ { - name = "cfg-if"; - packageId = "cfg-if"; - } - { name = "crossbeam-utils"; packageId = "crossbeam-utils"; - optional = true; usesDefaultFeatures = false; } ]; features = { - "crossbeam-utils" = [ "dep:crossbeam-utils" ]; "default" = [ "std" ]; "std" = [ "crossbeam-utils/std" ]; }; - resolvedDefaultFeatures = [ "crossbeam-utils" "default" "std" ]; + resolvedDefaultFeatures = [ "default" "std" ]; }; "crossbeam-deque" = rec { crateName = "crossbeam-deque"; - version = "0.8.3"; - edition = "2018"; - sha256 = "1vqczbcild7nczh5z116w8w46z991kpjyw7qxkf24c14apwdcvyf"; + version = "0.8.5"; + edition = "2021"; + sha256 = "03bp38ljx4wj6vvy4fbhx41q8f585zyqix6pncz1mkz93z08qgv1"; + libName = "crossbeam_deque"; dependencies = [ { - name = "cfg-if"; - packageId = "cfg-if"; - } - { name = "crossbeam-epoch"; packageId = "crossbeam-epoch"; - optional = true; usesDefaultFeatures = false; } { name = "crossbeam-utils"; packageId = "crossbeam-utils"; - optional = true; usesDefaultFeatures = false; } ]; features = { - "crossbeam-epoch" = [ "dep:crossbeam-epoch" ]; - "crossbeam-utils" = [ "dep:crossbeam-utils" ]; "default" = [ "std" ]; "std" = [ "crossbeam-epoch/std" "crossbeam-utils/std" ]; }; - resolvedDefaultFeatures = [ "crossbeam-epoch" "crossbeam-utils" "default" "std" ]; + resolvedDefaultFeatures = [ "default" "std" ]; }; "crossbeam-epoch" = rec { crateName = "crossbeam-epoch"; - version = "0.9.15"; - edition = "2018"; - sha256 = "1ixwc3cq816wb8rlh3ix4jnybqbyyq4l61nwlx0mfm3ck0s148df"; + version = "0.9.18"; + edition = "2021"; + sha256 = "03j2np8llwf376m3fxqx859mgp9f83hj1w34153c7a9c7i5ar0jv"; + libName = "crossbeam_epoch"; dependencies = [ { - name = "cfg-if"; - packageId = "cfg-if"; - } - { name = "crossbeam-utils"; packageId = "crossbeam-utils"; usesDefaultFeatures = false; } - { - name = "memoffset"; - packageId = "memoffset"; - } - { - name = "scopeguard"; - packageId = "scopeguard"; - usesDefaultFeatures = false; - } - ]; - buildDependencies = [ - { - name = "autocfg"; - packageId = "autocfg"; - } ]; features = { "default" = [ "std" ]; @@ -1536,15 +1548,12 @@ rec { }; "crossbeam-queue" = rec { crateName = "crossbeam-queue"; - version = "0.3.8"; - edition = "2018"; - sha256 = "1p9s6n4ckwdgxkb7a8ay9zjzmgc8ppfbxix2vr07rwskibmb7kyi"; + version = "0.3.11"; + edition = "2021"; + sha256 = "0d8y8y3z48r9javzj67v3p2yfswd278myz1j9vzc4sp7snslc0yz"; + libName = "crossbeam_queue"; dependencies = [ { - name = "cfg-if"; - packageId = "cfg-if"; - } - { name = "crossbeam-utils"; packageId = "crossbeam-utils"; usesDefaultFeatures = false; @@ -1559,15 +1568,10 @@ rec { }; "crossbeam-utils" = rec { crateName = "crossbeam-utils"; - version = "0.8.16"; - edition = "2018"; - sha256 = "153j0gikblz7n7qdvdi8pslhi008s1yp9cmny6vw07ad7pbb48js"; - dependencies = [ - { - name = "cfg-if"; - packageId = "cfg-if"; - } - ]; + version = "0.8.20"; + edition = "2021"; + sha256 = "100fksq5mm1n7zj242cclkw6yf7a4a8ix3lvpfkhxvdhbda9kv12"; + libName = "crossbeam_utils"; features = { "default" = [ "std" ]; "loom" = [ "dep:loom" ]; @@ -1590,12 +1594,8 @@ rec { requiredFeatures = [ ]; } ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./.; } - else ./.; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./.; }; + libName = "crunch_v2"; dependencies = [ { name = "anyhow"; @@ -1705,6 +1705,7 @@ rec { version = "0.1.6"; edition = "2018"; sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; authors = [ "RustCrypto Developers" ]; @@ -1730,6 +1731,7 @@ rec { version = "0.11.1"; edition = "2018"; sha256 = "05672ncc54h66vph42s0a42ljl69bwnqjh0x4xgj2v1395psildi"; + libName = "crypto_mac"; authors = [ "RustCrypto Developers" ]; @@ -1752,9 +1754,10 @@ rec { }; "curve25519-dalek" = rec { crateName = "curve25519-dalek"; - version = "4.1.1"; + version = "4.1.3"; edition = "2021"; - sha256 = "0p7ns5917k6369gajrsbfj24llc5zfm635yh3abla7sb5rm8r6z8"; + sha256 = "1gmjb9dsknrr8lypmhkyjd67p1arb8mbfamlwxm7vph38my8pywp"; + libName = "curve25519_dalek"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -1800,10 +1803,6 @@ rec { ]; buildDependencies = [ { - name = "platforms"; - packageId = "platforms"; - } - { name = "rustc_version"; packageId = "rustc_version"; } @@ -1827,6 +1826,7 @@ rec { edition = "2021"; sha256 = "1cry71xxrr0mcy5my3fb502cwfxy6822k4pm19cwrilrg7hq4s7l"; procMacro = true; + libName = "curve25519_dalek_derive"; dependencies = [ { name = "proc-macro2"; @@ -1838,7 +1838,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -1846,9 +1846,10 @@ rec { }; "data-encoding" = rec { crateName = "data-encoding"; - version = "2.4.0"; + version = "2.6.0"; edition = "2018"; - sha256 = "023k3dk8422jgbj7k72g63x51h1mhv91dhw1j4h205vzh6fnrrn2"; + sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -1860,9 +1861,9 @@ rec { }; "der" = rec { crateName = "der"; - version = "0.7.8"; + version = "0.7.9"; edition = "2021"; - sha256 = "070bwiyr80800h31c5zd96ckkgagfjgnrrdmz3dzg2lccsd3dypz"; + sha256 = "1h4vzjfa1lczxdf8avfj9qlwh1qianqlxdy1g5rn762qnvkzhnzm"; authors = [ "RustCrypto Developers" ]; @@ -1953,6 +1954,7 @@ rec { version = "2.0.0"; edition = "2018"; sha256 = "1q9kr151h9681wwp6is18750ssghz6j9j7qm7qi1ngcwy7mzi35r"; + libName = "dirs_next"; authors = [ "The @xdg-rs members" ]; @@ -1973,6 +1975,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "0kavhavdxv4phzj4l0psvh55hszwnr0rcz8sxbvx20pyqi2a3gaf"; + libName = "dirs_sys_next"; authors = [ "The @xdg-rs members" ]; @@ -1999,9 +2002,10 @@ rec { }; "dyn-clone" = rec { crateName = "dyn-clone"; - version = "1.0.16"; + version = "1.0.17"; edition = "2018"; - sha256 = "0pa9kas6a241pbx0q82ipwi4f7m7wwyzkkc725caky24gl4j4nsl"; + sha256 = "09cig7dgg6jnqa10p4233nd8wllbjf4ffsw7wj0m4lwa5w3z0vhd"; + libName = "dyn_clone"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -2041,9 +2045,10 @@ rec { }; "ed25519-dalek" = rec { crateName = "ed25519-dalek"; - version = "2.1.0"; + version = "2.1.1"; edition = "2021"; - sha256 = "1h13qm789m9gdjl6jazss80hqi8ll37m0afwcnw23zcbqjp8wqhz"; + sha256 = "0w88cafwglg9hjizldbmlza0ns3hls81zk1bcih3m5m3h67algaa"; + libName = "ed25519_dalek"; authors = [ "isis lovecruft <isis@patternsinthevoid.net>" "Tony Arcieri <bascule@gmail.com>" @@ -2118,9 +2123,9 @@ rec { }; "either" = rec { crateName = "either"; - version = "1.9.0"; + version = "1.13.0"; edition = "2018"; - sha256 = "01qy3anr7jal5lpc20791vxrw0nl6vksb5j7x56q2fycgcyy8sm2"; + sha256 = "1w2c1mybrd7vljyxk77y9f4w9dyjrmp3yp82mk7bcm8848fazcb0"; authors = [ "bluss" ]; @@ -2145,11 +2150,38 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; + "enum-primitive-derive" = rec { + crateName = "enum-primitive-derive"; + version = "0.3.0"; + edition = "2018"; + sha256 = "0k6wcf58h5kh64yq5nfq71va53kaya0kzxwsjwbgwm2n2zd9axxs"; + procMacro = true; + libName = "enum_primitive_derive"; + authors = [ + "Doug Goldstein <cardoe@cardoe.com>" + ]; + dependencies = [ + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + } + ]; + + }; "enum_dispatch" = rec { crateName = "enum_dispatch"; - version = "0.3.12"; + version = "0.3.13"; edition = "2018"; - sha256 = "03l998igqfzkykmj8i5qlbwhv2id9jn98fkkl82lv3dvg0q32cwg"; + sha256 = "1kby2jz173ggg7wk41vjsskmkdyx7749ll8lhqhv6mb5qqmww65a"; procMacro = true; authors = [ "Anton Lazarev <https://antonok.com>" @@ -2169,7 +2201,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -2184,9 +2216,9 @@ rec { }; "errno" = rec { crateName = "errno"; - version = "0.3.7"; + version = "0.3.9"; edition = "2018"; - sha256 = "1f4f7s0wngfxwh6a4kq3aws3i37xnzm3m4d86xw2lz3z9qcsfn7j"; + sha256 = "1fi0m0493maq1jygcf1bya9cymz2pc1mqxj26bdv7yjd37v5qk2k"; authors = [ "Chris Wong <lambda.fairy@gmail.com>" ]; @@ -2211,7 +2243,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_System_Diagnostics_Debug" ]; } @@ -2241,6 +2273,7 @@ rec { version = "0.1.9"; edition = "2015"; sha256 = "0nj6j26p71bjy8h42x6jahx1hn0ng6mc2miwpgwnp8vnwqf4jq3k"; + libName = "fallible_streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -2251,6 +2284,7 @@ rec { version = "0.2.0"; edition = "2018"; sha256 = "0g7kfll3xyh99kc7r352lhljnwvgayxxa6saifb6725inikmyxlm"; + libName = "fast_float"; authors = [ "Ivan Smirnov <i.s.smirnov@gmail.com>" ]; @@ -2277,9 +2311,9 @@ rec { }; "fastrand" = rec { crateName = "fastrand"; - version = "2.0.1"; + version = "2.1.1"; edition = "2018"; - sha256 = "19flpv5zbzpf0rk4x77z4zf25in0brg8l7m304d3yrf47qvwxjr5"; + sha256 = "19nyzdq3ha4g173364y2wijmd6jlyms8qx40daqkxsnl458jmh78"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -2293,9 +2327,10 @@ rec { }; "fiat-crypto" = rec { crateName = "fiat-crypto"; - version = "0.2.5"; + version = "0.2.9"; edition = "2018"; - sha256 = "1dxn0g50pv0ppal779vi7k40fr55pbhkyv4in7i13pgl4sn3wmr7"; + sha256 = "07c1vknddv3ak7w89n85ik0g34nzzpms6yb845vrjnv9m4csbpi8"; + libName = "fiat_crypto"; authors = [ "Fiat Crypto library authors <jgross@mit.edu>" ]; @@ -2318,9 +2353,9 @@ rec { }; "flate2" = rec { crateName = "flate2"; - version = "1.0.28"; + version = "1.0.34"; edition = "2018"; - sha256 = "03llhsh4gqdirnfxxb9g2w9n0721dyn4yjir3pz7z4vjaxb3yc26"; + sha256 = "1w1nf2ap4q1sq1v6v951011wcvljk449ap7q7jnnjf8hvjs8kdd1"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Josh Triplett <josh@joshtriplett.org>" @@ -2351,6 +2386,7 @@ rec { "cloudflare_zlib" = [ "any_zlib" "cloudflare-zlib-sys" ]; "default" = [ "rust_backend" ]; "libz-ng-sys" = [ "dep:libz-ng-sys" ]; + "libz-rs-sys" = [ "dep:libz-rs-sys" ]; "libz-sys" = [ "dep:libz-sys" ]; "miniz-sys" = [ "rust_backend" ]; "miniz_oxide" = [ "dep:miniz_oxide" ]; @@ -2359,6 +2395,7 @@ rec { "zlib-default" = [ "any_zlib" "libz-sys/default" ]; "zlib-ng" = [ "any_zlib" "libz-ng-sys" ]; "zlib-ng-compat" = [ "zlib" "libz-sys/zlib-ng" ]; + "zlib-rs" = [ "any_zlib" "libz-rs-sys" ]; }; resolvedDefaultFeatures = [ "any_impl" "miniz_oxide" "rust_backend" ]; }; @@ -2411,9 +2448,9 @@ rec { }; "futures" = rec { crateName = "futures"; - version = "0.3.29"; + version = "0.3.31"; edition = "2018"; - sha256 = "0dak2ilpcmyjrb1j54fzy9hlw6vd10vqljq9gd59pbrq9dqr00ns"; + sha256 = "0xh8ddbkm9jy8kc5gbvjp9a4b6rqqxvc8471yb2qaz5wm2qhgg35"; dependencies = [ { name = "futures-channel"; @@ -2472,9 +2509,10 @@ rec { }; "futures-channel" = rec { crateName = "futures-channel"; - version = "0.3.29"; + version = "0.3.31"; edition = "2018"; - sha256 = "1jxsifvrbqzdadk0svbax71cba5d3qg3wgjq8i160mxmd1kdckgz"; + sha256 = "040vpqpqlbk099razq8lyn74m0f161zd0rp36hciqrwcg2zibzrd"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -2499,9 +2537,10 @@ rec { }; "futures-core" = rec { crateName = "futures-core"; - version = "0.3.29"; + version = "0.3.31"; edition = "2018"; - sha256 = "1308bpj0g36nhx2y6bl4mm6f1gnh9xyvvw2q2wpdgnb6dv3247gb"; + sha256 = "0gk6yrxgi5ihfanm2y431jadrll00n5ifhnpx090c2f2q1cr1wh5"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -2511,9 +2550,10 @@ rec { }; "futures-executor" = rec { crateName = "futures-executor"; - version = "0.3.29"; + version = "0.3.31"; edition = "2018"; - sha256 = "1g4pjni0sw28djx6mlcfz584abm2lpifz86cmng0kkxh7mlvhkqg"; + sha256 = "17vcci6mdfzx4gbk0wx64chr2f13wwwpvyf3xd5fb1gmjzcx2a0y"; + libName = "futures_executor"; dependencies = [ { name = "futures-core"; @@ -2541,9 +2581,10 @@ rec { }; "futures-io" = rec { crateName = "futures-io"; - version = "0.3.29"; + version = "0.3.31"; edition = "2018"; - sha256 = "1ajsljgny3zfxwahba9byjzclrgvm1ypakca8z854k2w7cb4mwwb"; + sha256 = "1ikmw1yfbgvsychmsihdkwa8a1knank2d9a8dk01mbjar9w1np4y"; + libName = "futures_io"; features = { "default" = [ "std" ]; }; @@ -2551,10 +2592,11 @@ rec { }; "futures-macro" = rec { crateName = "futures-macro"; - version = "0.3.29"; + version = "0.3.31"; edition = "2018"; - sha256 = "1nwd18i8kvpkdfwm045hddjli0n96zi7pn6f99zi9c74j7ym7cak"; + sha256 = "0l1n7kqzwwmgiznn0ywdc5i24z72zvh9q1dwps54mimppi7f6bhn"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -2566,7 +2608,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -2574,9 +2616,10 @@ rec { }; "futures-sink" = rec { crateName = "futures-sink"; - version = "0.3.29"; + version = "0.3.31"; edition = "2018"; - sha256 = "05q8jykqddxzp8nwf00wjk5m5mqi546d7i8hsxma7hiqxrw36vg3"; + sha256 = "1xyly6naq6aqm52d5rh236snm08kw8zadydwqz8bip70s6vzlxg5"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -2585,9 +2628,10 @@ rec { }; "futures-task" = rec { crateName = "futures-task"; - version = "0.3.29"; + version = "0.3.31"; edition = "2018"; - sha256 = "1qmsss8rb5ppql4qvd4r70h9gpfcpd0bg2b3qilxrnhdkc397lgg"; + sha256 = "124rv4n90f5xwfsm9qw6y99755y021cmi5dhzh253s920z77s3zr"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -2596,9 +2640,10 @@ rec { }; "futures-util" = rec { crateName = "futures-util"; - version = "0.3.29"; + version = "0.3.31"; edition = "2018"; - sha256 = "0141rkqh0psj4h8x8lgsl1p29dhqr7z2wcixkcbs60z74kb2d5d1"; + sha256 = "10aa1ar8bgkgbr4wzxlidkqkcxf77gffyj8j7768h831pcaq784z"; + libName = "futures_util"; dependencies = [ { name = "futures-channel"; @@ -2726,9 +2771,9 @@ rec { }; "getrandom" = rec { crateName = "getrandom"; - version = "0.2.11"; + version = "0.2.15"; edition = "2018"; - sha256 = "03q7120cc2kn7ry013i67zmjl2g9q73h1ks5z08hq5v9syz0d47y"; + sha256 = "1mzlnrb3dgyd1fb84gvw10pyr8wdqdl4ry4sr64i1s8an66pqmn4"; authors = [ "The Rand Project Developers" ]; @@ -2775,9 +2820,9 @@ rec { }; "gimli" = rec { crateName = "gimli"; - version = "0.28.0"; + version = "0.31.1"; edition = "2018"; - sha256 = "1h7hcl3chfvd2gfrrxjymnwj7anqxjslvz20kcargkvsya2dgf3g"; + sha256 = "0gvqc0ramx8szv76jhfd4dms0zyamvlg4whhiz11j34hh3dqxqh7"; features = { "default" = [ "read-all" "write" ]; "endian-reader" = [ "read" "dep:stable_deref_trait" ]; @@ -2802,9 +2847,9 @@ rec { }; "h2" = rec { crateName = "h2"; - version = "0.3.22"; + version = "0.3.26"; edition = "2018"; - sha256 = "0y41jlflvw8niifdirgng67zdmic62cjf5m2z69hzrpn5qr50qjd"; + sha256 = "1s7msnfv7xprzs6xzfj5sg6p8bjcdpcqcmjjbkd345cyi1x55zl1"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -2872,11 +2917,11 @@ rec { ]; features = { }; }; - "hashbrown" = rec { + "hashbrown 0.14.5" = rec { crateName = "hashbrown"; - version = "0.14.2"; + version = "0.14.5"; edition = "2021"; - sha256 = "0mj1x1d16acxf4zg7wr7q2x8pgzfi1bzpifygcsxmg4d2n972gpr"; + sha256 = "1wa1vy1xs3mp11bn3z9dv0jricgr6a2j0zkf1g19yz3vw4il89z5"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -2920,9 +2965,32 @@ rec { "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" ]; "serde" = [ "dep:serde" ]; }; - resolvedDefaultFeatures = [ "ahash" "allocator-api2" "default" "inline-more" "raw" "rayon" ]; + resolvedDefaultFeatures = [ "ahash" "allocator-api2" "default" "inline-more" "rayon" ]; + }; + "hashbrown 0.15.0" = rec { + crateName = "hashbrown"; + version = "0.15.0"; + edition = "2021"; + sha256 = "1yx4xq091s7i6mw6bn77k8cp4jrpcac149xr32rg8szqsj27y20y"; + authors = [ + "Amanieu d'Antras <amanieu@gmail.com>" + ]; + features = { + "alloc" = [ "dep:alloc" ]; + "allocator-api2" = [ "dep:allocator-api2" ]; + "borsh" = [ "dep:borsh" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "default-hasher" "inline-more" "allocator-api2" "equivalent" "raw-entry" ]; + "default-hasher" = [ "dep:foldhash" ]; + "equivalent" = [ "dep:equivalent" ]; + "nightly" = [ "allocator-api2?/nightly" "bumpalo/allocator_api" ]; + "rayon" = [ "dep:rayon" ]; + "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" "raw-entry" ]; + "serde" = [ "dep:serde" ]; + }; }; - "heck" = rec { + "heck 0.4.1" = rec { crateName = "heck"; version = "0.4.1"; edition = "2018"; @@ -2936,11 +3004,19 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; + "heck 0.5.0" = rec { + crateName = "heck"; + version = "0.5.0"; + edition = "2021"; + sha256 = "1sjmpsdl8czyh9ywl3qcsfsq9a307dg4ni2vnlwgnzzqhc4y0113"; + + }; "hermit-abi" = rec { crateName = "hermit-abi"; - version = "0.3.3"; + version = "0.3.9"; edition = "2021"; - sha256 = "1dyc8qsjh876n74a3rcz8h43s27nj1sypdhsn2ms61bd3b47wzyp"; + sha256 = "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -2998,27 +3074,27 @@ rec { }; "home" = rec { crateName = "home"; - version = "0.5.5"; - edition = "2018"; - sha256 = "1nqx1krijvpd03d96avsdyknd12h8hs3xhxwgqghf8v9xxzc4i2l"; + version = "0.5.9"; + edition = "2021"; + sha256 = "19grxyg35rqfd802pcc9ys1q3lafzlcjcv2pl2s5q8xpyr5kblg3"; authors = [ "Brian Anderson <andersrb@gmail.com>" ]; dependencies = [ { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); - features = [ "Win32_Foundation" "Win32_UI_Shell" ]; + features = [ "Win32_Foundation" "Win32_UI_Shell" "Win32_System_Com" ]; } ]; }; "http" = rec { crateName = "http"; - version = "0.2.11"; + version = "0.2.12"; edition = "2018"; - sha256 = "1fwz3mhh86h5kfnr5767jlx9agpdggclq7xsqx930fflzakb2iw9"; + sha256 = "1w81s4bcbmcj9bjp7mllm8jlz6b31wzvirz8bgpzbqkpwmbvn730"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Carl Lerche <me@carllerche.com>" @@ -3042,9 +3118,10 @@ rec { }; "http-body" = rec { crateName = "http-body"; - version = "0.4.5"; + version = "0.4.6"; edition = "2018"; - sha256 = "1l967qwwlvhp198xdrnc0p5d7jwfcp6q2lm510j6zqw4s4b8zwym"; + sha256 = "1lmyjfk6bqk6k9gkn1dxq770sb78pqbqshga241hr5p995bb5skw"; + libName = "http_body"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -3068,9 +3145,9 @@ rec { }; "httparse" = rec { crateName = "httparse"; - version = "1.8.0"; + version = "1.9.5"; edition = "2018"; - sha256 = "010rrfahm1jss3p022fqf3j3jmm72vhn4iqhykahb9ynpaag75yq"; + sha256 = "0ip9v8m9lvgvq1lznl31wvn0ch1v254na7lhid9p29yx9rbx6wbx"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -3091,9 +3168,9 @@ rec { }; "hyper" = rec { crateName = "hyper"; - version = "0.14.27"; + version = "0.14.31"; edition = "2018"; - sha256 = "0s2l74p3harvjgb0bvaxlxgxq71vpfrzv0cqz2p9w8d8akbczcgz"; + sha256 = "11bf6mqcpzi0x2758p7q9zk3m877avzpbiw8nx8v2dd3iwp3024c"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -3147,7 +3224,7 @@ rec { } { name = "socket2"; - packageId = "socket2 0.4.10"; + packageId = "socket2"; optional = true; features = [ "all" ]; } @@ -3201,6 +3278,7 @@ rec { version = "0.23.2"; edition = "2018"; sha256 = "0736s6a32dqr107f943xaz1n05flbinq6l19lq1wsrxkc5g9d20p"; + libName = "hyper_rustls"; dependencies = [ { name = "http"; @@ -3272,9 +3350,10 @@ rec { }; "iana-time-zone" = rec { crateName = "iana-time-zone"; - version = "0.1.58"; + version = "0.1.61"; edition = "2018"; - sha256 = "081vcr8z8ddhl5r1ywif6grnswk01b2ac4nks2bhn8zzdimvh9l3"; + sha256 = "085jjsls330yj1fnwykfzmb2f10zp6l7w4fhq81ng81574ghhpi3"; + libName = "iana_time_zone"; authors = [ "Andrew Straw <strawman@astraw.com>" "René Kijewski <rene.kijewski@fu-berlin.de>" @@ -3299,12 +3378,12 @@ rec { { name = "js-sys"; packageId = "js-sys"; - target = { target, features }: ("wasm32" == target."arch" or null); + target = { target, features }: (("wasm32" == target."arch" or null) && ("unknown" == target."os" or null)); } { name = "wasm-bindgen"; packageId = "wasm-bindgen"; - target = { target, features }: ("wasm32" == target."arch" or null); + target = { target, features }: (("wasm32" == target."arch" or null) && ("unknown" == target."os" or null)); } { name = "windows-core"; @@ -3320,6 +3399,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k"; + libName = "iana_time_zone_haiku"; authors = [ "René Kijewski <crates.io@k6i.de>" ]; @@ -3333,9 +3413,9 @@ rec { }; "indexmap" = rec { crateName = "indexmap"; - version = "2.1.0"; + version = "2.6.0"; edition = "2021"; - sha256 = "07rxrqmryr1xfnmhrjlz8ic6jw28v6h5cig3ws2c9d0wifhy2c6m"; + sha256 = "1nmrwn8lbs19gkvhxaawffzbvrpyrb5y3drcrr645x957kz0fybh"; dependencies = [ { name = "equivalent"; @@ -3344,13 +3424,13 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.15.0"; usesDefaultFeatures = false; - features = [ "raw" ]; } ]; features = { "arbitrary" = [ "dep:arbitrary" ]; + "borsh" = [ "dep:borsh" ]; "default" = [ "std" ]; "quickcheck" = [ "dep:quickcheck" ]; "rayon" = [ "dep:rayon" ]; @@ -3361,9 +3441,9 @@ rec { }; "indicatif" = rec { crateName = "indicatif"; - version = "0.17.7"; + version = "0.17.8"; edition = "2021"; - sha256 = "098ggvg7ps4097p5n9hmb3pqqy10bi8vjfzb7pci79xrklf78a7v"; + sha256 = "18xyqxw9i5x4sbpzckhfz3nm984iq9r7nbi2lk76nz888n7mlfkn"; dependencies = [ { name = "console"; @@ -3405,9 +3485,9 @@ rec { }; "instant" = rec { crateName = "instant"; - version = "0.1.12"; + version = "0.1.13"; edition = "2018"; - sha256 = "0b2bx5qdlwayriidhrag8vhy10kdfimfhmb3jnjmsz2h9j1bwnvs"; + sha256 = "08h27kzvb5jw74mh0ajv0nv9ggwvgqm8ynjsn2sa9jsks4cjh970"; authors = [ "sebcrozet <developer@crozet.re>" ]; @@ -3425,11 +3505,19 @@ rec { "web-sys" = [ "dep:web-sys" ]; }; }; + "is_terminal_polyfill" = rec { + crateName = "is_terminal_polyfill"; + version = "1.70.1"; + edition = "2021"; + sha256 = "1kwfgglh91z33kl0w5i338mfpa3zs0hidq5j4ny4rmjwrikchhvr"; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; "itertools" = rec { crateName = "itertools"; - version = "0.11.0"; + version = "0.12.1"; edition = "2018"; - sha256 = "0mzyqcc59azx9g5cg6fs8k529gvh4463smmka6jvzs3cd2jp7hdi"; + sha256 = "0s95jbb3ndj1lvfxyq5wanc0fm0r6hg6q4ngb92qlfdxvci10ads"; authors = [ "bluss" ]; @@ -3448,9 +3536,9 @@ rec { }; "itoa" = rec { crateName = "itoa"; - version = "1.0.9"; + version = "1.0.11"; edition = "2018"; - sha256 = "0f6cpb4yqzhkrhhg6kqsw3wnmmhdnnffi6r2xzy248gzi2v0l5dg"; + sha256 = "0nv9cqjwzr3q58qz84dcz63ggc54yhf1yqar1m858m1kfd4g3wa9"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3460,9 +3548,9 @@ rec { }; "jobserver" = rec { crateName = "jobserver"; - version = "0.1.27"; - edition = "2018"; - sha256 = "0z9w6vfqwbr6hfk9yaw7kydlh6f7k39xdlszxlh39in4acwzcdwc"; + version = "0.1.32"; + edition = "2021"; + sha256 = "1l2k50qmj84x9mn39ivjz76alqmx72jhm12rw33zx9xnpv5xpla8"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -3477,9 +3565,10 @@ rec { }; "js-sys" = rec { crateName = "js-sys"; - version = "0.3.65"; - edition = "2018"; - sha256 = "1s1gaxgzpqfyygc7f2pwp9y128rh5f8zvsc4nm5yazgna9cw7h2l"; + version = "0.3.72"; + edition = "2021"; + sha256 = "1a8r61hbgw5kmscgj3g5pzg2ywlnswvljy0l592v0xdxlayz323a"; + libName = "js_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -3493,9 +3582,9 @@ rec { }; "lazy_static" = rec { crateName = "lazy_static"; - version = "1.4.0"; + version = "1.5.0"; edition = "2015"; - sha256 = "0in6ikhw8mgl33wjv6q6xfrb5b9jr16q8ygjy803fay4zcisvaz2"; + sha256 = "1zk6dqqni0193xg6iijh7i3i44sryglwgvx20spdvwk3r6sbrlmv"; authors = [ "Marvin Löbel <loebel.marvin@gmail.com>" ]; @@ -3506,9 +3595,9 @@ rec { }; "libc" = rec { crateName = "libc"; - version = "0.2.150"; + version = "0.2.160"; edition = "2015"; - sha256 = "0g10n8c830alndgjb8xk1i9kz5z727np90z1z81119pr8d3jmnc9"; + sha256 = "0kyf734dm5iplyq5p5jc4x5dqxjnc5jwawq9cngawx0qrl311cph"; authors = [ "The Rust Project Developers" ]; @@ -3534,39 +3623,65 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; + "libmimalloc-sys" = rec { + crateName = "libmimalloc-sys"; + version = "0.1.39"; + edition = "2018"; + links = "mimalloc"; + sha256 = "0i3b0dzz7cp0ik7ys66q92r16va78gwlbrnxhj5fnkdxsc8niai3"; + libName = "libmimalloc_sys"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cty" = [ "dep:cty" ]; + "extended" = [ "cty" ]; + }; + }; "libredox" = rec { crateName = "libredox"; - version = "0.0.1"; + version = "0.1.3"; edition = "2021"; - sha256 = "1s2fh4ikpp9xl0lsl01pi0n8pw1q9s3ld452vd8qh1v63v537j45"; + sha256 = "139602gzgs0k91zb7dvgj1qh4ynb8g1lbxsswdim18hcb6ykgzy0"; authors = [ "4lDO2 <4lDO2@protonmail.com>" ]; dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.1"; + packageId = "bitflags 2.6.0"; } { name = "libc"; packageId = "libc"; } - { - name = "redox_syscall"; - packageId = "redox_syscall 0.4.1"; - } ]; features = { - "default" = [ "scheme" "call" ]; - "scheme" = [ "call" ]; + "default" = [ "call" "std" "redox_syscall" ]; + "ioslice" = [ "dep:ioslice" ]; + "mkns" = [ "ioslice" ]; + "redox_syscall" = [ "dep:redox_syscall" ]; }; - resolvedDefaultFeatures = [ "call" ]; + resolvedDefaultFeatures = [ "call" "std" ]; }; "linux-raw-sys" = rec { crateName = "linux-raw-sys"; - version = "0.4.11"; + version = "0.4.14"; edition = "2021"; - sha256 = "0adqqaya81s7k5r323g65pw6q85pxd1x4prz9whh5i4abysqi54n"; + sha256 = "12gsjgbhhjwywpqcrizv80vrp7p7grsz5laqq773i33wphjsxcvq"; + libName = "linux_raw_sys"; authors = [ "Dan Gohman <dev@sunfishcode.online>" ]; @@ -3580,9 +3695,9 @@ rec { }; "lock_api" = rec { crateName = "lock_api"; - version = "0.4.11"; - edition = "2018"; - sha256 = "0iggx0h4jx63xm35861106af3jkxq06fpqhpkhgw0axi2n38y5iw"; + version = "0.4.12"; + edition = "2021"; + sha256 = "05qvxa6g27yyva25a5ghsg85apdxkvr77yhkyhapj6r8vnf8pbq7"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -3608,17 +3723,20 @@ rec { }; "log" = rec { crateName = "log"; - version = "0.4.20"; - edition = "2015"; - sha256 = "13rf7wphnwd61vazpxr7fiycin6cb1g8fmvgqg18i464p0y1drmm"; + version = "0.4.22"; + edition = "2021"; + sha256 = "093vs0wkm1rgyykk7fjbqp2lwizbixac1w52gv109p5r4jh0p9x7"; authors = [ "The Rust Project Developers" ]; features = { - "kv_unstable" = [ "value-bag" ]; - "kv_unstable_serde" = [ "kv_unstable_std" "value-bag/serde" "serde" ]; - "kv_unstable_std" = [ "std" "kv_unstable" "value-bag/error" ]; - "kv_unstable_sval" = [ "kv_unstable" "value-bag/sval" "sval" "sval_ref" ]; + "kv_serde" = [ "kv_std" "value-bag/serde" "serde" ]; + "kv_std" = [ "std" "kv" "value-bag/error" ]; + "kv_sval" = [ "kv" "value-bag/sval" "sval" "sval_ref" ]; + "kv_unstable" = [ "kv" "value-bag" ]; + "kv_unstable_serde" = [ "kv_serde" "kv_unstable_std" ]; + "kv_unstable_std" = [ "kv_std" "kv_unstable" ]; + "kv_unstable_sval" = [ "kv_sval" "kv_unstable" ]; "serde" = [ "dep:serde" ]; "sval" = [ "dep:sval" ]; "sval_ref" = [ "dep:sval_ref" ]; @@ -3627,10 +3745,10 @@ rec { }; "lz4" = rec { crateName = "lz4"; - version = "1.24.0"; + version = "1.28.0"; edition = "2018"; crateBin = [ ]; - sha256 = "1wad97k0asgvaj16ydd09gqs2yvgaanzcvqglrhffv7kdpc2v7ky"; + sha256 = "09b70ciyfbynzpy3yf501ab9f8chyyl0dppfh0cxv7d7njrfn7sd"; authors = [ "Jens Heyens <jens.heyens@ewetel.net>" "Artem V. Navrotskiy <bozaro@buzzsoft.ru>" @@ -3638,10 +3756,6 @@ rec { ]; dependencies = [ { - name = "libc"; - packageId = "libc"; - } - { name = "lz4-sys"; packageId = "lz4-sys"; } @@ -3650,10 +3764,11 @@ rec { }; "lz4-sys" = rec { crateName = "lz4-sys"; - version = "1.9.4"; + version = "1.11.1+lz4-1.10.0"; edition = "2015"; links = "lz4"; - sha256 = "0059ik4xlvnss5qfh6l691psk4g3350ljxaykzv10yr0gqqppljp"; + sha256 = "1rhqnhwq05fmlc2q39ipsq0vpi0xf6w6p22j6q5x637dqvbc1n3b"; + libName = "lz4_sys"; authors = [ "Jens Heyens <jens.heyens@ewetel.net>" "Artem V. Navrotskiy <bozaro@buzzsoft.ru>" @@ -3679,6 +3794,7 @@ rec { edition = "2018"; links = "lzma"; sha256 = "09sxp20waxyglgn3cjz8qjkspb3ryz2fwx4rigkwvrk46ymh9njz"; + libName = "lzma_sys"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -3740,9 +3856,9 @@ rec { }; "memchr" = rec { crateName = "memchr"; - version = "2.6.4"; + version = "2.7.4"; edition = "2021"; - sha256 = "0rq1ka8790ns41j147npvxcqcl2anxyngsdimy85ag2api0fwrgn"; + sha256 = "18z32bhxrax0fnjikv475z7ii718hq457qwmaryixfxsl2qrmjkq"; authors = [ "Andrew Gallant <jamslam@gmail.com>" "bluss" @@ -3778,21 +3894,32 @@ rec { "stable_deref_trait" = [ "dep:stable_deref_trait" ]; }; }; - "memoffset" = rec { - crateName = "memoffset"; - version = "0.9.0"; - edition = "2015"; - sha256 = "0v20ihhdzkfw1jx00a7zjpk2dcp5qjq6lz302nyqamd9c4f4nqss"; + "mimalloc" = rec { + crateName = "mimalloc"; + version = "0.1.43"; + edition = "2018"; + sha256 = "0csnyrxc16i592gm5ffham07jyj2w98qsh9jyy1rv59lmr8474b8"; authors = [ - "Gilad Naaman <gilad.naaman@gmail.com>" + "Octavian Oncescu <octavonce@gmail.com>" + "Vincent Rouillé <vincent@speedy37.fr>" + "Thom Chiovoloni <chiovolonit@gmail.com>" ]; - buildDependencies = [ + dependencies = [ { - name = "autocfg"; - packageId = "autocfg"; + name = "libmimalloc-sys"; + packageId = "libmimalloc-sys"; + usesDefaultFeatures = false; } ]; - features = { }; + features = { + "debug" = [ "libmimalloc-sys/debug" ]; + "debug_in_debug" = [ "libmimalloc-sys/debug_in_debug" ]; + "extended" = [ "libmimalloc-sys/extended" ]; + "local_dynamic_tls" = [ "libmimalloc-sys/local_dynamic_tls" ]; + "no_thp" = [ "libmimalloc-sys/no_thp" ]; + "override" = [ "libmimalloc-sys/override" ]; + "secure" = [ "libmimalloc-sys/secure" ]; + }; resolvedDefaultFeatures = [ "default" ]; }; "minimal-lexical" = rec { @@ -3800,6 +3927,7 @@ rec { version = "0.2.1"; edition = "2018"; sha256 = "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8"; + libName = "minimal_lexical"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -3810,17 +3938,17 @@ rec { }; "miniz_oxide" = rec { crateName = "miniz_oxide"; - version = "0.7.1"; - edition = "2018"; - sha256 = "1ivl3rbbdm53bzscrd01g60l46lz5krl270487d8lhjvwl5hx0g7"; + version = "0.8.0"; + edition = "2021"; + sha256 = "1wadxkg6a6z4lr7kskapj5d8pxlx7cp1ifw4daqnkzqjxych5n72"; authors = [ "Frommi <daniil.liferenko@gmail.com>" "oyvindln <oyvindln@users.noreply.github.com>" ]; dependencies = [ { - name = "adler"; - packageId = "adler"; + name = "adler2"; + packageId = "adler2"; usesDefaultFeatures = false; } ]; @@ -3829,7 +3957,7 @@ rec { "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; "default" = [ "with-alloc" ]; - "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler/rustc-dep-of-std" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler2/rustc-dep-of-std" ]; "simd" = [ "simd-adler32" ]; "simd-adler32" = [ "dep:simd-adler32" ]; }; @@ -3837,9 +3965,9 @@ rec { }; "mio" = rec { crateName = "mio"; - version = "0.8.9"; - edition = "2018"; - sha256 = "1l23hg513c23nhcdzvk25caaj28mic6qgqadbn8axgj6bqf2ikix"; + version = "1.0.2"; + edition = "2021"; + sha256 = "1v1cnnn44awxbcfm4zlavwgkvbyg7gp5zzjm8mqf1apkrwflvq40"; authors = [ "Carl Lerche <me@carllerche.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -3847,6 +3975,12 @@ rec { ]; dependencies = [ { + name = "hermit-abi"; + packageId = "hermit-abi"; + rename = "libc"; + target = { target, features }: ("hermit" == target."os" or null); + } + { name = "libc"; packageId = "libc"; target = { target, features }: ("wasi" == target."os" or null); @@ -3863,9 +3997,9 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); - features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; + features = [ "Wdk_Foundation" "Wdk_Storage_FileSystem" "Wdk_System_IO" "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; } ]; features = { @@ -3877,9 +4011,9 @@ rec { }; "multimap" = rec { crateName = "multimap"; - version = "0.8.3"; + version = "0.10.0"; edition = "2015"; - sha256 = "0sicyz4n500vdhgcxn4g8jz97cp1ijir1rnbgph3pmx9ckz4dkp5"; + sha256 = "00vs2frqdhrr8iqx4y3fbq73ax5l12837fvbjrpi729d85alrz6y"; authors = [ "HÃ¥var Nøvik <havar.novik@gmail.com>" ]; @@ -3891,9 +4025,9 @@ rec { }; "multiversion" = rec { crateName = "multiversion"; - version = "0.7.3"; + version = "0.7.4"; edition = "2021"; - sha256 = "0al7yrf489lqzxx291sx9566n7slk2njwlqrxbjhqxk1zvbvkixj"; + sha256 = "0hm1y7dhdbam2yvaxmxzd0bj7gv777y0zn82jjzx0fhxl5hi31f4"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -3916,10 +4050,11 @@ rec { }; "multiversion-macros" = rec { crateName = "multiversion-macros"; - version = "0.7.3"; + version = "0.7.4"; edition = "2021"; - sha256 = "1j1avbxw7jscyi7dmnywhlwbiny1fvg1vpp9fy4dc1pd022kva16"; + sha256 = "142yhgdxvy9qjyi8n4wg2hi1dsckay816g1jg0jpvhp0x7g4v9vr"; procMacro = true; + libName = "multiversion_macros"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -3952,16 +4087,12 @@ rec { version = "0.1.0"; edition = "2021"; crateBin = [ ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ../../nix-compat; } - else ../../nix-compat; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat; }; + libName = "nix_compat"; dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.1"; + packageId = "bitflags 2.6.0"; } { name = "bstr"; @@ -3969,6 +4100,11 @@ rec { features = [ "alloc" "unicode" "serde" ]; } { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { name = "data-encoding"; packageId = "data-encoding"; } @@ -3981,14 +4117,36 @@ rec { packageId = "ed25519-dalek"; } { + name = "enum-primitive-derive"; + packageId = "enum-primitive-derive"; + } + { name = "glob"; packageId = "glob"; } { + name = "mimalloc"; + packageId = "mimalloc"; + } + { + name = "nix-compat-derive"; + packageId = "nix-compat-derive"; + optional = true; + } + { name = "nom"; packageId = "nom"; } { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + optional = true; + } + { name = "serde"; packageId = "serde"; features = [ "derive" ]; @@ -4005,17 +4163,63 @@ rec { name = "thiserror"; packageId = "thiserror"; } + { + name = "tokio"; + packageId = "tokio"; + optional = true; + features = [ "io-util" "macros" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } ]; devDependencies = [ { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "serde_json"; packageId = "serde_json"; } ]; features = { - "async" = [ "futures-util" ]; - "futures-util" = [ "dep:futures-util" ]; + "async" = [ "tokio" ]; + "bytes" = [ "dep:bytes" ]; + "default" = [ "async" "wire" "nix-compat-derive" ]; + "nix-compat-derive" = [ "dep:nix-compat-derive" ]; + "pin-project-lite" = [ "dep:pin-project-lite" ]; + "tokio" = [ "dep:tokio" ]; + "wire" = [ "tokio" "pin-project-lite" "bytes" ]; }; + resolvedDefaultFeatures = [ "async" "bytes" "default" "nix-compat-derive" "pin-project-lite" "tokio" "wire" ]; + }; + "nix-compat-derive" = rec { + crateName = "nix-compat-derive"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat-derive; }; + procMacro = true; + libName = "nix_compat_derive"; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + features = [ "proc-macro" ]; + } + { + name = "quote"; + packageId = "quote"; + features = [ "proc-macro" ]; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" "extra-traits" ]; + } + ]; + }; "nom" = rec { crateName = "nom"; @@ -4084,9 +4288,10 @@ rec { }; "num-traits" = rec { crateName = "num-traits"; - version = "0.2.17"; - edition = "2018"; - sha256 = "0z16bi5zwgfysz6765v3rd6whfbjpihx3mhsn4dg8dzj2c221qrr"; + version = "0.2.19"; + edition = "2021"; + sha256 = "0h984rhdkkqd4ny9cif7y2azl3xdfb7768hb9irhpsch4q3gq787"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -4109,28 +4314,6 @@ rec { }; resolvedDefaultFeatures = [ "default" "libm" "std" ]; }; - "num_cpus" = rec { - crateName = "num_cpus"; - version = "1.16.0"; - edition = "2015"; - sha256 = "0hra6ihpnh06dvfvz9ipscys0xfqa9ca9hzp384d5m02ssvgqqa1"; - authors = [ - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "hermit-abi"; - packageId = "hermit-abi"; - target = { target, features }: ("hermit" == target."os" or null); - } - { - name = "libc"; - packageId = "libc"; - target = { target, features }: (!(target."windows" or false)); - } - ]; - - }; "number_prefix" = rec { crateName = "number_prefix"; version = "0.4.0"; @@ -4146,9 +4329,9 @@ rec { }; "object" = rec { crateName = "object"; - version = "0.32.1"; + version = "0.36.5"; edition = "2018"; - sha256 = "1c02x4kvqpnl3wn7gz9idm4jrbirbycyqjgiw6lm1g9k77fzkxcw"; + sha256 = "0gk8lhbs229c68lapq6w6qmnm4jkj48hrcw5ilfyswy514nhmpxf"; dependencies = [ { name = "memchr"; @@ -4157,13 +4340,15 @@ rec { } ]; features = { - "all" = [ "read" "write" "std" "compression" "wasm" ]; + "all" = [ "read" "write" "build" "std" "compression" "wasm" ]; "alloc" = [ "dep:alloc" ]; + "build" = [ "build_core" "write_std" "elf" ]; + "build_core" = [ "read_core" "write_core" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "compression" = [ "dep:flate2" "dep:ruzstd" "std" ]; "core" = [ "dep:core" ]; "default" = [ "read" "compression" ]; - "doc" = [ "read_core" "write_std" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; + "doc" = [ "read_core" "write_std" "build_core" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; "pe" = [ "coff" ]; "read" = [ "read_core" "archive" "coff" "elf" "macho" "pe" "xcoff" "unaligned" ]; "rustc-dep-of-std" = [ "core" "compiler_builtins" "alloc" "memchr/rustc-dep-of-std" ]; @@ -4174,31 +4359,33 @@ rec { "write_core" = [ "dep:crc32fast" "dep:indexmap" "dep:hashbrown" ]; "write_std" = [ "write_core" "std" "indexmap?/std" "crc32fast?/std" ]; }; - resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" ]; + resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" "xcoff" ]; }; "once_cell" = rec { crateName = "once_cell"; - version = "1.18.0"; + version = "1.20.2"; edition = "2021"; - sha256 = "0vapcd5ambwck95wyz3ymlim35jirgnqn9a0qmi19msymv95v2yx"; + sha256 = "0xb7rw1aqr7pa4z3b00y7786gyf8awx2gca3md73afy76dzgwq8j"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" ]; features = { "alloc" = [ "race" ]; "atomic-polyfill" = [ "critical-section" ]; - "critical-section" = [ "dep:critical-section" "dep:atomic-polyfill" ]; + "critical-section" = [ "dep:critical-section" "portable-atomic" ]; "default" = [ "std" ]; "parking_lot" = [ "dep:parking_lot_core" ]; + "portable-atomic" = [ "dep:portable-atomic" ]; "std" = [ "alloc" ]; }; - resolvedDefaultFeatures = [ "alloc" "default" "race" "std" "unstable" ]; + resolvedDefaultFeatures = [ "alloc" "default" "race" "std" ]; }; "opaque-debug" = rec { crateName = "opaque-debug"; - version = "0.3.0"; + version = "0.3.1"; edition = "2018"; - sha256 = "1m8kzi4nd6shdqimn0mgb24f0hxslhnqd1whakyq06wcqd086jk2"; + sha256 = "10b3w0kydz5jf1ydyli5nv10gdfp97xh79bgz327d273bs46b3f0"; + libName = "opaque_debug"; authors = [ "RustCrypto Developers" ]; @@ -4209,6 +4396,7 @@ rec { version = "0.1.5"; edition = "2015"; sha256 = "1kq18qm48rvkwgcggfkqq6pm948190czqc94d6bm2sir5hq1l0gz"; + libName = "openssl_probe"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -4247,11 +4435,11 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "parking_lot 0.12.1" = rec { + "parking_lot 0.12.3" = rec { crateName = "parking_lot"; - version = "0.12.1"; - edition = "2018"; - sha256 = "13r2xk7mnxfc5g0g6dkdxqdqad99j7s7z8zhzz4npw5r0g0v4hip"; + version = "0.12.3"; + edition = "2021"; + sha256 = "09ws9g6245iiq8z975h8ycf818a66q3c6zv4b5h8skpm7hc1igzi"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -4262,7 +4450,7 @@ rec { } { name = "parking_lot_core"; - packageId = "parking_lot_core 0.9.9"; + packageId = "parking_lot_core 0.9.10"; } ]; features = { @@ -4319,11 +4507,11 @@ rec { "thread-id" = [ "dep:thread-id" ]; }; }; - "parking_lot_core 0.9.9" = rec { + "parking_lot_core 0.9.10" = rec { crateName = "parking_lot_core"; - version = "0.9.9"; - edition = "2018"; - sha256 = "13h0imw1aq86wj28gxkblhkzx6z1gk8q18n0v76qmmj6cliajhjc"; + version = "0.9.10"; + edition = "2021"; + sha256 = "1y3cf9ld9ijf7i4igwzffcn0xl16dxyn4c5bwgjck1dkgabiyh0y"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -4339,7 +4527,7 @@ rec { } { name = "redox_syscall"; - packageId = "redox_syscall 0.4.1"; + packageId = "redox_syscall 0.5.7"; target = { target, features }: ("redox" == target."os" or null); } { @@ -4348,7 +4536,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets 0.48.5"; + packageId = "windows-targets"; target = { target, features }: (target."windows" or false); } ]; @@ -4364,6 +4552,7 @@ rec { version = "0.2.4"; edition = "2021"; sha256 = "07wf6wf4jrxlq5p3xldxsnabp7jl06my2qp7kiwy9m3x2r5wac8i"; + libName = "parquet_format_safe"; authors = [ "Apache Thrift contributors <dev@thrift.apache.org>" "Jorge Leitao <jorgecarleitao@gmail.com>" @@ -4390,9 +4579,10 @@ rec { }; "percent-encoding" = rec { crateName = "percent-encoding"; - version = "2.3.0"; + version = "2.3.1"; edition = "2018"; - sha256 = "152slflmparkh27hprw62sph8rv77wckzhwl2dhqk6bf563lfalv"; + sha256 = "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -4404,9 +4594,9 @@ rec { }; "petgraph" = rec { crateName = "petgraph"; - version = "0.6.4"; + version = "0.6.5"; edition = "2018"; - sha256 = "1ac6wfq5f5pzcv0nvzzfgjbwg2kwslpnzsw5wcmxlscfcb9azlz1"; + sha256 = "1ns7mbxidnn2pqahbbjccxkrqkrll2i5rbxx43ns6rh6fn3cridl"; authors = [ "bluss" "mitchmindtree" @@ -4423,9 +4613,10 @@ rec { } ]; features = { - "all" = [ "unstable" "quickcheck" "matrix_graph" "stable_graph" "graphmap" ]; + "all" = [ "unstable" "quickcheck" "matrix_graph" "stable_graph" "graphmap" "rayon" ]; "default" = [ "graphmap" "stable_graph" "matrix_graph" ]; "quickcheck" = [ "dep:quickcheck" ]; + "rayon" = [ "dep:rayon" "indexmap/rayon" ]; "serde" = [ "dep:serde" ]; "serde-1" = [ "serde" "serde_derive" ]; "serde_derive" = [ "dep:serde_derive" ]; @@ -4434,9 +4625,10 @@ rec { }; "pin-project-lite" = rec { crateName = "pin-project-lite"; - version = "0.2.13"; + version = "0.2.14"; edition = "2018"; - sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + sha256 = "00nx3f04agwjlsmd3mc5rx5haibj2v8q9b52b0kwn63wcv4nz9mx"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -4444,6 +4636,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -4485,9 +4678,10 @@ rec { }; "pkg-config" = rec { crateName = "pkg-config"; - version = "0.3.27"; - edition = "2015"; - sha256 = "0r39ryh1magcq4cz5g9x88jllsnxnhcqr753islvyk4jp9h2h1r6"; + version = "0.3.31"; + edition = "2018"; + sha256 = "1wk6yp2phl91795ia0lwkr3wl4a9xkrympvhqq8cxk4d75hwhglm"; + libName = "pkg_config"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -4509,21 +4703,6 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "platforms" = rec { - crateName = "platforms"; - version = "3.2.0"; - edition = "2018"; - sha256 = "1c6bzwn877aqdbbmyqsl753ycbciwvbdh4lpzijb8vrfb4zsprhl"; - authors = [ - "Tony Arcieri <bascule@gmail.com>" - "Sergey \"Shnatsel\" Davidoff <shnatsel@gmail.com>" - ]; - features = { - "default" = [ "std" ]; - "serde" = [ "dep:serde" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "polars" = rec { crateName = "polars"; version = "0.35.4"; @@ -4718,6 +4897,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1rxa9dfsqy7mh4w9gy7y7kpig0wrzrjqi1axj43rnxyrlqq38l6x"; + libName = "polars_arrow"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -4779,12 +4959,12 @@ rec { { name = "getrandom"; packageId = "getrandom"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "wasm32-unknown-unknown"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "wasm32-unknown-unknown"); features = [ "js" ]; } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.14.5"; features = [ "rayon" "ahash" ]; } { @@ -4896,6 +5076,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1mnginlmgmlp167ij0r5lywvy50zns1cr8db1ikxxv2xwnwdawxf"; + libName = "polars_core"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4906,7 +5087,7 @@ rec { } { name = "bitflags"; - packageId = "bitflags 2.4.1"; + packageId = "bitflags 2.6.0"; } { name = "bytemuck"; @@ -4926,7 +5107,7 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.14.5"; features = [ "rayon" "ahash" ]; } { @@ -5045,6 +5226,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "127l5hazh5hn73j767cfyjwgbvvbab8hj53l1jp976daivb201gb"; + libName = "polars_error"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5081,6 +5263,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "01mwcdikw7y92xjhlsmj4wf0p9r3kvmhrvsbnsfh1mmc8l3hmqcn"; + libName = "polars_io"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5239,6 +5422,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "084gp9qa1w9b7dglcmrvlx6xrcl7hw5nmlb26w6xvrjvf1czfm9m"; + libName = "polars_lazy"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5249,7 +5433,7 @@ rec { } { name = "bitflags"; - packageId = "bitflags 2.4.1"; + packageId = "bitflags 2.6.0"; } { name = "glob"; @@ -5428,6 +5612,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "0dpnxcgc57k8xvp4jmjhz8jwz8rclf62h22zjiwpzaka54cb4zhs"; + libName = "polars_ops"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5453,7 +5638,7 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.14.5"; features = [ "rayon" "ahash" ]; } { @@ -5568,6 +5753,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1pb79wb1f31pk48lfm2w72hdfxqz6vv65iyxb072skfxnzj10q0l"; + libName = "polars_parquet"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -5585,7 +5771,7 @@ rec { } { name = "base64"; - packageId = "base64 0.21.5"; + packageId = "base64 0.21.7"; } { name = "brotli"; @@ -5688,6 +5874,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1v5xniw8yxx9cnksc4bf169b3p7gcl6dzryzgfd2m4scyrylw2b6"; + libName = "polars_pipe"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5706,7 +5893,7 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.14.5"; features = [ "rayon" "ahash" ]; } { @@ -5795,6 +5982,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1g2z0g0hpg05jp4n9s6m6m32adrjrdlq6zxd5c9lp1ggb04jmqqh"; + libName = "polars_plan"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5978,6 +6166,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1b3d8pdxz12dzg75nqb7b2p83l15c1z4r6589sknp462ra0sndfi"; + libName = "polars_row"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -6007,6 +6196,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "17jiflfmyymz1fdk2mrsdri2yqs1h7rqn66y3yny79a9d1wdgnxq"; + libName = "polars_sql"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -6071,6 +6261,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "0lgyk3fpp7krbyfra51pb4fqn6m3hk5gbj61fdvn3pffx5wnzrda"; + libName = "polars_time"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -6149,6 +6340,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1z7v7h54p883ww64mqpn4cphzwv0fd2bgsn8b1lx8qgyd60ycv6s"; + libName = "polars_utils"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -6164,7 +6356,7 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.14.5"; features = [ "rayon" "ahash" ]; } { @@ -6213,9 +6405,10 @@ rec { }; "portable-atomic" = rec { crateName = "portable-atomic"; - version = "1.5.1"; + version = "1.9.0"; edition = "2018"; - sha256 = "0fxg0i7n3wmffbfn95nwi062srdg40bwkj5143w1kk6pgw7apk1v"; + sha256 = "1cmd87qj90panwsi350djb8lsxdryqkkxmimjcz7a1nsysini76c"; + libName = "portable_atomic"; features = { "critical-section" = [ "dep:critical-section" ]; "default" = [ "fallback" ]; @@ -6225,12 +6418,20 @@ rec { }; "ppv-lite86" = rec { crateName = "ppv-lite86"; - version = "0.2.17"; - edition = "2018"; - sha256 = "1pp6g52aw970adv3x2310n7glqnji96z0a9wiamzw89ibf0ayh2v"; + version = "0.2.20"; + edition = "2021"; + sha256 = "017ax9ssdnpww7nrl1hvqh2lzncpv04nnsibmnw9nxjnaqlpp5bp"; + libName = "ppv_lite86"; authors = [ "The CryptoCorrosion Contributors" ]; + dependencies = [ + { + name = "zerocopy"; + packageId = "zerocopy"; + features = [ "simd" "derive" ]; + } + ]; features = { "default" = [ "std" ]; }; @@ -6238,10 +6439,10 @@ rec { }; "prettyplease" = rec { crateName = "prettyplease"; - version = "0.2.15"; + version = "0.2.22"; edition = "2021"; links = "prettyplease02"; - sha256 = "17az47j29q76gnyqvd5giryjz2fp7zw7vzcka1rb8ndbfgbmn05f"; + sha256 = "1fpsyn4x1scbp8ik8xw4pfh4jxfm5bv7clax5k1jcd5vzd0gk727"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -6253,15 +6454,20 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; usesDefaultFeatures = false; features = [ "full" ]; } ]; devDependencies = [ { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; usesDefaultFeatures = false; features = [ "parsing" ]; } @@ -6272,9 +6478,10 @@ rec { }; "proc-macro2" = rec { crateName = "proc-macro2"; - version = "1.0.69"; + version = "1.0.88"; edition = "2021"; - sha256 = "1nljgyllbm3yr3pa081bf83gxh6l4zvjqzaldw7v4mj9xfgihk0k"; + sha256 = "1ygjzcawivbziakc6sfc816alabvnp6whlm3g6kxamqyvg2pyfkw"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -6292,12 +6499,13 @@ rec { }; "prost" = rec { crateName = "prost"; - version = "0.12.2"; + version = "0.12.6"; edition = "2021"; - sha256 = "04k3c8d2k554gcbhii04canz6g1m6wbx00cdxdnzcal8qw7l2njs"; + sha256 = "0a8z87ir8yqjgl1kxbdj30a7pzsjs9ka85szll6i6xlb31f47cfy"; authors = [ "Dan Burkert <dan@danburkert.com>" - "Lucio Franco <luciofranco14@gmail.com" + "Lucio Franco <luciofranco14@gmail.com>" + "Casper Meijn <casper@meijn.net>" "Tokio Contributors <team@tokio.rs>" ]; dependencies = [ @@ -6313,19 +6521,22 @@ rec { } ]; features = { - "default" = [ "prost-derive" "std" ]; - "prost-derive" = [ "dep:prost-derive" ]; + "default" = [ "derive" "std" ]; + "derive" = [ "dep:prost-derive" ]; + "prost-derive" = [ "derive" ]; }; - resolvedDefaultFeatures = [ "default" "prost-derive" "std" ]; + resolvedDefaultFeatures = [ "default" "derive" "prost-derive" "std" ]; }; "prost-build" = rec { crateName = "prost-build"; - version = "0.12.2"; + version = "0.12.6"; edition = "2021"; - sha256 = "0f57mmf6cg7f4401x9s3fgdc1idnz7i1nxxjxyzi2jbhr22d18qz"; + sha256 = "1936q2grirm4rh5l26p88gbw8dijjcf4sfcn55y3p3nsjif5ll12"; + libName = "prost_build"; authors = [ "Dan Burkert <dan@danburkert.com>" "Lucio Franco <luciofranco14@gmail.com>" + "Casper Meijn <casper@meijn.net>" "Tokio Contributors <team@tokio.rs>" ]; dependencies = [ @@ -6336,7 +6547,7 @@ rec { } { name = "heck"; - packageId = "heck"; + packageId = "heck 0.5.0"; } { name = "itertools"; @@ -6385,7 +6596,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; optional = true; features = [ "full" ]; } @@ -6393,31 +6604,25 @@ rec { name = "tempfile"; packageId = "tempfile"; } - { - name = "which"; - packageId = "which"; - } ]; features = { - "cleanup-markdown" = [ "pulldown-cmark" "pulldown-cmark-to-cmark" ]; + "cleanup-markdown" = [ "dep:pulldown-cmark" "dep:pulldown-cmark-to-cmark" ]; "default" = [ "format" ]; - "format" = [ "prettyplease" "syn" ]; - "prettyplease" = [ "dep:prettyplease" ]; - "pulldown-cmark" = [ "dep:pulldown-cmark" ]; - "pulldown-cmark-to-cmark" = [ "dep:pulldown-cmark-to-cmark" ]; - "syn" = [ "dep:syn" ]; + "format" = [ "dep:prettyplease" "dep:syn" ]; }; - resolvedDefaultFeatures = [ "default" "format" "prettyplease" "syn" ]; + resolvedDefaultFeatures = [ "default" "format" ]; }; "prost-derive" = rec { crateName = "prost-derive"; - version = "0.12.2"; + version = "0.12.6"; edition = "2021"; - sha256 = "1g268fzmswaf6rx1sm8000h6a4rigd4b6zg55wysi95cvyjifmq6"; + sha256 = "1waaq9d2f114bvvpw957s7vsx268licnfawr20b51ydb43dxrgc1"; procMacro = true; + libName = "prost_derive"; authors = [ "Dan Burkert <dan@danburkert.com>" "Lucio Franco <luciofranco14@gmail.com>" + "Casper Meijn <casper@meijn.net>" "Tokio Contributors <team@tokio.rs>" ]; dependencies = [ @@ -6441,7 +6646,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "extra-traits" ]; } ]; @@ -6449,12 +6654,14 @@ rec { }; "prost-types" = rec { crateName = "prost-types"; - version = "0.12.2"; + version = "0.12.6"; edition = "2021"; - sha256 = "0lls5w7yh2jxi764kd9k44dwskrr85j2fs335wg2i47m6qig6fc3"; + sha256 = "1c6mvfhz91q8a8fwada9smaxgg9w4y8l1ypj9yc8wq1j185wk4ch"; + libName = "prost_types"; authors = [ "Dan Burkert <dan@danburkert.com>" - "Lucio Franco <luciofranco14@gmail.com" + "Lucio Franco <luciofranco14@gmail.com>" + "Casper Meijn <casper@meijn.net>" "Tokio Contributors <team@tokio.rs>" ]; dependencies = [ @@ -6472,9 +6679,9 @@ rec { }; "quote" = rec { crateName = "quote"; - version = "1.0.33"; + version = "1.0.37"; edition = "2018"; - sha256 = "1biw54hbbr12wdwjac55z1m2x2rylciw83qnjn564a3096jgqrsj"; + sha256 = "1brklraw2g34bxy9y4q1nbrccn7bv36ylihv12c9vlcii55x7fdm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -6630,9 +6837,9 @@ rec { }; "rayon" = rec { crateName = "rayon"; - version = "1.8.0"; + version = "1.10.0"; edition = "2021"; - sha256 = "1cfdnvchf7j4cpha5jkcrrsr61li9i9lp5ak7xdq6d3pvc1xn9ww"; + sha256 = "1ylgnzwgllajalr4v00y4kj22klq2jbwllm70aha232iah0sc65l"; authors = [ "Niko Matsakis <niko@alum.mit.edu>" "Josh Stone <cuviper@gmail.com>" @@ -6648,14 +6855,17 @@ rec { packageId = "rayon-core"; } ]; - + features = { + "web_spin_lock" = [ "dep:wasm_sync" "rayon-core/web_spin_lock" ]; + }; }; "rayon-core" = rec { crateName = "rayon-core"; - version = "1.12.0"; + version = "1.12.1"; edition = "2021"; links = "rayon-core"; - sha256 = "1vaq0q71yfvcwlmia0iqf6ixj2fibjcf2xjy92n1m1izv1mgpqsw"; + sha256 = "1qpwim68ai5h0j7axa8ai8z0payaawv3id0lrgkqmapx7lx8fr8l"; + libName = "rayon_core"; authors = [ "Niko Matsakis <niko@alum.mit.edu>" "Josh Stone <cuviper@gmail.com>" @@ -6670,7 +6880,9 @@ rec { packageId = "crossbeam-utils"; } ]; - + features = { + "web_spin_lock" = [ "dep:wasm_sync" ]; + }; }; "redox_syscall 0.2.16" = rec { crateName = "redox_syscall"; @@ -6689,11 +6901,11 @@ rec { ]; }; - "redox_syscall 0.4.1" = rec { + "redox_syscall 0.5.7" = rec { crateName = "redox_syscall"; - version = "0.4.1"; - edition = "2018"; - sha256 = "1aiifyz5dnybfvkk4cdab9p2kmphag1yad6iknc7aszlxxldf8j7"; + version = "0.5.7"; + edition = "2021"; + sha256 = "07vpgfr6a04k0x19zqr1xdlqm6fncik3zydbdi3f5g3l5k7zwvcv"; libName = "syscall"; authors = [ "Jeremy Soller <jackpot51@gmail.com>" @@ -6701,19 +6913,21 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 1.3.2"; + packageId = "bitflags 2.6.0"; } ]; features = { "core" = [ "dep:core" ]; + "default" = [ "userspace" ]; "rustc-dep-of-std" = [ "core" "bitflags/rustc-dep-of-std" ]; }; + resolvedDefaultFeatures = [ "default" "userspace" ]; }; "redox_users" = rec { crateName = "redox_users"; - version = "0.4.4"; + version = "0.4.6"; edition = "2021"; - sha256 = "1d1c7dhbb62sh8jrq9dhvqcyxqsh3wg8qknsi94iwq3r0wh7k151"; + sha256 = "0hya2cxx6hxmjfxzv9n8rjl5igpychav7zfi1f81pz6i4krry05s"; authors = [ "Jose Narvaez <goyox86@gmail.com>" "Wesley Hershberger <mggmugginsmc@gmail.com>" @@ -6728,7 +6942,7 @@ rec { name = "libredox"; packageId = "libredox"; usesDefaultFeatures = false; - features = [ "call" ]; + features = [ "std" "call" ]; } { name = "thiserror"; @@ -6744,9 +6958,9 @@ rec { }; "regex" = rec { crateName = "regex"; - version = "1.10.2"; + version = "1.11.0"; edition = "2021"; - sha256 = "0hxkd814n4irind8im5c9am221ri6bprx49nc7yxv02ykhd9a2rq"; + sha256 = "1n5imk7yxam409ik5nagsjpwqvbg3f0g0mznd5drf549x1g0w81q"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -6756,11 +6970,13 @@ rec { name = "aho-corasick"; packageId = "aho-corasick"; optional = true; + usesDefaultFeatures = false; } { name = "memchr"; packageId = "memchr"; optional = true; + usesDefaultFeatures = false; } { name = "regex-automata"; @@ -6800,9 +7016,10 @@ rec { }; "regex-automata" = rec { crateName = "regex-automata"; - version = "0.4.3"; + version = "0.4.8"; edition = "2021"; - sha256 = "0gs8q9yhd3kcg4pr00ag4viqxnh5l7jpyb9fsfr8hzh451w4r02z"; + sha256 = "18wd530ndrmygi6xnz3sp345qi0hy2kdbsa89182nwbl6br5i1rn"; + libName = "regex_automata"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -6860,9 +7077,10 @@ rec { }; "regex-syntax" = rec { crateName = "regex-syntax"; - version = "0.8.2"; + version = "0.8.5"; edition = "2021"; - sha256 = "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360"; + sha256 = "0p41p3hj9ww7blnbwbj9h7rwxzxg0c1hvrdycgys8rxyhqqw859b"; + libName = "regex_syntax"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -6953,17 +7171,22 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "dev_urandom_fallback" "once_cell" ]; }; - "ring 0.17.5" = rec { + "ring 0.17.8" = rec { crateName = "ring"; - version = "0.17.5"; + version = "0.17.8"; edition = "2021"; - links = "ring_core_0_17_5"; - sha256 = "02sd768l7594rm3jw048z7kkml7zcyw4ir62p6cxirap8wq0a0pv"; + links = "ring_core_0_17_8"; + sha256 = "03fwlb1ssrmfxdckvqv033pfmk01rhx9ynwi7r186dcfcp5s8zy1"; authors = [ "Brian Smith <brian@briansmith.org>" ]; dependencies = [ { + name = "cfg-if"; + packageId = "cfg-if"; + usesDefaultFeatures = false; + } + { name = "getrandom"; packageId = "getrandom"; } @@ -6971,13 +7194,13 @@ rec { name = "libc"; packageId = "libc"; usesDefaultFeatures = false; - target = { target, features }: (("android" == target."os" or null) || ("linux" == target."os" or null)); + target = { target, features }: ((("android" == target."os" or null) || ("linux" == target."os" or null)) && (("aarch64" == target."arch" or null) || ("arm" == target."arch" or null))); } { name = "spin"; packageId = "spin 0.9.8"; usesDefaultFeatures = false; - target = { target, features }: (("x86" == target."arch" or null) || ("x86_64" == target."arch" or null) || ((("aarch64" == target."arch" or null) || ("arm" == target."arch" or null)) && (("android" == target."os" or null) || ("fuchsia" == target."os" or null) || ("linux" == target."os" or null) || ("windows" == target."os" or null)))); + target = { target, features }: (("aarch64" == target."arch" or null) || ("arm" == target."arch" or null) || ("x86" == target."arch" or null) || ("x86_64" == target."arch" or null)); features = [ "once" ]; } { @@ -6986,7 +7209,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (("aarch64" == target."arch" or null) && ("windows" == target."os" or null)); features = [ "Win32_Foundation" "Win32_System_Threading" ]; } @@ -7340,9 +7563,10 @@ rec { }; "rustc-demangle" = rec { crateName = "rustc-demangle"; - version = "0.1.23"; + version = "0.1.24"; edition = "2015"; - sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + sha256 = "07zysaafgrkzy2rjgwqdj2a8qdpsm6zv6f5pgpk9x0lm40z9b6vi"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -7354,13 +7578,9 @@ rec { }; "rustc_version" = rec { crateName = "rustc_version"; - version = "0.4.0"; + version = "0.4.1"; edition = "2018"; - sha256 = "0rpk9rcdk405xhbmgclsh4pai0svn49x35aggl4nhbkd4a2zb85z"; - authors = [ - "Dirkjan Ochtman <dirkjan@ochtman.nl>" - "Marvin Löbel <loebel.marvin@gmail.com>" - ]; + sha256 = "14lvdsmr5si5qbqzrajgb6vfn69k0sfygrvfvr2mps26xwi3mjyg"; dependencies = [ { name = "semver"; @@ -7371,9 +7591,9 @@ rec { }; "rustix" = rec { crateName = "rustix"; - version = "0.38.24"; + version = "0.38.37"; edition = "2021"; - sha256 = "0d72f5q2csk5mff87jrzlfgpxv44c2f8s0m183f9r920qgb83ncs"; + sha256 = "04b8f99c2g36gyggf4aphw8742k2b1vls3364n2z493whj5pijwa"; authors = [ "Dan Gohman <dev@sunfishcode.online>" "Jakub Konka <kubkon@jakubkonka.com>" @@ -7381,7 +7601,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.1"; + packageId = "bitflags 2.6.0"; usesDefaultFeatures = false; } { @@ -7412,14 +7632,12 @@ rec { optional = true; usesDefaultFeatures = false; target = { target, features }: ((!(target."rustix_use_libc" or false)) && (!(target."miri" or false)) && ("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null)))); - features = [ "extra_traits" ]; } { name = "libc"; packageId = "libc"; usesDefaultFeatures = false; target = { target, features }: ((!(target."windows" or false)) && ((target."rustix_use_libc" or false) || (target."miri" or false) || (!(("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null))))))); - features = [ "extra_traits" ]; } { name = "linux-raw-sys"; @@ -7437,7 +7655,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_NetworkManagement_IpHelper" "Win32_System_Threading" ]; } @@ -7456,27 +7674,31 @@ rec { ]; features = { "all-apis" = [ "event" "fs" "io_uring" "mm" "mount" "net" "param" "pipe" "process" "procfs" "pty" "rand" "runtime" "shm" "stdio" "system" "termios" "thread" "time" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; "default" = [ "std" "use-libc-auxv" ]; "io_uring" = [ "event" "fs" "net" "linux-raw-sys/io_uring" ]; "itoa" = [ "dep:itoa" ]; "libc" = [ "dep:libc" ]; + "libc-extra-traits" = [ "libc?/extra_traits" ]; "libc_errno" = [ "dep:libc_errno" ]; "linux_latest" = [ "linux_4_11" ]; - "net" = [ "linux-raw-sys/net" "linux-raw-sys/netlink" "linux-raw-sys/if_ether" ]; + "net" = [ "linux-raw-sys/net" "linux-raw-sys/netlink" "linux-raw-sys/if_ether" "linux-raw-sys/xdp" ]; "once_cell" = [ "dep:once_cell" ]; "param" = [ "fs" ]; "process" = [ "linux-raw-sys/prctl" ]; "procfs" = [ "once_cell" "itoa" "fs" ]; "pty" = [ "itoa" "fs" ]; "runtime" = [ "linux-raw-sys/prctl" ]; - "rustc-dep-of-std" = [ "dep:core" "dep:alloc" "dep:compiler_builtins" "linux-raw-sys/rustc-dep-of-std" "bitflags/rustc-dep-of-std" "compiler_builtins?/rustc-dep-of-std" ]; + "rustc-dep-of-std" = [ "core" "rustc-std-workspace-alloc" "compiler_builtins" "linux-raw-sys/rustc-dep-of-std" "bitflags/rustc-dep-of-std" "compiler_builtins?/rustc-dep-of-std" ]; + "rustc-std-workspace-alloc" = [ "dep:rustc-std-workspace-alloc" ]; "shm" = [ "fs" ]; - "std" = [ "bitflags/std" "alloc" "libc?/std" "libc_errno?/std" ]; + "std" = [ "bitflags/std" "alloc" "libc?/std" "libc_errno?/std" "libc-extra-traits" ]; "system" = [ "linux-raw-sys/system" ]; "thread" = [ "linux-raw-sys/prctl" ]; - "use-libc" = [ "libc_errno" "libc" ]; + "use-libc" = [ "libc_errno" "libc" "libc-extra-traits" ]; }; - resolvedDefaultFeatures = [ "alloc" "default" "fs" "std" "use-libc-auxv" ]; + resolvedDefaultFeatures = [ "alloc" "default" "fs" "libc-extra-traits" "std" "use-libc-auxv" ]; }; "rustls" = rec { crateName = "rustls"; @@ -7523,6 +7745,7 @@ rec { version = "0.6.3"; edition = "2021"; sha256 = "007zind70rd5rfsrkdcfm8vn09j8sg02phg9334kark6rdscxam9"; + libName = "rustls_native_certs"; dependencies = [ { name = "openssl-probe"; @@ -7551,19 +7774,20 @@ rec { version = "1.0.4"; edition = "2018"; sha256 = "1324n5bcns0rnw6vywr5agff3rwfvzphi7rmbyzwnv6glkhclx0w"; + libName = "rustls_pemfile"; dependencies = [ { name = "base64"; - packageId = "base64 0.21.5"; + packageId = "base64 0.21.7"; } ]; }; "rustversion" = rec { crateName = "rustversion"; - version = "1.0.14"; + version = "1.0.18"; edition = "2018"; - sha256 = "1x1pz1yynk5xzzrazk2svmidj69jhz89dz5vrc28sixl20x1iz3z"; + sha256 = "0j2207vmgrcxwwwvknfn3lwv4i8djhjnxlvwdnz8bwijqqmrz08f"; procMacro = true; build = "build/build.rs"; authors = [ @@ -7573,9 +7797,9 @@ rec { }; "ryu" = rec { crateName = "ryu"; - version = "1.0.15"; + version = "1.0.18"; edition = "2018"; - sha256 = "0hfphpn1xnpzxwj8qg916ga1lyc33lc03lnf1gb3wwpglj6wrm0s"; + sha256 = "17xx2s8j1lln7iackzd9p0sv546vjq71i779gphjq923vjh5pjzk"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -7585,9 +7809,9 @@ rec { }; "schannel" = rec { crateName = "schannel"; - version = "0.1.22"; + version = "0.1.26"; edition = "2018"; - sha256 = "126zy5jb95fc5hvzyjwiq6lc81r08rdcn6affn00ispp9jzk6dqc"; + sha256 = "1hfip5mdwqcfnmrnkrq9d8zwy6bssmf6rfm2441nk83ghbjpn8h1"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Steffen Butzer <steffen.butzer@outlook.com>" @@ -7595,14 +7819,14 @@ rec { dependencies = [ { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; - features = [ "Win32_Foundation" "Win32_Security_Cryptography" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_System_Memory" ]; + packageId = "windows-sys 0.59.0"; + features = [ "Win32_Foundation" "Win32_Security_Cryptography" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_System_LibraryLoader" "Win32_System_Memory" "Win32_System_SystemInformation" ]; } ]; devDependencies = [ { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.59.0"; features = [ "Win32_System_SystemInformation" "Win32_System_Time" ]; } ]; @@ -7631,7 +7855,7 @@ rec { dependencies = [ { name = "ring"; - packageId = "ring 0.17.5"; + packageId = "ring 0.17.8"; } { name = "untrusted"; @@ -7642,9 +7866,10 @@ rec { }; "security-framework" = rec { crateName = "security-framework"; - version = "2.9.2"; + version = "2.11.1"; edition = "2021"; - sha256 = "1pplxk15s5yxvi2m1sz5xfmjibp96cscdcl432w9jzbk0frlzdh5"; + sha256 = "00ldclwx78dm61v7wkach9lcx76awlrv0fdgjdwch4dmy12j4yw9"; + libName = "security_framework"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -7652,7 +7877,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 1.3.2"; + packageId = "bitflags 2.6.0"; } { name = "core-foundation"; @@ -7680,17 +7905,18 @@ rec { "OSX_10_14" = [ "OSX_10_13" "security-framework-sys/OSX_10_14" ]; "OSX_10_15" = [ "OSX_10_14" "security-framework-sys/OSX_10_15" ]; "OSX_10_9" = [ "security-framework-sys/OSX_10_9" ]; - "default" = [ "OSX_10_9" ]; + "default" = [ "OSX_10_12" ]; "log" = [ "dep:log" ]; "serial-number-bigint" = [ "dep:num-bigint" ]; }; - resolvedDefaultFeatures = [ "OSX_10_9" "default" ]; + resolvedDefaultFeatures = [ "OSX_10_10" "OSX_10_11" "OSX_10_12" "OSX_10_9" "default" ]; }; "security-framework-sys" = rec { crateName = "security-framework-sys"; - version = "2.9.1"; + version = "2.12.0"; edition = "2021"; - sha256 = "0yhciwlsy9dh0ps1gw3197kvyqx1bvc4knrhiznhid6kax196cp9"; + sha256 = "1dml0lp9lrvvi01s011lyss5kzzsmakaamdwsxr0431jd4l2jjpa"; + libName = "security_framework_sys"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -7712,15 +7938,15 @@ rec { "OSX_10_13" = [ "OSX_10_12" ]; "OSX_10_14" = [ "OSX_10_13" ]; "OSX_10_15" = [ "OSX_10_14" ]; - "default" = [ "OSX_10_9" ]; + "default" = [ "OSX_10_12" ]; }; - resolvedDefaultFeatures = [ "OSX_10_9" ]; + resolvedDefaultFeatures = [ "OSX_10_10" "OSX_10_11" "OSX_10_12" "OSX_10_9" ]; }; "semver" = rec { crateName = "semver"; - version = "1.0.20"; + version = "1.0.23"; edition = "2018"; - sha256 = "140hmbfa743hbmah1zjf07s8apavhvn04204qjigjiz5w6iscvw3"; + sha256 = "12wqpxfflclbq4dv8sa6gchdh92ahhwn4ci1ls22wlby3h57wsb1"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -7736,6 +7962,7 @@ rec { edition = "2018"; sha256 = "1d50kbaslrrd0374ivx15jg57f03y5xzil1wd2ajlvajzlkbzw53"; procMacro = true; + libName = "seq_macro"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -7743,9 +7970,9 @@ rec { }; "serde" = rec { crateName = "serde"; - version = "1.0.192"; + version = "1.0.210"; edition = "2018"; - sha256 = "00ghhaabyrnr2cn504lckyqzh3fwr8k7pxnhhardr1djhj2a18mw"; + sha256 = "0flc0z8wgax1k4j5bf2zyq48bgzyv425jkd5w0i6wbh7f8j5kqy8"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -7777,9 +8004,9 @@ rec { }; "serde_derive" = rec { crateName = "serde_derive"; - version = "1.0.192"; + version = "1.0.210"; edition = "2015"; - sha256 = "1hgvm47ffd748sx22z1da7mgcfjmpr60gqzkff0a9yn9przj1iyn"; + sha256 = "07yzy4wafk79ps0hmbqmsqh5xjna4pm4q57wc847bb8gl3nh4f94"; procMacro = true; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" @@ -7789,14 +8016,20 @@ rec { { name = "proc-macro2"; packageId = "proc-macro2"; + usesDefaultFeatures = false; + features = [ "proc-macro" ]; } { name = "quote"; packageId = "quote"; + usesDefaultFeatures = false; + features = [ "proc-macro" ]; } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "clone-impls" "derive" "parsing" "printing" "proc-macro" ]; } ]; features = { }; @@ -7804,9 +8037,9 @@ rec { }; "serde_json" = rec { crateName = "serde_json"; - version = "1.0.108"; + version = "1.0.128"; edition = "2021"; - sha256 = "0ssj59s7lpzqh1m50kfzlnrip0p0jg9lmhn4098i33a0mhz7w71x"; + sha256 = "1n43nia50ybpcfmh3gcw4lcc627qsg9nyakzwgkk9pm10xklbxbg"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -7817,6 +8050,11 @@ rec { packageId = "itoa"; } { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + { name = "ryu"; packageId = "ryu"; } @@ -7838,7 +8076,7 @@ rec { "default" = [ "std" ]; "indexmap" = [ "dep:indexmap" ]; "preserve_order" = [ "indexmap" "std" ]; - "std" = [ "serde/std" ]; + "std" = [ "memchr/std" "serde/std" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; @@ -7937,9 +8175,10 @@ rec { }; "sha2-asm" = rec { crateName = "sha2-asm"; - version = "0.6.3"; + version = "0.6.4"; edition = "2018"; - sha256 = "0kp480744vkwg3fqx98379nsdw1lzzzimd88v0qgpqqic03afyzj"; + sha256 = "1ay1vai08d802avl41r0s6r1nrcnzv7jnj5xna34d03mc56j2idq"; + libName = "sha2_asm"; authors = [ "RustCrypto Developers" ]; @@ -7953,12 +8192,16 @@ rec { }; "shlex" = rec { crateName = "shlex"; - version = "1.2.0"; + version = "1.3.0"; edition = "2015"; - sha256 = "1033pj9dyb76nm5yv597nnvj3zpvr2aw9rm5wy0gah3dk99f1km7"; + sha256 = "0r1y6bv26c1scpxvhg2cabimrmwgbp4p3wy6syj9n0c4s3q2znhg"; authors = [ "comex <comexk@gmail.com>" "Fenhl <fenhl@fenhl.net>" + "Adrian Taylor <adetaylor@chromium.org>" + "Alex Touchet <alextouchet@outlook.com>" + "Daniel Parks <dp+git@oxidized.org>" + "Garrett Berg <googberg@gmail.com>" ]; features = { "default" = [ "std" ]; @@ -7967,9 +8210,10 @@ rec { }; "signal-hook-registry" = rec { crateName = "signal-hook-registry"; - version = "1.4.1"; + version = "1.4.2"; edition = "2015"; - sha256 = "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq"; + sha256 = "1cb5akgq8ajnd5spyn587srvs4n26ryq0p78nswffwhv46sf1sd9"; + libName = "signal_hook_registry"; authors = [ "Michal 'vorner' Vaner <vorner@vorner.cz>" "Masaki Hara <ackie.h.gmai@gmail.com>" @@ -8008,9 +8252,9 @@ rec { }; "simdutf8" = rec { crateName = "simdutf8"; - version = "0.1.4"; + version = "0.1.5"; edition = "2018"; - sha256 = "0fi6zvnldaw7g726wnm9vvpv4s89s5jsk7fgp3rg2l99amw64zzj"; + sha256 = "0vmpf7xaa0dnaikib5jlx6y4dxd3hxqz6l830qb079g7wcsgxag3"; authors = [ "Hans Kratz <hans@appfour.com>" ]; @@ -8104,9 +8348,9 @@ rec { }; "smallvec" = rec { crateName = "smallvec"; - version = "1.11.2"; + version = "1.13.2"; edition = "2018"; - sha256 = "0w79x38f7c0np7hqfmzrif9zmn0avjvvm31b166zdk9d1aad1k2d"; + sha256 = "0rsw5samawl3wsw6glrsb127rx6sh89a8wyikicw6dkdcjd1lpiw"; authors = [ "The Servo Project Developers" ]; @@ -8152,44 +8396,19 @@ rec { }; "snap" = rec { crateName = "snap"; - version = "1.1.0"; + version = "1.1.1"; edition = "2018"; - sha256 = "0c882cs4wbyi34nw8njpxa729gyi6sj71h8rj4ykbdvyxyv0m7sy"; + sha256 = "0fxw80m831l76a5zxcwmz2aq7mcwc1pp345pnljl4cv1kbxnfsqv"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; }; - "socket2 0.4.10" = rec { - crateName = "socket2"; - version = "0.4.10"; - edition = "2018"; - sha256 = "03ack54dxhgfifzsj14k7qa3r5c9wqy3v6mqhlim99cc03y1cycz"; - authors = [ - "Alex Crichton <alex@alexcrichton.com>" - "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" - ]; - dependencies = [ - { - name = "libc"; - packageId = "libc"; - target = { target, features }: (target."unix" or false); - } - { - name = "winapi"; - packageId = "winapi"; - target = { target, features }: (target."windows" or false); - features = [ "handleapi" "ws2ipdef" "ws2tcpip" ]; - } - ]; - features = { }; - resolvedDefaultFeatures = [ "all" ]; - }; - "socket2 0.5.5" = rec { + "socket2" = rec { crateName = "socket2"; - version = "0.5.5"; + version = "0.5.7"; edition = "2021"; - sha256 = "1sgq315f1njky114ip7wcy83qlphv9qclprfjwvxcpfblmcsqpvv"; + sha256 = "070r941wbq76xpy039an4pyiy3rfj7mp7pvibf1rcri9njq5wc6f"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -8202,7 +8421,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_System_IO" "Win32_System_Threading" "Win32_System_WindowsProgramming" ]; } @@ -8248,9 +8467,9 @@ rec { }; "spki" = rec { crateName = "spki"; - version = "0.7.2"; + version = "0.7.3"; edition = "2021"; - sha256 = "0jhq00sv4w3psdi6li3vjjmspc6z2d9b1wc1srbljircy1p9j7lx"; + sha256 = "17fj8k5fmx4w9mp27l970clrh5qa7r5sjdvbsln987xhb34dc7nr"; authors = [ "RustCrypto Developers" ]; @@ -8318,6 +8537,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "1wscqj3s30qknda778wf7z99mknk65p0h9hhs658l4pvkfqw6v5z"; + libName = "streaming_decompression"; dependencies = [ { name = "fallible-streaming-iterator"; @@ -8331,6 +8551,7 @@ rec { version = "0.1.9"; edition = "2021"; sha256 = "0845zdv8qb7zwqzglpqc0830i43xh3fb6vqms155wz85qfvk28ib"; + libName = "streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -8350,11 +8571,12 @@ rec { }; "strsim" = rec { crateName = "strsim"; - version = "0.10.0"; + version = "0.11.1"; edition = "2015"; - sha256 = "08s69r4rcrahwnickvi0kq49z524ci50capybln83mg6b473qivk"; + sha256 = "0kzvqlw8hxqb7y598w1s0hxlnmi84sg5vsipp3yg5na5d1rvba3x"; authors = [ "Danny Guo <danny@dannyguo.com>" + "maxbachmann <oss@maxbachmann.de>" ]; }; @@ -8370,7 +8592,7 @@ rec { dependencies = [ { name = "heck"; - packageId = "heck"; + packageId = "heck 0.4.1"; } { name = "proc-macro2"; @@ -8386,7 +8608,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "parsing" "extra-traits" ]; } ]; @@ -8439,11 +8661,11 @@ rec { }; resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit-mut" ]; }; - "syn 2.0.39" = rec { + "syn 2.0.79" = rec { crateName = "syn"; - version = "2.0.39"; + version = "2.0.79"; edition = "2021"; - sha256 = "0ymyhxnk1yi4pzf72qk3lrdm9lgjwcrcwci0hhz5vx7wya88prr3"; + sha256 = "147mk4sgigmvsb9l8qzj199ygf0fgb0bphwdsghn8205pz82q4w9"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -8466,18 +8688,17 @@ rec { ]; features = { "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; - "printing" = [ "quote" ]; - "proc-macro" = [ "proc-macro2/proc-macro" "quote/proc-macro" ]; - "quote" = [ "dep:quote" ]; + "printing" = [ "dep:quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; "test" = [ "syn-test-suite/all-features" ]; }; - resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit" "visit-mut" ]; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; }; "sysinfo" = rec { crateName = "sysinfo"; - version = "0.29.10"; + version = "0.29.11"; edition = "2018"; - sha256 = "19cbs7d7fcq8cpfpr94n68h04d02lab8xg76j6la7b90shad260a"; + sha256 = "0rp6911qqjppvvbh72j27znscrawfvplqlyrj9n0y1n24g27ywnd"; authors = [ "Guillaume Gomez <guillaume1.gomez@gmail.com>" ]; @@ -8524,9 +8745,10 @@ rec { }; "target-features" = rec { crateName = "target-features"; - version = "0.1.5"; + version = "0.1.6"; edition = "2021"; - sha256 = "1gb974chm9aj8ifkyibylxkyb5an4bf5y8dxb18pqmck698gmdfg"; + sha256 = "1m8y0ksw30gnkidjsjvnmhlpj165mgyj8ylk0lbs0qy4qprvkfy1"; + libName = "target_features"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -8534,9 +8756,9 @@ rec { }; "tempfile" = rec { crateName = "tempfile"; - version = "3.8.1"; - edition = "2018"; - sha256 = "1r88v07zdafzf46y63vs39rmzwl4vqd4g2c5qarz9mqa8nnavwby"; + version = "3.13.0"; + edition = "2021"; + sha256 = "0nyagmbd4v5g6nzfydiihcn6l9j1w9bxgzyca5lyzgnhcbyckwph"; authors = [ "Steven Allen <steven@stebalien.com>" "The Rust Project Developers" @@ -8553,9 +8775,10 @@ rec { packageId = "fastrand"; } { - name = "redox_syscall"; - packageId = "redox_syscall 0.4.1"; - target = { target, features }: ("redox" == target."os" or null); + name = "once_cell"; + packageId = "once_cell"; + usesDefaultFeatures = false; + features = [ "std" ]; } { name = "rustix"; @@ -8565,7 +8788,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.59.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Storage_FileSystem" "Win32_Foundation" ]; } @@ -8574,9 +8797,9 @@ rec { }; "thiserror" = rec { crateName = "thiserror"; - version = "1.0.50"; + version = "1.0.64"; edition = "2021"; - sha256 = "1ll2sfbrxks8jja161zh1pgm3yssr7aawdmaa2xmcwcsbh7j39zr"; + sha256 = "114s8lmssxl0c2480s671am88vzlasbaikxbvfv8pyqrq6mzh2nm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -8590,10 +8813,11 @@ rec { }; "thiserror-impl" = rec { crateName = "thiserror-impl"; - version = "1.0.50"; + version = "1.0.64"; edition = "2021"; - sha256 = "1f0lmam4765sfnwr4b1n00y14vxh10g0311mkk0adr80pi02wsr6"; + sha256 = "1hvzmjx9iamln854l74qyhs0jl2pg3hhqzpqm9p8gszmf9v4x408"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -8608,16 +8832,16 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; } ]; }; "tokio" = rec { crateName = "tokio"; - version = "1.34.0"; + version = "1.40.0"; edition = "2021"; - sha256 = "1fgmssdga42a2hn9spm9dh1v9ajpcbs4r3svmzvk9s0iciv19h6h"; + sha256 = "166rllhfkyqp0fs7sxn6crv74iizi4wzd3cvxkcpmlk52qip1c72"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -8645,13 +8869,8 @@ rec { usesDefaultFeatures = false; } { - name = "num_cpus"; - packageId = "num_cpus"; - optional = true; - } - { name = "parking_lot"; - packageId = "parking_lot 0.12.1"; + packageId = "parking_lot 0.12.3"; optional = true; } { @@ -8666,7 +8885,7 @@ rec { } { name = "socket2"; - packageId = "socket2 0.5.5"; + packageId = "socket2"; optional = true; target = { target, features }: (!(builtins.elem "wasm" target."family")); features = [ "all" ]; @@ -8678,7 +8897,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; optional = true; target = { target, features }: (target."windows" or false); } @@ -8691,12 +8910,12 @@ rec { } { name = "socket2"; - packageId = "socket2 0.5.5"; + packageId = "socket2"; target = { target, features }: (!(builtins.elem "wasm" target."family")); } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Security_Authorization" ]; } @@ -8709,10 +8928,9 @@ rec { "macros" = [ "tokio-macros" ]; "mio" = [ "dep:mio" ]; "net" = [ "libc" "mio/os-poll" "mio/os-ext" "mio/net" "socket2" "windows-sys/Win32_Foundation" "windows-sys/Win32_Security" "windows-sys/Win32_Storage_FileSystem" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_System_SystemServices" ]; - "num_cpus" = [ "dep:num_cpus" ]; "parking_lot" = [ "dep:parking_lot" ]; "process" = [ "bytes" "libc" "mio/os-poll" "mio/os-ext" "mio/net" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Threading" "windows-sys/Win32_System_WindowsProgramming" ]; - "rt-multi-thread" = [ "num_cpus" "rt" ]; + "rt-multi-thread" = [ "rt" ]; "signal" = [ "libc" "mio/os-poll" "mio/net" "mio/os-ext" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Console" ]; "signal-hook-registry" = [ "dep:signal-hook-registry" ]; "socket2" = [ "dep:socket2" ]; @@ -8721,14 +8939,15 @@ rec { "tracing" = [ "dep:tracing" ]; "windows-sys" = [ "dep:windows-sys" ]; }; - resolvedDefaultFeatures = [ "bytes" "default" "fs" "full" "io-std" "io-util" "libc" "macros" "mio" "net" "num_cpus" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "time" "tokio-macros" "windows-sys" ]; + resolvedDefaultFeatures = [ "bytes" "default" "fs" "full" "io-std" "io-util" "libc" "macros" "mio" "net" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "time" "tokio-macros" "windows-sys" ]; }; "tokio-macros" = rec { crateName = "tokio-macros"; - version = "2.2.0"; + version = "2.4.0"; edition = "2021"; - sha256 = "0fwjy4vdx1h9pi4g2nml72wi0fr27b5m954p13ji9anyy8l1x2jv"; + sha256 = "0lnpg14h1v3fh2jvnc8cz7cjf0m7z1xgkwfpcyy632g829imjgb9"; procMacro = true; + libName = "tokio_macros"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -8743,7 +8962,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -8754,6 +8973,7 @@ rec { version = "0.23.4"; edition = "2018"; sha256 = "0nfsmmi8l1lgpbfy6079d5i13984djzcxrdr9jc06ghi0cwyhgn4"; + libName = "tokio_rustls"; authors = [ "quininer kel <quininer@live.com>" ]; @@ -8789,9 +9009,10 @@ rec { }; "tokio-util" = rec { crateName = "tokio-util"; - version = "0.7.10"; + version = "0.7.12"; edition = "2021"; - sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + sha256 = "0spc0g4irbnf2flgag22gfii87avqzibwfm0si0d1g0k9ijw7rv1"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -8817,13 +9038,6 @@ rec { packageId = "tokio"; features = [ "sync" ]; } - { - name = "tracing"; - packageId = "tracing"; - optional = true; - usesDefaultFeatures = false; - features = [ "std" ]; - } ]; devDependencies = [ { @@ -8834,7 +9048,6 @@ rec { ]; features = { "__docs_rs" = [ "futures-util" ]; - "codec" = [ "tracing" ]; "compat" = [ "futures-io" ]; "full" = [ "codec" "compat" "io-util" "time" "net" "rt" ]; "futures-io" = [ "dep:futures-io" ]; @@ -8847,13 +9060,14 @@ rec { "time" = [ "tokio/time" "slab" ]; "tracing" = [ "dep:tracing" ]; }; - resolvedDefaultFeatures = [ "codec" "default" "io" "io-util" "tracing" ]; + resolvedDefaultFeatures = [ "codec" "default" "io" "io-util" ]; }; "tower-service" = rec { crateName = "tower-service"; - version = "0.3.2"; + version = "0.3.3"; edition = "2018"; - sha256 = "0lmfzmmvid2yp2l36mbavhmqgsvzqf7r2wiwz73ml4xmwaf1rg5n"; + sha256 = "1hzfkvkci33ra94xjx64vv3pp0sq346w06fpkcdwjcid7zhvdycd"; + libName = "tower_service"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -8874,6 +9088,11 @@ rec { packageId = "pin-project-lite"; } { + name = "tracing-attributes"; + packageId = "tracing-attributes"; + optional = true; + } + { name = "tracing-core"; packageId = "tracing-core"; usesDefaultFeatures = false; @@ -8888,13 +9107,44 @@ rec { "tracing-attributes" = [ "dep:tracing-attributes" ]; "valuable" = [ "tracing-core/valuable" ]; }; - resolvedDefaultFeatures = [ "std" ]; + resolvedDefaultFeatures = [ "attributes" "default" "std" "tracing-attributes" ]; + }; + "tracing-attributes" = rec { + crateName = "tracing-attributes"; + version = "0.1.27"; + edition = "2018"; + sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; + procMacro = true; + libName = "tracing_attributes"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + "Eliza Weisman <eliza@buoyant.io>" + "David Barsky <dbarsky@amazon.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "visit-mut" "clone-impls" "extra-traits" "proc-macro" ]; + } + ]; + features = { }; }; "tracing-core" = rec { crateName = "tracing-core"; version = "0.1.32"; edition = "2018"; sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -8915,9 +9165,10 @@ rec { }; "try-lock" = rec { crateName = "try-lock"; - version = "0.2.4"; + version = "0.2.5"; edition = "2015"; - sha256 = "1vc15paa4zi06ixsxihwbvfn24d708nsyg1ncgqwcrn42byyqa1m"; + sha256 = "0jqijrrvm1pyq34zn1jmy2vihd4jcrjlvsh4alkjahhssjnsn8g4"; + libName = "try_lock"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -8940,9 +9191,10 @@ rec { }; "unicode-ident" = rec { crateName = "unicode-ident"; - version = "1.0.12"; + version = "1.0.13"; edition = "2018"; - sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + sha256 = "1zm1xylzsdfvm2a5ib9li3g5pp7qnkv4amhspydvgbmd9k6mc6z9"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -8950,9 +9202,10 @@ rec { }; "unicode-width" = rec { crateName = "unicode-width"; - version = "0.1.11"; - edition = "2015"; - sha256 = "11ds4ydhg8g7l06rlmh712q41qsrd0j0h00n1jm74kww3kqk65z5"; + version = "0.1.14"; + edition = "2021"; + sha256 = "1bzn2zv0gp8xxbxbhifw778a7fc93pa6a1kj24jgg9msj07f7mkx"; + libName = "unicode_width"; authors = [ "kwantam <kwantam@gmail.com>" "Manish Goregaokar <manishsmail@gmail.com>" @@ -8960,10 +9213,11 @@ rec { features = { "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; + "default" = [ "cjk" ]; "rustc-dep-of-std" = [ "std" "core" "compiler_builtins" ]; "std" = [ "dep:std" ]; }; - resolvedDefaultFeatures = [ "default" ]; + resolvedDefaultFeatures = [ "cjk" "default" ]; }; "untrusted 0.7.1" = rec { crateName = "untrusted"; @@ -8988,9 +9242,9 @@ rec { }; "utf8parse" = rec { crateName = "utf8parse"; - version = "0.2.1"; + version = "0.2.2"; edition = "2018"; - sha256 = "02ip1a0az0qmc2786vxk2nqwsgcwf17d3a38fkf0q7hrmwh9c6vi"; + sha256 = "088807qwjq46azicqwbhlmzwrbkz7l4hpw43sdkdyyk524vdxaq6"; authors = [ "Joe Wilm <joe@jwilm.com>" "Christian Duerr <contact@christianduerr.com>" @@ -9000,9 +9254,9 @@ rec { }; "version_check" = rec { crateName = "version_check"; - version = "0.9.4"; + version = "0.9.5"; edition = "2015"; - sha256 = "0gs8grwdlgh0xq660d7wr80x14vxbizmd8dbp29p2pdncx8lp1s9"; + sha256 = "0nhhi4i5x89gm911azqbn7avs9mdacw2i3vcz3cnmz3mv4rqz4hb"; authors = [ "Sergio Benitez <sb@sergio.bz>" ]; @@ -9043,9 +9297,10 @@ rec { }; "wasm-bindgen" = rec { crateName = "wasm-bindgen"; - version = "0.2.88"; - edition = "2018"; - sha256 = "1khgsh4z9bga35mjhg41dl7523i69ffc5m8ckhqaw6ssyabc5bkx"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0bpbvmxhil380gpv53smaypl8wc7sy7rq8apxfw349pn78v1x38j"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -9055,6 +9310,10 @@ rec { packageId = "cfg-if"; } { + name = "once_cell"; + packageId = "once_cell"; + } + { name = "wasm-bindgen-macro"; packageId = "wasm-bindgen-macro"; } @@ -9062,7 +9321,6 @@ rec { features = { "default" = [ "spans" "std" ]; "enable-interning" = [ "std" ]; - "gg-alloc" = [ "wasm-bindgen-test/gg-alloc" ]; "serde" = [ "dep:serde" ]; "serde-serialize" = [ "serde" "serde_json" "std" ]; "serde_json" = [ "dep:serde_json" ]; @@ -9074,9 +9332,10 @@ rec { }; "wasm-bindgen-backend" = rec { crateName = "wasm-bindgen-backend"; - version = "0.2.88"; - edition = "2018"; - sha256 = "05zj8yl243rvs87rhicq2l1d6443lnm6k90khf744khf9ikg95z3"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0n53wgy78bgzgjwk0z69zbspzhv8p2a4zh69s4fzvpqdrb9x8vfb"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -9103,7 +9362,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" ]; } { @@ -9118,10 +9377,11 @@ rec { }; "wasm-bindgen-macro" = rec { crateName = "wasm-bindgen-macro"; - version = "0.2.88"; - edition = "2018"; - sha256 = "1chn3wgw9awmvs0fpmazbqyc5rwfgy3pj7lzwczmzb887dxh2qar"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0mic8b2vab1a91m6x3hjxkwz23094bq1cwhnszarsnlggyz894z7"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -9143,9 +9403,10 @@ rec { }; "wasm-bindgen-macro-support" = rec { crateName = "wasm-bindgen-macro-support"; - version = "0.2.88"; - edition = "2018"; - sha256 = "01rrzg3y1apqygsjz1jg0n7p831nm4kdyxmxyl85x7v6mf6kndf5"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0s7g6glb85lyx2pj83shbmg4d50mvqhb2c2qk2j28yigaxbspii6"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -9160,8 +9421,8 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; - features = [ "visit" "full" ]; + packageId = "syn 2.0.79"; + features = [ "visit" "visit-mut" "full" ]; } { name = "wasm-bindgen-backend"; @@ -9180,10 +9441,11 @@ rec { }; "wasm-bindgen-shared" = rec { crateName = "wasm-bindgen-shared"; - version = "0.2.88"; - edition = "2018"; + version = "0.2.95"; + edition = "2021"; links = "wasm_bindgen"; - sha256 = "02vmw2rzsla1qm0zgfng4kqz52xn8k54v8ads4g1macv09fnq10d"; + sha256 = "1386q7mvv5ky003hcc6yyxpid3y1m7fy0l920i3z3ab60vqhkz35"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -9191,9 +9453,10 @@ rec { }; "web-sys" = rec { crateName = "web-sys"; - version = "0.3.65"; - edition = "2018"; - sha256 = "11ba406ca9qssc21c37v49sn2y2gsdn6c3nva4hjf8v3yv2rkd2x"; + version = "0.3.72"; + edition = "2021"; + sha256 = "04k19hilj9r8sx6q20fz853149gfpmf83yk2zvq0s14c2288nj7n"; + libName = "web_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -9304,8 +9567,6 @@ rec { "FontFaceSet" = [ "EventTarget" ]; "FontFaceSetLoadEvent" = [ "Event" ]; "GainNode" = [ "AudioNode" "EventTarget" ]; - "GamepadAxisMoveEvent" = [ "Event" "GamepadEvent" ]; - "GamepadButtonEvent" = [ "Event" "GamepadEvent" ]; "GamepadEvent" = [ "Event" ]; "GpuDevice" = [ "EventTarget" ]; "GpuInternalError" = [ "GpuError" ]; @@ -9405,7 +9666,9 @@ rec { "IirFilterNode" = [ "AudioNode" "EventTarget" ]; "ImageCaptureErrorEvent" = [ "Event" ]; "ImageTrack" = [ "EventTarget" ]; + "InputDeviceInfo" = [ "MediaDeviceInfo" ]; "InputEvent" = [ "Event" "UiEvent" ]; + "KeyFrameRequestEvent" = [ "Event" ]; "KeyboardEvent" = [ "Event" "UiEvent" ]; "KeyframeEffect" = [ "AnimationEffect" ]; "LocalMediaStream" = [ "EventTarget" "MediaStream" ]; @@ -9476,10 +9739,15 @@ rec { "RtcDataChannel" = [ "EventTarget" ]; "RtcDataChannelEvent" = [ "Event" ]; "RtcPeerConnection" = [ "EventTarget" ]; + "RtcPeerConnectionIceErrorEvent" = [ "Event" ]; "RtcPeerConnectionIceEvent" = [ "Event" ]; + "RtcRtpScriptTransformer" = [ "EventTarget" ]; "RtcTrackEvent" = [ "Event" ]; + "RtcTransformEvent" = [ "Event" ]; "RtcdtmfSender" = [ "EventTarget" ]; "RtcdtmfToneChangeEvent" = [ "Event" ]; + "SFrameTransform" = [ "EventTarget" ]; + "SFrameTransformErrorEvent" = [ "Event" ]; "Screen" = [ "EventTarget" ]; "ScreenOrientation" = [ "EventTarget" ]; "ScriptProcessorNode" = [ "AudioNode" "EventTarget" ]; @@ -9609,6 +9877,7 @@ rec { "TextTrackCue" = [ "EventTarget" ]; "TextTrackList" = [ "EventTarget" ]; "TimeEvent" = [ "Event" ]; + "ToggleEvent" = [ "Event" ]; "TouchEvent" = [ "Event" "UiEvent" ]; "TrackEvent" = [ "Event" ]; "TransitionEvent" = [ "Event" ]; @@ -9620,6 +9889,7 @@ rec { "ValueEvent" = [ "Event" ]; "VideoStreamTrack" = [ "EventTarget" "MediaStreamTrack" ]; "VideoTrackList" = [ "EventTarget" ]; + "VisualViewport" = [ "EventTarget" ]; "VrDisplay" = [ "EventTarget" ]; "VttCue" = [ "EventTarget" "TextTrackCue" ]; "WakeLockSentinel" = [ "EventTarget" ]; @@ -9669,7 +9939,7 @@ rec { dependencies = [ { name = "ring"; - packageId = "ring 0.17.5"; + packageId = "ring 0.17.8"; usesDefaultFeatures = false; } { @@ -9683,40 +9953,6 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "std" ]; }; - "which" = rec { - crateName = "which"; - version = "4.4.2"; - edition = "2021"; - sha256 = "1ixzmx3svsv5hbdvd8vdhd3qwvf6ns8jdpif1wmwsy10k90j9fl7"; - authors = [ - "Harry Fei <tiziyuanfang@gmail.com>" - ]; - dependencies = [ - { - name = "either"; - packageId = "either"; - } - { - name = "home"; - packageId = "home"; - target = { target, features }: ((target."windows" or false) || (target."unix" or false) || ("redox" == target."os" or null)); - } - { - name = "once_cell"; - packageId = "once_cell"; - target = { target, features }: (target."windows" or false); - } - { - name = "rustix"; - packageId = "rustix"; - usesDefaultFeatures = false; - features = [ "fs" "std" ]; - } - ]; - features = { - "regex" = [ "dep:regex" ]; - }; - }; "winapi" = rec { crateName = "winapi"; version = "0.3.9"; @@ -9729,24 +9965,25 @@ rec { { name = "winapi-i686-pc-windows-gnu"; packageId = "winapi-i686-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "i686-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnu"); } { name = "winapi-x86_64-pc-windows-gnu"; packageId = "winapi-x86_64-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnu"); } ]; features = { "debug" = [ "impl-debug" ]; }; - resolvedDefaultFeatures = [ "cfg" "combaseapi" "errhandlingapi" "evntrace" "fileapi" "handleapi" "heapapi" "ifdef" "in6addr" "inaddr" "ioapiset" "iphlpapi" "knownfolders" "lmaccess" "lmapibuf" "lmcons" "memoryapi" "minwinbase" "minwindef" "netioapi" "ntlsa" "ntsecapi" "ntstatus" "objbase" "objidl" "oleauto" "pdh" "powerbase" "processthreadsapi" "psapi" "rpcdce" "sddl" "securitybaseapi" "shellapi" "shlobj" "std" "synchapi" "sysinfoapi" "wbemcli" "winbase" "windef" "winerror" "winioctl" "winnt" "winsock2" "ws2ipdef" "ws2tcpip" "wtypesbase" ]; + resolvedDefaultFeatures = [ "cfg" "combaseapi" "errhandlingapi" "evntrace" "fileapi" "handleapi" "heapapi" "ifdef" "in6addr" "inaddr" "ioapiset" "iphlpapi" "knownfolders" "lmaccess" "lmapibuf" "lmcons" "memoryapi" "minwinbase" "minwindef" "netioapi" "ntlsa" "ntsecapi" "ntstatus" "objbase" "objidl" "oleauto" "pdh" "powerbase" "processthreadsapi" "psapi" "rpcdce" "sddl" "securitybaseapi" "shellapi" "shlobj" "std" "synchapi" "sysinfoapi" "wbemcli" "winbase" "windef" "winerror" "winioctl" "winnt" "winsock2" "wtypesbase" ]; }; "winapi-i686-pc-windows-gnu" = rec { crateName = "winapi-i686-pc-windows-gnu"; version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -9757,6 +9994,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -9764,346 +10002,66 @@ rec { }; "windows-core" = rec { crateName = "windows-core"; - version = "0.51.1"; + version = "0.52.0"; edition = "2021"; - sha256 = "0r1f57hsshsghjyc7ypp2s0i78f7b1vr93w68sdb8baxyf2czy7i"; + sha256 = "1nc3qv7sy24x0nlnb32f7alzpd6f72l4p24vl65vydbyil669ark"; + libName = "windows_core"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets 0.48.5"; + packageId = "windows-targets"; } ]; features = { }; resolvedDefaultFeatures = [ "default" ]; }; - "windows-sys 0.45.0" = rec { - crateName = "windows-sys"; - version = "0.45.0"; - edition = "2018"; - sha256 = "1l36bcqm4g89pknfp8r9rl1w4bn017q6a8qlx8viv0xjxzjkna3m"; - authors = [ - "Microsoft" - ]; - dependencies = [ - { - name = "windows-targets"; - packageId = "windows-targets 0.42.2"; - target = { target, features }: (!(target."windows_raw_dylib" or false)); - } - ]; - features = { - "Win32_Data" = [ "Win32" ]; - "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; - "Win32_Data_RightsManagement" = [ "Win32_Data" ]; - "Win32_Data_Xml" = [ "Win32_Data" ]; - "Win32_Data_Xml_MsXml" = [ "Win32_Data_Xml" ]; - "Win32_Data_Xml_XmlLite" = [ "Win32_Data_Xml" ]; - "Win32_Devices" = [ "Win32" ]; - "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; - "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; - "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; - "Win32_Devices_Communication" = [ "Win32_Devices" ]; - "Win32_Devices_DeviceAccess" = [ "Win32_Devices" ]; - "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; - "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; - "Win32_Devices_Display" = [ "Win32_Devices" ]; - "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; - "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; - "Win32_Devices_Fax" = [ "Win32_Devices" ]; - "Win32_Devices_FunctionDiscovery" = [ "Win32_Devices" ]; - "Win32_Devices_Geolocation" = [ "Win32_Devices" ]; - "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; - "Win32_Devices_ImageAcquisition" = [ "Win32_Devices" ]; - "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; - "Win32_Devices_Properties" = [ "Win32_Devices" ]; - "Win32_Devices_Pwm" = [ "Win32_Devices" ]; - "Win32_Devices_Sensors" = [ "Win32_Devices" ]; - "Win32_Devices_SerialCommunication" = [ "Win32_Devices" ]; - "Win32_Devices_Tapi" = [ "Win32_Devices" ]; - "Win32_Devices_Usb" = [ "Win32_Devices" ]; - "Win32_Devices_WebServicesOnDevices" = [ "Win32_Devices" ]; - "Win32_Foundation" = [ "Win32" ]; - "Win32_Gaming" = [ "Win32" ]; - "Win32_Globalization" = [ "Win32" ]; - "Win32_Graphics" = [ "Win32" ]; - "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; - "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; - "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; - "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; - "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; - "Win32_Graphics_Printing_PrintTicket" = [ "Win32_Graphics_Printing" ]; - "Win32_Management" = [ "Win32" ]; - "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; - "Win32_Media" = [ "Win32" ]; - "Win32_Media_Audio" = [ "Win32_Media" ]; - "Win32_Media_Audio_Apo" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_DirectMusic" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_Endpoints" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_XAudio2" = [ "Win32_Media_Audio" ]; - "Win32_Media_DeviceManager" = [ "Win32_Media" ]; - "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; - "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; - "Win32_Media_LibrarySharingServices" = [ "Win32_Media" ]; - "Win32_Media_MediaPlayer" = [ "Win32_Media" ]; - "Win32_Media_Multimedia" = [ "Win32_Media" ]; - "Win32_Media_Speech" = [ "Win32_Media" ]; - "Win32_Media_Streaming" = [ "Win32_Media" ]; - "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; - "Win32_NetworkManagement" = [ "Win32" ]; - "Win32_NetworkManagement_Dhcp" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_MobileBroadband" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetworkPolicyServer" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Snmp" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsConnectNow" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; - "Win32_Networking" = [ "Win32" ]; - "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; - "Win32_Networking_BackgroundIntelligentTransferService" = [ "Win32_Networking" ]; - "Win32_Networking_Clustering" = [ "Win32_Networking" ]; - "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; - "Win32_Networking_Ldap" = [ "Win32_Networking" ]; - "Win32_Networking_NetworkListManager" = [ "Win32_Networking" ]; - "Win32_Networking_RemoteDifferentialCompression" = [ "Win32_Networking" ]; - "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; - "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; - "Win32_Networking_WinInet" = [ "Win32_Networking" ]; - "Win32_Networking_WinSock" = [ "Win32_Networking" ]; - "Win32_Networking_WindowsWebServices" = [ "Win32_Networking" ]; - "Win32_Security" = [ "Win32" ]; - "Win32_Security_AppLocker" = [ "Win32_Security" ]; - "Win32_Security_Authentication" = [ "Win32_Security" ]; - "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; - "Win32_Security_Authentication_Identity_Provider" = [ "Win32_Security_Authentication_Identity" ]; - "Win32_Security_Authorization" = [ "Win32_Security" ]; - "Win32_Security_Authorization_UI" = [ "Win32_Security_Authorization" ]; - "Win32_Security_ConfigurationSnapin" = [ "Win32_Security" ]; - "Win32_Security_Credentials" = [ "Win32_Security" ]; - "Win32_Security_Cryptography" = [ "Win32_Security" ]; - "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_Cryptography_Certificates" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_Cryptography_Sip" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_Cryptography_UI" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_DiagnosticDataQuery" = [ "Win32_Security" ]; - "Win32_Security_DirectoryServices" = [ "Win32_Security" ]; - "Win32_Security_EnterpriseData" = [ "Win32_Security" ]; - "Win32_Security_ExtensibleAuthenticationProtocol" = [ "Win32_Security" ]; - "Win32_Security_Isolation" = [ "Win32_Security" ]; - "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; - "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; - "Win32_Security_Tpm" = [ "Win32_Security" ]; - "Win32_Security_WinTrust" = [ "Win32_Security" ]; - "Win32_Security_WinWlx" = [ "Win32_Security" ]; - "Win32_Storage" = [ "Win32" ]; - "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; - "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; - "Win32_Storage_Compression" = [ "Win32_Storage" ]; - "Win32_Storage_DataDeduplication" = [ "Win32_Storage" ]; - "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; - "Win32_Storage_EnhancedStorage" = [ "Win32_Storage" ]; - "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; - "Win32_Storage_FileServerResourceManager" = [ "Win32_Storage" ]; - "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; - "Win32_Storage_Imapi" = [ "Win32_Storage" ]; - "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; - "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; - "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; - "Win32_Storage_Jet" = [ "Win32_Storage" ]; - "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; - "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; - "Win32_Storage_Packaging" = [ "Win32_Storage" ]; - "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; - "Win32_Storage_Packaging_Opc" = [ "Win32_Storage_Packaging" ]; - "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; - "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; - "Win32_Storage_Vhd" = [ "Win32_Storage" ]; - "Win32_Storage_VirtualDiskService" = [ "Win32_Storage" ]; - "Win32_Storage_Vss" = [ "Win32_Storage" ]; - "Win32_Storage_Xps" = [ "Win32_Storage" ]; - "Win32_Storage_Xps_Printing" = [ "Win32_Storage_Xps" ]; - "Win32_System" = [ "Win32" ]; - "Win32_System_AddressBook" = [ "Win32_System" ]; - "Win32_System_Antimalware" = [ "Win32_System" ]; - "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; - "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; - "Win32_System_AssessmentTool" = [ "Win32_System" ]; - "Win32_System_Com" = [ "Win32_System" ]; - "Win32_System_Com_CallObj" = [ "Win32_System_Com" ]; - "Win32_System_Com_ChannelCredentials" = [ "Win32_System_Com" ]; - "Win32_System_Com_Events" = [ "Win32_System_Com" ]; - "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; - "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; - "Win32_System_Com_UI" = [ "Win32_System_Com" ]; - "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; - "Win32_System_ComponentServices" = [ "Win32_System" ]; - "Win32_System_Console" = [ "Win32_System" ]; - "Win32_System_Contacts" = [ "Win32_System" ]; - "Win32_System_CorrelationVector" = [ "Win32_System" ]; - "Win32_System_DataExchange" = [ "Win32_System" ]; - "Win32_System_DeploymentServices" = [ "Win32_System" ]; - "Win32_System_DesktopSharing" = [ "Win32_System" ]; - "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; - "Win32_System_Diagnostics" = [ "Win32_System" ]; - "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; - "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; - "Win32_System_Environment" = [ "Win32_System" ]; - "Win32_System_ErrorReporting" = [ "Win32_System" ]; - "Win32_System_EventCollector" = [ "Win32_System" ]; - "Win32_System_EventLog" = [ "Win32_System" ]; - "Win32_System_EventNotificationService" = [ "Win32_System" ]; - "Win32_System_GroupPolicy" = [ "Win32_System" ]; - "Win32_System_HostCompute" = [ "Win32_System" ]; - "Win32_System_HostComputeNetwork" = [ "Win32_System" ]; - "Win32_System_HostComputeSystem" = [ "Win32_System" ]; - "Win32_System_Hypervisor" = [ "Win32_System" ]; - "Win32_System_IO" = [ "Win32_System" ]; - "Win32_System_Iis" = [ "Win32_System" ]; - "Win32_System_Ioctl" = [ "Win32_System" ]; - "Win32_System_JobObjects" = [ "Win32_System" ]; - "Win32_System_Js" = [ "Win32_System" ]; - "Win32_System_Kernel" = [ "Win32_System" ]; - "Win32_System_LibraryLoader" = [ "Win32_System" ]; - "Win32_System_Mailslots" = [ "Win32_System" ]; - "Win32_System_Mapi" = [ "Win32_System" ]; - "Win32_System_Memory" = [ "Win32_System" ]; - "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; - "Win32_System_MessageQueuing" = [ "Win32_System" ]; - "Win32_System_MixedReality" = [ "Win32_System" ]; - "Win32_System_Mmc" = [ "Win32_System" ]; - "Win32_System_Ole" = [ "Win32_System" ]; - "Win32_System_ParentalControls" = [ "Win32_System" ]; - "Win32_System_PasswordManagement" = [ "Win32_System" ]; - "Win32_System_Performance" = [ "Win32_System" ]; - "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; - "Win32_System_Pipes" = [ "Win32_System" ]; - "Win32_System_Power" = [ "Win32_System" ]; - "Win32_System_ProcessStatus" = [ "Win32_System" ]; - "Win32_System_RealTimeCommunications" = [ "Win32_System" ]; - "Win32_System_Recovery" = [ "Win32_System" ]; - "Win32_System_Registry" = [ "Win32_System" ]; - "Win32_System_RemoteAssistance" = [ "Win32_System" ]; - "Win32_System_RemoteDesktop" = [ "Win32_System" ]; - "Win32_System_RemoteManagement" = [ "Win32_System" ]; - "Win32_System_RestartManager" = [ "Win32_System" ]; - "Win32_System_Restore" = [ "Win32_System" ]; - "Win32_System_Rpc" = [ "Win32_System" ]; - "Win32_System_Search" = [ "Win32_System" ]; - "Win32_System_Search_Common" = [ "Win32_System_Search" ]; - "Win32_System_SecurityCenter" = [ "Win32_System" ]; - "Win32_System_ServerBackup" = [ "Win32_System" ]; - "Win32_System_Services" = [ "Win32_System" ]; - "Win32_System_SettingsManagementInfrastructure" = [ "Win32_System" ]; - "Win32_System_SetupAndMigration" = [ "Win32_System" ]; - "Win32_System_Shutdown" = [ "Win32_System" ]; - "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; - "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; - "Win32_System_SystemInformation" = [ "Win32_System" ]; - "Win32_System_SystemServices" = [ "Win32_System" ]; - "Win32_System_TaskScheduler" = [ "Win32_System" ]; - "Win32_System_Threading" = [ "Win32_System" ]; - "Win32_System_Time" = [ "Win32_System" ]; - "Win32_System_TpmBaseServices" = [ "Win32_System" ]; - "Win32_System_UpdateAgent" = [ "Win32_System" ]; - "Win32_System_UpdateAssessment" = [ "Win32_System" ]; - "Win32_System_UserAccessLogging" = [ "Win32_System" ]; - "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; - "Win32_System_WindowsProgramming" = [ "Win32_System" ]; - "Win32_System_WindowsSync" = [ "Win32_System" ]; - "Win32_System_Wmi" = [ "Win32_System" ]; - "Win32_UI" = [ "Win32" ]; - "Win32_UI_Accessibility" = [ "Win32_UI" ]; - "Win32_UI_Animation" = [ "Win32_UI" ]; - "Win32_UI_ColorSystem" = [ "Win32_UI" ]; - "Win32_UI_Controls" = [ "Win32_UI" ]; - "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; - "Win32_UI_Controls_RichEdit" = [ "Win32_UI_Controls" ]; - "Win32_UI_HiDpi" = [ "Win32_UI" ]; - "Win32_UI_Input" = [ "Win32_UI" ]; - "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Ink" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Radial" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; - "Win32_UI_InteractionContext" = [ "Win32_UI" ]; - "Win32_UI_LegacyWindowsEnvironmentFeatures" = [ "Win32_UI" ]; - "Win32_UI_Magnification" = [ "Win32_UI" ]; - "Win32_UI_Notifications" = [ "Win32_UI" ]; - "Win32_UI_Ribbon" = [ "Win32_UI" ]; - "Win32_UI_Shell" = [ "Win32_UI" ]; - "Win32_UI_Shell_Common" = [ "Win32_UI_Shell" ]; - "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; - "Win32_UI_TabletPC" = [ "Win32_UI" ]; - "Win32_UI_TextServices" = [ "Win32_UI" ]; - "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; - "Win32_UI_Wpf" = [ "Win32_UI" ]; - }; - resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Console" "Win32_UI" "Win32_UI_Input" "Win32_UI_Input_KeyboardAndMouse" "default" ]; - }; - "windows-sys 0.48.0" = rec { + "windows-sys 0.52.0" = rec { crateName = "windows-sys"; - version = "0.48.0"; - edition = "2018"; - sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; + version = "0.52.0"; + edition = "2021"; + sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + libName = "windows_sys"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets 0.48.5"; + packageId = "windows-targets"; } ]; features = { + "Wdk_Foundation" = [ "Wdk" ]; + "Wdk_Graphics" = [ "Wdk" ]; + "Wdk_Graphics_Direct3D" = [ "Wdk_Graphics" ]; + "Wdk_Storage" = [ "Wdk" ]; + "Wdk_Storage_FileSystem" = [ "Wdk_Storage" ]; + "Wdk_Storage_FileSystem_Minifilters" = [ "Wdk_Storage_FileSystem" ]; "Wdk_System" = [ "Wdk" ]; + "Wdk_System_IO" = [ "Wdk_System" ]; "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; + "Wdk_System_Registry" = [ "Wdk_System" ]; + "Wdk_System_SystemInformation" = [ "Wdk_System" ]; + "Wdk_System_SystemServices" = [ "Wdk_System" ]; + "Wdk_System_Threading" = [ "Wdk_System" ]; "Win32_Data" = [ "Win32" ]; "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; "Win32_Data_RightsManagement" = [ "Win32_Data" ]; - "Win32_Data_Xml" = [ "Win32_Data" ]; - "Win32_Data_Xml_MsXml" = [ "Win32_Data_Xml" ]; - "Win32_Data_Xml_XmlLite" = [ "Win32_Data_Xml" ]; "Win32_Devices" = [ "Win32" ]; "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; "Win32_Devices_Communication" = [ "Win32_Devices" ]; - "Win32_Devices_DeviceAccess" = [ "Win32_Devices" ]; "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; "Win32_Devices_Display" = [ "Win32_Devices" ]; "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; "Win32_Devices_Fax" = [ "Win32_Devices" ]; - "Win32_Devices_FunctionDiscovery" = [ "Win32_Devices" ]; - "Win32_Devices_Geolocation" = [ "Win32_Devices" ]; "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; - "Win32_Devices_ImageAcquisition" = [ "Win32_Devices" ]; "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; "Win32_Devices_Properties" = [ "Win32_Devices" ]; "Win32_Devices_Pwm" = [ "Win32_Devices" ]; @@ -10118,6 +10076,7 @@ rec { "Win32_Graphics" = [ "Win32" ]; "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; + "Win32_Graphics_GdiPlus" = [ "Win32_Graphics" ]; "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; @@ -10126,17 +10085,9 @@ rec { "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; "Win32_Media" = [ "Win32" ]; "Win32_Media_Audio" = [ "Win32_Media" ]; - "Win32_Media_Audio_Apo" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_DirectMusic" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_Endpoints" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_XAudio2" = [ "Win32_Media_Audio" ]; - "Win32_Media_DeviceManager" = [ "Win32_Media" ]; "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; - "Win32_Media_LibrarySharingServices" = [ "Win32_Media" ]; - "Win32_Media_MediaPlayer" = [ "Win32_Media" ]; "Win32_Media_Multimedia" = [ "Win32_Media" ]; - "Win32_Media_Speech" = [ "Win32_Media" ]; "Win32_Media_Streaming" = [ "Win32_Media" ]; "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; "Win32_NetworkManagement" = [ "Win32" ]; @@ -10144,14 +10095,12 @@ rec { "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_MobileBroadband" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetworkPolicyServer" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; @@ -10159,19 +10108,15 @@ rec { "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsConnectNow" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; "Win32_Networking" = [ "Win32" ]; "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; - "Win32_Networking_BackgroundIntelligentTransferService" = [ "Win32_Networking" ]; "Win32_Networking_Clustering" = [ "Win32_Networking" ]; "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; "Win32_Networking_Ldap" = [ "Win32_Networking" ]; - "Win32_Networking_NetworkListManager" = [ "Win32_Networking" ]; - "Win32_Networking_RemoteDifferentialCompression" = [ "Win32_Networking" ]; "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; "Win32_Networking_WinInet" = [ "Win32_Networking" ]; @@ -10181,10 +10126,7 @@ rec { "Win32_Security_AppLocker" = [ "Win32_Security" ]; "Win32_Security_Authentication" = [ "Win32_Security" ]; "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; - "Win32_Security_Authentication_Identity_Provider" = [ "Win32_Security_Authentication_Identity" ]; "Win32_Security_Authorization" = [ "Win32_Security" ]; - "Win32_Security_Authorization_UI" = [ "Win32_Security_Authorization" ]; - "Win32_Security_ConfigurationSnapin" = [ "Win32_Security" ]; "Win32_Security_Credentials" = [ "Win32_Security" ]; "Win32_Security_Cryptography" = [ "Win32_Security" ]; "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; @@ -10198,64 +10140,48 @@ rec { "Win32_Security_Isolation" = [ "Win32_Security" ]; "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; - "Win32_Security_Tpm" = [ "Win32_Security" ]; "Win32_Security_WinTrust" = [ "Win32_Security" ]; "Win32_Security_WinWlx" = [ "Win32_Security" ]; "Win32_Storage" = [ "Win32" ]; "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; "Win32_Storage_Compression" = [ "Win32_Storage" ]; - "Win32_Storage_DataDeduplication" = [ "Win32_Storage" ]; "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; - "Win32_Storage_EnhancedStorage" = [ "Win32_Storage" ]; "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; - "Win32_Storage_FileServerResourceManager" = [ "Win32_Storage" ]; "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; "Win32_Storage_Imapi" = [ "Win32_Storage" ]; "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; "Win32_Storage_Jet" = [ "Win32_Storage" ]; + "Win32_Storage_Nvme" = [ "Win32_Storage" ]; "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; "Win32_Storage_Packaging" = [ "Win32_Storage" ]; "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; - "Win32_Storage_Packaging_Opc" = [ "Win32_Storage_Packaging" ]; "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; "Win32_Storage_Vhd" = [ "Win32_Storage" ]; - "Win32_Storage_VirtualDiskService" = [ "Win32_Storage" ]; - "Win32_Storage_Vss" = [ "Win32_Storage" ]; "Win32_Storage_Xps" = [ "Win32_Storage" ]; - "Win32_Storage_Xps_Printing" = [ "Win32_Storage_Xps" ]; "Win32_System" = [ "Win32" ]; "Win32_System_AddressBook" = [ "Win32_System" ]; "Win32_System_Antimalware" = [ "Win32_System" ]; "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; - "Win32_System_AssessmentTool" = [ "Win32_System" ]; "Win32_System_ClrHosting" = [ "Win32_System" ]; "Win32_System_Com" = [ "Win32_System" ]; - "Win32_System_Com_CallObj" = [ "Win32_System_Com" ]; - "Win32_System_Com_ChannelCredentials" = [ "Win32_System_Com" ]; - "Win32_System_Com_Events" = [ "Win32_System_Com" ]; "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; - "Win32_System_Com_UI" = [ "Win32_System_Com" ]; "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; "Win32_System_ComponentServices" = [ "Win32_System" ]; "Win32_System_Console" = [ "Win32_System" ]; - "Win32_System_Contacts" = [ "Win32_System" ]; "Win32_System_CorrelationVector" = [ "Win32_System" ]; "Win32_System_DataExchange" = [ "Win32_System" ]; "Win32_System_DeploymentServices" = [ "Win32_System" ]; - "Win32_System_DesktopSharing" = [ "Win32_System" ]; "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; "Win32_System_Diagnostics" = [ "Win32_System" ]; "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_ClrProfiling" = [ "Win32_System_Diagnostics" ]; "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_Debug_ActiveScript" = [ "Win32_System_Diagnostics_Debug" ]; "Win32_System_Diagnostics_Debug_Extensions" = [ "Win32_System_Diagnostics_Debug" ]; "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; @@ -10284,19 +10210,15 @@ rec { "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; "Win32_System_MessageQueuing" = [ "Win32_System" ]; "Win32_System_MixedReality" = [ "Win32_System" ]; - "Win32_System_Mmc" = [ "Win32_System" ]; "Win32_System_Ole" = [ "Win32_System" ]; - "Win32_System_ParentalControls" = [ "Win32_System" ]; "Win32_System_PasswordManagement" = [ "Win32_System" ]; "Win32_System_Performance" = [ "Win32_System" ]; "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; "Win32_System_Pipes" = [ "Win32_System" ]; "Win32_System_Power" = [ "Win32_System" ]; "Win32_System_ProcessStatus" = [ "Win32_System" ]; - "Win32_System_RealTimeCommunications" = [ "Win32_System" ]; "Win32_System_Recovery" = [ "Win32_System" ]; "Win32_System_Registry" = [ "Win32_System" ]; - "Win32_System_RemoteAssistance" = [ "Win32_System" ]; "Win32_System_RemoteDesktop" = [ "Win32_System" ]; "Win32_System_RemoteManagement" = [ "Win32_System" ]; "Win32_System_RestartManager" = [ "Win32_System" ]; @@ -10305,87 +10227,83 @@ rec { "Win32_System_Search" = [ "Win32_System" ]; "Win32_System_Search_Common" = [ "Win32_System_Search" ]; "Win32_System_SecurityCenter" = [ "Win32_System" ]; - "Win32_System_ServerBackup" = [ "Win32_System" ]; "Win32_System_Services" = [ "Win32_System" ]; - "Win32_System_SettingsManagementInfrastructure" = [ "Win32_System" ]; "Win32_System_SetupAndMigration" = [ "Win32_System" ]; "Win32_System_Shutdown" = [ "Win32_System" ]; "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; "Win32_System_SystemInformation" = [ "Win32_System" ]; "Win32_System_SystemServices" = [ "Win32_System" ]; - "Win32_System_TaskScheduler" = [ "Win32_System" ]; "Win32_System_Threading" = [ "Win32_System" ]; "Win32_System_Time" = [ "Win32_System" ]; "Win32_System_TpmBaseServices" = [ "Win32_System" ]; - "Win32_System_UpdateAgent" = [ "Win32_System" ]; - "Win32_System_UpdateAssessment" = [ "Win32_System" ]; "Win32_System_UserAccessLogging" = [ "Win32_System" ]; + "Win32_System_Variant" = [ "Win32_System" ]; "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; "Win32_System_WindowsProgramming" = [ "Win32_System" ]; - "Win32_System_WindowsSync" = [ "Win32_System" ]; "Win32_System_Wmi" = [ "Win32_System" ]; "Win32_UI" = [ "Win32" ]; "Win32_UI_Accessibility" = [ "Win32_UI" ]; - "Win32_UI_Animation" = [ "Win32_UI" ]; "Win32_UI_ColorSystem" = [ "Win32_UI" ]; "Win32_UI_Controls" = [ "Win32_UI" ]; "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; - "Win32_UI_Controls_RichEdit" = [ "Win32_UI_Controls" ]; "Win32_UI_HiDpi" = [ "Win32_UI" ]; "Win32_UI_Input" = [ "Win32_UI" ]; "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Ink" = [ "Win32_UI_Input" ]; "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Radial" = [ "Win32_UI_Input" ]; "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; "Win32_UI_InteractionContext" = [ "Win32_UI" ]; - "Win32_UI_LegacyWindowsEnvironmentFeatures" = [ "Win32_UI" ]; "Win32_UI_Magnification" = [ "Win32_UI" ]; - "Win32_UI_Notifications" = [ "Win32_UI" ]; - "Win32_UI_Ribbon" = [ "Win32_UI" ]; "Win32_UI_Shell" = [ "Win32_UI" ]; - "Win32_UI_Shell_Common" = [ "Win32_UI_Shell" ]; "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; "Win32_UI_TabletPC" = [ "Win32_UI" ]; "Win32_UI_TextServices" = [ "Win32_UI" ]; "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; - "Win32_UI_Wpf" = [ "Win32_UI" ]; "Win32_Web" = [ "Win32" ]; "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; }; - resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_NetworkManagement" "Win32_NetworkManagement_IpHelper" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Security_Authentication" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_Security_Cryptography" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Console" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_Memory" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "Win32_UI" "Win32_UI_Shell" "default" ]; + resolvedDefaultFeatures = [ "Wdk" "Wdk_Foundation" "Wdk_Storage" "Wdk_Storage_FileSystem" "Wdk_System" "Wdk_System_IO" "Win32" "Win32_Foundation" "Win32_NetworkManagement" "Win32_NetworkManagement_IpHelper" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Com" "Win32_System_Console" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "Win32_UI" "Win32_UI_Input" "Win32_UI_Input_KeyboardAndMouse" "Win32_UI_Shell" "default" ]; }; - "windows-sys 0.52.0" = rec { + "windows-sys 0.59.0" = rec { crateName = "windows-sys"; - version = "0.52.0"; + version = "0.59.0"; edition = "2021"; - sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + sha256 = "0fw5672ziw8b3zpmnbp9pdv1famk74f1l9fcbc3zsrzdg56vqf0y"; + libName = "windows_sys"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets 0.52.0"; + packageId = "windows-targets"; } ]; features = { + "Wdk" = [ "Win32_Foundation" ]; + "Wdk_Devices" = [ "Wdk" ]; + "Wdk_Devices_Bluetooth" = [ "Wdk_Devices" ]; + "Wdk_Devices_HumanInterfaceDevice" = [ "Wdk_Devices" ]; "Wdk_Foundation" = [ "Wdk" ]; "Wdk_Graphics" = [ "Wdk" ]; "Wdk_Graphics_Direct3D" = [ "Wdk_Graphics" ]; + "Wdk_NetworkManagement" = [ "Wdk" ]; + "Wdk_NetworkManagement_Ndis" = [ "Wdk_NetworkManagement" ]; + "Wdk_NetworkManagement_WindowsFilteringPlatform" = [ "Wdk_NetworkManagement" ]; "Wdk_Storage" = [ "Wdk" ]; "Wdk_Storage_FileSystem" = [ "Wdk_Storage" ]; "Wdk_Storage_FileSystem_Minifilters" = [ "Wdk_Storage_FileSystem" ]; "Wdk_System" = [ "Wdk" ]; "Wdk_System_IO" = [ "Wdk_System" ]; + "Wdk_System_Memory" = [ "Wdk_System" ]; "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; "Wdk_System_Registry" = [ "Wdk_System" ]; "Wdk_System_SystemInformation" = [ "Wdk_System" ]; "Wdk_System_SystemServices" = [ "Wdk_System" ]; "Wdk_System_Threading" = [ "Wdk_System" ]; + "Win32" = [ "Win32_Foundation" ]; "Win32_Data" = [ "Win32" ]; "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; "Win32_Data_RightsManagement" = [ "Win32_Data" ]; @@ -10525,6 +10443,7 @@ rec { "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_TraceLogging" = [ "Win32_System_Diagnostics" ]; "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; "Win32_System_Environment" = [ "Win32_System" ]; "Win32_System_ErrorReporting" = [ "Win32_System" ]; @@ -10596,6 +10515,7 @@ rec { "Win32_UI_InteractionContext" = [ "Win32_UI" ]; "Win32_UI_Magnification" = [ "Win32_UI" ]; "Win32_UI_Shell" = [ "Win32_UI" ]; + "Win32_UI_Shell_Common" = [ "Win32_UI_Shell" ]; "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; "Win32_UI_TabletPC" = [ "Win32_UI" ]; "Win32_UI_TextServices" = [ "Win32_UI" ]; @@ -10603,379 +10523,136 @@ rec { "Win32_Web" = [ "Win32" ]; "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; }; - resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_System" "Win32_System_Console" "default" ]; + resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Security" "Win32_Security_Authentication" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_Security_Cryptography" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_LibraryLoader" "Win32_System_Memory" "Win32_System_SystemInformation" "default" ]; }; - "windows-targets 0.42.2" = rec { + "windows-targets" = rec { crateName = "windows-targets"; - version = "0.42.2"; - edition = "2018"; - sha256 = "0wfhnib2fisxlx8c507dbmh97kgij4r6kcxdi0f9nk6l1k080lcf"; - authors = [ - "Microsoft" - ]; - dependencies = [ - { - name = "windows_aarch64_gnullvm"; - packageId = "windows_aarch64_gnullvm 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); - } - { - name = "windows_aarch64_msvc"; - packageId = "windows_aarch64_msvc 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-msvc"); - } - { - name = "windows_aarch64_msvc"; - packageId = "windows_aarch64_msvc 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-uwp-windows-msvc"); - } - { - name = "windows_i686_gnu"; - packageId = "windows_i686_gnu 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "i686-pc-windows-gnu"); - } - { - name = "windows_i686_gnu"; - packageId = "windows_i686_gnu 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "i686-uwp-windows-gnu"); - } - { - name = "windows_i686_msvc"; - packageId = "windows_i686_msvc 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "i686-pc-windows-msvc"); - } - { - name = "windows_i686_msvc"; - packageId = "windows_i686_msvc 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "i686-uwp-windows-msvc"); - } - { - name = "windows_x86_64_gnu"; - packageId = "windows_x86_64_gnu 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnu"); - } - { - name = "windows_x86_64_gnu"; - packageId = "windows_x86_64_gnu 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-uwp-windows-gnu"); - } - { - name = "windows_x86_64_gnullvm"; - packageId = "windows_x86_64_gnullvm 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); - } - { - name = "windows_x86_64_msvc"; - packageId = "windows_x86_64_msvc 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-msvc"); - } - { - name = "windows_x86_64_msvc"; - packageId = "windows_x86_64_msvc 0.42.2"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-uwp-windows-msvc"); - } - ]; - - }; - "windows-targets 0.48.5" = rec { - crateName = "windows-targets"; - version = "0.48.5"; - edition = "2018"; - sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0wwrx625nwlfp7k93r2rra568gad1mwd888h1jwnl0vfg5r4ywlv"; + libName = "windows_targets"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows_aarch64_gnullvm"; - packageId = "windows_aarch64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + packageId = "windows_aarch64_gnullvm"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); } { name = "windows_aarch64_msvc"; - packageId = "windows_aarch64_msvc 0.48.5"; + packageId = "windows_aarch64_msvc"; target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_i686_gnu"; - packageId = "windows_i686_gnu 0.48.5"; - target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!(target."windows_raw_dylib" or false))); - } - { - name = "windows_i686_msvc"; - packageId = "windows_i686_msvc 0.48.5"; - target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + packageId = "windows_i686_gnu"; + target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); } { - name = "windows_x86_64_gnu"; - packageId = "windows_x86_64_gnu 0.48.5"; - target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); - } - { - name = "windows_x86_64_gnullvm"; - packageId = "windows_x86_64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); - } - { - name = "windows_x86_64_msvc"; - packageId = "windows_x86_64_msvc 0.48.5"; - target = { target, features }: (("x86_64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); - } - ]; - - }; - "windows-targets 0.52.0" = rec { - crateName = "windows-targets"; - version = "0.52.0"; - edition = "2021"; - sha256 = "1kg7a27ynzw8zz3krdgy6w5gbqcji27j1sz4p7xk2j5j8082064a"; - authors = [ - "Microsoft" - ]; - dependencies = [ - { - name = "windows_aarch64_gnullvm"; - packageId = "windows_aarch64_gnullvm 0.52.0"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); - } - { - name = "windows_aarch64_msvc"; - packageId = "windows_aarch64_msvc 0.52.0"; - target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); - } - { - name = "windows_i686_gnu"; - packageId = "windows_i686_gnu 0.52.0"; - target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + name = "windows_i686_gnullvm"; + packageId = "windows_i686_gnullvm"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnullvm"); } { name = "windows_i686_msvc"; - packageId = "windows_i686_msvc 0.52.0"; + packageId = "windows_i686_msvc"; target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnu"; - packageId = "windows_x86_64_gnu 0.52.0"; + packageId = "windows_x86_64_gnu"; target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnullvm"; - packageId = "windows_x86_64_gnullvm 0.52.0"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); + packageId = "windows_x86_64_gnullvm"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); } { name = "windows_x86_64_msvc"; - packageId = "windows_x86_64_msvc 0.52.0"; - target = { target, features }: (("x86_64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + packageId = "windows_x86_64_msvc"; + target = { target, features }: ((("x86_64" == target."arch" or null) || ("arm64ec" == target."arch" or null)) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } ]; }; - "windows_aarch64_gnullvm 0.42.2" = rec { + "windows_aarch64_gnullvm" = rec { crateName = "windows_aarch64_gnullvm"; - version = "0.42.2"; - edition = "2018"; - sha256 = "1y4q0qmvl0lvp7syxvfykafvmwal5hrjb4fmv04bqs0bawc52yjr"; - authors = [ - "Microsoft" - ]; - - }; - "windows_aarch64_gnullvm 0.48.5" = rec { - crateName = "windows_aarch64_gnullvm"; - version = "0.48.5"; - edition = "2018"; - sha256 = "1n05v7qblg1ci3i567inc7xrkmywczxrs1z3lj3rkkxw18py6f1b"; - authors = [ - "Microsoft" - ]; - - }; - "windows_aarch64_gnullvm 0.52.0" = rec { - crateName = "windows_aarch64_gnullvm"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "1shmn1kbdc0bpphcxz0vlph96bxz0h1jlmh93s9agf2dbpin8xyb"; + sha256 = "1lrcq38cr2arvmz19v32qaggvj8bh1640mdm9c2fr877h0hn591j"; authors = [ "Microsoft" ]; }; - "windows_aarch64_msvc 0.42.2" = rec { + "windows_aarch64_msvc" = rec { crateName = "windows_aarch64_msvc"; - version = "0.42.2"; - edition = "2018"; - sha256 = "0hsdikjl5sa1fva5qskpwlxzpc5q9l909fpl1w6yy1hglrj8i3p0"; - authors = [ - "Microsoft" - ]; - - }; - "windows_aarch64_msvc 0.48.5" = rec { - crateName = "windows_aarch64_msvc"; - version = "0.48.5"; - edition = "2018"; - sha256 = "1g5l4ry968p73g6bg6jgyvy9lb8fyhcs54067yzxpcpkf44k2dfw"; - authors = [ - "Microsoft" - ]; - - }; - "windows_aarch64_msvc 0.52.0" = rec { - crateName = "windows_aarch64_msvc"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "1vvmy1ypvzdvxn9yf0b8ygfl85gl2gpcyvsvqppsmlpisil07amv"; - authors = [ - "Microsoft" - ]; - - }; - "windows_i686_gnu 0.42.2" = rec { - crateName = "windows_i686_gnu"; - version = "0.42.2"; - edition = "2018"; - sha256 = "0kx866dfrby88lqs9v1vgmrkk1z6af9lhaghh5maj7d4imyr47f6"; + sha256 = "0sfl0nysnz32yyfh773hpi49b1q700ah6y7sacmjbqjjn5xjmv09"; authors = [ "Microsoft" ]; }; - "windows_i686_gnu 0.48.5" = rec { + "windows_i686_gnu" = rec { crateName = "windows_i686_gnu"; - version = "0.48.5"; - edition = "2018"; - sha256 = "0gklnglwd9ilqx7ac3cn8hbhkraqisd0n83jxzf9837nvvkiand7"; - authors = [ - "Microsoft" - ]; - - }; - "windows_i686_gnu 0.52.0" = rec { - crateName = "windows_i686_gnu"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "04zkglz4p3pjsns5gbz85v4s5aw102raz4spj4b0lmm33z5kg1m2"; - authors = [ - "Microsoft" - ]; - - }; - "windows_i686_msvc 0.42.2" = rec { - crateName = "windows_i686_msvc"; - version = "0.42.2"; - edition = "2018"; - sha256 = "0q0h9m2aq1pygc199pa5jgc952qhcnf0zn688454i7v4xjv41n24"; + sha256 = "02zspglbykh1jh9pi7gn8g1f97jh1rrccni9ivmrfbl0mgamm6wf"; authors = [ "Microsoft" ]; }; - "windows_i686_msvc 0.48.5" = rec { - crateName = "windows_i686_msvc"; - version = "0.48.5"; - edition = "2018"; - sha256 = "01m4rik437dl9rdf0ndnm2syh10hizvq0dajdkv2fjqcywrw4mcg"; + "windows_i686_gnullvm" = rec { + crateName = "windows_i686_gnullvm"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0rpdx1537mw6slcpqa0rm3qixmsb79nbhqy5fsm3q2q9ik9m5vhf"; authors = [ "Microsoft" ]; }; - "windows_i686_msvc 0.52.0" = rec { + "windows_i686_msvc" = rec { crateName = "windows_i686_msvc"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "16kvmbvx0vr0zbgnaz6nsks9ycvfh5xp05bjrhq65kj623iyirgz"; + sha256 = "0rkcqmp4zzmfvrrrx01260q3xkpzi6fzi2x2pgdcdry50ny4h294"; authors = [ "Microsoft" ]; }; - "windows_x86_64_gnu 0.42.2" = rec { + "windows_x86_64_gnu" = rec { crateName = "windows_x86_64_gnu"; - version = "0.42.2"; - edition = "2018"; - sha256 = "0dnbf2xnp3xrvy8v9mgs3var4zq9v9yh9kv79035rdgyp2w15scd"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_gnu 0.48.5" = rec { - crateName = "windows_x86_64_gnu"; - version = "0.48.5"; - edition = "2018"; - sha256 = "13kiqqcvz2vnyxzydjh73hwgigsdr2z1xpzx313kxll34nyhmm2k"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_gnu 0.52.0" = rec { - crateName = "windows_x86_64_gnu"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "1zdy4qn178sil5sdm63lm7f0kkcjg6gvdwmcprd2yjmwn8ns6vrx"; + sha256 = "0y0sifqcb56a56mvn7xjgs8g43p33mfqkd8wj1yhrgxzma05qyhl"; authors = [ "Microsoft" ]; }; - "windows_x86_64_gnullvm 0.42.2" = rec { + "windows_x86_64_gnullvm" = rec { crateName = "windows_x86_64_gnullvm"; - version = "0.42.2"; - edition = "2018"; - sha256 = "18wl9r8qbsl475j39zvawlidp1bsbinliwfymr43fibdld31pm16"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_gnullvm 0.48.5" = rec { - crateName = "windows_x86_64_gnullvm"; - version = "0.48.5"; - edition = "2018"; - sha256 = "1k24810wfbgz8k48c2yknqjmiigmql6kk3knmddkv8k8g1v54yqb"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_gnullvm 0.52.0" = rec { - crateName = "windows_x86_64_gnullvm"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "17lllq4l2k1lqgcnw1cccphxp9vs7inq99kjlm2lfl9zklg7wr8s"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_msvc 0.42.2" = rec { - crateName = "windows_x86_64_msvc"; - version = "0.42.2"; - edition = "2018"; - sha256 = "1w5r0q0yzx827d10dpjza2ww0j8iajqhmb54s735hhaj66imvv4s"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_msvc 0.48.5" = rec { - crateName = "windows_x86_64_msvc"; - version = "0.48.5"; - edition = "2018"; - sha256 = "0f4mdp895kkjh9zv8dxvn4pc10xr7839lf5pa9l0193i2pkgr57d"; + sha256 = "03gda7zjx1qh8k9nnlgb7m3w3s1xkysg55hkd1wjch8pqhyv5m94"; authors = [ "Microsoft" ]; }; - "windows_x86_64_msvc 0.52.0" = rec { + "windows_x86_64_msvc" = rec { crateName = "windows_x86_64_msvc"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "012wfq37f18c09ij5m6rniw7xxn5fcvrxbqd0wd8vgnl3hfn9yfz"; + sha256 = "1v7rb5cibyzx8vak29pdrk8nx9hycsjs4w0jgms08qk49jl6v7sq"; authors = [ "Microsoft" ]; @@ -10983,10 +10660,10 @@ rec { }; "xml-rs" = rec { crateName = "xml-rs"; - version = "0.8.19"; + version = "0.8.22"; edition = "2021"; crateBin = [ ]; - sha256 = "0nnpvk3fv32hgh7vs9gbg2swmzxx5yz73f4b7rak7q39q2x9rjqg"; + sha256 = "09pg779vjh0xp3ph10j4wy1ihz8pzvxm1qf1jqw0jnmsghpjwkmg"; libName = "xml"; authors = [ "Vladimir Matveev <vmatveev@citrine.cc>" @@ -10995,9 +10672,10 @@ rec { }; "xxhash-rust" = rec { crateName = "xxhash-rust"; - version = "0.8.7"; + version = "0.8.12"; edition = "2018"; - sha256 = "0yz037yrkn0qa0g0r6733ynd1xbw7zvx58v6qylhyi2kv9wb2a4q"; + sha256 = "1139skyp136z8710r916kb1djp7f7flfly31zccqi5800isvyp3a"; + libName = "xxhash_rust"; authors = [ "Douman <douman@gmx.se>" ]; @@ -11027,14 +10705,20 @@ rec { }; "zerocopy" = rec { crateName = "zerocopy"; - version = "0.7.26"; + version = "0.7.35"; edition = "2018"; - sha256 = "184s51bzn8mpx3p9h6klrlppv9b7ja1b8y9998jr36jmj1a42zp9"; + sha256 = "1w36q7b9il2flg0qskapgi9ymgg7p985vniqd09vi0mwib8lz6qv"; authors = [ "Joshua Liebow-Feeser <joshlf@google.com>" ]; dependencies = [ { + name = "byteorder"; + packageId = "byteorder"; + optional = true; + usesDefaultFeatures = false; + } + { name = "zerocopy-derive"; packageId = "zerocopy-derive"; optional = true; @@ -11059,14 +10743,15 @@ rec { "simd-nightly" = [ "simd" ]; "zerocopy-derive" = [ "dep:zerocopy-derive" ]; }; - resolvedDefaultFeatures = [ "simd" ]; + resolvedDefaultFeatures = [ "byteorder" "default" "derive" "simd" "zerocopy-derive" ]; }; "zerocopy-derive" = rec { crateName = "zerocopy-derive"; - version = "0.7.26"; + version = "0.7.35"; edition = "2018"; - sha256 = "17v8yshfa23z5az2xhclpwrlzih26nj7imwbra12i5b6y764hznx"; + sha256 = "0gnf2ap2y92nwdalzz3x7142f2b83sni66l39vxp2ijd6j080kzs"; procMacro = true; + libName = "zerocopy_derive"; authors = [ "Joshua Liebow-Feeser <joshlf@google.com>" ]; @@ -11081,16 +10766,16 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; } ]; }; "zeroize" = rec { crateName = "zeroize"; - version = "1.7.0"; + version = "1.8.1"; edition = "2021"; - sha256 = "0bfvby7k9pdp6623p98yz2irqnamcyzpn7zh20nqmdn68b0lwnsj"; + sha256 = "1pjdrmjwmszpxfd7r860jx54cyk94qk59x13sc307cvr5256glyf"; authors = [ "The RustCrypto Project Developers" ]; @@ -11105,9 +10790,9 @@ rec { }; "zstd" = rec { crateName = "zstd"; - version = "0.13.0"; + version = "0.13.2"; edition = "2018"; - sha256 = "0401q54s9r35x2i7m1kwppgkj79g0pb6xz3xpby7qlkdb44k7yxz"; + sha256 = "1ygkr6wspm9clbp7ykyl0rv69cfsf9q4lic9wcqiwn34lrwbgwpw"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -11138,9 +10823,10 @@ rec { }; "zstd-safe" = rec { crateName = "zstd-safe"; - version = "7.0.0"; + version = "7.2.1"; edition = "2018"; - sha256 = "0gpav2lcibrpmyslmjkcn3w0w64qif3jjljd2h8lr4p249s7qx23"; + sha256 = "0nch85m5cr493y26yvndm6a8j6sd9mxpr2awrim3dslcnr6sp8sl"; + libName = "zstd_safe"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -11170,10 +10856,11 @@ rec { }; "zstd-sys" = rec { crateName = "zstd-sys"; - version = "2.0.9+zstd.1.5.5"; + version = "2.0.13+zstd.1.5.6"; edition = "2018"; links = "zstd"; - sha256 = "0mk6a2367swdi22zg03lcackpnvgq96d7120awd4i83lm2lfy5ly"; + sha256 = "1almbackh06am0d2kc4a089n3al91jg3ahgg9kcrg3zfrwhhzzrq"; + libName = "zstd_sys"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -11209,14 +10896,11 @@ rec { fuchsia = true; test = false; - /* We are choosing an arbitrary rust version to grab `lib` from, - which is unfortunate, but `lib` has been version-agnostic the - whole time so this is good enough for now. - */ - os = pkgs.rust.lib.toTargetOs platform; - arch = pkgs.rust.lib.toTargetArch platform; - family = pkgs.rust.lib.toTargetFamily platform; - vendor = pkgs.rust.lib.toTargetVendor platform; + inherit (platform.rust.platform) + arch + os + vendor; + family = platform.rust.platform.target-family; env = "gnu"; endian = if platform.parsed.cpu.significantByte.name == "littleEndian" @@ -11293,6 +10977,7 @@ rec { ( _: { buildTests = true; + release = false; } ); # If the user hasn't set any pre/post commands, we don't want to @@ -11305,51 +10990,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e - - export RUST_BACKTRACE=1 - - # recreate a file hierarchy as when running tests with cargo - - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # TODO(raitobezarius): I believe there could be more edge cases if `crate.sourceRoot` - # do exist but it's very hard to reason about them, so let's wait until the first bug report. - mkdir -p source/ - cd source/ - - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} - - # build outputs - testRoot=target/debug - mkdir -p $testRoot - - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . - - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; + + inherit (crate) src; + + inherit testCrateFlags; + + buildInputs = testInputs; + + buildPhase = '' + set -e + export RUST_BACKTRACE=1 + + # build outputs + testRoot=target/debug + mkdir -p $testRoot + + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . + + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { @@ -11458,7 +11133,7 @@ rec { let self = { crates = lib.mapAttrs (packageId: value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs; - target = makeTarget pkgs.stdenv.hostPlatform; + target = makeTarget stdenv.hostPlatform; build = mkBuiltByPackageIdByPkgs pkgs.buildPackages; }; in @@ -11533,8 +11208,6 @@ rec { buildRustCrateForPkgsFunc pkgs ( crateConfig // { - # https://github.com/NixOS/nixpkgs/issues/218712 - dontStrip = stdenv.hostPlatform.isDarwin; src = crateConfig.src or ( pkgs.fetchurl rec { name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz"; diff --git a/tvix/tools/crunch-v2/Cargo.toml b/users/edef/crunch-v2/Cargo.toml index 1e3f0252504d..2dd94203367f 100644 --- a/tvix/tools/crunch-v2/Cargo.toml +++ b/users/edef/crunch-v2/Cargo.toml @@ -11,15 +11,15 @@ anyhow = { version = "1.0.75", features = ["backtrace"] } lazy_static = "1.4.0" bstr = "1.8.0" -bytes = "1.5.0" +bytes = "1.6.1" futures = "0.3.29" -tokio = { version = "1.34.0", features = ["full"] } +tokio = { version = "1.37.0", features = ["full"] } rusoto_core = { version = "0.48.0", default-features = false, features = ["hyper-rustls"] } rusoto_s3 = { version = "0.48.0", default-features = false, features = ["rustls"] } -nix-compat = { version = "0.1.0", path = "../../nix-compat" } +nix-compat = { version = "0.1.0", path = "../../../tvix/nix-compat" } sled = "0.34.7" fastcdc = "3.1.0" diff --git a/tvix/tools/crunch-v2/OWNERS b/users/edef/crunch-v2/OWNERS index b9bc074a8020..b9bc074a8020 100644 --- a/tvix/tools/crunch-v2/OWNERS +++ b/users/edef/crunch-v2/OWNERS diff --git a/tvix/tools/crunch-v2/build.rs b/users/edef/crunch-v2/build.rs index 25e6d0be21a4..25e6d0be21a4 100644 --- a/tvix/tools/crunch-v2/build.rs +++ b/users/edef/crunch-v2/build.rs diff --git a/users/edef/crunch-v2/default.nix b/users/edef/crunch-v2/default.nix new file mode 100644 index 000000000000..8014aa9443c8 --- /dev/null +++ b/users/edef/crunch-v2/default.nix @@ -0,0 +1,15 @@ +{ pkgs, depot, lib, ... }: + +(pkgs.callPackage ./Cargo.nix { + defaultCrateOverrides = (depot.tvix.utils.defaultCrateOverridesForPkgs pkgs) // { + crunch-v2 = prev: { + src = depot.tvix.utils.filterRustCrateSrc rec { + root = prev.src.origSrc; + extraFileset = lib.fileset.fileFilter (f: f.hasExt "proto") root; + }; + nativeBuildInputs = [ pkgs.protobuf ]; + }; + }; +}).rootCrate.build.overrideAttrs { + meta.ci.extraSteps.crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; +} diff --git a/tvix/tools/crunch-v2/protos/flatstore.proto b/users/edef/crunch-v2/protos/flatstore.proto index 2f2838fc75c2..2f2838fc75c2 100644 --- a/tvix/tools/crunch-v2/protos/flatstore.proto +++ b/users/edef/crunch-v2/protos/flatstore.proto diff --git a/tvix/tools/crunch-v2/src/bin/extract.rs b/users/edef/crunch-v2/src/bin/extract.rs index 416d201f4e04..416d201f4e04 100644 --- a/tvix/tools/crunch-v2/src/bin/extract.rs +++ b/users/edef/crunch-v2/src/bin/extract.rs diff --git a/tvix/tools/crunch-v2/src/lib.rs b/users/edef/crunch-v2/src/lib.rs index 09ea2e75d5a3..09ea2e75d5a3 100644 --- a/tvix/tools/crunch-v2/src/lib.rs +++ b/users/edef/crunch-v2/src/lib.rs diff --git a/tvix/tools/crunch-v2/src/main.rs b/users/edef/crunch-v2/src/main.rs index a5d538f6beac..5be8c28e293f 100644 --- a/tvix/tools/crunch-v2/src/main.rs +++ b/users/edef/crunch-v2/src/main.rs @@ -147,7 +147,7 @@ fn ingest(node: nar::Node, name: Vec<u8>, avg_chunk_size: u32) -> Result<proto:: let mut symlinks = vec![]; while let Some(node) = reader.next()? { - match ingest(node.node, node.name, avg_chunk_size)? { + match ingest(node.node, node.name.to_owned(), avg_chunk_size)? { proto::path::Node::Directory(node) => { directories.push(node); } diff --git a/tvix/tools/crunch-v2/src/remote.rs b/users/edef/crunch-v2/src/remote.rs index 93952ecd737f..93952ecd737f 100644 --- a/tvix/tools/crunch-v2/src/remote.rs +++ b/users/edef/crunch-v2/src/remote.rs diff --git a/users/edef/fetchroots/.gitignore b/users/edef/fetchroots/.gitignore new file mode 100644 index 000000000000..01c40520240c --- /dev/null +++ b/users/edef/fetchroots/.gitignore @@ -0,0 +1,2 @@ +/target +/roots.parquet diff --git a/users/edef/fetchroots/Cargo.lock b/users/edef/fetchroots/Cargo.lock new file mode 100644 index 000000000000..1229b886e4e8 --- /dev/null +++ b/users/edef/fetchroots/Cargo.lock @@ -0,0 +1,3340 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +dependencies = [ + "backtrace", +] + +[[package]] +name = "argminmax" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "202108b46429b765ef483f8a24d5c46f48c14acfdacc086dd4ab6dddf6bcdbd2" +dependencies = [ + "num-traits", +] + +[[package]] +name = "array-init-cursor" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7d0a018de4f6aa429b9d33d69edf69072b1c5b1cb8d3e4a5f7ef898fc3eb76" + +[[package]] +name = "arrow-format" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07884ea216994cdc32a2d5f8274a8bee979cfe90274b83f86f440866ee3132c7" +dependencies = [ + "planus", + "serde", +] + +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "async-trait" +version = "0.1.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atoi_simd" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae037714f313c1353189ead58ef9eec30a8e8dc101b2622d461418fd59e28a9" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "aws-config" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3182c19847238b50b62ae0383a6dbfc14514e552eb5e307e1ea83ccf5840b8a6" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-sdk-sso", + "aws-sdk-ssooidc", + "aws-sdk-sts", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "hex", + "http 0.2.11", + "hyper", + "ring", + "time", + "tokio", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-credential-types" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5635d8707f265c773282a22abe1ecd4fbe96a8eb2f0f14c0796f8016f11a41a" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "zeroize", +] + +[[package]] +name = "aws-runtime" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f82b9ae2adfd9d6582440d0eeb394c07f74d21b4c0cc72bdb73735c9e1a9c0e" +dependencies = [ + "aws-credential-types", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "http 0.2.11", + "http-body", + "percent-encoding", + "pin-project-lite", + "tracing", + "uuid", +] + +[[package]] +name = "aws-sdk-s3" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5076637347e7d0218e61facae853110682ae58efabd2f4e2a9e530c203d5fa7b" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-checksums", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "bytes", + "http 0.2.11", + "http-body", + "once_cell", + "percent-encoding", + "regex-lite", + "tracing", + "url", +] + +[[package]] +name = "aws-sdk-sso" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca7e8097448832fcd22faf6bb227e97d76b40e354509d1307653a885811c7151" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.11", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-ssooidc" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75073590e23d63044606771afae309fada8eb10ded54a1ce4598347221d3fef" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.11", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-sts" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650e4aaae41547151dea4d8142f7ffcc8ab8ba76d5dccc8933936ef2102c3356" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-query", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "http 0.2.11", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sigv4" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404c64a104188ac70dd1684718765cb5559795458e446480e41984e68e57d888" +dependencies = [ + "aws-credential-types", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "crypto-bigint 0.5.5", + "form_urlencoded", + "hex", + "hmac", + "http 0.2.11", + "http 1.0.0", + "once_cell", + "p256", + "percent-encoding", + "ring", + "sha2", + "subtle", + "time", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-async" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf7f09a27286d84315dfb9346208abb3b0973a692454ae6d0bc8d803fcce3b4" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "aws-smithy-checksums" +version = "0.60.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fd4b66f2a8e7c84d7e97bda2666273d41d2a2e25302605bcf906b7b2661ae5e" +dependencies = [ + "aws-smithy-http", + "aws-smithy-types", + "bytes", + "crc32c", + "crc32fast", + "hex", + "http 0.2.11", + "http-body", + "md-5", + "pin-project-lite", + "sha1", + "sha2", + "tracing", +] + +[[package]] +name = "aws-smithy-eventstream" +version = "0.60.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6363078f927f612b970edf9d1903ef5cef9a64d1e8423525ebb1f0a1633c858" +dependencies = [ + "aws-smithy-types", + "bytes", + "crc32fast", +] + +[[package]] +name = "aws-smithy-http" +version = "0.60.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6ca214a6a26f1b7ebd63aa8d4f5e2194095643023f9608edf99a58247b9d80d" +dependencies = [ + "aws-smithy-eventstream", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.11", + "http-body", + "once_cell", + "percent-encoding", + "pin-project-lite", + "pin-utils", + "tracing", +] + +[[package]] +name = "aws-smithy-json" +version = "0.60.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1af80ecf3057fb25fe38d1687e94c4601a7817c6a1e87c1b0635f7ecb644ace5" +dependencies = [ + "aws-smithy-types", +] + +[[package]] +name = "aws-smithy-query" +version = "0.60.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb27084f72ea5fc20033efe180618677ff4a2f474b53d84695cfe310a6526cbc" +dependencies = [ + "aws-smithy-types", + "urlencoding", +] + +[[package]] +name = "aws-smithy-runtime" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbb5fca54a532a36ff927fbd7407a7c8eb9c3b4faf72792ba2965ea2cad8ed55" +dependencies = [ + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "fastrand", + "h2", + "http 0.2.11", + "http-body", + "hyper", + "hyper-rustls", + "once_cell", + "pin-project-lite", + "pin-utils", + "rustls", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-runtime-api" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22389cb6f7cac64f266fb9f137745a9349ced7b47e0d2ba503e9e40ede4f7060" +dependencies = [ + "aws-smithy-async", + "aws-smithy-types", + "bytes", + "http 0.2.11", + "http 1.0.0", + "pin-project-lite", + "tokio", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-types" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f081da5481210523d44ffd83d9f0740320050054006c719eae0232d411f024d3" +dependencies = [ + "base64-simd", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.11", + "http-body", + "itoa", + "num-integer", + "pin-project-lite", + "pin-utils", + "ryu", + "serde", + "time", + "tokio", + "tokio-util", +] + +[[package]] +name = "aws-smithy-xml" +version = "0.60.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fccd8f595d0ca839f9f2548e66b99514a85f92feb4c01cf2868d93eb4888a42" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "aws-types" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fbb5d48aae496f628e7aa2e41991dd4074f606d9e3ade1ce1059f293d40f9a2" +dependencies = [ + "aws-credential-types", + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "http 0.2.11", + "rustc_version", + "tracing", +] + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "brotli" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bstr" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" + +[[package]] +name = "bytemuck" +version = "1.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + +[[package]] +name = "bytes-utils" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" +dependencies = [ + "bytes", + "either", +] + +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "cc" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.3", +] + +[[package]] +name = "comfy-table" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" +dependencies = [ + "crossterm", + "strum", + "strum_macros", + "unicode-width", +] + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32c" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89254598aa9b9fa608de44b3ae54c810f0f06d755e24c50177f1f8f31ff50ce2" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +dependencies = [ + "crossbeam-utils", +] + +[[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-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +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 = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.6.0", + "crossterm_winapi", + "libc", + "parking_lot", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der 0.6.1", + "elliptic-curve", + "rfc6979", + "signature 1.6.4", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8 0.10.2", + "signature 2.2.0", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2", + "subtle", + "zeroize", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest", + "ff", + "generic-array", + "group", + "pkcs8 0.9.0", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "enum-primitive-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c" +dependencies = [ + "num-traits", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "ethnum" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "fast-float" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c" + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fetchroots" +version = "0.0.0" +dependencies = [ + "anyhow", + "aws-config", + "aws-sdk-s3", + "bytes", + "bytes-utils", + "bzip2", + "chrono", + "futures", + "indicatif", + "nix-compat", + "polars", + "rayon", + "tokio", + "xz2", +] + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee1b05cbd864bcaecbd3455d6d967862d446e4ebfc3c2e5e5b9841e53cba6673" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.11", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", + "rayon", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.11", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http 0.2.11", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.11", + "hyper", + "log", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "js-sys" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +dependencies = [ + "wasm-bindgen", +] + +[[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.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libmimalloc-sys" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "lz4" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +dependencies = [ + "libc", + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "lzma-sys" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +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 = "mimalloc" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "multiversion" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2c7b9d7fe61760ce5ea19532ead98541f6b4c495d87247aff9826445cf6872a" +dependencies = [ + "multiversion-macros", + "target-features", +] + +[[package]] +name = "multiversion-macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26a83d8500ed06d68877e9de1dde76c1dbb83885dcdbda4ef44ccbc3fbda2ac8" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "target-features", +] + +[[package]] +name = "nix-compat" +version = "0.1.0" +dependencies = [ + "bitflags 2.6.0", + "bstr", + "bytes", + "data-encoding", + "ed25519", + "ed25519-dalek", + "enum-primitive-derive", + "glob", + "mimalloc", + "nix-compat-derive", + "nom", + "num-traits", + "pin-project-lite", + "serde", + "serde_json", + "sha2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "nix-compat-derive" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "now" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d89e9874397a1f0a52fc1f197a8effd9735223cb2390e9dcc83ac6cd02923d0" +dependencies = [ + "chrono", +] + +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "parquet-format-safe" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1131c54b167dd4e4799ce762e1ab01549ebb94d5bdd13e6ec1b467491c378e1f" +dependencies = [ + "async-trait", + "futures", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der 0.6.1", + "spki 0.6.0", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.8", + "spki 0.7.3", +] + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "planus" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1691dd09e82f428ce8d6310bd6d5da2557c82ff17694d2a32cad7242aea89f" +dependencies = [ + "array-init-cursor", +] + +[[package]] +name = "platforms" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" + +[[package]] +name = "polars" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938048fcda6a8e2ace6eb168bee1b415a92423ce51e418b853bf08fc40349b6b" +dependencies = [ + "getrandom", + "polars-core", + "polars-io", + "polars-lazy", + "polars-ops", + "polars-sql", + "polars-time", + "version_check", +] + +[[package]] +name = "polars-arrow" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce68a02f698ff7787c261aea1b4c040a8fe183a8fb200e2436d7f35d95a1b86f" +dependencies = [ + "ahash", + "arrow-format", + "atoi_simd", + "bytemuck", + "chrono", + "dyn-clone", + "either", + "ethnum", + "fast-float", + "foreign_vec", + "futures", + "getrandom", + "hashbrown", + "itoa", + "lz4", + "multiversion", + "num-traits", + "polars-error", + "polars-utils", + "ryu", + "simdutf8", + "streaming-iterator", + "strength_reduce", + "version_check", + "zstd", +] + +[[package]] +name = "polars-compute" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b14fbc5f141b29b656a4cec4802632e5bff10bf801c6809c6bbfbd4078a044dd" +dependencies = [ + "bytemuck", + "num-traits", + "polars-arrow", + "polars-utils", + "version_check", +] + +[[package]] +name = "polars-core" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f5efe734b6cbe5f97ea769be8360df5324fade396f1f3f5ad7fe9360ca4a23" +dependencies = [ + "ahash", + "bitflags 2.6.0", + "bytemuck", + "chrono", + "comfy-table", + "either", + "hashbrown", + "indexmap", + "num-traits", + "once_cell", + "polars-arrow", + "polars-compute", + "polars-error", + "polars-row", + "polars-utils", + "rand", + "rand_distr", + "rayon", + "regex", + "smartstring", + "thiserror", + "version_check", + "xxhash-rust", +] + +[[package]] +name = "polars-error" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6396de788f99ebfc9968e7b6f523e23000506cde4ba6dfc62ae4ce949002a886" +dependencies = [ + "arrow-format", + "regex", + "simdutf8", + "thiserror", +] + +[[package]] +name = "polars-io" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d0458efe8946f4718fd352f230c0db5a37926bd0d2bd25af79dc24746abaaea" +dependencies = [ + "ahash", + "async-trait", + "atoi_simd", + "bytes", + "chrono", + "fast-float", + "futures", + "home", + "itoa", + "memchr", + "memmap2", + "num-traits", + "once_cell", + "percent-encoding", + "polars-arrow", + "polars-core", + "polars-error", + "polars-parquet", + "polars-time", + "polars-utils", + "rayon", + "regex", + "ryu", + "simdutf8", + "smartstring", + "tokio", + "tokio-util", +] + +[[package]] +name = "polars-lazy" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d7105b40905bb38e8fc4a7fd736594b7491baa12fad3ac492969ca221a1b5d5" +dependencies = [ + "ahash", + "bitflags 2.6.0", + "glob", + "once_cell", + "polars-arrow", + "polars-core", + "polars-io", + "polars-ops", + "polars-pipe", + "polars-plan", + "polars-time", + "polars-utils", + "rayon", + "smartstring", + "version_check", +] + +[[package]] +name = "polars-ops" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e09afc456ab11e75e5dcb43e00a01c71f3a46a2781e450054acb6bb096ca78e" +dependencies = [ + "ahash", + "argminmax", + "bytemuck", + "either", + "hashbrown", + "indexmap", + "memchr", + "num-traits", + "polars-arrow", + "polars-compute", + "polars-core", + "polars-error", + "polars-utils", + "rayon", + "regex", + "smartstring", + "version_check", +] + +[[package]] +name = "polars-parquet" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba24d67b1f64ab85143033dd46fa090b13c0f74acdf91b0780c16aecf005e3d" +dependencies = [ + "ahash", + "async-stream", + "base64", + "brotli", + "ethnum", + "flate2", + "futures", + "lz4", + "num-traits", + "parquet-format-safe", + "polars-arrow", + "polars-error", + "polars-utils", + "seq-macro", + "simdutf8", + "snap", + "streaming-decompression", + "zstd", +] + +[[package]] +name = "polars-pipe" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b7ead073cc3917027d77b59861a9f071db47125de9314f8907db1a0a3e4100" +dependencies = [ + "crossbeam-channel", + "crossbeam-queue", + "enum_dispatch", + "hashbrown", + "num-traits", + "polars-arrow", + "polars-compute", + "polars-core", + "polars-io", + "polars-ops", + "polars-plan", + "polars-row", + "polars-utils", + "rayon", + "smartstring", + "version_check", +] + +[[package]] +name = "polars-plan" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384a175624d050c31c473ee11df9d7af5d729ae626375e522158cfb3d150acd0" +dependencies = [ + "ahash", + "bytemuck", + "once_cell", + "percent-encoding", + "polars-arrow", + "polars-core", + "polars-io", + "polars-ops", + "polars-parquet", + "polars-time", + "polars-utils", + "rayon", + "regex", + "smartstring", + "strum_macros", + "version_check", +] + +[[package]] +name = "polars-row" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32322f7acbb83db3e9c7697dc821be73d06238da89c817dcc8bc1549a5e9c72f" +dependencies = [ + "polars-arrow", + "polars-error", + "polars-utils", +] + +[[package]] +name = "polars-sql" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f0b4c6ddffdfd0453e84bc3918572c633014d661d166654399cf93752aa95b5" +dependencies = [ + "polars-arrow", + "polars-core", + "polars-error", + "polars-lazy", + "polars-plan", + "rand", + "serde", + "serde_json", + "sqlparser", +] + +[[package]] +name = "polars-time" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee2649fc96bd1b6584e0e4a4b3ca7d22ed3d117a990e63ad438ecb26f7544d0" +dependencies = [ + "atoi", + "chrono", + "now", + "once_cell", + "polars-arrow", + "polars-core", + "polars-error", + "polars-ops", + "polars-utils", + "regex", + "smartstring", +] + +[[package]] +name = "polars-utils" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b174ca4a77ad47d7b91a0460aaae65bbf874c8bfbaaa5308675dadef3976bbda" +dependencies = [ + "ahash", + "bytemuck", + "hashbrown", + "indexmap", + "num-traits", + "once_cell", + "polars-error", + "rayon", + "smartstring", + "sysinfo", + "version_check", +] + +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_distr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +dependencies = [ + "num-traits", + "rand", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-lite" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint 0.4.9", + "hmac", + "zeroize", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der 0.6.1", + "generic-array", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "seq-macro" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core", +] + +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" + +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg", + "static_assertions", + "version_check", +] + +[[package]] +name = "snap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der 0.6.1", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der 0.7.8", +] + +[[package]] +name = "sqlparser" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743b4dc2cbde11890ccb254a8fc9d537fa41b36da00de2a1c5e9848c9bc42bd7" +dependencies = [ + "log", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "streaming-decompression" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf6cc3b19bfb128a8ad11026086e31d3ce9ad23f8ea37354b31383a187c44cf3" +dependencies = [ + "fallible-streaming-iterator", +] + +[[package]] +name = "streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" + +[[package]] +name = "strength_reduce" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.79", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sysinfo" +version = "0.30.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb4f3438c8f6389c864e61221cbc97e9bca98b4daf39a5beb7bea660f528bb2" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "windows", +] + +[[package]] +name = "target-features" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfb5fa503293557c5158bd215fdc225695e567a77e453f5d4452a50a193969bd" + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "uuid" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[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 = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets 0.52.3", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.3", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.3", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f" +dependencies = [ + "windows_aarch64_gnullvm 0.52.3", + "windows_aarch64_msvc 0.52.3", + "windows_i686_gnu 0.52.3", + "windows_i686_msvc 0.52.3", + "windows_x86_64_gnu 0.52.3", + "windows_x86_64_gnullvm 0.52.3", + "windows_x86_64_msvc 0.52.3", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" + +[[package]] +name = "xmlparser" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" + +[[package]] +name = "xxhash-rust" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" + +[[package]] +name = "xz2" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" +dependencies = [ + "lzma-sys", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" + +[[package]] +name = "zstd" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/users/edef/fetchroots/Cargo.nix b/users/edef/fetchroots/Cargo.nix new file mode 100644 index 000000000000..f45fc85d6e55 --- /dev/null +++ b/users/edef/fetchroots/Cargo.nix @@ -0,0 +1,12617 @@ +# This file was @generated by crate2nix 0.14.1 with the command: +# "generate" "--all-features" +# See https://github.com/kolloch/crate2nix for more info. + +{ nixpkgs ? <nixpkgs> +, pkgs ? import nixpkgs { config = { }; } +, lib ? pkgs.lib +, stdenv ? pkgs.stdenv +, buildRustCrateForPkgs ? pkgs: pkgs.buildRustCrate + # This is used as the `crateOverrides` argument for `buildRustCrate`. +, defaultCrateOverrides ? pkgs.defaultCrateOverrides + # The features to enable for the root_crate or the workspace_members. +, rootFeatures ? [ "default" ] + # If true, throw errors instead of issueing deprecation warnings. +, strictDeprecation ? false + # Elements to add to the `-C target-feature=` argument passed to `rustc` + # (separated by `,`, prefixed with `+`). + # Used for conditional compilation based on CPU feature detection. +, targetFeatures ? [ ] + # Whether to perform release builds: longer compile times, faster binaries. +, release ? true + # Additional crate2nix configuration if it exists. +, crateConfig ? if builtins.pathExists ./crate-config.nix + then pkgs.callPackage ./crate-config.nix { } + else { } +}: + +rec { + # + # "public" attributes that we attempt to keep stable with new versions of crate2nix. + # + + rootCrate = rec { + packageId = "fetchroots"; + + # Use this attribute to refer to the derivation building your root crate package. + # You can override the features with rootCrate.build.override { features = [ "default" "feature1" ... ]; }. + build = internal.buildRustCrateWithFeatures { + inherit packageId; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + # Refer your crate build derivation by name here. + # You can override the features with + # workspaceMembers."${crateName}".build.override { features = [ "default" "feature1" ... ]; }. + workspaceMembers = { + "fetchroots" = rec { + packageId = "fetchroots"; + build = internal.buildRustCrateWithFeatures { + packageId = "fetchroots"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + }; + + # A derivation that joins the outputs of all workspace members together. + allWorkspaceMembers = pkgs.symlinkJoin { + name = "all-workspace-members"; + paths = + let members = builtins.attrValues workspaceMembers; + in builtins.map (m: m.build) members; + }; + + # + # "internal" ("private") attributes that may change in every new version of crate2nix. + # + + internal = rec { + # Build and dependency information for crates. + # Many of the fields are passed one-to-one to buildRustCrate. + # + # Noteworthy: + # * `dependencies`/`buildDependencies`: similar to the corresponding fields for buildRustCrate. + # but with additional information which is used during dependency/feature resolution. + # * `resolvedDependencies`: the selected default features reported by cargo - only included for debugging. + # * `devDependencies` as of now not used by `buildRustCrate` but used to + # inject test dependencies into the build + + crates = { + "addr2line" = rec { + crateName = "addr2line"; + version = "0.21.0"; + edition = "2018"; + sha256 = "1jx0k3iwyqr8klqbzk6kjvr496yd94aspis10vwsj5wy7gib4c4a"; + dependencies = [ + { + name = "gimli"; + packageId = "gimli"; + usesDefaultFeatures = false; + features = [ "read" ]; + } + ]; + features = { + "alloc" = [ "dep:alloc" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "cpp_demangle" = [ "dep:cpp_demangle" ]; + "default" = [ "rustc-demangle" "cpp_demangle" "std-object" "fallible-iterator" "smallvec" "memmap2" ]; + "fallible-iterator" = [ "dep:fallible-iterator" ]; + "memmap2" = [ "dep:memmap2" ]; + "object" = [ "dep:object" ]; + "rustc-demangle" = [ "dep:rustc-demangle" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "gimli/rustc-dep-of-std" ]; + "smallvec" = [ "dep:smallvec" ]; + "std" = [ "gimli/std" ]; + "std-object" = [ "std" "object" "object/std" "object/compression" "gimli/endian-reader" ]; + }; + }; + "adler" = rec { + crateName = "adler"; + version = "1.0.2"; + edition = "2015"; + sha256 = "1zim79cvzd5yrkzl3nyfx0avijwgk9fqv3yrscdy1cc79ih02qpj"; + authors = [ + "Jonas Schievink <jonasschievink@gmail.com>" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "std" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + }; + }; + "ahash" = rec { + crateName = "ahash"; + version = "0.8.9"; + edition = "2018"; + sha256 = "17y8qags59458pxppikwr46y7qkn28y5c9fmsh257f3n9n1v64yp"; + authors = [ + "Tom Kaitchuck <Tom.Kaitchuck@gmail.com>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "getrandom"; + packageId = "getrandom"; + optional = true; + } + { + name = "once_cell"; + packageId = "once_cell"; + usesDefaultFeatures = false; + target = { target, features }: (!(("arm" == target."arch" or null) && ("none" == target."os" or null))); + features = [ "alloc" ]; + } + { + name = "zerocopy"; + packageId = "zerocopy"; + usesDefaultFeatures = false; + features = [ "simd" ]; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "atomic-polyfill" = [ "dep:atomic-polyfill" "once_cell/atomic-polyfill" ]; + "compile-time-rng" = [ "const-random" ]; + "const-random" = [ "dep:const-random" ]; + "default" = [ "std" "runtime-rng" ]; + "getrandom" = [ "dep:getrandom" ]; + "runtime-rng" = [ "getrandom" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "getrandom" "runtime-rng" "std" ]; + }; + "aho-corasick" = rec { + crateName = "aho-corasick"; + version = "1.1.2"; + edition = "2021"; + sha256 = "1w510wnixvlgimkx1zjbvlxh6xps2vjgfqgwf5a6adlbjp5rv5mj"; + libName = "aho_corasick"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "memchr"; + packageId = "memchr"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" "perf-literal" ]; + "logging" = [ "dep:log" ]; + "perf-literal" = [ "dep:memchr" ]; + "std" = [ "memchr?/std" ]; + }; + resolvedDefaultFeatures = [ "perf-literal" "std" ]; + }; + "alloc-no-stdlib" = rec { + crateName = "alloc-no-stdlib"; + version = "2.0.4"; + edition = "2015"; + crateBin = [ ]; + sha256 = "1cy6r2sfv5y5cigv86vms7n5nlwhx1rbyxwcraqnmm1rxiib2yyc"; + libName = "alloc_no_stdlib"; + authors = [ + "Daniel Reiter Horn <danielrh@dropbox.com>" + ]; + features = { }; + }; + "alloc-stdlib" = rec { + crateName = "alloc-stdlib"; + version = "0.2.2"; + edition = "2015"; + crateBin = [ ]; + sha256 = "1kkfbld20ab4165p29v172h8g0wvq8i06z8vnng14whw0isq5ywl"; + libName = "alloc_stdlib"; + authors = [ + "Daniel Reiter Horn <danielrh@dropbox.com>" + ]; + dependencies = [ + { + name = "alloc-no-stdlib"; + packageId = "alloc-no-stdlib"; + } + ]; + features = { }; + }; + "allocator-api2" = rec { + crateName = "allocator-api2"; + version = "0.2.16"; + edition = "2018"; + sha256 = "1iayppgq4wqbfbfcqmsbwgamj0s65012sskfvyx07pxavk3gyhh9"; + libName = "allocator_api2"; + authors = [ + "Zakarum <zaq.dev@icloud.com>" + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" ]; + }; + "android-tzdata" = rec { + crateName = "android-tzdata"; + version = "0.1.1"; + edition = "2018"; + sha256 = "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9"; + libName = "android_tzdata"; + authors = [ + "RumovZ" + ]; + + }; + "android_system_properties" = rec { + crateName = "android_system_properties"; + version = "0.1.5"; + edition = "2018"; + sha256 = "04b3wrz12837j7mdczqd95b732gw5q7q66cv4yn4646lvccp57l1"; + authors = [ + "Nicolas Silva <nical@fastmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + + }; + "anyhow" = rec { + crateName = "anyhow"; + version = "1.0.80"; + edition = "2018"; + sha256 = "1qdlk0mbf6mycr9rxyfc0ic9n8nn5v6pgh4qf07p6qa15vjjrlss"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "backtrace"; + packageId = "backtrace"; + optional = true; + } + ]; + features = { + "backtrace" = [ "dep:backtrace" ]; + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "backtrace" "default" "std" ]; + }; + "argminmax" = rec { + crateName = "argminmax"; + version = "0.6.1"; + edition = "2021"; + sha256 = "1lnvpkvdsvdbsinhik6srx5c2j3gqkaj92iz93pnbdr9cjs0h890"; + authors = [ + "Jeroen Van Der Donckt" + ]; + dependencies = [ + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + } + ]; + features = { + "arrow" = [ "dep:arrow" ]; + "arrow2" = [ "dep:arrow2" ]; + "default" = [ "nightly_simd" "float" ]; + "half" = [ "dep:half" ]; + "ndarray" = [ "dep:ndarray" ]; + }; + resolvedDefaultFeatures = [ "float" ]; + }; + "array-init-cursor" = rec { + crateName = "array-init-cursor"; + version = "0.2.0"; + edition = "2021"; + sha256 = "0xpbqf7qkvzplpjd7f0wbcf2n1v9vygdccwxkd1amxp4il0hlzdz"; + libName = "array_init_cursor"; + + }; + "arrow-format" = rec { + crateName = "arrow-format"; + version = "0.8.1"; + edition = "2018"; + sha256 = "1irj67p6c224dzw86jr7j3z9r5zfid52gy6ml8rdqk4r2si4x207"; + libName = "arrow_format"; + authors = [ + "Jorge C. Leitao <jorgecarleitao@gmail.com>" + ]; + dependencies = [ + { + name = "planus"; + packageId = "planus"; + optional = true; + } + { + name = "serde"; + packageId = "serde"; + optional = true; + usesDefaultFeatures = false; + features = [ "derive" "std" ]; + } + ]; + features = { + "flight-data" = [ "prost" "prost-derive" ]; + "flight-service" = [ "flight-data" "tonic" ]; + "full" = [ "ipc" "flight-data" "flight-service" ]; + "ipc" = [ "planus" "serde" ]; + "planus" = [ "dep:planus" ]; + "prost" = [ "dep:prost" ]; + "prost-derive" = [ "dep:prost-derive" ]; + "serde" = [ "dep:serde" ]; + "tonic" = [ "dep:tonic" ]; + }; + resolvedDefaultFeatures = [ "default" "ipc" "planus" "serde" ]; + }; + "async-stream" = rec { + crateName = "async-stream"; + version = "0.3.5"; + edition = "2018"; + sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + libName = "async_stream"; + authors = [ + "Carl Lerche <me@carllerche.com>" + ]; + dependencies = [ + { + name = "async-stream-impl"; + packageId = "async-stream-impl"; + } + { + name = "futures-core"; + packageId = "futures-core"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + ]; + + }; + "async-stream-impl" = rec { + crateName = "async-stream-impl"; + version = "0.3.5"; + edition = "2018"; + sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; + procMacro = true; + libName = "async_stream_impl"; + authors = [ + "Carl Lerche <me@carllerche.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" "visit-mut" ]; + } + ]; + + }; + "async-trait" = rec { + crateName = "async-trait"; + version = "0.1.77"; + edition = "2021"; + sha256 = "1adf1jh2yg39rkpmqjqyr9xyd6849p0d95425i6imgbhx0syx069"; + procMacro = true; + libName = "async_trait"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" "visit-mut" ]; + } + ]; + + }; + "atoi" = rec { + crateName = "atoi"; + version = "2.0.0"; + edition = "2021"; + sha256 = "0a05h42fggmy7h0ajjv6m7z72l924i7igbx13hk9d8pyign9k3gj"; + authors = [ + "Markus Klein" + ]; + dependencies = [ + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "num-traits/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "atoi_simd" = rec { + crateName = "atoi_simd"; + version = "0.15.6"; + edition = "2018"; + sha256 = "1a98kvaqyhb1shi2c6qhvklahc7ckvpmibcy319i6g1i9xqkgq4s"; + authors = [ + "Dmitry Rodionov <gh@rdmtr.com>" + ]; + features = { + "default" = [ "std" ]; + "std" = [ "arrayvec/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "autocfg" = rec { + crateName = "autocfg"; + version = "1.1.0"; + edition = "2015"; + sha256 = "1ylp3cb47ylzabimazvbz9ms6ap784zhb6syaz6c1jqpmcmq0s6l"; + authors = [ + "Josh Stone <cuviper@gmail.com>" + ]; + + }; + "aws-config" = rec { + crateName = "aws-config"; + version = "1.1.6"; + edition = "2021"; + sha256 = "19mq81ccyg583rz30ppbabji8if1pxnklf705av512r38ycc30ii"; + libName = "aws_config"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Russell Cohen <rcoh@amazon.com>" + ]; + dependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + features = [ "test-util" ]; + } + { + name = "aws-runtime"; + packageId = "aws-runtime"; + } + { + name = "aws-sdk-sso"; + packageId = "aws-sdk-sso"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "aws-sdk-ssooidc"; + packageId = "aws-sdk-ssooidc"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "aws-sdk-sts"; + packageId = "aws-sdk-sts"; + usesDefaultFeatures = false; + } + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + } + { + name = "aws-smithy-http"; + packageId = "aws-smithy-http"; + } + { + name = "aws-smithy-json"; + packageId = "aws-smithy-json"; + } + { + name = "aws-smithy-runtime"; + packageId = "aws-smithy-runtime"; + features = [ "client" ]; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "client" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "aws-types"; + packageId = "aws-types"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "fastrand"; + packageId = "fastrand"; + } + { + name = "hex"; + packageId = "hex"; + optional = true; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "hyper"; + packageId = "hyper"; + usesDefaultFeatures = false; + } + { + name = "ring"; + packageId = "ring"; + optional = true; + } + { + name = "time"; + packageId = "time"; + features = [ "parsing" ]; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "sync" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + } + ]; + devDependencies = [ + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + features = [ "rt-tokio" "test-util" ]; + } + { + name = "aws-smithy-runtime"; + packageId = "aws-smithy-runtime"; + features = [ "client" "connector-hyper-0-14-x" "test-util" ]; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "test-util" ]; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "full" "test-util" ]; + } + ]; + features = { + "client-hyper" = [ "aws-smithy-runtime/connector-hyper-0-14-x" ]; + "credentials-process" = [ "tokio/process" ]; + "default" = [ "client-hyper" "rustls" "rt-tokio" "credentials-process" "sso" ]; + "rt-tokio" = [ "aws-smithy-async/rt-tokio" "aws-smithy-runtime/rt-tokio" "tokio/rt" ]; + "rustls" = [ "aws-smithy-runtime/tls-rustls" "client-hyper" ]; + "sso" = [ "dep:aws-sdk-sso" "dep:aws-sdk-ssooidc" "dep:ring" "dep:hex" "dep:zeroize" "aws-smithy-runtime-api/http-auth" ]; + }; + resolvedDefaultFeatures = [ "client-hyper" "credentials-process" "default" "rt-tokio" "rustls" "sso" ]; + }; + "aws-credential-types" = rec { + crateName = "aws-credential-types"; + version = "1.1.6"; + edition = "2021"; + sha256 = "06m425ph3y4n0x6g3w5jirmfkyylxkhsn8ia51rwfrgj0y3msqz5"; + libName = "aws_credential_types"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + ]; + dependencies = [ + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "client" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "zeroize"; + packageId = "zeroize"; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "test-util" ]; + }; + "aws-runtime" = rec { + crateName = "aws-runtime"; + version = "1.1.6"; + edition = "2021"; + sha256 = "03lw3ag5qwvkvcmwf32c3g978zy0jjryxl204icddnfz5apbk0kg"; + libName = "aws_runtime"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + ]; + dependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + } + { + name = "aws-sigv4"; + packageId = "aws-sigv4"; + features = [ "http0-compat" ]; + } + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + } + { + name = "aws-smithy-eventstream"; + packageId = "aws-smithy-eventstream"; + optional = true; + } + { + name = "aws-smithy-http"; + packageId = "aws-smithy-http"; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "client" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "aws-types"; + packageId = "aws-types"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "fastrand"; + packageId = "fastrand"; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "http-body"; + packageId = "http-body"; + } + { + name = "percent-encoding"; + packageId = "percent-encoding"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "uuid"; + packageId = "uuid"; + } + ]; + devDependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + features = [ "test-util" ]; + } + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + features = [ "test-util" ]; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "test-util" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + features = [ "test-util" ]; + } + ]; + features = { + "event-stream" = [ "dep:aws-smithy-eventstream" "aws-sigv4/sign-eventstream" ]; + "sigv4a" = [ "aws-sigv4/sigv4a" ]; + }; + resolvedDefaultFeatures = [ "event-stream" "http-02x" "sigv4a" ]; + }; + "aws-sdk-s3" = rec { + crateName = "aws-sdk-s3"; + version = "1.16.0"; + edition = "2021"; + sha256 = "0yzssl1w4c75m7ig9lmbxxcax0h6259yijpsc6723l778xrn6xjh"; + libName = "aws_sdk_s3"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Russell Cohen <rcoh@amazon.com>" + ]; + dependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + } + { + name = "aws-runtime"; + packageId = "aws-runtime"; + features = [ "event-stream" "http-02x" ]; + } + { + name = "aws-sigv4"; + packageId = "aws-sigv4"; + } + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + } + { + name = "aws-smithy-checksums"; + packageId = "aws-smithy-checksums"; + } + { + name = "aws-smithy-eventstream"; + packageId = "aws-smithy-eventstream"; + } + { + name = "aws-smithy-http"; + packageId = "aws-smithy-http"; + features = [ "event-stream" ]; + } + { + name = "aws-smithy-json"; + packageId = "aws-smithy-json"; + } + { + name = "aws-smithy-runtime"; + packageId = "aws-smithy-runtime"; + features = [ "client" ]; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "client" "http-02x" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "aws-smithy-xml"; + packageId = "aws-smithy-xml"; + } + { + name = "aws-types"; + packageId = "aws-types"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "http-body"; + packageId = "http-body"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "percent-encoding"; + packageId = "percent-encoding"; + } + { + name = "regex-lite"; + packageId = "regex-lite"; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "url"; + packageId = "url"; + } + ]; + devDependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + features = [ "test-util" ]; + } + { + name = "aws-runtime"; + packageId = "aws-runtime"; + features = [ "test-util" ]; + } + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + features = [ "test-util" ]; + } + { + name = "aws-smithy-runtime"; + packageId = "aws-smithy-runtime"; + features = [ "test-util" "wire-mock" "client" ]; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "test-util" "client" "http-02x" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + features = [ "test-util" ]; + } + ]; + features = { + "default" = [ "sigv4a" "rustls" "rt-tokio" ]; + "rt-tokio" = [ "aws-smithy-async/rt-tokio" "aws-smithy-types/rt-tokio" ]; + "rustls" = [ "aws-smithy-runtime/tls-rustls" ]; + "sigv4a" = [ "aws-runtime/sigv4a" ]; + "test-util" = [ "aws-credential-types/test-util" "aws-smithy-runtime/test-util" ]; + }; + resolvedDefaultFeatures = [ "default" "rt-tokio" "rustls" "sigv4a" ]; + }; + "aws-sdk-sso" = rec { + crateName = "aws-sdk-sso"; + version = "1.14.0"; + edition = "2021"; + sha256 = "0lbi3j0qba2kfqqd22a56l7b8xkxx4kv4sxg5z9gqcl88jbq0zna"; + libName = "aws_sdk_sso"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Russell Cohen <rcoh@amazon.com>" + ]; + dependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + } + { + name = "aws-runtime"; + packageId = "aws-runtime"; + } + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + } + { + name = "aws-smithy-http"; + packageId = "aws-smithy-http"; + } + { + name = "aws-smithy-json"; + packageId = "aws-smithy-json"; + } + { + name = "aws-smithy-runtime"; + packageId = "aws-smithy-runtime"; + features = [ "client" ]; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "client" "http-02x" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "aws-types"; + packageId = "aws-types"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "regex-lite"; + packageId = "regex-lite"; + } + { + name = "tracing"; + packageId = "tracing"; + } + ]; + devDependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + features = [ "test-util" ]; + } + ]; + features = { + "default" = [ "rustls" "rt-tokio" ]; + "rt-tokio" = [ "aws-smithy-async/rt-tokio" "aws-smithy-types/rt-tokio" ]; + "rustls" = [ "aws-smithy-runtime/tls-rustls" ]; + "test-util" = [ "aws-credential-types/test-util" "aws-smithy-runtime/test-util" ]; + }; + }; + "aws-sdk-ssooidc" = rec { + crateName = "aws-sdk-ssooidc"; + version = "1.14.0"; + edition = "2021"; + sha256 = "1vrz3li4g0srwhf4mmfy23msibcz62paywb7c1231mi31rcp6l57"; + libName = "aws_sdk_ssooidc"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Russell Cohen <rcoh@amazon.com>" + ]; + dependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + } + { + name = "aws-runtime"; + packageId = "aws-runtime"; + } + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + } + { + name = "aws-smithy-http"; + packageId = "aws-smithy-http"; + } + { + name = "aws-smithy-json"; + packageId = "aws-smithy-json"; + } + { + name = "aws-smithy-runtime"; + packageId = "aws-smithy-runtime"; + features = [ "client" ]; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "client" "http-02x" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "aws-types"; + packageId = "aws-types"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "regex-lite"; + packageId = "regex-lite"; + } + { + name = "tracing"; + packageId = "tracing"; + } + ]; + devDependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + features = [ "test-util" ]; + } + ]; + features = { + "default" = [ "rustls" "rt-tokio" ]; + "rt-tokio" = [ "aws-smithy-async/rt-tokio" "aws-smithy-types/rt-tokio" ]; + "rustls" = [ "aws-smithy-runtime/tls-rustls" ]; + "test-util" = [ "aws-credential-types/test-util" "aws-smithy-runtime/test-util" ]; + }; + }; + "aws-sdk-sts" = rec { + crateName = "aws-sdk-sts"; + version = "1.14.0"; + edition = "2021"; + sha256 = "0mik5h8g4vlk6f4wrp6mfsxbi2nczzvl50adx8fiaiqmwjm4l3k5"; + libName = "aws_sdk_sts"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Russell Cohen <rcoh@amazon.com>" + ]; + dependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + } + { + name = "aws-runtime"; + packageId = "aws-runtime"; + } + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + } + { + name = "aws-smithy-http"; + packageId = "aws-smithy-http"; + } + { + name = "aws-smithy-json"; + packageId = "aws-smithy-json"; + } + { + name = "aws-smithy-query"; + packageId = "aws-smithy-query"; + } + { + name = "aws-smithy-runtime"; + packageId = "aws-smithy-runtime"; + features = [ "client" ]; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "client" "http-02x" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "aws-smithy-xml"; + packageId = "aws-smithy-xml"; + } + { + name = "aws-types"; + packageId = "aws-types"; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "regex-lite"; + packageId = "regex-lite"; + } + { + name = "tracing"; + packageId = "tracing"; + } + ]; + devDependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + features = [ "test-util" ]; + } + { + name = "aws-runtime"; + packageId = "aws-runtime"; + features = [ "test-util" ]; + } + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + features = [ "test-util" ]; + } + { + name = "aws-smithy-runtime"; + packageId = "aws-smithy-runtime"; + features = [ "test-util" "wire-mock" ]; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "test-util" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + features = [ "test-util" ]; + } + ]; + features = { + "default" = [ "rustls" "rt-tokio" ]; + "rt-tokio" = [ "aws-smithy-async/rt-tokio" "aws-smithy-types/rt-tokio" ]; + "rustls" = [ "aws-smithy-runtime/tls-rustls" ]; + "test-util" = [ "aws-credential-types/test-util" "aws-smithy-runtime/test-util" ]; + }; + }; + "aws-sigv4" = rec { + crateName = "aws-sigv4"; + version = "1.1.6"; + edition = "2021"; + sha256 = "126qay7fd10rwj068i4f8narfmdmbiv1hiv8s46wg2hq0jhn8k20"; + libName = "aws_sigv4"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "David Barsky <me@davidbarsky.com>" + ]; + dependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + } + { + name = "aws-smithy-eventstream"; + packageId = "aws-smithy-eventstream"; + optional = true; + } + { + name = "aws-smithy-http"; + packageId = "aws-smithy-http"; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "client" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "crypto-bigint"; + packageId = "crypto-bigint 0.5.5"; + optional = true; + } + { + name = "form_urlencoded"; + packageId = "form_urlencoded"; + optional = true; + } + { + name = "hex"; + packageId = "hex"; + } + { + name = "hmac"; + packageId = "hmac"; + } + { + name = "http"; + packageId = "http 0.2.11"; + rename = "http0"; + optional = true; + } + { + name = "http"; + packageId = "http 1.0.0"; + optional = true; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "p256"; + packageId = "p256"; + optional = true; + features = [ "ecdsa" ]; + } + { + name = "percent-encoding"; + packageId = "percent-encoding"; + optional = true; + } + { + name = "ring"; + packageId = "ring"; + optional = true; + } + { + name = "sha2"; + packageId = "sha2"; + } + { + name = "subtle"; + packageId = "subtle"; + optional = true; + } + { + name = "time"; + packageId = "time"; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + } + ]; + devDependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + features = [ "test-util" "hardcoded-credentials" ]; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "client" "test-util" ]; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "ring"; + packageId = "ring"; + target = { target, features }: (!(("powerpc" == target."arch" or null) || ("powerpc64" == target."arch" or null))); + } + { + name = "time"; + packageId = "time"; + features = [ "parsing" ]; + } + ]; + features = { + "default" = [ "sign-http" "http1" ]; + "http0-compat" = [ "dep:http0" ]; + "http1" = [ "dep:http" ]; + "num-bigint" = [ "dep:num-bigint" ]; + "sign-eventstream" = [ "dep:aws-smithy-eventstream" ]; + "sign-http" = [ "dep:http0" "dep:percent-encoding" "dep:form_urlencoded" ]; + "sigv4a" = [ "dep:p256" "dep:crypto-bigint" "dep:subtle" "dep:zeroize" "dep:ring" ]; + }; + resolvedDefaultFeatures = [ "default" "http0-compat" "http1" "sign-eventstream" "sign-http" "sigv4a" ]; + }; + "aws-smithy-async" = rec { + crateName = "aws-smithy-async"; + version = "1.1.7"; + edition = "2021"; + sha256 = "1d73rhzq13dws3k4licjlrrhjfxvi8h4d4zvblqq8v984ydg1xzw"; + libName = "aws_smithy_async"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "John DiSanti <jdisanti@amazon.com>" + ]; + dependencies = [ + { + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "sync" ]; + } + ]; + devDependencies = [ + { + name = "tokio"; + packageId = "tokio"; + features = [ "rt" "macros" "test-util" ]; + } + ]; + features = { + "rt-tokio" = [ "tokio/time" ]; + "test-util" = [ "rt-tokio" ]; + }; + resolvedDefaultFeatures = [ "rt-tokio" ]; + }; + "aws-smithy-checksums" = rec { + crateName = "aws-smithy-checksums"; + version = "0.60.6"; + edition = "2021"; + sha256 = "0pmfc4k7nswhrxdn00jkwaid4h9x4xk2dnkvx7bq8z4f59pvdm0g"; + libName = "aws_smithy_checksums"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Zelda Hessler <zhessler@amazon.com>" + ]; + dependencies = [ + { + name = "aws-smithy-http"; + packageId = "aws-smithy-http"; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "crc32c"; + packageId = "crc32c"; + } + { + name = "crc32fast"; + packageId = "crc32fast"; + } + { + name = "hex"; + packageId = "hex"; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "http-body"; + packageId = "http-body"; + } + { + name = "md-5"; + packageId = "md-5"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "sha1"; + packageId = "sha1"; + } + { + name = "sha2"; + packageId = "sha2"; + } + { + name = "tracing"; + packageId = "tracing"; + } + ]; + + }; + "aws-smithy-eventstream" = rec { + crateName = "aws-smithy-eventstream"; + version = "0.60.4"; + edition = "2021"; + sha256 = "0n686cb0l7xvbr92710y9nkgkkpm7s8d3ygdf2wi5xi7z5w30dp6"; + libName = "aws_smithy_eventstream"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "John DiSanti <jdisanti@amazon.com>" + ]; + dependencies = [ + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "crc32fast"; + packageId = "crc32fast"; + } + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "derive-arbitrary" = [ "arbitrary" "derive_arbitrary" ]; + "derive_arbitrary" = [ "dep:derive_arbitrary" ]; + }; + }; + "aws-smithy-http" = rec { + crateName = "aws-smithy-http"; + version = "0.60.6"; + edition = "2021"; + sha256 = "03fqp53q59crvy761y9361j9ah0rwbsx9a1ssvmvgw96d9523jmn"; + libName = "aws_smithy_http"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Russell Cohen <rcoh@amazon.com>" + ]; + dependencies = [ + { + name = "aws-smithy-eventstream"; + packageId = "aws-smithy-eventstream"; + optional = true; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "client" "http-02x" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + features = [ "byte-stream-poll-next" "http-body-0-4-x" ]; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "bytes-utils"; + packageId = "bytes-utils"; + } + { + name = "futures-core"; + packageId = "futures-core"; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "http-body"; + packageId = "http-body"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "percent-encoding"; + packageId = "percent-encoding"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "pin-utils"; + packageId = "pin-utils"; + } + { + name = "tracing"; + packageId = "tracing"; + } + ]; + features = { + "aws-smithy-eventstream" = [ "dep:aws-smithy-eventstream" ]; + "event-stream" = [ "aws-smithy-eventstream" ]; + "rt-tokio" = [ "aws-smithy-types/rt-tokio" ]; + }; + resolvedDefaultFeatures = [ "aws-smithy-eventstream" "event-stream" ]; + }; + "aws-smithy-json" = rec { + crateName = "aws-smithy-json"; + version = "0.60.6"; + edition = "2021"; + sha256 = "1rdc8jvfrxrm0qdprs51qqbph6k0qja7ws6i73z2bysp637hxy0s"; + libName = "aws_smithy_json"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "John DiSanti <jdisanti@amazon.com>" + ]; + dependencies = [ + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + ]; + + }; + "aws-smithy-query" = rec { + crateName = "aws-smithy-query"; + version = "0.60.6"; + edition = "2021"; + sha256 = "1g3caak11qygjm3dhlsb8wplmzvphrhq1qgg6c0c4pzaf97hh9zb"; + libName = "aws_smithy_query"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "John DiSanti <jdisanti@amazon.com>" + ]; + dependencies = [ + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "urlencoding"; + packageId = "urlencoding"; + } + ]; + + }; + "aws-smithy-runtime" = rec { + crateName = "aws-smithy-runtime"; + version = "1.1.7"; + edition = "2021"; + sha256 = "0mgdv35a4plnl8mpjwmg9wxrrsy8lw3p9gbzjbzkcajk9ajzrdgv"; + libName = "aws_smithy_runtime"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Zelda Hessler <zhessler@amazon.com>" + ]; + dependencies = [ + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + } + { + name = "aws-smithy-http"; + packageId = "aws-smithy-http"; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + features = [ "http-body-0-4-x" ]; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "fastrand"; + packageId = "fastrand"; + } + { + name = "h2"; + packageId = "h2"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "http-body"; + packageId = "http-body"; + rename = "http-body-0-4"; + } + { + name = "hyper"; + packageId = "hyper"; + rename = "hyper-0-14"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "hyper-rustls"; + packageId = "hyper-rustls"; + optional = true; + features = [ "rustls-native-certs" "http2" ]; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "pin-utils"; + packageId = "pin-utils"; + } + { + name = "rustls"; + packageId = "rustls"; + optional = true; + } + { + name = "tokio"; + packageId = "tokio"; + } + { + name = "tracing"; + packageId = "tracing"; + } + ]; + devDependencies = [ + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + features = [ "rt-tokio" "test-util" ]; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "test-util" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + features = [ "test-util" ]; + } + { + name = "hyper"; + packageId = "hyper"; + rename = "hyper_0_14"; + features = [ "client" "server" "tcp" "http1" "http2" ]; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "macros" "rt" "rt-multi-thread" "test-util" "full" ]; + } + ]; + features = { + "client" = [ "aws-smithy-runtime-api/client" ]; + "connector-hyper-0-14-x" = [ "dep:hyper-0-14" "hyper-0-14?/client" "hyper-0-14?/http2" "hyper-0-14?/http1" "hyper-0-14?/tcp" "hyper-0-14?/stream" "dep:h2" ]; + "http-auth" = [ "aws-smithy-runtime-api/http-auth" ]; + "rt-tokio" = [ "tokio/rt" ]; + "test-util" = [ "aws-smithy-runtime-api/test-util" "dep:aws-smithy-protocol-test" "dep:tracing-subscriber" "dep:serde" "dep:serde_json" ]; + "tls-rustls" = [ "dep:hyper-rustls" "dep:rustls" "connector-hyper-0-14-x" ]; + "wire-mock" = [ "test-util" "connector-hyper-0-14-x" "hyper-0-14?/server" ]; + }; + resolvedDefaultFeatures = [ "client" "connector-hyper-0-14-x" "rt-tokio" "tls-rustls" ]; + }; + "aws-smithy-runtime-api" = rec { + crateName = "aws-smithy-runtime-api"; + version = "1.1.7"; + edition = "2021"; + sha256 = "0q3h9zg0xr790fjjn3bynkbwwjckb9s3gwdrdwk4zinayyv9qf12"; + libName = "aws_smithy_runtime_api"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Zelda Hessler <zhessler@amazon.com>" + ]; + dependencies = [ + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "http"; + packageId = "http 1.0.0"; + rename = "http1"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "sync" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + } + ]; + devDependencies = [ + { + name = "tokio"; + packageId = "tokio"; + features = [ "macros" "rt" "rt-multi-thread" ]; + } + ]; + features = { + "http-auth" = [ "dep:zeroize" ]; + "test-util" = [ "aws-smithy-types/test-util" "http-1x" ]; + }; + resolvedDefaultFeatures = [ "client" "default" "http-02x" "http-auth" ]; + }; + "aws-smithy-types" = rec { + crateName = "aws-smithy-types"; + version = "1.1.7"; + edition = "2021"; + sha256 = "1lr4y08x8ch2msg72v00ah00a803fkqdk0zx9za26191h5adm0gh"; + libName = "aws_smithy_types"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Russell Cohen <rcoh@amazon.com>" + ]; + dependencies = [ + { + name = "base64-simd"; + packageId = "base64-simd"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "bytes-utils"; + packageId = "bytes-utils"; + } + { + name = "futures-core"; + packageId = "futures-core"; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "http-body"; + packageId = "http-body"; + rename = "http-body-0-4"; + optional = true; + } + { + name = "itoa"; + packageId = "itoa"; + } + { + name = "num-integer"; + packageId = "num-integer"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "pin-utils"; + packageId = "pin-utils"; + } + { + name = "ryu"; + packageId = "ryu"; + } + { + name = "serde"; + packageId = "serde"; + target = { target, features }: (target."aws_sdk_unstable" or false); + features = [ "derive" ]; + } + { + name = "time"; + packageId = "time"; + features = [ "parsing" ]; + } + { + name = "tokio"; + packageId = "tokio"; + optional = true; + } + { + name = "tokio-util"; + packageId = "tokio-util"; + optional = true; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "macros" "rt" "rt-multi-thread" "fs" "io-util" ]; + } + ]; + features = { + "http-body-0-4-x" = [ "dep:http-body-0-4" ]; + "http-body-1-x" = [ "dep:http-body-1-0" "dep:http-body-util" "dep:http-body-0-4" "dep:http-1x" ]; + "hyper-0-14-x" = [ "dep:hyper-0-14" ]; + "rt-tokio" = [ "dep:http-body-0-4" "dep:tokio-util" "dep:tokio" "tokio?/rt" "tokio?/fs" "tokio?/io-util" "tokio-util?/io" ]; + }; + resolvedDefaultFeatures = [ "byte-stream-poll-next" "http-body-0-4-x" "rt-tokio" ]; + }; + "aws-smithy-xml" = rec { + crateName = "aws-smithy-xml"; + version = "0.60.6"; + edition = "2021"; + sha256 = "0hlai2s3xnb8537h2k7b5zwqajjik5mycj15kygq7jnhjpsxik0g"; + libName = "aws_smithy_xml"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Russell Cohen <rcoh@amazon.com>" + ]; + dependencies = [ + { + name = "xmlparser"; + packageId = "xmlparser"; + } + ]; + + }; + "aws-types" = rec { + crateName = "aws-types"; + version = "1.1.6"; + edition = "2021"; + sha256 = "18pr80yjk7q5w4fdwflydmh4y1yl3ncl2bmawwlgd5p4m945vfwg"; + libName = "aws_types"; + authors = [ + "AWS Rust SDK Team <aws-sdk-rust@amazon.com>" + "Russell Cohen <rcoh@amazon.com>" + ]; + dependencies = [ + { + name = "aws-credential-types"; + packageId = "aws-credential-types"; + } + { + name = "aws-smithy-async"; + packageId = "aws-smithy-async"; + } + { + name = "aws-smithy-runtime-api"; + packageId = "aws-smithy-runtime-api"; + features = [ "client" ]; + } + { + name = "aws-smithy-types"; + packageId = "aws-smithy-types"; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "tracing"; + packageId = "tracing"; + } + ]; + buildDependencies = [ + { + name = "rustc_version"; + packageId = "rustc_version"; + } + ]; + devDependencies = [ + { + name = "http"; + packageId = "http 0.2.11"; + } + ]; + features = { + "aws-smithy-runtime" = [ "dep:aws-smithy-runtime" ]; + "examples" = [ "dep:hyper-rustls" "aws-smithy-runtime/client" "aws-smithy-runtime/connector-hyper-0-14-x" "aws-smithy-runtime/tls-rustls" ]; + }; + }; + "backtrace" = rec { + crateName = "backtrace"; + version = "0.3.69"; + edition = "2018"; + sha256 = "0dsq23dhw4pfndkx2nsa1ml2g31idm7ss7ljxp8d57avygivg290"; + authors = [ + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "addr2line"; + packageId = "addr2line"; + usesDefaultFeatures = false; + target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); + } + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "libc"; + packageId = "libc"; + usesDefaultFeatures = false; + target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); + } + { + name = "miniz_oxide"; + packageId = "miniz_oxide"; + usesDefaultFeatures = false; + target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); + } + { + name = "object"; + packageId = "object"; + usesDefaultFeatures = false; + target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); + features = [ "read_core" "elf" "macho" "pe" "unaligned" "archive" ]; + } + { + name = "rustc-demangle"; + packageId = "rustc-demangle"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cpp_demangle" = [ "dep:cpp_demangle" ]; + "default" = [ "std" ]; + "rustc-serialize" = [ "dep:rustc-serialize" ]; + "serde" = [ "dep:serde" ]; + "serialize-rustc" = [ "rustc-serialize" ]; + "serialize-serde" = [ "serde" ]; + "verify-winapi" = [ "winapi/dbghelp" "winapi/handleapi" "winapi/libloaderapi" "winapi/memoryapi" "winapi/minwindef" "winapi/processthreadsapi" "winapi/synchapi" "winapi/tlhelp32" "winapi/winbase" "winapi/winnt" ]; + "winapi" = [ "dep:winapi" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "base16ct" = rec { + crateName = "base16ct"; + version = "0.1.1"; + edition = "2021"; + sha256 = "1klccxr7igf73wpi0x3asjd8n0xjg0v6a7vxgvfk5ybvgh1hd6il"; + authors = [ + "RustCrypto Developers" + ]; + features = { + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" ]; + }; + "base64" = rec { + crateName = "base64"; + version = "0.21.7"; + edition = "2018"; + sha256 = "0rw52yvsk75kar9wgqfwgb414kvil1gn7mqkrhn9zf1537mpsacx"; + authors = [ + "Alice Maz <alice@alicemaz.com>" + "Marshall Pierce <marshall@mpierce.org>" + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "base64-simd" = rec { + crateName = "base64-simd"; + version = "0.8.0"; + edition = "2021"; + sha256 = "15cihnjqpxy0h7llpk816czyp5z613yrvsivw9i8f5vkivkvp6ik"; + libName = "base64_simd"; + dependencies = [ + { + name = "outref"; + packageId = "outref"; + } + { + name = "vsimd"; + packageId = "vsimd"; + } + ]; + features = { + "alloc" = [ "vsimd/alloc" ]; + "default" = [ "std" "detect" ]; + "detect" = [ "vsimd/detect" ]; + "std" = [ "alloc" "vsimd/std" ]; + "unstable" = [ "vsimd/unstable" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "detect" "std" ]; + }; + "base64ct" = rec { + crateName = "base64ct"; + version = "1.6.0"; + edition = "2021"; + sha256 = "0nvdba4jb8aikv60az40x2w1y96sjdq8z3yp09rwzmkhiwv1lg4c"; + authors = [ + "RustCrypto Developers" + ]; + features = { + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" ]; + }; + "bitflags 1.3.2" = rec { + crateName = "bitflags"; + version = "1.3.2"; + edition = "2018"; + sha256 = "12ki6w8gn1ldq7yz9y680llwk5gmrhrzszaa17g1sbrw2r2qvwxy"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "bitflags 2.6.0" = rec { + crateName = "bitflags"; + version = "2.6.0"; + edition = "2021"; + sha256 = "1pkidwzn3hnxlsl8zizh0bncgbjnw7c41cx7bby26ncbzmiznj5h"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "bytemuck" = [ "dep:bytemuck" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + "serde" = [ "dep:serde" ]; + }; + }; + "block-buffer" = rec { + crateName = "block-buffer"; + version = "0.10.4"; + edition = "2018"; + sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "generic-array"; + packageId = "generic-array"; + } + ]; + + }; + "brotli" = rec { + crateName = "brotli"; + version = "3.4.0"; + edition = "2015"; + crateBin = [ ]; + sha256 = "03qhcq09a6f8y4gm0bmsn7jrq5804cwpkcx3fyay1g7lgsj78q2i"; + authors = [ + "Daniel Reiter Horn <danielrh@dropbox.com>" + "The Brotli Authors" + ]; + dependencies = [ + { + name = "alloc-no-stdlib"; + packageId = "alloc-no-stdlib"; + } + { + name = "alloc-stdlib"; + packageId = "alloc-stdlib"; + optional = true; + } + { + name = "brotli-decompressor"; + packageId = "brotli-decompressor"; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc-stdlib" = [ "dep:alloc-stdlib" ]; + "benchmark" = [ "brotli-decompressor/benchmark" ]; + "default" = [ "std" "ffi-api" ]; + "disable-timer" = [ "brotli-decompressor/disable-timer" ]; + "seccomp" = [ "brotli-decompressor/seccomp" ]; + "sha2" = [ "dep:sha2" ]; + "std" = [ "alloc-stdlib" "brotli-decompressor/std" ]; + "validation" = [ "sha2" ]; + }; + resolvedDefaultFeatures = [ "alloc-stdlib" "default" "ffi-api" "std" ]; + }; + "brotli-decompressor" = rec { + crateName = "brotli-decompressor"; + version = "2.5.1"; + edition = "2015"; + crateBin = [ ]; + sha256 = "0kyyh9701dwqzwvn2frff4ww0zibikqd1s1xvl7n1pfpc3z4lbjf"; + libName = "brotli_decompressor"; + authors = [ + "Daniel Reiter Horn <danielrh@dropbox.com>" + "The Brotli Authors" + ]; + dependencies = [ + { + name = "alloc-no-stdlib"; + packageId = "alloc-no-stdlib"; + } + { + name = "alloc-stdlib"; + packageId = "alloc-stdlib"; + optional = true; + } + ]; + features = { + "alloc-stdlib" = [ "dep:alloc-stdlib" ]; + "default" = [ "std" ]; + "std" = [ "alloc-stdlib" ]; + "unsafe" = [ "alloc-no-stdlib/unsafe" "alloc-stdlib/unsafe" ]; + }; + resolvedDefaultFeatures = [ "alloc-stdlib" "std" ]; + }; + "bstr" = rec { + crateName = "bstr"; + version = "1.10.0"; + edition = "2021"; + sha256 = "036wwrchd5gq3q4k6w1j2bfl2bk2ff8c0dsa9y7w7aw7nf7knwj0"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + { + name = "regex-automata"; + packageId = "regex-automata"; + optional = true; + usesDefaultFeatures = false; + features = [ "dfa-search" ]; + } + { + name = "serde"; + packageId = "serde"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "memchr/alloc" "serde?/alloc" ]; + "default" = [ "std" "unicode" ]; + "serde" = [ "dep:serde" ]; + "std" = [ "alloc" "memchr/std" "serde?/std" ]; + "unicode" = [ "dep:regex-automata" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "serde" "std" "unicode" ]; + }; + "bumpalo" = rec { + crateName = "bumpalo"; + version = "3.15.3"; + edition = "2021"; + sha256 = "0nsm985rzdcnx8lmy9px1179f8yc8jarg5n8aw8jldmvf6m898cf"; + authors = [ + "Nick Fitzgerald <fitzgen@gmail.com>" + ]; + features = { + "allocator-api2" = [ "dep:allocator-api2" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "bytemuck" = rec { + crateName = "bytemuck"; + version = "1.14.3"; + edition = "2018"; + sha256 = "17xpdkrnw7vcc72cfnmbs6x1pndrh5naj86rkdb4h6k90m7h7vx2"; + authors = [ + "Lokathor <zefria@gmail.com>" + ]; + dependencies = [ + { + name = "bytemuck_derive"; + packageId = "bytemuck_derive"; + optional = true; + } + ]; + features = { + "bytemuck_derive" = [ "dep:bytemuck_derive" ]; + "derive" = [ "bytemuck_derive" ]; + "extern_crate_std" = [ "extern_crate_alloc" ]; + }; + resolvedDefaultFeatures = [ "bytemuck_derive" "derive" "extern_crate_alloc" ]; + }; + "bytemuck_derive" = rec { + crateName = "bytemuck_derive"; + version = "1.5.0"; + edition = "2018"; + sha256 = "1cgj75df2v32l4fmvnp25xxkkz4lp6hz76f7hfhd55wgbzmvfnln"; + procMacro = true; + authors = [ + "Lokathor <zefria@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + } + ]; + + }; + "bytes" = rec { + crateName = "bytes"; + version = "1.7.2"; + edition = "2018"; + sha256 = "1wzs7l57iwqmrszdpr2mmqf1b1hgvpxafc30imxhnry0zfl9m3a2"; + authors = [ + "Carl Lerche <me@carllerche.com>" + "Sean McArthur <sean@seanmonstar.com>" + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "bytes-utils" = rec { + crateName = "bytes-utils"; + version = "0.1.4"; + edition = "2021"; + sha256 = "0dcd0lxfpj367j9nwm7izj4mkib3slg61rg4wqmpw0kvfnlf7bvx"; + libName = "bytes_utils"; + authors = [ + "Michal 'vorner' Vaner <vorner@vorner.cz>" + ]; + dependencies = [ + { + name = "bytes"; + packageId = "bytes"; + usesDefaultFeatures = false; + } + { + name = "either"; + packageId = "either"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" "bytes/serde" ]; + "std" = [ "bytes/default" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "bzip2" = rec { + crateName = "bzip2"; + version = "0.4.4"; + edition = "2015"; + sha256 = "1y27wgqkx3k2jmh4k26vra2kqjq1qc1asww8hac3cv1zxyk1dcdx"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "bzip2-sys"; + packageId = "bzip2-sys"; + } + { + name = "libc"; + packageId = "libc"; + } + ]; + features = { + "futures" = [ "dep:futures" ]; + "static" = [ "bzip2-sys/static" ]; + "tokio" = [ "tokio-io" "futures" ]; + "tokio-io" = [ "dep:tokio-io" ]; + }; + }; + "bzip2-sys" = rec { + crateName = "bzip2-sys"; + version = "0.1.11+1.0.8"; + edition = "2015"; + links = "bzip2"; + sha256 = "1p2crnv8d8gpz5c2vlvzl0j55i3yqg5bi0kwsl1531x77xgraskk"; + libName = "bzip2_sys"; + libPath = "lib.rs"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + { + name = "pkg-config"; + packageId = "pkg-config"; + } + ]; + features = { }; + }; + "cc" = rec { + crateName = "cc"; + version = "1.0.88"; + edition = "2018"; + sha256 = "1p0w5ni5zh9464ai48i6d2lfki5af5cwwc8nwjk5b4fijg043wq2"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: (target."unix" or false); + } + ]; + features = { + "libc" = [ "dep:libc" ]; + "parallel" = [ "libc" ]; + }; + resolvedDefaultFeatures = [ "libc" "parallel" ]; + }; + "cfg-if" = rec { + crateName = "cfg-if"; + version = "1.0.0"; + edition = "2018"; + sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + }; + }; + "chrono" = rec { + crateName = "chrono"; + version = "0.4.34"; + edition = "2021"; + sha256 = "12zk0ja924f55va2fs0qj34xaygq46fy92blmc7qkmcj9dj1bh2v"; + dependencies = [ + { + name = "android-tzdata"; + packageId = "android-tzdata"; + optional = true; + target = { target, features }: ("android" == target."os" or null); + } + { + name = "iana-time-zone"; + packageId = "iana-time-zone"; + optional = true; + target = { target, features }: (target."unix" or false); + features = [ "fallback" ]; + } + { + name = "js-sys"; + packageId = "js-sys"; + optional = true; + target = { target, features }: (("wasm32" == target."arch" or null) && (!(("emscripten" == target."os" or null) || ("wasi" == target."os" or null)))); + } + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + optional = true; + target = { target, features }: (("wasm32" == target."arch" or null) && (!(("emscripten" == target."os" or null) || ("wasi" == target."os" or null)))); + } + { + name = "windows-targets"; + packageId = "windows-targets 0.52.3"; + optional = true; + target = { target, features }: (target."windows" or false); + } + ]; + features = { + "android-tzdata" = [ "dep:android-tzdata" ]; + "arbitrary" = [ "dep:arbitrary" ]; + "clock" = [ "winapi" "iana-time-zone" "android-tzdata" "now" ]; + "default" = [ "clock" "std" "oldtime" "wasmbind" ]; + "iana-time-zone" = [ "dep:iana-time-zone" ]; + "js-sys" = [ "dep:js-sys" ]; + "now" = [ "std" ]; + "pure-rust-locales" = [ "dep:pure-rust-locales" ]; + "rkyv" = [ "dep:rkyv" "rkyv/size_32" ]; + "rkyv-16" = [ "dep:rkyv" "rkyv?/size_16" ]; + "rkyv-32" = [ "dep:rkyv" "rkyv?/size_32" ]; + "rkyv-64" = [ "dep:rkyv" "rkyv?/size_64" ]; + "rkyv-validation" = [ "rkyv?/validation" ]; + "rustc-serialize" = [ "dep:rustc-serialize" ]; + "serde" = [ "dep:serde" ]; + "std" = [ "alloc" ]; + "unstable-locales" = [ "pure-rust-locales" ]; + "wasm-bindgen" = [ "dep:wasm-bindgen" ]; + "wasmbind" = [ "wasm-bindgen" "js-sys" ]; + "winapi" = [ "windows-targets" ]; + "windows-targets" = [ "dep:windows-targets" ]; + }; + resolvedDefaultFeatures = [ "alloc" "android-tzdata" "clock" "default" "iana-time-zone" "js-sys" "now" "oldtime" "std" "wasm-bindgen" "wasmbind" "winapi" "windows-targets" ]; + }; + "comfy-table" = rec { + crateName = "comfy-table"; + version = "7.1.0"; + edition = "2021"; + sha256 = "11i6sm6vznv9982hqpbrba43vfd7vv7zqzlywdc4qykvdhyh8r3w"; + libName = "comfy_table"; + authors = [ + "Arne Beer <contact@arne.beer>" + ]; + dependencies = [ + { + name = "crossterm"; + packageId = "crossterm"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: (!(target."windows" or false)); + } + { + name = "crossterm"; + packageId = "crossterm"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: (target."windows" or false); + features = [ "windows" ]; + } + { + name = "strum"; + packageId = "strum"; + } + { + name = "strum_macros"; + packageId = "strum_macros"; + } + { + name = "unicode-width"; + packageId = "unicode-width"; + } + ]; + features = { + "console" = [ "dep:console" ]; + "crossterm" = [ "dep:crossterm" ]; + "custom_styling" = [ "console" ]; + "default" = [ "tty" ]; + "reexport_crossterm" = [ "tty" ]; + "tty" = [ "crossterm" ]; + }; + resolvedDefaultFeatures = [ "crossterm" "tty" ]; + }; + "console" = rec { + crateName = "console"; + version = "0.15.8"; + edition = "2018"; + sha256 = "1sz4nl9nz8pkmapqni6py7jxzi7nzqjxzb3ya4kxvmkb0zy867qf"; + authors = [ + "Armin Ronacher <armin.ronacher@active-4.com>" + ]; + dependencies = [ + { + name = "encode_unicode"; + packageId = "encode_unicode"; + target = { target, features }: (target."windows" or false); + } + { + name = "lazy_static"; + packageId = "lazy_static"; + } + { + name = "libc"; + packageId = "libc"; + } + { + name = "unicode-width"; + packageId = "unicode-width"; + optional = true; + } + { + name = "windows-sys"; + packageId = "windows-sys"; + target = { target, features }: (target."windows" or false); + features = [ "Win32_Foundation" "Win32_System_Console" "Win32_Storage_FileSystem" "Win32_UI_Input_KeyboardAndMouse" ]; + } + ]; + features = { + "default" = [ "unicode-width" "ansi-parsing" ]; + "unicode-width" = [ "dep:unicode-width" ]; + "windows-console-colors" = [ "ansi-parsing" ]; + }; + resolvedDefaultFeatures = [ "ansi-parsing" "unicode-width" ]; + }; + "const-oid" = rec { + crateName = "const-oid"; + version = "0.9.6"; + edition = "2021"; + sha256 = "1y0jnqaq7p2wvspnx7qj76m7hjcqpz73qzvr9l2p9n2s51vr6if2"; + libName = "const_oid"; + authors = [ + "RustCrypto Developers" + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + }; + }; + "core-foundation" = rec { + crateName = "core-foundation"; + version = "0.9.4"; + edition = "2018"; + sha256 = "13zvbbj07yk3b61b8fhwfzhy35535a583irf23vlcg59j7h9bqci"; + libName = "core_foundation"; + authors = [ + "The Servo Project Developers" + ]; + dependencies = [ + { + name = "core-foundation-sys"; + packageId = "core-foundation-sys"; + usesDefaultFeatures = false; + } + { + name = "libc"; + packageId = "libc"; + } + ]; + features = { + "chrono" = [ "dep:chrono" ]; + "default" = [ "link" ]; + "link" = [ "core-foundation-sys/link" ]; + "mac_os_10_7_support" = [ "core-foundation-sys/mac_os_10_7_support" ]; + "mac_os_10_8_features" = [ "core-foundation-sys/mac_os_10_8_features" ]; + "uuid" = [ "dep:uuid" ]; + "with-chrono" = [ "chrono" ]; + "with-uuid" = [ "uuid" ]; + }; + resolvedDefaultFeatures = [ "default" "link" ]; + }; + "core-foundation-sys" = rec { + crateName = "core-foundation-sys"; + version = "0.8.6"; + edition = "2018"; + sha256 = "13w6sdf06r0hn7bx2b45zxsg1mm2phz34jikm6xc5qrbr6djpsh6"; + libName = "core_foundation_sys"; + authors = [ + "The Servo Project Developers" + ]; + features = { + "default" = [ "link" ]; + }; + resolvedDefaultFeatures = [ "default" "link" ]; + }; + "cpufeatures" = rec { + crateName = "cpufeatures"; + version = "0.2.12"; + edition = "2018"; + sha256 = "012m7rrak4girqlii3jnqwrr73gv1i980q4wra5yyyhvzwk5xzjk"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-linux-android"); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (("aarch64" == target."arch" or null) && ("linux" == target."os" or null)); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (("aarch64" == target."arch" or null) && ("apple" == target."vendor" or null)); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (("loongarch64" == target."arch" or null) && ("linux" == target."os" or null)); + } + ]; + + }; + "crc32c" = rec { + crateName = "crc32c"; + version = "0.6.5"; + edition = "2018"; + sha256 = "1qhcylgz7y7ifw0wa92yfmnz1w0hr1aaxcs4vq4ad7wvmac4a9c9"; + authors = [ + "Zack Owens" + ]; + buildDependencies = [ + { + name = "rustc_version"; + packageId = "rustc_version"; + } + ]; + + }; + "crc32fast" = rec { + crateName = "crc32fast"; + version = "1.4.0"; + edition = "2015"; + sha256 = "1ahy259ypc955l5ak24hdlgllb6vm6y2pvwr6qrlyisbg255m1dk"; + authors = [ + "Sam Rijs <srijs@airpost.net>" + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "crossbeam-channel" = rec { + crateName = "crossbeam-channel"; + version = "0.5.11"; + edition = "2021"; + sha256 = "16v48qdflpw3hgdik70bhsj7hympna79q7ci47rw0mlgnxsw2v8p"; + libName = "crossbeam_channel"; + dependencies = [ + { + name = "crossbeam-utils"; + packageId = "crossbeam-utils"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "crossbeam-utils/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "crossbeam-deque" = rec { + crateName = "crossbeam-deque"; + version = "0.8.5"; + edition = "2021"; + sha256 = "03bp38ljx4wj6vvy4fbhx41q8f585zyqix6pncz1mkz93z08qgv1"; + libName = "crossbeam_deque"; + dependencies = [ + { + name = "crossbeam-epoch"; + packageId = "crossbeam-epoch"; + usesDefaultFeatures = false; + } + { + name = "crossbeam-utils"; + packageId = "crossbeam-utils"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "crossbeam-epoch/std" "crossbeam-utils/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "crossbeam-epoch" = rec { + crateName = "crossbeam-epoch"; + version = "0.9.18"; + edition = "2021"; + sha256 = "03j2np8llwf376m3fxqx859mgp9f83hj1w34153c7a9c7i5ar0jv"; + libName = "crossbeam_epoch"; + dependencies = [ + { + name = "crossbeam-utils"; + packageId = "crossbeam-utils"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "loom" = [ "loom-crate" "crossbeam-utils/loom" ]; + "loom-crate" = [ "dep:loom-crate" ]; + "nightly" = [ "crossbeam-utils/nightly" ]; + "std" = [ "alloc" "crossbeam-utils/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "std" ]; + }; + "crossbeam-queue" = rec { + crateName = "crossbeam-queue"; + version = "0.3.11"; + edition = "2021"; + sha256 = "0d8y8y3z48r9javzj67v3p2yfswd278myz1j9vzc4sp7snslc0yz"; + libName = "crossbeam_queue"; + dependencies = [ + { + name = "crossbeam-utils"; + packageId = "crossbeam-utils"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "nightly" = [ "crossbeam-utils/nightly" ]; + "std" = [ "alloc" "crossbeam-utils/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "crossbeam-utils" = rec { + crateName = "crossbeam-utils"; + version = "0.8.19"; + edition = "2021"; + sha256 = "0iakrb1b8fjqrag7wphl94d10irhbh2fw1g444xslsywqyn3p3i4"; + libName = "crossbeam_utils"; + features = { + "default" = [ "std" ]; + "loom" = [ "dep:loom" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "crossterm" = rec { + crateName = "crossterm"; + version = "0.27.0"; + edition = "2021"; + sha256 = "1pr413ki440xgddlmkrc4j1bfx1h8rpmll87zn8ykja1bm2gwxpl"; + authors = [ + "T. Post" + ]; + dependencies = [ + { + name = "bitflags"; + packageId = "bitflags 2.6.0"; + } + { + name = "crossterm_winapi"; + packageId = "crossterm_winapi"; + optional = true; + target = { target, features }: (target."windows" or false); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "parking_lot"; + packageId = "parking_lot"; + } + { + name = "winapi"; + packageId = "winapi"; + optional = true; + target = { target, features }: (target."windows" or false); + features = [ "winuser" "winerror" ]; + } + ]; + features = { + "default" = [ "bracketed-paste" "windows" "events" ]; + "event-stream" = [ "dep:futures-core" "events" ]; + "events" = [ "dep:mio" "dep:signal-hook" "dep:signal-hook-mio" ]; + "filedescriptor" = [ "dep:filedescriptor" ]; + "serde" = [ "dep:serde" "bitflags/serde" ]; + "use-dev-tty" = [ "filedescriptor" ]; + "windows" = [ "dep:winapi" "dep:crossterm_winapi" ]; + }; + resolvedDefaultFeatures = [ "windows" ]; + }; + "crossterm_winapi" = rec { + crateName = "crossterm_winapi"; + version = "0.9.1"; + edition = "2018"; + sha256 = "0axbfb2ykbwbpf1hmxwpawwfs8wvmkcka5m561l7yp36ldi7rpdc"; + authors = [ + "T. Post" + ]; + dependencies = [ + { + name = "winapi"; + packageId = "winapi"; + target = { target, features }: (target."windows" or false); + features = [ "winbase" "consoleapi" "processenv" "handleapi" "synchapi" "impl-default" ]; + } + ]; + + }; + "crypto-bigint 0.4.9" = rec { + crateName = "crypto-bigint"; + version = "0.4.9"; + edition = "2021"; + sha256 = "1vqprgj0aj1340w186zyspi58397ih78jsc0iydvhs6zrlilnazg"; + libName = "crypto_bigint"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "generic-array"; + packageId = "generic-array"; + optional = true; + } + { + name = "rand_core"; + packageId = "rand_core"; + optional = true; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "rand_core"; + packageId = "rand_core"; + features = [ "std" ]; + } + ]; + features = { + "default" = [ "rand" ]; + "der" = [ "dep:der" ]; + "generic-array" = [ "dep:generic-array" ]; + "rand" = [ "rand_core/std" ]; + "rand_core" = [ "dep:rand_core" ]; + "rlp" = [ "dep:rlp" ]; + "serde" = [ "serdect" ]; + "serdect" = [ "dep:serdect" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "generic-array" "rand_core" "zeroize" ]; + }; + "crypto-bigint 0.5.5" = rec { + crateName = "crypto-bigint"; + version = "0.5.5"; + edition = "2021"; + sha256 = "0xmbdff3g6ii5sbxjxc31xfkv9lrmyril4arh3dzckd4gjsjzj8d"; + libName = "crypto_bigint"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "rand_core"; + packageId = "rand_core"; + optional = true; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "rand_core"; + packageId = "rand_core"; + features = [ "std" ]; + } + ]; + features = { + "alloc" = [ "serdect?/alloc" ]; + "default" = [ "rand" ]; + "der" = [ "dep:der" ]; + "generic-array" = [ "dep:generic-array" ]; + "rand" = [ "rand_core/std" ]; + "rand_core" = [ "dep:rand_core" ]; + "rlp" = [ "dep:rlp" ]; + "serde" = [ "dep:serdect" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "default" "rand" "rand_core" ]; + }; + "crypto-common" = rec { + crateName = "crypto-common"; + version = "0.1.6"; + edition = "2018"; + sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "generic-array"; + packageId = "generic-array"; + features = [ "more_lengths" ]; + } + { + name = "typenum"; + packageId = "typenum"; + } + ]; + features = { + "getrandom" = [ "rand_core/getrandom" ]; + "rand_core" = [ "dep:rand_core" ]; + }; + resolvedDefaultFeatures = [ "std" ]; + }; + "curve25519-dalek" = rec { + crateName = "curve25519-dalek"; + version = "4.1.2"; + edition = "2021"; + sha256 = "0j7kqchcgycs4a11gvlda93h9w2jr05nn4hjpfyh2kn94a4pnrqa"; + libName = "curve25519_dalek"; + authors = [ + "Isis Lovecruft <isis@patternsinthevoid.net>" + "Henry de Valence <hdevalence@hdevalence.ca>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "cpufeatures"; + packageId = "cpufeatures"; + target = { target, features }: ("x86_64" == target."arch" or null); + } + { + name = "curve25519-dalek-derive"; + packageId = "curve25519-dalek-derive"; + target = { target, features }: ((!("fiat" == target."curve25519_dalek_backend" or null)) && (!("serial" == target."curve25519_dalek_backend" or null)) && ("x86_64" == target."arch" or null)); + } + { + name = "digest"; + packageId = "digest"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "fiat-crypto"; + packageId = "fiat-crypto"; + usesDefaultFeatures = false; + target = { target, features }: ("fiat" == target."curve25519_dalek_backend" or null); + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + usesDefaultFeatures = false; + } + ]; + buildDependencies = [ + { + name = "platforms"; + packageId = "platforms"; + } + { + name = "rustc_version"; + packageId = "rustc_version"; + } + ]; + features = { + "alloc" = [ "zeroize?/alloc" ]; + "default" = [ "alloc" "precomputed-tables" "zeroize" ]; + "digest" = [ "dep:digest" ]; + "ff" = [ "dep:ff" ]; + "group" = [ "dep:group" "rand_core" ]; + "group-bits" = [ "group" "ff/bits" ]; + "rand_core" = [ "dep:rand_core" ]; + "serde" = [ "dep:serde" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "alloc" "digest" "precomputed-tables" "zeroize" ]; + }; + "curve25519-dalek-derive" = rec { + crateName = "curve25519-dalek-derive"; + version = "0.1.1"; + edition = "2021"; + sha256 = "1cry71xxrr0mcy5my3fb502cwfxy6822k4pm19cwrilrg7hq4s7l"; + procMacro = true; + libName = "curve25519_dalek_derive"; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" ]; + } + ]; + + }; + "data-encoding" = rec { + crateName = "data-encoding"; + version = "2.6.0"; + edition = "2018"; + sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; + authors = [ + "Julien Cretin <git@ia0.eu>" + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "der 0.6.1" = rec { + crateName = "der"; + version = "0.6.1"; + edition = "2021"; + sha256 = "1pnl3y52m1s6srxpfrfbazf6qilzq8fgksk5dv79nxaybjk6g97i"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "const-oid"; + packageId = "const-oid"; + optional = true; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + usesDefaultFeatures = false; + features = [ "alloc" ]; + } + ]; + features = { + "const-oid" = [ "dep:const-oid" ]; + "der_derive" = [ "dep:der_derive" ]; + "derive" = [ "der_derive" ]; + "flagset" = [ "dep:flagset" ]; + "oid" = [ "const-oid" ]; + "pem" = [ "alloc" "pem-rfc7468/alloc" "zeroize" ]; + "pem-rfc7468" = [ "dep:pem-rfc7468" ]; + "std" = [ "alloc" ]; + "time" = [ "dep:time" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "alloc" "const-oid" "oid" "zeroize" ]; + }; + "der 0.7.8" = rec { + crateName = "der"; + version = "0.7.8"; + edition = "2021"; + sha256 = "070bwiyr80800h31c5zd96ckkgagfjgnrrdmz3dzg2lccsd3dypz"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "const-oid"; + packageId = "const-oid"; + optional = true; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "zeroize?/alloc" ]; + "arbitrary" = [ "dep:arbitrary" "const-oid?/arbitrary" "std" ]; + "bytes" = [ "dep:bytes" "alloc" ]; + "derive" = [ "dep:der_derive" ]; + "flagset" = [ "dep:flagset" ]; + "oid" = [ "dep:const-oid" ]; + "pem" = [ "dep:pem-rfc7468" "alloc" "zeroize" ]; + "std" = [ "alloc" ]; + "time" = [ "dep:time" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "alloc" "oid" "std" "zeroize" ]; + }; + "deranged" = rec { + crateName = "deranged"; + version = "0.3.11"; + edition = "2021"; + sha256 = "1d1ibqqnr5qdrpw8rclwrf1myn3wf0dygl04idf4j2s49ah6yaxl"; + authors = [ + "Jacob Pratt <jacob@jhpratt.dev>" + ]; + dependencies = [ + { + name = "powerfmt"; + packageId = "powerfmt"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "num" = [ "dep:num-traits" ]; + "powerfmt" = [ "dep:powerfmt" ]; + "quickcheck" = [ "dep:quickcheck" "alloc" ]; + "rand" = [ "dep:rand" ]; + "serde" = [ "dep:serde" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "powerfmt" "std" ]; + }; + "digest" = rec { + crateName = "digest"; + version = "0.10.7"; + edition = "2018"; + sha256 = "14p2n6ih29x81akj097lvz7wi9b6b9hvls0lwrv7b6xwyy0s5ncy"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "block-buffer"; + packageId = "block-buffer"; + optional = true; + } + { + name = "crypto-common"; + packageId = "crypto-common"; + } + { + name = "subtle"; + packageId = "subtle"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "blobby" = [ "dep:blobby" ]; + "block-buffer" = [ "dep:block-buffer" ]; + "const-oid" = [ "dep:const-oid" ]; + "core-api" = [ "block-buffer" ]; + "default" = [ "core-api" ]; + "dev" = [ "blobby" ]; + "mac" = [ "subtle" ]; + "oid" = [ "const-oid" ]; + "rand_core" = [ "crypto-common/rand_core" ]; + "std" = [ "alloc" "crypto-common/std" ]; + "subtle" = [ "dep:subtle" ]; + }; + resolvedDefaultFeatures = [ "alloc" "block-buffer" "core-api" "default" "mac" "std" "subtle" ]; + }; + "dyn-clone" = rec { + crateName = "dyn-clone"; + version = "1.0.17"; + edition = "2018"; + sha256 = "09cig7dgg6jnqa10p4233nd8wllbjf4ffsw7wj0m4lwa5w3z0vhd"; + libName = "dyn_clone"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + + }; + "ecdsa" = rec { + crateName = "ecdsa"; + version = "0.14.8"; + edition = "2021"; + sha256 = "0p1wxap2s6jm06y2w3cal8dkz6p9223ir9wws70rgx8h929h2cs1"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "der"; + packageId = "der 0.6.1"; + optional = true; + } + { + name = "elliptic-curve"; + packageId = "elliptic-curve"; + usesDefaultFeatures = false; + features = [ "digest" "sec1" ]; + } + { + name = "rfc6979"; + packageId = "rfc6979"; + optional = true; + } + { + name = "signature"; + packageId = "signature 1.6.4"; + usesDefaultFeatures = false; + features = [ "hazmat-preview" "rand-preview" ]; + } + ]; + devDependencies = [ + { + name = "elliptic-curve"; + packageId = "elliptic-curve"; + usesDefaultFeatures = false; + features = [ "dev" ]; + } + ]; + features = { + "arithmetic" = [ "elliptic-curve/arithmetic" ]; + "default" = [ "digest" ]; + "der" = [ "dep:der" ]; + "dev" = [ "arithmetic" "digest" "elliptic-curve/dev" "hazmat" ]; + "digest" = [ "signature/digest-preview" ]; + "pem" = [ "elliptic-curve/pem" "pkcs8" ]; + "pkcs8" = [ "elliptic-curve/pkcs8" "der" ]; + "rfc6979" = [ "dep:rfc6979" ]; + "serde" = [ "elliptic-curve/serde" "serdect" ]; + "serdect" = [ "dep:serdect" ]; + "sign" = [ "arithmetic" "digest" "hazmat" "rfc6979" ]; + "std" = [ "alloc" "elliptic-curve/std" "signature/std" ]; + "verify" = [ "arithmetic" "digest" "hazmat" ]; + }; + resolvedDefaultFeatures = [ "alloc" "arithmetic" "der" "digest" "hazmat" "pkcs8" "rfc6979" "sign" "std" "verify" ]; + }; + "ed25519" = rec { + crateName = "ed25519"; + version = "2.2.3"; + edition = "2021"; + sha256 = "0lydzdf26zbn82g7xfczcac9d7mzm3qgx934ijjrd5hjpjx32m8i"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "pkcs8"; + packageId = "pkcs8 0.10.2"; + optional = true; + } + { + name = "signature"; + packageId = "signature 2.2.0"; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "pkcs8?/alloc" ]; + "default" = [ "std" ]; + "pem" = [ "alloc" "pkcs8/pem" ]; + "pkcs8" = [ "dep:pkcs8" ]; + "serde" = [ "dep:serde" ]; + "serde_bytes" = [ "serde" "dep:serde_bytes" ]; + "std" = [ "pkcs8?/std" "signature/std" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "ed25519-dalek" = rec { + crateName = "ed25519-dalek"; + version = "2.1.1"; + edition = "2021"; + sha256 = "0w88cafwglg9hjizldbmlza0ns3hls81zk1bcih3m5m3h67algaa"; + libName = "ed25519_dalek"; + authors = [ + "isis lovecruft <isis@patternsinthevoid.net>" + "Tony Arcieri <bascule@gmail.com>" + "Michael Rosenberg <michael@mrosenberg.pub>" + ]; + dependencies = [ + { + name = "curve25519-dalek"; + packageId = "curve25519-dalek"; + usesDefaultFeatures = false; + features = [ "digest" ]; + } + { + name = "ed25519"; + packageId = "ed25519"; + usesDefaultFeatures = false; + } + { + name = "serde"; + packageId = "serde"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "sha2"; + packageId = "sha2"; + usesDefaultFeatures = false; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "curve25519-dalek"; + packageId = "curve25519-dalek"; + usesDefaultFeatures = false; + features = [ "digest" "rand_core" ]; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + ]; + features = { + "alloc" = [ "curve25519-dalek/alloc" "ed25519/alloc" "serde?/alloc" "zeroize/alloc" ]; + "asm" = [ "sha2/asm" ]; + "batch" = [ "alloc" "merlin" "rand_core" ]; + "default" = [ "fast" "std" "zeroize" ]; + "digest" = [ "signature/digest" ]; + "fast" = [ "curve25519-dalek/precomputed-tables" ]; + "legacy_compatibility" = [ "curve25519-dalek/legacy_compatibility" ]; + "merlin" = [ "dep:merlin" ]; + "pem" = [ "alloc" "ed25519/pem" "pkcs8" ]; + "pkcs8" = [ "ed25519/pkcs8" ]; + "rand_core" = [ "dep:rand_core" ]; + "serde" = [ "dep:serde" "ed25519/serde" ]; + "signature" = [ "dep:signature" ]; + "std" = [ "alloc" "ed25519/std" "serde?/std" "sha2/std" ]; + "zeroize" = [ "dep:zeroize" "curve25519-dalek/zeroize" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "fast" "std" "zeroize" ]; + }; + "either" = rec { + crateName = "either"; + version = "1.10.0"; + edition = "2018"; + sha256 = "0jiyq2mc1aa5b8whwl1bhm11i06xxcbk9ck7macxxggzjk07l58i"; + authors = [ + "bluss" + ]; + features = { + "default" = [ "use_std" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "use_std" ]; + }; + "elliptic-curve" = rec { + crateName = "elliptic-curve"; + version = "0.12.3"; + edition = "2021"; + sha256 = "1lwi108mh6drw5nzqzlz7ighdba5qxdg5vmwwnw1j2ihnn58ifz7"; + libName = "elliptic_curve"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "base16ct"; + packageId = "base16ct"; + } + { + name = "crypto-bigint"; + packageId = "crypto-bigint 0.4.9"; + usesDefaultFeatures = false; + features = [ "rand_core" "generic-array" "zeroize" ]; + } + { + name = "der"; + packageId = "der 0.6.1"; + usesDefaultFeatures = false; + features = [ "oid" ]; + } + { + name = "digest"; + packageId = "digest"; + optional = true; + } + { + name = "ff"; + packageId = "ff"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "generic-array"; + packageId = "generic-array"; + usesDefaultFeatures = false; + } + { + name = "group"; + packageId = "group"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "pkcs8"; + packageId = "pkcs8 0.9.0"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "rand_core"; + packageId = "rand_core"; + usesDefaultFeatures = false; + } + { + name = "sec1"; + packageId = "sec1"; + optional = true; + features = [ "subtle" "zeroize" ]; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + } + { + name = "zeroize"; + packageId = "zeroize"; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "base16ct/alloc" "der/alloc" "sec1/alloc" "zeroize/alloc" ]; + "arithmetic" = [ "ff" "group" ]; + "base64ct" = [ "dep:base64ct" ]; + "bits" = [ "arithmetic" "ff/bits" ]; + "default" = [ "arithmetic" ]; + "dev" = [ "arithmetic" "hex-literal" "pem" "pkcs8" ]; + "digest" = [ "dep:digest" ]; + "ecdh" = [ "arithmetic" "digest" "hkdf" ]; + "ff" = [ "dep:ff" ]; + "group" = [ "dep:group" ]; + "hash2curve" = [ "arithmetic" "digest" ]; + "hex-literal" = [ "dep:hex-literal" ]; + "hkdf" = [ "dep:hkdf" ]; + "jwk" = [ "alloc" "base64ct/alloc" "serde" "serde_json" "zeroize/alloc" ]; + "pem" = [ "alloc" "arithmetic" "der/pem" "pem-rfc7468/alloc" "pkcs8" "sec1/pem" ]; + "pem-rfc7468" = [ "dep:pem-rfc7468" ]; + "pkcs8" = [ "dep:pkcs8" ]; + "sec1" = [ "dep:sec1" ]; + "serde" = [ "alloc" "pkcs8" "sec1/serde" "serdect" ]; + "serde_json" = [ "dep:serde_json" ]; + "serdect" = [ "dep:serdect" ]; + "std" = [ "alloc" "rand_core/std" ]; + "voprf" = [ "digest" ]; + }; + resolvedDefaultFeatures = [ "alloc" "arithmetic" "digest" "ff" "group" "hazmat" "pkcs8" "sec1" "std" ]; + }; + "encode_unicode" = rec { + crateName = "encode_unicode"; + version = "0.3.6"; + edition = "2015"; + sha256 = "07w3vzrhxh9lpjgsg2y5bwzfar2aq35mdznvcp3zjl0ssj7d4mx3"; + authors = [ + "Torbjørn Birch Moltu <t.b.moltu@lyse.net>" + ]; + features = { + "ascii" = [ "dep:ascii" ]; + "clippy" = [ "dep:clippy" ]; + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "enum-primitive-derive" = rec { + crateName = "enum-primitive-derive"; + version = "0.3.0"; + edition = "2018"; + sha256 = "0k6wcf58h5kh64yq5nfq71va53kaya0kzxwsjwbgwm2n2zd9axxs"; + procMacro = true; + libName = "enum_primitive_derive"; + authors = [ + "Doug Goldstein <cardoe@cardoe.com>" + ]; + dependencies = [ + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + } + ]; + + }; + "enum_dispatch" = rec { + crateName = "enum_dispatch"; + version = "0.3.12"; + edition = "2018"; + sha256 = "03l998igqfzkykmj8i5qlbwhv2id9jn98fkkl82lv3dvg0q32cwg"; + procMacro = true; + authors = [ + "Anton Lazarev <https://antonok.com>" + ]; + dependencies = [ + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" ]; + } + ]; + + }; + "equivalent" = rec { + crateName = "equivalent"; + version = "1.0.1"; + edition = "2015"; + sha256 = "1malmx5f4lkfvqasz319lq6gb3ddg19yzf9s8cykfsgzdmyq0hsl"; + + }; + "ethnum" = rec { + crateName = "ethnum"; + version = "1.5.0"; + edition = "2021"; + sha256 = "0b68ngvisb0d40vc6h30zlhghbb3mc8wlxjbf8gnmavk1dca435r"; + authors = [ + "Nicholas Rodrigues Lordello <nlordell@gmail.com>" + ]; + features = { + "ethnum-intrinsics" = [ "dep:ethnum-intrinsics" ]; + "llvm-intrinsics" = [ "ethnum-intrinsics" ]; + "serde" = [ "dep:serde" ]; + }; + }; + "fallible-streaming-iterator" = rec { + crateName = "fallible-streaming-iterator"; + version = "0.1.9"; + edition = "2015"; + sha256 = "0nj6j26p71bjy8h42x6jahx1hn0ng6mc2miwpgwnp8vnwqf4jq3k"; + libName = "fallible_streaming_iterator"; + authors = [ + "Steven Fackler <sfackler@gmail.com>" + ]; + features = { }; + }; + "fast-float" = rec { + crateName = "fast-float"; + version = "0.2.0"; + edition = "2018"; + sha256 = "0g7kfll3xyh99kc7r352lhljnwvgayxxa6saifb6725inikmyxlm"; + libName = "fast_float"; + authors = [ + "Ivan Smirnov <i.s.smirnov@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "fastrand" = rec { + crateName = "fastrand"; + version = "2.0.1"; + edition = "2018"; + sha256 = "19flpv5zbzpf0rk4x77z4zf25in0brg8l7m304d3yrf47qvwxjr5"; + authors = [ + "Stjepan Glavina <stjepang@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + "getrandom" = [ "dep:getrandom" ]; + "js" = [ "std" "getrandom" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "fetchroots" = rec { + crateName = "fetchroots"; + version = "0.0.0"; + edition = "2021"; + crateBin = [ + { + name = "fetchroots"; + path = "src/main.rs"; + requiredFeatures = [ ]; + } + ]; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./.; }; + dependencies = [ + { + name = "anyhow"; + packageId = "anyhow"; + features = [ "backtrace" ]; + } + { + name = "aws-config"; + packageId = "aws-config"; + } + { + name = "aws-sdk-s3"; + packageId = "aws-sdk-s3"; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "bytes-utils"; + packageId = "bytes-utils"; + } + { + name = "bzip2"; + packageId = "bzip2"; + } + { + name = "chrono"; + packageId = "chrono"; + } + { + name = "futures"; + packageId = "futures"; + } + { + name = "indicatif"; + packageId = "indicatif"; + } + { + name = "nix-compat"; + packageId = "nix-compat"; + } + { + name = "polars"; + packageId = "polars"; + features = [ "parquet" ]; + } + { + name = "rayon"; + packageId = "rayon"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "full" ]; + } + { + name = "xz2"; + packageId = "xz2"; + } + ]; + + }; + "ff" = rec { + crateName = "ff"; + version = "0.12.1"; + edition = "2021"; + sha256 = "0q3imz4m3dj2cy182i20wa8kbclgj13ddfngqb2miicc6cjzq4yh"; + authors = [ + "Sean Bowe <ewillbefull@gmail.com>" + "Jack Grigg <thestr4d@gmail.com>" + ]; + dependencies = [ + { + name = "rand_core"; + packageId = "rand_core"; + usesDefaultFeatures = false; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + features = [ "i128" ]; + } + ]; + features = { + "bits" = [ "bitvec" ]; + "bitvec" = [ "dep:bitvec" ]; + "byteorder" = [ "dep:byteorder" ]; + "default" = [ "bits" "std" ]; + "derive" = [ "byteorder" "ff_derive" ]; + "derive_bits" = [ "bits" "ff_derive/bits" ]; + "ff_derive" = [ "dep:ff_derive" ]; + "std" = [ "alloc" ]; + }; + }; + "fiat-crypto" = rec { + crateName = "fiat-crypto"; + version = "0.2.6"; + edition = "2018"; + sha256 = "10hkkkjynhibvchznkxx81gwxqarn9i5sgz40d6xxb8xzhsz8xhn"; + libName = "fiat_crypto"; + authors = [ + "Fiat Crypto library authors <jgross@mit.edu>" + ]; + features = { + "default" = [ "std" ]; + }; + }; + "flate2" = rec { + crateName = "flate2"; + version = "1.0.28"; + edition = "2018"; + sha256 = "03llhsh4gqdirnfxxb9g2w9n0721dyn4yjir3pz7z4vjaxb3yc26"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + "Josh Triplett <josh@joshtriplett.org>" + ]; + dependencies = [ + { + name = "crc32fast"; + packageId = "crc32fast"; + } + { + name = "miniz_oxide"; + packageId = "miniz_oxide"; + optional = true; + usesDefaultFeatures = false; + features = [ "with-alloc" ]; + } + { + name = "miniz_oxide"; + packageId = "miniz_oxide"; + usesDefaultFeatures = false; + target = { target, features }: (("wasm32" == target."arch" or null) && (!("emscripten" == target."os" or null))); + features = [ "with-alloc" ]; + } + ]; + features = { + "any_zlib" = [ "any_impl" ]; + "cloudflare-zlib-sys" = [ "dep:cloudflare-zlib-sys" ]; + "cloudflare_zlib" = [ "any_zlib" "cloudflare-zlib-sys" ]; + "default" = [ "rust_backend" ]; + "libz-ng-sys" = [ "dep:libz-ng-sys" ]; + "libz-sys" = [ "dep:libz-sys" ]; + "miniz-sys" = [ "rust_backend" ]; + "miniz_oxide" = [ "dep:miniz_oxide" ]; + "rust_backend" = [ "miniz_oxide" "any_impl" ]; + "zlib" = [ "any_zlib" "libz-sys" ]; + "zlib-default" = [ "any_zlib" "libz-sys/default" ]; + "zlib-ng" = [ "any_zlib" "libz-ng-sys" ]; + "zlib-ng-compat" = [ "zlib" "libz-sys/zlib-ng" ]; + }; + resolvedDefaultFeatures = [ "any_impl" "miniz_oxide" "rust_backend" ]; + }; + "fnv" = rec { + crateName = "fnv"; + version = "1.0.7"; + edition = "2015"; + sha256 = "1hc2mcqha06aibcaza94vbi81j6pr9a1bbxrxjfhc91zin8yr7iz"; + libPath = "lib.rs"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "foreign_vec" = rec { + crateName = "foreign_vec"; + version = "0.1.0"; + edition = "2021"; + sha256 = "0wv6p8yfahcqbdg2wg7wxgj4dm32g2b6spa5sg5sxg34v35ha6zf"; + authors = [ + "Jorge C. Leitao <jorgecarleitao@gmail.com>" + ]; + + }; + "form_urlencoded" = rec { + crateName = "form_urlencoded"; + version = "1.2.1"; + edition = "2018"; + sha256 = "0milh8x7nl4f450s3ddhg57a3flcv6yq8hlkyk6fyr3mcb128dp1"; + authors = [ + "The rust-url developers" + ]; + dependencies = [ + { + name = "percent-encoding"; + packageId = "percent-encoding"; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "percent-encoding/alloc" ]; + "default" = [ "std" ]; + "std" = [ "alloc" "percent-encoding/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "futures" = rec { + crateName = "futures"; + version = "0.3.30"; + edition = "2018"; + sha256 = "1c04g14bccmprwsvx2j9m2blhwrynq7vhl151lsvcv4gi0b6jp34"; + dependencies = [ + { + name = "futures-channel"; + packageId = "futures-channel"; + usesDefaultFeatures = false; + features = [ "sink" ]; + } + { + name = "futures-core"; + packageId = "futures-core"; + usesDefaultFeatures = false; + } + { + name = "futures-executor"; + packageId = "futures-executor"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "futures-io"; + packageId = "futures-io"; + usesDefaultFeatures = false; + } + { + name = "futures-sink"; + packageId = "futures-sink"; + usesDefaultFeatures = false; + } + { + name = "futures-task"; + packageId = "futures-task"; + usesDefaultFeatures = false; + } + { + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; + features = [ "sink" ]; + } + ]; + features = { + "alloc" = [ "futures-core/alloc" "futures-task/alloc" "futures-sink/alloc" "futures-channel/alloc" "futures-util/alloc" ]; + "async-await" = [ "futures-util/async-await" "futures-util/async-await-macro" ]; + "bilock" = [ "futures-util/bilock" ]; + "compat" = [ "std" "futures-util/compat" ]; + "default" = [ "std" "async-await" "executor" ]; + "executor" = [ "std" "futures-executor/std" ]; + "futures-executor" = [ "dep:futures-executor" ]; + "io-compat" = [ "compat" "futures-util/io-compat" ]; + "std" = [ "alloc" "futures-core/std" "futures-task/std" "futures-io/std" "futures-sink/std" "futures-util/std" "futures-util/io" "futures-util/channel" ]; + "thread-pool" = [ "executor" "futures-executor/thread-pool" ]; + "unstable" = [ "futures-core/unstable" "futures-task/unstable" "futures-channel/unstable" "futures-io/unstable" "futures-util/unstable" ]; + "write-all-vectored" = [ "futures-util/write-all-vectored" ]; + }; + resolvedDefaultFeatures = [ "alloc" "async-await" "default" "executor" "futures-executor" "std" ]; + }; + "futures-channel" = rec { + crateName = "futures-channel"; + version = "0.3.30"; + edition = "2018"; + sha256 = "0y6b7xxqdjm9hlcjpakcg41qfl7lihf6gavk8fyqijsxhvbzgj7a"; + libName = "futures_channel"; + dependencies = [ + { + name = "futures-core"; + packageId = "futures-core"; + usesDefaultFeatures = false; + } + { + name = "futures-sink"; + packageId = "futures-sink"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "futures-core/alloc" ]; + "default" = [ "std" ]; + "futures-sink" = [ "dep:futures-sink" ]; + "sink" = [ "futures-sink" ]; + "std" = [ "alloc" "futures-core/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "futures-sink" "sink" "std" ]; + }; + "futures-core" = rec { + crateName = "futures-core"; + version = "0.3.30"; + edition = "2018"; + sha256 = "07aslayrn3lbggj54kci0ishmd1pr367fp7iks7adia1p05miinz"; + libName = "futures_core"; + features = { + "default" = [ "std" ]; + "portable-atomic" = [ "dep:portable-atomic" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "futures-executor" = rec { + crateName = "futures-executor"; + version = "0.3.30"; + edition = "2018"; + sha256 = "07dh08gs9vfll2h36kq32q9xd86xm6lyl9xikmmwlkqnmrrgqxm5"; + libName = "futures_executor"; + dependencies = [ + { + name = "futures-core"; + packageId = "futures-core"; + usesDefaultFeatures = false; + } + { + name = "futures-task"; + packageId = "futures-task"; + usesDefaultFeatures = false; + } + { + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "num_cpus" = [ "dep:num_cpus" ]; + "std" = [ "futures-core/std" "futures-task/std" "futures-util/std" ]; + "thread-pool" = [ "std" "num_cpus" ]; + }; + resolvedDefaultFeatures = [ "std" ]; + }; + "futures-io" = rec { + crateName = "futures-io"; + version = "0.3.30"; + edition = "2018"; + sha256 = "1hgh25isvsr4ybibywhr4dpys8mjnscw4wfxxwca70cn1gi26im4"; + libName = "futures_io"; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "std" ]; + }; + "futures-macro" = rec { + crateName = "futures-macro"; + version = "0.3.30"; + edition = "2018"; + sha256 = "1b49qh9d402y8nka4q6wvvj0c88qq91wbr192mdn5h54nzs0qxc7"; + procMacro = true; + libName = "futures_macro"; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" ]; + } + ]; + + }; + "futures-sink" = rec { + crateName = "futures-sink"; + version = "0.3.30"; + edition = "2018"; + sha256 = "1dag8xyyaya8n8mh8smx7x6w2dpmafg2din145v973a3hw7f1f4z"; + libName = "futures_sink"; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "futures-task" = rec { + crateName = "futures-task"; + version = "0.3.30"; + edition = "2018"; + sha256 = "013h1724454hj8qczp8vvs10qfiqrxr937qsrv6rhii68ahlzn1q"; + libName = "futures_task"; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "std" ]; + }; + "futures-util" = rec { + crateName = "futures-util"; + version = "0.3.30"; + edition = "2018"; + sha256 = "0j0xqhcir1zf2dcbpd421kgw6wvsk0rpxflylcysn1rlp3g02r1x"; + libName = "futures_util"; + dependencies = [ + { + name = "futures-channel"; + packageId = "futures-channel"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "futures-core"; + packageId = "futures-core"; + usesDefaultFeatures = false; + } + { + name = "futures-io"; + packageId = "futures-io"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "futures-macro"; + packageId = "futures-macro"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "futures-sink"; + packageId = "futures-sink"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "futures-task"; + packageId = "futures-task"; + usesDefaultFeatures = false; + } + { + name = "memchr"; + packageId = "memchr"; + optional = true; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "pin-utils"; + packageId = "pin-utils"; + } + { + name = "slab"; + packageId = "slab"; + optional = true; + } + ]; + features = { + "alloc" = [ "futures-core/alloc" "futures-task/alloc" ]; + "async-await-macro" = [ "async-await" "futures-macro" ]; + "channel" = [ "std" "futures-channel" ]; + "compat" = [ "std" "futures_01" ]; + "default" = [ "std" "async-await" "async-await-macro" ]; + "futures-channel" = [ "dep:futures-channel" ]; + "futures-io" = [ "dep:futures-io" ]; + "futures-macro" = [ "dep:futures-macro" ]; + "futures-sink" = [ "dep:futures-sink" ]; + "futures_01" = [ "dep:futures_01" ]; + "io" = [ "std" "futures-io" "memchr" ]; + "io-compat" = [ "io" "compat" "tokio-io" ]; + "memchr" = [ "dep:memchr" ]; + "portable-atomic" = [ "futures-core/portable-atomic" ]; + "sink" = [ "futures-sink" ]; + "slab" = [ "dep:slab" ]; + "std" = [ "alloc" "futures-core/std" "futures-task/std" "slab" ]; + "tokio-io" = [ "dep:tokio-io" ]; + "unstable" = [ "futures-core/unstable" "futures-task/unstable" ]; + "write-all-vectored" = [ "io" ]; + }; + resolvedDefaultFeatures = [ "alloc" "async-await" "async-await-macro" "channel" "futures-channel" "futures-io" "futures-macro" "futures-sink" "io" "memchr" "sink" "slab" "std" ]; + }; + "generic-array" = rec { + crateName = "generic-array"; + version = "0.14.7"; + edition = "2015"; + sha256 = "16lyyrzrljfq424c3n8kfwkqihlimmsg5nhshbbp48np3yjrqr45"; + libName = "generic_array"; + authors = [ + "BartÅ‚omiej KamiÅ„ski <fizyk20@gmail.com>" + "Aaron Trent <novacrazy@gmail.com>" + ]; + dependencies = [ + { + name = "typenum"; + packageId = "typenum"; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "serde" = [ "dep:serde" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "more_lengths" ]; + }; + "getrandom" = rec { + crateName = "getrandom"; + version = "0.2.12"; + edition = "2018"; + sha256 = "1d8jb9bv38nkwlqqdjcav6gxckgwc9g30pm3qq506rvncpm9400r"; + authors = [ + "The Rand Project Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "js-sys"; + packageId = "js-sys"; + optional = true; + target = { target, features }: ((("wasm32" == target."arch" or null) || ("wasm64" == target."arch" or null)) && ("unknown" == target."os" or null)); + } + { + name = "libc"; + packageId = "libc"; + usesDefaultFeatures = false; + target = { target, features }: (target."unix" or false); + } + { + name = "wasi"; + packageId = "wasi"; + usesDefaultFeatures = false; + target = { target, features }: ("wasi" == target."os" or null); + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: ((("wasm32" == target."arch" or null) || ("wasm64" == target."arch" or null)) && ("unknown" == target."os" or null)); + } + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "js" = [ "wasm-bindgen" "js-sys" ]; + "js-sys" = [ "dep:js-sys" ]; + "rustc-dep-of-std" = [ "compiler_builtins" "core" "libc/rustc-dep-of-std" "wasi/rustc-dep-of-std" ]; + "wasm-bindgen" = [ "dep:wasm-bindgen" ]; + }; + resolvedDefaultFeatures = [ "js" "js-sys" "std" "wasm-bindgen" ]; + }; + "gimli" = rec { + crateName = "gimli"; + version = "0.28.1"; + edition = "2018"; + sha256 = "0lv23wc8rxvmjia3mcxc6hj9vkqnv1bqq0h8nzjcgf71mrxx6wa2"; + features = { + "default" = [ "read-all" "write" ]; + "endian-reader" = [ "read" "dep:stable_deref_trait" ]; + "fallible-iterator" = [ "dep:fallible-iterator" ]; + "read" = [ "read-core" ]; + "read-all" = [ "read" "std" "fallible-iterator" "endian-reader" ]; + "rustc-dep-of-std" = [ "dep:core" "dep:alloc" "dep:compiler_builtins" ]; + "std" = [ "fallible-iterator?/std" "stable_deref_trait?/std" ]; + "write" = [ "dep:indexmap" ]; + }; + resolvedDefaultFeatures = [ "read" "read-core" ]; + }; + "glob" = rec { + crateName = "glob"; + version = "0.3.1"; + edition = "2015"; + sha256 = "16zca52nglanv23q5qrwd5jinw3d3as5ylya6y1pbx47vkxvrynj"; + authors = [ + "The Rust Project Developers" + ]; + + }; + "group" = rec { + crateName = "group"; + version = "0.12.1"; + edition = "2021"; + sha256 = "1ixspxqdpq0hxg0hd9s6rngrp6rll21v4jjnr7ar1lzvdhxgpysx"; + authors = [ + "Sean Bowe <ewillbefull@gmail.com>" + "Jack Grigg <jack@z.cash>" + ]; + dependencies = [ + { + name = "ff"; + packageId = "ff"; + usesDefaultFeatures = false; + } + { + name = "rand_core"; + packageId = "rand_core"; + usesDefaultFeatures = false; + } + { + name = "subtle"; + packageId = "subtle"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "alloc" ]; + "memuse" = [ "dep:memuse" ]; + "rand" = [ "dep:rand" ]; + "rand_xorshift" = [ "dep:rand_xorshift" ]; + "tests" = [ "alloc" "rand" "rand_xorshift" ]; + "wnaf-memuse" = [ "alloc" "memuse" ]; + }; + }; + "h2" = rec { + crateName = "h2"; + version = "0.3.24"; + edition = "2018"; + sha256 = "1jf9488b66nayxzp3iw3b2rb64y49hdbbywnv9wfwrsv14i48b5v"; + authors = [ + "Carl Lerche <me@carllerche.com>" + "Sean McArthur <sean@seanmonstar.com>" + ]; + dependencies = [ + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "fnv"; + packageId = "fnv"; + } + { + name = "futures-core"; + packageId = "futures-core"; + usesDefaultFeatures = false; + } + { + name = "futures-sink"; + packageId = "futures-sink"; + usesDefaultFeatures = false; + } + { + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "indexmap"; + packageId = "indexmap"; + features = [ "std" ]; + } + { + name = "slab"; + packageId = "slab"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "io-util" ]; + } + { + name = "tokio-util"; + packageId = "tokio-util"; + features = [ "codec" "io" ]; + } + { + name = "tracing"; + packageId = "tracing"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + ]; + devDependencies = [ + { + name = "tokio"; + packageId = "tokio"; + features = [ "rt-multi-thread" "macros" "sync" "net" ]; + } + ]; + features = { }; + }; + "hashbrown" = rec { + crateName = "hashbrown"; + version = "0.14.3"; + edition = "2021"; + sha256 = "012nywlg0lj9kwanh69my5x67vjlfmzfi9a0rq4qvis2j8fil3r9"; + authors = [ + "Amanieu d'Antras <amanieu@gmail.com>" + ]; + dependencies = [ + { + name = "ahash"; + packageId = "ahash"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "allocator-api2"; + packageId = "allocator-api2"; + optional = true; + usesDefaultFeatures = false; + features = [ "alloc" ]; + } + { + name = "rayon"; + packageId = "rayon"; + optional = true; + } + ]; + devDependencies = [ + { + name = "rayon"; + packageId = "rayon"; + } + ]; + features = { + "ahash" = [ "dep:ahash" ]; + "alloc" = [ "dep:alloc" ]; + "allocator-api2" = [ "dep:allocator-api2" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "ahash" "inline-more" "allocator-api2" ]; + "equivalent" = [ "dep:equivalent" ]; + "nightly" = [ "allocator-api2?/nightly" "bumpalo/allocator_api" ]; + "rayon" = [ "dep:rayon" ]; + "rkyv" = [ "dep:rkyv" ]; + "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "ahash" "allocator-api2" "default" "inline-more" "raw" "rayon" ]; + }; + "heck" = rec { + crateName = "heck"; + version = "0.4.1"; + edition = "2018"; + sha256 = "1a7mqsnycv5z4z5vnv1k34548jzmc0ajic7c1j8jsaspnhw5ql4m"; + authors = [ + "Without Boats <woboats@gmail.com>" + ]; + features = { + "unicode" = [ "unicode-segmentation" ]; + "unicode-segmentation" = [ "dep:unicode-segmentation" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "hermit-abi" = rec { + crateName = "hermit-abi"; + version = "0.3.9"; + edition = "2021"; + sha256 = "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj"; + libName = "hermit_abi"; + authors = [ + "Stefan Lankes" + ]; + features = { + "alloc" = [ "dep:alloc" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins/rustc-dep-of-std" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "hex" = rec { + crateName = "hex"; + version = "0.4.3"; + edition = "2018"; + sha256 = "0w1a4davm1lgzpamwnba907aysmlrnygbqmfis2mqjx5m552a93z"; + authors = [ + "KokaKiwi <kokakiwi@kokakiwi.net>" + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "hmac" = rec { + crateName = "hmac"; + version = "0.12.1"; + edition = "2018"; + sha256 = "0pmbr069sfg76z7wsssfk5ddcqd9ncp79fyz6zcm6yn115yc6jbc"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "digest"; + packageId = "digest"; + features = [ "mac" ]; + } + ]; + devDependencies = [ + { + name = "digest"; + packageId = "digest"; + features = [ "dev" ]; + } + ]; + features = { + "std" = [ "digest/std" ]; + }; + resolvedDefaultFeatures = [ "reset" ]; + }; + "home" = rec { + crateName = "home"; + version = "0.5.9"; + edition = "2021"; + sha256 = "19grxyg35rqfd802pcc9ys1q3lafzlcjcv2pl2s5q8xpyr5kblg3"; + authors = [ + "Brian Anderson <andersrb@gmail.com>" + ]; + dependencies = [ + { + name = "windows-sys"; + packageId = "windows-sys"; + target = { target, features }: (target."windows" or false); + features = [ "Win32_Foundation" "Win32_UI_Shell" "Win32_System_Com" ]; + } + ]; + + }; + "http 0.2.11" = rec { + crateName = "http"; + version = "0.2.11"; + edition = "2018"; + sha256 = "1fwz3mhh86h5kfnr5767jlx9agpdggclq7xsqx930fflzakb2iw9"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + "Carl Lerche <me@carllerche.com>" + "Sean McArthur <sean@seanmonstar.com>" + ]; + dependencies = [ + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "fnv"; + packageId = "fnv"; + } + { + name = "itoa"; + packageId = "itoa"; + } + ]; + + }; + "http 1.0.0" = rec { + crateName = "http"; + version = "1.0.0"; + edition = "2018"; + sha256 = "1sllw565jn8r5w7h928nsfqq33x586pyasdfr7vid01scwwgsamk"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + "Carl Lerche <me@carllerche.com>" + "Sean McArthur <sean@seanmonstar.com>" + ]; + dependencies = [ + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "fnv"; + packageId = "fnv"; + } + { + name = "itoa"; + packageId = "itoa"; + } + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "http-body" = rec { + crateName = "http-body"; + version = "0.4.6"; + edition = "2018"; + sha256 = "1lmyjfk6bqk6k9gkn1dxq770sb78pqbqshga241hr5p995bb5skw"; + libName = "http_body"; + authors = [ + "Carl Lerche <me@carllerche.com>" + "Lucio Franco <luciofranco14@gmail.com>" + "Sean McArthur <sean@seanmonstar.com>" + ]; + dependencies = [ + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + ]; + + }; + "httparse" = rec { + crateName = "httparse"; + version = "1.8.0"; + edition = "2018"; + sha256 = "010rrfahm1jss3p022fqf3j3jmm72vhn4iqhykahb9ynpaag75yq"; + authors = [ + "Sean McArthur <sean@seanmonstar.com>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "httpdate" = rec { + crateName = "httpdate"; + version = "1.0.3"; + edition = "2021"; + sha256 = "1aa9rd2sac0zhjqh24c9xvir96g188zldkx0hr6dnnlx5904cfyz"; + authors = [ + "Pyfisch <pyfisch@posteo.org>" + ]; + + }; + "hyper" = rec { + crateName = "hyper"; + version = "0.14.28"; + edition = "2018"; + sha256 = "107gkvqx4h9bl17d602zkm2dgpfq86l2dr36yzfsi8l3xcsy35mz"; + authors = [ + "Sean McArthur <sean@seanmonstar.com>" + ]; + dependencies = [ + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "futures-channel"; + packageId = "futures-channel"; + } + { + name = "futures-core"; + packageId = "futures-core"; + usesDefaultFeatures = false; + } + { + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; + } + { + name = "h2"; + packageId = "h2"; + optional = true; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "http-body"; + packageId = "http-body"; + } + { + name = "httparse"; + packageId = "httparse"; + } + { + name = "httpdate"; + packageId = "httpdate"; + } + { + name = "itoa"; + packageId = "itoa"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "socket2"; + packageId = "socket2"; + optional = true; + features = [ "all" ]; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "sync" ]; + } + { + name = "tower-service"; + packageId = "tower-service"; + } + { + name = "tracing"; + packageId = "tracing"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "want"; + packageId = "want"; + } + ]; + devDependencies = [ + { + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; + features = [ "alloc" ]; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "fs" "macros" "io-std" "io-util" "rt" "rt-multi-thread" "sync" "time" "test-util" ]; + } + ]; + features = { + "ffi" = [ "libc" ]; + "full" = [ "client" "http1" "http2" "server" "stream" "runtime" ]; + "h2" = [ "dep:h2" ]; + "http2" = [ "h2" ]; + "libc" = [ "dep:libc" ]; + "runtime" = [ "tcp" "tokio/rt" "tokio/time" ]; + "socket2" = [ "dep:socket2" ]; + "tcp" = [ "socket2" "tokio/net" "tokio/rt" "tokio/time" ]; + }; + resolvedDefaultFeatures = [ "client" "h2" "http1" "http2" "runtime" "server" "socket2" "stream" "tcp" ]; + }; + "hyper-rustls" = rec { + crateName = "hyper-rustls"; + version = "0.24.2"; + edition = "2021"; + sha256 = "1475j4a2nczz4aajzzsq3hpwg1zacmzbqg393a14j80ff8izsgpc"; + libName = "hyper_rustls"; + dependencies = [ + { + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; + } + { + name = "http"; + packageId = "http 0.2.11"; + } + { + name = "hyper"; + packageId = "hyper"; + usesDefaultFeatures = false; + features = [ "client" ]; + } + { + name = "log"; + packageId = "log"; + optional = true; + } + { + name = "rustls"; + packageId = "rustls"; + usesDefaultFeatures = false; + } + { + name = "rustls-native-certs"; + packageId = "rustls-native-certs"; + optional = true; + } + { + name = "tokio"; + packageId = "tokio"; + } + { + name = "tokio-rustls"; + packageId = "tokio-rustls"; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "hyper"; + packageId = "hyper"; + features = [ "full" ]; + } + { + name = "rustls"; + packageId = "rustls"; + usesDefaultFeatures = false; + features = [ "tls12" ]; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "io-std" "macros" "net" "rt-multi-thread" ]; + } + ]; + features = { + "acceptor" = [ "hyper/server" "tokio-runtime" ]; + "default" = [ "native-tokio" "http1" "tls12" "logging" "acceptor" ]; + "http1" = [ "hyper/http1" ]; + "http2" = [ "hyper/http2" ]; + "log" = [ "dep:log" ]; + "logging" = [ "log" "tokio-rustls/logging" "rustls/logging" ]; + "native-tokio" = [ "tokio-runtime" "rustls-native-certs" ]; + "rustls-native-certs" = [ "dep:rustls-native-certs" ]; + "tls12" = [ "tokio-rustls/tls12" "rustls/tls12" ]; + "tokio-runtime" = [ "hyper/runtime" ]; + "webpki-roots" = [ "dep:webpki-roots" ]; + "webpki-tokio" = [ "tokio-runtime" "webpki-roots" ]; + }; + resolvedDefaultFeatures = [ "acceptor" "default" "http1" "http2" "log" "logging" "native-tokio" "rustls-native-certs" "tls12" "tokio-runtime" ]; + }; + "iana-time-zone" = rec { + crateName = "iana-time-zone"; + version = "0.1.60"; + edition = "2018"; + sha256 = "0hdid5xz3jznm04lysjm3vi93h3c523w0hcc3xba47jl3ddbpzz7"; + libName = "iana_time_zone"; + authors = [ + "Andrew Straw <strawman@astraw.com>" + "René Kijewski <rene.kijewski@fu-berlin.de>" + "Ryan Lopopolo <rjl@hyperbo.la>" + ]; + dependencies = [ + { + name = "android_system_properties"; + packageId = "android_system_properties"; + target = { target, features }: ("android" == target."os" or null); + } + { + name = "core-foundation-sys"; + packageId = "core-foundation-sys"; + target = { target, features }: (("macos" == target."os" or null) || ("ios" == target."os" or null)); + } + { + name = "iana-time-zone-haiku"; + packageId = "iana-time-zone-haiku"; + target = { target, features }: ("haiku" == target."os" or null); + } + { + name = "js-sys"; + packageId = "js-sys"; + target = { target, features }: ("wasm32" == target."arch" or null); + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + target = { target, features }: ("wasm32" == target."arch" or null); + } + { + name = "windows-core"; + packageId = "windows-core"; + target = { target, features }: ("windows" == target."os" or null); + } + ]; + features = { }; + resolvedDefaultFeatures = [ "fallback" ]; + }; + "iana-time-zone-haiku" = rec { + crateName = "iana-time-zone-haiku"; + version = "0.1.2"; + edition = "2018"; + sha256 = "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k"; + libName = "iana_time_zone_haiku"; + authors = [ + "René Kijewski <crates.io@k6i.de>" + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + + }; + "idna" = rec { + crateName = "idna"; + version = "0.5.0"; + edition = "2018"; + sha256 = "1xhjrcjqq0l5bpzvdgylvpkgk94panxgsirzhjnnqfdgc4a9nkb3"; + authors = [ + "The rust-url developers" + ]; + dependencies = [ + { + name = "unicode-bidi"; + packageId = "unicode-bidi"; + usesDefaultFeatures = false; + features = [ "hardcoded-data" ]; + } + { + name = "unicode-normalization"; + packageId = "unicode-normalization"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" "unicode-bidi/std" "unicode-normalization/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "indexmap" = rec { + crateName = "indexmap"; + version = "2.2.3"; + edition = "2021"; + sha256 = "0xy1wcad2da199f6y0mwmx9scw7glgs1n2g4m8nfln7hcf8g6g13"; + dependencies = [ + { + name = "equivalent"; + packageId = "equivalent"; + usesDefaultFeatures = false; + } + { + name = "hashbrown"; + packageId = "hashbrown"; + usesDefaultFeatures = false; + features = [ "raw" ]; + } + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "default" = [ "std" ]; + "quickcheck" = [ "dep:quickcheck" ]; + "rayon" = [ "dep:rayon" ]; + "rustc-rayon" = [ "dep:rustc-rayon" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "indicatif" = rec { + crateName = "indicatif"; + version = "0.17.8"; + edition = "2021"; + sha256 = "18xyqxw9i5x4sbpzckhfz3nm984iq9r7nbi2lk76nz888n7mlfkn"; + dependencies = [ + { + name = "console"; + packageId = "console"; + usesDefaultFeatures = false; + features = [ "ansi-parsing" ]; + } + { + name = "instant"; + packageId = "instant"; + target = { target, features }: ("wasm32" == target."arch" or null); + } + { + name = "number_prefix"; + packageId = "number_prefix"; + } + { + name = "portable-atomic"; + packageId = "portable-atomic"; + } + { + name = "unicode-width"; + packageId = "unicode-width"; + optional = true; + } + ]; + features = { + "default" = [ "unicode-width" "console/unicode-width" ]; + "futures" = [ "dep:futures-core" ]; + "improved_unicode" = [ "unicode-segmentation" "unicode-width" "console/unicode-width" ]; + "in_memory" = [ "vt100" ]; + "rayon" = [ "dep:rayon" ]; + "tokio" = [ "dep:tokio" ]; + "unicode-segmentation" = [ "dep:unicode-segmentation" ]; + "unicode-width" = [ "dep:unicode-width" ]; + "vt100" = [ "dep:vt100" ]; + }; + resolvedDefaultFeatures = [ "default" "unicode-width" ]; + }; + "instant" = rec { + crateName = "instant"; + version = "0.1.12"; + edition = "2018"; + sha256 = "0b2bx5qdlwayriidhrag8vhy10kdfimfhmb3jnjmsz2h9j1bwnvs"; + authors = [ + "sebcrozet <developer@crozet.re>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + ]; + features = { + "js-sys" = [ "dep:js-sys" ]; + "stdweb" = [ "dep:stdweb" ]; + "wasm-bindgen" = [ "js-sys" "wasm-bindgen_rs" "web-sys" ]; + "wasm-bindgen_rs" = [ "dep:wasm-bindgen_rs" ]; + "web-sys" = [ "dep:web-sys" ]; + }; + }; + "itoa" = rec { + crateName = "itoa"; + version = "1.0.10"; + edition = "2018"; + sha256 = "0k7xjfki7mnv6yzjrbnbnjllg86acmbnk4izz2jmm1hx2wd6v95i"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + features = { + "no-panic" = [ "dep:no-panic" ]; + }; + }; + "js-sys" = rec { + crateName = "js-sys"; + version = "0.3.68"; + edition = "2018"; + sha256 = "1vm98fhnhs4w6yakchi9ip7ar95900k9vkr24a21qlwd6r5xlv20"; + libName = "js_sys"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + ]; + + }; + "lazy_static" = rec { + crateName = "lazy_static"; + version = "1.4.0"; + edition = "2015"; + sha256 = "0in6ikhw8mgl33wjv6q6xfrb5b9jr16q8ygjy803fay4zcisvaz2"; + authors = [ + "Marvin Löbel <loebel.marvin@gmail.com>" + ]; + features = { + "spin" = [ "dep:spin" ]; + "spin_no_std" = [ "spin" ]; + }; + }; + "libc" = rec { + crateName = "libc"; + version = "0.2.153"; + edition = "2015"; + sha256 = "1gg7m1ils5dms5miq9fyllrcp0jxnbpgkx71chd2i0lafa8qy6cw"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "default" = [ "std" ]; + "rustc-dep-of-std" = [ "align" "rustc-std-workspace-core" ]; + "rustc-std-workspace-core" = [ "dep:rustc-std-workspace-core" ]; + "use_std" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "libm" = rec { + crateName = "libm"; + version = "0.2.8"; + edition = "2018"; + sha256 = "0n4hk1rs8pzw8hdfmwn96c4568s93kfxqgcqswr7sajd2diaihjf"; + authors = [ + "Jorge Aparicio <jorge@japaric.io>" + ]; + features = { + "musl-reference-tests" = [ "rand" ]; + "rand" = [ "dep:rand" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "libmimalloc-sys" = rec { + crateName = "libmimalloc-sys"; + version = "0.1.39"; + edition = "2018"; + links = "mimalloc"; + sha256 = "0i3b0dzz7cp0ik7ys66q92r16va78gwlbrnxhj5fnkdxsc8niai3"; + libName = "libmimalloc_sys"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cty" = [ "dep:cty" ]; + "extended" = [ "cty" ]; + }; + }; + "lock_api" = rec { + crateName = "lock_api"; + version = "0.4.11"; + edition = "2018"; + sha256 = "0iggx0h4jx63xm35861106af3jkxq06fpqhpkhgw0axi2n38y5iw"; + authors = [ + "Amanieu d'Antras <amanieu@gmail.com>" + ]; + dependencies = [ + { + name = "scopeguard"; + packageId = "scopeguard"; + usesDefaultFeatures = false; + } + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + features = { + "default" = [ "atomic_usize" ]; + "owning_ref" = [ "dep:owning_ref" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "atomic_usize" "default" ]; + }; + "log" = rec { + crateName = "log"; + version = "0.4.20"; + edition = "2015"; + sha256 = "13rf7wphnwd61vazpxr7fiycin6cb1g8fmvgqg18i464p0y1drmm"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "kv_unstable" = [ "value-bag" ]; + "kv_unstable_serde" = [ "kv_unstable_std" "value-bag/serde" "serde" ]; + "kv_unstable_std" = [ "std" "kv_unstable" "value-bag/error" ]; + "kv_unstable_sval" = [ "kv_unstable" "value-bag/sval" "sval" "sval_ref" ]; + "serde" = [ "dep:serde" ]; + "sval" = [ "dep:sval" ]; + "sval_ref" = [ "dep:sval_ref" ]; + "value-bag" = [ "dep:value-bag" ]; + }; + }; + "lz4" = rec { + crateName = "lz4"; + version = "1.24.0"; + edition = "2018"; + crateBin = [ ]; + sha256 = "1wad97k0asgvaj16ydd09gqs2yvgaanzcvqglrhffv7kdpc2v7ky"; + authors = [ + "Jens Heyens <jens.heyens@ewetel.net>" + "Artem V. Navrotskiy <bozaro@buzzsoft.ru>" + "Patrick Marks <pmarks@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + { + name = "lz4-sys"; + packageId = "lz4-sys"; + } + ]; + + }; + "lz4-sys" = rec { + crateName = "lz4-sys"; + version = "1.9.4"; + edition = "2015"; + links = "lz4"; + sha256 = "0059ik4xlvnss5qfh6l691psk4g3350ljxaykzv10yr0gqqppljp"; + libName = "lz4_sys"; + authors = [ + "Jens Heyens <jens.heyens@ewetel.net>" + "Artem V. Navrotskiy <bozaro@buzzsoft.ru>" + "Patrick Marks <pmarks@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + + }; + "lzma-sys" = rec { + crateName = "lzma-sys"; + version = "0.1.20"; + edition = "2018"; + links = "lzma"; + sha256 = "09sxp20waxyglgn3cjz8qjkspb3ryz2fwx4rigkwvrk46ymh9njz"; + libName = "lzma_sys"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + { + name = "pkg-config"; + packageId = "pkg-config"; + } + ]; + features = { }; + }; + "md-5" = rec { + crateName = "md-5"; + version = "0.10.6"; + edition = "2018"; + sha256 = "1kvq5rnpm4fzwmyv5nmnxygdhhb2369888a06gdc9pxyrzh7x7nq"; + libName = "md5"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "digest"; + packageId = "digest"; + } + ]; + devDependencies = [ + { + name = "digest"; + packageId = "digest"; + features = [ "dev" ]; + } + ]; + features = { + "asm" = [ "md5-asm" ]; + "default" = [ "std" ]; + "md5-asm" = [ "dep:md5-asm" ]; + "oid" = [ "digest/oid" ]; + "std" = [ "digest/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "memchr" = rec { + crateName = "memchr"; + version = "2.7.1"; + edition = "2021"; + sha256 = "0jf1kicqa4vs9lyzj4v4y1p90q0dh87hvhsdd5xvhnp527sw8gaj"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + "bluss" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "std" ]; + "logging" = [ "dep:log" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + "std" = [ "alloc" ]; + "use_std" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "memmap2" = rec { + crateName = "memmap2"; + version = "0.7.1"; + edition = "2018"; + sha256 = "1il82b0mw304jlwvl0m89aa8bj5dgmm3vbb0jg8lqlrk0p98i4zl"; + authors = [ + "Dan Burkert <dan@danburkert.com>" + "Yevhenii Reizner <razrfalcon@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + ]; + features = { + "stable_deref_trait" = [ "dep:stable_deref_trait" ]; + }; + }; + "mimalloc" = rec { + crateName = "mimalloc"; + version = "0.1.43"; + edition = "2018"; + sha256 = "0csnyrxc16i592gm5ffham07jyj2w98qsh9jyy1rv59lmr8474b8"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + "Vincent Rouillé <vincent@speedy37.fr>" + "Thom Chiovoloni <chiovolonit@gmail.com>" + ]; + dependencies = [ + { + name = "libmimalloc-sys"; + packageId = "libmimalloc-sys"; + usesDefaultFeatures = false; + } + ]; + features = { + "debug" = [ "libmimalloc-sys/debug" ]; + "debug_in_debug" = [ "libmimalloc-sys/debug_in_debug" ]; + "extended" = [ "libmimalloc-sys/extended" ]; + "local_dynamic_tls" = [ "libmimalloc-sys/local_dynamic_tls" ]; + "no_thp" = [ "libmimalloc-sys/no_thp" ]; + "override" = [ "libmimalloc-sys/override" ]; + "secure" = [ "libmimalloc-sys/secure" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "minimal-lexical" = rec { + crateName = "minimal-lexical"; + version = "0.2.1"; + edition = "2018"; + sha256 = "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8"; + libName = "minimal_lexical"; + authors = [ + "Alex Huszagh <ahuszagh@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "std" ]; + }; + "miniz_oxide" = rec { + crateName = "miniz_oxide"; + version = "0.7.2"; + edition = "2018"; + sha256 = "19qlxb21s6kabgqq61mk7kd1qk2invyygj076jz6i1gj2lz1z0cx"; + authors = [ + "Frommi <daniil.liferenko@gmail.com>" + "oyvindln <oyvindln@users.noreply.github.com>" + ]; + dependencies = [ + { + name = "adler"; + packageId = "adler"; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "dep:alloc" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "with-alloc" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler/rustc-dep-of-std" ]; + "simd" = [ "simd-adler32" ]; + "simd-adler32" = [ "dep:simd-adler32" ]; + }; + resolvedDefaultFeatures = [ "with-alloc" ]; + }; + "mio" = rec { + crateName = "mio"; + version = "1.0.2"; + edition = "2021"; + sha256 = "1v1cnnn44awxbcfm4zlavwgkvbyg7gp5zzjm8mqf1apkrwflvq40"; + authors = [ + "Carl Lerche <me@carllerche.com>" + "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "hermit-abi"; + packageId = "hermit-abi"; + rename = "libc"; + target = { target, features }: ("hermit" == target."os" or null); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: ("wasi" == target."os" or null); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "wasi"; + packageId = "wasi"; + target = { target, features }: ("wasi" == target."os" or null); + } + { + name = "windows-sys"; + packageId = "windows-sys"; + target = { target, features }: (target."windows" or false); + features = [ "Wdk_Foundation" "Wdk_Storage_FileSystem" "Wdk_System_IO" "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; + } + ]; + features = { + "default" = [ "log" ]; + "log" = [ "dep:log" ]; + "os-ext" = [ "os-poll" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_Security" ]; + }; + resolvedDefaultFeatures = [ "net" "os-ext" "os-poll" ]; + }; + "multiversion" = rec { + crateName = "multiversion"; + version = "0.7.3"; + edition = "2021"; + sha256 = "0al7yrf489lqzxx291sx9566n7slk2njwlqrxbjhqxk1zvbvkixj"; + authors = [ + "Caleb Zulawski <caleb.zulawski@gmail.com>" + ]; + dependencies = [ + { + name = "multiversion-macros"; + packageId = "multiversion-macros"; + usesDefaultFeatures = false; + } + { + name = "target-features"; + packageId = "target-features"; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "multiversion-macros/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "multiversion-macros" = rec { + crateName = "multiversion-macros"; + version = "0.7.3"; + edition = "2021"; + sha256 = "1j1avbxw7jscyi7dmnywhlwbiny1fvg1vpp9fy4dc1pd022kva16"; + procMacro = true; + libName = "multiversion_macros"; + authors = [ + "Caleb Zulawski <caleb.zulawski@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 1.0.109"; + features = [ "full" "extra-traits" "visit-mut" ]; + } + { + name = "target-features"; + packageId = "target-features"; + } + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "std" ]; + }; + "nix-compat" = rec { + crateName = "nix-compat"; + version = "0.1.0"; + edition = "2021"; + crateBin = [ ]; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat; }; + libName = "nix_compat"; + dependencies = [ + { + name = "bitflags"; + packageId = "bitflags 2.6.0"; + } + { + name = "bstr"; + packageId = "bstr"; + features = [ "alloc" "unicode" "serde" ]; + } + { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { + name = "data-encoding"; + packageId = "data-encoding"; + } + { + name = "ed25519"; + packageId = "ed25519"; + } + { + name = "ed25519-dalek"; + packageId = "ed25519-dalek"; + } + { + name = "enum-primitive-derive"; + packageId = "enum-primitive-derive"; + } + { + name = "glob"; + packageId = "glob"; + } + { + name = "mimalloc"; + packageId = "mimalloc"; + } + { + name = "nix-compat-derive"; + packageId = "nix-compat-derive"; + optional = true; + } + { + name = "nom"; + packageId = "nom"; + } + { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + optional = true; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "serde_json"; + packageId = "serde_json"; + } + { + name = "sha2"; + packageId = "sha2"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "tokio"; + packageId = "tokio"; + optional = true; + features = [ "io-util" "macros" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } + ]; + devDependencies = [ + { + name = "mimalloc"; + packageId = "mimalloc"; + } + { + name = "serde_json"; + packageId = "serde_json"; + } + ]; + features = { + "async" = [ "tokio" ]; + "bytes" = [ "dep:bytes" ]; + "default" = [ "async" "wire" "nix-compat-derive" ]; + "nix-compat-derive" = [ "dep:nix-compat-derive" ]; + "pin-project-lite" = [ "dep:pin-project-lite" ]; + "tokio" = [ "dep:tokio" ]; + "wire" = [ "tokio" "pin-project-lite" "bytes" ]; + }; + resolvedDefaultFeatures = [ "async" "bytes" "default" "nix-compat-derive" "pin-project-lite" "tokio" "wire" ]; + }; + "nix-compat-derive" = rec { + crateName = "nix-compat-derive"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat-derive; }; + procMacro = true; + libName = "nix_compat_derive"; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + features = [ "proc-macro" ]; + } + { + name = "quote"; + packageId = "quote"; + features = [ "proc-macro" ]; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" "extra-traits" ]; + } + ]; + + }; + "nom" = rec { + crateName = "nom"; + version = "7.1.3"; + edition = "2018"; + sha256 = "0jha9901wxam390jcf5pfa0qqfrgh8li787jx2ip0yk5b8y9hwyj"; + authors = [ + "contact@geoffroycouprie.com" + ]; + dependencies = [ + { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + { + name = "minimal-lexical"; + packageId = "minimal-lexical"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" "memchr/std" "minimal-lexical/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "now" = rec { + crateName = "now"; + version = "0.1.3"; + edition = "2018"; + sha256 = "1l135786rb43rjfhwfdj7hi3b5zxxyl9gwf15yjz18cp8f3yk2bd"; + authors = [ + "Kilerd <blove694@gmail.com>" + ]; + dependencies = [ + { + name = "chrono"; + packageId = "chrono"; + usesDefaultFeatures = false; + features = [ "clock" "std" ]; + } + ]; + + }; + "ntapi" = rec { + crateName = "ntapi"; + version = "0.4.1"; + edition = "2018"; + sha256 = "1r38zhbwdvkis2mzs6671cm1p6djgsl49i7bwxzrvhwicdf8k8z8"; + authors = [ + "MSxDOS <melcodos@gmail.com>" + ]; + dependencies = [ + { + name = "winapi"; + packageId = "winapi"; + features = [ "cfg" "evntrace" "in6addr" "inaddr" "minwinbase" "ntsecapi" "windef" "winioctl" ]; + } + ]; + features = { + "default" = [ "user" ]; + "impl-default" = [ "winapi/impl-default" ]; + }; + resolvedDefaultFeatures = [ "default" "user" ]; + }; + "num-conv" = rec { + crateName = "num-conv"; + version = "0.1.0"; + edition = "2021"; + sha256 = "1ndiyg82q73783jq18isi71a7mjh56wxrk52rlvyx0mi5z9ibmai"; + libName = "num_conv"; + authors = [ + "Jacob Pratt <jacob@jhpratt.dev>" + ]; + + }; + "num-integer" = rec { + crateName = "num-integer"; + version = "0.1.46"; + edition = "2018"; + sha256 = "13w5g54a9184cqlbsq80rnxw4jj4s0d8wv75jsq5r2lms8gncsbr"; + libName = "num_integer"; + authors = [ + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + features = [ "i128" ]; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "num-traits/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "num-traits" = rec { + crateName = "num-traits"; + version = "0.2.19"; + edition = "2021"; + sha256 = "0h984rhdkkqd4ny9cif7y2azl3xdfb7768hb9irhpsch4q3gq787"; + libName = "num_traits"; + authors = [ + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "libm"; + packageId = "libm"; + optional = true; + } + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + features = { + "default" = [ "std" ]; + "libm" = [ "dep:libm" ]; + }; + resolvedDefaultFeatures = [ "default" "i128" "libm" "std" ]; + }; + "number_prefix" = rec { + crateName = "number_prefix"; + version = "0.4.0"; + edition = "2015"; + sha256 = "1wvh13wvlajqxkb1filsfzbrnq0vrmrw298v2j3sy82z1rm282w3"; + authors = [ + "Benjamin Sago <ogham@bsago.me>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "object" = rec { + crateName = "object"; + version = "0.32.2"; + edition = "2018"; + sha256 = "0hc4cjwyngiy6k51hlzrlsxgv5z25vv7c2cp0ky1lckfic0259m6"; + dependencies = [ + { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + ]; + features = { + "all" = [ "read" "write" "std" "compression" "wasm" ]; + "alloc" = [ "dep:alloc" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "compression" = [ "dep:flate2" "dep:ruzstd" "std" ]; + "core" = [ "dep:core" ]; + "default" = [ "read" "compression" ]; + "doc" = [ "read_core" "write_std" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; + "pe" = [ "coff" ]; + "read" = [ "read_core" "archive" "coff" "elf" "macho" "pe" "xcoff" "unaligned" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" "alloc" "memchr/rustc-dep-of-std" ]; + "std" = [ "memchr/std" ]; + "unstable-all" = [ "all" "unstable" ]; + "wasm" = [ "dep:wasmparser" ]; + "write" = [ "write_std" "coff" "elf" "macho" "pe" "xcoff" ]; + "write_core" = [ "dep:crc32fast" "dep:indexmap" "dep:hashbrown" ]; + "write_std" = [ "write_core" "std" "indexmap?/std" "crc32fast?/std" ]; + }; + resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" ]; + }; + "once_cell" = rec { + crateName = "once_cell"; + version = "1.19.0"; + edition = "2021"; + sha256 = "14kvw7px5z96dk4dwdm1r9cqhhy2cyj1l5n5b29mynbb8yr15nrz"; + authors = [ + "Aleksey Kladov <aleksey.kladov@gmail.com>" + ]; + features = { + "alloc" = [ "race" ]; + "atomic-polyfill" = [ "critical-section" ]; + "critical-section" = [ "dep:critical-section" "portable-atomic" ]; + "default" = [ "std" ]; + "parking_lot" = [ "dep:parking_lot_core" ]; + "portable-atomic" = [ "dep:portable-atomic" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "race" "std" ]; + }; + "openssl-probe" = rec { + crateName = "openssl-probe"; + version = "0.1.5"; + edition = "2015"; + sha256 = "1kq18qm48rvkwgcggfkqq6pm948190czqc94d6bm2sir5hq1l0gz"; + libName = "openssl_probe"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + + }; + "outref" = rec { + crateName = "outref"; + version = "0.5.1"; + edition = "2021"; + sha256 = "0ynw7nb89603gkfi83f9chsf76ds3b710gxfn12yyawrzl7pcc20"; + + }; + "p256" = rec { + crateName = "p256"; + version = "0.11.1"; + edition = "2021"; + sha256 = "151mqd8m25c8ib97saz4fwkg4nhw098i051gazg2l7pm13flxx2i"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "ecdsa"; + packageId = "ecdsa"; + rename = "ecdsa-core"; + optional = true; + usesDefaultFeatures = false; + features = [ "der" ]; + } + { + name = "elliptic-curve"; + packageId = "elliptic-curve"; + usesDefaultFeatures = false; + features = [ "hazmat" "sec1" ]; + } + { + name = "sha2"; + packageId = "sha2"; + optional = true; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "ecdsa"; + packageId = "ecdsa"; + rename = "ecdsa-core"; + usesDefaultFeatures = false; + features = [ "dev" ]; + } + ]; + features = { + "arithmetic" = [ "elliptic-curve/arithmetic" ]; + "bits" = [ "arithmetic" "elliptic-curve/bits" ]; + "default" = [ "arithmetic" "ecdsa" "pkcs8" "std" ]; + "digest" = [ "ecdsa-core/digest" "ecdsa-core/hazmat" ]; + "ecdh" = [ "arithmetic" "elliptic-curve/ecdh" ]; + "ecdsa" = [ "arithmetic" "ecdsa-core/sign" "ecdsa-core/verify" "sha256" ]; + "ecdsa-core" = [ "dep:ecdsa-core" ]; + "expose-field" = [ "arithmetic" ]; + "hash2curve" = [ "arithmetic" "elliptic-curve/hash2curve" ]; + "hex-literal" = [ "dep:hex-literal" ]; + "jwk" = [ "elliptic-curve/jwk" ]; + "pem" = [ "elliptic-curve/pem" "ecdsa-core/pem" "pkcs8" ]; + "pkcs8" = [ "ecdsa-core/pkcs8" "elliptic-curve/pkcs8" ]; + "serde" = [ "ecdsa-core/serde" "elliptic-curve/serde" "serdect" ]; + "serdect" = [ "dep:serdect" ]; + "sha2" = [ "dep:sha2" ]; + "sha256" = [ "digest" "sha2" ]; + "std" = [ "ecdsa-core/std" "elliptic-curve/std" ]; + "test-vectors" = [ "hex-literal" ]; + "voprf" = [ "elliptic-curve/voprf" "sha2" ]; + }; + resolvedDefaultFeatures = [ "arithmetic" "default" "digest" "ecdsa" "ecdsa-core" "pkcs8" "sha2" "sha256" "std" ]; + }; + "parking_lot" = rec { + crateName = "parking_lot"; + version = "0.12.1"; + edition = "2018"; + sha256 = "13r2xk7mnxfc5g0g6dkdxqdqad99j7s7z8zhzz4npw5r0g0v4hip"; + authors = [ + "Amanieu d'Antras <amanieu@gmail.com>" + ]; + dependencies = [ + { + name = "lock_api"; + packageId = "lock_api"; + } + { + name = "parking_lot_core"; + packageId = "parking_lot_core"; + } + ]; + features = { + "arc_lock" = [ "lock_api/arc_lock" ]; + "deadlock_detection" = [ "parking_lot_core/deadlock_detection" ]; + "nightly" = [ "parking_lot_core/nightly" "lock_api/nightly" ]; + "owning_ref" = [ "lock_api/owning_ref" ]; + "serde" = [ "lock_api/serde" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "parking_lot_core" = rec { + crateName = "parking_lot_core"; + version = "0.9.9"; + edition = "2018"; + sha256 = "13h0imw1aq86wj28gxkblhkzx6z1gk8q18n0v76qmmj6cliajhjc"; + authors = [ + "Amanieu d'Antras <amanieu@gmail.com>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "redox_syscall"; + packageId = "redox_syscall"; + target = { target, features }: ("redox" == target."os" or null); + } + { + name = "smallvec"; + packageId = "smallvec"; + } + { + name = "windows-targets"; + packageId = "windows-targets 0.48.5"; + target = { target, features }: (target."windows" or false); + } + ]; + features = { + "backtrace" = [ "dep:backtrace" ]; + "deadlock_detection" = [ "petgraph" "thread-id" "backtrace" ]; + "petgraph" = [ "dep:petgraph" ]; + "thread-id" = [ "dep:thread-id" ]; + }; + }; + "parquet-format-safe" = rec { + crateName = "parquet-format-safe"; + version = "0.2.4"; + edition = "2021"; + sha256 = "07wf6wf4jrxlq5p3xldxsnabp7jl06my2qp7kiwy9m3x2r5wac8i"; + libName = "parquet_format_safe"; + authors = [ + "Apache Thrift contributors <dev@thrift.apache.org>" + "Jorge Leitao <jorgecarleitao@gmail.com>" + ]; + dependencies = [ + { + name = "async-trait"; + packageId = "async-trait"; + optional = true; + } + { + name = "futures"; + packageId = "futures"; + optional = true; + } + ]; + features = { + "async" = [ "futures" "async-trait" ]; + "async-trait" = [ "dep:async-trait" ]; + "full" = [ "async" ]; + "futures" = [ "dep:futures" ]; + }; + resolvedDefaultFeatures = [ "async" "async-trait" "default" "futures" ]; + }; + "percent-encoding" = rec { + crateName = "percent-encoding"; + version = "2.3.1"; + edition = "2018"; + sha256 = "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573"; + libName = "percent_encoding"; + authors = [ + "The rust-url developers" + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "pin-project-lite" = rec { + crateName = "pin-project-lite"; + version = "0.2.14"; + edition = "2018"; + sha256 = "00nx3f04agwjlsmd3mc5rx5haibj2v8q9b52b0kwn63wcv4nz9mx"; + libName = "pin_project_lite"; + + }; + "pin-utils" = rec { + crateName = "pin-utils"; + version = "0.1.0"; + edition = "2018"; + sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; + authors = [ + "Josef Brandl <mail@josefbrandl.de>" + ]; + + }; + "pkcs8 0.10.2" = rec { + crateName = "pkcs8"; + version = "0.10.2"; + edition = "2021"; + sha256 = "1dx7w21gvn07azszgqd3ryjhyphsrjrmq5mmz1fbxkj5g0vv4l7r"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "der"; + packageId = "der 0.7.8"; + features = [ "oid" ]; + } + { + name = "spki"; + packageId = "spki 0.7.3"; + } + ]; + features = { + "3des" = [ "encryption" "pkcs5/3des" ]; + "alloc" = [ "der/alloc" "der/zeroize" "spki/alloc" ]; + "des-insecure" = [ "encryption" "pkcs5/des-insecure" ]; + "encryption" = [ "alloc" "pkcs5/alloc" "pkcs5/pbes2" "rand_core" ]; + "getrandom" = [ "rand_core/getrandom" ]; + "pem" = [ "alloc" "der/pem" "spki/pem" ]; + "pkcs5" = [ "dep:pkcs5" ]; + "rand_core" = [ "dep:rand_core" ]; + "sha1-insecure" = [ "encryption" "pkcs5/sha1-insecure" ]; + "std" = [ "alloc" "der/std" "spki/std" ]; + "subtle" = [ "dep:subtle" ]; + }; + resolvedDefaultFeatures = [ "alloc" "std" ]; + }; + "pkcs8 0.9.0" = rec { + crateName = "pkcs8"; + version = "0.9.0"; + edition = "2021"; + sha256 = "1fm4sigvcd0zpzg9jcp862a8p272kk08b9lgcs1dm1az19cjrjly"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "der"; + packageId = "der 0.6.1"; + features = [ "oid" ]; + } + { + name = "spki"; + packageId = "spki 0.6.0"; + } + ]; + features = { + "3des" = [ "encryption" "pkcs5/3des" ]; + "alloc" = [ "der/alloc" "der/zeroize" "spki/alloc" ]; + "des-insecure" = [ "encryption" "pkcs5/des-insecure" ]; + "encryption" = [ "alloc" "pkcs5/alloc" "pkcs5/pbes2" "rand_core" ]; + "getrandom" = [ "rand_core/getrandom" ]; + "pem" = [ "alloc" "der/pem" "spki/pem" ]; + "pkcs5" = [ "dep:pkcs5" ]; + "rand_core" = [ "dep:rand_core" ]; + "sha1" = [ "encryption" "pkcs5/sha1" ]; + "std" = [ "alloc" "der/std" "spki/std" ]; + "subtle" = [ "dep:subtle" ]; + }; + resolvedDefaultFeatures = [ "alloc" ]; + }; + "pkg-config" = rec { + crateName = "pkg-config"; + version = "0.3.30"; + edition = "2015"; + sha256 = "1v07557dj1sa0aly9c90wsygc0i8xv5vnmyv0g94lpkvj8qb4cfj"; + libName = "pkg_config"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + + }; + "planus" = rec { + crateName = "planus"; + version = "0.3.1"; + edition = "2021"; + sha256 = "17x8mr175b9clg998xpi5z45f9fsspb0ncfnx2644bz817fr25pw"; + dependencies = [ + { + name = "array-init-cursor"; + packageId = "array-init-cursor"; + } + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "platforms" = rec { + crateName = "platforms"; + version = "3.3.0"; + edition = "2018"; + sha256 = "0k7q6pigmnvgpfasvssb12m2pv3pc94zrhrfg9by3h3wmhyfqvb2"; + authors = [ + "Tony Arcieri <bascule@gmail.com>" + "Sergey \"Shnatsel\" Davidoff <shnatsel@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "polars" = rec { + crateName = "polars"; + version = "0.36.2"; + edition = "2021"; + sha256 = "0swv6i0gq25zafw1ir2irqij9a8mnkhvws5idv72m3kavby4i04k"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "getrandom"; + packageId = "getrandom"; + target = { target, features }: (builtins.elem "wasm" target."family"); + features = [ "js" ]; + } + { + name = "polars-core"; + packageId = "polars-core"; + usesDefaultFeatures = false; + features = [ "algorithm_group_by" ]; + } + { + name = "polars-io"; + packageId = "polars-io"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "polars-lazy"; + packageId = "polars-lazy"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "polars-ops"; + packageId = "polars-ops"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "polars-sql"; + packageId = "polars-sql"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "polars-time"; + packageId = "polars-time"; + optional = true; + usesDefaultFeatures = false; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "abs" = [ "polars-ops/abs" "polars-lazy?/abs" ]; + "approx_unique" = [ "polars-lazy?/approx_unique" "polars-ops/approx_unique" ]; + "arg_where" = [ "polars-lazy?/arg_where" ]; + "array_any_all" = [ "polars-lazy?/array_any_all" "dtype-array" ]; + "asof_join" = [ "polars-core/asof_join" "polars-lazy?/asof_join" "polars-ops/asof_join" ]; + "async" = [ "polars-lazy?/async" ]; + "avro" = [ "polars-io" "polars-io/avro" ]; + "avx512" = [ "polars-core/avx512" ]; + "aws" = [ "async" "cloud" "polars-io/aws" ]; + "azure" = [ "async" "cloud" "polars-io/azure" ]; + "bench" = [ "lazy" ]; + "bigidx" = [ "polars-core/bigidx" "polars-lazy?/bigidx" "polars-ops/big_idx" ]; + "binary_encoding" = [ "polars-ops/binary_encoding" "polars-lazy?/binary_encoding" ]; + "checked_arithmetic" = [ "polars-core/checked_arithmetic" ]; + "chunked_ids" = [ "polars-lazy?/chunked_ids" "polars-core/chunked_ids" "polars-ops/chunked_ids" ]; + "cloud" = [ "polars-lazy?/cloud" "polars-io/cloud" ]; + "cloud_write" = [ "cloud" "polars-lazy?/cloud_write" ]; + "coalesce" = [ "polars-lazy?/coalesce" ]; + "concat_str" = [ "polars-lazy?/concat_str" ]; + "cov" = [ "polars-lazy/cov" ]; + "cross_join" = [ "polars-lazy?/cross_join" "polars-ops/cross_join" ]; + "cse" = [ "polars-lazy?/cse" ]; + "csv" = [ "polars-io" "polars-io/csv" "polars-lazy?/csv" "polars-sql?/csv" ]; + "cum_agg" = [ "polars-ops/cum_agg" "polars-lazy?/cum_agg" ]; + "cumulative_eval" = [ "polars-lazy?/cumulative_eval" ]; + "cutqcut" = [ "polars-lazy?/cutqcut" ]; + "dataframe_arithmetic" = [ "polars-core/dataframe_arithmetic" ]; + "date_offset" = [ "polars-lazy?/date_offset" ]; + "decompress" = [ "polars-io/decompress" ]; + "decompress-fast" = [ "polars-io/decompress-fast" ]; + "default" = [ "docs" "zip_with" "csv" "temporal" "fmt" "dtype-slim" ]; + "describe" = [ "polars-core/describe" ]; + "diagonal_concat" = [ "polars-core/diagonal_concat" "polars-lazy?/diagonal_concat" "polars-sql?/diagonal_concat" ]; + "diff" = [ "polars-ops/diff" "polars-lazy?/diff" ]; + "docs" = [ "polars-core/docs" ]; + "docs-selection" = [ "csv" "json" "parquet" "ipc" "ipc_streaming" "dtype-full" "is_in" "rows" "docs" "strings" "object" "lazy" "temporal" "random" "zip_with" "round_series" "checked_arithmetic" "ndarray" "repeat_by" "is_first_distinct" "is_last_distinct" "asof_join" "cross_join" "concat_str" "string_reverse" "string_to_integer" "decompress" "mode" "take_opt_iter" "cum_agg" "rolling_window" "interpolate" "diff" "rank" "range" "diagonal_concat" "horizontal_concat" "abs" "dot_diagram" "string_encoding" "product" "to_dummies" "describe" "list_eval" "cumulative_eval" "timezones" "arg_where" "propagate_nans" "coalesce" "dynamic_group_by" "extract_groups" "replace" ]; + "dot_diagram" = [ "polars-lazy?/dot_diagram" ]; + "dot_product" = [ "polars-core/dot_product" ]; + "dtype-array" = [ "polars-core/dtype-array" "polars-lazy?/dtype-array" "polars-ops/dtype-array" ]; + "dtype-categorical" = [ "polars-core/dtype-categorical" "polars-io/dtype-categorical" "polars-lazy?/dtype-categorical" "polars-ops/dtype-categorical" ]; + "dtype-date" = [ "polars-core/dtype-date" "polars-lazy?/dtype-date" "polars-io/dtype-date" "polars-time?/dtype-date" "polars-core/dtype-date" "polars-ops/dtype-date" ]; + "dtype-datetime" = [ "polars-core/dtype-datetime" "polars-lazy?/dtype-datetime" "polars-io/dtype-datetime" "polars-time?/dtype-datetime" "polars-ops/dtype-datetime" ]; + "dtype-decimal" = [ "polars-core/dtype-decimal" "polars-lazy?/dtype-decimal" "polars-ops/dtype-decimal" "polars-io/dtype-decimal" ]; + "dtype-duration" = [ "polars-core/dtype-duration" "polars-lazy?/dtype-duration" "polars-time?/dtype-duration" "polars-core/dtype-duration" "polars-ops/dtype-duration" ]; + "dtype-full" = [ "dtype-date" "dtype-datetime" "dtype-duration" "dtype-time" "dtype-array" "dtype-i8" "dtype-i16" "dtype-decimal" "dtype-u8" "dtype-u16" "dtype-categorical" "dtype-struct" ]; + "dtype-i16" = [ "polars-core/dtype-i16" "polars-lazy?/dtype-i16" "polars-ops/dtype-i16" ]; + "dtype-i8" = [ "polars-core/dtype-i8" "polars-lazy?/dtype-i8" "polars-ops/dtype-i8" ]; + "dtype-slim" = [ "dtype-date" "dtype-datetime" "dtype-duration" ]; + "dtype-struct" = [ "polars-core/dtype-struct" "polars-lazy?/dtype-struct" "polars-ops/dtype-struct" "polars-io/dtype-struct" ]; + "dtype-time" = [ "polars-core/dtype-time" "polars-io/dtype-time" "polars-time?/dtype-time" "polars-ops/dtype-time" ]; + "dtype-u16" = [ "polars-core/dtype-u16" "polars-lazy?/dtype-u16" "polars-ops/dtype-u16" ]; + "dtype-u8" = [ "polars-core/dtype-u8" "polars-lazy?/dtype-u8" "polars-ops/dtype-u8" ]; + "dynamic_group_by" = [ "polars-core/dynamic_group_by" "polars-lazy?/dynamic_group_by" ]; + "ewma" = [ "polars-ops/ewma" "polars-lazy?/ewma" ]; + "extract_groups" = [ "polars-lazy?/extract_groups" ]; + "extract_jsonpath" = [ "polars-core/strings" "polars-ops/extract_jsonpath" "polars-ops/strings" "polars-lazy?/extract_jsonpath" ]; + "find_many" = [ "polars-plan/find_many" ]; + "fmt" = [ "polars-core/fmt" ]; + "fmt_no_tty" = [ "polars-core/fmt_no_tty" ]; + "fused" = [ "polars-ops/fused" "polars-lazy?/fused" ]; + "gcp" = [ "async" "cloud" "polars-io/gcp" ]; + "group_by_list" = [ "polars-core/group_by_list" "polars-ops/group_by_list" ]; + "hist" = [ "polars-ops/hist" "polars-lazy/hist" ]; + "horizontal_concat" = [ "polars-core/horizontal_concat" "polars-lazy?/horizontal_concat" ]; + "http" = [ "async" "cloud" "polars-io/http" ]; + "interpolate" = [ "polars-ops/interpolate" "polars-lazy?/interpolate" ]; + "ipc" = [ "polars-io" "polars-io/ipc" "polars-lazy?/ipc" "polars-sql?/ipc" ]; + "ipc_streaming" = [ "polars-io" "polars-io/ipc_streaming" "polars-lazy?/ipc" ]; + "is_first_distinct" = [ "polars-lazy?/is_first_distinct" "polars-ops/is_first_distinct" ]; + "is_in" = [ "polars-lazy?/is_in" ]; + "is_last_distinct" = [ "polars-lazy?/is_last_distinct" "polars-ops/is_last_distinct" ]; + "is_unique" = [ "polars-lazy?/is_unique" "polars-ops/is_unique" ]; + "json" = [ "polars-io" "polars-io/json" "polars-lazy?/json" "polars-sql?/json" "dtype-struct" ]; + "lazy" = [ "polars-core/lazy" "polars-lazy" ]; + "lazy_regex" = [ "polars-lazy?/regex" ]; + "list_any_all" = [ "polars-lazy?/list_any_all" ]; + "list_count" = [ "polars-ops/list_count" "polars-lazy?/list_count" ]; + "list_drop_nulls" = [ "polars-lazy?/list_drop_nulls" ]; + "list_eval" = [ "polars-lazy?/list_eval" ]; + "list_gather" = [ "polars-ops/list_gather" "polars-lazy?/list_gather" ]; + "list_sample" = [ "polars-lazy?/list_sample" ]; + "list_sets" = [ "polars-lazy?/list_sets" ]; + "list_to_struct" = [ "polars-ops/list_to_struct" "polars-lazy?/list_to_struct" ]; + "log" = [ "polars-ops/log" "polars-lazy?/log" ]; + "merge_sorted" = [ "polars-lazy?/merge_sorted" ]; + "meta" = [ "polars-lazy?/meta" ]; + "mode" = [ "polars-ops/mode" "polars-lazy?/mode" ]; + "moment" = [ "polars-ops/moment" "polars-lazy?/moment" ]; + "ndarray" = [ "polars-core/ndarray" ]; + "nightly" = [ "polars-core/nightly" "polars-ops?/nightly" "simd" "polars-lazy?/nightly" "polars-sql/nightly" ]; + "object" = [ "polars-core/object" "polars-lazy?/object" "polars-io/object" ]; + "parquet" = [ "polars-io" "polars-lazy?/parquet" "polars-io/parquet" "polars-sql?/parquet" ]; + "partition_by" = [ "polars-core/partition_by" ]; + "pct_change" = [ "polars-ops/pct_change" "polars-lazy?/pct_change" ]; + "peaks" = [ "polars-lazy/peaks" ]; + "performant" = [ "polars-core/performant" "chunked_ids" "dtype-u8" "dtype-u16" "dtype-struct" "cse" "polars-ops/performant" "streaming" "fused" ]; + "pivot" = [ "polars-lazy?/pivot" ]; + "polars-io" = [ "dep:polars-io" ]; + "polars-lazy" = [ "dep:polars-lazy" ]; + "polars-ops" = [ "dep:polars-ops" ]; + "polars-plan" = [ "dep:polars-plan" ]; + "polars-sql" = [ "dep:polars-sql" ]; + "polars-time" = [ "dep:polars-time" ]; + "product" = [ "polars-core/product" ]; + "propagate_nans" = [ "polars-lazy?/propagate_nans" ]; + "random" = [ "polars-core/random" "polars-lazy?/random" "polars-ops/random" ]; + "range" = [ "polars-lazy?/range" ]; + "rank" = [ "polars-lazy?/rank" "polars-ops/rank" ]; + "reinterpret" = [ "polars-core/reinterpret" ]; + "repeat_by" = [ "polars-ops/repeat_by" "polars-lazy?/repeat_by" ]; + "replace" = [ "polars-ops/replace" "polars-lazy?/replace" ]; + "rle" = [ "polars-lazy?/rle" ]; + "rolling_window" = [ "polars-core/rolling_window" "polars-lazy?/rolling_window" "polars-time/rolling_window" ]; + "round_series" = [ "polars-ops/round_series" "polars-lazy?/round_series" ]; + "row_hash" = [ "polars-core/row_hash" "polars-lazy?/row_hash" ]; + "rows" = [ "polars-core/rows" ]; + "search_sorted" = [ "polars-lazy?/search_sorted" ]; + "semi_anti_join" = [ "polars-lazy?/semi_anti_join" "polars-ops/semi_anti_join" "polars-sql?/semi_anti_join" ]; + "serde" = [ "polars-core/serde" ]; + "serde-lazy" = [ "polars-core/serde-lazy" "polars-lazy?/serde" "polars-time?/serde" "polars-io?/serde" "polars-ops?/serde" ]; + "sign" = [ "polars-lazy?/sign" ]; + "simd" = [ "polars-core/simd" "polars-io/simd" "polars-ops?/simd" ]; + "sql" = [ "polars-sql" ]; + "streaming" = [ "polars-lazy?/streaming" ]; + "string_encoding" = [ "polars-ops/string_encoding" "polars-lazy?/string_encoding" "polars-core/strings" ]; + "string_pad" = [ "polars-lazy?/string_pad" "polars-ops/string_pad" ]; + "string_reverse" = [ "polars-lazy?/string_reverse" "polars-ops/string_reverse" ]; + "string_to_integer" = [ "polars-lazy?/string_to_integer" "polars-ops/string_to_integer" ]; + "strings" = [ "polars-core/strings" "polars-lazy?/strings" "polars-ops/strings" ]; + "take_opt_iter" = [ "polars-core/take_opt_iter" ]; + "temporal" = [ "polars-core/temporal" "polars-lazy?/temporal" "polars-io/temporal" "polars-time" ]; + "test" = [ "lazy" "rolling_window" "rank" "round_series" "csv" "dtype-categorical" "cum_agg" "fmt" "diff" "abs" "parquet" "ipc" "ipc_streaming" "json" ]; + "timezones" = [ "polars-core/timezones" "polars-lazy?/timezones" "polars-io/timezones" ]; + "to_dummies" = [ "polars-ops/to_dummies" ]; + "top_k" = [ "polars-lazy?/top_k" ]; + "trigonometry" = [ "polars-lazy?/trigonometry" ]; + "true_div" = [ "polars-lazy?/true_div" ]; + "unique_counts" = [ "polars-ops/unique_counts" "polars-lazy?/unique_counts" ]; + "zip_with" = [ "polars-core/zip_with" ]; + }; + resolvedDefaultFeatures = [ "csv" "default" "docs" "dtype-date" "dtype-datetime" "dtype-duration" "dtype-slim" "fmt" "parquet" "polars-io" "polars-ops" "polars-time" "temporal" "zip_with" ]; + }; + "polars-arrow" = rec { + crateName = "polars-arrow"; + version = "0.36.2"; + edition = "2021"; + sha256 = "0vxql6amvwyp6qj0w87vm21y33qa0i61pshs4ry7ixwgd4ps0s6f"; + libName = "polars_arrow"; + authors = [ + "Jorge C. Leitao <jorgecarleitao@gmail.com>" + "Apache Arrow <dev@arrow.apache.org>" + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "ahash"; + packageId = "ahash"; + } + { + name = "arrow-format"; + packageId = "arrow-format"; + optional = true; + features = [ "ipc" ]; + } + { + name = "atoi_simd"; + packageId = "atoi_simd"; + optional = true; + } + { + name = "bytemuck"; + packageId = "bytemuck"; + features = [ "derive" "extern_crate_alloc" ]; + } + { + name = "chrono"; + packageId = "chrono"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "dyn-clone"; + packageId = "dyn-clone"; + } + { + name = "either"; + packageId = "either"; + } + { + name = "ethnum"; + packageId = "ethnum"; + } + { + name = "fast-float"; + packageId = "fast-float"; + optional = true; + } + { + name = "foreign_vec"; + packageId = "foreign_vec"; + } + { + name = "futures"; + packageId = "futures"; + optional = true; + } + { + name = "getrandom"; + packageId = "getrandom"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "wasm32-unknown-unknown"); + features = [ "js" ]; + } + { + name = "hashbrown"; + packageId = "hashbrown"; + features = [ "rayon" "ahash" ]; + } + { + name = "itoa"; + packageId = "itoa"; + optional = true; + } + { + name = "lz4"; + packageId = "lz4"; + optional = true; + } + { + name = "multiversion"; + packageId = "multiversion"; + optional = true; + } + { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "polars-error"; + packageId = "polars-error"; + usesDefaultFeatures = false; + } + { + name = "polars-utils"; + packageId = "polars-utils"; + usesDefaultFeatures = false; + } + { + name = "ryu"; + packageId = "ryu"; + optional = true; + } + { + name = "simdutf8"; + packageId = "simdutf8"; + } + { + name = "streaming-iterator"; + packageId = "streaming-iterator"; + } + { + name = "strength_reduce"; + packageId = "strength_reduce"; + optional = true; + } + { + name = "zstd"; + packageId = "zstd"; + optional = true; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "arrow-array" = [ "dep:arrow-array" ]; + "arrow-buffer" = [ "dep:arrow-buffer" ]; + "arrow-data" = [ "dep:arrow-data" ]; + "arrow-format" = [ "dep:arrow-format" ]; + "arrow-schema" = [ "dep:arrow-schema" ]; + "arrow_rs" = [ "arrow-buffer" "arrow-schema" "arrow-data" "arrow-array" ]; + "async-stream" = [ "dep:async-stream" ]; + "atoi" = [ "dep:atoi" ]; + "atoi_simd" = [ "dep:atoi_simd" ]; + "avro-schema" = [ "dep:avro-schema" ]; + "chrono-tz" = [ "dep:chrono-tz" ]; + "compute" = [ "compute_aggregate" "compute_arithmetics" "compute_bitwise" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_hash" "compute_if_then_else" "compute_take" "compute_temporal" ]; + "compute_aggregate" = [ "multiversion" ]; + "compute_arithmetics" = [ "strength_reduce" "compute_arithmetics_decimal" ]; + "compute_arithmetics_decimal" = [ "strength_reduce" ]; + "compute_cast" = [ "compute_take" "ryu" "atoi_simd" "itoa" "fast-float" ]; + "compute_comparison" = [ "compute_take" "compute_boolean" ]; + "compute_hash" = [ "multiversion" ]; + "dtype-decimal" = [ "atoi" ]; + "fast-float" = [ "dep:fast-float" ]; + "full" = [ "arrow_rs" "io_ipc" "io_flight" "io_ipc_write_async" "io_ipc_read_async" "io_ipc_compression" "io_avro" "io_avro_compression" "io_avro_async" "regex-syntax" "compute" "chrono-tz" ]; + "futures" = [ "dep:futures" ]; + "hex" = [ "dep:hex" ]; + "indexmap" = [ "dep:indexmap" ]; + "io_avro" = [ "avro-schema" "polars-error/avro-schema" ]; + "io_avro_async" = [ "avro-schema/async" ]; + "io_avro_compression" = [ "avro-schema/compression" ]; + "io_flight" = [ "io_ipc" "arrow-format/flight-data" ]; + "io_ipc" = [ "arrow-format" "polars-error/arrow-format" ]; + "io_ipc_compression" = [ "lz4" "zstd" ]; + "io_ipc_read_async" = [ "io_ipc" "futures" "async-stream" ]; + "io_ipc_write_async" = [ "io_ipc" "futures" ]; + "itoa" = [ "dep:itoa" ]; + "lz4" = [ "dep:lz4" ]; + "multiversion" = [ "dep:multiversion" ]; + "regex" = [ "dep:regex" ]; + "regex-syntax" = [ "dep:regex-syntax" ]; + "ryu" = [ "dep:ryu" ]; + "serde" = [ "dep:serde" ]; + "strength_reduce" = [ "dep:strength_reduce" ]; + "zstd" = [ "dep:zstd" ]; + }; + resolvedDefaultFeatures = [ "arrow-format" "atoi_simd" "compute" "compute_aggregate" "compute_arithmetics" "compute_arithmetics_decimal" "compute_bitwise" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_hash" "compute_if_then_else" "compute_take" "compute_temporal" "fast-float" "futures" "io_ipc" "io_ipc_compression" "io_ipc_write_async" "itoa" "lz4" "multiversion" "ryu" "strength_reduce" "strings" "temporal" "zstd" ]; + }; + "polars-compute" = rec { + crateName = "polars-compute"; + version = "0.36.2"; + edition = "2021"; + sha256 = "1pa4l1w41gdzdff81ih1z05z3gz568k81i6flibbca8v2igvqkxi"; + libName = "polars_compute"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "bytemuck"; + packageId = "bytemuck"; + features = [ "derive" "extern_crate_alloc" ]; + } + { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "polars-arrow"; + packageId = "polars-arrow"; + rename = "arrow"; + usesDefaultFeatures = false; + features = [ "compute_aggregate" "compute_arithmetics" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_if_then_else" ]; + } + { + name = "polars-utils"; + packageId = "polars-utils"; + usesDefaultFeatures = false; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { }; + }; + "polars-core" = rec { + crateName = "polars-core"; + version = "0.36.2"; + edition = "2021"; + sha256 = "08sar9h97znpb8ziyvrrvvx28lyzc21vwsd7gvwybjxn6kkyzxfh"; + libName = "polars_core"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "ahash"; + packageId = "ahash"; + } + { + name = "bitflags"; + packageId = "bitflags 2.6.0"; + } + { + name = "bytemuck"; + packageId = "bytemuck"; + features = [ "derive" "extern_crate_alloc" ]; + } + { + name = "chrono"; + packageId = "chrono"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "comfy-table"; + packageId = "comfy-table"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "either"; + packageId = "either"; + } + { + name = "hashbrown"; + packageId = "hashbrown"; + features = [ "rayon" "ahash" ]; + } + { + name = "indexmap"; + packageId = "indexmap"; + features = [ "std" ]; + } + { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "polars-arrow"; + packageId = "polars-arrow"; + rename = "arrow"; + usesDefaultFeatures = false; + features = [ "compute_aggregate" "compute_arithmetics" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_if_then_else" ]; + } + { + name = "polars-compute"; + packageId = "polars-compute"; + usesDefaultFeatures = false; + } + { + name = "polars-error"; + packageId = "polars-error"; + usesDefaultFeatures = false; + } + { + name = "polars-row"; + packageId = "polars-row"; + usesDefaultFeatures = false; + } + { + name = "polars-utils"; + packageId = "polars-utils"; + usesDefaultFeatures = false; + } + { + name = "rand"; + packageId = "rand"; + optional = true; + features = [ "small_rng" "std" ]; + } + { + name = "rand_distr"; + packageId = "rand_distr"; + optional = true; + } + { + name = "rayon"; + packageId = "rayon"; + } + { + name = "regex"; + packageId = "regex"; + optional = true; + } + { + name = "smartstring"; + packageId = "smartstring"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "xxhash-rust"; + packageId = "xxhash-rust"; + features = [ "xxh3" ]; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "arrow-array" = [ "dep:arrow-array" ]; + "arrow_rs" = [ "arrow-array" "arrow/arrow_rs" ]; + "bigidx" = [ "arrow/bigidx" "polars-utils/bigidx" ]; + "chrono" = [ "dep:chrono" ]; + "chrono-tz" = [ "dep:chrono-tz" ]; + "comfy-table" = [ "dep:comfy-table" ]; + "default" = [ "algorithm_group_by" ]; + "docs-selection" = [ "ndarray" "rows" "docs" "strings" "object" "lazy" "temporal" "random" "zip_with" "checked_arithmetic" "is_first_distinct" "is_last_distinct" "asof_join" "dot_product" "row_hash" "rolling_window" "dtype-categorical" "dtype-decimal" "diagonal_concat" "horizontal_concat" "dataframe_arithmetic" "product" "describe" "chunked_ids" "partition_by" "algorithm_group_by" ]; + "dtype-array" = [ "arrow/dtype-array" "polars-compute/dtype-array" ]; + "dtype-date" = [ "temporal" ]; + "dtype-datetime" = [ "temporal" ]; + "dtype-decimal" = [ "dep:itoap" "arrow/dtype-decimal" ]; + "dtype-duration" = [ "temporal" ]; + "dtype-time" = [ "temporal" ]; + "dynamic_group_by" = [ "dtype-datetime" "dtype-date" ]; + "fmt" = [ "comfy-table/tty" ]; + "fmt_no_tty" = [ "comfy-table" ]; + "ndarray" = [ "dep:ndarray" ]; + "nightly" = [ "simd" "hashbrown/nightly" "polars-utils/nightly" "arrow/nightly" ]; + "object" = [ "serde_json" ]; + "performant" = [ "arrow/performant" "reinterpret" ]; + "rand" = [ "dep:rand" ]; + "rand_distr" = [ "dep:rand_distr" ]; + "random" = [ "rand" "rand_distr" ]; + "regex" = [ "dep:regex" ]; + "serde" = [ "dep:serde" "smartstring/serde" "bitflags/serde" ]; + "serde-lazy" = [ "serde" "arrow/serde" "indexmap/serde" "smartstring/serde" "chrono/serde" ]; + "serde_json" = [ "dep:serde_json" ]; + "simd" = [ "arrow/simd" "polars-compute/simd" ]; + "strings" = [ "regex" "arrow/strings" "polars-error/regex" ]; + "temporal" = [ "regex" "chrono" "polars-error/regex" ]; + "timezones" = [ "chrono-tz" "arrow/chrono-tz" "arrow/timezones" ]; + }; + resolvedDefaultFeatures = [ "algorithm_group_by" "chrono" "chunked_ids" "comfy-table" "docs" "dtype-date" "dtype-datetime" "dtype-duration" "dtype-i16" "dtype-i8" "dtype-time" "fmt" "lazy" "rand" "rand_distr" "random" "regex" "reinterpret" "rows" "strings" "temporal" "zip_with" ]; + }; + "polars-error" = rec { + crateName = "polars-error"; + version = "0.36.2"; + edition = "2021"; + sha256 = "11m80a899kp45b3dz9jbvrn5001hw8izbdp7d2czrswrixwdx5k3"; + libName = "polars_error"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "arrow-format"; + packageId = "arrow-format"; + optional = true; + } + { + name = "regex"; + packageId = "regex"; + optional = true; + } + { + name = "simdutf8"; + packageId = "simdutf8"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + ]; + features = { + "arrow-format" = [ "dep:arrow-format" ]; + "avro-schema" = [ "dep:avro-schema" ]; + "object_store" = [ "dep:object_store" ]; + "regex" = [ "dep:regex" ]; + }; + resolvedDefaultFeatures = [ "arrow-format" "regex" ]; + }; + "polars-io" = rec { + crateName = "polars-io"; + version = "0.36.2"; + edition = "2021"; + sha256 = "1smamd34ghlxyxdd4aqdplk7k8xm1l626brmzlc4fvwlx3pmh13x"; + libName = "polars_io"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "ahash"; + packageId = "ahash"; + } + { + name = "async-trait"; + packageId = "async-trait"; + optional = true; + } + { + name = "atoi_simd"; + packageId = "atoi_simd"; + optional = true; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "chrono"; + packageId = "chrono"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "fast-float"; + packageId = "fast-float"; + optional = true; + } + { + name = "futures"; + packageId = "futures"; + optional = true; + } + { + name = "home"; + packageId = "home"; + target = { target, features }: (!(builtins.elem "wasm" target."family")); + } + { + name = "itoa"; + packageId = "itoa"; + optional = true; + } + { + name = "memchr"; + packageId = "memchr"; + } + { + name = "memmap2"; + packageId = "memmap2"; + rename = "memmap"; + } + { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "percent-encoding"; + packageId = "percent-encoding"; + } + { + name = "polars-arrow"; + packageId = "polars-arrow"; + rename = "arrow"; + usesDefaultFeatures = false; + features = [ "compute_aggregate" "compute_arithmetics" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_if_then_else" ]; + } + { + name = "polars-core"; + packageId = "polars-core"; + usesDefaultFeatures = false; + } + { + name = "polars-error"; + packageId = "polars-error"; + usesDefaultFeatures = false; + } + { + name = "polars-parquet"; + packageId = "polars-parquet"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "polars-time"; + packageId = "polars-time"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "polars-utils"; + packageId = "polars-utils"; + usesDefaultFeatures = false; + } + { + name = "rayon"; + packageId = "rayon"; + } + { + name = "regex"; + packageId = "regex"; + } + { + name = "ryu"; + packageId = "ryu"; + optional = true; + } + { + name = "simdutf8"; + packageId = "simdutf8"; + optional = true; + } + { + name = "smartstring"; + packageId = "smartstring"; + } + { + name = "tokio"; + packageId = "tokio"; + optional = true; + features = [ "net" "rt-multi-thread" "time" "sync" ]; + } + { + name = "tokio-util"; + packageId = "tokio-util"; + optional = true; + features = [ "io" "io-util" ]; + } + ]; + features = { + "async" = [ "async-trait" "futures" "tokio" "tokio-util" "arrow/io_ipc_write_async" "polars-error/regex" "polars-parquet?/async" ]; + "async-trait" = [ "dep:async-trait" ]; + "atoi_simd" = [ "dep:atoi_simd" ]; + "avro" = [ "arrow/io_avro" "arrow/io_avro_compression" ]; + "aws" = [ "object_store/aws" "cloud" "reqwest" ]; + "azure" = [ "object_store/azure" "cloud" ]; + "chrono" = [ "dep:chrono" ]; + "chrono-tz" = [ "dep:chrono-tz" ]; + "cloud" = [ "object_store" "async" "polars-error/object_store" "url" ]; + "csv" = [ "atoi_simd" "polars-core/rows" "itoa" "ryu" "fast-float" "simdutf8" ]; + "decompress" = [ "flate2/rust_backend" "zstd" ]; + "decompress-fast" = [ "flate2/zlib-ng" "zstd" ]; + "default" = [ "decompress" ]; + "dtype-categorical" = [ "polars-core/dtype-categorical" ]; + "dtype-date" = [ "polars-core/dtype-date" "polars-time/dtype-date" ]; + "dtype-datetime" = [ "polars-core/dtype-datetime" "polars-core/temporal" "polars-time/dtype-datetime" "chrono" ]; + "dtype-decimal" = [ "polars-core/dtype-decimal" ]; + "dtype-struct" = [ "polars-core/dtype-struct" ]; + "dtype-time" = [ "polars-core/dtype-time" "polars-core/temporal" "polars-time/dtype-time" ]; + "fast-float" = [ "dep:fast-float" ]; + "flate2" = [ "dep:flate2" ]; + "fmt" = [ "polars-core/fmt" ]; + "futures" = [ "dep:futures" ]; + "gcp" = [ "object_store/gcp" "cloud" ]; + "http" = [ "object_store/http" "cloud" ]; + "ipc" = [ "arrow/io_ipc" "arrow/io_ipc_compression" ]; + "ipc_streaming" = [ "arrow/io_ipc" "arrow/io_ipc_compression" ]; + "itoa" = [ "dep:itoa" ]; + "json" = [ "polars-json" "simd-json" "atoi_simd" "serde_json" "dtype-struct" "csv" ]; + "object_store" = [ "dep:object_store" ]; + "parquet" = [ "polars-parquet" "polars-parquet/compression" ]; + "partition" = [ "polars-core/partition_by" ]; + "polars-json" = [ "dep:polars-json" ]; + "polars-parquet" = [ "dep:polars-parquet" ]; + "polars-time" = [ "dep:polars-time" ]; + "python" = [ "polars-error/python" ]; + "reqwest" = [ "dep:reqwest" ]; + "ryu" = [ "dep:ryu" ]; + "serde" = [ "dep:serde" "polars-core/serde-lazy" ]; + "serde_json" = [ "dep:serde_json" ]; + "simd-json" = [ "dep:simd-json" ]; + "simdutf8" = [ "dep:simdutf8" ]; + "temporal" = [ "dtype-datetime" "dtype-date" "dtype-time" ]; + "timezones" = [ "chrono-tz" "dtype-datetime" ]; + "tokio" = [ "dep:tokio" ]; + "tokio-util" = [ "dep:tokio-util" ]; + "url" = [ "dep:url" ]; + "zstd" = [ "dep:zstd" ]; + }; + resolvedDefaultFeatures = [ "async" "async-trait" "atoi_simd" "chrono" "csv" "dtype-date" "dtype-datetime" "dtype-time" "fast-float" "futures" "ipc" "itoa" "lazy" "parquet" "polars-parquet" "polars-time" "ryu" "simdutf8" "temporal" "tokio" "tokio-util" ]; + }; + "polars-lazy" = rec { + crateName = "polars-lazy"; + version = "0.36.2"; + edition = "2021"; + sha256 = "1mdml4hs574njb23mb9gl6x92x2bb4vdfzsazkl3ifq516s0awcx"; + libName = "polars_lazy"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "ahash"; + packageId = "ahash"; + } + { + name = "bitflags"; + packageId = "bitflags 2.6.0"; + } + { + name = "glob"; + packageId = "glob"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "polars-arrow"; + packageId = "polars-arrow"; + rename = "arrow"; + usesDefaultFeatures = false; + features = [ "compute_aggregate" "compute_arithmetics" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_if_then_else" ]; + } + { + name = "polars-core"; + packageId = "polars-core"; + usesDefaultFeatures = false; + features = [ "lazy" "zip_with" "random" ]; + } + { + name = "polars-io"; + packageId = "polars-io"; + usesDefaultFeatures = false; + features = [ "lazy" ]; + } + { + name = "polars-ops"; + packageId = "polars-ops"; + usesDefaultFeatures = false; + } + { + name = "polars-pipe"; + packageId = "polars-pipe"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "polars-plan"; + packageId = "polars-plan"; + usesDefaultFeatures = false; + } + { + name = "polars-time"; + packageId = "polars-time"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "polars-utils"; + packageId = "polars-utils"; + usesDefaultFeatures = false; + } + { + name = "rayon"; + packageId = "rayon"; + } + { + name = "smartstring"; + packageId = "smartstring"; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "abs" = [ "polars-plan/abs" ]; + "approx_unique" = [ "polars-plan/approx_unique" ]; + "arg_where" = [ "polars-plan/arg_where" ]; + "array_any_all" = [ "polars-ops/array_any_all" "polars-plan/array_any_all" "dtype-array" ]; + "asof_join" = [ "polars-plan/asof_join" "polars-time" "polars-ops/asof_join" ]; + "async" = [ "polars-plan/async" "polars-io/cloud" "polars-pipe?/async" ]; + "bigidx" = [ "polars-plan/bigidx" ]; + "binary_encoding" = [ "polars-plan/binary_encoding" ]; + "chunked_ids" = [ "polars-plan/chunked_ids" "polars-core/chunked_ids" "polars-ops/chunked_ids" ]; + "cloud" = [ "async" "polars-pipe?/cloud" "polars-plan/cloud" "tokio" "futures" ]; + "cloud_write" = [ "cloud" ]; + "coalesce" = [ "polars-plan/coalesce" ]; + "concat_str" = [ "polars-plan/concat_str" ]; + "cov" = [ "polars-ops/cov" "polars-plan/cov" ]; + "cross_join" = [ "polars-plan/cross_join" "polars-pipe?/cross_join" "polars-ops/cross_join" ]; + "cse" = [ "polars-plan/cse" ]; + "csv" = [ "polars-io/csv" "polars-plan/csv" "polars-pipe?/csv" ]; + "cum_agg" = [ "polars-plan/cum_agg" ]; + "cutqcut" = [ "polars-plan/cutqcut" "polars-ops/cutqcut" ]; + "date_offset" = [ "polars-plan/date_offset" ]; + "diff" = [ "polars-plan/diff" "polars-plan/diff" ]; + "dot_diagram" = [ "polars-plan/dot_diagram" ]; + "dtype-array" = [ "polars-plan/dtype-array" "polars-pipe?/dtype-array" "polars-ops/dtype-array" ]; + "dtype-categorical" = [ "polars-plan/dtype-categorical" "polars-pipe?/dtype-categorical" ]; + "dtype-date" = [ "polars-plan/dtype-date" "polars-time/dtype-date" "temporal" ]; + "dtype-datetime" = [ "polars-plan/dtype-datetime" "polars-time/dtype-datetime" "temporal" ]; + "dtype-decimal" = [ "polars-plan/dtype-decimal" "polars-pipe?/dtype-decimal" ]; + "dtype-duration" = [ "polars-plan/dtype-duration" "polars-time/dtype-duration" "temporal" ]; + "dtype-i16" = [ "polars-plan/dtype-i16" "polars-pipe?/dtype-i16" ]; + "dtype-i8" = [ "polars-plan/dtype-i8" "polars-pipe?/dtype-i8" ]; + "dtype-struct" = [ "polars-plan/dtype-struct" ]; + "dtype-time" = [ "polars-core/dtype-time" "temporal" ]; + "dtype-u16" = [ "polars-plan/dtype-u16" "polars-pipe?/dtype-u16" ]; + "dtype-u8" = [ "polars-plan/dtype-u8" "polars-pipe?/dtype-u8" ]; + "dynamic_group_by" = [ "polars-plan/dynamic_group_by" "polars-time" "temporal" ]; + "ewma" = [ "polars-plan/ewma" ]; + "extract_groups" = [ "polars-plan/extract_groups" ]; + "extract_jsonpath" = [ "polars-plan/extract_jsonpath" "polars-ops/extract_jsonpath" ]; + "fmt" = [ "polars-core/fmt" "polars-plan/fmt" ]; + "fused" = [ "polars-plan/fused" "polars-ops/fused" ]; + "futures" = [ "dep:futures" ]; + "hist" = [ "polars-plan/hist" ]; + "horizontal_concat" = [ "polars-plan/horizontal_concat" "polars-core/horizontal_concat" ]; + "interpolate" = [ "polars-plan/interpolate" ]; + "ipc" = [ "polars-io/ipc" "polars-plan/ipc" "polars-pipe?/ipc" ]; + "is_first_distinct" = [ "polars-plan/is_first_distinct" ]; + "is_in" = [ "polars-plan/is_in" "polars-ops/is_in" ]; + "is_last_distinct" = [ "polars-plan/is_last_distinct" ]; + "is_unique" = [ "polars-plan/is_unique" ]; + "json" = [ "polars-io/json" "polars-plan/json" "polars-json" "polars-pipe/json" ]; + "list_any_all" = [ "polars-ops/list_any_all" "polars-plan/list_any_all" ]; + "list_count" = [ "polars-ops/list_count" "polars-plan/list_count" ]; + "list_drop_nulls" = [ "polars-ops/list_drop_nulls" "polars-plan/list_drop_nulls" ]; + "list_gather" = [ "polars-ops/list_gather" "polars-plan/list_gather" ]; + "list_sample" = [ "polars-ops/list_sample" "polars-plan/list_sample" ]; + "list_sets" = [ "polars-plan/list_sets" "polars-ops/list_sets" ]; + "list_to_struct" = [ "polars-plan/list_to_struct" ]; + "log" = [ "polars-plan/log" ]; + "merge_sorted" = [ "polars-plan/merge_sorted" ]; + "meta" = [ "polars-plan/meta" ]; + "mode" = [ "polars-plan/mode" ]; + "moment" = [ "polars-plan/moment" "polars-ops/moment" ]; + "nightly" = [ "polars-core/nightly" "polars-pipe?/nightly" "polars-plan/nightly" ]; + "object" = [ "polars-plan/object" ]; + "panic_on_schema" = [ "polars-plan/panic_on_schema" ]; + "parquet" = [ "polars-io/parquet" "polars-plan/parquet" "polars-pipe?/parquet" ]; + "pct_change" = [ "polars-plan/pct_change" ]; + "peaks" = [ "polars-plan/peaks" ]; + "pivot" = [ "polars-core/rows" "polars-ops/pivot" ]; + "polars-json" = [ "dep:polars-json" ]; + "polars-pipe" = [ "dep:polars-pipe" ]; + "polars-time" = [ "dep:polars-time" ]; + "propagate_nans" = [ "polars-plan/propagate_nans" ]; + "pyo3" = [ "dep:pyo3" ]; + "python" = [ "pyo3" "polars-plan/python" "polars-core/python" "polars-io/python" ]; + "random" = [ "polars-plan/random" ]; + "range" = [ "polars-plan/range" ]; + "rank" = [ "polars-plan/rank" ]; + "regex" = [ "polars-plan/regex" ]; + "repeat_by" = [ "polars-plan/repeat_by" ]; + "replace" = [ "polars-plan/replace" ]; + "rle" = [ "polars-plan/rle" "polars-ops/rle" ]; + "rolling_window" = [ "polars-plan/rolling_window" "polars-time/rolling_window" ]; + "round_series" = [ "polars-plan/round_series" "polars-ops/round_series" ]; + "row_hash" = [ "polars-plan/row_hash" ]; + "search_sorted" = [ "polars-plan/search_sorted" ]; + "semi_anti_join" = [ "polars-plan/semi_anti_join" ]; + "serde" = [ "polars-plan/serde" "arrow/serde" "polars-core/serde-lazy" "polars-time?/serde" "polars-io/serde" "polars-ops/serde" ]; + "sign" = [ "polars-plan/sign" ]; + "streaming" = [ "chunked_ids" "polars-pipe" "polars-plan/streaming" "polars-ops/chunked_ids" ]; + "string_encoding" = [ "polars-plan/string_encoding" ]; + "string_pad" = [ "polars-plan/string_pad" ]; + "string_reverse" = [ "polars-plan/string_reverse" ]; + "string_to_integer" = [ "polars-plan/string_to_integer" ]; + "strings" = [ "polars-plan/strings" ]; + "temporal" = [ "dtype-datetime" "dtype-date" "dtype-time" "dtype-i8" "dtype-i16" "dtype-duration" "polars-plan/temporal" ]; + "test" = [ "polars-plan/debugging" "panic_on_schema" "rolling_window" "rank" "round_series" "csv" "dtype-categorical" "cum_agg" "regex" "polars-core/fmt" "diff" "abs" "parquet" "ipc" "dtype-date" ]; + "test_all" = [ "test" "strings" "regex" "ipc" "row_hash" "string_pad" "string_to_integer" "search_sorted" "top_k" "pivot" "semi_anti_join" "cse" ]; + "timezones" = [ "polars-plan/timezones" ]; + "tokio" = [ "dep:tokio" ]; + "top_k" = [ "polars-plan/top_k" ]; + "trigonometry" = [ "polars-plan/trigonometry" ]; + "true_div" = [ "polars-plan/true_div" ]; + "unique_counts" = [ "polars-plan/unique_counts" ]; + }; + resolvedDefaultFeatures = [ "abs" "cross_join" "csv" "cum_agg" "dtype-date" "dtype-datetime" "dtype-duration" "dtype-i16" "dtype-i8" "dtype-time" "is_in" "log" "meta" "parquet" "polars-time" "regex" "round_series" "strings" "temporal" "trigonometry" ]; + }; + "polars-ops" = rec { + crateName = "polars-ops"; + version = "0.36.2"; + edition = "2021"; + sha256 = "13m7dh4vpdmcah04a7kql933l7y7045f0hybbmgff4dbav2ay29f"; + libName = "polars_ops"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "ahash"; + packageId = "ahash"; + } + { + name = "argminmax"; + packageId = "argminmax"; + usesDefaultFeatures = false; + features = [ "float" ]; + } + { + name = "bytemuck"; + packageId = "bytemuck"; + features = [ "derive" "extern_crate_alloc" ]; + } + { + name = "either"; + packageId = "either"; + } + { + name = "hashbrown"; + packageId = "hashbrown"; + features = [ "rayon" "ahash" ]; + } + { + name = "indexmap"; + packageId = "indexmap"; + features = [ "std" ]; + } + { + name = "memchr"; + packageId = "memchr"; + } + { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "polars-arrow"; + packageId = "polars-arrow"; + rename = "arrow"; + usesDefaultFeatures = false; + features = [ "compute_aggregate" "compute_arithmetics" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_if_then_else" ]; + } + { + name = "polars-compute"; + packageId = "polars-compute"; + usesDefaultFeatures = false; + } + { + name = "polars-core"; + packageId = "polars-core"; + usesDefaultFeatures = false; + features = [ "algorithm_group_by" "zip_with" ]; + } + { + name = "polars-error"; + packageId = "polars-error"; + usesDefaultFeatures = false; + } + { + name = "polars-utils"; + packageId = "polars-utils"; + usesDefaultFeatures = false; + } + { + name = "rayon"; + packageId = "rayon"; + } + { + name = "regex"; + packageId = "regex"; + } + { + name = "smartstring"; + packageId = "smartstring"; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "aho-corasick" = [ "dep:aho-corasick" ]; + "array_any_all" = [ "dtype-array" ]; + "asof_join" = [ "polars-core/asof_join" ]; + "base64" = [ "dep:base64" ]; + "big_idx" = [ "polars-core/bigidx" ]; + "binary_encoding" = [ "base64" "hex" ]; + "chrono" = [ "dep:chrono" ]; + "chrono-tz" = [ "dep:chrono-tz" ]; + "chunked_ids" = [ "polars-core/chunked_ids" ]; + "cutqcut" = [ "dtype-categorical" "dtype-struct" ]; + "dtype-array" = [ "polars-core/dtype-array" ]; + "dtype-categorical" = [ "polars-core/dtype-categorical" ]; + "dtype-date" = [ "polars-core/dtype-date" "polars-core/temporal" ]; + "dtype-datetime" = [ "polars-core/dtype-datetime" "polars-core/temporal" ]; + "dtype-decimal" = [ "polars-core/dtype-decimal" ]; + "dtype-duration" = [ "polars-core/dtype-duration" "polars-core/temporal" ]; + "dtype-i16" = [ "polars-core/dtype-i16" ]; + "dtype-i8" = [ "polars-core/dtype-i8" ]; + "dtype-struct" = [ "polars-core/dtype-struct" "polars-core/temporal" ]; + "dtype-time" = [ "polars-core/dtype-time" "polars-core/temporal" ]; + "dtype-u16" = [ "polars-core/dtype-u16" ]; + "dtype-u8" = [ "polars-core/dtype-u8" ]; + "extract_groups" = [ "dtype-struct" "polars-core/regex" ]; + "extract_jsonpath" = [ "serde_json" "jsonpath_lib" "polars-json" ]; + "find_many" = [ "aho-corasick" ]; + "group_by_list" = [ "polars-core/group_by_list" ]; + "hex" = [ "dep:hex" ]; + "hist" = [ "dtype-categorical" "dtype-struct" ]; + "is_in" = [ "polars-core/reinterpret" ]; + "jsonpath_lib" = [ "dep:jsonpath_lib" ]; + "list_to_struct" = [ "polars-core/dtype-struct" ]; + "nightly" = [ "polars-utils/nightly" ]; + "object" = [ "polars-core/object" ]; + "pct_change" = [ "diff" ]; + "performant" = [ "polars-core/performant" "fused" ]; + "pivot" = [ "polars-core/reinterpret" ]; + "polars-json" = [ "dep:polars-json" ]; + "rand" = [ "dep:rand" ]; + "rand_distr" = [ "dep:rand_distr" ]; + "random" = [ "rand" "rand_distr" ]; + "rank" = [ "rand" ]; + "replace" = [ "is_in" ]; + "rle" = [ "dtype-struct" ]; + "rolling_window" = [ "polars-core/rolling_window" ]; + "serde" = [ "dep:serde" ]; + "serde_json" = [ "dep:serde_json" ]; + "simd" = [ "argminmax/nightly_simd" ]; + "string_encoding" = [ "base64" "hex" ]; + "string_pad" = [ "polars-core/strings" ]; + "string_reverse" = [ "polars-core/strings" "unicode-reverse" ]; + "string_to_integer" = [ "polars-core/strings" ]; + "strings" = [ "polars-core/strings" ]; + "timezones" = [ "chrono-tz" "chrono" ]; + "unicode-reverse" = [ "dep:unicode-reverse" ]; + }; + resolvedDefaultFeatures = [ "abs" "cross_join" "cum_agg" "dtype-date" "dtype-datetime" "dtype-duration" "is_in" "log" "round_series" "search_sorted" "strings" ]; + }; + "polars-parquet" = rec { + crateName = "polars-parquet"; + version = "0.36.2"; + edition = "2021"; + sha256 = "0gay037sw5hcg2q93pxcfh7krcchl1px8g838d8vhjpnn5klv8kv"; + libName = "polars_parquet"; + authors = [ + "Jorge C. Leitao <jorgecarleitao@gmail.com>" + "Apache Arrow <dev@arrow.apache.org>" + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "ahash"; + packageId = "ahash"; + } + { + name = "async-stream"; + packageId = "async-stream"; + optional = true; + } + { + name = "base64"; + packageId = "base64"; + } + { + name = "brotli"; + packageId = "brotli"; + optional = true; + } + { + name = "ethnum"; + packageId = "ethnum"; + } + { + name = "flate2"; + packageId = "flate2"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "futures"; + packageId = "futures"; + optional = true; + } + { + name = "lz4"; + packageId = "lz4"; + optional = true; + } + { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "parquet-format-safe"; + packageId = "parquet-format-safe"; + } + { + name = "polars-arrow"; + packageId = "polars-arrow"; + rename = "arrow"; + usesDefaultFeatures = false; + features = [ "compute_aggregate" "compute_arithmetics" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_if_then_else" "io_ipc" ]; + } + { + name = "polars-error"; + packageId = "polars-error"; + usesDefaultFeatures = false; + } + { + name = "polars-utils"; + packageId = "polars-utils"; + usesDefaultFeatures = false; + } + { + name = "seq-macro"; + packageId = "seq-macro"; + usesDefaultFeatures = false; + } + { + name = "simdutf8"; + packageId = "simdutf8"; + } + { + name = "snap"; + packageId = "snap"; + optional = true; + } + { + name = "streaming-decompression"; + packageId = "streaming-decompression"; + } + { + name = "zstd"; + packageId = "zstd"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "async" = [ "async-stream" "futures" "parquet-format-safe/async" ]; + "async-stream" = [ "dep:async-stream" ]; + "bloom_filter" = [ "xxhash-rust" ]; + "brotli" = [ "dep:brotli" ]; + "compression" = [ "zstd" "gzip" "snappy" "lz4" "brotli" ]; + "fallible-streaming-iterator" = [ "dep:fallible-streaming-iterator" ]; + "flate2" = [ "dep:flate2" ]; + "futures" = [ "dep:futures" ]; + "gzip" = [ "flate2/rust_backend" ]; + "gzip_zlib_ng" = [ "flate2/zlib-ng" ]; + "lz4" = [ "dep:lz4" ]; + "serde" = [ "dep:serde" ]; + "serde_types" = [ "serde" ]; + "snap" = [ "dep:snap" ]; + "snappy" = [ "snap" ]; + "xxhash-rust" = [ "dep:xxhash-rust" ]; + "zstd" = [ "dep:zstd" ]; + }; + resolvedDefaultFeatures = [ "async" "async-stream" "brotli" "compression" "flate2" "futures" "gzip" "lz4" "snap" "snappy" "zstd" ]; + }; + "polars-pipe" = rec { + crateName = "polars-pipe"; + version = "0.36.2"; + edition = "2021"; + sha256 = "00217q51mnq7i57k3sax293xnwghm5hridbpgl11fffcfg8fmdyr"; + libName = "polars_pipe"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "crossbeam-channel"; + packageId = "crossbeam-channel"; + } + { + name = "crossbeam-queue"; + packageId = "crossbeam-queue"; + } + { + name = "enum_dispatch"; + packageId = "enum_dispatch"; + } + { + name = "hashbrown"; + packageId = "hashbrown"; + features = [ "rayon" "ahash" ]; + } + { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "polars-arrow"; + packageId = "polars-arrow"; + rename = "arrow"; + usesDefaultFeatures = false; + features = [ "compute_aggregate" "compute_arithmetics" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_if_then_else" ]; + } + { + name = "polars-compute"; + packageId = "polars-compute"; + usesDefaultFeatures = false; + } + { + name = "polars-core"; + packageId = "polars-core"; + usesDefaultFeatures = false; + features = [ "lazy" "zip_with" "random" "rows" "chunked_ids" ]; + } + { + name = "polars-io"; + packageId = "polars-io"; + usesDefaultFeatures = false; + features = [ "ipc" ]; + } + { + name = "polars-ops"; + packageId = "polars-ops"; + usesDefaultFeatures = false; + features = [ "search_sorted" ]; + } + { + name = "polars-plan"; + packageId = "polars-plan"; + usesDefaultFeatures = false; + } + { + name = "polars-row"; + packageId = "polars-row"; + usesDefaultFeatures = false; + } + { + name = "polars-utils"; + packageId = "polars-utils"; + usesDefaultFeatures = false; + features = [ "sysinfo" ]; + } + { + name = "rayon"; + packageId = "rayon"; + } + { + name = "smartstring"; + packageId = "smartstring"; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "async" = [ "polars-plan/async" "polars-io/async" ]; + "cloud" = [ "async" "polars-io/cloud" "polars-plan/cloud" "tokio" "futures" ]; + "cross_join" = [ "polars-ops/cross_join" ]; + "csv" = [ "polars-plan/csv" "polars-io/csv" ]; + "dtype-array" = [ "polars-core/dtype-array" ]; + "dtype-categorical" = [ "polars-core/dtype-categorical" ]; + "dtype-decimal" = [ "polars-core/dtype-decimal" ]; + "dtype-i16" = [ "polars-core/dtype-i16" ]; + "dtype-i8" = [ "polars-core/dtype-i8" ]; + "dtype-u16" = [ "polars-core/dtype-u16" ]; + "dtype-u8" = [ "polars-core/dtype-u8" ]; + "futures" = [ "dep:futures" ]; + "ipc" = [ "polars-plan/ipc" "polars-io/ipc" ]; + "json" = [ "polars-plan/json" "polars-io/json" ]; + "nightly" = [ "polars-core/nightly" "polars-utils/nightly" "hashbrown/nightly" ]; + "parquet" = [ "polars-plan/parquet" "polars-io/parquet" "polars-io/async" ]; + "test" = [ "polars-core/chunked_ids" ]; + "tokio" = [ "dep:tokio" ]; + }; + resolvedDefaultFeatures = [ "cross_join" "csv" "dtype-i16" "dtype-i8" "parquet" ]; + }; + "polars-plan" = rec { + crateName = "polars-plan"; + version = "0.36.2"; + edition = "2021"; + sha256 = "1l5ca38v7ksq4595wdr6wsd74pdgszwivq9y8wfc6l6h4ib1fjiq"; + libName = "polars_plan"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "ahash"; + packageId = "ahash"; + } + { + name = "bytemuck"; + packageId = "bytemuck"; + features = [ "derive" "extern_crate_alloc" ]; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "percent-encoding"; + packageId = "percent-encoding"; + } + { + name = "polars-arrow"; + packageId = "polars-arrow"; + rename = "arrow"; + usesDefaultFeatures = false; + features = [ "compute_aggregate" "compute_arithmetics" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_if_then_else" ]; + } + { + name = "polars-core"; + packageId = "polars-core"; + usesDefaultFeatures = false; + features = [ "lazy" "zip_with" "random" ]; + } + { + name = "polars-io"; + packageId = "polars-io"; + usesDefaultFeatures = false; + features = [ "lazy" ]; + } + { + name = "polars-ops"; + packageId = "polars-ops"; + usesDefaultFeatures = false; + } + { + name = "polars-parquet"; + packageId = "polars-parquet"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "polars-time"; + packageId = "polars-time"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "polars-utils"; + packageId = "polars-utils"; + usesDefaultFeatures = false; + } + { + name = "rayon"; + packageId = "rayon"; + } + { + name = "regex"; + packageId = "regex"; + optional = true; + } + { + name = "smartstring"; + packageId = "smartstring"; + } + { + name = "strum_macros"; + packageId = "strum_macros"; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "abs" = [ "polars-ops/abs" ]; + "approx_unique" = [ "polars-ops/approx_unique" ]; + "array_any_all" = [ "polars-ops/array_any_all" "dtype-array" ]; + "asof_join" = [ "polars-core/asof_join" "polars-time" "polars-ops/asof_join" ]; + "async" = [ "polars-io/async" ]; + "bigidx" = [ "polars-core/bigidx" ]; + "binary_encoding" = [ "polars-ops/binary_encoding" ]; + "chrono" = [ "dep:chrono" ]; + "chrono-tz" = [ "dep:chrono-tz" ]; + "chunked_ids" = [ "polars-core/chunked_ids" ]; + "ciborium" = [ "dep:ciborium" ]; + "cloud" = [ "async" "polars-io/cloud" ]; + "cov" = [ "polars-ops/cov" ]; + "cross_join" = [ "polars-ops/cross_join" ]; + "csv" = [ "polars-io/csv" ]; + "cum_agg" = [ "polars-ops/cum_agg" ]; + "cutqcut" = [ "polars-ops/cutqcut" ]; + "date_offset" = [ "polars-time" "chrono" ]; + "diff" = [ "polars-ops/diff" ]; + "dtype-array" = [ "polars-core/dtype-array" "polars-ops/dtype-array" ]; + "dtype-categorical" = [ "polars-core/dtype-categorical" ]; + "dtype-date" = [ "polars-core/dtype-date" "polars-time/dtype-date" "temporal" ]; + "dtype-datetime" = [ "polars-core/dtype-datetime" "polars-time/dtype-datetime" "temporal" ]; + "dtype-decimal" = [ "polars-core/dtype-decimal" ]; + "dtype-duration" = [ "polars-core/dtype-duration" "polars-time/dtype-duration" "temporal" ]; + "dtype-i16" = [ "polars-core/dtype-i16" ]; + "dtype-i8" = [ "polars-core/dtype-i8" ]; + "dtype-struct" = [ "polars-core/dtype-struct" ]; + "dtype-time" = [ "polars-core/dtype-time" "polars-time/dtype-time" ]; + "dtype-u16" = [ "polars-core/dtype-u16" ]; + "dtype-u8" = [ "polars-core/dtype-u8" ]; + "dynamic_group_by" = [ "polars-core/dynamic_group_by" ]; + "ewma" = [ "polars-ops/ewma" ]; + "extract_groups" = [ "regex" "dtype-struct" "polars-ops/extract_groups" ]; + "extract_jsonpath" = [ "polars-ops/extract_jsonpath" ]; + "ffi_plugin" = [ "libloading" "polars-ffi" ]; + "find_many" = [ "polars-ops/find_many" ]; + "fmt" = [ "polars-core/fmt" ]; + "fused" = [ "polars-ops/fused" ]; + "futures" = [ "dep:futures" ]; + "hist" = [ "polars-ops/hist" ]; + "interpolate" = [ "polars-ops/interpolate" ]; + "ipc" = [ "polars-io/ipc" ]; + "is_first_distinct" = [ "polars-core/is_first_distinct" "polars-ops/is_first_distinct" ]; + "is_in" = [ "polars-ops/is_in" ]; + "is_last_distinct" = [ "polars-core/is_last_distinct" "polars-ops/is_last_distinct" ]; + "is_unique" = [ "polars-ops/is_unique" ]; + "json" = [ "polars-io/json" "polars-json" ]; + "libloading" = [ "dep:libloading" ]; + "list_any_all" = [ "polars-ops/list_any_all" ]; + "list_count" = [ "polars-ops/list_count" ]; + "list_drop_nulls" = [ "polars-ops/list_drop_nulls" ]; + "list_gather" = [ "polars-ops/list_gather" ]; + "list_sample" = [ "polars-ops/list_sample" ]; + "list_sets" = [ "polars-ops/list_sets" ]; + "list_to_struct" = [ "polars-ops/list_to_struct" ]; + "log" = [ "polars-ops/log" ]; + "merge_sorted" = [ "polars-ops/merge_sorted" ]; + "mode" = [ "polars-ops/mode" ]; + "moment" = [ "polars-ops/moment" ]; + "nightly" = [ "polars-utils/nightly" "polars-ops/nightly" ]; + "object" = [ "polars-core/object" ]; + "parquet" = [ "polars-io/parquet" "polars-parquet" ]; + "pct_change" = [ "polars-ops/pct_change" ]; + "peaks" = [ "polars-ops/peaks" ]; + "pivot" = [ "polars-core/rows" "polars-ops/pivot" ]; + "polars-ffi" = [ "dep:polars-ffi" ]; + "polars-json" = [ "dep:polars-json" ]; + "polars-parquet" = [ "dep:polars-parquet" ]; + "polars-time" = [ "dep:polars-time" ]; + "propagate_nans" = [ "polars-ops/propagate_nans" ]; + "python" = [ "dep:pyo3" "ciborium" ]; + "random" = [ "polars-core/random" ]; + "rank" = [ "polars-ops/rank" ]; + "regex" = [ "dep:regex" ]; + "repeat_by" = [ "polars-ops/repeat_by" ]; + "replace" = [ "polars-ops/replace" ]; + "rle" = [ "polars-ops/rle" ]; + "rolling_window" = [ "polars-core/rolling_window" "polars-time/rolling_window" "polars-ops/rolling_window" "polars-time/rolling_window" ]; + "round_series" = [ "polars-ops/round_series" ]; + "row_hash" = [ "polars-core/row_hash" "polars-ops/hash" ]; + "search_sorted" = [ "polars-ops/search_sorted" ]; + "semi_anti_join" = [ "polars-ops/semi_anti_join" ]; + "serde" = [ "dep:serde" "polars-core/serde-lazy" "polars-time/serde" "polars-io/serde" "polars-ops/serde" ]; + "string_encoding" = [ "polars-ops/string_encoding" ]; + "string_pad" = [ "polars-ops/string_pad" ]; + "string_reverse" = [ "polars-ops/string_reverse" ]; + "string_to_integer" = [ "polars-ops/string_to_integer" ]; + "strings" = [ "polars-core/strings" "polars-ops/strings" ]; + "temporal" = [ "polars-core/temporal" "dtype-date" "dtype-datetime" "dtype-time" "dtype-i8" "dtype-i16" ]; + "timezones" = [ "chrono-tz" "polars-time/timezones" "polars-core/timezones" "regex" ]; + "top_k" = [ "polars-ops/top_k" ]; + "unique_counts" = [ "polars-ops/unique_counts" ]; + }; + resolvedDefaultFeatures = [ "abs" "cross_join" "csv" "cum_agg" "dtype-date" "dtype-datetime" "dtype-duration" "dtype-i16" "dtype-i8" "dtype-time" "is_in" "log" "meta" "parquet" "polars-parquet" "polars-time" "regex" "round_series" "strings" "temporal" "trigonometry" ]; + }; + "polars-row" = rec { + crateName = "polars-row"; + version = "0.36.2"; + edition = "2021"; + sha256 = "0by7x6jlj5dwr3f1gj49v8w65l3kpqhwhzb9qzlv6gdqrdx2ycij"; + libName = "polars_row"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "polars-arrow"; + packageId = "polars-arrow"; + rename = "arrow"; + usesDefaultFeatures = false; + features = [ "compute_aggregate" "compute_arithmetics" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_if_then_else" ]; + } + { + name = "polars-error"; + packageId = "polars-error"; + usesDefaultFeatures = false; + } + { + name = "polars-utils"; + packageId = "polars-utils"; + usesDefaultFeatures = false; + } + ]; + + }; + "polars-sql" = rec { + crateName = "polars-sql"; + version = "0.36.2"; + edition = "2021"; + sha256 = "1dcmm993gycw75a6c5hxcr6h2cy6fa2r3hsbx19h9zgxvxnlq2wz"; + libName = "polars_sql"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "polars-arrow"; + packageId = "polars-arrow"; + rename = "arrow"; + usesDefaultFeatures = false; + features = [ "compute_aggregate" "compute_arithmetics" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_if_then_else" ]; + } + { + name = "polars-core"; + packageId = "polars-core"; + usesDefaultFeatures = false; + } + { + name = "polars-error"; + packageId = "polars-error"; + usesDefaultFeatures = false; + } + { + name = "polars-lazy"; + packageId = "polars-lazy"; + usesDefaultFeatures = false; + features = [ "strings" "cross_join" "trigonometry" "abs" "round_series" "log" "regex" "is_in" "meta" "cum_agg" "dtype-date" ]; + } + { + name = "polars-plan"; + packageId = "polars-plan"; + usesDefaultFeatures = false; + } + { + name = "rand"; + packageId = "rand"; + } + { + name = "serde"; + packageId = "serde"; + } + { + name = "serde_json"; + packageId = "serde_json"; + } + { + name = "sqlparser"; + packageId = "sqlparser"; + } + ]; + features = { + "csv" = [ "polars-lazy/csv" ]; + "diagonal_concat" = [ "polars-lazy/diagonal_concat" ]; + "ipc" = [ "polars-lazy/ipc" ]; + "json" = [ "polars-lazy/json" ]; + "parquet" = [ "polars-lazy/parquet" ]; + "semi_anti_join" = [ "polars-lazy/semi_anti_join" ]; + }; + resolvedDefaultFeatures = [ "csv" "parquet" ]; + }; + "polars-time" = rec { + crateName = "polars-time"; + version = "0.36.2"; + edition = "2021"; + sha256 = "1l24fmpv5v1qshxfd4592z8x6bnjlwy4njhf9rcbdlbbr6gn9qny"; + libName = "polars_time"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "atoi"; + packageId = "atoi"; + } + { + name = "chrono"; + packageId = "chrono"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "now"; + packageId = "now"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "polars-arrow"; + packageId = "polars-arrow"; + rename = "arrow"; + usesDefaultFeatures = false; + features = [ "compute_aggregate" "compute_arithmetics" "compute_boolean" "compute_boolean_kleene" "compute_cast" "compute_comparison" "compute_concatenate" "compute_filter" "compute_if_then_else" "compute" "temporal" ]; + } + { + name = "polars-core"; + packageId = "polars-core"; + usesDefaultFeatures = false; + features = [ "dtype-datetime" "dtype-duration" "dtype-time" "dtype-date" ]; + } + { + name = "polars-error"; + packageId = "polars-error"; + usesDefaultFeatures = false; + } + { + name = "polars-ops"; + packageId = "polars-ops"; + usesDefaultFeatures = false; + } + { + name = "polars-utils"; + packageId = "polars-utils"; + usesDefaultFeatures = false; + } + { + name = "regex"; + packageId = "regex"; + } + { + name = "smartstring"; + packageId = "smartstring"; + } + ]; + features = { + "chrono-tz" = [ "dep:chrono-tz" ]; + "dtype-date" = [ "polars-core/dtype-date" "polars-core/temporal" ]; + "dtype-datetime" = [ "polars-core/dtype-date" "polars-core/temporal" ]; + "dtype-duration" = [ "polars-core/dtype-duration" "polars-core/temporal" ]; + "dtype-time" = [ "polars-core/dtype-time" "polars-core/temporal" ]; + "fmt" = [ "polars-core/fmt" ]; + "rolling_window" = [ "polars-core/rolling_window" "dtype-duration" ]; + "serde" = [ "dep:serde" ]; + "test" = [ "dtype-date" "dtype-datetime" "polars-core/fmt" ]; + "timezones" = [ "chrono-tz" "dtype-datetime" "polars-core/timezones" "arrow/timezones" "polars-ops/timezones" ]; + }; + resolvedDefaultFeatures = [ "dtype-date" "dtype-datetime" "dtype-duration" "dtype-time" ]; + }; + "polars-utils" = rec { + crateName = "polars-utils"; + version = "0.36.2"; + edition = "2021"; + sha256 = "1nmvfqwyzbaxcw457amspz479y5vcnpalq043awxfixdfx5clx5i"; + libName = "polars_utils"; + authors = [ + "Ritchie Vink <ritchie46@gmail.com>" + ]; + dependencies = [ + { + name = "ahash"; + packageId = "ahash"; + } + { + name = "bytemuck"; + packageId = "bytemuck"; + features = [ "derive" "extern_crate_alloc" ]; + } + { + name = "hashbrown"; + packageId = "hashbrown"; + features = [ "rayon" "ahash" ]; + } + { + name = "indexmap"; + packageId = "indexmap"; + features = [ "std" ]; + } + { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "polars-error"; + packageId = "polars-error"; + usesDefaultFeatures = false; + } + { + name = "rayon"; + packageId = "rayon"; + } + { + name = "smartstring"; + packageId = "smartstring"; + } + { + name = "sysinfo"; + packageId = "sysinfo"; + optional = true; + usesDefaultFeatures = false; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "sysinfo" = [ "dep:sysinfo" ]; + }; + resolvedDefaultFeatures = [ "sysinfo" ]; + }; + "portable-atomic" = rec { + crateName = "portable-atomic"; + version = "1.6.0"; + edition = "2018"; + sha256 = "1h77x9qx7pns0d66vdrmdbmwpi7586h7ysnkdnhrn5mwi2cyyw3i"; + libName = "portable_atomic"; + features = { + "critical-section" = [ "dep:critical-section" ]; + "default" = [ "fallback" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "fallback" ]; + }; + "powerfmt" = rec { + crateName = "powerfmt"; + version = "0.2.0"; + edition = "2021"; + sha256 = "14ckj2xdpkhv3h6l5sdmb9f1d57z8hbfpdldjc2vl5givq2y77j3"; + authors = [ + "Jacob Pratt <jacob@jhpratt.dev>" + ]; + features = { + "default" = [ "std" "macros" ]; + "macros" = [ "dep:powerfmt-macros" ]; + "std" = [ "alloc" ]; + }; + }; + "ppv-lite86" = rec { + crateName = "ppv-lite86"; + version = "0.2.17"; + edition = "2018"; + sha256 = "1pp6g52aw970adv3x2310n7glqnji96z0a9wiamzw89ibf0ayh2v"; + libName = "ppv_lite86"; + authors = [ + "The CryptoCorrosion Contributors" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "simd" "std" ]; + }; + "proc-macro2" = rec { + crateName = "proc-macro2"; + version = "1.0.88"; + edition = "2021"; + sha256 = "1ygjzcawivbziakc6sfc816alabvnp6whlm3g6kxamqyvg2pyfkw"; + libName = "proc_macro2"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "unicode-ident"; + packageId = "unicode-ident"; + } + ]; + features = { + "default" = [ "proc-macro" ]; + }; + resolvedDefaultFeatures = [ "default" "proc-macro" ]; + }; + "quote" = rec { + crateName = "quote"; + version = "1.0.37"; + edition = "2018"; + sha256 = "1brklraw2g34bxy9y4q1nbrccn7bv36ylihv12c9vlcii55x7fdm"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "proc-macro" ]; + "proc-macro" = [ "proc-macro2/proc-macro" ]; + }; + resolvedDefaultFeatures = [ "default" "proc-macro" ]; + }; + "rand" = rec { + crateName = "rand"; + version = "0.8.5"; + edition = "2018"; + sha256 = "013l6931nn7gkc23jz5mm3qdhf93jjf0fg64nz2lp4i51qd8vbrl"; + authors = [ + "The Rand Project Developers" + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: (target."unix" or false); + } + { + name = "rand_chacha"; + packageId = "rand_chacha"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "rand_core"; + packageId = "rand_core"; + } + ]; + features = { + "alloc" = [ "rand_core/alloc" ]; + "default" = [ "std" "std_rng" ]; + "getrandom" = [ "rand_core/getrandom" ]; + "libc" = [ "dep:libc" ]; + "log" = [ "dep:log" ]; + "packed_simd" = [ "dep:packed_simd" ]; + "rand_chacha" = [ "dep:rand_chacha" ]; + "serde" = [ "dep:serde" ]; + "serde1" = [ "serde" "rand_core/serde1" ]; + "simd_support" = [ "packed_simd" ]; + "std" = [ "rand_core/std" "rand_chacha/std" "alloc" "getrandom" "libc" ]; + "std_rng" = [ "rand_chacha" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "getrandom" "libc" "rand_chacha" "small_rng" "std" "std_rng" ]; + }; + "rand_chacha" = rec { + crateName = "rand_chacha"; + version = "0.3.1"; + edition = "2018"; + sha256 = "123x2adin558xbhvqb8w4f6syjsdkmqff8cxwhmjacpsl1ihmhg6"; + authors = [ + "The Rand Project Developers" + "The Rust Project Developers" + "The CryptoCorrosion Contributors" + ]; + dependencies = [ + { + name = "ppv-lite86"; + packageId = "ppv-lite86"; + usesDefaultFeatures = false; + features = [ "simd" ]; + } + { + name = "rand_core"; + packageId = "rand_core"; + } + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + "serde1" = [ "serde" ]; + "std" = [ "ppv-lite86/std" ]; + }; + resolvedDefaultFeatures = [ "std" ]; + }; + "rand_core" = rec { + crateName = "rand_core"; + version = "0.6.4"; + edition = "2018"; + sha256 = "0b4j2v4cb5krak1pv6kakv4sz6xcwbrmy2zckc32hsigbrwy82zc"; + authors = [ + "The Rand Project Developers" + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "getrandom"; + packageId = "getrandom"; + optional = true; + } + ]; + features = { + "getrandom" = [ "dep:getrandom" ]; + "serde" = [ "dep:serde" ]; + "serde1" = [ "serde" ]; + "std" = [ "alloc" "getrandom" "getrandom/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "getrandom" "std" ]; + }; + "rand_distr" = rec { + crateName = "rand_distr"; + version = "0.4.3"; + edition = "2018"; + sha256 = "0cgfwg3z0pkqhrl0x90c77kx70r6g9z4m6fxq9v0h2ibr2dhpjrj"; + authors = [ + "The Rand Project Developers" + ]; + dependencies = [ + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + features = [ "libm" ]; + } + { + name = "rand"; + packageId = "rand"; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "rand"; + packageId = "rand"; + usesDefaultFeatures = false; + features = [ "std_rng" "std" "small_rng" ]; + } + ]; + features = { + "alloc" = [ "rand/alloc" ]; + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + "serde1" = [ "serde" "rand/serde1" ]; + "std" = [ "alloc" "rand/std" ]; + "std_math" = [ "num-traits/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "rayon" = rec { + crateName = "rayon"; + version = "1.8.1"; + edition = "2021"; + sha256 = "0lg0488xwpj5jsfz2gfczcrpclbjl8221mj5vdrhg8bp3883fwps"; + authors = [ + "Niko Matsakis <niko@alum.mit.edu>" + "Josh Stone <cuviper@gmail.com>" + ]; + dependencies = [ + { + name = "either"; + packageId = "either"; + usesDefaultFeatures = false; + } + { + name = "rayon-core"; + packageId = "rayon-core"; + } + ]; + features = { + "web_spin_lock" = [ "dep:wasm_sync" "rayon-core/web_spin_lock" ]; + }; + }; + "rayon-core" = rec { + crateName = "rayon-core"; + version = "1.12.1"; + edition = "2021"; + links = "rayon-core"; + sha256 = "1qpwim68ai5h0j7axa8ai8z0payaawv3id0lrgkqmapx7lx8fr8l"; + libName = "rayon_core"; + authors = [ + "Niko Matsakis <niko@alum.mit.edu>" + "Josh Stone <cuviper@gmail.com>" + ]; + dependencies = [ + { + name = "crossbeam-deque"; + packageId = "crossbeam-deque"; + } + { + name = "crossbeam-utils"; + packageId = "crossbeam-utils"; + } + ]; + features = { + "web_spin_lock" = [ "dep:wasm_sync" ]; + }; + }; + "redox_syscall" = rec { + crateName = "redox_syscall"; + version = "0.4.1"; + edition = "2018"; + sha256 = "1aiifyz5dnybfvkk4cdab9p2kmphag1yad6iknc7aszlxxldf8j7"; + libName = "syscall"; + authors = [ + "Jeremy Soller <jackpot51@gmail.com>" + ]; + dependencies = [ + { + name = "bitflags"; + packageId = "bitflags 1.3.2"; + } + ]; + features = { + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "bitflags/rustc-dep-of-std" ]; + }; + }; + "regex" = rec { + crateName = "regex"; + version = "1.10.3"; + edition = "2021"; + sha256 = "05cvihqy0wgnh9i8a9y2n803n5azg2h0b7nlqy6rsvxhy00vwbdn"; + authors = [ + "The Rust Project Developers" + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "aho-corasick"; + packageId = "aho-corasick"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "memchr"; + packageId = "memchr"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "regex-automata"; + packageId = "regex-automata"; + usesDefaultFeatures = false; + features = [ "alloc" "syntax" "meta" "nfa-pikevm" ]; + } + { + name = "regex-syntax"; + packageId = "regex-syntax"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" "perf" "unicode" "regex-syntax/default" ]; + "logging" = [ "aho-corasick?/logging" "memchr?/logging" "regex-automata/logging" ]; + "perf" = [ "perf-cache" "perf-dfa" "perf-onepass" "perf-backtrack" "perf-inline" "perf-literal" ]; + "perf-backtrack" = [ "regex-automata/nfa-backtrack" ]; + "perf-dfa" = [ "regex-automata/hybrid" ]; + "perf-dfa-full" = [ "regex-automata/dfa-build" "regex-automata/dfa-search" ]; + "perf-inline" = [ "regex-automata/perf-inline" ]; + "perf-literal" = [ "dep:aho-corasick" "dep:memchr" "regex-automata/perf-literal" ]; + "perf-onepass" = [ "regex-automata/dfa-onepass" ]; + "std" = [ "aho-corasick?/std" "memchr?/std" "regex-automata/std" "regex-syntax/std" ]; + "unicode" = [ "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" "regex-automata/unicode" "regex-syntax/unicode" ]; + "unicode-age" = [ "regex-automata/unicode-age" "regex-syntax/unicode-age" ]; + "unicode-bool" = [ "regex-automata/unicode-bool" "regex-syntax/unicode-bool" ]; + "unicode-case" = [ "regex-automata/unicode-case" "regex-syntax/unicode-case" ]; + "unicode-gencat" = [ "regex-automata/unicode-gencat" "regex-syntax/unicode-gencat" ]; + "unicode-perl" = [ "regex-automata/unicode-perl" "regex-automata/unicode-word-boundary" "regex-syntax/unicode-perl" ]; + "unicode-script" = [ "regex-automata/unicode-script" "regex-syntax/unicode-script" ]; + "unicode-segment" = [ "regex-automata/unicode-segment" "regex-syntax/unicode-segment" ]; + "unstable" = [ "pattern" ]; + "use_std" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "perf" "perf-backtrack" "perf-cache" "perf-dfa" "perf-inline" "perf-literal" "perf-onepass" "std" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; + }; + "regex-automata" = rec { + crateName = "regex-automata"; + version = "0.4.5"; + edition = "2021"; + sha256 = "1karc80mx15z435rm1jg3sqylnc58nxi15gqypcd1inkzzpqgfav"; + libName = "regex_automata"; + authors = [ + "The Rust Project Developers" + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "aho-corasick"; + packageId = "aho-corasick"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "memchr"; + packageId = "memchr"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "regex-syntax"; + packageId = "regex-syntax"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" "syntax" "perf" "unicode" "meta" "nfa" "dfa" "hybrid" ]; + "dfa" = [ "dfa-build" "dfa-search" "dfa-onepass" ]; + "dfa-build" = [ "nfa-thompson" "dfa-search" ]; + "dfa-onepass" = [ "nfa-thompson" ]; + "hybrid" = [ "alloc" "nfa-thompson" ]; + "internal-instrument" = [ "internal-instrument-pikevm" ]; + "internal-instrument-pikevm" = [ "logging" "std" ]; + "logging" = [ "dep:log" "aho-corasick?/logging" "memchr?/logging" ]; + "meta" = [ "syntax" "nfa-pikevm" ]; + "nfa" = [ "nfa-thompson" "nfa-pikevm" "nfa-backtrack" ]; + "nfa-backtrack" = [ "nfa-thompson" ]; + "nfa-pikevm" = [ "nfa-thompson" ]; + "nfa-thompson" = [ "alloc" ]; + "perf" = [ "perf-inline" "perf-literal" ]; + "perf-literal" = [ "perf-literal-substring" "perf-literal-multisubstring" ]; + "perf-literal-multisubstring" = [ "std" "dep:aho-corasick" ]; + "perf-literal-substring" = [ "aho-corasick?/perf-literal" "dep:memchr" ]; + "std" = [ "regex-syntax?/std" "memchr?/std" "aho-corasick?/std" "alloc" ]; + "syntax" = [ "dep:regex-syntax" "alloc" ]; + "unicode" = [ "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" "unicode-word-boundary" "regex-syntax?/unicode" ]; + "unicode-age" = [ "regex-syntax?/unicode-age" ]; + "unicode-bool" = [ "regex-syntax?/unicode-bool" ]; + "unicode-case" = [ "regex-syntax?/unicode-case" ]; + "unicode-gencat" = [ "regex-syntax?/unicode-gencat" ]; + "unicode-perl" = [ "regex-syntax?/unicode-perl" ]; + "unicode-script" = [ "regex-syntax?/unicode-script" ]; + "unicode-segment" = [ "regex-syntax?/unicode-segment" ]; + }; + resolvedDefaultFeatures = [ "alloc" "dfa-onepass" "dfa-search" "hybrid" "meta" "nfa-backtrack" "nfa-pikevm" "nfa-thompson" "perf-inline" "perf-literal" "perf-literal-multisubstring" "perf-literal-substring" "std" "syntax" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" "unicode-word-boundary" ]; + }; + "regex-lite" = rec { + crateName = "regex-lite"; + version = "0.1.5"; + edition = "2021"; + sha256 = "13ndx7ibckvlasyzylqpmwlbp4kahrrdl3ph2sybsdviyar63dih"; + libName = "regex_lite"; + authors = [ + "The Rust Project Developers" + "Andrew Gallant <jamslam@gmail.com>" + ]; + features = { + "default" = [ "std" "string" ]; + }; + resolvedDefaultFeatures = [ "default" "std" "string" ]; + }; + "regex-syntax" = rec { + crateName = "regex-syntax"; + version = "0.8.2"; + edition = "2021"; + sha256 = "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360"; + libName = "regex_syntax"; + authors = [ + "The Rust Project Developers" + "Andrew Gallant <jamslam@gmail.com>" + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "default" = [ "std" "unicode" ]; + "unicode" = [ "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; + }; + resolvedDefaultFeatures = [ "default" "std" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; + }; + "rfc6979" = rec { + crateName = "rfc6979"; + version = "0.3.1"; + edition = "2021"; + sha256 = "1fzsp705b5lhwd2r9il9grc3lj6rm3b2r89vh0xv181gy5xg2hvp"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "crypto-bigint"; + packageId = "crypto-bigint 0.4.9"; + usesDefaultFeatures = false; + features = [ "generic-array" "zeroize" ]; + } + { + name = "hmac"; + packageId = "hmac"; + usesDefaultFeatures = false; + features = [ "reset" ]; + } + { + name = "zeroize"; + packageId = "zeroize"; + usesDefaultFeatures = false; + } + ]; + + }; + "ring" = rec { + crateName = "ring"; + version = "0.17.8"; + edition = "2021"; + links = "ring_core_0_17_8"; + sha256 = "03fwlb1ssrmfxdckvqv033pfmk01rhx9ynwi7r186dcfcp5s8zy1"; + authors = [ + "Brian Smith <brian@briansmith.org>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + usesDefaultFeatures = false; + } + { + name = "getrandom"; + packageId = "getrandom"; + } + { + name = "libc"; + packageId = "libc"; + usesDefaultFeatures = false; + target = { target, features }: ((("android" == target."os" or null) || ("linux" == target."os" or null)) && (("aarch64" == target."arch" or null) || ("arm" == target."arch" or null))); + } + { + name = "spin"; + packageId = "spin"; + usesDefaultFeatures = false; + target = { target, features }: (("aarch64" == target."arch" or null) || ("arm" == target."arch" or null) || ("x86" == target."arch" or null) || ("x86_64" == target."arch" or null)); + features = [ "once" ]; + } + { + name = "untrusted"; + packageId = "untrusted"; + } + { + name = "windows-sys"; + packageId = "windows-sys"; + target = { target, features }: (("aarch64" == target."arch" or null) && ("windows" == target."os" or null)); + features = [ "Win32_Foundation" "Win32_System_Threading" ]; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "libc"; + packageId = "libc"; + usesDefaultFeatures = false; + target = { target, features }: ((target."unix" or false) || (target."windows" or false) || ("wasi" == target."os" or null)); + } + ]; + features = { + "default" = [ "alloc" "dev_urandom_fallback" ]; + "std" = [ "alloc" ]; + "wasm32_unknown_unknown_js" = [ "getrandom/js" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "dev_urandom_fallback" ]; + }; + "rustc-demangle" = rec { + crateName = "rustc-demangle"; + version = "0.1.23"; + edition = "2015"; + sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + libName = "rustc_demangle"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + }; + }; + "rustc_version" = rec { + crateName = "rustc_version"; + version = "0.4.0"; + edition = "2018"; + sha256 = "0rpk9rcdk405xhbmgclsh4pai0svn49x35aggl4nhbkd4a2zb85z"; + authors = [ + "Dirkjan Ochtman <dirkjan@ochtman.nl>" + "Marvin Löbel <loebel.marvin@gmail.com>" + ]; + dependencies = [ + { + name = "semver"; + packageId = "semver"; + } + ]; + + }; + "rustls" = rec { + crateName = "rustls"; + version = "0.21.10"; + edition = "2021"; + sha256 = "1fmpzk3axnhkd99saqkvraifdfms4pkyi56lkihf8n877j0sdmgr"; + dependencies = [ + { + name = "log"; + packageId = "log"; + optional = true; + } + { + name = "ring"; + packageId = "ring"; + } + { + name = "rustls-webpki"; + packageId = "rustls-webpki"; + rename = "webpki"; + features = [ "alloc" "std" ]; + } + { + name = "sct"; + packageId = "sct"; + } + ]; + devDependencies = [ + { + name = "log"; + packageId = "log"; + } + ]; + features = { + "default" = [ "logging" "tls12" ]; + "log" = [ "dep:log" ]; + "logging" = [ "log" ]; + "read_buf" = [ "rustversion" ]; + "rustversion" = [ "dep:rustversion" ]; + }; + resolvedDefaultFeatures = [ "default" "log" "logging" "tls12" ]; + }; + "rustls-native-certs" = rec { + crateName = "rustls-native-certs"; + version = "0.6.3"; + edition = "2021"; + sha256 = "007zind70rd5rfsrkdcfm8vn09j8sg02phg9334kark6rdscxam9"; + libName = "rustls_native_certs"; + dependencies = [ + { + name = "openssl-probe"; + packageId = "openssl-probe"; + target = { target, features }: ((target."unix" or false) && (!("macos" == target."os" or null))); + } + { + name = "rustls-pemfile"; + packageId = "rustls-pemfile"; + } + { + name = "schannel"; + packageId = "schannel"; + target = { target, features }: (target."windows" or false); + } + { + name = "security-framework"; + packageId = "security-framework"; + target = { target, features }: ("macos" == target."os" or null); + } + ]; + + }; + "rustls-pemfile" = rec { + crateName = "rustls-pemfile"; + version = "1.0.4"; + edition = "2018"; + sha256 = "1324n5bcns0rnw6vywr5agff3rwfvzphi7rmbyzwnv6glkhclx0w"; + libName = "rustls_pemfile"; + dependencies = [ + { + name = "base64"; + packageId = "base64"; + } + ]; + + }; + "rustls-webpki" = rec { + crateName = "rustls-webpki"; + version = "0.101.7"; + edition = "2021"; + sha256 = "0rapfhpkqp75552i8r0y7f4vq7csb4k7gjjans0df73sxv8paqlb"; + libName = "webpki"; + dependencies = [ + { + name = "ring"; + packageId = "ring"; + usesDefaultFeatures = false; + } + { + name = "untrusted"; + packageId = "untrusted"; + } + ]; + features = { + "alloc" = [ "ring/alloc" ]; + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "rustversion" = rec { + crateName = "rustversion"; + version = "1.0.14"; + edition = "2018"; + sha256 = "1x1pz1yynk5xzzrazk2svmidj69jhz89dz5vrc28sixl20x1iz3z"; + procMacro = true; + build = "build/build.rs"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + + }; + "ryu" = rec { + crateName = "ryu"; + version = "1.0.17"; + edition = "2018"; + sha256 = "188vrsh3zlnl5xl7lw0rp2sc0knpx8yaqpwvr648b6h12v4rfrp8"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + features = { + "no-panic" = [ "dep:no-panic" ]; + }; + }; + "schannel" = rec { + crateName = "schannel"; + version = "0.1.23"; + edition = "2018"; + sha256 = "0d1m156bsjrws6xzzr1wyfyih9i22mb2csb5pc5kmkrvci2ibjgv"; + authors = [ + "Steven Fackler <sfackler@gmail.com>" + "Steffen Butzer <steffen.butzer@outlook.com>" + ]; + dependencies = [ + { + name = "windows-sys"; + packageId = "windows-sys"; + features = [ "Win32_Foundation" "Win32_Security_Cryptography" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_System_Memory" ]; + } + ]; + devDependencies = [ + { + name = "windows-sys"; + packageId = "windows-sys"; + features = [ "Win32_System_SystemInformation" "Win32_System_Time" ]; + } + ]; + + }; + "scopeguard" = rec { + crateName = "scopeguard"; + version = "1.2.0"; + edition = "2015"; + sha256 = "0jcz9sd47zlsgcnm1hdw0664krxwb5gczlif4qngj2aif8vky54l"; + authors = [ + "bluss" + ]; + features = { + "default" = [ "use_std" ]; + }; + }; + "sct" = rec { + crateName = "sct"; + version = "0.7.1"; + edition = "2021"; + sha256 = "056lmi2xkzdg1dbai6ha3n57s18cbip4pnmpdhyljli3m99n216s"; + authors = [ + "Joseph Birr-Pixton <jpixton@gmail.com>" + ]; + dependencies = [ + { + name = "ring"; + packageId = "ring"; + } + { + name = "untrusted"; + packageId = "untrusted"; + } + ]; + + }; + "sec1" = rec { + crateName = "sec1"; + version = "0.3.0"; + edition = "2021"; + sha256 = "0a09lk5w3nyggpyz54m10nnlg9v8qbh6kw3v1bgla31988c4rqiv"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "base16ct"; + packageId = "base16ct"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "der"; + packageId = "der 0.6.1"; + optional = true; + features = [ "oid" ]; + } + { + name = "generic-array"; + packageId = "generic-array"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "pkcs8"; + packageId = "pkcs8 0.9.0"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "subtle"; + packageId = "subtle"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "zeroize"; + packageId = "zeroize"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "der/alloc" "pkcs8/alloc" "zeroize/alloc" ]; + "base16ct" = [ "dep:base16ct" ]; + "default" = [ "der" "point" ]; + "der" = [ "dep:der" ]; + "generic-array" = [ "dep:generic-array" ]; + "pem" = [ "alloc" "der/pem" "pkcs8/pem" ]; + "pkcs8" = [ "dep:pkcs8" ]; + "point" = [ "base16ct" "generic-array" ]; + "serde" = [ "serdect" ]; + "serdect" = [ "dep:serdect" ]; + "std" = [ "der/std" "alloc" ]; + "subtle" = [ "dep:subtle" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "alloc" "base16ct" "default" "der" "generic-array" "pkcs8" "point" "subtle" "zeroize" ]; + }; + "security-framework" = rec { + crateName = "security-framework"; + version = "2.9.2"; + edition = "2021"; + sha256 = "1pplxk15s5yxvi2m1sz5xfmjibp96cscdcl432w9jzbk0frlzdh5"; + libName = "security_framework"; + authors = [ + "Steven Fackler <sfackler@gmail.com>" + "Kornel <kornel@geekhood.net>" + ]; + dependencies = [ + { + name = "bitflags"; + packageId = "bitflags 1.3.2"; + } + { + name = "core-foundation"; + packageId = "core-foundation"; + } + { + name = "core-foundation-sys"; + packageId = "core-foundation-sys"; + } + { + name = "libc"; + packageId = "libc"; + } + { + name = "security-framework-sys"; + packageId = "security-framework-sys"; + usesDefaultFeatures = false; + } + ]; + features = { + "OSX_10_10" = [ "OSX_10_9" "security-framework-sys/OSX_10_10" ]; + "OSX_10_11" = [ "OSX_10_10" "security-framework-sys/OSX_10_11" ]; + "OSX_10_12" = [ "OSX_10_11" "security-framework-sys/OSX_10_12" ]; + "OSX_10_13" = [ "OSX_10_12" "security-framework-sys/OSX_10_13" "alpn" "session-tickets" "serial-number-bigint" ]; + "OSX_10_14" = [ "OSX_10_13" "security-framework-sys/OSX_10_14" ]; + "OSX_10_15" = [ "OSX_10_14" "security-framework-sys/OSX_10_15" ]; + "OSX_10_9" = [ "security-framework-sys/OSX_10_9" ]; + "default" = [ "OSX_10_9" ]; + "log" = [ "dep:log" ]; + "serial-number-bigint" = [ "dep:num-bigint" ]; + }; + resolvedDefaultFeatures = [ "OSX_10_9" "default" ]; + }; + "security-framework-sys" = rec { + crateName = "security-framework-sys"; + version = "2.9.1"; + edition = "2021"; + sha256 = "0yhciwlsy9dh0ps1gw3197kvyqx1bvc4knrhiznhid6kax196cp9"; + libName = "security_framework_sys"; + authors = [ + "Steven Fackler <sfackler@gmail.com>" + "Kornel <kornel@geekhood.net>" + ]; + dependencies = [ + { + name = "core-foundation-sys"; + packageId = "core-foundation-sys"; + } + { + name = "libc"; + packageId = "libc"; + } + ]; + features = { + "OSX_10_10" = [ "OSX_10_9" ]; + "OSX_10_11" = [ "OSX_10_10" ]; + "OSX_10_12" = [ "OSX_10_11" ]; + "OSX_10_13" = [ "OSX_10_12" ]; + "OSX_10_14" = [ "OSX_10_13" ]; + "OSX_10_15" = [ "OSX_10_14" ]; + "default" = [ "OSX_10_9" ]; + }; + resolvedDefaultFeatures = [ "OSX_10_9" ]; + }; + "semver" = rec { + crateName = "semver"; + version = "1.0.22"; + edition = "2018"; + sha256 = "1jir6q2ps4s5v52bqxpvwj35p0m0ahl5pf62ppwksbv5kvk3zm4j"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "seq-macro" = rec { + crateName = "seq-macro"; + version = "0.3.5"; + edition = "2018"; + sha256 = "1d50kbaslrrd0374ivx15jg57f03y5xzil1wd2ajlvajzlkbzw53"; + procMacro = true; + libName = "seq_macro"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + + }; + "serde" = rec { + crateName = "serde"; + version = "1.0.210"; + edition = "2018"; + sha256 = "0flc0z8wgax1k4j5bf2zyq48bgzyv425jkd5w0i6wbh7f8j5kqy8"; + authors = [ + "Erick Tryzelaar <erick.tryzelaar@gmail.com>" + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "serde_derive"; + packageId = "serde_derive"; + optional = true; + } + { + name = "serde_derive"; + packageId = "serde_derive"; + target = { target, features }: false; + } + ]; + devDependencies = [ + { + name = "serde_derive"; + packageId = "serde_derive"; + } + ]; + features = { + "default" = [ "std" ]; + "derive" = [ "serde_derive" ]; + "serde_derive" = [ "dep:serde_derive" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "derive" "serde_derive" "std" ]; + }; + "serde_derive" = rec { + crateName = "serde_derive"; + version = "1.0.210"; + edition = "2015"; + sha256 = "07yzy4wafk79ps0hmbqmsqh5xjna4pm4q57wc847bb8gl3nh4f94"; + procMacro = true; + authors = [ + "Erick Tryzelaar <erick.tryzelaar@gmail.com>" + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + features = [ "proc-macro" ]; + } + { + name = "quote"; + packageId = "quote"; + usesDefaultFeatures = false; + features = [ "proc-macro" ]; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "clone-impls" "derive" "parsing" "printing" "proc-macro" ]; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; + "serde_json" = rec { + crateName = "serde_json"; + version = "1.0.114"; + edition = "2021"; + sha256 = "1q4saigxwkf8bw4y5kp6k33dnavlvvwa2q4zmag59vrjsqdrpw65"; + authors = [ + "Erick Tryzelaar <erick.tryzelaar@gmail.com>" + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "itoa"; + packageId = "itoa"; + } + { + name = "ryu"; + packageId = "ryu"; + } + { + name = "serde"; + packageId = "serde"; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + ]; + features = { + "alloc" = [ "serde/alloc" ]; + "default" = [ "std" ]; + "indexmap" = [ "dep:indexmap" ]; + "preserve_order" = [ "indexmap" "std" ]; + "std" = [ "serde/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "sha1" = rec { + crateName = "sha1"; + version = "0.10.6"; + edition = "2018"; + sha256 = "1fnnxlfg08xhkmwf2ahv634as30l1i3xhlhkvxflmasi5nd85gz3"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "cpufeatures"; + packageId = "cpufeatures"; + target = { target, features }: (("aarch64" == target."arch" or null) || ("x86" == target."arch" or null) || ("x86_64" == target."arch" or null)); + } + { + name = "digest"; + packageId = "digest"; + } + ]; + devDependencies = [ + { + name = "digest"; + packageId = "digest"; + features = [ "dev" ]; + } + ]; + features = { + "asm" = [ "sha1-asm" ]; + "default" = [ "std" ]; + "oid" = [ "digest/oid" ]; + "sha1-asm" = [ "dep:sha1-asm" ]; + "std" = [ "digest/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "sha2" = rec { + crateName = "sha2"; + version = "0.10.8"; + edition = "2018"; + sha256 = "1j1x78zk9il95w9iv46dh9wm73r6xrgj32y6lzzw7bxws9dbfgbr"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "cpufeatures"; + packageId = "cpufeatures"; + target = { target, features }: (("aarch64" == target."arch" or null) || ("x86_64" == target."arch" or null) || ("x86" == target."arch" or null)); + } + { + name = "digest"; + packageId = "digest"; + } + ]; + devDependencies = [ + { + name = "digest"; + packageId = "digest"; + features = [ "dev" ]; + } + ]; + features = { + "asm" = [ "sha2-asm" ]; + "asm-aarch64" = [ "asm" ]; + "default" = [ "std" ]; + "oid" = [ "digest/oid" ]; + "sha2-asm" = [ "dep:sha2-asm" ]; + "std" = [ "digest/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "signal-hook-registry" = rec { + crateName = "signal-hook-registry"; + version = "1.4.1"; + edition = "2015"; + sha256 = "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq"; + libName = "signal_hook_registry"; + authors = [ + "Michal 'vorner' Vaner <vorner@vorner.cz>" + "Masaki Hara <ackie.h.gmai@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + + }; + "signature 1.6.4" = rec { + crateName = "signature"; + version = "1.6.4"; + edition = "2021"; + sha256 = "0z3xg405pg827g6hfdprnszsdqkkbrsfx7f1dl04nv9g7cxks8vl"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "digest"; + packageId = "digest"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "rand_core"; + packageId = "rand_core"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "derive-preview" = [ "digest-preview" "signature_derive" ]; + "digest" = [ "dep:digest" ]; + "digest-preview" = [ "digest" ]; + "rand-preview" = [ "rand_core" ]; + "rand_core" = [ "dep:rand_core" ]; + "signature_derive" = [ "dep:signature_derive" ]; + }; + resolvedDefaultFeatures = [ "digest" "digest-preview" "hazmat-preview" "rand-preview" "rand_core" "std" ]; + }; + "signature 2.2.0" = rec { + crateName = "signature"; + version = "2.2.0"; + edition = "2021"; + sha256 = "1pi9hd5vqfr3q3k49k37z06p7gs5si0in32qia4mmr1dancr6m3p"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "rand_core"; + packageId = "rand_core"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "derive" = [ "dep:derive" ]; + "digest" = [ "dep:digest" ]; + "rand_core" = [ "dep:rand_core" ]; + "std" = [ "alloc" "rand_core?/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "std" ]; + }; + "simdutf8" = rec { + crateName = "simdutf8"; + version = "0.1.4"; + edition = "2018"; + sha256 = "0fi6zvnldaw7g726wnm9vvpv4s89s5jsk7fgp3rg2l99amw64zzj"; + authors = [ + "Hans Kratz <hans@appfour.com>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "slab" = rec { + crateName = "slab"; + version = "0.4.9"; + edition = "2018"; + sha256 = "0rxvsgir0qw5lkycrqgb1cxsvxzjv9bmx73bk5y42svnzfba94lg"; + authors = [ + "Carl Lerche <me@carllerche.com>" + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "smallvec" = rec { + crateName = "smallvec"; + version = "1.13.1"; + edition = "2018"; + sha256 = "1mzk9j117pn3k1gabys0b7nz8cdjsx5xc6q7fwnm8r0an62d7v76"; + authors = [ + "The Servo Project Developers" + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "const_new" = [ "const_generics" ]; + "drain_keep_rest" = [ "drain_filter" ]; + "serde" = [ "dep:serde" ]; + }; + }; + "smartstring" = rec { + crateName = "smartstring"; + version = "1.0.1"; + edition = "2021"; + sha256 = "0agf4x0jz79r30aqibyfjm1h9hrjdh0harcqcvb2vapv7rijrdrz"; + authors = [ + "Bodil Stokke <bodil@bodil.org>" + ]; + dependencies = [ + { + name = "static_assertions"; + packageId = "static_assertions"; + } + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "default" = [ "std" ]; + "proptest" = [ "dep:proptest" ]; + "serde" = [ "dep:serde" ]; + "test" = [ "std" "arbitrary" "arbitrary/derive" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "snap" = rec { + crateName = "snap"; + version = "1.1.1"; + edition = "2018"; + sha256 = "0fxw80m831l76a5zxcwmz2aq7mcwc1pp345pnljl4cv1kbxnfsqv"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + ]; + + }; + "socket2" = rec { + crateName = "socket2"; + version = "0.5.6"; + edition = "2021"; + sha256 = "0w98g7dh9m74vpxln401hl4knpjzrx7jhng7cbh46x9vm70dkzq5"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "windows-sys"; + packageId = "windows-sys"; + target = { target, features }: (target."windows" or false); + features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_System_IO" "Win32_System_Threading" "Win32_System_WindowsProgramming" ]; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "all" ]; + }; + "spin" = rec { + crateName = "spin"; + version = "0.9.8"; + edition = "2015"; + sha256 = "0rvam5r0p3a6qhc18scqpvpgb3ckzyqxpgdfyjnghh8ja7byi039"; + authors = [ + "Mathijs van de Nes <git@mathijs.vd-nes.nl>" + "John Ericson <git@JohnEricson.me>" + "Joshua Barretto <joshua.s.barretto@gmail.com>" + ]; + features = { + "barrier" = [ "mutex" ]; + "default" = [ "lock_api" "mutex" "spin_mutex" "rwlock" "once" "lazy" "barrier" ]; + "fair_mutex" = [ "mutex" ]; + "lazy" = [ "once" ]; + "lock_api" = [ "lock_api_crate" ]; + "lock_api_crate" = [ "dep:lock_api_crate" ]; + "portable-atomic" = [ "dep:portable-atomic" ]; + "portable_atomic" = [ "portable-atomic" ]; + "spin_mutex" = [ "mutex" ]; + "ticket_mutex" = [ "mutex" ]; + "use_ticket_mutex" = [ "mutex" "ticket_mutex" ]; + }; + resolvedDefaultFeatures = [ "once" ]; + }; + "spki 0.6.0" = rec { + crateName = "spki"; + version = "0.6.0"; + edition = "2021"; + sha256 = "0ar1ldkl7svp8l3gfw2hyiiph7n2nqynjnjgdv1pscvsmjxh5kv7"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "base64ct"; + packageId = "base64ct"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "der"; + packageId = "der 0.6.1"; + features = [ "oid" ]; + } + ]; + features = { + "alloc" = [ "base64ct/alloc" "der/alloc" ]; + "base64ct" = [ "dep:base64ct" ]; + "fingerprint" = [ "sha2" ]; + "pem" = [ "alloc" "der/pem" ]; + "sha2" = [ "dep:sha2" ]; + "std" = [ "der/std" "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "base64ct" ]; + }; + "spki 0.7.3" = rec { + crateName = "spki"; + version = "0.7.3"; + edition = "2021"; + sha256 = "17fj8k5fmx4w9mp27l970clrh5qa7r5sjdvbsln987xhb34dc7nr"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "base64ct"; + packageId = "base64ct"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "der"; + packageId = "der 0.7.8"; + features = [ "oid" ]; + } + ]; + features = { + "alloc" = [ "base64ct?/alloc" "der/alloc" ]; + "arbitrary" = [ "std" "dep:arbitrary" "der/arbitrary" ]; + "base64" = [ "dep:base64ct" ]; + "fingerprint" = [ "sha2" ]; + "pem" = [ "alloc" "der/pem" ]; + "sha2" = [ "dep:sha2" ]; + "std" = [ "der/std" "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "std" ]; + }; + "sqlparser" = rec { + crateName = "sqlparser"; + version = "0.39.0"; + edition = "2021"; + sha256 = "1mrbqjdqr179qnhy43d0dnrl3yipsp4qyji5rc68j4fyrg14sfvl"; + authors = [ + "Andy Grove <andygrove73@gmail.com>" + ]; + dependencies = [ + { + name = "log"; + packageId = "log"; + } + ]; + features = { + "bigdecimal" = [ "dep:bigdecimal" ]; + "default" = [ "std" ]; + "json_example" = [ "serde_json" "serde" ]; + "serde" = [ "dep:serde" ]; + "serde_json" = [ "dep:serde_json" ]; + "sqlparser_derive" = [ "dep:sqlparser_derive" ]; + "visitor" = [ "sqlparser_derive" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "static_assertions" = rec { + crateName = "static_assertions"; + version = "1.1.0"; + edition = "2015"; + sha256 = "0gsl6xmw10gvn3zs1rv99laj5ig7ylffnh71f9l34js4nr4r7sx2"; + authors = [ + "Nikolai Vazquez" + ]; + features = { }; + }; + "streaming-decompression" = rec { + crateName = "streaming-decompression"; + version = "0.1.2"; + edition = "2018"; + sha256 = "1wscqj3s30qknda778wf7z99mknk65p0h9hhs658l4pvkfqw6v5z"; + libName = "streaming_decompression"; + dependencies = [ + { + name = "fallible-streaming-iterator"; + packageId = "fallible-streaming-iterator"; + } + ]; + + }; + "streaming-iterator" = rec { + crateName = "streaming-iterator"; + version = "0.1.9"; + edition = "2021"; + sha256 = "0845zdv8qb7zwqzglpqc0830i43xh3fb6vqms155wz85qfvk28ib"; + libName = "streaming_iterator"; + authors = [ + "Steven Fackler <sfackler@gmail.com>" + ]; + features = { + "std" = [ "alloc" ]; + }; + }; + "strength_reduce" = rec { + crateName = "strength_reduce"; + version = "0.2.4"; + edition = "2015"; + sha256 = "10jdq9dijjdkb20wg1dmwg447rnj37jbq0mwvbadvqi2gys5x2gy"; + authors = [ + "Elliott Mahler <join.together@gmail.com>" + ]; + + }; + "strum" = rec { + crateName = "strum"; + version = "0.25.0"; + edition = "2018"; + sha256 = "09g1q55ms8vax1z0mxlbva3vm8n2r1179kfvbccnkjcidzm58399"; + authors = [ + "Peter Glotfelty <peter.glotfelty@microsoft.com>" + ]; + features = { + "default" = [ "std" ]; + "derive" = [ "strum_macros" ]; + "phf" = [ "dep:phf" ]; + "strum_macros" = [ "dep:strum_macros" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "strum_macros" = rec { + crateName = "strum_macros"; + version = "0.25.3"; + edition = "2018"; + sha256 = "184y62g474zqb2f7n16x3ghvlyjbh50viw32p9w9l5lwmjlizp13"; + procMacro = true; + authors = [ + "Peter Glotfelty <peter.glotfelty@microsoft.com>" + ]; + dependencies = [ + { + name = "heck"; + packageId = "heck"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "rustversion"; + packageId = "rustversion"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "parsing" "extra-traits" ]; + } + ]; + + }; + "subtle" = rec { + crateName = "subtle"; + version = "2.5.0"; + edition = "2018"; + sha256 = "1g2yjs7gffgmdvkkq0wrrh0pxds3q0dv6dhkw9cdpbib656xdkc1"; + authors = [ + "Isis Lovecruft <isis@patternsinthevoid.net>" + "Henry de Valence <hdevalence@hdevalence.ca>" + ]; + features = { + "default" = [ "std" "i128" ]; + }; + resolvedDefaultFeatures = [ "default" "i128" "std" ]; + }; + "syn 1.0.109" = rec { + crateName = "syn"; + version = "1.0.109"; + edition = "2018"; + sha256 = "0ds2if4600bd59wsv7jjgfkayfzy3hnazs394kz6zdkmna8l3dkj"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + { + name = "quote"; + packageId = "quote"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "unicode-ident"; + packageId = "unicode-ident"; + } + ]; + features = { + "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; + "printing" = [ "quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote/proc-macro" ]; + "quote" = [ "dep:quote" ]; + "test" = [ "syn-test-suite/all-features" ]; + }; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit-mut" ]; + }; + "syn 2.0.79" = rec { + crateName = "syn"; + version = "2.0.79"; + edition = "2021"; + sha256 = "147mk4sgigmvsb9l8qzj199ygf0fgb0bphwdsghn8205pz82q4w9"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + { + name = "quote"; + packageId = "quote"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "unicode-ident"; + packageId = "unicode-ident"; + } + ]; + features = { + "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; + "printing" = [ "dep:quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; + "test" = [ "syn-test-suite/all-features" ]; + }; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; + }; + "sysinfo" = rec { + crateName = "sysinfo"; + version = "0.30.5"; + edition = "2018"; + sha256 = "1clba87ndskvxddrmwysnjccm6vyr75j24p6ck48jqwgii1z7d0z"; + authors = [ + "Guillaume Gomez <guillaume1.gomez@gmail.com>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "core-foundation-sys"; + packageId = "core-foundation-sys"; + target = { target, features }: (("macos" == target."os" or null) || ("ios" == target."os" or null)); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (!(("unknown" == target."os" or null) || ("wasm32" == target."arch" or null))); + } + { + name = "ntapi"; + packageId = "ntapi"; + target = { target, features }: (target."windows" or false); + } + { + name = "once_cell"; + packageId = "once_cell"; + target = { target, features }: ((target."windows" or false) || ("linux" == target."os" or null) || ("android" == target."os" or null)); + } + { + name = "windows"; + packageId = "windows"; + target = { target, features }: (target."windows" or false); + features = [ "Wdk_System_SystemInformation" "Wdk_System_SystemServices" "Wdk_System_Threading" "Win32_Foundation" "Win32_NetworkManagement_IpHelper" "Win32_NetworkManagement_NetManagement" "Win32_NetworkManagement_Ndis" "Win32_Networking_WinSock" "Win32_Security" "Win32_Security_Authentication_Identity" "Win32_Security_Authorization" "Win32_Storage_FileSystem" "Win32_System_Com" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_Ioctl" "Win32_System_LibraryLoader" "Win32_System_Kernel" "Win32_System_Memory" "Win32_System_Ole" "Win32_System_Performance" "Win32_System_Power" "Win32_System_ProcessStatus" "Win32_System_Registry" "Win32_System_RemoteDesktop" "Win32_System_Rpc" "Win32_System_SystemInformation" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_Variant" "Win32_System_WindowsProgramming" "Win32_System_Wmi" "Win32_UI_Shell" ]; + } + ]; + features = { + "apple-app-store" = [ "apple-sandbox" ]; + "debug" = [ "libc/extra_traits" ]; + "default" = [ "multithread" ]; + "multithread" = [ "rayon" ]; + "rayon" = [ "dep:rayon" ]; + "serde" = [ "dep:serde" ]; + }; + }; + "target-features" = rec { + crateName = "target-features"; + version = "0.1.5"; + edition = "2021"; + sha256 = "1gb974chm9aj8ifkyibylxkyb5an4bf5y8dxb18pqmck698gmdfg"; + libName = "target_features"; + authors = [ + "Caleb Zulawski <caleb.zulawski@gmail.com>" + ]; + + }; + "thiserror" = rec { + crateName = "thiserror"; + version = "1.0.64"; + edition = "2021"; + sha256 = "114s8lmssxl0c2480s671am88vzlasbaikxbvfv8pyqrq6mzh2nm"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "thiserror-impl"; + packageId = "thiserror-impl"; + } + ]; + + }; + "thiserror-impl" = rec { + crateName = "thiserror-impl"; + version = "1.0.64"; + edition = "2021"; + sha256 = "1hvzmjx9iamln854l74qyhs0jl2pg3hhqzpqm9p8gszmf9v4x408"; + procMacro = true; + libName = "thiserror_impl"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + } + ]; + + }; + "time" = rec { + crateName = "time"; + version = "0.3.36"; + edition = "2021"; + sha256 = "11g8hdpahgrf1wwl2rpsg5nxq3aj7ri6xr672v4qcij6cgjqizax"; + authors = [ + "Jacob Pratt <open-source@jhpratt.dev>" + "Time contributors" + ]; + dependencies = [ + { + name = "deranged"; + packageId = "deranged"; + usesDefaultFeatures = false; + features = [ "powerfmt" ]; + } + { + name = "num-conv"; + packageId = "num-conv"; + } + { + name = "powerfmt"; + packageId = "powerfmt"; + usesDefaultFeatures = false; + } + { + name = "serde"; + packageId = "serde"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "time-core"; + packageId = "time-core"; + } + { + name = "time-macros"; + packageId = "time-macros"; + optional = true; + } + ]; + devDependencies = [ + { + name = "num-conv"; + packageId = "num-conv"; + } + { + name = "serde"; + packageId = "serde"; + usesDefaultFeatures = false; + features = [ "derive" ]; + } + { + name = "time-macros"; + packageId = "time-macros"; + } + ]; + features = { + "alloc" = [ "serde?/alloc" ]; + "default" = [ "std" ]; + "formatting" = [ "dep:itoa" "std" "time-macros?/formatting" ]; + "large-dates" = [ "time-macros?/large-dates" ]; + "local-offset" = [ "std" "dep:libc" "dep:num_threads" ]; + "macros" = [ "dep:time-macros" ]; + "parsing" = [ "time-macros?/parsing" ]; + "quickcheck" = [ "dep:quickcheck" "alloc" "deranged/quickcheck" ]; + "rand" = [ "dep:rand" "deranged/rand" ]; + "serde" = [ "dep:serde" "time-macros?/serde" "deranged/serde" ]; + "serde-human-readable" = [ "serde" "formatting" "parsing" ]; + "serde-well-known" = [ "serde" "formatting" "parsing" ]; + "std" = [ "alloc" "deranged/std" ]; + "wasm-bindgen" = [ "dep:js-sys" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "parsing" "std" ]; + }; + "time-core" = rec { + crateName = "time-core"; + version = "0.1.2"; + edition = "2021"; + sha256 = "1wx3qizcihw6z151hywfzzyd1y5dl804ydyxci6qm07vbakpr4pg"; + libName = "time_core"; + authors = [ + "Jacob Pratt <open-source@jhpratt.dev>" + "Time contributors" + ]; + + }; + "time-macros" = rec { + crateName = "time-macros"; + version = "0.2.18"; + edition = "2021"; + sha256 = "1kqwxvfh2jkpg38fy673d6danh1bhcmmbsmffww3mphgail2l99z"; + procMacro = true; + libName = "time_macros"; + authors = [ + "Jacob Pratt <open-source@jhpratt.dev>" + "Time contributors" + ]; + dependencies = [ + { + name = "num-conv"; + packageId = "num-conv"; + } + { + name = "time-core"; + packageId = "time-core"; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "parsing" ]; + }; + "tinyvec" = rec { + crateName = "tinyvec"; + version = "1.6.0"; + edition = "2018"; + sha256 = "0l6bl2h62a5m44jdnpn7lmj14rd44via8180i7121fvm73mmrk47"; + authors = [ + "Lokathor <zefria@gmail.com>" + ]; + dependencies = [ + { + name = "tinyvec_macros"; + packageId = "tinyvec_macros"; + optional = true; + } + ]; + features = { + "alloc" = [ "tinyvec_macros" ]; + "arbitrary" = [ "dep:arbitrary" ]; + "real_blackbox" = [ "criterion/real_blackbox" ]; + "rustc_1_55" = [ "rustc_1_40" ]; + "rustc_1_57" = [ "rustc_1_55" ]; + "serde" = [ "dep:serde" ]; + "std" = [ "alloc" ]; + "tinyvec_macros" = [ "dep:tinyvec_macros" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "tinyvec_macros" ]; + }; + "tinyvec_macros" = rec { + crateName = "tinyvec_macros"; + version = "0.1.1"; + edition = "2018"; + sha256 = "081gag86208sc3y6sdkshgw3vysm5d34p431dzw0bshz66ncng0z"; + authors = [ + "Soveu <marx.tomasz@gmail.com>" + ]; + + }; + "tokio" = rec { + crateName = "tokio"; + version = "1.40.0"; + edition = "2021"; + sha256 = "166rllhfkyqp0fs7sxn6crv74iizi4wzd3cvxkcpmlk52qip1c72"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "backtrace"; + packageId = "backtrace"; + target = { target, features }: (target."tokio_taskdump" or false); + } + { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { + name = "libc"; + packageId = "libc"; + optional = true; + target = { target, features }: (target."unix" or false); + } + { + name = "mio"; + packageId = "mio"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "parking_lot"; + packageId = "parking_lot"; + optional = true; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "signal-hook-registry"; + packageId = "signal-hook-registry"; + optional = true; + target = { target, features }: (target."unix" or false); + } + { + name = "socket2"; + packageId = "socket2"; + optional = true; + target = { target, features }: (!(builtins.elem "wasm" target."family")); + features = [ "all" ]; + } + { + name = "tokio-macros"; + packageId = "tokio-macros"; + optional = true; + } + { + name = "windows-sys"; + packageId = "windows-sys"; + optional = true; + target = { target, features }: (target."windows" or false); + } + ]; + devDependencies = [ + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "socket2"; + packageId = "socket2"; + target = { target, features }: (!(builtins.elem "wasm" target."family")); + } + { + name = "windows-sys"; + packageId = "windows-sys"; + target = { target, features }: (target."windows" or false); + features = [ "Win32_Foundation" "Win32_Security_Authorization" ]; + } + ]; + features = { + "bytes" = [ "dep:bytes" ]; + "full" = [ "fs" "io-util" "io-std" "macros" "net" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "sync" "time" ]; + "io-util" = [ "bytes" ]; + "libc" = [ "dep:libc" ]; + "macros" = [ "tokio-macros" ]; + "mio" = [ "dep:mio" ]; + "net" = [ "libc" "mio/os-poll" "mio/os-ext" "mio/net" "socket2" "windows-sys/Win32_Foundation" "windows-sys/Win32_Security" "windows-sys/Win32_Storage_FileSystem" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_System_SystemServices" ]; + "parking_lot" = [ "dep:parking_lot" ]; + "process" = [ "bytes" "libc" "mio/os-poll" "mio/os-ext" "mio/net" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Threading" "windows-sys/Win32_System_WindowsProgramming" ]; + "rt-multi-thread" = [ "rt" ]; + "signal" = [ "libc" "mio/os-poll" "mio/net" "mio/os-ext" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Console" ]; + "signal-hook-registry" = [ "dep:signal-hook-registry" ]; + "socket2" = [ "dep:socket2" ]; + "test-util" = [ "rt" "sync" "time" ]; + "tokio-macros" = [ "dep:tokio-macros" ]; + "tracing" = [ "dep:tracing" ]; + "windows-sys" = [ "dep:windows-sys" ]; + }; + resolvedDefaultFeatures = [ "bytes" "default" "fs" "full" "io-std" "io-util" "libc" "macros" "mio" "net" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "time" "tokio-macros" "windows-sys" ]; + }; + "tokio-macros" = rec { + crateName = "tokio-macros"; + version = "2.4.0"; + edition = "2021"; + sha256 = "0lnpg14h1v3fh2jvnc8cz7cjf0m7z1xgkwfpcyy632g829imjgb9"; + procMacro = true; + libName = "tokio_macros"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" ]; + } + ]; + + }; + "tokio-rustls" = rec { + crateName = "tokio-rustls"; + version = "0.24.1"; + edition = "2018"; + sha256 = "10bhibg57mqir7xjhb2xmf24xgfpx6fzpyw720a4ih8a737jg0y2"; + libName = "tokio_rustls"; + dependencies = [ + { + name = "rustls"; + packageId = "rustls"; + usesDefaultFeatures = false; + } + { + name = "tokio"; + packageId = "tokio"; + } + ]; + devDependencies = [ + { + name = "tokio"; + packageId = "tokio"; + features = [ "full" ]; + } + ]; + features = { + "dangerous_configuration" = [ "rustls/dangerous_configuration" ]; + "default" = [ "logging" "tls12" ]; + "logging" = [ "rustls/logging" ]; + "secret_extraction" = [ "rustls/secret_extraction" ]; + "tls12" = [ "rustls/tls12" ]; + }; + resolvedDefaultFeatures = [ "logging" "tls12" ]; + }; + "tokio-util" = rec { + crateName = "tokio-util"; + version = "0.7.10"; + edition = "2021"; + sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + libName = "tokio_util"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "futures-core"; + packageId = "futures-core"; + } + { + name = "futures-sink"; + packageId = "futures-sink"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "sync" ]; + } + { + name = "tracing"; + packageId = "tracing"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" ]; + } + ]; + devDependencies = [ + { + name = "tokio"; + packageId = "tokio"; + features = [ "full" ]; + } + ]; + features = { + "__docs_rs" = [ "futures-util" ]; + "codec" = [ "tracing" ]; + "compat" = [ "futures-io" ]; + "full" = [ "codec" "compat" "io-util" "time" "net" "rt" ]; + "futures-io" = [ "dep:futures-io" ]; + "futures-util" = [ "dep:futures-util" ]; + "hashbrown" = [ "dep:hashbrown" ]; + "io-util" = [ "io" "tokio/rt" "tokio/io-util" ]; + "net" = [ "tokio/net" ]; + "rt" = [ "tokio/rt" "tokio/sync" "futures-util" "hashbrown" ]; + "slab" = [ "dep:slab" ]; + "time" = [ "tokio/time" "slab" ]; + "tracing" = [ "dep:tracing" ]; + }; + resolvedDefaultFeatures = [ "codec" "default" "io" "io-util" "tracing" ]; + }; + "tower-service" = rec { + crateName = "tower-service"; + version = "0.3.2"; + edition = "2018"; + sha256 = "0lmfzmmvid2yp2l36mbavhmqgsvzqf7r2wiwz73ml4xmwaf1rg5n"; + libName = "tower_service"; + authors = [ + "Tower Maintainers <team@tower-rs.com>" + ]; + + }; + "tracing" = rec { + crateName = "tracing"; + version = "0.1.40"; + edition = "2018"; + sha256 = "1vv48dac9zgj9650pg2b4d0j3w6f3x9gbggf43scq5hrlysklln3"; + authors = [ + "Eliza Weisman <eliza@buoyant.io>" + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tracing-attributes"; + packageId = "tracing-attributes"; + optional = true; + } + { + name = "tracing-core"; + packageId = "tracing-core"; + usesDefaultFeatures = false; + } + ]; + features = { + "attributes" = [ "tracing-attributes" ]; + "default" = [ "std" "attributes" ]; + "log" = [ "dep:log" ]; + "log-always" = [ "log" ]; + "std" = [ "tracing-core/std" ]; + "tracing-attributes" = [ "dep:tracing-attributes" ]; + "valuable" = [ "tracing-core/valuable" ]; + }; + resolvedDefaultFeatures = [ "attributes" "default" "std" "tracing-attributes" ]; + }; + "tracing-attributes" = rec { + crateName = "tracing-attributes"; + version = "0.1.27"; + edition = "2018"; + sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; + procMacro = true; + libName = "tracing_attributes"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + "Eliza Weisman <eliza@buoyant.io>" + "David Barsky <dbarsky@amazon.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "visit-mut" "clone-impls" "extra-traits" "proc-macro" ]; + } + ]; + features = { }; + }; + "tracing-core" = rec { + crateName = "tracing-core"; + version = "0.1.32"; + edition = "2018"; + sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "once_cell"; + packageId = "once_cell"; + optional = true; + } + ]; + features = { + "default" = [ "std" "valuable/std" ]; + "once_cell" = [ "dep:once_cell" ]; + "std" = [ "once_cell" ]; + "valuable" = [ "dep:valuable" ]; + }; + resolvedDefaultFeatures = [ "once_cell" "std" ]; + }; + "try-lock" = rec { + crateName = "try-lock"; + version = "0.2.5"; + edition = "2015"; + sha256 = "0jqijrrvm1pyq34zn1jmy2vihd4jcrjlvsh4alkjahhssjnsn8g4"; + libName = "try_lock"; + authors = [ + "Sean McArthur <sean@seanmonstar.com>" + ]; + + }; + "typenum" = rec { + crateName = "typenum"; + version = "1.17.0"; + edition = "2018"; + sha256 = "09dqxv69m9lj9zvv6xw5vxaqx15ps0vxyy5myg33i0kbqvq0pzs2"; + build = "build/main.rs"; + authors = [ + "Paho Lurie-Gregg <paho@paholg.com>" + "Andre Bogus <bogusandre@gmail.com>" + ]; + features = { + "scale-info" = [ "dep:scale-info" ]; + "scale_info" = [ "scale-info/derive" ]; + }; + }; + "unicode-bidi" = rec { + crateName = "unicode-bidi"; + version = "0.3.15"; + edition = "2018"; + sha256 = "0xcdxm7h0ydyprwpcbh436rbs6s6lph7f3gr527lzgv6lw053y88"; + libName = "unicode_bidi"; + authors = [ + "The Servo Project Developers" + ]; + features = { + "default" = [ "std" "hardcoded-data" ]; + "flame" = [ "dep:flame" ]; + "flame_it" = [ "flame" "flamer" ]; + "flamer" = [ "dep:flamer" ]; + "serde" = [ "dep:serde" ]; + "with_serde" = [ "serde" ]; + }; + resolvedDefaultFeatures = [ "hardcoded-data" "std" ]; + }; + "unicode-ident" = rec { + crateName = "unicode-ident"; + version = "1.0.12"; + edition = "2018"; + sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + + }; + "unicode-normalization" = rec { + crateName = "unicode-normalization"; + version = "0.1.23"; + edition = "2018"; + sha256 = "1x81a50h2zxigj74b9bqjsirxxbyhmis54kg600xj213vf31cvd5"; + libName = "unicode_normalization"; + authors = [ + "kwantam <kwantam@gmail.com>" + "Manish Goregaokar <manishsmail@gmail.com>" + ]; + dependencies = [ + { + name = "tinyvec"; + packageId = "tinyvec"; + features = [ "alloc" ]; + } + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "std" ]; + }; + "unicode-width" = rec { + crateName = "unicode-width"; + version = "0.1.11"; + edition = "2015"; + sha256 = "11ds4ydhg8g7l06rlmh712q41qsrd0j0h00n1jm74kww3kqk65z5"; + libName = "unicode_width"; + authors = [ + "kwantam <kwantam@gmail.com>" + "Manish Goregaokar <manishsmail@gmail.com>" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "std" "core" "compiler_builtins" ]; + "std" = [ "dep:std" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "untrusted" = rec { + crateName = "untrusted"; + version = "0.9.0"; + edition = "2018"; + sha256 = "1ha7ib98vkc538x0z60gfn0fc5whqdd85mb87dvisdcaifi6vjwf"; + authors = [ + "Brian Smith <brian@briansmith.org>" + ]; + + }; + "url" = rec { + crateName = "url"; + version = "2.5.0"; + edition = "2018"; + sha256 = "0cs65961miawncdg2z20171w0vqrmraswv2ihdpd8lxp7cp31rii"; + authors = [ + "The rust-url developers" + ]; + dependencies = [ + { + name = "form_urlencoded"; + packageId = "form_urlencoded"; + } + { + name = "idna"; + packageId = "idna"; + } + { + name = "percent-encoding"; + packageId = "percent-encoding"; + } + ]; + features = { + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "urlencoding" = rec { + crateName = "urlencoding"; + version = "2.1.3"; + edition = "2021"; + sha256 = "1nj99jp37k47n0hvaz5fvz7z6jd0sb4ppvfy3nphr1zbnyixpy6s"; + authors = [ + "Kornel <kornel@geekhood.net>" + "Bertram Truong <b@bertramtruong.com>" + ]; + + }; + "uuid" = rec { + crateName = "uuid"; + version = "1.7.0"; + edition = "2018"; + sha256 = "0aivp5ys7sg2izlj2sn6rr8p43vdcwg64naj8n0kqbd15iqcj37h"; + authors = [ + "Ashley Mannix<ashleymannix@live.com.au>" + "Christopher Armstrong" + "Dylan DPC<dylan.dpc@gmail.com>" + "Hunar Roop Kahlon<hunar.roop@gmail.com>" + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "atomic" = [ "dep:atomic" ]; + "borsh" = [ "dep:borsh" "dep:borsh-derive" ]; + "bytemuck" = [ "dep:bytemuck" ]; + "default" = [ "std" ]; + "fast-rng" = [ "rng" "dep:rand" ]; + "js" = [ "dep:wasm-bindgen" "getrandom?/js" ]; + "macro-diagnostics" = [ "dep:uuid-macro-internal" ]; + "md5" = [ "dep:md-5" ]; + "rng" = [ "dep:getrandom" ]; + "serde" = [ "dep:serde" ]; + "sha1" = [ "dep:sha1_smol" ]; + "slog" = [ "dep:slog" ]; + "v1" = [ "atomic" ]; + "v3" = [ "md5" ]; + "v4" = [ "rng" ]; + "v5" = [ "sha1" ]; + "v6" = [ "atomic" ]; + "v7" = [ "atomic" "rng" ]; + "zerocopy" = [ "dep:zerocopy" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "version_check" = rec { + crateName = "version_check"; + version = "0.9.4"; + edition = "2015"; + sha256 = "0gs8grwdlgh0xq660d7wr80x14vxbizmd8dbp29p2pdncx8lp1s9"; + authors = [ + "Sergio Benitez <sb@sergio.bz>" + ]; + + }; + "vsimd" = rec { + crateName = "vsimd"; + version = "0.8.0"; + edition = "2021"; + sha256 = "0r4wn54jxb12r0x023r5yxcrqk785akmbddqkcafz9fm03584c2w"; + features = { + "detect" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "detect" "std" ]; + }; + "want" = rec { + crateName = "want"; + version = "0.3.1"; + edition = "2018"; + sha256 = "03hbfrnvqqdchb5kgxyavb9jabwza0dmh2vw5kg0dq8rxl57d9xz"; + authors = [ + "Sean McArthur <sean@seanmonstar.com>" + ]; + dependencies = [ + { + name = "try-lock"; + packageId = "try-lock"; + } + ]; + + }; + "wasi" = rec { + crateName = "wasi"; + version = "0.11.0+wasi-snapshot-preview1"; + edition = "2018"; + sha256 = "08z4hxwkpdpalxjps1ai9y7ihin26y9f476i53dv98v45gkqg3cw"; + authors = [ + "The Cranelift Project Developers" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "std" ]; + "rustc-dep-of-std" = [ "compiler_builtins" "core" "rustc-std-workspace-alloc" ]; + "rustc-std-workspace-alloc" = [ "dep:rustc-std-workspace-alloc" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "wasm-bindgen" = rec { + crateName = "wasm-bindgen"; + version = "0.2.91"; + edition = "2018"; + sha256 = "0zwbb07ln4m5hh6axamc701nnj090nd66syxbf6bagzf189j9qf1"; + libName = "wasm_bindgen"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "wasm-bindgen-macro"; + packageId = "wasm-bindgen-macro"; + } + ]; + features = { + "default" = [ "spans" "std" ]; + "enable-interning" = [ "std" ]; + "gg-alloc" = [ "wasm-bindgen-test/gg-alloc" ]; + "serde" = [ "dep:serde" ]; + "serde-serialize" = [ "serde" "serde_json" "std" ]; + "serde_json" = [ "dep:serde_json" ]; + "spans" = [ "wasm-bindgen-macro/spans" ]; + "strict-macro" = [ "wasm-bindgen-macro/strict-macro" ]; + "xxx_debug_only_print_generated_code" = [ "wasm-bindgen-macro/xxx_debug_only_print_generated_code" ]; + }; + resolvedDefaultFeatures = [ "default" "spans" "std" ]; + }; + "wasm-bindgen-backend" = rec { + crateName = "wasm-bindgen-backend"; + version = "0.2.91"; + edition = "2018"; + sha256 = "02zpi9sjzhd8kfv1yj9m1bs4a41ik9ii5bc8hjf60arm1j8f3ry9"; + libName = "wasm_bindgen_backend"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "bumpalo"; + packageId = "bumpalo"; + } + { + name = "log"; + packageId = "log"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" ]; + } + { + name = "wasm-bindgen-shared"; + packageId = "wasm-bindgen-shared"; + } + ]; + features = { + "extra-traits" = [ "syn/extra-traits" ]; + }; + resolvedDefaultFeatures = [ "spans" ]; + }; + "wasm-bindgen-macro" = rec { + crateName = "wasm-bindgen-macro"; + version = "0.2.91"; + edition = "2018"; + sha256 = "1va6dilw9kcnvsg5043h5b9mwc5sgq0lyhj9fif2n62qsgigj2mk"; + procMacro = true; + libName = "wasm_bindgen_macro"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "quote"; + packageId = "quote"; + } + { + name = "wasm-bindgen-macro-support"; + packageId = "wasm-bindgen-macro-support"; + } + ]; + features = { + "spans" = [ "wasm-bindgen-macro-support/spans" ]; + "strict-macro" = [ "wasm-bindgen-macro-support/strict-macro" ]; + }; + resolvedDefaultFeatures = [ "spans" ]; + }; + "wasm-bindgen-macro-support" = rec { + crateName = "wasm-bindgen-macro-support"; + version = "0.2.91"; + edition = "2018"; + sha256 = "0rlyl3yzwbcnc691mvx78m1wbqf1qs52mlc3g88bh7ihwrdk4bv4"; + libName = "wasm_bindgen_macro_support"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "visit" "full" ]; + } + { + name = "wasm-bindgen-backend"; + packageId = "wasm-bindgen-backend"; + } + { + name = "wasm-bindgen-shared"; + packageId = "wasm-bindgen-shared"; + } + ]; + features = { + "extra-traits" = [ "syn/extra-traits" ]; + "spans" = [ "wasm-bindgen-backend/spans" ]; + }; + resolvedDefaultFeatures = [ "spans" ]; + }; + "wasm-bindgen-shared" = rec { + crateName = "wasm-bindgen-shared"; + version = "0.2.91"; + edition = "2018"; + links = "wasm_bindgen"; + sha256 = "0f4qmjv57ppwi4xpdxgcd77vz9vmvlrnybg8dj430hzhvk96n62g"; + libName = "wasm_bindgen_shared"; + authors = [ + "The wasm-bindgen Developers" + ]; + + }; + "winapi" = rec { + crateName = "winapi"; + version = "0.3.9"; + edition = "2015"; + sha256 = "06gl025x418lchw1wxj64ycr7gha83m44cjr5sarhynd9xkrm0sw"; + authors = [ + "Peter Atashian <retep998@gmail.com>" + ]; + dependencies = [ + { + name = "winapi-i686-pc-windows-gnu"; + packageId = "winapi-i686-pc-windows-gnu"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnu"); + } + { + name = "winapi-x86_64-pc-windows-gnu"; + packageId = "winapi-x86_64-pc-windows-gnu"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnu"); + } + ]; + features = { + "debug" = [ "impl-debug" ]; + }; + resolvedDefaultFeatures = [ "cfg" "consoleapi" "evntrace" "handleapi" "impl-default" "in6addr" "inaddr" "minwinbase" "ntsecapi" "processenv" "synchapi" "winbase" "windef" "winerror" "winioctl" "winuser" ]; + }; + "winapi-i686-pc-windows-gnu" = rec { + crateName = "winapi-i686-pc-windows-gnu"; + version = "0.4.0"; + edition = "2015"; + sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; + authors = [ + "Peter Atashian <retep998@gmail.com>" + ]; + + }; + "winapi-x86_64-pc-windows-gnu" = rec { + crateName = "winapi-x86_64-pc-windows-gnu"; + version = "0.4.0"; + edition = "2015"; + sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; + authors = [ + "Peter Atashian <retep998@gmail.com>" + ]; + + }; + "windows" = rec { + crateName = "windows"; + version = "0.52.0"; + edition = "2021"; + sha256 = "1gnh210qjlprpd1szaq04rjm1zqgdm9j7l9absg0kawi2rwm72p4"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-core"; + packageId = "windows-core"; + } + { + name = "windows-targets"; + packageId = "windows-targets 0.52.3"; + } + ]; + features = { + "AI_MachineLearning" = [ "AI" ]; + "ApplicationModel_Activation" = [ "ApplicationModel" ]; + "ApplicationModel_AppExtensions" = [ "ApplicationModel" ]; + "ApplicationModel_AppService" = [ "ApplicationModel" ]; + "ApplicationModel_Appointments" = [ "ApplicationModel" ]; + "ApplicationModel_Appointments_AppointmentsProvider" = [ "ApplicationModel_Appointments" ]; + "ApplicationModel_Appointments_DataProvider" = [ "ApplicationModel_Appointments" ]; + "ApplicationModel_Background" = [ "ApplicationModel" ]; + "ApplicationModel_Calls" = [ "ApplicationModel" ]; + "ApplicationModel_Calls_Background" = [ "ApplicationModel_Calls" ]; + "ApplicationModel_Calls_Provider" = [ "ApplicationModel_Calls" ]; + "ApplicationModel_Chat" = [ "ApplicationModel" ]; + "ApplicationModel_CommunicationBlocking" = [ "ApplicationModel" ]; + "ApplicationModel_Contacts" = [ "ApplicationModel" ]; + "ApplicationModel_Contacts_DataProvider" = [ "ApplicationModel_Contacts" ]; + "ApplicationModel_Contacts_Provider" = [ "ApplicationModel_Contacts" ]; + "ApplicationModel_ConversationalAgent" = [ "ApplicationModel" ]; + "ApplicationModel_Core" = [ "ApplicationModel" ]; + "ApplicationModel_DataTransfer" = [ "ApplicationModel" ]; + "ApplicationModel_DataTransfer_DragDrop" = [ "ApplicationModel_DataTransfer" ]; + "ApplicationModel_DataTransfer_DragDrop_Core" = [ "ApplicationModel_DataTransfer_DragDrop" ]; + "ApplicationModel_DataTransfer_ShareTarget" = [ "ApplicationModel_DataTransfer" ]; + "ApplicationModel_Email" = [ "ApplicationModel" ]; + "ApplicationModel_Email_DataProvider" = [ "ApplicationModel_Email" ]; + "ApplicationModel_ExtendedExecution" = [ "ApplicationModel" ]; + "ApplicationModel_ExtendedExecution_Foreground" = [ "ApplicationModel_ExtendedExecution" ]; + "ApplicationModel_Holographic" = [ "ApplicationModel" ]; + "ApplicationModel_LockScreen" = [ "ApplicationModel" ]; + "ApplicationModel_Payments" = [ "ApplicationModel" ]; + "ApplicationModel_Payments_Provider" = [ "ApplicationModel_Payments" ]; + "ApplicationModel_Preview" = [ "ApplicationModel" ]; + "ApplicationModel_Preview_Holographic" = [ "ApplicationModel_Preview" ]; + "ApplicationModel_Preview_InkWorkspace" = [ "ApplicationModel_Preview" ]; + "ApplicationModel_Preview_Notes" = [ "ApplicationModel_Preview" ]; + "ApplicationModel_Resources" = [ "ApplicationModel" ]; + "ApplicationModel_Resources_Core" = [ "ApplicationModel_Resources" ]; + "ApplicationModel_Resources_Management" = [ "ApplicationModel_Resources" ]; + "ApplicationModel_Search" = [ "ApplicationModel" ]; + "ApplicationModel_Search_Core" = [ "ApplicationModel_Search" ]; + "ApplicationModel_Store" = [ "ApplicationModel" ]; + "ApplicationModel_Store_LicenseManagement" = [ "ApplicationModel_Store" ]; + "ApplicationModel_Store_Preview" = [ "ApplicationModel_Store" ]; + "ApplicationModel_Store_Preview_InstallControl" = [ "ApplicationModel_Store_Preview" ]; + "ApplicationModel_UserActivities" = [ "ApplicationModel" ]; + "ApplicationModel_UserActivities_Core" = [ "ApplicationModel_UserActivities" ]; + "ApplicationModel_UserDataAccounts" = [ "ApplicationModel" ]; + "ApplicationModel_UserDataAccounts_Provider" = [ "ApplicationModel_UserDataAccounts" ]; + "ApplicationModel_UserDataAccounts_SystemAccess" = [ "ApplicationModel_UserDataAccounts" ]; + "ApplicationModel_UserDataTasks" = [ "ApplicationModel" ]; + "ApplicationModel_UserDataTasks_DataProvider" = [ "ApplicationModel_UserDataTasks" ]; + "ApplicationModel_VoiceCommands" = [ "ApplicationModel" ]; + "ApplicationModel_Wallet" = [ "ApplicationModel" ]; + "ApplicationModel_Wallet_System" = [ "ApplicationModel_Wallet" ]; + "Data_Html" = [ "Data" ]; + "Data_Json" = [ "Data" ]; + "Data_Pdf" = [ "Data" ]; + "Data_Text" = [ "Data" ]; + "Data_Xml" = [ "Data" ]; + "Data_Xml_Dom" = [ "Data_Xml" ]; + "Data_Xml_Xsl" = [ "Data_Xml" ]; + "Devices_Adc" = [ "Devices" ]; + "Devices_Adc_Provider" = [ "Devices_Adc" ]; + "Devices_Background" = [ "Devices" ]; + "Devices_Bluetooth" = [ "Devices" ]; + "Devices_Bluetooth_Advertisement" = [ "Devices_Bluetooth" ]; + "Devices_Bluetooth_Background" = [ "Devices_Bluetooth" ]; + "Devices_Bluetooth_GenericAttributeProfile" = [ "Devices_Bluetooth" ]; + "Devices_Bluetooth_Rfcomm" = [ "Devices_Bluetooth" ]; + "Devices_Custom" = [ "Devices" ]; + "Devices_Display" = [ "Devices" ]; + "Devices_Display_Core" = [ "Devices_Display" ]; + "Devices_Enumeration" = [ "Devices" ]; + "Devices_Enumeration_Pnp" = [ "Devices_Enumeration" ]; + "Devices_Geolocation" = [ "Devices" ]; + "Devices_Geolocation_Geofencing" = [ "Devices_Geolocation" ]; + "Devices_Geolocation_Provider" = [ "Devices_Geolocation" ]; + "Devices_Gpio" = [ "Devices" ]; + "Devices_Gpio_Provider" = [ "Devices_Gpio" ]; + "Devices_Haptics" = [ "Devices" ]; + "Devices_HumanInterfaceDevice" = [ "Devices" ]; + "Devices_I2c" = [ "Devices" ]; + "Devices_I2c_Provider" = [ "Devices_I2c" ]; + "Devices_Input" = [ "Devices" ]; + "Devices_Input_Preview" = [ "Devices_Input" ]; + "Devices_Lights" = [ "Devices" ]; + "Devices_Lights_Effects" = [ "Devices_Lights" ]; + "Devices_Midi" = [ "Devices" ]; + "Devices_PointOfService" = [ "Devices" ]; + "Devices_PointOfService_Provider" = [ "Devices_PointOfService" ]; + "Devices_Portable" = [ "Devices" ]; + "Devices_Power" = [ "Devices" ]; + "Devices_Printers" = [ "Devices" ]; + "Devices_Printers_Extensions" = [ "Devices_Printers" ]; + "Devices_Pwm" = [ "Devices" ]; + "Devices_Pwm_Provider" = [ "Devices_Pwm" ]; + "Devices_Radios" = [ "Devices" ]; + "Devices_Scanners" = [ "Devices" ]; + "Devices_Sensors" = [ "Devices" ]; + "Devices_Sensors_Custom" = [ "Devices_Sensors" ]; + "Devices_SerialCommunication" = [ "Devices" ]; + "Devices_SmartCards" = [ "Devices" ]; + "Devices_Sms" = [ "Devices" ]; + "Devices_Spi" = [ "Devices" ]; + "Devices_Spi_Provider" = [ "Devices_Spi" ]; + "Devices_Usb" = [ "Devices" ]; + "Devices_WiFi" = [ "Devices" ]; + "Devices_WiFiDirect" = [ "Devices" ]; + "Devices_WiFiDirect_Services" = [ "Devices_WiFiDirect" ]; + "Embedded_DeviceLockdown" = [ "Embedded" ]; + "Foundation_Collections" = [ "Foundation" ]; + "Foundation_Diagnostics" = [ "Foundation" ]; + "Foundation_Metadata" = [ "Foundation" ]; + "Foundation_Numerics" = [ "Foundation" ]; + "Gaming_Input" = [ "Gaming" ]; + "Gaming_Input_Custom" = [ "Gaming_Input" ]; + "Gaming_Input_ForceFeedback" = [ "Gaming_Input" ]; + "Gaming_Input_Preview" = [ "Gaming_Input" ]; + "Gaming_Preview" = [ "Gaming" ]; + "Gaming_Preview_GamesEnumeration" = [ "Gaming_Preview" ]; + "Gaming_UI" = [ "Gaming" ]; + "Gaming_XboxLive" = [ "Gaming" ]; + "Gaming_XboxLive_Storage" = [ "Gaming_XboxLive" ]; + "Globalization_Collation" = [ "Globalization" ]; + "Globalization_DateTimeFormatting" = [ "Globalization" ]; + "Globalization_Fonts" = [ "Globalization" ]; + "Globalization_NumberFormatting" = [ "Globalization" ]; + "Globalization_PhoneNumberFormatting" = [ "Globalization" ]; + "Graphics_Capture" = [ "Graphics" ]; + "Graphics_DirectX" = [ "Graphics" ]; + "Graphics_DirectX_Direct3D11" = [ "Graphics_DirectX" ]; + "Graphics_Display" = [ "Graphics" ]; + "Graphics_Display_Core" = [ "Graphics_Display" ]; + "Graphics_Effects" = [ "Graphics" ]; + "Graphics_Holographic" = [ "Graphics" ]; + "Graphics_Imaging" = [ "Graphics" ]; + "Graphics_Printing" = [ "Graphics" ]; + "Graphics_Printing3D" = [ "Graphics" ]; + "Graphics_Printing_OptionDetails" = [ "Graphics_Printing" ]; + "Graphics_Printing_PrintSupport" = [ "Graphics_Printing" ]; + "Graphics_Printing_PrintTicket" = [ "Graphics_Printing" ]; + "Graphics_Printing_Workflow" = [ "Graphics_Printing" ]; + "Management_Core" = [ "Management" ]; + "Management_Deployment" = [ "Management" ]; + "Management_Deployment_Preview" = [ "Management_Deployment" ]; + "Management_Policies" = [ "Management" ]; + "Management_Update" = [ "Management" ]; + "Management_Workplace" = [ "Management" ]; + "Media_AppBroadcasting" = [ "Media" ]; + "Media_AppRecording" = [ "Media" ]; + "Media_Audio" = [ "Media" ]; + "Media_Capture" = [ "Media" ]; + "Media_Capture_Core" = [ "Media_Capture" ]; + "Media_Capture_Frames" = [ "Media_Capture" ]; + "Media_Casting" = [ "Media" ]; + "Media_ClosedCaptioning" = [ "Media" ]; + "Media_ContentRestrictions" = [ "Media" ]; + "Media_Control" = [ "Media" ]; + "Media_Core" = [ "Media" ]; + "Media_Core_Preview" = [ "Media_Core" ]; + "Media_Devices" = [ "Media" ]; + "Media_Devices_Core" = [ "Media_Devices" ]; + "Media_DialProtocol" = [ "Media" ]; + "Media_Editing" = [ "Media" ]; + "Media_Effects" = [ "Media" ]; + "Media_FaceAnalysis" = [ "Media" ]; + "Media_Import" = [ "Media" ]; + "Media_MediaProperties" = [ "Media" ]; + "Media_Miracast" = [ "Media" ]; + "Media_Ocr" = [ "Media" ]; + "Media_PlayTo" = [ "Media" ]; + "Media_Playback" = [ "Media" ]; + "Media_Playlists" = [ "Media" ]; + "Media_Protection" = [ "Media" ]; + "Media_Protection_PlayReady" = [ "Media_Protection" ]; + "Media_Render" = [ "Media" ]; + "Media_SpeechRecognition" = [ "Media" ]; + "Media_SpeechSynthesis" = [ "Media" ]; + "Media_Streaming" = [ "Media" ]; + "Media_Streaming_Adaptive" = [ "Media_Streaming" ]; + "Media_Transcoding" = [ "Media" ]; + "Networking_BackgroundTransfer" = [ "Networking" ]; + "Networking_Connectivity" = [ "Networking" ]; + "Networking_NetworkOperators" = [ "Networking" ]; + "Networking_Proximity" = [ "Networking" ]; + "Networking_PushNotifications" = [ "Networking" ]; + "Networking_ServiceDiscovery" = [ "Networking" ]; + "Networking_ServiceDiscovery_Dnssd" = [ "Networking_ServiceDiscovery" ]; + "Networking_Sockets" = [ "Networking" ]; + "Networking_Vpn" = [ "Networking" ]; + "Networking_XboxLive" = [ "Networking" ]; + "Perception_Automation" = [ "Perception" ]; + "Perception_Automation_Core" = [ "Perception_Automation" ]; + "Perception_People" = [ "Perception" ]; + "Perception_Spatial" = [ "Perception" ]; + "Perception_Spatial_Preview" = [ "Perception_Spatial" ]; + "Perception_Spatial_Surfaces" = [ "Perception_Spatial" ]; + "Phone_ApplicationModel" = [ "Phone" ]; + "Phone_Devices" = [ "Phone" ]; + "Phone_Devices_Notification" = [ "Phone_Devices" ]; + "Phone_Devices_Power" = [ "Phone_Devices" ]; + "Phone_Management" = [ "Phone" ]; + "Phone_Management_Deployment" = [ "Phone_Management" ]; + "Phone_Media" = [ "Phone" ]; + "Phone_Media_Devices" = [ "Phone_Media" ]; + "Phone_Notification" = [ "Phone" ]; + "Phone_Notification_Management" = [ "Phone_Notification" ]; + "Phone_PersonalInformation" = [ "Phone" ]; + "Phone_PersonalInformation_Provisioning" = [ "Phone_PersonalInformation" ]; + "Phone_Speech" = [ "Phone" ]; + "Phone_Speech_Recognition" = [ "Phone_Speech" ]; + "Phone_StartScreen" = [ "Phone" ]; + "Phone_System" = [ "Phone" ]; + "Phone_System_Power" = [ "Phone_System" ]; + "Phone_System_Profile" = [ "Phone_System" ]; + "Phone_System_UserProfile" = [ "Phone_System" ]; + "Phone_System_UserProfile_GameServices" = [ "Phone_System_UserProfile" ]; + "Phone_System_UserProfile_GameServices_Core" = [ "Phone_System_UserProfile_GameServices" ]; + "Phone_UI" = [ "Phone" ]; + "Phone_UI_Input" = [ "Phone_UI" ]; + "Security_Authentication" = [ "Security" ]; + "Security_Authentication_Identity" = [ "Security_Authentication" ]; + "Security_Authentication_Identity_Core" = [ "Security_Authentication_Identity" ]; + "Security_Authentication_OnlineId" = [ "Security_Authentication" ]; + "Security_Authentication_Web" = [ "Security_Authentication" ]; + "Security_Authentication_Web_Core" = [ "Security_Authentication_Web" ]; + "Security_Authentication_Web_Provider" = [ "Security_Authentication_Web" ]; + "Security_Authorization" = [ "Security" ]; + "Security_Authorization_AppCapabilityAccess" = [ "Security_Authorization" ]; + "Security_Credentials" = [ "Security" ]; + "Security_Credentials_UI" = [ "Security_Credentials" ]; + "Security_Cryptography" = [ "Security" ]; + "Security_Cryptography_Certificates" = [ "Security_Cryptography" ]; + "Security_Cryptography_Core" = [ "Security_Cryptography" ]; + "Security_Cryptography_DataProtection" = [ "Security_Cryptography" ]; + "Security_DataProtection" = [ "Security" ]; + "Security_EnterpriseData" = [ "Security" ]; + "Security_ExchangeActiveSyncProvisioning" = [ "Security" ]; + "Security_Isolation" = [ "Security" ]; + "Services_Maps" = [ "Services" ]; + "Services_Maps_Guidance" = [ "Services_Maps" ]; + "Services_Maps_LocalSearch" = [ "Services_Maps" ]; + "Services_Maps_OfflineMaps" = [ "Services_Maps" ]; + "Services_Store" = [ "Services" ]; + "Services_TargetedContent" = [ "Services" ]; + "Storage_AccessCache" = [ "Storage" ]; + "Storage_BulkAccess" = [ "Storage" ]; + "Storage_Compression" = [ "Storage" ]; + "Storage_FileProperties" = [ "Storage" ]; + "Storage_Pickers" = [ "Storage" ]; + "Storage_Pickers_Provider" = [ "Storage_Pickers" ]; + "Storage_Provider" = [ "Storage" ]; + "Storage_Search" = [ "Storage" ]; + "Storage_Streams" = [ "Storage" ]; + "System_Diagnostics" = [ "System" ]; + "System_Diagnostics_DevicePortal" = [ "System_Diagnostics" ]; + "System_Diagnostics_Telemetry" = [ "System_Diagnostics" ]; + "System_Diagnostics_TraceReporting" = [ "System_Diagnostics" ]; + "System_Display" = [ "System" ]; + "System_Implementation" = [ "System" ]; + "System_Implementation_FileExplorer" = [ "System_Implementation" ]; + "System_Inventory" = [ "System" ]; + "System_Power" = [ "System" ]; + "System_Profile" = [ "System" ]; + "System_Profile_SystemManufacturers" = [ "System_Profile" ]; + "System_RemoteDesktop" = [ "System" ]; + "System_RemoteDesktop_Input" = [ "System_RemoteDesktop" ]; + "System_RemoteSystems" = [ "System" ]; + "System_Threading" = [ "System" ]; + "System_Threading_Core" = [ "System_Threading" ]; + "System_Update" = [ "System" ]; + "System_UserProfile" = [ "System" ]; + "UI_Accessibility" = [ "UI" ]; + "UI_ApplicationSettings" = [ "UI" ]; + "UI_Composition" = [ "UI" ]; + "UI_Composition_Core" = [ "UI_Composition" ]; + "UI_Composition_Desktop" = [ "UI_Composition" ]; + "UI_Composition_Diagnostics" = [ "UI_Composition" ]; + "UI_Composition_Effects" = [ "UI_Composition" ]; + "UI_Composition_Interactions" = [ "UI_Composition" ]; + "UI_Composition_Scenes" = [ "UI_Composition" ]; + "UI_Core" = [ "UI" ]; + "UI_Core_AnimationMetrics" = [ "UI_Core" ]; + "UI_Core_Preview" = [ "UI_Core" ]; + "UI_Input" = [ "UI" ]; + "UI_Input_Core" = [ "UI_Input" ]; + "UI_Input_Inking" = [ "UI_Input" ]; + "UI_Input_Inking_Analysis" = [ "UI_Input_Inking" ]; + "UI_Input_Inking_Core" = [ "UI_Input_Inking" ]; + "UI_Input_Inking_Preview" = [ "UI_Input_Inking" ]; + "UI_Input_Preview" = [ "UI_Input" ]; + "UI_Input_Preview_Injection" = [ "UI_Input_Preview" ]; + "UI_Input_Spatial" = [ "UI_Input" ]; + "UI_Notifications" = [ "UI" ]; + "UI_Notifications_Management" = [ "UI_Notifications" ]; + "UI_Popups" = [ "UI" ]; + "UI_Shell" = [ "UI" ]; + "UI_StartScreen" = [ "UI" ]; + "UI_Text" = [ "UI" ]; + "UI_Text_Core" = [ "UI_Text" ]; + "UI_UIAutomation" = [ "UI" ]; + "UI_UIAutomation_Core" = [ "UI_UIAutomation" ]; + "UI_ViewManagement" = [ "UI" ]; + "UI_ViewManagement_Core" = [ "UI_ViewManagement" ]; + "UI_WebUI" = [ "UI" ]; + "UI_WebUI_Core" = [ "UI_WebUI" ]; + "UI_WindowManagement" = [ "UI" ]; + "UI_WindowManagement_Preview" = [ "UI_WindowManagement" ]; + "Wdk_Foundation" = [ "Wdk" ]; + "Wdk_Graphics" = [ "Wdk" ]; + "Wdk_Graphics_Direct3D" = [ "Wdk_Graphics" ]; + "Wdk_Storage" = [ "Wdk" ]; + "Wdk_Storage_FileSystem" = [ "Wdk_Storage" ]; + "Wdk_Storage_FileSystem_Minifilters" = [ "Wdk_Storage_FileSystem" ]; + "Wdk_System" = [ "Wdk" ]; + "Wdk_System_IO" = [ "Wdk_System" ]; + "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; + "Wdk_System_Registry" = [ "Wdk_System" ]; + "Wdk_System_SystemInformation" = [ "Wdk_System" ]; + "Wdk_System_SystemServices" = [ "Wdk_System" ]; + "Wdk_System_Threading" = [ "Wdk_System" ]; + "Web_AtomPub" = [ "Web" ]; + "Web_Http" = [ "Web" ]; + "Web_Http_Diagnostics" = [ "Web_Http" ]; + "Web_Http_Filters" = [ "Web_Http" ]; + "Web_Http_Headers" = [ "Web_Http" ]; + "Web_Syndication" = [ "Web" ]; + "Web_UI" = [ "Web" ]; + "Web_UI_Interop" = [ "Web_UI" ]; + "Win32_AI" = [ "Win32" ]; + "Win32_AI_MachineLearning" = [ "Win32_AI" ]; + "Win32_AI_MachineLearning_DirectML" = [ "Win32_AI_MachineLearning" ]; + "Win32_AI_MachineLearning_WinML" = [ "Win32_AI_MachineLearning" ]; + "Win32_Data" = [ "Win32" ]; + "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; + "Win32_Data_RightsManagement" = [ "Win32_Data" ]; + "Win32_Data_Xml" = [ "Win32_Data" ]; + "Win32_Data_Xml_MsXml" = [ "Win32_Data_Xml" ]; + "Win32_Data_Xml_XmlLite" = [ "Win32_Data_Xml" ]; + "Win32_Devices" = [ "Win32" ]; + "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; + "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; + "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; + "Win32_Devices_Communication" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceAccess" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; + "Win32_Devices_Display" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; + "Win32_Devices_Fax" = [ "Win32_Devices" ]; + "Win32_Devices_FunctionDiscovery" = [ "Win32_Devices" ]; + "Win32_Devices_Geolocation" = [ "Win32_Devices" ]; + "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; + "Win32_Devices_ImageAcquisition" = [ "Win32_Devices" ]; + "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; + "Win32_Devices_Properties" = [ "Win32_Devices" ]; + "Win32_Devices_Pwm" = [ "Win32_Devices" ]; + "Win32_Devices_Sensors" = [ "Win32_Devices" ]; + "Win32_Devices_SerialCommunication" = [ "Win32_Devices" ]; + "Win32_Devices_Tapi" = [ "Win32_Devices" ]; + "Win32_Devices_Usb" = [ "Win32_Devices" ]; + "Win32_Devices_WebServicesOnDevices" = [ "Win32_Devices" ]; + "Win32_Foundation" = [ "Win32" ]; + "Win32_Gaming" = [ "Win32" ]; + "Win32_Globalization" = [ "Win32" ]; + "Win32_Graphics" = [ "Win32" ]; + "Win32_Graphics_CompositionSwapchain" = [ "Win32_Graphics" ]; + "Win32_Graphics_DXCore" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct2D" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct2D_Common" = [ "Win32_Graphics_Direct2D" ]; + "Win32_Graphics_Direct3D" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D10" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D11" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D11on12" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D12" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D9" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D9on12" = [ "Win32_Graphics" ]; + "Win32_Graphics_Direct3D_Dxc" = [ "Win32_Graphics_Direct3D" ]; + "Win32_Graphics_Direct3D_Fxc" = [ "Win32_Graphics_Direct3D" ]; + "Win32_Graphics_DirectComposition" = [ "Win32_Graphics" ]; + "Win32_Graphics_DirectDraw" = [ "Win32_Graphics" ]; + "Win32_Graphics_DirectManipulation" = [ "Win32_Graphics" ]; + "Win32_Graphics_DirectWrite" = [ "Win32_Graphics" ]; + "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; + "Win32_Graphics_Dxgi" = [ "Win32_Graphics" ]; + "Win32_Graphics_Dxgi_Common" = [ "Win32_Graphics_Dxgi" ]; + "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; + "Win32_Graphics_GdiPlus" = [ "Win32_Graphics" ]; + "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; + "Win32_Graphics_Imaging" = [ "Win32_Graphics" ]; + "Win32_Graphics_Imaging_D2D" = [ "Win32_Graphics_Imaging" ]; + "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing_PrintTicket" = [ "Win32_Graphics_Printing" ]; + "Win32_Management" = [ "Win32" ]; + "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; + "Win32_Media" = [ "Win32" ]; + "Win32_Media_Audio" = [ "Win32_Media" ]; + "Win32_Media_Audio_Apo" = [ "Win32_Media_Audio" ]; + "Win32_Media_Audio_DirectMusic" = [ "Win32_Media_Audio" ]; + "Win32_Media_Audio_DirectSound" = [ "Win32_Media_Audio" ]; + "Win32_Media_Audio_Endpoints" = [ "Win32_Media_Audio" ]; + "Win32_Media_Audio_XAudio2" = [ "Win32_Media_Audio" ]; + "Win32_Media_DeviceManager" = [ "Win32_Media" ]; + "Win32_Media_DirectShow" = [ "Win32_Media" ]; + "Win32_Media_DirectShow_Tv" = [ "Win32_Media_DirectShow" ]; + "Win32_Media_DirectShow_Xml" = [ "Win32_Media_DirectShow" ]; + "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; + "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; + "Win32_Media_LibrarySharingServices" = [ "Win32_Media" ]; + "Win32_Media_MediaFoundation" = [ "Win32_Media" ]; + "Win32_Media_MediaPlayer" = [ "Win32_Media" ]; + "Win32_Media_Multimedia" = [ "Win32_Media" ]; + "Win32_Media_PictureAcquisition" = [ "Win32_Media" ]; + "Win32_Media_Speech" = [ "Win32_Media" ]; + "Win32_Media_Streaming" = [ "Win32_Media" ]; + "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; + "Win32_NetworkManagement" = [ "Win32" ]; + "Win32_NetworkManagement_Dhcp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_MobileBroadband" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetworkPolicyServer" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Snmp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsConnectNow" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; + "Win32_Networking" = [ "Win32" ]; + "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; + "Win32_Networking_BackgroundIntelligentTransferService" = [ "Win32_Networking" ]; + "Win32_Networking_Clustering" = [ "Win32_Networking" ]; + "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; + "Win32_Networking_Ldap" = [ "Win32_Networking" ]; + "Win32_Networking_NetworkListManager" = [ "Win32_Networking" ]; + "Win32_Networking_RemoteDifferentialCompression" = [ "Win32_Networking" ]; + "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; + "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; + "Win32_Networking_WinInet" = [ "Win32_Networking" ]; + "Win32_Networking_WinSock" = [ "Win32_Networking" ]; + "Win32_Networking_WindowsWebServices" = [ "Win32_Networking" ]; + "Win32_Security" = [ "Win32" ]; + "Win32_Security_AppLocker" = [ "Win32_Security" ]; + "Win32_Security_Authentication" = [ "Win32_Security" ]; + "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; + "Win32_Security_Authentication_Identity_Provider" = [ "Win32_Security_Authentication_Identity" ]; + "Win32_Security_Authorization" = [ "Win32_Security" ]; + "Win32_Security_Authorization_UI" = [ "Win32_Security_Authorization" ]; + "Win32_Security_ConfigurationSnapin" = [ "Win32_Security" ]; + "Win32_Security_Credentials" = [ "Win32_Security" ]; + "Win32_Security_Cryptography" = [ "Win32_Security" ]; + "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Certificates" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Sip" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_UI" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_DiagnosticDataQuery" = [ "Win32_Security" ]; + "Win32_Security_DirectoryServices" = [ "Win32_Security" ]; + "Win32_Security_EnterpriseData" = [ "Win32_Security" ]; + "Win32_Security_ExtensibleAuthenticationProtocol" = [ "Win32_Security" ]; + "Win32_Security_Isolation" = [ "Win32_Security" ]; + "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; + "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; + "Win32_Security_Tpm" = [ "Win32_Security" ]; + "Win32_Security_WinTrust" = [ "Win32_Security" ]; + "Win32_Security_WinWlx" = [ "Win32_Security" ]; + "Win32_Storage" = [ "Win32" ]; + "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; + "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; + "Win32_Storage_Compression" = [ "Win32_Storage" ]; + "Win32_Storage_DataDeduplication" = [ "Win32_Storage" ]; + "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_EnhancedStorage" = [ "Win32_Storage" ]; + "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; + "Win32_Storage_FileServerResourceManager" = [ "Win32_Storage" ]; + "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_Imapi" = [ "Win32_Storage" ]; + "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; + "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; + "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; + "Win32_Storage_Jet" = [ "Win32_Storage" ]; + "Win32_Storage_Nvme" = [ "Win32_Storage" ]; + "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; + "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; + "Win32_Storage_Packaging_Opc" = [ "Win32_Storage_Packaging" ]; + "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; + "Win32_Storage_Vhd" = [ "Win32_Storage" ]; + "Win32_Storage_VirtualDiskService" = [ "Win32_Storage" ]; + "Win32_Storage_Vss" = [ "Win32_Storage" ]; + "Win32_Storage_Xps" = [ "Win32_Storage" ]; + "Win32_Storage_Xps_Printing" = [ "Win32_Storage_Xps" ]; + "Win32_System" = [ "Win32" ]; + "Win32_System_AddressBook" = [ "Win32_System" ]; + "Win32_System_Antimalware" = [ "Win32_System" ]; + "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; + "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; + "Win32_System_AssessmentTool" = [ "Win32_System" ]; + "Win32_System_ClrHosting" = [ "Win32_System" ]; + "Win32_System_Com" = [ "Win32_System" ]; + "Win32_System_Com_CallObj" = [ "Win32_System_Com" ]; + "Win32_System_Com_ChannelCredentials" = [ "Win32_System_Com" ]; + "Win32_System_Com_Events" = [ "Win32_System_Com" ]; + "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; + "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; + "Win32_System_Com_UI" = [ "Win32_System_Com" ]; + "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; + "Win32_System_ComponentServices" = [ "Win32_System" ]; + "Win32_System_Console" = [ "Win32_System" ]; + "Win32_System_Contacts" = [ "Win32_System" ]; + "Win32_System_CorrelationVector" = [ "Win32_System" ]; + "Win32_System_DataExchange" = [ "Win32_System" ]; + "Win32_System_DeploymentServices" = [ "Win32_System" ]; + "Win32_System_DesktopSharing" = [ "Win32_System" ]; + "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; + "Win32_System_Diagnostics" = [ "Win32_System" ]; + "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ClrProfiling" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug_ActiveScript" = [ "Win32_System_Diagnostics_Debug" ]; + "Win32_System_Diagnostics_Debug_Extensions" = [ "Win32_System_Diagnostics_Debug" ]; + "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; + "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; + "Win32_System_Environment" = [ "Win32_System" ]; + "Win32_System_ErrorReporting" = [ "Win32_System" ]; + "Win32_System_EventCollector" = [ "Win32_System" ]; + "Win32_System_EventLog" = [ "Win32_System" ]; + "Win32_System_EventNotificationService" = [ "Win32_System" ]; + "Win32_System_GroupPolicy" = [ "Win32_System" ]; + "Win32_System_HostCompute" = [ "Win32_System" ]; + "Win32_System_HostComputeNetwork" = [ "Win32_System" ]; + "Win32_System_HostComputeSystem" = [ "Win32_System" ]; + "Win32_System_Hypervisor" = [ "Win32_System" ]; + "Win32_System_IO" = [ "Win32_System" ]; + "Win32_System_Iis" = [ "Win32_System" ]; + "Win32_System_Ioctl" = [ "Win32_System" ]; + "Win32_System_JobObjects" = [ "Win32_System" ]; + "Win32_System_Js" = [ "Win32_System" ]; + "Win32_System_Kernel" = [ "Win32_System" ]; + "Win32_System_LibraryLoader" = [ "Win32_System" ]; + "Win32_System_Mailslots" = [ "Win32_System" ]; + "Win32_System_Mapi" = [ "Win32_System" ]; + "Win32_System_Memory" = [ "Win32_System" ]; + "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; + "Win32_System_MessageQueuing" = [ "Win32_System" ]; + "Win32_System_MixedReality" = [ "Win32_System" ]; + "Win32_System_Mmc" = [ "Win32_System" ]; + "Win32_System_Ole" = [ "Win32_System" ]; + "Win32_System_ParentalControls" = [ "Win32_System" ]; + "Win32_System_PasswordManagement" = [ "Win32_System" ]; + "Win32_System_Performance" = [ "Win32_System" ]; + "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; + "Win32_System_Pipes" = [ "Win32_System" ]; + "Win32_System_Power" = [ "Win32_System" ]; + "Win32_System_ProcessStatus" = [ "Win32_System" ]; + "Win32_System_RealTimeCommunications" = [ "Win32_System" ]; + "Win32_System_Recovery" = [ "Win32_System" ]; + "Win32_System_Registry" = [ "Win32_System" ]; + "Win32_System_RemoteAssistance" = [ "Win32_System" ]; + "Win32_System_RemoteDesktop" = [ "Win32_System" ]; + "Win32_System_RemoteManagement" = [ "Win32_System" ]; + "Win32_System_RestartManager" = [ "Win32_System" ]; + "Win32_System_Restore" = [ "Win32_System" ]; + "Win32_System_Rpc" = [ "Win32_System" ]; + "Win32_System_Search" = [ "Win32_System" ]; + "Win32_System_Search_Common" = [ "Win32_System_Search" ]; + "Win32_System_SecurityCenter" = [ "Win32_System" ]; + "Win32_System_ServerBackup" = [ "Win32_System" ]; + "Win32_System_Services" = [ "Win32_System" ]; + "Win32_System_SettingsManagementInfrastructure" = [ "Win32_System" ]; + "Win32_System_SetupAndMigration" = [ "Win32_System" ]; + "Win32_System_Shutdown" = [ "Win32_System" ]; + "Win32_System_SideShow" = [ "Win32_System" ]; + "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; + "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; + "Win32_System_SystemInformation" = [ "Win32_System" ]; + "Win32_System_SystemServices" = [ "Win32_System" ]; + "Win32_System_TaskScheduler" = [ "Win32_System" ]; + "Win32_System_Threading" = [ "Win32_System" ]; + "Win32_System_Time" = [ "Win32_System" ]; + "Win32_System_TpmBaseServices" = [ "Win32_System" ]; + "Win32_System_TransactionServer" = [ "Win32_System" ]; + "Win32_System_UpdateAgent" = [ "Win32_System" ]; + "Win32_System_UpdateAssessment" = [ "Win32_System" ]; + "Win32_System_UserAccessLogging" = [ "Win32_System" ]; + "Win32_System_Variant" = [ "Win32_System" ]; + "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; + "Win32_System_WinRT" = [ "Win32_System" ]; + "Win32_System_WinRT_AllJoyn" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Composition" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_CoreInputView" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Direct3D11" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Display" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Graphics" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Graphics_Capture" = [ "Win32_System_WinRT_Graphics" ]; + "Win32_System_WinRT_Graphics_Direct2D" = [ "Win32_System_WinRT_Graphics" ]; + "Win32_System_WinRT_Graphics_Imaging" = [ "Win32_System_WinRT_Graphics" ]; + "Win32_System_WinRT_Holographic" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Isolation" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_ML" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Media" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Metadata" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Pdf" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Printing" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Shell" = [ "Win32_System_WinRT" ]; + "Win32_System_WinRT_Storage" = [ "Win32_System_WinRT" ]; + "Win32_System_WindowsProgramming" = [ "Win32_System" ]; + "Win32_System_WindowsSync" = [ "Win32_System" ]; + "Win32_System_Wmi" = [ "Win32_System" ]; + "Win32_UI" = [ "Win32" ]; + "Win32_UI_Accessibility" = [ "Win32_UI" ]; + "Win32_UI_Animation" = [ "Win32_UI" ]; + "Win32_UI_ColorSystem" = [ "Win32_UI" ]; + "Win32_UI_Controls" = [ "Win32_UI" ]; + "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; + "Win32_UI_Controls_RichEdit" = [ "Win32_UI_Controls" ]; + "Win32_UI_HiDpi" = [ "Win32_UI" ]; + "Win32_UI_Input" = [ "Win32_UI" ]; + "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Ink" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Radial" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; + "Win32_UI_InteractionContext" = [ "Win32_UI" ]; + "Win32_UI_LegacyWindowsEnvironmentFeatures" = [ "Win32_UI" ]; + "Win32_UI_Magnification" = [ "Win32_UI" ]; + "Win32_UI_Notifications" = [ "Win32_UI" ]; + "Win32_UI_Ribbon" = [ "Win32_UI" ]; + "Win32_UI_Shell" = [ "Win32_UI" ]; + "Win32_UI_Shell_Common" = [ "Win32_UI_Shell" ]; + "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; + "Win32_UI_TabletPC" = [ "Win32_UI" ]; + "Win32_UI_TextServices" = [ "Win32_UI" ]; + "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; + "Win32_UI_Wpf" = [ "Win32_UI" ]; + "Win32_Web" = [ "Win32" ]; + "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; + "implement" = [ "windows-implement" "windows-interface" "windows-core/implement" ]; + "windows-implement" = [ "dep:windows-implement" ]; + "windows-interface" = [ "dep:windows-interface" ]; + }; + resolvedDefaultFeatures = [ "Wdk" "Wdk_System" "Wdk_System_SystemInformation" "Wdk_System_SystemServices" "Wdk_System_Threading" "Win32" "Win32_Foundation" "Win32_NetworkManagement" "Win32_NetworkManagement_IpHelper" "Win32_NetworkManagement_Ndis" "Win32_NetworkManagement_NetManagement" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Security_Authentication" "Win32_Security_Authentication_Identity" "Win32_Security_Authorization" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Com" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_Ioctl" "Win32_System_Kernel" "Win32_System_LibraryLoader" "Win32_System_Memory" "Win32_System_Ole" "Win32_System_Performance" "Win32_System_Power" "Win32_System_ProcessStatus" "Win32_System_Registry" "Win32_System_RemoteDesktop" "Win32_System_Rpc" "Win32_System_SystemInformation" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_Variant" "Win32_System_WindowsProgramming" "Win32_System_Wmi" "Win32_UI" "Win32_UI_Shell" "default" ]; + }; + "windows-core" = rec { + crateName = "windows-core"; + version = "0.52.0"; + edition = "2021"; + sha256 = "1nc3qv7sy24x0nlnb32f7alzpd6f72l4p24vl65vydbyil669ark"; + libName = "windows_core"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-targets"; + packageId = "windows-targets 0.52.3"; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; + "windows-sys" = rec { + crateName = "windows-sys"; + version = "0.52.0"; + edition = "2021"; + sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + libName = "windows_sys"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-targets"; + packageId = "windows-targets 0.52.3"; + } + ]; + features = { + "Wdk_Foundation" = [ "Wdk" ]; + "Wdk_Graphics" = [ "Wdk" ]; + "Wdk_Graphics_Direct3D" = [ "Wdk_Graphics" ]; + "Wdk_Storage" = [ "Wdk" ]; + "Wdk_Storage_FileSystem" = [ "Wdk_Storage" ]; + "Wdk_Storage_FileSystem_Minifilters" = [ "Wdk_Storage_FileSystem" ]; + "Wdk_System" = [ "Wdk" ]; + "Wdk_System_IO" = [ "Wdk_System" ]; + "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; + "Wdk_System_Registry" = [ "Wdk_System" ]; + "Wdk_System_SystemInformation" = [ "Wdk_System" ]; + "Wdk_System_SystemServices" = [ "Wdk_System" ]; + "Wdk_System_Threading" = [ "Wdk_System" ]; + "Win32_Data" = [ "Win32" ]; + "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; + "Win32_Data_RightsManagement" = [ "Win32_Data" ]; + "Win32_Devices" = [ "Win32" ]; + "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; + "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; + "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; + "Win32_Devices_Communication" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; + "Win32_Devices_Display" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; + "Win32_Devices_Fax" = [ "Win32_Devices" ]; + "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; + "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; + "Win32_Devices_Properties" = [ "Win32_Devices" ]; + "Win32_Devices_Pwm" = [ "Win32_Devices" ]; + "Win32_Devices_Sensors" = [ "Win32_Devices" ]; + "Win32_Devices_SerialCommunication" = [ "Win32_Devices" ]; + "Win32_Devices_Tapi" = [ "Win32_Devices" ]; + "Win32_Devices_Usb" = [ "Win32_Devices" ]; + "Win32_Devices_WebServicesOnDevices" = [ "Win32_Devices" ]; + "Win32_Foundation" = [ "Win32" ]; + "Win32_Gaming" = [ "Win32" ]; + "Win32_Globalization" = [ "Win32" ]; + "Win32_Graphics" = [ "Win32" ]; + "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; + "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; + "Win32_Graphics_GdiPlus" = [ "Win32_Graphics" ]; + "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; + "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing_PrintTicket" = [ "Win32_Graphics_Printing" ]; + "Win32_Management" = [ "Win32" ]; + "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; + "Win32_Media" = [ "Win32" ]; + "Win32_Media_Audio" = [ "Win32_Media" ]; + "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; + "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; + "Win32_Media_Multimedia" = [ "Win32_Media" ]; + "Win32_Media_Streaming" = [ "Win32_Media" ]; + "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; + "Win32_NetworkManagement" = [ "Win32" ]; + "Win32_NetworkManagement_Dhcp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Snmp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; + "Win32_Networking" = [ "Win32" ]; + "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; + "Win32_Networking_Clustering" = [ "Win32_Networking" ]; + "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; + "Win32_Networking_Ldap" = [ "Win32_Networking" ]; + "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; + "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; + "Win32_Networking_WinInet" = [ "Win32_Networking" ]; + "Win32_Networking_WinSock" = [ "Win32_Networking" ]; + "Win32_Networking_WindowsWebServices" = [ "Win32_Networking" ]; + "Win32_Security" = [ "Win32" ]; + "Win32_Security_AppLocker" = [ "Win32_Security" ]; + "Win32_Security_Authentication" = [ "Win32_Security" ]; + "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; + "Win32_Security_Authorization" = [ "Win32_Security" ]; + "Win32_Security_Credentials" = [ "Win32_Security" ]; + "Win32_Security_Cryptography" = [ "Win32_Security" ]; + "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Certificates" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Sip" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_UI" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_DiagnosticDataQuery" = [ "Win32_Security" ]; + "Win32_Security_DirectoryServices" = [ "Win32_Security" ]; + "Win32_Security_EnterpriseData" = [ "Win32_Security" ]; + "Win32_Security_ExtensibleAuthenticationProtocol" = [ "Win32_Security" ]; + "Win32_Security_Isolation" = [ "Win32_Security" ]; + "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; + "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; + "Win32_Security_WinTrust" = [ "Win32_Security" ]; + "Win32_Security_WinWlx" = [ "Win32_Security" ]; + "Win32_Storage" = [ "Win32" ]; + "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; + "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; + "Win32_Storage_Compression" = [ "Win32_Storage" ]; + "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; + "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_Imapi" = [ "Win32_Storage" ]; + "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; + "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; + "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; + "Win32_Storage_Jet" = [ "Win32_Storage" ]; + "Win32_Storage_Nvme" = [ "Win32_Storage" ]; + "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; + "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; + "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; + "Win32_Storage_Vhd" = [ "Win32_Storage" ]; + "Win32_Storage_Xps" = [ "Win32_Storage" ]; + "Win32_System" = [ "Win32" ]; + "Win32_System_AddressBook" = [ "Win32_System" ]; + "Win32_System_Antimalware" = [ "Win32_System" ]; + "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; + "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; + "Win32_System_ClrHosting" = [ "Win32_System" ]; + "Win32_System_Com" = [ "Win32_System" ]; + "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; + "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; + "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; + "Win32_System_ComponentServices" = [ "Win32_System" ]; + "Win32_System_Console" = [ "Win32_System" ]; + "Win32_System_CorrelationVector" = [ "Win32_System" ]; + "Win32_System_DataExchange" = [ "Win32_System" ]; + "Win32_System_DeploymentServices" = [ "Win32_System" ]; + "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; + "Win32_System_Diagnostics" = [ "Win32_System" ]; + "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug_Extensions" = [ "Win32_System_Diagnostics_Debug" ]; + "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; + "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; + "Win32_System_Environment" = [ "Win32_System" ]; + "Win32_System_ErrorReporting" = [ "Win32_System" ]; + "Win32_System_EventCollector" = [ "Win32_System" ]; + "Win32_System_EventLog" = [ "Win32_System" ]; + "Win32_System_EventNotificationService" = [ "Win32_System" ]; + "Win32_System_GroupPolicy" = [ "Win32_System" ]; + "Win32_System_HostCompute" = [ "Win32_System" ]; + "Win32_System_HostComputeNetwork" = [ "Win32_System" ]; + "Win32_System_HostComputeSystem" = [ "Win32_System" ]; + "Win32_System_Hypervisor" = [ "Win32_System" ]; + "Win32_System_IO" = [ "Win32_System" ]; + "Win32_System_Iis" = [ "Win32_System" ]; + "Win32_System_Ioctl" = [ "Win32_System" ]; + "Win32_System_JobObjects" = [ "Win32_System" ]; + "Win32_System_Js" = [ "Win32_System" ]; + "Win32_System_Kernel" = [ "Win32_System" ]; + "Win32_System_LibraryLoader" = [ "Win32_System" ]; + "Win32_System_Mailslots" = [ "Win32_System" ]; + "Win32_System_Mapi" = [ "Win32_System" ]; + "Win32_System_Memory" = [ "Win32_System" ]; + "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; + "Win32_System_MessageQueuing" = [ "Win32_System" ]; + "Win32_System_MixedReality" = [ "Win32_System" ]; + "Win32_System_Ole" = [ "Win32_System" ]; + "Win32_System_PasswordManagement" = [ "Win32_System" ]; + "Win32_System_Performance" = [ "Win32_System" ]; + "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; + "Win32_System_Pipes" = [ "Win32_System" ]; + "Win32_System_Power" = [ "Win32_System" ]; + "Win32_System_ProcessStatus" = [ "Win32_System" ]; + "Win32_System_Recovery" = [ "Win32_System" ]; + "Win32_System_Registry" = [ "Win32_System" ]; + "Win32_System_RemoteDesktop" = [ "Win32_System" ]; + "Win32_System_RemoteManagement" = [ "Win32_System" ]; + "Win32_System_RestartManager" = [ "Win32_System" ]; + "Win32_System_Restore" = [ "Win32_System" ]; + "Win32_System_Rpc" = [ "Win32_System" ]; + "Win32_System_Search" = [ "Win32_System" ]; + "Win32_System_Search_Common" = [ "Win32_System_Search" ]; + "Win32_System_SecurityCenter" = [ "Win32_System" ]; + "Win32_System_Services" = [ "Win32_System" ]; + "Win32_System_SetupAndMigration" = [ "Win32_System" ]; + "Win32_System_Shutdown" = [ "Win32_System" ]; + "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; + "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; + "Win32_System_SystemInformation" = [ "Win32_System" ]; + "Win32_System_SystemServices" = [ "Win32_System" ]; + "Win32_System_Threading" = [ "Win32_System" ]; + "Win32_System_Time" = [ "Win32_System" ]; + "Win32_System_TpmBaseServices" = [ "Win32_System" ]; + "Win32_System_UserAccessLogging" = [ "Win32_System" ]; + "Win32_System_Variant" = [ "Win32_System" ]; + "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; + "Win32_System_WindowsProgramming" = [ "Win32_System" ]; + "Win32_System_Wmi" = [ "Win32_System" ]; + "Win32_UI" = [ "Win32" ]; + "Win32_UI_Accessibility" = [ "Win32_UI" ]; + "Win32_UI_ColorSystem" = [ "Win32_UI" ]; + "Win32_UI_Controls" = [ "Win32_UI" ]; + "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; + "Win32_UI_HiDpi" = [ "Win32_UI" ]; + "Win32_UI_Input" = [ "Win32_UI" ]; + "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; + "Win32_UI_InteractionContext" = [ "Win32_UI" ]; + "Win32_UI_Magnification" = [ "Win32_UI" ]; + "Win32_UI_Shell" = [ "Win32_UI" ]; + "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; + "Win32_UI_TabletPC" = [ "Win32_UI" ]; + "Win32_UI_TextServices" = [ "Win32_UI" ]; + "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; + "Win32_Web" = [ "Win32" ]; + "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; + }; + resolvedDefaultFeatures = [ "Wdk" "Wdk_Foundation" "Wdk_Storage" "Wdk_Storage_FileSystem" "Wdk_System" "Wdk_System_IO" "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Security_Authentication" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_Security_Cryptography" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Com" "Win32_System_Console" "Win32_System_IO" "Win32_System_Memory" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "Win32_UI" "Win32_UI_Input" "Win32_UI_Input_KeyboardAndMouse" "Win32_UI_Shell" "default" ]; + }; + "windows-targets 0.48.5" = rec { + crateName = "windows-targets"; + version = "0.48.5"; + edition = "2018"; + sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + libName = "windows_targets"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows_aarch64_gnullvm"; + packageId = "windows_aarch64_gnullvm 0.48.5"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); + } + { + name = "windows_aarch64_msvc"; + packageId = "windows_aarch64_msvc 0.48.5"; + target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_i686_gnu"; + packageId = "windows_i686_gnu 0.48.5"; + target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_i686_msvc"; + packageId = "windows_i686_msvc 0.48.5"; + target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_x86_64_gnu"; + packageId = "windows_x86_64_gnu 0.48.5"; + target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_x86_64_gnullvm"; + packageId = "windows_x86_64_gnullvm 0.48.5"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); + } + { + name = "windows_x86_64_msvc"; + packageId = "windows_x86_64_msvc 0.48.5"; + target = { target, features }: (("x86_64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + } + ]; + + }; + "windows-targets 0.52.3" = rec { + crateName = "windows-targets"; + version = "0.52.3"; + edition = "2021"; + sha256 = "0pywy8z7zbfisapc1f5cpcik3hygii5x67p9m6l6jx8qqwfvm06k"; + libName = "windows_targets"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows_aarch64_gnullvm"; + packageId = "windows_aarch64_gnullvm 0.52.3"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); + } + { + name = "windows_aarch64_msvc"; + packageId = "windows_aarch64_msvc 0.52.3"; + target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_i686_gnu"; + packageId = "windows_i686_gnu 0.52.3"; + target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_i686_msvc"; + packageId = "windows_i686_msvc 0.52.3"; + target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_x86_64_gnu"; + packageId = "windows_x86_64_gnu 0.52.3"; + target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_x86_64_gnullvm"; + packageId = "windows_x86_64_gnullvm 0.52.3"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); + } + { + name = "windows_x86_64_msvc"; + packageId = "windows_x86_64_msvc 0.52.3"; + target = { target, features }: (("x86_64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + } + ]; + + }; + "windows_aarch64_gnullvm 0.48.5" = rec { + crateName = "windows_aarch64_gnullvm"; + version = "0.48.5"; + edition = "2018"; + sha256 = "1n05v7qblg1ci3i567inc7xrkmywczxrs1z3lj3rkkxw18py6f1b"; + authors = [ + "Microsoft" + ]; + + }; + "windows_aarch64_gnullvm 0.52.3" = rec { + crateName = "windows_aarch64_gnullvm"; + version = "0.52.3"; + edition = "2021"; + sha256 = "1ikfdjjznh4yvji0w296zaidk1jdgdmfb1lgkkykmx8kjkxxrrb8"; + authors = [ + "Microsoft" + ]; + + }; + "windows_aarch64_msvc 0.48.5" = rec { + crateName = "windows_aarch64_msvc"; + version = "0.48.5"; + edition = "2018"; + sha256 = "1g5l4ry968p73g6bg6jgyvy9lb8fyhcs54067yzxpcpkf44k2dfw"; + authors = [ + "Microsoft" + ]; + + }; + "windows_aarch64_msvc 0.52.3" = rec { + crateName = "windows_aarch64_msvc"; + version = "0.52.3"; + edition = "2021"; + sha256 = "03xkcn4mxzmkqqc9pd30czj1qm4f629bzvk9kqqrhmy4pfg4dawd"; + authors = [ + "Microsoft" + ]; + + }; + "windows_i686_gnu 0.48.5" = rec { + crateName = "windows_i686_gnu"; + version = "0.48.5"; + edition = "2018"; + sha256 = "0gklnglwd9ilqx7ac3cn8hbhkraqisd0n83jxzf9837nvvkiand7"; + authors = [ + "Microsoft" + ]; + + }; + "windows_i686_gnu 0.52.3" = rec { + crateName = "windows_i686_gnu"; + version = "0.52.3"; + edition = "2021"; + sha256 = "1yrkl23hcmknja9hyv3b6bc08d5c9q2f391q865llwxcgim9nkia"; + authors = [ + "Microsoft" + ]; + + }; + "windows_i686_msvc 0.48.5" = rec { + crateName = "windows_i686_msvc"; + version = "0.48.5"; + edition = "2018"; + sha256 = "01m4rik437dl9rdf0ndnm2syh10hizvq0dajdkv2fjqcywrw4mcg"; + authors = [ + "Microsoft" + ]; + + }; + "windows_i686_msvc 0.52.3" = rec { + crateName = "windows_i686_msvc"; + version = "0.52.3"; + edition = "2021"; + sha256 = "0n1c4dgwmxqca1kwwniav9qi79fldbx5qxbq9brmza9c8affrc18"; + authors = [ + "Microsoft" + ]; + + }; + "windows_x86_64_gnu 0.48.5" = rec { + crateName = "windows_x86_64_gnu"; + version = "0.48.5"; + edition = "2018"; + sha256 = "13kiqqcvz2vnyxzydjh73hwgigsdr2z1xpzx313kxll34nyhmm2k"; + authors = [ + "Microsoft" + ]; + + }; + "windows_x86_64_gnu 0.52.3" = rec { + crateName = "windows_x86_64_gnu"; + version = "0.52.3"; + edition = "2021"; + sha256 = "050n225hmbpvj7snhi6gisqqj9b3srvj4j23rpbqjgm93dbk2hbh"; + authors = [ + "Microsoft" + ]; + + }; + "windows_x86_64_gnullvm 0.48.5" = rec { + crateName = "windows_x86_64_gnullvm"; + version = "0.48.5"; + edition = "2018"; + sha256 = "1k24810wfbgz8k48c2yknqjmiigmql6kk3knmddkv8k8g1v54yqb"; + authors = [ + "Microsoft" + ]; + + }; + "windows_x86_64_gnullvm 0.52.3" = rec { + crateName = "windows_x86_64_gnullvm"; + version = "0.52.3"; + edition = "2021"; + sha256 = "077jxkl54lgxrkvmdd1ashnyai64mk03h76nk0g1ahqna6ar41s2"; + authors = [ + "Microsoft" + ]; + + }; + "windows_x86_64_msvc 0.48.5" = rec { + crateName = "windows_x86_64_msvc"; + version = "0.48.5"; + edition = "2018"; + sha256 = "0f4mdp895kkjh9zv8dxvn4pc10xr7839lf5pa9l0193i2pkgr57d"; + authors = [ + "Microsoft" + ]; + + }; + "windows_x86_64_msvc 0.52.3" = rec { + crateName = "windows_x86_64_msvc"; + version = "0.52.3"; + edition = "2021"; + sha256 = "1mnjdqcr16bxzmcicgcni37svami5gysjgwvk2766w59c0yq6w07"; + authors = [ + "Microsoft" + ]; + + }; + "xmlparser" = rec { + crateName = "xmlparser"; + version = "0.13.6"; + edition = "2018"; + sha256 = "1r796g21c70p983ax0j6rmhzmalg4rhx61mvd4farxdhfyvy1zk6"; + authors = [ + "Yevhenii Reizner <razrfalcon@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "xxhash-rust" = rec { + crateName = "xxhash-rust"; + version = "0.8.10"; + edition = "2018"; + sha256 = "00zfsfigb6zh0x8aaickkkyd3vyjgnrq36ym04lil7my4lgahzcj"; + libName = "xxhash_rust"; + authors = [ + "Douman <douman@gmx.se>" + ]; + features = { }; + resolvedDefaultFeatures = [ "xxh3" ]; + }; + "xz2" = rec { + crateName = "xz2"; + version = "0.1.7"; + edition = "2018"; + sha256 = "1qk7nzpblizvayyq4xzi4b0zacmmbqr6vb9fc0v1avyp17f4931q"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "lzma-sys"; + packageId = "lzma-sys"; + } + ]; + features = { + "futures" = [ "dep:futures" ]; + "static" = [ "lzma-sys/static" ]; + "tokio" = [ "tokio-io" "futures" ]; + "tokio-io" = [ "dep:tokio-io" ]; + }; + }; + "zerocopy" = rec { + crateName = "zerocopy"; + version = "0.7.32"; + edition = "2018"; + sha256 = "1ghnfxw69kx5d1aqfd5fsfrra9dgpz17yqx84nd4ryjk3sbd7m3l"; + authors = [ + "Joshua Liebow-Feeser <joshlf@google.com>" + ]; + dependencies = [ + { + name = "zerocopy-derive"; + packageId = "zerocopy-derive"; + optional = true; + } + { + name = "zerocopy-derive"; + packageId = "zerocopy-derive"; + target = { target, features }: false; + } + ]; + devDependencies = [ + { + name = "zerocopy-derive"; + packageId = "zerocopy-derive"; + } + ]; + features = { + "__internal_use_only_features_that_work_on_stable" = [ "alloc" "derive" "simd" ]; + "byteorder" = [ "dep:byteorder" ]; + "default" = [ "byteorder" ]; + "derive" = [ "zerocopy-derive" ]; + "simd-nightly" = [ "simd" ]; + "zerocopy-derive" = [ "dep:zerocopy-derive" ]; + }; + resolvedDefaultFeatures = [ "simd" ]; + }; + "zerocopy-derive" = rec { + crateName = "zerocopy-derive"; + version = "0.7.32"; + edition = "2018"; + sha256 = "19nj11md42aijyqnfx8pa647fjzhz537xyc624rajwwfrn6b3qcw"; + procMacro = true; + libName = "zerocopy_derive"; + authors = [ + "Joshua Liebow-Feeser <joshlf@google.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + } + ]; + + }; + "zeroize" = rec { + crateName = "zeroize"; + version = "1.7.0"; + edition = "2021"; + sha256 = "0bfvby7k9pdp6623p98yz2irqnamcyzpn7zh20nqmdn68b0lwnsj"; + authors = [ + "The RustCrypto Project Developers" + ]; + features = { + "default" = [ "alloc" ]; + "derive" = [ "zeroize_derive" ]; + "serde" = [ "dep:serde" ]; + "std" = [ "alloc" ]; + "zeroize_derive" = [ "dep:zeroize_derive" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" ]; + }; + "zstd" = rec { + crateName = "zstd"; + version = "0.13.0"; + edition = "2018"; + sha256 = "0401q54s9r35x2i7m1kwppgkj79g0pb6xz3xpby7qlkdb44k7yxz"; + authors = [ + "Alexandre Bury <alexandre.bury@gmail.com>" + ]; + dependencies = [ + { + name = "zstd-safe"; + packageId = "zstd-safe"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + ]; + features = { + "arrays" = [ "zstd-safe/arrays" ]; + "bindgen" = [ "zstd-safe/bindgen" ]; + "debug" = [ "zstd-safe/debug" ]; + "default" = [ "legacy" "arrays" "zdict_builder" ]; + "experimental" = [ "zstd-safe/experimental" ]; + "fat-lto" = [ "zstd-safe/fat-lto" ]; + "legacy" = [ "zstd-safe/legacy" ]; + "no_asm" = [ "zstd-safe/no_asm" ]; + "pkg-config" = [ "zstd-safe/pkg-config" ]; + "thin" = [ "zstd-safe/thin" ]; + "thin-lto" = [ "zstd-safe/thin-lto" ]; + "zdict_builder" = [ "zstd-safe/zdict_builder" ]; + "zstdmt" = [ "zstd-safe/zstdmt" ]; + }; + resolvedDefaultFeatures = [ "arrays" "default" "legacy" "zdict_builder" ]; + }; + "zstd-safe" = rec { + crateName = "zstd-safe"; + version = "7.0.0"; + edition = "2018"; + sha256 = "0gpav2lcibrpmyslmjkcn3w0w64qif3jjljd2h8lr4p249s7qx23"; + libName = "zstd_safe"; + authors = [ + "Alexandre Bury <alexandre.bury@gmail.com>" + ]; + dependencies = [ + { + name = "zstd-sys"; + packageId = "zstd-sys"; + usesDefaultFeatures = false; + } + ]; + features = { + "bindgen" = [ "zstd-sys/bindgen" ]; + "debug" = [ "zstd-sys/debug" ]; + "default" = [ "legacy" "arrays" "zdict_builder" ]; + "experimental" = [ "zstd-sys/experimental" ]; + "fat-lto" = [ "zstd-sys/fat-lto" ]; + "legacy" = [ "zstd-sys/legacy" ]; + "no_asm" = [ "zstd-sys/no_asm" ]; + "pkg-config" = [ "zstd-sys/pkg-config" ]; + "std" = [ "zstd-sys/std" ]; + "thin" = [ "zstd-sys/thin" ]; + "thin-lto" = [ "zstd-sys/thin-lto" ]; + "zdict_builder" = [ "zstd-sys/zdict_builder" ]; + "zstdmt" = [ "zstd-sys/zstdmt" ]; + }; + resolvedDefaultFeatures = [ "arrays" "legacy" "std" "zdict_builder" ]; + }; + "zstd-sys" = rec { + crateName = "zstd-sys"; + version = "2.0.9+zstd.1.5.5"; + edition = "2018"; + links = "zstd"; + sha256 = "0mk6a2367swdi22zg03lcackpnvgq96d7120awd4i83lm2lfy5ly"; + libName = "zstd_sys"; + authors = [ + "Alexandre Bury <alexandre.bury@gmail.com>" + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + features = [ "parallel" ]; + } + { + name = "pkg-config"; + packageId = "pkg-config"; + } + ]; + features = { + "bindgen" = [ "dep:bindgen" ]; + "default" = [ "legacy" "zdict_builder" ]; + }; + resolvedDefaultFeatures = [ "legacy" "std" "zdict_builder" ]; + }; + }; + + # + # crate2nix/default.nix (excerpt start) + # + + /* Target (platform) data for conditional dependencies. + This corresponds roughly to what buildRustCrate is setting. + */ + makeDefaultTarget = platform: { + unix = platform.isUnix; + windows = platform.isWindows; + fuchsia = true; + test = false; + + inherit (platform.rust.platform) + arch + os + vendor; + family = platform.rust.platform.target-family; + env = "gnu"; + endian = + if platform.parsed.cpu.significantByte.name == "littleEndian" + then "little" else "big"; + pointer_width = toString platform.parsed.cpu.bits; + debug_assertions = false; + }; + + /* Filters common temp files and build files. */ + # TODO(pkolloch): Substitute with gitignore filter + sourceFilter = name: type: + let + baseName = builtins.baseNameOf (builtins.toString name); + in + ! ( + # Filter out git + baseName == ".gitignore" + || (type == "directory" && baseName == ".git") + + # Filter out build results + || ( + type == "directory" && ( + baseName == "target" + || baseName == "_site" + || baseName == ".sass-cache" + || baseName == ".jekyll-metadata" + || baseName == "build-artifacts" + ) + ) + + # Filter out nix-build result symlinks + || ( + type == "symlink" && lib.hasPrefix "result" baseName + ) + + # Filter out IDE config + || ( + type == "directory" && ( + baseName == ".idea" || baseName == ".vscode" + ) + ) || lib.hasSuffix ".iml" baseName + + # Filter out nix build files + || baseName == "Cargo.nix" + + # Filter out editor backup / swap files. + || lib.hasSuffix "~" baseName + || builtins.match "^\\.sw[a-z]$$" baseName != null + || builtins.match "^\\..*\\.sw[a-z]$$" baseName != null + || lib.hasSuffix ".tmp" baseName + || lib.hasSuffix ".bak" baseName + || baseName == "tests.nix" + ); + + /* Returns a crate which depends on successful test execution + of crate given as the second argument. + + testCrateFlags: list of flags to pass to the test exectuable + testInputs: list of packages that should be available during test execution + */ + crateWithTest = { crate, testCrate, testCrateFlags, testInputs, testPreRun, testPostRun }: + assert builtins.typeOf testCrateFlags == "list"; + assert builtins.typeOf testInputs == "list"; + assert builtins.typeOf testPreRun == "string"; + assert builtins.typeOf testPostRun == "string"; + let + # override the `crate` so that it will build and execute tests instead of + # building the actual lib and bin targets We just have to pass `--test` + # to rustc and it will do the right thing. We execute the tests and copy + # their log and the test executables to $out for later inspection. + test = + let + drv = testCrate.override + ( + _: { + buildTests = true; + release = false; + } + ); + # If the user hasn't set any pre/post commands, we don't want to + # insert empty lines. This means that any existing users of crate2nix + # don't get a spurious rebuild unless they set these explicitly. + testCommand = pkgs.lib.concatStringsSep "\n" + (pkgs.lib.filter (s: s != "") [ + testPreRun + "$f $testCrateFlags 2>&1 | tee -a $out" + testPostRun + ]); + in + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; + + inherit (crate) src; + + inherit testCrateFlags; + + buildInputs = testInputs; + + buildPhase = '' + set -e + export RUST_BACKTRACE=1 + + # build outputs + testRoot=target/debug + mkdir -p $testRoot + + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . + + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; + in + pkgs.runCommand "${crate.name}-linked" + { + inherit (crate) outputs crateName; + passthru = (crate.passthru or { }) // { + inherit test; + }; + } + (lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) '' + echo tested by ${test} + '' + '' + ${lib.concatMapStringsSep "\n" (output: "ln -s ${crate.${output}} ${"$"}${output}") crate.outputs} + ''); + + /* A restricted overridable version of builtRustCratesWithFeatures. */ + buildRustCrateWithFeatures = + { packageId + , features ? rootFeatures + , crateOverrides ? defaultCrateOverrides + , buildRustCrateForPkgsFunc ? null + , runTests ? false + , testCrateFlags ? [ ] + , testInputs ? [ ] + # Any command to run immediatelly before a test is executed. + , testPreRun ? "" + # Any command run immediatelly after a test is executed. + , testPostRun ? "" + }: + lib.makeOverridable + ( + { features + , crateOverrides + , runTests + , testCrateFlags + , testInputs + , testPreRun + , testPostRun + }: + let + buildRustCrateForPkgsFuncOverriden = + if buildRustCrateForPkgsFunc != null + then buildRustCrateForPkgsFunc + else + ( + if crateOverrides == pkgs.defaultCrateOverrides + then buildRustCrateForPkgs + else + pkgs: (buildRustCrateForPkgs pkgs).override { + defaultCrateOverrides = crateOverrides; + } + ); + builtRustCrates = builtRustCratesWithFeatures { + inherit packageId features; + buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; + runTests = false; + }; + builtTestRustCrates = builtRustCratesWithFeatures { + inherit packageId features; + buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; + runTests = true; + }; + drv = builtRustCrates.crates.${packageId}; + testDrv = builtTestRustCrates.crates.${packageId}; + derivation = + if runTests then + crateWithTest + { + crate = drv; + testCrate = testDrv; + inherit testCrateFlags testInputs testPreRun testPostRun; + } + else drv; + in + derivation + ) + { inherit features crateOverrides runTests testCrateFlags testInputs testPreRun testPostRun; }; + + /* Returns an attr set with packageId mapped to the result of buildRustCrateForPkgsFunc + for the corresponding crate. + */ + builtRustCratesWithFeatures = + { packageId + , features + , crateConfigs ? crates + , buildRustCrateForPkgsFunc + , runTests + , makeTarget ? makeDefaultTarget + } @ args: + assert (builtins.isAttrs crateConfigs); + assert (builtins.isString packageId); + assert (builtins.isList features); + assert (builtins.isAttrs (makeTarget stdenv.hostPlatform)); + assert (builtins.isBool runTests); + let + rootPackageId = packageId; + mergedFeatures = mergePackageFeatures + ( + args // { + inherit rootPackageId; + target = makeTarget stdenv.hostPlatform // { test = runTests; }; + } + ); + # Memoize built packages so that reappearing packages are only built once. + builtByPackageIdByPkgs = mkBuiltByPackageIdByPkgs pkgs; + mkBuiltByPackageIdByPkgs = pkgs: + let + self = { + crates = lib.mapAttrs (packageId: value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs; + target = makeTarget stdenv.hostPlatform; + build = mkBuiltByPackageIdByPkgs pkgs.buildPackages; + }; + in + self; + buildByPackageIdForPkgsImpl = self: pkgs: packageId: + let + features = mergedFeatures."${packageId}" or [ ]; + crateConfig' = crateConfigs."${packageId}"; + crateConfig = + builtins.removeAttrs crateConfig' [ "resolvedDefaultFeatures" "devDependencies" ]; + devDependencies = + lib.optionals + (runTests && packageId == rootPackageId) + (crateConfig'.devDependencies or [ ]); + dependencies = + dependencyDerivations { + inherit features; + inherit (self) target; + buildByPackageId = depPackageId: + # proc_macro crates must be compiled for the build architecture + if crateConfigs.${depPackageId}.procMacro or false + then self.build.crates.${depPackageId} + else self.crates.${depPackageId}; + dependencies = + (crateConfig.dependencies or [ ]) + ++ devDependencies; + }; + buildDependencies = + dependencyDerivations { + inherit features; + inherit (self.build) target; + buildByPackageId = depPackageId: + self.build.crates.${depPackageId}; + dependencies = crateConfig.buildDependencies or [ ]; + }; + dependenciesWithRenames = + let + buildDeps = filterEnabledDependencies { + inherit features; + inherit (self) target; + dependencies = crateConfig.dependencies or [ ] ++ devDependencies; + }; + hostDeps = filterEnabledDependencies { + inherit features; + inherit (self.build) target; + dependencies = crateConfig.buildDependencies or [ ]; + }; + in + lib.filter (d: d ? "rename") (hostDeps ++ buildDeps); + # Crate renames have the form: + # + # { + # crate_name = [ + # { version = "1.2.3"; rename = "crate_name01"; } + # ]; + # # ... + # } + crateRenames = + let + grouped = + lib.groupBy + (dependency: dependency.name) + dependenciesWithRenames; + versionAndRename = dep: + let + package = crateConfigs."${dep.packageId}"; + in + { inherit (dep) rename; inherit (package) version; }; + in + lib.mapAttrs (name: builtins.map versionAndRename) grouped; + in + buildRustCrateForPkgsFunc pkgs + ( + crateConfig // { + src = crateConfig.src or ( + pkgs.fetchurl rec { + name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz"; + # https://www.pietroalbini.org/blog/downloading-crates-io/ + # Not rate-limited, CDN URL. + url = "https://static.crates.io/crates/${crateConfig.crateName}/${crateConfig.crateName}-${crateConfig.version}.crate"; + sha256 = + assert (lib.assertMsg (crateConfig ? sha256) "Missing sha256 for ${name}"); + crateConfig.sha256; + } + ); + extraRustcOpts = lib.lists.optional (targetFeatures != [ ]) "-C target-feature=${lib.concatMapStringsSep "," (x: "+${x}") targetFeatures}"; + inherit features dependencies buildDependencies crateRenames release; + } + ); + in + builtByPackageIdByPkgs; + + /* Returns the actual derivations for the given dependencies. */ + dependencyDerivations = + { buildByPackageId + , features + , dependencies + , target + }: + assert (builtins.isList features); + assert (builtins.isList dependencies); + assert (builtins.isAttrs target); + let + enabledDependencies = filterEnabledDependencies { + inherit dependencies features target; + }; + depDerivation = dependency: buildByPackageId dependency.packageId; + in + map depDerivation enabledDependencies; + + /* Returns a sanitized version of val with all values substituted that cannot + be serialized as JSON. + */ + sanitizeForJson = val: + if builtins.isAttrs val + then lib.mapAttrs (n: sanitizeForJson) val + else if builtins.isList val + then builtins.map sanitizeForJson val + else if builtins.isFunction val + then "function" + else val; + + /* Returns various tools to debug a crate. */ + debugCrate = { packageId, target ? makeDefaultTarget stdenv.hostPlatform }: + assert (builtins.isString packageId); + let + debug = rec { + # The built tree as passed to buildRustCrate. + buildTree = buildRustCrateWithFeatures { + buildRustCrateForPkgsFunc = _: lib.id; + inherit packageId; + }; + sanitizedBuildTree = sanitizeForJson buildTree; + dependencyTree = sanitizeForJson + ( + buildRustCrateWithFeatures { + buildRustCrateForPkgsFunc = _: crate: { + "01_crateName" = crate.crateName or false; + "02_features" = crate.features or [ ]; + "03_dependencies" = crate.dependencies or [ ]; + }; + inherit packageId; + } + ); + mergedPackageFeatures = mergePackageFeatures { + features = rootFeatures; + inherit packageId target; + }; + diffedDefaultPackageFeatures = diffDefaultPackageFeatures { + inherit packageId target; + }; + }; + in + { internal = debug; }; + + /* Returns differences between cargo default features and crate2nix default + features. + + This is useful for verifying the feature resolution in crate2nix. + */ + diffDefaultPackageFeatures = + { crateConfigs ? crates + , packageId + , target + }: + assert (builtins.isAttrs crateConfigs); + let + prefixValues = prefix: lib.mapAttrs (n: v: { "${prefix}" = v; }); + mergedFeatures = + prefixValues + "crate2nix" + (mergePackageFeatures { inherit crateConfigs packageId target; features = [ "default" ]; }); + configs = prefixValues "cargo" crateConfigs; + combined = lib.foldAttrs (a: b: a // b) { } [ mergedFeatures configs ]; + onlyInCargo = + builtins.attrNames + (lib.filterAttrs (n: v: !(v ? "crate2nix") && (v ? "cargo")) combined); + onlyInCrate2Nix = + builtins.attrNames + (lib.filterAttrs (n: v: (v ? "crate2nix") && !(v ? "cargo")) combined); + differentFeatures = lib.filterAttrs + ( + n: v: + (v ? "crate2nix") + && (v ? "cargo") + && (v.crate2nix.features or [ ]) != (v."cargo".resolved_default_features or [ ]) + ) + combined; + in + builtins.toJSON { + inherit onlyInCargo onlyInCrate2Nix differentFeatures; + }; + + /* Returns an attrset mapping packageId to the list of enabled features. + + If multiple paths to a dependency enable different features, the + corresponding feature sets are merged. Features in rust are additive. + */ + mergePackageFeatures = + { crateConfigs ? crates + , packageId + , rootPackageId ? packageId + , features ? rootFeatures + , dependencyPath ? [ crates.${packageId}.crateName ] + , featuresByPackageId ? { } + , target + # Adds devDependencies to the crate with rootPackageId. + , runTests ? false + , ... + } @ args: + assert (builtins.isAttrs crateConfigs); + assert (builtins.isString packageId); + assert (builtins.isString rootPackageId); + assert (builtins.isList features); + assert (builtins.isList dependencyPath); + assert (builtins.isAttrs featuresByPackageId); + assert (builtins.isAttrs target); + assert (builtins.isBool runTests); + let + crateConfig = crateConfigs."${packageId}" or (builtins.throw "Package not found: ${packageId}"); + expandedFeatures = expandFeatures (crateConfig.features or { }) features; + enabledFeatures = enableFeatures (crateConfig.dependencies or [ ]) expandedFeatures; + depWithResolvedFeatures = dependency: + let + inherit (dependency) packageId; + features = dependencyFeatures enabledFeatures dependency; + in + { inherit packageId features; }; + resolveDependencies = cache: path: dependencies: + assert (builtins.isAttrs cache); + assert (builtins.isList dependencies); + let + enabledDependencies = filterEnabledDependencies { + inherit dependencies target; + features = enabledFeatures; + }; + directDependencies = map depWithResolvedFeatures enabledDependencies; + foldOverCache = op: lib.foldl op cache directDependencies; + in + foldOverCache + ( + cache: { packageId, features }: + let + cacheFeatures = cache.${packageId} or [ ]; + combinedFeatures = sortedUnique (cacheFeatures ++ features); + in + if cache ? ${packageId} && cache.${packageId} == combinedFeatures + then cache + else + mergePackageFeatures { + features = combinedFeatures; + featuresByPackageId = cache; + inherit crateConfigs packageId target runTests rootPackageId; + } + ); + cacheWithSelf = + let + cacheFeatures = featuresByPackageId.${packageId} or [ ]; + combinedFeatures = sortedUnique (cacheFeatures ++ enabledFeatures); + in + featuresByPackageId // { + "${packageId}" = combinedFeatures; + }; + cacheWithDependencies = + resolveDependencies cacheWithSelf "dep" + ( + crateConfig.dependencies or [ ] + ++ lib.optionals + (runTests && packageId == rootPackageId) + (crateConfig.devDependencies or [ ]) + ); + cacheWithAll = + resolveDependencies + cacheWithDependencies "build" + (crateConfig.buildDependencies or [ ]); + in + cacheWithAll; + + /* Returns the enabled dependencies given the enabled features. */ + filterEnabledDependencies = { dependencies, features, target }: + assert (builtins.isList dependencies); + assert (builtins.isList features); + assert (builtins.isAttrs target); + + lib.filter + ( + dep: + let + targetFunc = dep.target or (features: true); + in + targetFunc { inherit features target; } + && ( + !(dep.optional or false) + || builtins.any (doesFeatureEnableDependency dep) features + ) + ) + dependencies; + + /* Returns whether the given feature should enable the given dependency. */ + doesFeatureEnableDependency = dependency: feature: + let + name = dependency.rename or dependency.name; + prefix = "${name}/"; + len = builtins.stringLength prefix; + startsWithPrefix = builtins.substring 0 len feature == prefix; + in + feature == name || feature == "dep:" + name || startsWithPrefix; + + /* Returns the expanded features for the given inputFeatures by applying the + rules in featureMap. + + featureMap is an attribute set which maps feature names to lists of further + feature names to enable in case this feature is selected. + */ + expandFeatures = featureMap: inputFeatures: + assert (builtins.isAttrs featureMap); + assert (builtins.isList inputFeatures); + let + expandFeaturesNoCycle = oldSeen: inputFeatures: + if inputFeatures != [ ] + then + let + # The feature we're currently expanding. + feature = builtins.head inputFeatures; + # All the features we've seen/expanded so far, including the one + # we're currently processing. + seen = oldSeen // { ${feature} = 1; }; + # Expand the feature but be careful to not re-introduce a feature + # that we've already seen: this can easily cause a cycle, see issue + # #209. + enables = builtins.filter (f: !(seen ? "${f}")) (featureMap."${feature}" or [ ]); + in + [ feature ] ++ (expandFeaturesNoCycle seen (builtins.tail inputFeatures ++ enables)) + # No more features left, nothing to expand to. + else [ ]; + outFeatures = expandFeaturesNoCycle { } inputFeatures; + in + sortedUnique outFeatures; + + /* This function adds optional dependencies as features if they are enabled + indirectly by dependency features. This function mimics Cargo's behavior + described in a note at: + https://doc.rust-lang.org/nightly/cargo/reference/features.html#dependency-features + */ + enableFeatures = dependencies: features: + assert (builtins.isList features); + assert (builtins.isList dependencies); + let + additionalFeatures = lib.concatMap + ( + dependency: + assert (builtins.isAttrs dependency); + let + enabled = builtins.any (doesFeatureEnableDependency dependency) features; + in + if (dependency.optional or false) && enabled + then [ (dependency.rename or dependency.name) ] + else [ ] + ) + dependencies; + in + sortedUnique (features ++ additionalFeatures); + + /* + Returns the actual features for the given dependency. + + features: The features of the crate that refers this dependency. + */ + dependencyFeatures = features: dependency: + assert (builtins.isList features); + assert (builtins.isAttrs dependency); + let + defaultOrNil = + if dependency.usesDefaultFeatures or true + then [ "default" ] + else [ ]; + explicitFeatures = dependency.features or [ ]; + additionalDependencyFeatures = + let + name = dependency.rename or dependency.name; + stripPrefixMatch = prefix: s: + if lib.hasPrefix prefix s + then lib.removePrefix prefix s + else null; + extractFeature = feature: lib.findFirst + (f: f != null) + null + (map (prefix: stripPrefixMatch prefix feature) [ + (name + "/") + (name + "?/") + ]); + dependencyFeatures = lib.filter (f: f != null) (map extractFeature features); + in + dependencyFeatures; + in + defaultOrNil ++ explicitFeatures ++ additionalDependencyFeatures; + + /* Sorts and removes duplicates from a list of strings. */ + sortedUnique = features: + assert (builtins.isList features); + assert (builtins.all builtins.isString features); + let + outFeaturesSet = lib.foldl (set: feature: set // { "${feature}" = 1; }) { } features; + outFeaturesUnique = builtins.attrNames outFeaturesSet; + in + builtins.sort (a: b: a < b) outFeaturesUnique; + + deprecationWarning = message: value: + if strictDeprecation + then builtins.throw "strictDeprecation enabled, aborting: ${message}" + else builtins.trace message value; + + # + # crate2nix/default.nix (excerpt end) + # + }; +} + diff --git a/users/edef/fetchroots/Cargo.toml b/users/edef/fetchroots/Cargo.toml new file mode 100644 index 000000000000..a8c1437b1c18 --- /dev/null +++ b/users/edef/fetchroots/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "fetchroots" +version = "0.0.0" +edition = "2021" + +[workspace] +members = ["."] + +[dependencies] +anyhow = { version = "1.0.80", features = ["backtrace"] } +aws-config = "1.1.6" +aws-sdk-s3 = "1.16.0" +bytes = "1.5.0" +bytes-utils = "0.1.4" +bzip2 = "0.4.4" +chrono = "0.4.34" +futures = "0.3.30" +indicatif = "0.17.8" +nix-compat = { version = "0.1.0", path = "../../../tvix/nix-compat" } +polars = { version = "0.36.2", features = ["parquet"] } +rayon = "1.8.1" +tokio = { version = "1.36.0", features = ["full"] } +xz2 = "0.1.7" diff --git a/users/edef/fetchroots/README.md b/users/edef/fetchroots/README.md new file mode 100644 index 000000000000..f20cfbf28389 --- /dev/null +++ b/users/edef/fetchroots/README.md @@ -0,0 +1,36 @@ +# fetchroots + +> This tool is part of a suite of tools built to manage cache.nixos.org. + +This tool's purpose is to build an index of all the GC roots from the +channels.nixos.org releases. The result is then combined with other tools. + +It does this by: +1. Listing all the release files in the bucket. +2. Getting the data for each of the release. +3. Putting them in a local parquet file. + +## Getting started + +In order to run this, you'll need AWS SSO credentials from the NixOS Infra team. + +Get the creds from https://nixos.awsapps.com/start/ -> LBNixOS_Dev_PDX -> AWSReadOnlyAccess. + +Run `mg run`, you should see a progress bar. + +Congrats, you now have a `roots.parquet` file. You can now load it with python polars-rs or clickhouse. + +## `roots.parquet` file format + + * `key` (`String`): the release, eg `nixos/22.11-small/nixos-22.11.513.563dc6476b8` + * `timestamp` (`DateTime`): the timestamp of the GC roots file for this release + * `store_path_hash` (`List[Binary]`): hash part of the store paths rooted by this release + +## Development + +When the Cargo.lock changes, run `mg run //tools:crate2nix-generate`. + +To build the project, run `mg build`. + +To get a dev environment, run `nix-shell -p cargo`. + diff --git a/users/edef/fetchroots/default.nix b/users/edef/fetchroots/default.nix new file mode 100644 index 000000000000..2b655ee9c3e9 --- /dev/null +++ b/users/edef/fetchroots/default.nix @@ -0,0 +1,11 @@ +{ pkgs, depot, ... }: + +(pkgs.callPackage ./Cargo.nix { + defaultCrateOverrides = (depot.tvix.utils.defaultCrateOverridesForPkgs pkgs) // { + fetchroots = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + }; +}).rootCrate.build.overrideAttrs { + meta.ci.extraSteps.crate2nix = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; +} diff --git a/users/edef/fetchroots/src/main.rs b/users/edef/fetchroots/src/main.rs new file mode 100644 index 000000000000..842b719c2ac9 --- /dev/null +++ b/users/edef/fetchroots/src/main.rs @@ -0,0 +1,257 @@ +//! Fetch all[^1] GC roots from releases.nixos.org into a `roots.parquet` file. +//! +//! The resulting Parquet has three columns: +//! +//! * `key` (`String`): the release, eg `nixos/22.11-small/nixos-22.11.513.563dc6476b8` +//! * `timestamp` (`DateTime`): the timestamp of the GC roots file for this release +//! * `store_path_hash` (`List[Binary]`): hash part of the store paths rooted by this release +//! +//! [^1]: some roots are truly ancient, and aren't compatible with Nix 1.x + +use anyhow::Result; +use std::{ + collections::BTreeMap, + fs::File, + io::{BufRead, Read}, + sync::Arc, + time::SystemTime, +}; + +use aws_config::Region; +use aws_sdk_s3::operation::get_object::builders::GetObjectFluentBuilder; +use bytes::{Buf, Bytes}; +use bytes_utils::SegmentedBuf; +use chrono::{DateTime, Utc}; +use nix_compat::nixbase32; +use polars::prelude::*; +use tokio::{ + sync::Semaphore, + task::{block_in_place, JoinSet}, +}; + +#[derive(Debug)] +struct Meta { + format: Format, + e_tag: String, + last_modified: DateTime<Utc>, +} + +#[tokio::main] +async fn main() { + let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::v2023_11_09()) + .await + .into_builder() + .region(Region::from_static("eu-west-1")) + .build(); + + let s3 = aws_sdk_s3::Client::new(&sdk_config); + + let mut keys: BTreeMap<String, Meta> = { + let pages = s3 + .list_objects_v2() + .bucket("nix-releases") + .into_paginator() + .send() + .try_collect() + .await + .unwrap(); + + let objects = pages.into_iter().flat_map(|page| { + assert_eq!(page.prefix().unwrap_or_default(), ""); + assert!(page.common_prefixes.is_none()); + page.contents.unwrap_or_default() + }); + + let mut prev_key = String::new(); + objects + .filter_map(|obj| { + let key = obj.key().unwrap(); + + assert!(&*prev_key < key); + key.clone_into(&mut prev_key); + + let (key, tail) = key.rsplit_once('/')?; + // Our preference order happens to match lexicographical order, + // and listings are returned in lexicographical order. + let format = match tail { + "MANIFEST" => Format::Manifest, + "MANIFEST.bz2" => Format::ManifestBz, + "store-paths.xz" => Format::StorePathsXz, + _ => return None, + }; + + Some(( + key.to_owned(), + Meta { + format, + e_tag: obj.e_tag.unwrap(), + last_modified: SystemTime::try_from(obj.last_modified.unwrap()) + .unwrap() + .into(), + }, + )) + }) + .collect() + }; + + // These releases are so old they don't even use nixbase32 store paths. + for key in [ + "nix/nix-0.6", + "nix/nix-0.6.1", + "nix/nix-0.7", + "nix/nix-0.8", + "nixpkgs/nixpkgs-0.5", + "nixpkgs/nixpkgs-0.5.1", + "nixpkgs/nixpkgs-0.6", + "nixpkgs/nixpkgs-0.7", + "nixpkgs/nixpkgs-0.8", + "nixpkgs/nixpkgs-0.9", + "nixpkgs/nixpkgs-0.10", + "nixpkgs/nixpkgs-0.11", + ] { + assert!(keys.remove(key).is_some()); + } + + let mut js = JoinSet::new(); + let sem = Arc::new(Semaphore::new(16)); + + let bar = indicatif::ProgressBar::new(keys.len() as u64); + for (root, meta) in keys { + let sem = sem.clone(); + let s3 = s3.clone(); + + js.spawn(async move { + let _permit = sem.acquire().await.unwrap(); + + let body = get_object( + s3.get_object() + .bucket("nix-releases") + .key(format!("{root}/{}", meta.format.as_str())) + .if_match(meta.e_tag), + ) + .await + .unwrap() + .reader(); + + let ph_array = block_in_place(|| meta.format.to_ph_array(body).rechunk()); + df! { + "key" => [root], + "timestamp" => [meta.last_modified.naive_utc()], + "store_path_hash" => ph_array.into_series().implode().unwrap() + } + .unwrap() + }); + } + + let mut writer = ParquetWriter::new(File::create("roots.parquet").unwrap()) + .batched(&Schema::from_iter([ + Field::new("key", DataType::String), + Field::new( + "timestamp", + DataType::Datetime(TimeUnit::Milliseconds, None), + ), + Field::new( + "store_path_hash", + DataType::List(Box::new(DataType::Binary)), + ), + ])) + .unwrap(); + + while let Some(df) = js.join_next().await.transpose().unwrap() { + block_in_place(|| writer.write_batch(&df)).unwrap(); + bar.inc(1); + } + + writer.finish().unwrap(); +} + +#[derive(Debug)] +enum Format { + Manifest, + ManifestBz, + StorePathsXz, +} + +impl Format { + fn as_str(&self) -> &'static str { + match self { + Format::Manifest => "MANIFEST", + Format::ManifestBz => "MANIFEST.bz2", + Format::StorePathsXz => "store-paths.xz", + } + } + + fn to_ph_array(&self, mut body: impl BufRead) -> BinaryChunked { + match self { + Format::Manifest | Format::ManifestBz => { + let mut buf = String::new(); + match self { + Format::Manifest => { + body.read_to_string(&mut buf).unwrap(); + } + Format::ManifestBz => { + bzip2::bufread::BzDecoder::new(body) + .read_to_string(&mut buf) + .unwrap(); + } + _ => unreachable!(), + } + + let buf = buf + .strip_prefix("version {\n ManifestVersion: 3\n}\n") + .unwrap(); + + BinaryChunked::from_iter_values( + "store_path_hash", + buf.split_terminator("}\n").map(|chunk| -> [u8; 20] { + let chunk = chunk.strip_prefix("patch ").unwrap_or(chunk); + let line = chunk.strip_prefix("{\n StorePath: /nix/store/").unwrap(); + nixbase32::decode_fixed(&line[..32]).unwrap() + }), + ) + } + Format::StorePathsXz => { + let mut buf = String::new(); + xz2::bufread::XzDecoder::new(body) + .read_to_string(&mut buf) + .unwrap(); + + BinaryChunked::from_iter_values( + "store_path_hash", + buf.split_terminator('\n').map(|line| -> [u8; 20] { + let line = line.strip_prefix("/nix/store/").unwrap(); + nixbase32::decode_fixed(&line[..32]).unwrap() + }), + ) + } + } + } +} + +async fn get_object(request: GetObjectFluentBuilder) -> Result<SegmentedBuf<Bytes>> { + // if we don't constrain the ETag, we might experience read skew + assert!(request.get_if_match().is_some(), "if_match must be set"); + + let mut buf: SegmentedBuf<Bytes> = SegmentedBuf::new(); + let mut resp = request.clone().send().await?; + let content_length: usize = resp.content_length.unwrap().try_into().unwrap(); + + loop { + while let Ok(Some(chunk)) = resp.body.try_next().await { + buf.push(chunk); + } + + if buf.remaining() >= content_length { + assert_eq!(buf.remaining(), content_length, "got excess bytes"); + break Ok(buf); + } + + resp = request + .clone() + .range(format!("bytes={}-", buf.remaining())) + .send() + .await?; + + assert_ne!(resp.content_range, None); + } +} diff --git a/tvix/tools/narinfo2parquet/Cargo.lock b/users/edef/narinfo2parquet/Cargo.lock index e59f70732daf..97a7ea712433 100644 --- a/tvix/tools/narinfo2parquet/Cargo.lock +++ b/users/edef/narinfo2parquet/Cargo.lock @@ -128,7 +128,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] @@ -139,7 +139,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] @@ -198,9 +198,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -234,9 +234,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "regex-automata", @@ -266,14 +266,14 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" @@ -398,16 +398,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -421,14 +420,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "der" @@ -468,9 +467,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", @@ -487,6 +486,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] +name = "enum-primitive-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c" +dependencies = [ + "num-traits", + "quote", + "syn 2.0.79", +] + +[[package]] name = "enum_dispatch" version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -495,7 +505,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] @@ -511,7 +521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -616,7 +626,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] @@ -703,9 +713,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "home" @@ -713,7 +723,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -806,6 +816,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] +name = "libmimalloc-sys" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] + +[[package]] name = "linux-raw-sys" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -839,9 +859,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -862,6 +882,15 @@ dependencies = [ ] [[package]] +name = "mimalloc" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -878,13 +907,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.9" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -925,17 +955,34 @@ dependencies = [ name = "nix-compat" version = "0.1.0" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "bstr", + "bytes", "data-encoding", "ed25519", "ed25519-dalek", + "enum-primitive-derive", "glob", + "mimalloc", + "nix-compat-derive", "nom", + "num-traits", + "pin-project-lite", "serde", "serde_json", "sha2", "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "nix-compat-derive" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", ] [[package]] @@ -968,25 +1015,15 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] [[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] name = "object" version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1019,9 +1056,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1055,12 +1092,6 @@ dependencies = [ ] [[package]] -name = "platforms" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" - -[[package]] name = "polars" version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1128,7 +1159,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0f5efe734b6cbe5f97ea769be8360df5324fade396f1f3f5ad7fe9360ca4a23" dependencies = [ "ahash", - "bitflags 2.4.1", + "bitflags 2.6.0", "bytemuck", "chrono", "either", @@ -1198,7 +1229,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d7105b40905bb38e8fc4a7fd736594b7491baa12fad3ac492969ca221a1b5d5" dependencies = [ "ahash", - "bitflags 2.4.1", + "bitflags 2.6.0", "glob", "once_cell", "polars-arrow", @@ -1387,18 +1418,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1522,11 +1553,11 @@ version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1561,22 +1592,22 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.192" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] @@ -1649,7 +1680,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1708,7 +1739,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] @@ -1730,9 +1761,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -1769,7 +1800,7 @@ dependencies = [ "fastrand", "redox_syscall", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1785,38 +1816,49 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] name = "tokio" -version = "1.33.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", "socket2", - "windows-sys", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", ] [[package]] @@ -1833,6 +1875,37 @@ dependencies = [ ] [[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1877,7 +1950,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", "wasm-bindgen-shared", ] @@ -1899,7 +1972,7 @@ checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1970,6 +2043,15 @@ dependencies = [ ] [[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2091,22 +2173,22 @@ checksum = "9828b178da53440fa9c766a3d2f73f7cf5d0ac1fe3980c1e5018d899fd19e07b" [[package]] name = "zerocopy" -version = "0.7.25" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.25" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.79", ] [[package]] diff --git a/tvix/tools/narinfo2parquet/Cargo.nix b/users/edef/narinfo2parquet/Cargo.nix index 27a5d684b66e..fb8b59b2dea2 100644 --- a/tvix/tools/narinfo2parquet/Cargo.nix +++ b/users/edef/narinfo2parquet/Cargo.nix @@ -1,4 +1,4 @@ -# This file was @generated by crate2nix 0.13.0 with the command: +# This file was @generated by crate2nix 0.14.1 with the command: # "generate" "--all-features" # See https://github.com/kolloch/crate2nix for more info. @@ -13,6 +13,8 @@ , rootFeatures ? [ "default" ] # If true, throw errors instead of issueing deprecation warnings. , strictDeprecation ? false + # Elements to add to the `-C target-feature=` argument passed to `rustc` + # (separated by `,`, prefixed with `+`). # Used for conditional compilation based on CPU feature detection. , targetFeatures ? [ ] # Whether to perform release builds: longer compile times, faster binaries. @@ -205,6 +207,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1cy6r2sfv5y5cigv86vms7n5nlwhx1rbyxwcraqnmm1rxiib2yyc"; + libName = "alloc_no_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -216,6 +219,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1kkfbld20ab4165p29v172h8g0wvq8i06z8vnng14whw0isq5ywl"; + libName = "alloc_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -232,6 +236,7 @@ rec { version = "0.2.16"; edition = "2018"; sha256 = "1iayppgq4wqbfbfcqmsbwgamj0s65012sskfvyx07pxavk3gyhh9"; + libName = "allocator_api2"; authors = [ "Zakarum <zaq.dev@icloud.com>" ]; @@ -247,6 +252,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9"; + libName = "android_tzdata"; authors = [ "RumovZ" ]; @@ -318,6 +324,7 @@ rec { version = "0.2.0"; edition = "2021"; sha256 = "0xpbqf7qkvzplpjd7f0wbcf2n1v9vygdccwxkd1amxp4il0hlzdz"; + libName = "array_init_cursor"; }; "arrow-format" = rec { @@ -325,6 +332,7 @@ rec { version = "0.8.1"; edition = "2018"; sha256 = "1irj67p6c224dzw86jr7j3z9r5zfid52gy6ml8rdqk4r2si4x207"; + libName = "arrow_format"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" ]; @@ -360,6 +368,7 @@ rec { version = "0.3.5"; edition = "2018"; sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -385,6 +394,7 @@ rec { edition = "2018"; sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -399,7 +409,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" "visit-mut" ]; } ]; @@ -411,6 +421,7 @@ rec { edition = "2021"; sha256 = "1ydhbsqjqqa6bxbv0kgys2wq2vi3jpwjy57dk162ajwppgqkfrd6"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -425,7 +436,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" "visit-mut" ]; } ]; @@ -580,11 +591,11 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "bitflags 2.4.1" = rec { + "bitflags 2.6.0" = rec { crateName = "bitflags"; - version = "2.4.1"; + version = "2.6.0"; edition = "2021"; - sha256 = "01ryy3kd671b0ll4bhdvhsz67vwz1lz53fz504injrd7wpv64xrj"; + sha256 = "1pkidwzn3hnxlsl8zizh0bncgbjnw7c41cx7bby26ncbzmiznj5h"; authors = [ "The Rust Project Developers" ]; @@ -603,6 +614,7 @@ rec { version = "0.10.4"; edition = "2018"; sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -658,6 +670,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "0kyyh9701dwqzwvn2frff4ww0zibikqd1s1xvl7n1pfpc3z4lbjf"; + libName = "brotli_decompressor"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" "The Brotli Authors" @@ -683,9 +696,9 @@ rec { }; "bstr" = rec { crateName = "bstr"; - version = "1.7.0"; + version = "1.10.0"; edition = "2021"; - sha256 = "06gh43qpgdqfsfpykw9y4708y0qclajwc2bbsymkv3yk5pxxg6n7"; + sha256 = "036wwrchd5gq3q4k6w1j2bfl2bk2ff8c0dsa9y7w7aw7nf7knwj0"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -773,16 +786,16 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; } ]; }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.7.2"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "1wzs7l57iwqmrszdpr2mmqf1b1hgvpxafc30imxhnry0zfl9m3a2"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -826,6 +839,7 @@ rec { version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -890,6 +904,7 @@ rec { version = "0.9.5"; edition = "2021"; sha256 = "0vxb4d25mgk8y0phay7j078limx2553716ixsr1x5605k31j5h98"; + libName = "const_oid"; authors = [ "RustCrypto Developers" ]; @@ -902,6 +917,7 @@ rec { version = "0.8.4"; edition = "2015"; sha256 = "1yhf471qj6snnm2mcswai47vsbc9w30y4abmdp4crb4av87sb5p4"; + libName = "core_foundation_sys"; authors = [ "The Servo Project Developers" ]; @@ -919,7 +935,7 @@ rec { { name = "libc"; packageId = "libc"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-linux-android"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-linux-android"); } { name = "libc"; @@ -964,6 +980,7 @@ rec { version = "0.5.8"; edition = "2018"; sha256 = "004jz4wxp9k26z657i7rsh9s7586dklx2c5aqf1n3w1dgzvjng53"; + libName = "crossbeam_channel"; dependencies = [ { name = "cfg-if"; @@ -988,6 +1005,7 @@ rec { version = "0.8.3"; edition = "2018"; sha256 = "1vqczbcild7nczh5z116w8w46z991kpjyw7qxkf24c14apwdcvyf"; + libName = "crossbeam_deque"; dependencies = [ { name = "cfg-if"; @@ -1019,6 +1037,7 @@ rec { version = "0.9.15"; edition = "2018"; sha256 = "1ixwc3cq816wb8rlh3ix4jnybqbyyq4l61nwlx0mfm3ck0s148df"; + libName = "crossbeam_epoch"; dependencies = [ { name = "cfg-if"; @@ -1059,6 +1078,7 @@ rec { version = "0.3.8"; edition = "2018"; sha256 = "1p9s6n4ckwdgxkb7a8ay9zjzmgc8ppfbxix2vr07rwskibmb7kyi"; + libName = "crossbeam_queue"; dependencies = [ { name = "cfg-if"; @@ -1082,6 +1102,7 @@ rec { version = "0.8.16"; edition = "2018"; sha256 = "153j0gikblz7n7qdvdi8pslhi008s1yp9cmny6vw07ad7pbb48js"; + libName = "crossbeam_utils"; dependencies = [ { name = "cfg-if"; @@ -1099,6 +1120,7 @@ rec { version = "0.1.6"; edition = "2018"; sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; authors = [ "RustCrypto Developers" ]; @@ -1121,9 +1143,10 @@ rec { }; "curve25519-dalek" = rec { crateName = "curve25519-dalek"; - version = "4.1.1"; + version = "4.1.3"; edition = "2021"; - sha256 = "0p7ns5917k6369gajrsbfj24llc5zfm635yh3abla7sb5rm8r6z8"; + sha256 = "1gmjb9dsknrr8lypmhkyjd67p1arb8mbfamlwxm7vph38my8pywp"; + libName = "curve25519_dalek"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -1169,10 +1192,6 @@ rec { ]; buildDependencies = [ { - name = "platforms"; - packageId = "platforms"; - } - { name = "rustc_version"; packageId = "rustc_version"; } @@ -1196,6 +1215,7 @@ rec { edition = "2021"; sha256 = "1cry71xxrr0mcy5my3fb502cwfxy6822k4pm19cwrilrg7hq4s7l"; procMacro = true; + libName = "curve25519_dalek_derive"; dependencies = [ { name = "proc-macro2"; @@ -1207,7 +1227,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -1215,9 +1235,10 @@ rec { }; "data-encoding" = rec { crateName = "data-encoding"; - version = "2.4.0"; + version = "2.6.0"; edition = "2018"; - sha256 = "023k3dk8422jgbj7k72g63x51h1mhv91dhw1j4h205vzh6fnrrn2"; + sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -1301,6 +1322,7 @@ rec { version = "1.0.16"; edition = "2018"; sha256 = "0pa9kas6a241pbx0q82ipwi4f7m7wwyzkkc725caky24gl4j4nsl"; + libName = "dyn_clone"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -1340,9 +1362,10 @@ rec { }; "ed25519-dalek" = rec { crateName = "ed25519-dalek"; - version = "2.1.0"; + version = "2.1.1"; edition = "2021"; - sha256 = "1h13qm789m9gdjl6jazss80hqi8ll37m0afwcnw23zcbqjp8wqhz"; + sha256 = "0w88cafwglg9hjizldbmlza0ns3hls81zk1bcih3m5m3h67algaa"; + libName = "ed25519_dalek"; authors = [ "isis lovecruft <isis@patternsinthevoid.net>" "Tony Arcieri <bascule@gmail.com>" @@ -1429,6 +1452,33 @@ rec { }; resolvedDefaultFeatures = [ "default" "use_std" ]; }; + "enum-primitive-derive" = rec { + crateName = "enum-primitive-derive"; + version = "0.3.0"; + edition = "2018"; + sha256 = "0k6wcf58h5kh64yq5nfq71va53kaya0kzxwsjwbgwm2n2zd9axxs"; + procMacro = true; + libName = "enum_primitive_derive"; + authors = [ + "Doug Goldstein <cardoe@cardoe.com>" + ]; + dependencies = [ + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + } + ]; + + }; "enum_dispatch" = rec { crateName = "enum_dispatch"; version = "0.3.12"; @@ -1453,7 +1503,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -1495,7 +1545,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.48.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_System_Diagnostics_Debug" ]; } @@ -1525,6 +1575,7 @@ rec { version = "0.1.9"; edition = "2015"; sha256 = "0nj6j26p71bjy8h42x6jahx1hn0ng6mc2miwpgwnp8vnwqf4jq3k"; + libName = "fallible_streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -1535,6 +1586,7 @@ rec { version = "0.2.0"; edition = "2018"; sha256 = "0g7kfll3xyh99kc7r352lhljnwvgayxxa6saifb6725inikmyxlm"; + libName = "fast_float"; authors = [ "Ivan Smirnov <i.s.smirnov@gmail.com>" ]; @@ -1564,6 +1616,7 @@ rec { version = "0.2.5"; edition = "2018"; sha256 = "1dxn0g50pv0ppal779vi7k40fr55pbhkyv4in7i13pgl4sn3wmr7"; + libName = "fiat_crypto"; authors = [ "Fiat Crypto library authors <jgross@mit.edu>" ]; @@ -1693,6 +1746,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1jxsifvrbqzdadk0svbax71cba5d3qg3wgjq8i160mxmd1kdckgz"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -1720,6 +1774,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1308bpj0g36nhx2y6bl4mm6f1gnh9xyvvw2q2wpdgnb6dv3247gb"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -1732,6 +1787,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1g4pjni0sw28djx6mlcfz584abm2lpifz86cmng0kkxh7mlvhkqg"; + libName = "futures_executor"; dependencies = [ { name = "futures-core"; @@ -1762,6 +1818,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1ajsljgny3zfxwahba9byjzclrgvm1ypakca8z854k2w7cb4mwwb"; + libName = "futures_io"; features = { "default" = [ "std" ]; }; @@ -1773,6 +1830,7 @@ rec { edition = "2018"; sha256 = "1nwd18i8kvpkdfwm045hddjli0n96zi7pn6f99zi9c74j7ym7cak"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -1784,7 +1842,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -1795,6 +1853,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "05q8jykqddxzp8nwf00wjk5m5mqi546d7i8hsxma7hiqxrw36vg3"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1806,6 +1865,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1qmsss8rb5ppql4qvd4r70h9gpfcpd0bg2b3qilxrnhdkc397lgg"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1817,6 +1877,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "0141rkqh0psj4h8x8lgsl1p29dhqr7z2wcixkcbs60z74kb2d5d1"; + libName = "futures_util"; dependencies = [ { name = "futures-channel"; @@ -2067,9 +2128,10 @@ rec { }; "hermit-abi" = rec { crateName = "hermit-abi"; - version = "0.3.3"; + version = "0.3.9"; edition = "2021"; - sha256 = "1dyc8qsjh876n74a3rcz8h43s27nj1sypdhsn2ms61bd3b47wzyp"; + sha256 = "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -2092,7 +2154,7 @@ rec { dependencies = [ { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.48.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_UI_Shell" ]; } @@ -2104,6 +2166,7 @@ rec { version = "0.1.58"; edition = "2018"; sha256 = "081vcr8z8ddhl5r1ywif6grnswk01b2ac4nks2bhn8zzdimvh9l3"; + libName = "iana_time_zone"; authors = [ "Andrew Straw <strawman@astraw.com>" "René Kijewski <rene.kijewski@fu-berlin.de>" @@ -2149,6 +2212,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k"; + libName = "iana_time_zone_haiku"; authors = [ "René Kijewski <crates.io@k6i.de>" ]; @@ -2206,6 +2270,7 @@ rec { edition = "2018"; links = "jemalloc"; sha256 = "1wpbpwhfs6wd484cdfpl0zdf441ann9wj0fypy67i8ffw531jv5c"; + libName = "jemalloc_sys"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Gonzalo Brito Gadeschi <gonzalobg88@gmail.com>" @@ -2288,6 +2353,7 @@ rec { version = "0.3.65"; edition = "2018"; sha256 = "1s1gaxgzpqfyygc7f2pwp9y128rh5f8zvsc4nm5yazgna9cw7h2l"; + libName = "js_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -2329,11 +2395,39 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; + "libmimalloc-sys" = rec { + crateName = "libmimalloc-sys"; + version = "0.1.39"; + edition = "2018"; + links = "mimalloc"; + sha256 = "0i3b0dzz7cp0ik7ys66q92r16va78gwlbrnxhj5fnkdxsc8niai3"; + libName = "libmimalloc_sys"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cty" = [ "dep:cty" ]; + "extended" = [ "cty" ]; + }; + }; "linux-raw-sys" = rec { crateName = "linux-raw-sys"; version = "0.4.10"; edition = "2021"; sha256 = "0gz0671d4hgrdngrryaajxl962ny4g40pykg0vq0pr32q3l7j96s"; + libName = "linux_raw_sys"; authors = [ "Dan Gohman <dev@sunfishcode.online>" ]; @@ -2393,6 +2487,7 @@ rec { edition = "2015"; links = "lz4"; sha256 = "0059ik4xlvnss5qfh6l691psk4g3350ljxaykzv10yr0gqqppljp"; + libName = "lz4_sys"; authors = [ "Jens Heyens <jens.heyens@ewetel.net>" "Artem V. Navrotskiy <bozaro@buzzsoft.ru>" @@ -2414,9 +2509,9 @@ rec { }; "memchr" = rec { crateName = "memchr"; - version = "2.6.4"; + version = "2.7.4"; edition = "2021"; - sha256 = "0rq1ka8790ns41j147npvxcqcl2anxyngsdimy85ag2api0fwrgn"; + sha256 = "18z32bhxrax0fnjikv475z7ii718hq457qwmaryixfxsl2qrmjkq"; authors = [ "Andrew Gallant <jamslam@gmail.com>" "bluss" @@ -2469,11 +2564,40 @@ rec { features = { }; resolvedDefaultFeatures = [ "default" ]; }; + "mimalloc" = rec { + crateName = "mimalloc"; + version = "0.1.43"; + edition = "2018"; + sha256 = "0csnyrxc16i592gm5ffham07jyj2w98qsh9jyy1rv59lmr8474b8"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + "Vincent Rouillé <vincent@speedy37.fr>" + "Thom Chiovoloni <chiovolonit@gmail.com>" + ]; + dependencies = [ + { + name = "libmimalloc-sys"; + packageId = "libmimalloc-sys"; + usesDefaultFeatures = false; + } + ]; + features = { + "debug" = [ "libmimalloc-sys/debug" ]; + "debug_in_debug" = [ "libmimalloc-sys/debug_in_debug" ]; + "extended" = [ "libmimalloc-sys/extended" ]; + "local_dynamic_tls" = [ "libmimalloc-sys/local_dynamic_tls" ]; + "no_thp" = [ "libmimalloc-sys/no_thp" ]; + "override" = [ "libmimalloc-sys/override" ]; + "secure" = [ "libmimalloc-sys/secure" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; "minimal-lexical" = rec { crateName = "minimal-lexical"; version = "0.2.1"; edition = "2018"; sha256 = "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8"; + libName = "minimal_lexical"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2511,9 +2635,9 @@ rec { }; "mio" = rec { crateName = "mio"; - version = "0.8.9"; - edition = "2018"; - sha256 = "1l23hg513c23nhcdzvk25caaj28mic6qgqadbn8axgj6bqf2ikix"; + version = "1.0.2"; + edition = "2021"; + sha256 = "1v1cnnn44awxbcfm4zlavwgkvbyg7gp5zzjm8mqf1apkrwflvq40"; authors = [ "Carl Lerche <me@carllerche.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -2521,6 +2645,12 @@ rec { ]; dependencies = [ { + name = "hermit-abi"; + packageId = "hermit-abi"; + rename = "libc"; + target = { target, features }: ("hermit" == target."os" or null); + } + { name = "libc"; packageId = "libc"; target = { target, features }: ("wasi" == target."os" or null); @@ -2537,9 +2667,9 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); - features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; + features = [ "Wdk_Foundation" "Wdk_Storage_FileSystem" "Wdk_System_IO" "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; } ]; features = { @@ -2580,6 +2710,7 @@ rec { edition = "2021"; sha256 = "1j1avbxw7jscyi7dmnywhlwbiny1fvg1vpp9fy4dc1pd022kva16"; procMacro = true; + libName = "multiversion_macros"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -2618,12 +2749,7 @@ rec { requiredFeatures = [ ]; } ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./.; } - else ./.; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./.; }; dependencies = [ { name = "anyhow"; @@ -2660,16 +2786,12 @@ rec { version = "0.1.0"; edition = "2021"; crateBin = [ ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ../../nix-compat; } - else ../../nix-compat; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat; }; + libName = "nix_compat"; dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.1"; + packageId = "bitflags 2.6.0"; } { name = "bstr"; @@ -2677,6 +2799,11 @@ rec { features = [ "alloc" "unicode" "serde" ]; } { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { name = "data-encoding"; packageId = "data-encoding"; } @@ -2689,14 +2816,36 @@ rec { packageId = "ed25519-dalek"; } { + name = "enum-primitive-derive"; + packageId = "enum-primitive-derive"; + } + { name = "glob"; packageId = "glob"; } { + name = "mimalloc"; + packageId = "mimalloc"; + } + { + name = "nix-compat-derive"; + packageId = "nix-compat-derive"; + optional = true; + } + { name = "nom"; packageId = "nom"; } { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + optional = true; + } + { name = "serde"; packageId = "serde"; features = [ "derive" ]; @@ -2713,17 +2862,63 @@ rec { name = "thiserror"; packageId = "thiserror"; } + { + name = "tokio"; + packageId = "tokio"; + optional = true; + features = [ "io-util" "macros" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } ]; devDependencies = [ { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "serde_json"; packageId = "serde_json"; } ]; features = { - "async" = [ "futures-util" ]; - "futures-util" = [ "dep:futures-util" ]; + "async" = [ "tokio" ]; + "bytes" = [ "dep:bytes" ]; + "default" = [ "async" "wire" "nix-compat-derive" ]; + "nix-compat-derive" = [ "dep:nix-compat-derive" ]; + "pin-project-lite" = [ "dep:pin-project-lite" ]; + "tokio" = [ "dep:tokio" ]; + "wire" = [ "tokio" "pin-project-lite" "bytes" ]; }; + resolvedDefaultFeatures = [ "async" "bytes" "default" "nix-compat-derive" "pin-project-lite" "tokio" "wire" ]; + }; + "nix-compat-derive" = rec { + crateName = "nix-compat-derive"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat-derive; }; + procMacro = true; + libName = "nix_compat_derive"; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + features = [ "proc-macro" ]; + } + { + name = "quote"; + packageId = "quote"; + features = [ "proc-macro" ]; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" "extra-traits" ]; + } + ]; + }; "nom" = rec { crateName = "nom"; @@ -2792,9 +2987,10 @@ rec { }; "num-traits" = rec { crateName = "num-traits"; - version = "0.2.17"; - edition = "2018"; - sha256 = "0z16bi5zwgfysz6765v3rd6whfbjpihx3mhsn4dg8dzj2c221qrr"; + version = "0.2.19"; + edition = "2021"; + sha256 = "0h984rhdkkqd4ny9cif7y2azl3xdfb7768hb9irhpsch4q3gq787"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -2817,28 +3013,6 @@ rec { }; resolvedDefaultFeatures = [ "default" "libm" "std" ]; }; - "num_cpus" = rec { - crateName = "num_cpus"; - version = "1.16.0"; - edition = "2015"; - sha256 = "0hra6ihpnh06dvfvz9ipscys0xfqa9ca9hzp384d5m02ssvgqqa1"; - authors = [ - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "hermit-abi"; - packageId = "hermit-abi"; - target = { target, features }: ("hermit" == target."os" or null); - } - { - name = "libc"; - packageId = "libc"; - target = { target, features }: (!(target."windows" or false)); - } - ]; - - }; "object" = rec { crateName = "object"; version = "0.32.1"; @@ -2894,6 +3068,7 @@ rec { version = "0.2.4"; edition = "2021"; sha256 = "07wf6wf4jrxlq5p3xldxsnabp7jl06my2qp7kiwy9m3x2r5wac8i"; + libName = "parquet_format_safe"; authors = [ "Apache Thrift contributors <dev@thrift.apache.org>" "Jorge Leitao <jorgecarleitao@gmail.com>" @@ -2923,6 +3098,7 @@ rec { version = "2.3.0"; edition = "2018"; sha256 = "152slflmparkh27hprw62sph8rv77wckzhwl2dhqk6bf563lfalv"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -2934,9 +3110,10 @@ rec { }; "pin-project-lite" = rec { crateName = "pin-project-lite"; - version = "0.2.13"; + version = "0.2.14"; edition = "2018"; - sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + sha256 = "00nx3f04agwjlsmd3mc5rx5haibj2v8q9b52b0kwn63wcv4nz9mx"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -2944,6 +3121,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -2988,6 +3166,7 @@ rec { version = "0.3.27"; edition = "2015"; sha256 = "0r39ryh1magcq4cz5g9x88jllsnxnhcqr753islvyk4jp9h2h1r6"; + libName = "pkg_config"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -3009,21 +3188,6 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "platforms" = rec { - crateName = "platforms"; - version = "3.2.0"; - edition = "2018"; - sha256 = "1c6bzwn877aqdbbmyqsl753ycbciwvbdh4lpzijb8vrfb4zsprhl"; - authors = [ - "Tony Arcieri <bascule@gmail.com>" - "Sergey \"Shnatsel\" Davidoff <shnatsel@gmail.com>" - ]; - features = { - "default" = [ "std" ]; - "serde" = [ "dep:serde" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "polars" = rec { crateName = "polars"; version = "0.36.2"; @@ -3224,6 +3388,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "0vxql6amvwyp6qj0w87vm21y33qa0i61pshs4ry7ixwgd4ps0s6f"; + libName = "polars_arrow"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -3285,7 +3450,7 @@ rec { { name = "getrandom"; packageId = "getrandom"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "wasm32-unknown-unknown"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "wasm32-unknown-unknown"); features = [ "js" ]; } { @@ -3402,6 +3567,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1pa4l1w41gdzdff81ih1z05z3gz568k81i6flibbca8v2igvqkxi"; + libName = "polars_compute"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3441,6 +3607,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "08sar9h97znpb8ziyvrrvvx28lyzc21vwsd7gvwybjxn6kkyzxfh"; + libName = "polars_core"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3451,7 +3618,7 @@ rec { } { name = "bitflags"; - packageId = "bitflags 2.4.1"; + packageId = "bitflags 2.6.0"; } { name = "bytemuck"; @@ -3595,6 +3762,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "11m80a899kp45b3dz9jbvrn5001hw8izbdp7d2czrswrixwdx5k3"; + libName = "polars_error"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3631,6 +3799,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1smamd34ghlxyxdd4aqdplk7k8xm1l626brmzlc4fvwlx3pmh13x"; + libName = "polars_io"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3789,6 +3958,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1mdml4hs574njb23mb9gl6x92x2bb4vdfzsazkl3ifq516s0awcx"; + libName = "polars_lazy"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3799,7 +3969,7 @@ rec { } { name = "bitflags"; - packageId = "bitflags 2.4.1"; + packageId = "bitflags 2.6.0"; } { name = "glob"; @@ -3983,6 +4153,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "13m7dh4vpdmcah04a7kql933l7y7045f0hybbmgff4dbav2ay29f"; + libName = "polars_ops"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4134,6 +4305,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "0gay037sw5hcg2q93pxcfh7krcchl1px8g838d8vhjpnn5klv8kv"; + libName = "polars_parquet"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -4254,6 +4426,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "00217q51mnq7i57k3sax293xnwghm5hridbpgl11fffcfg8fmdyr"; + libName = "polars_pipe"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4367,6 +4540,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1l5ca38v7ksq4595wdr6wsd74pdgszwivq9y8wfc6l6h4ib1fjiq"; + libName = "polars_plan"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4555,6 +4729,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "0by7x6jlj5dwr3f1gj49v8w65l3kpqhwhzb9qzlv6gdqrdx2ycij"; + libName = "polars_row"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4584,6 +4759,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1dcmm993gycw75a6c5hxcr6h2cy6fa2r3hsbx19h9zgxvxnlq2wz"; + libName = "polars_sql"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4648,6 +4824,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1l24fmpv5v1qshxfd4592z8x6bnjlwy4njhf9rcbdlbbr6gn9qny"; + libName = "polars_time"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4726,6 +4903,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1nmvfqwyzbaxcw457amspz479y5vcnpalq043awxfixdfx5clx5i"; + libName = "polars_utils"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4793,6 +4971,7 @@ rec { version = "0.2.17"; edition = "2018"; sha256 = "1pp6g52aw970adv3x2310n7glqnji96z0a9wiamzw89ibf0ayh2v"; + libName = "ppv_lite86"; authors = [ "The CryptoCorrosion Contributors" ]; @@ -4803,9 +4982,10 @@ rec { }; "proc-macro2" = rec { crateName = "proc-macro2"; - version = "1.0.69"; + version = "1.0.87"; edition = "2021"; - sha256 = "1nljgyllbm3yr3pa081bf83gxh6l4zvjqzaldw7v4mj9xfgihk0k"; + sha256 = "16mifsq1nqzk81qm82aszib44jsd23gpqic5z4kbmzpnvjhdmr5k"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -4823,9 +5003,9 @@ rec { }; "quote" = rec { crateName = "quote"; - version = "1.0.33"; + version = "1.0.37"; edition = "2018"; - sha256 = "1biw54hbbr12wdwjac55z1m2x2rylciw83qnjn564a3096jgqrsj"; + sha256 = "1brklraw2g34bxy9y4q1nbrccn7bv36ylihv12c9vlcii55x7fdm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5007,6 +5187,7 @@ rec { edition = "2021"; links = "rayon-core"; sha256 = "1vaq0q71yfvcwlmia0iqf6ixj2fibjcf2xjy92n1m1izv1mgpqsw"; + libName = "rayon_core"; authors = [ "Niko Matsakis <niko@alum.mit.edu>" "Josh Stone <cuviper@gmail.com>" @@ -5104,6 +5285,7 @@ rec { version = "0.4.3"; edition = "2021"; sha256 = "0gs8q9yhd3kcg4pr00ag4viqxnh5l7jpyb9fsfr8hzh451w4r02z"; + libName = "regex_automata"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -5164,6 +5346,7 @@ rec { version = "0.8.2"; edition = "2021"; sha256 = "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360"; + libName = "regex_syntax"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -5180,6 +5363,7 @@ rec { version = "0.1.23"; edition = "2015"; sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -5218,7 +5402,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.1"; + packageId = "bitflags 2.6.0"; usesDefaultFeatures = false; } { @@ -5274,7 +5458,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.48.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_NetworkManagement_IpHelper" "Win32_System_Threading" ]; } @@ -5371,6 +5555,7 @@ rec { edition = "2018"; sha256 = "1d50kbaslrrd0374ivx15jg57f03y5xzil1wd2ajlvajzlkbzw53"; procMacro = true; + libName = "seq_macro"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5378,9 +5563,9 @@ rec { }; "serde" = rec { crateName = "serde"; - version = "1.0.192"; + version = "1.0.210"; edition = "2018"; - sha256 = "00ghhaabyrnr2cn504lckyqzh3fwr8k7pxnhhardr1djhj2a18mw"; + sha256 = "0flc0z8wgax1k4j5bf2zyq48bgzyv425jkd5w0i6wbh7f8j5kqy8"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -5412,9 +5597,9 @@ rec { }; "serde_derive" = rec { crateName = "serde_derive"; - version = "1.0.192"; + version = "1.0.210"; edition = "2015"; - sha256 = "1hgvm47ffd748sx22z1da7mgcfjmpr60gqzkff0a9yn9przj1iyn"; + sha256 = "07yzy4wafk79ps0hmbqmsqh5xjna4pm4q57wc847bb8gl3nh4f94"; procMacro = true; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" @@ -5424,14 +5609,20 @@ rec { { name = "proc-macro2"; packageId = "proc-macro2"; + usesDefaultFeatures = false; + features = [ "proc-macro" ]; } { name = "quote"; packageId = "quote"; + usesDefaultFeatures = false; + features = [ "proc-macro" ]; } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "clone-impls" "derive" "parsing" "printing" "proc-macro" ]; } ]; features = { }; @@ -5634,7 +5825,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.48.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_System_IO" "Win32_System_Threading" "Win32_System_WindowsProgramming" ]; } @@ -5714,6 +5905,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "1wscqj3s30qknda778wf7z99mknk65p0h9hhs658l4pvkfqw6v5z"; + libName = "streaming_decompression"; dependencies = [ { name = "fallible-streaming-iterator"; @@ -5727,6 +5919,7 @@ rec { version = "0.1.9"; edition = "2021"; sha256 = "0845zdv8qb7zwqzglpqc0830i43xh3fb6vqms155wz85qfvk28ib"; + libName = "streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -5772,7 +5965,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "parsing" "extra-traits" ]; } ]; @@ -5825,11 +6018,11 @@ rec { }; resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit-mut" ]; }; - "syn 2.0.39" = rec { + "syn 2.0.79" = rec { crateName = "syn"; - version = "2.0.39"; + version = "2.0.79"; edition = "2021"; - sha256 = "0ymyhxnk1yi4pzf72qk3lrdm9lgjwcrcwci0hhz5vx7wya88prr3"; + sha256 = "147mk4sgigmvsb9l8qzj199ygf0fgb0bphwdsghn8205pz82q4w9"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5852,12 +6045,11 @@ rec { ]; features = { "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; - "printing" = [ "quote" ]; - "proc-macro" = [ "proc-macro2/proc-macro" "quote/proc-macro" ]; - "quote" = [ "dep:quote" ]; + "printing" = [ "dep:quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; "test" = [ "syn-test-suite/all-features" ]; }; - resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit" "visit-mut" ]; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; }; "sysinfo" = rec { crateName = "sysinfo"; @@ -5913,6 +6105,7 @@ rec { version = "0.1.5"; edition = "2021"; sha256 = "1gb974chm9aj8ifkyibylxkyb5an4bf5y8dxb18pqmck698gmdfg"; + libName = "target_features"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -5951,7 +6144,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.48.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Storage_FileSystem" "Win32_Foundation" ]; } @@ -5963,6 +6156,7 @@ rec { version = "0.3.4"; edition = "2018"; sha256 = "1xksx1l1019k9q0az9mhqsgb14w0vm88yax30iq6178s3d9yhjx7"; + libName = "tempfile_fast"; authors = [ "Chris West (Faux) <git@goeswhere.com>" ]; @@ -5985,9 +6179,9 @@ rec { }; "thiserror" = rec { crateName = "thiserror"; - version = "1.0.50"; + version = "1.0.64"; edition = "2021"; - sha256 = "1ll2sfbrxks8jja161zh1pgm3yssr7aawdmaa2xmcwcsbh7j39zr"; + sha256 = "114s8lmssxl0c2480s671am88vzlasbaikxbvfv8pyqrq6mzh2nm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -6001,10 +6195,11 @@ rec { }; "thiserror-impl" = rec { crateName = "thiserror-impl"; - version = "1.0.50"; + version = "1.0.64"; edition = "2021"; - sha256 = "1f0lmam4765sfnwr4b1n00y14vxh10g0311mkk0adr80pi02wsr6"; + sha256 = "1hvzmjx9iamln854l74qyhs0jl2pg3hhqzpqm9p8gszmf9v4x408"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -6019,16 +6214,16 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; } ]; }; "tokio" = rec { crateName = "tokio"; - version = "1.33.0"; + version = "1.40.0"; edition = "2021"; - sha256 = "0lynj8nfqziviw72qns9mjlhmnm66bsc5bivy5g5x6gp7q720f2g"; + sha256 = "166rllhfkyqp0fs7sxn6crv74iizi4wzd3cvxkcpmlk52qip1c72"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -6056,11 +6251,6 @@ rec { usesDefaultFeatures = false; } { - name = "num_cpus"; - packageId = "num_cpus"; - optional = true; - } - { name = "pin-project-lite"; packageId = "pin-project-lite"; } @@ -6072,8 +6262,13 @@ rec { features = [ "all" ]; } { + name = "tokio-macros"; + packageId = "tokio-macros"; + optional = true; + } + { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.52.0"; optional = true; target = { target, features }: (target."windows" or false); } @@ -6091,7 +6286,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Security_Authorization" ]; } @@ -6104,10 +6299,9 @@ rec { "macros" = [ "tokio-macros" ]; "mio" = [ "dep:mio" ]; "net" = [ "libc" "mio/os-poll" "mio/os-ext" "mio/net" "socket2" "windows-sys/Win32_Foundation" "windows-sys/Win32_Security" "windows-sys/Win32_Storage_FileSystem" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_System_SystemServices" ]; - "num_cpus" = [ "dep:num_cpus" ]; "parking_lot" = [ "dep:parking_lot" ]; "process" = [ "bytes" "libc" "mio/os-poll" "mio/os-ext" "mio/net" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Threading" "windows-sys/Win32_System_WindowsProgramming" ]; - "rt-multi-thread" = [ "num_cpus" "rt" ]; + "rt-multi-thread" = [ "rt" ]; "signal" = [ "libc" "mio/os-poll" "mio/net" "mio/os-ext" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Console" ]; "signal-hook-registry" = [ "dep:signal-hook-registry" ]; "socket2" = [ "dep:socket2" ]; @@ -6116,13 +6310,41 @@ rec { "tracing" = [ "dep:tracing" ]; "windows-sys" = [ "dep:windows-sys" ]; }; - resolvedDefaultFeatures = [ "bytes" "default" "io-util" "libc" "mio" "net" "num_cpus" "rt" "rt-multi-thread" "socket2" "sync" "time" "windows-sys" ]; + resolvedDefaultFeatures = [ "bytes" "default" "io-util" "libc" "macros" "mio" "net" "rt" "rt-multi-thread" "socket2" "sync" "time" "tokio-macros" "windows-sys" ]; + }; + "tokio-macros" = rec { + crateName = "tokio-macros"; + version = "2.4.0"; + edition = "2021"; + sha256 = "0lnpg14h1v3fh2jvnc8cz7cjf0m7z1xgkwfpcyy632g829imjgb9"; + procMacro = true; + libName = "tokio_macros"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" ]; + } + ]; + }; "tokio-util" = rec { crateName = "tokio-util"; version = "0.7.10"; edition = "2021"; sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -6173,6 +6395,96 @@ rec { }; resolvedDefaultFeatures = [ "default" "io" "io-util" ]; }; + "tracing" = rec { + crateName = "tracing"; + version = "0.1.40"; + edition = "2018"; + sha256 = "1vv48dac9zgj9650pg2b4d0j3w6f3x9gbggf43scq5hrlysklln3"; + authors = [ + "Eliza Weisman <eliza@buoyant.io>" + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tracing-attributes"; + packageId = "tracing-attributes"; + optional = true; + } + { + name = "tracing-core"; + packageId = "tracing-core"; + usesDefaultFeatures = false; + } + ]; + features = { + "attributes" = [ "tracing-attributes" ]; + "default" = [ "std" "attributes" ]; + "log" = [ "dep:log" ]; + "log-always" = [ "log" ]; + "std" = [ "tracing-core/std" ]; + "tracing-attributes" = [ "dep:tracing-attributes" ]; + "valuable" = [ "tracing-core/valuable" ]; + }; + resolvedDefaultFeatures = [ "attributes" "default" "std" "tracing-attributes" ]; + }; + "tracing-attributes" = rec { + crateName = "tracing-attributes"; + version = "0.1.27"; + edition = "2018"; + sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; + procMacro = true; + libName = "tracing_attributes"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + "Eliza Weisman <eliza@buoyant.io>" + "David Barsky <dbarsky@amazon.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "visit-mut" "clone-impls" "extra-traits" "proc-macro" ]; + } + ]; + features = { }; + }; + "tracing-core" = rec { + crateName = "tracing-core"; + version = "0.1.32"; + edition = "2018"; + sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "once_cell"; + packageId = "once_cell"; + optional = true; + } + ]; + features = { + "default" = [ "std" "valuable/std" ]; + "once_cell" = [ "dep:once_cell" ]; + "std" = [ "once_cell" ]; + "valuable" = [ "dep:valuable" ]; + }; + resolvedDefaultFeatures = [ "once_cell" "std" ]; + }; "typenum" = rec { crateName = "typenum"; version = "1.17.0"; @@ -6193,6 +6505,7 @@ rec { version = "1.0.12"; edition = "2018"; sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -6230,6 +6543,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "1khgsh4z9bga35mjhg41dl7523i69ffc5m8ckhqaw6ssyabc5bkx"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -6261,6 +6575,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "05zj8yl243rvs87rhicq2l1d6443lnm6k90khf744khf9ikg95z3"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -6287,7 +6602,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "full" ]; } { @@ -6306,6 +6621,7 @@ rec { edition = "2018"; sha256 = "1chn3wgw9awmvs0fpmazbqyc5rwfgy3pj7lzwczmzb887dxh2qar"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -6330,6 +6646,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "01rrzg3y1apqygsjz1jg0n7p831nm4kdyxmxyl85x7v6mf6kndf5"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -6344,7 +6661,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; features = [ "visit" "full" ]; } { @@ -6368,6 +6685,7 @@ rec { edition = "2018"; links = "wasm_bindgen"; sha256 = "02vmw2rzsla1qm0zgfng4kqz52xn8k54v8ads4g1macv09fnq10d"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -6385,12 +6703,12 @@ rec { { name = "winapi-i686-pc-windows-gnu"; packageId = "winapi-i686-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "i686-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnu"); } { name = "winapi-x86_64-pc-windows-gnu"; packageId = "winapi-x86_64-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnu"); } ]; features = { @@ -6403,6 +6721,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -6413,6 +6732,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -7104,6 +7424,7 @@ rec { version = "0.51.1"; edition = "2021"; sha256 = "0r1f57hsshsghjyc7ypp2s0i78f7b1vr93w68sdb8baxyf2czy7i"; + libName = "windows_core"; authors = [ "Microsoft" ]; @@ -7121,6 +7442,7 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "1nc3qv7sy24x0nlnb32f7alzpd6f72l4p24vl65vydbyil669ark"; + libName = "windows_core"; authors = [ "Microsoft" ]; @@ -7133,11 +7455,12 @@ rec { features = { }; resolvedDefaultFeatures = [ "default" ]; }; - "windows-sys" = rec { + "windows-sys 0.48.0" = rec { crateName = "windows-sys"; version = "0.48.0"; edition = "2018"; sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -7424,13 +7747,262 @@ rec { "Win32_Web" = [ "Win32" ]; "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; }; - resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_NetworkManagement" "Win32_NetworkManagement_IpHelper" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "Win32_UI" "Win32_UI_Shell" "default" ]; + resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_NetworkManagement" "Win32_NetworkManagement_IpHelper" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_Threading" "Win32_System_WindowsProgramming" "Win32_UI" "Win32_UI_Shell" "default" ]; + }; + "windows-sys 0.52.0" = rec { + crateName = "windows-sys"; + version = "0.52.0"; + edition = "2021"; + sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + libName = "windows_sys"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-targets"; + packageId = "windows-targets 0.52.0"; + } + ]; + features = { + "Wdk_Foundation" = [ "Wdk" ]; + "Wdk_Graphics" = [ "Wdk" ]; + "Wdk_Graphics_Direct3D" = [ "Wdk_Graphics" ]; + "Wdk_Storage" = [ "Wdk" ]; + "Wdk_Storage_FileSystem" = [ "Wdk_Storage" ]; + "Wdk_Storage_FileSystem_Minifilters" = [ "Wdk_Storage_FileSystem" ]; + "Wdk_System" = [ "Wdk" ]; + "Wdk_System_IO" = [ "Wdk_System" ]; + "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; + "Wdk_System_Registry" = [ "Wdk_System" ]; + "Wdk_System_SystemInformation" = [ "Wdk_System" ]; + "Wdk_System_SystemServices" = [ "Wdk_System" ]; + "Wdk_System_Threading" = [ "Wdk_System" ]; + "Win32_Data" = [ "Win32" ]; + "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; + "Win32_Data_RightsManagement" = [ "Win32_Data" ]; + "Win32_Devices" = [ "Win32" ]; + "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; + "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; + "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; + "Win32_Devices_Communication" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; + "Win32_Devices_Display" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; + "Win32_Devices_Fax" = [ "Win32_Devices" ]; + "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; + "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; + "Win32_Devices_Properties" = [ "Win32_Devices" ]; + "Win32_Devices_Pwm" = [ "Win32_Devices" ]; + "Win32_Devices_Sensors" = [ "Win32_Devices" ]; + "Win32_Devices_SerialCommunication" = [ "Win32_Devices" ]; + "Win32_Devices_Tapi" = [ "Win32_Devices" ]; + "Win32_Devices_Usb" = [ "Win32_Devices" ]; + "Win32_Devices_WebServicesOnDevices" = [ "Win32_Devices" ]; + "Win32_Foundation" = [ "Win32" ]; + "Win32_Gaming" = [ "Win32" ]; + "Win32_Globalization" = [ "Win32" ]; + "Win32_Graphics" = [ "Win32" ]; + "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; + "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; + "Win32_Graphics_GdiPlus" = [ "Win32_Graphics" ]; + "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; + "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing_PrintTicket" = [ "Win32_Graphics_Printing" ]; + "Win32_Management" = [ "Win32" ]; + "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; + "Win32_Media" = [ "Win32" ]; + "Win32_Media_Audio" = [ "Win32_Media" ]; + "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; + "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; + "Win32_Media_Multimedia" = [ "Win32_Media" ]; + "Win32_Media_Streaming" = [ "Win32_Media" ]; + "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; + "Win32_NetworkManagement" = [ "Win32" ]; + "Win32_NetworkManagement_Dhcp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Snmp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; + "Win32_Networking" = [ "Win32" ]; + "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; + "Win32_Networking_Clustering" = [ "Win32_Networking" ]; + "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; + "Win32_Networking_Ldap" = [ "Win32_Networking" ]; + "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; + "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; + "Win32_Networking_WinInet" = [ "Win32_Networking" ]; + "Win32_Networking_WinSock" = [ "Win32_Networking" ]; + "Win32_Networking_WindowsWebServices" = [ "Win32_Networking" ]; + "Win32_Security" = [ "Win32" ]; + "Win32_Security_AppLocker" = [ "Win32_Security" ]; + "Win32_Security_Authentication" = [ "Win32_Security" ]; + "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; + "Win32_Security_Authorization" = [ "Win32_Security" ]; + "Win32_Security_Credentials" = [ "Win32_Security" ]; + "Win32_Security_Cryptography" = [ "Win32_Security" ]; + "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Certificates" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Sip" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_UI" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_DiagnosticDataQuery" = [ "Win32_Security" ]; + "Win32_Security_DirectoryServices" = [ "Win32_Security" ]; + "Win32_Security_EnterpriseData" = [ "Win32_Security" ]; + "Win32_Security_ExtensibleAuthenticationProtocol" = [ "Win32_Security" ]; + "Win32_Security_Isolation" = [ "Win32_Security" ]; + "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; + "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; + "Win32_Security_WinTrust" = [ "Win32_Security" ]; + "Win32_Security_WinWlx" = [ "Win32_Security" ]; + "Win32_Storage" = [ "Win32" ]; + "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; + "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; + "Win32_Storage_Compression" = [ "Win32_Storage" ]; + "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; + "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_Imapi" = [ "Win32_Storage" ]; + "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; + "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; + "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; + "Win32_Storage_Jet" = [ "Win32_Storage" ]; + "Win32_Storage_Nvme" = [ "Win32_Storage" ]; + "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; + "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; + "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; + "Win32_Storage_Vhd" = [ "Win32_Storage" ]; + "Win32_Storage_Xps" = [ "Win32_Storage" ]; + "Win32_System" = [ "Win32" ]; + "Win32_System_AddressBook" = [ "Win32_System" ]; + "Win32_System_Antimalware" = [ "Win32_System" ]; + "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; + "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; + "Win32_System_ClrHosting" = [ "Win32_System" ]; + "Win32_System_Com" = [ "Win32_System" ]; + "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; + "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; + "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; + "Win32_System_ComponentServices" = [ "Win32_System" ]; + "Win32_System_Console" = [ "Win32_System" ]; + "Win32_System_CorrelationVector" = [ "Win32_System" ]; + "Win32_System_DataExchange" = [ "Win32_System" ]; + "Win32_System_DeploymentServices" = [ "Win32_System" ]; + "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; + "Win32_System_Diagnostics" = [ "Win32_System" ]; + "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug_Extensions" = [ "Win32_System_Diagnostics_Debug" ]; + "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; + "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; + "Win32_System_Environment" = [ "Win32_System" ]; + "Win32_System_ErrorReporting" = [ "Win32_System" ]; + "Win32_System_EventCollector" = [ "Win32_System" ]; + "Win32_System_EventLog" = [ "Win32_System" ]; + "Win32_System_EventNotificationService" = [ "Win32_System" ]; + "Win32_System_GroupPolicy" = [ "Win32_System" ]; + "Win32_System_HostCompute" = [ "Win32_System" ]; + "Win32_System_HostComputeNetwork" = [ "Win32_System" ]; + "Win32_System_HostComputeSystem" = [ "Win32_System" ]; + "Win32_System_Hypervisor" = [ "Win32_System" ]; + "Win32_System_IO" = [ "Win32_System" ]; + "Win32_System_Iis" = [ "Win32_System" ]; + "Win32_System_Ioctl" = [ "Win32_System" ]; + "Win32_System_JobObjects" = [ "Win32_System" ]; + "Win32_System_Js" = [ "Win32_System" ]; + "Win32_System_Kernel" = [ "Win32_System" ]; + "Win32_System_LibraryLoader" = [ "Win32_System" ]; + "Win32_System_Mailslots" = [ "Win32_System" ]; + "Win32_System_Mapi" = [ "Win32_System" ]; + "Win32_System_Memory" = [ "Win32_System" ]; + "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; + "Win32_System_MessageQueuing" = [ "Win32_System" ]; + "Win32_System_MixedReality" = [ "Win32_System" ]; + "Win32_System_Ole" = [ "Win32_System" ]; + "Win32_System_PasswordManagement" = [ "Win32_System" ]; + "Win32_System_Performance" = [ "Win32_System" ]; + "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; + "Win32_System_Pipes" = [ "Win32_System" ]; + "Win32_System_Power" = [ "Win32_System" ]; + "Win32_System_ProcessStatus" = [ "Win32_System" ]; + "Win32_System_Recovery" = [ "Win32_System" ]; + "Win32_System_Registry" = [ "Win32_System" ]; + "Win32_System_RemoteDesktop" = [ "Win32_System" ]; + "Win32_System_RemoteManagement" = [ "Win32_System" ]; + "Win32_System_RestartManager" = [ "Win32_System" ]; + "Win32_System_Restore" = [ "Win32_System" ]; + "Win32_System_Rpc" = [ "Win32_System" ]; + "Win32_System_Search" = [ "Win32_System" ]; + "Win32_System_Search_Common" = [ "Win32_System_Search" ]; + "Win32_System_SecurityCenter" = [ "Win32_System" ]; + "Win32_System_Services" = [ "Win32_System" ]; + "Win32_System_SetupAndMigration" = [ "Win32_System" ]; + "Win32_System_Shutdown" = [ "Win32_System" ]; + "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; + "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; + "Win32_System_SystemInformation" = [ "Win32_System" ]; + "Win32_System_SystemServices" = [ "Win32_System" ]; + "Win32_System_Threading" = [ "Win32_System" ]; + "Win32_System_Time" = [ "Win32_System" ]; + "Win32_System_TpmBaseServices" = [ "Win32_System" ]; + "Win32_System_UserAccessLogging" = [ "Win32_System" ]; + "Win32_System_Variant" = [ "Win32_System" ]; + "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; + "Win32_System_WindowsProgramming" = [ "Win32_System" ]; + "Win32_System_Wmi" = [ "Win32_System" ]; + "Win32_UI" = [ "Win32" ]; + "Win32_UI_Accessibility" = [ "Win32_UI" ]; + "Win32_UI_ColorSystem" = [ "Win32_UI" ]; + "Win32_UI_Controls" = [ "Win32_UI" ]; + "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; + "Win32_UI_HiDpi" = [ "Win32_UI" ]; + "Win32_UI_Input" = [ "Win32_UI" ]; + "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; + "Win32_UI_InteractionContext" = [ "Win32_UI" ]; + "Win32_UI_Magnification" = [ "Win32_UI" ]; + "Win32_UI_Shell" = [ "Win32_UI" ]; + "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; + "Win32_UI_TabletPC" = [ "Win32_UI" ]; + "Win32_UI_TextServices" = [ "Win32_UI" ]; + "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; + "Win32_Web" = [ "Win32" ]; + "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; + }; + resolvedDefaultFeatures = [ "Wdk" "Wdk_Foundation" "Wdk_Storage" "Wdk_Storage_FileSystem" "Wdk_System" "Wdk_System_IO" "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_WindowsProgramming" "default" ]; }; "windows-targets 0.48.5" = rec { crateName = "windows-targets"; version = "0.48.5"; edition = "2018"; sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -7438,7 +8010,7 @@ rec { { name = "windows_aarch64_gnullvm"; packageId = "windows_aarch64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); } { name = "windows_aarch64_msvc"; @@ -7463,7 +8035,7 @@ rec { { name = "windows_x86_64_gnullvm"; packageId = "windows_x86_64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); } { name = "windows_x86_64_msvc"; @@ -7478,6 +8050,7 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "1kg7a27ynzw8zz3krdgy6w5gbqcji27j1sz4p7xk2j5j8082064a"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -7485,7 +8058,7 @@ rec { { name = "windows_aarch64_gnullvm"; packageId = "windows_aarch64_gnullvm 0.52.0"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); } { name = "windows_aarch64_msvc"; @@ -7510,7 +8083,7 @@ rec { { name = "windows_x86_64_gnullvm"; packageId = "windows_x86_64_gnullvm 0.52.0"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); } { name = "windows_x86_64_msvc"; @@ -7665,6 +8238,7 @@ rec { version = "0.8.7"; edition = "2018"; sha256 = "0yz037yrkn0qa0g0r6733ynd1xbw7zvx58v6qylhyi2kv9wb2a4q"; + libName = "xxhash_rust"; authors = [ "Douman <douman@gmx.se>" ]; @@ -7673,9 +8247,9 @@ rec { }; "zerocopy" = rec { crateName = "zerocopy"; - version = "0.7.25"; + version = "0.7.34"; edition = "2018"; - sha256 = "0mv5w4fq1kcpw1ydcb5cvr8zdms5pqy0r60g04ayzpqfgjk6klwc"; + sha256 = "11xhrwixm78m6ca1jdxf584wdwvpgg7q00vg21fhwl0psvyf71xf"; authors = [ "Joshua Liebow-Feeser <joshlf@google.com>" ]; @@ -7709,10 +8283,11 @@ rec { }; "zerocopy-derive" = rec { crateName = "zerocopy-derive"; - version = "0.7.25"; + version = "0.7.34"; edition = "2018"; - sha256 = "0svxr32pp4lav1vjar127g2r09gpiajxn0yv1k66r8hrlayl1wf2"; + sha256 = "0fqvglw01w3hp7xj9gdk1800x9j7v58s9w8ijiyiz2a7krb39s8m"; procMacro = true; + libName = "zerocopy_derive"; authors = [ "Joshua Liebow-Feeser <joshlf@google.com>" ]; @@ -7727,7 +8302,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.39"; + packageId = "syn 2.0.79"; } ]; @@ -7787,6 +8362,7 @@ rec { version = "7.0.0"; edition = "2018"; sha256 = "0gpav2lcibrpmyslmjkcn3w0w64qif3jjljd2h8lr4p249s7qx23"; + libName = "zstd_safe"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -7820,6 +8396,7 @@ rec { edition = "2018"; links = "zstd"; sha256 = "0mk6a2367swdi22zg03lcackpnvgq96d7120awd4i83lm2lfy5ly"; + libName = "zstd_sys"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -7855,14 +8432,11 @@ rec { fuchsia = true; test = false; - /* We are choosing an arbitrary rust version to grab `lib` from, - which is unfortunate, but `lib` has been version-agnostic the - whole time so this is good enough for now. - */ - os = pkgs.rust.lib.toTargetOs platform; - arch = pkgs.rust.lib.toTargetArch platform; - family = pkgs.rust.lib.toTargetFamily platform; - vendor = pkgs.rust.lib.toTargetVendor platform; + inherit (platform.rust.platform) + arch + os + vendor; + family = platform.rust.platform.target-family; env = "gnu"; endian = if platform.parsed.cpu.significantByte.name == "littleEndian" @@ -7952,51 +8526,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; - export RUST_BACKTRACE=1 + inherit (crate) src; - # recreate a file hierarchy as when running tests with cargo + inherit testCrateFlags; - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # TODO(raitobezarius): I believe there could be more edge cases if `crate.sourceRoot` - # do exist but it's very hard to reason about them, so let's wait until the first bug report. - mkdir -p source/ - cd source/ + buildInputs = testInputs; - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + buildPhase = '' + set -e + export RUST_BACKTRACE=1 - # build outputs - testRoot=target/debug - mkdir -p $testRoot + # build outputs + testRoot=target/debug + mkdir -p $testRoot - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { @@ -8105,7 +8669,7 @@ rec { let self = { crates = lib.mapAttrs (packageId: value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs; - target = makeTarget pkgs.stdenv.hostPlatform; + target = makeTarget stdenv.hostPlatform; build = mkBuiltByPackageIdByPkgs pkgs.buildPackages; }; in @@ -8180,8 +8744,6 @@ rec { buildRustCrateForPkgsFunc pkgs ( crateConfig // { - # https://github.com/NixOS/nixpkgs/issues/218712 - dontStrip = stdenv.hostPlatform.isDarwin; src = crateConfig.src or ( pkgs.fetchurl rec { name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz"; diff --git a/tvix/tools/narinfo2parquet/Cargo.toml b/users/edef/narinfo2parquet/Cargo.toml index 3efa9d1df936..40d721d28cef 100644 --- a/tvix/tools/narinfo2parquet/Cargo.toml +++ b/users/edef/narinfo2parquet/Cargo.toml @@ -11,7 +11,7 @@ members = ["."] [dependencies] anyhow = { version = "1.0.75", features = ["backtrace"] } jemallocator = "0.5.4" -nix-compat = { version = "0.1.0", path = "../../nix-compat" } +nix-compat = { version = "0.1.0", path = "../../../tvix/nix-compat" } tempfile-fast = "0.3.4" zstd = "0.13.0" diff --git a/tvix/tools/narinfo2parquet/OWNERS b/users/edef/narinfo2parquet/OWNERS index b9bc074a8020..b9bc074a8020 100644 --- a/tvix/tools/narinfo2parquet/OWNERS +++ b/users/edef/narinfo2parquet/OWNERS diff --git a/users/edef/narinfo2parquet/default.nix b/users/edef/narinfo2parquet/default.nix new file mode 100644 index 000000000000..dfe2b66655c8 --- /dev/null +++ b/users/edef/narinfo2parquet/default.nix @@ -0,0 +1,11 @@ +{ pkgs, depot, ... }: + +(pkgs.callPackage ./Cargo.nix { + defaultCrateOverrides = (depot.tvix.utils.defaultCrateOverridesForPkgs pkgs) // { + narinfo2parquet = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + }; +}).rootCrate.build.overrideAttrs { + meta.ci.extraSteps.crate2nix = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; +} diff --git a/tvix/tools/narinfo2parquet/src/main.rs b/users/edef/narinfo2parquet/src/main.rs index 3b793e02b133..ea3d39af5503 100644 --- a/tvix/tools/narinfo2parquet/src/main.rs +++ b/users/edef/narinfo2parquet/src/main.rs @@ -12,7 +12,6 @@ use jemallocator::Jemalloc; use nix_compat::{ narinfo::{self, NarInfo}, nixbase32, - nixhash::{CAHash, NixHash}, }; use polars::{io::parquet::ParquetWriter, prelude::*}; use std::{ @@ -114,6 +113,9 @@ struct FrameBuilder { store_path_hash_str: StringChunkedBuilder, store_path_hash: BinaryChunkedBuilder, store_path_name: StringChunkedBuilder, + deriver_hash_str: StringChunkedBuilder, + deriver_hash: BinaryChunkedBuilder, + deriver_name: StringChunkedBuilder, nar_hash: BinaryChunkedBuilder, nar_size: PrimitiveChunkedBuilder<UInt64Type>, references: ListBinaryChunkedBuilder, @@ -133,6 +135,9 @@ impl Default for FrameBuilder { store_path_hash_str: StringChunkedBuilder::new("store_path_hash_str", 0, 0), store_path_hash: BinaryChunkedBuilder::new("store_path_hash", 0, 0), store_path_name: StringChunkedBuilder::new("store_path_name", 0, 0), + deriver_hash_str: StringChunkedBuilder::new("deriver_hash_str", 0, 0), + deriver_hash: BinaryChunkedBuilder::new("deriver_hash", 0, 0), + deriver_name: StringChunkedBuilder::new("deriver_name", 0, 0), nar_hash: BinaryChunkedBuilder::new("nar_hash", 0, 0), nar_size: PrimitiveChunkedBuilder::new("nar_size", 0), references: ListBinaryChunkedBuilder::new("references", 0, 0), @@ -159,10 +164,20 @@ impl FrameBuilder { fn push(&mut self, entry: &NarInfo) { self.store_path_hash_str .append_value(nixbase32::encode(entry.store_path.digest())); - self.store_path_hash.append_value(entry.store_path.digest()); self.store_path_name.append_value(entry.store_path.name()); + if let Some(deriver) = &entry.deriver { + self.deriver_hash_str + .append_value(nixbase32::encode(deriver.digest())); + self.deriver_hash.append_value(deriver.digest()); + self.deriver_name.append_value(deriver.name()); + } else { + self.deriver_hash_str.append_null(); + self.deriver_hash.append_null(); + self.deriver_name.append_null(); + } + self.nar_hash.append_value(&entry.nar_hash); self.nar_size.append_value(entry.nar_size); @@ -172,31 +187,13 @@ impl FrameBuilder { assert!(entry.signatures.len() <= 1); self.signature .append_option(entry.signatures.get(0).map(|sig| { - assert_eq!(sig.name(), "cache.nixos.org-1"); + assert_eq!(sig.name(), &"cache.nixos.org-1"); sig.bytes() })); if let Some(ca) = &entry.ca { - // decompose the CAHash into algo and hash parts - // TODO(edef): move this into CAHash - let (algo, hash) = match ca { - CAHash::Flat(h) => match h { - NixHash::Md5(h) => ("fixed:md5", &h[..]), - NixHash::Sha1(h) => ("fixed:sha1", &h[..]), - NixHash::Sha256(h) => ("fixed:sha256", &h[..]), - NixHash::Sha512(h) => ("fixed:sha512", &h[..]), - }, - CAHash::Nar(h) => match h { - NixHash::Md5(h) => ("fixed:r:md5", &h[..]), - NixHash::Sha1(h) => ("fixed:r:sha1", &h[..]), - NixHash::Sha256(h) => ("fixed:r:sha256", &h[..]), - NixHash::Sha512(h) => ("fixed:r:sha512", &h[..]), - }, - CAHash::Text(h) => ("text:sha256", &h[..]), - }; - - self.ca_algo.append_value(algo); - self.ca_hash.append_value(hash); + self.ca_algo.append_value(ca.algo_str()); + self.ca_hash.append_value(ca.hash().digest_as_bytes()); } else { self.ca_algo.append_null(); self.ca_hash.append_null(); @@ -247,6 +244,9 @@ impl FrameBuilder { "store_path_hash_str" => self.store_path_hash_str.finish().into_series(), "store_path_hash" => self.store_path_hash.finish().into_series(), "store_path_name" => self.store_path_name.finish().into_series(), + "deriver_hash_str" => self.deriver_hash_str.finish().into_series(), + "deriver_hash" => self.deriver_hash.finish().into_series(), + "deriver_name" => self.deriver_name.finish().into_series(), "nar_hash" => self.nar_hash.finish().into_series(), "nar_size" => self.nar_size.finish().into_series(), "references" => self.references.finish().into_series(), diff --git a/tvix/tools/turbofetch/Cargo.lock b/users/edef/turbofetch/Cargo.lock index 4d65fc40639c..423b3556eebf 100644 --- a/tvix/tools/turbofetch/Cargo.lock +++ b/users/edef/turbofetch/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "android-tzdata" @@ -34,9 +34,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -45,9 +45,9 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws_lambda_events" @@ -77,7 +77,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771c11de66cef31b3f49f0b38f06d94f0af424f60381409fc21972ff9c8f835b" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "http", "http-body", @@ -88,17 +88,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -115,21 +115,15 @@ checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" [[package]] name = "base64" -version = "0.21.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" - -[[package]] -name = "bitflags" -version = "1.3.2" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -142,27 +136,28 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" dependencies = [ "serde", ] [[package]] name = "cc" -version = "1.0.83" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -173,22 +168,22 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", "serde", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -196,24 +191,24 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -230,9 +225,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "digest" @@ -265,6 +260,12 @@ dependencies = [ ] [[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -272,9 +273,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -287,9 +288,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -297,15 +298,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -314,15 +315,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -331,21 +332,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -371,9 +372,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -382,15 +383,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "h2" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -407,15 +408,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -435,9 +436,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f95b9abcae896730d42b78e09c155ed4ddf82c07b4de772c64aee5b2d8b7c150" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -446,9 +447,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -467,9 +468,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -479,9 +480,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -494,7 +495,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -518,9 +519,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -541,34 +542,34 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ - "autocfg", + "equivalent", "hashbrown", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -611,32 +612,31 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.1", + "bitflags", "libc", - "redox_syscall", ] [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -644,15 +644,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "mach2" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" dependencies = [ "libc", ] @@ -666,7 +666,7 @@ dependencies = [ "libc", "mach2", "thiserror", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -682,28 +682,29 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.9" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -718,43 +719,33 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] name = "object" -version = "0.32.1" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl-probe" @@ -770,9 +761,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -780,37 +771,37 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", @@ -819,9 +810,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -831,36 +822,36 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -884,16 +875,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.5" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin 0.9.8", "untrusted 0.9.0", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -980,15 +972,15 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -1023,22 +1015,22 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", ] [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1053,17 +1045,17 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.5", + "ring 0.17.8", "untrusted 0.9.0", ] [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -1072,9 +1064,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -1082,24 +1074,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.192" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -1108,20 +1100,21 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "6dbcf9b78a125ee667ae19388837dd12294b858d101fdd393cb9d5501ef09eb2" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_path_to_error" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa", "serde", @@ -1151,15 +1144,15 @@ dependencies = [ [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -1175,28 +1168,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" - -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1219,9 +1202,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "2.0.39" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -1230,18 +1213,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -1250,9 +1233,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -1260,28 +1243,27 @@ dependencies = [ [[package]] name = "tokio" -version = "1.34.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", @@ -1301,9 +1283,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -1312,16 +1294,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -1341,15 +1322,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -1386,9 +1367,9 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ "log", "once_cell", @@ -1407,9 +1388,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "nu-ansi-term", "serde", @@ -1424,9 +1405,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "turbofetch" @@ -1459,9 +1440,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "untrusted" @@ -1483,9 +1464,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "want" @@ -1504,19 +1485,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", @@ -1529,9 +1511,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1539,9 +1521,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", @@ -1552,15 +1534,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "web-sys" -version = "0.3.65" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -1572,7 +1554,7 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.5", + "ring 0.17.8", "untrusted 0.9.0", ] @@ -1600,11 +1582,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1613,7 +1595,25 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -1622,13 +1622,29 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -1638,52 +1654,100 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] name = "xml-rs" -version = "0.8.19" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" [[package]] name = "zeroize" -version = "1.6.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zstd" diff --git a/tvix/tools/turbofetch/Cargo.nix b/users/edef/turbofetch/Cargo.nix index d7263727e2dd..cd31320bb7c5 100644 --- a/tvix/tools/turbofetch/Cargo.nix +++ b/users/edef/turbofetch/Cargo.nix @@ -1,4 +1,4 @@ -# This file was @generated by crate2nix 0.13.0 with the command: +# This file was @generated by crate2nix 0.14.1 with the command: # "generate" "--all-features" # See https://github.com/kolloch/crate2nix for more info. @@ -13,6 +13,8 @@ , rootFeatures ? [ "default" ] # If true, throw errors instead of issueing deprecation warnings. , strictDeprecation ? false + # Elements to add to the `-C target-feature=` argument passed to `rustc` + # (separated by `,`, prefixed with `+`). # Used for conditional compilation based on CPU feature detection. , targetFeatures ? [ ] # Whether to perform release builds: longer compile times, faster binaries. @@ -83,9 +85,10 @@ rec { crates = { "addr2line" = rec { crateName = "addr2line"; - version = "0.21.0"; + version = "0.24.2"; edition = "2018"; - sha256 = "1jx0k3iwyqr8klqbzk6kjvr496yd94aspis10vwsj5wy7gib4c4a"; + crateBin = [ ]; + sha256 = "1hd1i57zxgz08j6h5qrhsnm2fi0bcqvsh389fw400xm3arz2ggnz"; dependencies = [ { name = "gimli"; @@ -95,28 +98,29 @@ rec { } ]; features = { + "all" = [ "bin" ]; "alloc" = [ "dep:alloc" ]; + "bin" = [ "loader" "rustc-demangle" "cpp_demangle" "fallible-iterator" "smallvec" "dep:clap" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; "cpp_demangle" = [ "dep:cpp_demangle" ]; - "default" = [ "rustc-demangle" "cpp_demangle" "std-object" "fallible-iterator" "smallvec" "memmap2" ]; + "default" = [ "rustc-demangle" "cpp_demangle" "loader" "fallible-iterator" "smallvec" ]; "fallible-iterator" = [ "dep:fallible-iterator" ]; - "memmap2" = [ "dep:memmap2" ]; - "object" = [ "dep:object" ]; + "loader" = [ "std" "dep:object" "dep:memmap2" "dep:typed-arena" ]; "rustc-demangle" = [ "dep:rustc-demangle" ]; "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "gimli/rustc-dep-of-std" ]; "smallvec" = [ "dep:smallvec" ]; "std" = [ "gimli/std" ]; - "std-object" = [ "std" "object" "object/std" "object/compression" "gimli/endian-reader" ]; }; }; - "adler" = rec { - crateName = "adler"; - version = "1.0.2"; - edition = "2015"; - sha256 = "1zim79cvzd5yrkzl3nyfx0avijwgk9fqv3yrscdy1cc79ih02qpj"; + "adler2" = rec { + crateName = "adler2"; + version = "2.0.0"; + edition = "2021"; + sha256 = "09r6drylvgy8vv8k20lnbvwq8gp09h7smfn6h1rxsy15pgh629si"; authors = [ "Jonas Schievink <jonasschievink@gmail.com>" + "oyvindln <oyvindln@users.noreply.github.com>" ]; features = { "compiler_builtins" = [ "dep:compiler_builtins" ]; @@ -130,6 +134,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9"; + libName = "android_tzdata"; authors = [ "RumovZ" ]; @@ -153,9 +158,10 @@ rec { }; "async-stream" = rec { crateName = "async-stream"; - version = "0.3.5"; - edition = "2018"; - sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + version = "0.3.6"; + edition = "2021"; + sha256 = "0xl4zqncrdmw2g6241wgr11dxdg4h7byy6bz3l6si03qyfk72nhb"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -177,10 +183,11 @@ rec { }; "async-stream-impl" = rec { crateName = "async-stream-impl"; - version = "0.3.5"; - edition = "2018"; - sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; + version = "0.3.6"; + edition = "2021"; + sha256 = "0kaplfb5axsvf1gfs2gk6c4zx6zcsns0yf3ssk7iwni7bphlvhn7"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -203,10 +210,11 @@ rec { }; "async-trait" = rec { crateName = "async-trait"; - version = "0.1.74"; + version = "0.1.83"; edition = "2021"; - sha256 = "1ydhbsqjqqa6bxbv0kgys2wq2vi3jpwjy57dk162ajwppgqkfrd6"; + sha256 = "1p8q8gm4fv2fdka8hwy2w3f8df7p5inixqi7rlmbnky3wmysw73j"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -222,16 +230,17 @@ rec { { name = "syn"; packageId = "syn"; - features = [ "full" "visit-mut" ]; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "proc-macro" "visit-mut" ]; } ]; }; "autocfg" = rec { crateName = "autocfg"; - version = "1.1.0"; + version = "1.4.0"; edition = "2015"; - sha256 = "1ylp3cb47ylzabimazvbz9ms6ap784zhb6syaz6c1jqpmcmq0s6l"; + sha256 = "09lz3by90d2hphbq56znag9v87gfpd9gb8nr82hll8z6x2nhprdc"; authors = [ "Josh Stone <cuviper@gmail.com>" ]; @@ -250,7 +259,7 @@ rec { dependencies = [ { name = "base64"; - packageId = "base64 0.21.5"; + packageId = "base64 0.21.7"; } { name = "bytes"; @@ -322,9 +331,9 @@ rec { }; "backtrace" = rec { crateName = "backtrace"; - version = "0.3.69"; - edition = "2018"; - sha256 = "0dsq23dhw4pfndkx2nsa1ml2g31idm7ss7ljxp8d57avygivg290"; + version = "0.3.74"; + edition = "2021"; + sha256 = "06pfif7nwx66qf2zaanc2fcq7m64i91ki9imw9xd3bnz5hrwp0ld"; authors = [ "The Rust Project Developers" ]; @@ -356,28 +365,23 @@ rec { packageId = "object"; usesDefaultFeatures = false; target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); - features = [ "read_core" "elf" "macho" "pe" "unaligned" "archive" ]; + features = [ "read_core" "elf" "macho" "pe" "xcoff" "unaligned" "archive" ]; } { name = "rustc-demangle"; packageId = "rustc-demangle"; } - ]; - buildDependencies = [ { - name = "cc"; - packageId = "cc"; + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + target = { target, features }: (target."windows" or false); } ]; features = { "cpp_demangle" = [ "dep:cpp_demangle" ]; "default" = [ "std" ]; - "rustc-serialize" = [ "dep:rustc-serialize" ]; "serde" = [ "dep:serde" ]; - "serialize-rustc" = [ "rustc-serialize" ]; "serialize-serde" = [ "serde" ]; - "verify-winapi" = [ "winapi/dbghelp" "winapi/handleapi" "winapi/libloaderapi" "winapi/memoryapi" "winapi/minwindef" "winapi/processthreadsapi" "winapi/synchapi" "winapi/tlhelp32" "winapi/winbase" "winapi/winnt" ]; - "winapi" = [ "dep:winapi" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; @@ -409,11 +413,11 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "base64 0.21.5" = rec { + "base64 0.21.7" = rec { crateName = "base64"; - version = "0.21.5"; + version = "0.21.7"; edition = "2018"; - sha256 = "1y8x2xs9nszj5ix7gg4ycn5a6wy7ca74zxwqri3bdqzdjha6lqrm"; + sha256 = "0rw52yvsk75kar9wgqfwgb414kvil1gn7mqkrhn9zf1537mpsacx"; authors = [ "Alice Maz <alice@alicemaz.com>" "Marshall Pierce <marshall@mpierce.org>" @@ -424,26 +428,11 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; - "bitflags 1.3.2" = rec { - crateName = "bitflags"; - version = "1.3.2"; - edition = "2018"; - sha256 = "12ki6w8gn1ldq7yz9y680llwk5gmrhrzszaa17g1sbrw2r2qvwxy"; - authors = [ - "The Rust Project Developers" - ]; - features = { - "compiler_builtins" = [ "dep:compiler_builtins" ]; - "core" = [ "dep:core" ]; - "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; - }; - resolvedDefaultFeatures = [ "default" ]; - }; - "bitflags 2.4.1" = rec { + "bitflags" = rec { crateName = "bitflags"; - version = "2.4.1"; + version = "2.6.0"; edition = "2021"; - sha256 = "01ryy3kd671b0ll4bhdvhsz67vwz1lz53fz504injrd7wpv64xrj"; + sha256 = "1pkidwzn3hnxlsl8zizh0bncgbjnw7c41cx7bby26ncbzmiznj5h"; authors = [ "The Rust Project Developers" ]; @@ -461,6 +450,7 @@ rec { version = "0.9.0"; edition = "2018"; sha256 = "1r4pf90s7d7lj1wdjhlnqa26vvbm6pnc33z138lxpnp9srpi2lj1"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -476,22 +466,23 @@ rec { }; "bumpalo" = rec { crateName = "bumpalo"; - version = "3.14.0"; + version = "3.16.0"; edition = "2021"; - sha256 = "1v4arnv9kwk54v5d0qqpv4vyw2sgr660nk0w3apzixi1cm3yfc3z"; + sha256 = "0b015qb4knwanbdlp1x48pkb4pm57b8gidbhhhxr900q2wb6fabr"; authors = [ "Nick Fitzgerald <fitzgen@gmail.com>" ]; features = { "allocator-api2" = [ "dep:allocator-api2" ]; + "serde" = [ "dep:serde" ]; }; resolvedDefaultFeatures = [ "default" ]; }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.7.2"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "1wzs7l57iwqmrszdpr2mmqf1b1hgvpxafc30imxhnry0zfl9m3a2"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -513,10 +504,9 @@ rec { }; "cc" = rec { crateName = "cc"; - version = "1.0.83"; + version = "1.1.30"; edition = "2018"; - crateBin = [ ]; - sha256 = "1l643zidlb5iy1dskc5ggqs4wqa29a02f44piczqc8zcnsq4y5zi"; + sha256 = "0icr3vn2r5scpgylbplffd5mh7jcdivqh9dfgsxymnc13fk06s5i"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -525,25 +515,31 @@ rec { name = "jobserver"; packageId = "jobserver"; optional = true; + usesDefaultFeatures = false; } { name = "libc"; packageId = "libc"; + optional = true; usesDefaultFeatures = false; target = { target, features }: (target."unix" or false); } + { + name = "shlex"; + packageId = "shlex"; + } ]; features = { - "jobserver" = [ "dep:jobserver" ]; - "parallel" = [ "jobserver" ]; + "parallel" = [ "dep:libc" "dep:jobserver" ]; }; - resolvedDefaultFeatures = [ "jobserver" "parallel" ]; + resolvedDefaultFeatures = [ "parallel" ]; }; "cfg-if" = rec { crateName = "cfg-if"; version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -555,9 +551,9 @@ rec { }; "chrono" = rec { crateName = "chrono"; - version = "0.4.31"; + version = "0.4.38"; edition = "2021"; - sha256 = "0f6vg67pipm8cziad2yms6a639pssnvysk1m05dd9crymmdnhb3z"; + sha256 = "009l8vc5p8750vn02z30mblg4pv2qhkbfizhfwmzc6vpy5nr67x2"; dependencies = [ { name = "android-tzdata"; @@ -585,7 +581,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets"; + packageId = "windows-targets 0.52.6"; optional = true; target = { target, features }: (target."windows" or false); } @@ -593,27 +589,33 @@ rec { features = { "android-tzdata" = [ "dep:android-tzdata" ]; "arbitrary" = [ "dep:arbitrary" ]; - "clock" = [ "std" "winapi" "iana-time-zone" "android-tzdata" ]; + "clock" = [ "winapi" "iana-time-zone" "android-tzdata" "now" ]; "default" = [ "clock" "std" "oldtime" "wasmbind" ]; "iana-time-zone" = [ "dep:iana-time-zone" ]; "js-sys" = [ "dep:js-sys" ]; + "now" = [ "std" ]; "pure-rust-locales" = [ "dep:pure-rust-locales" ]; - "rkyv" = [ "dep:rkyv" ]; - "rustc-serialize" = [ "dep:rustc-serialize" ]; + "rkyv" = [ "dep:rkyv" "rkyv/size_32" ]; + "rkyv-16" = [ "dep:rkyv" "rkyv?/size_16" ]; + "rkyv-32" = [ "dep:rkyv" "rkyv?/size_32" ]; + "rkyv-64" = [ "dep:rkyv" "rkyv?/size_64" ]; + "rkyv-validation" = [ "rkyv?/validation" ]; "serde" = [ "dep:serde" ]; - "unstable-locales" = [ "pure-rust-locales" "alloc" ]; + "std" = [ "alloc" ]; + "unstable-locales" = [ "pure-rust-locales" ]; "wasm-bindgen" = [ "dep:wasm-bindgen" ]; "wasmbind" = [ "wasm-bindgen" "js-sys" ]; "winapi" = [ "windows-targets" ]; "windows-targets" = [ "dep:windows-targets" ]; }; - resolvedDefaultFeatures = [ "android-tzdata" "clock" "iana-time-zone" "serde" "std" "winapi" "windows-targets" ]; + resolvedDefaultFeatures = [ "alloc" "android-tzdata" "clock" "iana-time-zone" "now" "serde" "std" "winapi" "windows-targets" ]; }; "core-foundation" = rec { crateName = "core-foundation"; - version = "0.9.3"; - edition = "2015"; - sha256 = "0ii1ihpjb30fk38gdikm5wqlkmyr8k46fh4k2r8sagz5dng7ljhr"; + version = "0.9.4"; + edition = "2018"; + sha256 = "13zvbbj07yk3b61b8fhwfzhy35535a583irf23vlcg59j7h9bqci"; + libName = "core_foundation"; authors = [ "The Servo Project Developers" ]; @@ -621,6 +623,7 @@ rec { { name = "core-foundation-sys"; packageId = "core-foundation-sys"; + usesDefaultFeatures = false; } { name = "libc"; @@ -629,28 +632,35 @@ rec { ]; features = { "chrono" = [ "dep:chrono" ]; + "default" = [ "link" ]; + "link" = [ "core-foundation-sys/link" ]; "mac_os_10_7_support" = [ "core-foundation-sys/mac_os_10_7_support" ]; "mac_os_10_8_features" = [ "core-foundation-sys/mac_os_10_8_features" ]; "uuid" = [ "dep:uuid" ]; "with-chrono" = [ "chrono" ]; "with-uuid" = [ "uuid" ]; }; + resolvedDefaultFeatures = [ "default" "link" ]; }; "core-foundation-sys" = rec { crateName = "core-foundation-sys"; - version = "0.8.4"; - edition = "2015"; - sha256 = "1yhf471qj6snnm2mcswai47vsbc9w30y4abmdp4crb4av87sb5p4"; + version = "0.8.7"; + edition = "2018"; + sha256 = "12w8j73lazxmr1z0h98hf3z623kl8ms7g07jch7n4p8f9nwlhdkp"; + libName = "core_foundation_sys"; authors = [ "The Servo Project Developers" ]; - features = { }; + features = { + "default" = [ "link" ]; + }; + resolvedDefaultFeatures = [ "default" "link" ]; }; "cpufeatures" = rec { crateName = "cpufeatures"; - version = "0.2.11"; + version = "0.2.14"; edition = "2018"; - sha256 = "1l0gzsyy576n017g9bf0vkv5hhg9cpz1h1libxyfdlzcgbh0yhnf"; + sha256 = "1q3qd9qkw94vs7n5i0y3zz2cqgzcxvdgyb54ryngwmjhfbgrg1k0"; authors = [ "RustCrypto Developers" ]; @@ -658,7 +668,7 @@ rec { { name = "libc"; packageId = "libc"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-linux-android"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-linux-android"); } { name = "libc"; @@ -680,9 +690,9 @@ rec { }; "crc32fast" = rec { crateName = "crc32fast"; - version = "1.3.2"; + version = "1.4.2"; edition = "2015"; - sha256 = "03c8f29yx293yf43xar946xbls1g60c207m9drf8ilqhr25vsh5m"; + sha256 = "1czp7vif73b8xslr3c9yxysmh9ws2r8824qda7j47ffs9pcnjxx9"; authors = [ "Sam Rijs <srijs@airpost.net>" "Alex Crichton <alex@alexcrichton.com>" @@ -703,6 +713,7 @@ rec { version = "0.11.1"; edition = "2018"; sha256 = "05672ncc54h66vph42s0a42ljl69bwnqjh0x4xgj2v1395psildi"; + libName = "crypto_mac"; authors = [ "RustCrypto Developers" ]; @@ -725,9 +736,10 @@ rec { }; "data-encoding" = rec { crateName = "data-encoding"; - version = "2.4.0"; + version = "2.6.0"; edition = "2018"; - sha256 = "023k3dk8422jgbj7k72g63x51h1mhv91dhw1j4h205vzh6fnrrn2"; + sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -763,6 +775,7 @@ rec { version = "2.0.0"; edition = "2018"; sha256 = "1q9kr151h9681wwp6is18750ssghz6j9j7qm7qi1ngcwy7mzi35r"; + libName = "dirs_next"; authors = [ "The @xdg-rs members" ]; @@ -783,6 +796,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "0kavhavdxv4phzj4l0psvh55hszwnr0rcz8sxbvx20pyqi2a3gaf"; + libName = "dirs_sys_next"; authors = [ "The @xdg-rs members" ]; @@ -807,6 +821,13 @@ rec { ]; }; + "equivalent" = rec { + crateName = "equivalent"; + version = "1.0.1"; + edition = "2015"; + sha256 = "1malmx5f4lkfvqasz319lq6gb3ddg19yzf9s8cykfsgzdmyq0hsl"; + + }; "fnv" = rec { crateName = "fnv"; version = "1.0.7"; @@ -823,9 +844,9 @@ rec { }; "futures" = rec { crateName = "futures"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1c04g14bccmprwsvx2j9m2blhwrynq7vhl151lsvcv4gi0b6jp34"; + sha256 = "0xh8ddbkm9jy8kc5gbvjp9a4b6rqqxvc8471yb2qaz5wm2qhgg35"; dependencies = [ { name = "futures-channel"; @@ -884,9 +905,10 @@ rec { }; "futures-channel" = rec { crateName = "futures-channel"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "0y6b7xxqdjm9hlcjpakcg41qfl7lihf6gavk8fyqijsxhvbzgj7a"; + sha256 = "040vpqpqlbk099razq8lyn74m0f161zd0rp36hciqrwcg2zibzrd"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -911,9 +933,10 @@ rec { }; "futures-core" = rec { crateName = "futures-core"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "07aslayrn3lbggj54kci0ishmd1pr367fp7iks7adia1p05miinz"; + sha256 = "0gk6yrxgi5ihfanm2y431jadrll00n5ifhnpx090c2f2q1cr1wh5"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -923,9 +946,10 @@ rec { }; "futures-executor" = rec { crateName = "futures-executor"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "07dh08gs9vfll2h36kq32q9xd86xm6lyl9xikmmwlkqnmrrgqxm5"; + sha256 = "17vcci6mdfzx4gbk0wx64chr2f13wwwpvyf3xd5fb1gmjzcx2a0y"; + libName = "futures_executor"; dependencies = [ { name = "futures-core"; @@ -953,9 +977,10 @@ rec { }; "futures-io" = rec { crateName = "futures-io"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1hgh25isvsr4ybibywhr4dpys8mjnscw4wfxxwca70cn1gi26im4"; + sha256 = "1ikmw1yfbgvsychmsihdkwa8a1knank2d9a8dk01mbjar9w1np4y"; + libName = "futures_io"; features = { "default" = [ "std" ]; }; @@ -963,10 +988,11 @@ rec { }; "futures-macro" = rec { crateName = "futures-macro"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1b49qh9d402y8nka4q6wvvj0c88qq91wbr192mdn5h54nzs0qxc7"; + sha256 = "0l1n7kqzwwmgiznn0ywdc5i24z72zvh9q1dwps54mimppi7f6bhn"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -986,9 +1012,10 @@ rec { }; "futures-sink" = rec { crateName = "futures-sink"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1dag8xyyaya8n8mh8smx7x6w2dpmafg2din145v973a3hw7f1f4z"; + sha256 = "1xyly6naq6aqm52d5rh236snm08kw8zadydwqz8bip70s6vzlxg5"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -997,9 +1024,10 @@ rec { }; "futures-task" = rec { crateName = "futures-task"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "013h1724454hj8qczp8vvs10qfiqrxr937qsrv6rhii68ahlzn1q"; + sha256 = "124rv4n90f5xwfsm9qw6y99755y021cmi5dhzh253s920z77s3zr"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1008,9 +1036,10 @@ rec { }; "futures-util" = rec { crateName = "futures-util"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "0j0xqhcir1zf2dcbpd421kgw6wvsk0rpxflylcysn1rlp3g02r1x"; + sha256 = "10aa1ar8bgkgbr4wzxlidkqkcxf77gffyj8j7768h831pcaq784z"; + libName = "futures_util"; dependencies = [ { name = "futures-channel"; @@ -1120,9 +1149,9 @@ rec { }; "getrandom" = rec { crateName = "getrandom"; - version = "0.2.11"; + version = "0.2.15"; edition = "2018"; - sha256 = "03q7120cc2kn7ry013i67zmjl2g9q73h1ks5z08hq5v9syz0d47y"; + sha256 = "1mzlnrb3dgyd1fb84gvw10pyr8wdqdl4ry4sr64i1s8an66pqmn4"; authors = [ "The Rand Project Developers" ]; @@ -1156,9 +1185,9 @@ rec { }; "gimli" = rec { crateName = "gimli"; - version = "0.28.0"; + version = "0.31.1"; edition = "2018"; - sha256 = "1h7hcl3chfvd2gfrrxjymnwj7anqxjslvz20kcargkvsya2dgf3g"; + sha256 = "0gvqc0ramx8szv76jhfd4dms0zyamvlg4whhiz11j34hh3dqxqh7"; features = { "default" = [ "read-all" "write" ]; "endian-reader" = [ "read" "dep:stable_deref_trait" ]; @@ -1173,9 +1202,9 @@ rec { }; "h2" = rec { crateName = "h2"; - version = "0.3.21"; + version = "0.3.26"; edition = "2018"; - sha256 = "0cq8g5bgk3fihnqicy3g8gc3dpsalzqjg4bjyip9g4my26m27z4i"; + sha256 = "1s7msnfv7xprzs6xzfj5sg6p8bjcdpcqcmjjbkd345cyi1x55zl1"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -1225,7 +1254,7 @@ rec { { name = "tokio-util"; packageId = "tokio-util"; - features = [ "codec" ]; + features = [ "codec" "io" ]; } { name = "tracing"; @@ -1245,31 +1274,33 @@ rec { }; "hashbrown" = rec { crateName = "hashbrown"; - version = "0.12.3"; + version = "0.15.0"; edition = "2021"; - sha256 = "1268ka4750pyg2pbgsr43f0289l5zah4arir2k4igx5a8c6fg7la"; + sha256 = "1yx4xq091s7i6mw6bn77k8cp4jrpcac149xr32rg8szqsj27y20y"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; features = { - "ahash" = [ "dep:ahash" ]; - "ahash-compile-time-rng" = [ "ahash/compile-time-rng" ]; "alloc" = [ "dep:alloc" ]; - "bumpalo" = [ "dep:bumpalo" ]; + "allocator-api2" = [ "dep:allocator-api2" ]; + "borsh" = [ "dep:borsh" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; - "default" = [ "ahash" "inline-more" ]; + "default" = [ "default-hasher" "inline-more" "allocator-api2" "equivalent" "raw-entry" ]; + "default-hasher" = [ "dep:foldhash" ]; + "equivalent" = [ "dep:equivalent" ]; + "nightly" = [ "allocator-api2?/nightly" "bumpalo/allocator_api" ]; "rayon" = [ "dep:rayon" ]; - "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" ]; + "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" "raw-entry" ]; "serde" = [ "dep:serde" ]; }; - resolvedDefaultFeatures = [ "raw" ]; }; "hermit-abi" = rec { crateName = "hermit-abi"; - version = "0.3.3"; + version = "0.3.9"; edition = "2021"; - sha256 = "1dyc8qsjh876n74a3rcz8h43s27nj1sypdhsn2ms61bd3b47wzyp"; + sha256 = "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -1327,9 +1358,9 @@ rec { }; "http" = rec { crateName = "http"; - version = "0.2.10"; + version = "0.2.12"; edition = "2018"; - sha256 = "0l61nzcb5rdfchn7gpml0wngipflbqarrq3q5ga30rw9msy9lnzr"; + sha256 = "1w81s4bcbmcj9bjp7mllm8jlz6b31wzvirz8bgpzbqkpwmbvn730"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Carl Lerche <me@carllerche.com>" @@ -1353,9 +1384,10 @@ rec { }; "http-body" = rec { crateName = "http-body"; - version = "0.4.5"; + version = "0.4.6"; edition = "2018"; - sha256 = "1l967qwwlvhp198xdrnc0p5d7jwfcp6q2lm510j6zqw4s4b8zwym"; + sha256 = "1lmyjfk6bqk6k9gkn1dxq770sb78pqbqshga241hr5p995bb5skw"; + libName = "http_body"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -1382,6 +1414,7 @@ rec { version = "1.1.3"; edition = "2021"; sha256 = "1vnald3g10gxj15dc5jjjk7aff23p1zly0xgzhn5gwfrb9k0nmkg"; + libName = "http_serde"; authors = [ "Kornel <kornel@geekhood.net>" ]; @@ -1400,9 +1433,9 @@ rec { }; "httparse" = rec { crateName = "httparse"; - version = "1.8.0"; + version = "1.9.5"; edition = "2018"; - sha256 = "010rrfahm1jss3p022fqf3j3jmm72vhn4iqhykahb9ynpaag75yq"; + sha256 = "0ip9v8m9lvgvq1lznl31wvn0ch1v254na7lhid9p29yx9rbx6wbx"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -1423,9 +1456,9 @@ rec { }; "hyper" = rec { crateName = "hyper"; - version = "0.14.27"; + version = "0.14.31"; edition = "2018"; - sha256 = "0s2l74p3harvjgb0bvaxlxgxq71vpfrzv0cqz2p9w8d8akbczcgz"; + sha256 = "11bf6mqcpzi0x2758p7q9zk3m877avzpbiw8nx8v2dd3iwp3024c"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -1479,7 +1512,7 @@ rec { } { name = "socket2"; - packageId = "socket2 0.4.10"; + packageId = "socket2"; optional = true; features = [ "all" ]; } @@ -1533,6 +1566,7 @@ rec { version = "0.23.2"; edition = "2018"; sha256 = "0736s6a32dqr107f943xaz1n05flbinq6l19lq1wsrxkc5g9d20p"; + libName = "hyper_rustls"; dependencies = [ { name = "http"; @@ -1604,9 +1638,10 @@ rec { }; "iana-time-zone" = rec { crateName = "iana-time-zone"; - version = "0.1.58"; + version = "0.1.61"; edition = "2018"; - sha256 = "081vcr8z8ddhl5r1ywif6grnswk01b2ac4nks2bhn8zzdimvh9l3"; + sha256 = "085jjsls330yj1fnwykfzmb2f10zp6l7w4fhq81ng81574ghhpi3"; + libName = "iana_time_zone"; authors = [ "Andrew Straw <strawman@astraw.com>" "René Kijewski <rene.kijewski@fu-berlin.de>" @@ -1631,12 +1666,12 @@ rec { { name = "js-sys"; packageId = "js-sys"; - target = { target, features }: ("wasm32" == target."arch" or null); + target = { target, features }: (("wasm32" == target."arch" or null) && ("unknown" == target."os" or null)); } { name = "wasm-bindgen"; packageId = "wasm-bindgen"; - target = { target, features }: ("wasm32" == target."arch" or null); + target = { target, features }: (("wasm32" == target."arch" or null) && ("unknown" == target."os" or null)); } { name = "windows-core"; @@ -1652,6 +1687,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k"; + libName = "iana_time_zone_haiku"; authors = [ "René Kijewski <crates.io@k6i.de>" ]; @@ -1665,38 +1701,37 @@ rec { }; "indexmap" = rec { crateName = "indexmap"; - version = "1.9.3"; + version = "2.6.0"; edition = "2021"; - sha256 = "16dxmy7yvk51wvnih3a3im6fp5lmx0wx76i03n06wyak6cwhw1xx"; + sha256 = "1nmrwn8lbs19gkvhxaawffzbvrpyrb5y3drcrr645x957kz0fybh"; dependencies = [ { - name = "hashbrown"; - packageId = "hashbrown"; + name = "equivalent"; + packageId = "equivalent"; usesDefaultFeatures = false; - features = [ "raw" ]; } - ]; - buildDependencies = [ { - name = "autocfg"; - packageId = "autocfg"; + name = "hashbrown"; + packageId = "hashbrown"; + usesDefaultFeatures = false; } ]; features = { "arbitrary" = [ "dep:arbitrary" ]; + "borsh" = [ "dep:borsh" ]; + "default" = [ "std" ]; "quickcheck" = [ "dep:quickcheck" ]; "rayon" = [ "dep:rayon" ]; "rustc-rayon" = [ "dep:rustc-rayon" ]; "serde" = [ "dep:serde" ]; - "serde-1" = [ "serde" ]; }; - resolvedDefaultFeatures = [ "std" ]; + resolvedDefaultFeatures = [ "default" "std" ]; }; "itoa" = rec { crateName = "itoa"; - version = "1.0.9"; + version = "1.0.11"; edition = "2018"; - sha256 = "0f6cpb4yqzhkrhhg6kqsw3wnmmhdnnffi6r2xzy248gzi2v0l5dg"; + sha256 = "0nv9cqjwzr3q58qz84dcz63ggc54yhf1yqar1m858m1kfd4g3wa9"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -1706,9 +1741,9 @@ rec { }; "jobserver" = rec { crateName = "jobserver"; - version = "0.1.27"; - edition = "2018"; - sha256 = "0z9w6vfqwbr6hfk9yaw7kydlh6f7k39xdlszxlh39in4acwzcdwc"; + version = "0.1.32"; + edition = "2021"; + sha256 = "1l2k50qmj84x9mn39ivjz76alqmx72jhm12rw33zx9xnpv5xpla8"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -1723,9 +1758,10 @@ rec { }; "js-sys" = rec { crateName = "js-sys"; - version = "0.3.65"; - edition = "2018"; - sha256 = "1s1gaxgzpqfyygc7f2pwp9y128rh5f8zvsc4nm5yazgna9cw7h2l"; + version = "0.3.72"; + edition = "2021"; + sha256 = "1a8r61hbgw5kmscgj3g5pzg2ywlnswvljy0l592v0xdxlayz323a"; + libName = "js_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -1855,9 +1891,9 @@ rec { }; "lazy_static" = rec { crateName = "lazy_static"; - version = "1.4.0"; + version = "1.5.0"; edition = "2015"; - sha256 = "0in6ikhw8mgl33wjv6q6xfrb5b9jr16q8ygjy803fay4zcisvaz2"; + sha256 = "1zk6dqqni0193xg6iijh7i3i44sryglwgvx20spdvwk3r6sbrlmv"; authors = [ "Marvin Löbel <loebel.marvin@gmail.com>" ]; @@ -1868,9 +1904,9 @@ rec { }; "libc" = rec { crateName = "libc"; - version = "0.2.150"; + version = "0.2.161"; edition = "2015"; - sha256 = "0g10n8c830alndgjb8xk1i9kz5z727np90z1z81119pr8d3jmnc9"; + sha256 = "1lc5s3zd0491x9zxrv2kvclai1my1spz950pkkyry4vwh318k54f"; authors = [ "The Rust Project Developers" ]; @@ -1884,37 +1920,35 @@ rec { }; "libredox" = rec { crateName = "libredox"; - version = "0.0.1"; + version = "0.1.3"; edition = "2021"; - sha256 = "1s2fh4ikpp9xl0lsl01pi0n8pw1q9s3ld452vd8qh1v63v537j45"; + sha256 = "139602gzgs0k91zb7dvgj1qh4ynb8g1lbxsswdim18hcb6ykgzy0"; authors = [ "4lDO2 <4lDO2@protonmail.com>" ]; dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.1"; + packageId = "bitflags"; } { name = "libc"; packageId = "libc"; } - { - name = "redox_syscall"; - packageId = "redox_syscall"; - } ]; features = { - "default" = [ "scheme" "call" ]; - "scheme" = [ "call" ]; + "default" = [ "call" "std" "redox_syscall" ]; + "ioslice" = [ "dep:ioslice" ]; + "mkns" = [ "ioslice" ]; + "redox_syscall" = [ "dep:redox_syscall" ]; }; - resolvedDefaultFeatures = [ "call" ]; + resolvedDefaultFeatures = [ "call" "std" ]; }; "lock_api" = rec { crateName = "lock_api"; - version = "0.4.11"; - edition = "2018"; - sha256 = "0iggx0h4jx63xm35861106af3jkxq06fpqhpkhgw0axi2n38y5iw"; + version = "0.4.12"; + edition = "2021"; + sha256 = "05qvxa6g27yyva25a5ghsg85apdxkvr77yhkyhapj6r8vnf8pbq7"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -1940,17 +1974,20 @@ rec { }; "log" = rec { crateName = "log"; - version = "0.4.20"; - edition = "2015"; - sha256 = "13rf7wphnwd61vazpxr7fiycin6cb1g8fmvgqg18i464p0y1drmm"; + version = "0.4.22"; + edition = "2021"; + sha256 = "093vs0wkm1rgyykk7fjbqp2lwizbixac1w52gv109p5r4jh0p9x7"; authors = [ "The Rust Project Developers" ]; features = { - "kv_unstable" = [ "value-bag" ]; - "kv_unstable_serde" = [ "kv_unstable_std" "value-bag/serde" "serde" ]; - "kv_unstable_std" = [ "std" "kv_unstable" "value-bag/error" ]; - "kv_unstable_sval" = [ "kv_unstable" "value-bag/sval" "sval" "sval_ref" ]; + "kv_serde" = [ "kv_std" "value-bag/serde" "serde" ]; + "kv_std" = [ "std" "kv" "value-bag/error" ]; + "kv_sval" = [ "kv" "value-bag/sval" "sval" "sval_ref" ]; + "kv_unstable" = [ "kv" "value-bag" ]; + "kv_unstable_serde" = [ "kv_serde" "kv_unstable_std" ]; + "kv_unstable_std" = [ "kv_std" "kv_unstable" ]; + "kv_unstable_sval" = [ "kv_sval" "kv_unstable" ]; "serde" = [ "dep:serde" ]; "sval" = [ "dep:sval" ]; "sval_ref" = [ "dep:sval_ref" ]; @@ -1960,9 +1997,9 @@ rec { }; "mach2" = rec { crateName = "mach2"; - version = "0.4.1"; + version = "0.4.2"; edition = "2015"; - sha256 = "1s5dbscwk0w6czzvhxp9ix9c2djv4fpnj4za9byaclfiphq1h3bd"; + sha256 = "02gpyq89rcrqdbz4hgp5bpjas21dllxfc70jgw8vj0iaxg6mbf8r"; dependencies = [ { name = "libc"; @@ -1979,6 +2016,7 @@ rec { version = "0.1.1"; edition = "2021"; sha256 = "0bpzcrwq89cc5q8mgkmsyx39vjsqaxvaxs29qp8k04rndc7ysfh0"; + libName = "magic_buffer"; authors = [ "Sebastian Klose <mail@sklose.com>" ]; @@ -1999,7 +2037,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.48.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_System_SystemInformation" "Win32_System_Diagnostics_Debug" "Win32_System_Memory" "Win32_Security" ]; } @@ -2046,9 +2084,9 @@ rec { }; "memchr" = rec { crateName = "memchr"; - version = "2.6.4"; + version = "2.7.4"; edition = "2021"; - sha256 = "0rq1ka8790ns41j147npvxcqcl2anxyngsdimy85ag2api0fwrgn"; + sha256 = "18z32bhxrax0fnjikv475z7ii718hq457qwmaryixfxsl2qrmjkq"; authors = [ "Andrew Gallant <jamslam@gmail.com>" "bluss" @@ -2066,17 +2104,17 @@ rec { }; "miniz_oxide" = rec { crateName = "miniz_oxide"; - version = "0.7.1"; - edition = "2018"; - sha256 = "1ivl3rbbdm53bzscrd01g60l46lz5krl270487d8lhjvwl5hx0g7"; + version = "0.8.0"; + edition = "2021"; + sha256 = "1wadxkg6a6z4lr7kskapj5d8pxlx7cp1ifw4daqnkzqjxych5n72"; authors = [ "Frommi <daniil.liferenko@gmail.com>" "oyvindln <oyvindln@users.noreply.github.com>" ]; dependencies = [ { - name = "adler"; - packageId = "adler"; + name = "adler2"; + packageId = "adler2"; usesDefaultFeatures = false; } ]; @@ -2085,16 +2123,16 @@ rec { "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; "default" = [ "with-alloc" ]; - "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler/rustc-dep-of-std" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler2/rustc-dep-of-std" ]; "simd" = [ "simd-adler32" ]; "simd-adler32" = [ "dep:simd-adler32" ]; }; }; "mio" = rec { crateName = "mio"; - version = "0.8.9"; - edition = "2018"; - sha256 = "1l23hg513c23nhcdzvk25caaj28mic6qgqadbn8axgj6bqf2ikix"; + version = "1.0.2"; + edition = "2021"; + sha256 = "1v1cnnn44awxbcfm4zlavwgkvbyg7gp5zzjm8mqf1apkrwflvq40"; authors = [ "Carl Lerche <me@carllerche.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -2102,6 +2140,12 @@ rec { ]; dependencies = [ { + name = "hermit-abi"; + packageId = "hermit-abi"; + rename = "libc"; + target = { target, features }: ("hermit" == target."os" or null); + } + { name = "libc"; packageId = "libc"; target = { target, features }: ("wasi" == target."os" or null); @@ -2118,9 +2162,9 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); - features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; + features = [ "Wdk_Foundation" "Wdk_Storage_FileSystem" "Wdk_System_IO" "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; } ]; features = { @@ -2135,6 +2179,7 @@ rec { version = "0.46.0"; edition = "2018"; sha256 = "115sywxh53p190lyw97alm14nc004qj5jm5lvdj608z84rbida3p"; + libName = "nu_ansi_term"; authors = [ "ogham@bsago.me" "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>" @@ -2160,9 +2205,10 @@ rec { }; "num-traits" = rec { crateName = "num-traits"; - version = "0.2.17"; - edition = "2018"; - sha256 = "0z16bi5zwgfysz6765v3rd6whfbjpihx3mhsn4dg8dzj2c221qrr"; + version = "0.2.19"; + edition = "2021"; + sha256 = "0h984rhdkkqd4ny9cif7y2azl3xdfb7768hb9irhpsch4q3gq787"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -2177,33 +2223,11 @@ rec { "libm" = [ "dep:libm" ]; }; }; - "num_cpus" = rec { - crateName = "num_cpus"; - version = "1.16.0"; - edition = "2015"; - sha256 = "0hra6ihpnh06dvfvz9ipscys0xfqa9ca9hzp384d5m02ssvgqqa1"; - authors = [ - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "hermit-abi"; - packageId = "hermit-abi"; - target = { target, features }: ("hermit" == target."os" or null); - } - { - name = "libc"; - packageId = "libc"; - target = { target, features }: (!(target."windows" or false)); - } - ]; - - }; "object" = rec { crateName = "object"; - version = "0.32.1"; + version = "0.36.5"; edition = "2018"; - sha256 = "1c02x4kvqpnl3wn7gz9idm4jrbirbycyqjgiw6lm1g9k77fzkxcw"; + sha256 = "0gk8lhbs229c68lapq6w6qmnm4jkj48hrcw5ilfyswy514nhmpxf"; dependencies = [ { name = "memchr"; @@ -2212,13 +2236,15 @@ rec { } ]; features = { - "all" = [ "read" "write" "std" "compression" "wasm" ]; + "all" = [ "read" "write" "build" "std" "compression" "wasm" ]; "alloc" = [ "dep:alloc" ]; + "build" = [ "build_core" "write_std" "elf" ]; + "build_core" = [ "read_core" "write_core" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "compression" = [ "dep:flate2" "dep:ruzstd" "std" ]; "core" = [ "dep:core" ]; "default" = [ "read" "compression" ]; - "doc" = [ "read_core" "write_std" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; + "doc" = [ "read_core" "write_std" "build_core" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; "pe" = [ "coff" ]; "read" = [ "read_core" "archive" "coff" "elf" "macho" "pe" "xcoff" "unaligned" ]; "rustc-dep-of-std" = [ "core" "compiler_builtins" "alloc" "memchr/rustc-dep-of-std" ]; @@ -2229,31 +2255,33 @@ rec { "write_core" = [ "dep:crc32fast" "dep:indexmap" "dep:hashbrown" ]; "write_std" = [ "write_core" "std" "indexmap?/std" "crc32fast?/std" ]; }; - resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" ]; + resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" "xcoff" ]; }; "once_cell" = rec { crateName = "once_cell"; - version = "1.18.0"; + version = "1.20.2"; edition = "2021"; - sha256 = "0vapcd5ambwck95wyz3ymlim35jirgnqn9a0qmi19msymv95v2yx"; + sha256 = "0xb7rw1aqr7pa4z3b00y7786gyf8awx2gca3md73afy76dzgwq8j"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" ]; features = { "alloc" = [ "race" ]; "atomic-polyfill" = [ "critical-section" ]; - "critical-section" = [ "dep:critical-section" "dep:atomic-polyfill" ]; + "critical-section" = [ "dep:critical-section" "portable-atomic" ]; "default" = [ "std" ]; "parking_lot" = [ "dep:parking_lot_core" ]; + "portable-atomic" = [ "dep:portable-atomic" ]; "std" = [ "alloc" ]; }; resolvedDefaultFeatures = [ "alloc" "default" "race" "std" ]; }; "opaque-debug" = rec { crateName = "opaque-debug"; - version = "0.3.0"; + version = "0.3.1"; edition = "2018"; - sha256 = "1m8kzi4nd6shdqimn0mgb24f0hxslhnqd1whakyq06wcqd086jk2"; + sha256 = "10b3w0kydz5jf1ydyli5nv10gdfp97xh79bgz327d273bs46b3f0"; + libName = "opaque_debug"; authors = [ "RustCrypto Developers" ]; @@ -2264,6 +2292,7 @@ rec { version = "0.1.5"; edition = "2015"; sha256 = "1kq18qm48rvkwgcggfkqq6pm948190czqc94d6bm2sir5hq1l0gz"; + libName = "openssl_probe"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -2281,9 +2310,9 @@ rec { }; "parking_lot" = rec { crateName = "parking_lot"; - version = "0.12.1"; - edition = "2018"; - sha256 = "13r2xk7mnxfc5g0g6dkdxqdqad99j7s7z8zhzz4npw5r0g0v4hip"; + version = "0.12.3"; + edition = "2021"; + sha256 = "09ws9g6245iiq8z975h8ycf818a66q3c6zv4b5h8skpm7hc1igzi"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -2308,9 +2337,9 @@ rec { }; "parking_lot_core" = rec { crateName = "parking_lot_core"; - version = "0.9.9"; - edition = "2018"; - sha256 = "13h0imw1aq86wj28gxkblhkzx6z1gk8q18n0v76qmmj6cliajhjc"; + version = "0.9.10"; + edition = "2021"; + sha256 = "1y3cf9ld9ijf7i4igwzffcn0xl16dxyn4c5bwgjck1dkgabiyh0y"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -2335,7 +2364,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets"; + packageId = "windows-targets 0.52.6"; target = { target, features }: (target."windows" or false); } ]; @@ -2348,9 +2377,10 @@ rec { }; "percent-encoding" = rec { crateName = "percent-encoding"; - version = "2.3.0"; + version = "2.3.1"; edition = "2018"; - sha256 = "152slflmparkh27hprw62sph8rv77wckzhwl2dhqk6bf563lfalv"; + sha256 = "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -2362,9 +2392,10 @@ rec { }; "pin-project" = rec { crateName = "pin-project"; - version = "1.1.3"; + version = "1.1.6"; edition = "2021"; - sha256 = "08k4cpy8q3j93qqgnrbzkcgpn7g0a88l4a9nm33kyghpdhffv97x"; + sha256 = "1v4924b870bss0x5ahww9a164d4dbny90vzkmljfbqfxc6hj7wds"; + libName = "pin_project"; dependencies = [ { name = "pin-project-internal"; @@ -2375,10 +2406,11 @@ rec { }; "pin-project-internal" = rec { crateName = "pin-project-internal"; - version = "1.1.3"; + version = "1.1.6"; edition = "2021"; - sha256 = "01a4l3vb84brv9v7wl71chzxra2kynm6yvcjca66xv3ij6fgsna3"; + sha256 = "1y2pjavbcq40njylbnw3929i8nnrcdzrhgalzgqk57ya2n2jsl54"; procMacro = true; + libName = "pin_project_internal"; dependencies = [ { name = "proc-macro2"; @@ -2391,16 +2423,18 @@ rec { { name = "syn"; packageId = "syn"; - features = [ "full" "visit-mut" ]; + usesDefaultFeatures = false; + features = [ "parsing" "printing" "clone-impls" "proc-macro" "full" "visit-mut" ]; } ]; }; "pin-project-lite" = rec { crateName = "pin-project-lite"; - version = "0.2.13"; + version = "0.2.14"; edition = "2018"; - sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + sha256 = "00nx3f04agwjlsmd3mc5rx5haibj2v8q9b52b0kwn63wcv4nz9mx"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -2408,6 +2442,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -2415,9 +2450,10 @@ rec { }; "proc-macro2" = rec { crateName = "proc-macro2"; - version = "1.0.69"; + version = "1.0.88"; edition = "2021"; - sha256 = "1nljgyllbm3yr3pa081bf83gxh6l4zvjqzaldw7v4mj9xfgihk0k"; + sha256 = "1ygjzcawivbziakc6sfc816alabvnp6whlm3g6kxamqyvg2pyfkw"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -2435,9 +2471,9 @@ rec { }; "quote" = rec { crateName = "quote"; - version = "1.0.33"; + version = "1.0.37"; edition = "2018"; - sha256 = "1biw54hbbr12wdwjac55z1m2x2rylciw83qnjn564a3096jgqrsj"; + sha256 = "1brklraw2g34bxy9y4q1nbrccn7bv36ylihv12c9vlcii55x7fdm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -2456,9 +2492,9 @@ rec { }; "redox_syscall" = rec { crateName = "redox_syscall"; - version = "0.4.1"; - edition = "2018"; - sha256 = "1aiifyz5dnybfvkk4cdab9p2kmphag1yad6iknc7aszlxxldf8j7"; + version = "0.5.7"; + edition = "2021"; + sha256 = "07vpgfr6a04k0x19zqr1xdlqm6fncik3zydbdi3f5g3l5k7zwvcv"; libName = "syscall"; authors = [ "Jeremy Soller <jackpot51@gmail.com>" @@ -2466,19 +2502,21 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 1.3.2"; + packageId = "bitflags"; } ]; features = { "core" = [ "dep:core" ]; + "default" = [ "userspace" ]; "rustc-dep-of-std" = [ "core" "bitflags/rustc-dep-of-std" ]; }; + resolvedDefaultFeatures = [ "default" "userspace" ]; }; "redox_users" = rec { crateName = "redox_users"; - version = "0.4.4"; + version = "0.4.6"; edition = "2021"; - sha256 = "1d1c7dhbb62sh8jrq9dhvqcyxqsh3wg8qknsi94iwq3r0wh7k151"; + sha256 = "0hya2cxx6hxmjfxzv9n8rjl5igpychav7zfi1f81pz6i4krry05s"; authors = [ "Jose Narvaez <goyox86@gmail.com>" "Wesley Hershberger <mggmugginsmc@gmail.com>" @@ -2493,7 +2531,7 @@ rec { name = "libredox"; packageId = "libredox"; usesDefaultFeatures = false; - features = [ "call" ]; + features = [ "std" "call" ]; } { name = "thiserror"; @@ -2586,17 +2624,22 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "dev_urandom_fallback" "once_cell" ]; }; - "ring 0.17.5" = rec { + "ring 0.17.8" = rec { crateName = "ring"; - version = "0.17.5"; + version = "0.17.8"; edition = "2021"; - links = "ring_core_0_17_5"; - sha256 = "02sd768l7594rm3jw048z7kkml7zcyw4ir62p6cxirap8wq0a0pv"; + links = "ring_core_0_17_8"; + sha256 = "03fwlb1ssrmfxdckvqv033pfmk01rhx9ynwi7r186dcfcp5s8zy1"; authors = [ "Brian Smith <brian@briansmith.org>" ]; dependencies = [ { + name = "cfg-if"; + packageId = "cfg-if"; + usesDefaultFeatures = false; + } + { name = "getrandom"; packageId = "getrandom"; } @@ -2604,13 +2647,13 @@ rec { name = "libc"; packageId = "libc"; usesDefaultFeatures = false; - target = { target, features }: (("android" == target."os" or null) || ("linux" == target."os" or null)); + target = { target, features }: ((("android" == target."os" or null) || ("linux" == target."os" or null)) && (("aarch64" == target."arch" or null) || ("arm" == target."arch" or null))); } { name = "spin"; packageId = "spin 0.9.8"; usesDefaultFeatures = false; - target = { target, features }: (("x86" == target."arch" or null) || ("x86_64" == target."arch" or null) || ((("aarch64" == target."arch" or null) || ("arm" == target."arch" or null)) && (("android" == target."os" or null) || ("fuchsia" == target."os" or null) || ("linux" == target."os" or null) || ("windows" == target."os" or null)))); + target = { target, features }: (("aarch64" == target."arch" or null) || ("arm" == target."arch" or null) || ("x86" == target."arch" or null) || ("x86_64" == target."arch" or null)); features = [ "once" ]; } { @@ -2619,7 +2662,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (("aarch64" == target."arch" or null) && ("windows" == target."os" or null)); features = [ "Win32_Foundation" "Win32_System_Threading" ]; } @@ -2973,9 +3016,10 @@ rec { }; "rustc-demangle" = rec { crateName = "rustc-demangle"; - version = "0.1.23"; + version = "0.1.24"; edition = "2015"; - sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + sha256 = "07zysaafgrkzy2rjgwqdj2a8qdpsm6zv6f5pgpk9x0lm40z9b6vi"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -2987,13 +3031,9 @@ rec { }; "rustc_version" = rec { crateName = "rustc_version"; - version = "0.4.0"; + version = "0.4.1"; edition = "2018"; - sha256 = "0rpk9rcdk405xhbmgclsh4pai0svn49x35aggl4nhbkd4a2zb85z"; - authors = [ - "Dirkjan Ochtman <dirkjan@ochtman.nl>" - "Marvin Löbel <loebel.marvin@gmail.com>" - ]; + sha256 = "14lvdsmr5si5qbqzrajgb6vfn69k0sfygrvfvr2mps26xwi3mjyg"; dependencies = [ { name = "semver"; @@ -3047,6 +3087,7 @@ rec { version = "0.6.3"; edition = "2021"; sha256 = "007zind70rd5rfsrkdcfm8vn09j8sg02phg9334kark6rdscxam9"; + libName = "rustls_native_certs"; dependencies = [ { name = "openssl-probe"; @@ -3075,19 +3116,20 @@ rec { version = "1.0.4"; edition = "2018"; sha256 = "1324n5bcns0rnw6vywr5agff3rwfvzphi7rmbyzwnv6glkhclx0w"; + libName = "rustls_pemfile"; dependencies = [ { name = "base64"; - packageId = "base64 0.21.5"; + packageId = "base64 0.21.7"; } ]; }; "ryu" = rec { crateName = "ryu"; - version = "1.0.15"; + version = "1.0.18"; edition = "2018"; - sha256 = "0hfphpn1xnpzxwj8qg916ga1lyc33lc03lnf1gb3wwpglj6wrm0s"; + sha256 = "17xx2s8j1lln7iackzd9p0sv546vjq71i779gphjq923vjh5pjzk"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3097,9 +3139,9 @@ rec { }; "schannel" = rec { crateName = "schannel"; - version = "0.1.22"; + version = "0.1.26"; edition = "2018"; - sha256 = "126zy5jb95fc5hvzyjwiq6lc81r08rdcn6affn00ispp9jzk6dqc"; + sha256 = "1hfip5mdwqcfnmrnkrq9d8zwy6bssmf6rfm2441nk83ghbjpn8h1"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Steffen Butzer <steffen.butzer@outlook.com>" @@ -3107,14 +3149,14 @@ rec { dependencies = [ { name = "windows-sys"; - packageId = "windows-sys"; - features = [ "Win32_Foundation" "Win32_Security_Cryptography" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_System_Memory" ]; + packageId = "windows-sys 0.59.0"; + features = [ "Win32_Foundation" "Win32_Security_Cryptography" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_System_LibraryLoader" "Win32_System_Memory" "Win32_System_SystemInformation" ]; } ]; devDependencies = [ { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.59.0"; features = [ "Win32_System_SystemInformation" "Win32_System_Time" ]; } ]; @@ -3143,7 +3185,7 @@ rec { dependencies = [ { name = "ring"; - packageId = "ring 0.17.5"; + packageId = "ring 0.17.8"; } { name = "untrusted"; @@ -3154,9 +3196,10 @@ rec { }; "security-framework" = rec { crateName = "security-framework"; - version = "2.9.2"; + version = "2.11.1"; edition = "2021"; - sha256 = "1pplxk15s5yxvi2m1sz5xfmjibp96cscdcl432w9jzbk0frlzdh5"; + sha256 = "00ldclwx78dm61v7wkach9lcx76awlrv0fdgjdwch4dmy12j4yw9"; + libName = "security_framework"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -3164,7 +3207,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 1.3.2"; + packageId = "bitflags"; } { name = "core-foundation"; @@ -3192,17 +3235,18 @@ rec { "OSX_10_14" = [ "OSX_10_13" "security-framework-sys/OSX_10_14" ]; "OSX_10_15" = [ "OSX_10_14" "security-framework-sys/OSX_10_15" ]; "OSX_10_9" = [ "security-framework-sys/OSX_10_9" ]; - "default" = [ "OSX_10_9" ]; + "default" = [ "OSX_10_12" ]; "log" = [ "dep:log" ]; "serial-number-bigint" = [ "dep:num-bigint" ]; }; - resolvedDefaultFeatures = [ "OSX_10_9" "default" ]; + resolvedDefaultFeatures = [ "OSX_10_10" "OSX_10_11" "OSX_10_12" "OSX_10_9" "default" ]; }; "security-framework-sys" = rec { crateName = "security-framework-sys"; - version = "2.9.1"; + version = "2.12.0"; edition = "2021"; - sha256 = "0yhciwlsy9dh0ps1gw3197kvyqx1bvc4knrhiznhid6kax196cp9"; + sha256 = "1dml0lp9lrvvi01s011lyss5kzzsmakaamdwsxr0431jd4l2jjpa"; + libName = "security_framework_sys"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -3224,15 +3268,15 @@ rec { "OSX_10_13" = [ "OSX_10_12" ]; "OSX_10_14" = [ "OSX_10_13" ]; "OSX_10_15" = [ "OSX_10_14" ]; - "default" = [ "OSX_10_9" ]; + "default" = [ "OSX_10_12" ]; }; - resolvedDefaultFeatures = [ "OSX_10_9" ]; + resolvedDefaultFeatures = [ "OSX_10_10" "OSX_10_11" "OSX_10_12" "OSX_10_9" ]; }; "semver" = rec { crateName = "semver"; - version = "1.0.20"; + version = "1.0.23"; edition = "2018"; - sha256 = "140hmbfa743hbmah1zjf07s8apavhvn04204qjigjiz5w6iscvw3"; + sha256 = "12wqpxfflclbq4dv8sa6gchdh92ahhwn4ci1ls22wlby3h57wsb1"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3244,9 +3288,9 @@ rec { }; "serde" = rec { crateName = "serde"; - version = "1.0.192"; + version = "1.0.210"; edition = "2018"; - sha256 = "00ghhaabyrnr2cn504lckyqzh3fwr8k7pxnhhardr1djhj2a18mw"; + sha256 = "0flc0z8wgax1k4j5bf2zyq48bgzyv425jkd5w0i6wbh7f8j5kqy8"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -3278,9 +3322,9 @@ rec { }; "serde_derive" = rec { crateName = "serde_derive"; - version = "1.0.192"; + version = "1.0.210"; edition = "2015"; - sha256 = "1hgvm47ffd748sx22z1da7mgcfjmpr60gqzkff0a9yn9przj1iyn"; + sha256 = "07yzy4wafk79ps0hmbqmsqh5xjna4pm4q57wc847bb8gl3nh4f94"; procMacro = true; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" @@ -3290,14 +3334,20 @@ rec { { name = "proc-macro2"; packageId = "proc-macro2"; + usesDefaultFeatures = false; + features = [ "proc-macro" ]; } { name = "quote"; packageId = "quote"; + usesDefaultFeatures = false; + features = [ "proc-macro" ]; } { name = "syn"; packageId = "syn"; + usesDefaultFeatures = false; + features = [ "clone-impls" "derive" "parsing" "printing" "proc-macro" ]; } ]; features = { }; @@ -3305,9 +3355,9 @@ rec { }; "serde_json" = rec { crateName = "serde_json"; - version = "1.0.108"; + version = "1.0.129"; edition = "2021"; - sha256 = "0ssj59s7lpzqh1m50kfzlnrip0p0jg9lmhn4098i33a0mhz7w71x"; + sha256 = "1clyy0g51mdr7hwxs7qhin2lna8jvlvqhf0rmrkycphjiavzkg3d"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -3318,6 +3368,11 @@ rec { packageId = "itoa"; } { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + { name = "ryu"; packageId = "ryu"; } @@ -3339,15 +3394,15 @@ rec { "default" = [ "std" ]; "indexmap" = [ "dep:indexmap" ]; "preserve_order" = [ "indexmap" "std" ]; - "std" = [ "serde/std" ]; + "std" = [ "memchr/std" "serde/std" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; "serde_path_to_error" = rec { crateName = "serde_path_to_error"; - version = "0.1.14"; + version = "0.1.16"; edition = "2021"; - sha256 = "0dc31z4bg0jwn69gcqsczbmcy5y4w6r0vdcc4c38vma9x2ycivjb"; + sha256 = "19hlz2359l37ifirskpcds7sxg0gzpqvfilibs7whdys0128i6dg"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3415,6 +3470,7 @@ rec { version = "0.1.7"; edition = "2018"; sha256 = "1xipjr4nqsgw34k7a2cgj9zaasl2ds6jwn89886kww93d32a637l"; + libName = "sharded_slab"; authors = [ "Eliza Weisman <eliza@buoyant.io>" ]; @@ -3430,12 +3486,16 @@ rec { }; "shlex" = rec { crateName = "shlex"; - version = "1.2.0"; + version = "1.3.0"; edition = "2015"; - sha256 = "1033pj9dyb76nm5yv597nnvj3zpvr2aw9rm5wy0gah3dk99f1km7"; + sha256 = "0r1y6bv26c1scpxvhg2cabimrmwgbp4p3wy6syj9n0c4s3q2znhg"; authors = [ "comex <comexk@gmail.com>" "Fenhl <fenhl@fenhl.net>" + "Adrian Taylor <adetaylor@chromium.org>" + "Alex Touchet <alextouchet@outlook.com>" + "Daniel Parks <dp+git@oxidized.org>" + "Garrett Berg <googberg@gmail.com>" ]; features = { "default" = [ "std" ]; @@ -3444,9 +3504,10 @@ rec { }; "signal-hook-registry" = rec { crateName = "signal-hook-registry"; - version = "1.4.1"; + version = "1.4.2"; edition = "2015"; - sha256 = "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq"; + sha256 = "1cb5akgq8ajnd5spyn587srvs4n26ryq0p78nswffwhv46sf1sd9"; + libName = "signal_hook_registry"; authors = [ "Michal 'vorner' Vaner <vorner@vorner.cz>" "Masaki Hara <ackie.h.gmai@gmail.com>" @@ -3481,9 +3542,9 @@ rec { }; "smallvec" = rec { crateName = "smallvec"; - version = "1.11.2"; + version = "1.13.2"; edition = "2018"; - sha256 = "0w79x38f7c0np7hqfmzrif9zmn0avjvvm31b166zdk9d1aad1k2d"; + sha256 = "0rsw5samawl3wsw6glrsb127rx6sh89a8wyikicw6dkdcjd1lpiw"; authors = [ "The Servo Project Developers" ]; @@ -3494,36 +3555,11 @@ rec { "serde" = [ "dep:serde" ]; }; }; - "socket2 0.4.10" = rec { + "socket2" = rec { crateName = "socket2"; - version = "0.4.10"; - edition = "2018"; - sha256 = "03ack54dxhgfifzsj14k7qa3r5c9wqy3v6mqhlim99cc03y1cycz"; - authors = [ - "Alex Crichton <alex@alexcrichton.com>" - "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" - ]; - dependencies = [ - { - name = "libc"; - packageId = "libc"; - target = { target, features }: (target."unix" or false); - } - { - name = "winapi"; - packageId = "winapi"; - target = { target, features }: (target."windows" or false); - features = [ "handleapi" "ws2ipdef" "ws2tcpip" ]; - } - ]; - features = { }; - resolvedDefaultFeatures = [ "all" ]; - }; - "socket2 0.5.5" = rec { - crateName = "socket2"; - version = "0.5.5"; + version = "0.5.7"; edition = "2021"; - sha256 = "1sgq315f1njky114ip7wcy83qlphv9qclprfjwvxcpfblmcsqpvv"; + sha256 = "070r941wbq76xpy039an4pyiy3rfj7mp7pvibf1rcri9njq5wc6f"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -3536,7 +3572,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_System_IO" "Win32_System_Threading" "Win32_System_WindowsProgramming" ]; } @@ -3595,9 +3631,9 @@ rec { }; "syn" = rec { crateName = "syn"; - version = "2.0.39"; + version = "2.0.79"; edition = "2021"; - sha256 = "0ymyhxnk1yi4pzf72qk3lrdm9lgjwcrcwci0hhz5vx7wya88prr3"; + sha256 = "147mk4sgigmvsb9l8qzj199ygf0fgb0bphwdsghn8205pz82q4w9"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3620,18 +3656,17 @@ rec { ]; features = { "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; - "printing" = [ "quote" ]; - "proc-macro" = [ "proc-macro2/proc-macro" "quote/proc-macro" ]; - "quote" = [ "dep:quote" ]; + "printing" = [ "dep:quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; "test" = [ "syn-test-suite/all-features" ]; }; - resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit" "visit-mut" ]; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; }; "thiserror" = rec { crateName = "thiserror"; - version = "1.0.50"; + version = "1.0.64"; edition = "2021"; - sha256 = "1ll2sfbrxks8jja161zh1pgm3yssr7aawdmaa2xmcwcsbh7j39zr"; + sha256 = "114s8lmssxl0c2480s671am88vzlasbaikxbvfv8pyqrq6mzh2nm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3645,10 +3680,11 @@ rec { }; "thiserror-impl" = rec { crateName = "thiserror-impl"; - version = "1.0.50"; + version = "1.0.64"; edition = "2021"; - sha256 = "1f0lmam4765sfnwr4b1n00y14vxh10g0311mkk0adr80pi02wsr6"; + sha256 = "1hvzmjx9iamln854l74qyhs0jl2pg3hhqzpqm9p8gszmf9v4x408"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3670,9 +3706,9 @@ rec { }; "thread_local" = rec { crateName = "thread_local"; - version = "1.1.7"; + version = "1.1.8"; edition = "2021"; - sha256 = "0lp19jdgvp5m4l60cgxdnl00yw1hlqy8gcywg9bddwng9h36zp9z"; + sha256 = "173i5lyjh011gsimk21np9jn8al18rxsrkjli20a7b8ks2xgk7lb"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -3690,9 +3726,9 @@ rec { }; "tokio" = rec { crateName = "tokio"; - version = "1.34.0"; + version = "1.40.0"; edition = "2021"; - sha256 = "1fgmssdga42a2hn9spm9dh1v9ajpcbs4r3svmzvk9s0iciv19h6h"; + sha256 = "166rllhfkyqp0fs7sxn6crv74iizi4wzd3cvxkcpmlk52qip1c72"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3720,11 +3756,6 @@ rec { usesDefaultFeatures = false; } { - name = "num_cpus"; - packageId = "num_cpus"; - optional = true; - } - { name = "parking_lot"; packageId = "parking_lot"; optional = true; @@ -3741,7 +3772,7 @@ rec { } { name = "socket2"; - packageId = "socket2 0.5.5"; + packageId = "socket2"; optional = true; target = { target, features }: (!(builtins.elem "wasm" target."family")); features = [ "all" ]; @@ -3753,7 +3784,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.52.0"; optional = true; target = { target, features }: (target."windows" or false); } @@ -3766,12 +3797,12 @@ rec { } { name = "socket2"; - packageId = "socket2 0.5.5"; + packageId = "socket2"; target = { target, features }: (!(builtins.elem "wasm" target."family")); } { name = "windows-sys"; - packageId = "windows-sys"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Security_Authorization" ]; } @@ -3784,10 +3815,9 @@ rec { "macros" = [ "tokio-macros" ]; "mio" = [ "dep:mio" ]; "net" = [ "libc" "mio/os-poll" "mio/os-ext" "mio/net" "socket2" "windows-sys/Win32_Foundation" "windows-sys/Win32_Security" "windows-sys/Win32_Storage_FileSystem" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_System_SystemServices" ]; - "num_cpus" = [ "dep:num_cpus" ]; "parking_lot" = [ "dep:parking_lot" ]; "process" = [ "bytes" "libc" "mio/os-poll" "mio/os-ext" "mio/net" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Threading" "windows-sys/Win32_System_WindowsProgramming" ]; - "rt-multi-thread" = [ "num_cpus" "rt" ]; + "rt-multi-thread" = [ "rt" ]; "signal" = [ "libc" "mio/os-poll" "mio/net" "mio/os-ext" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Console" ]; "signal-hook-registry" = [ "dep:signal-hook-registry" ]; "socket2" = [ "dep:socket2" ]; @@ -3796,14 +3826,15 @@ rec { "tracing" = [ "dep:tracing" ]; "windows-sys" = [ "dep:windows-sys" ]; }; - resolvedDefaultFeatures = [ "bytes" "default" "fs" "full" "io-std" "io-util" "libc" "macros" "mio" "net" "num_cpus" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "time" "tokio-macros" "windows-sys" ]; + resolvedDefaultFeatures = [ "bytes" "default" "fs" "full" "io-std" "io-util" "libc" "macros" "mio" "net" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "time" "tokio-macros" "windows-sys" ]; }; "tokio-macros" = rec { crateName = "tokio-macros"; - version = "2.2.0"; + version = "2.4.0"; edition = "2021"; - sha256 = "0fwjy4vdx1h9pi4g2nml72wi0fr27b5m954p13ji9anyy8l1x2jv"; + sha256 = "0lnpg14h1v3fh2jvnc8cz7cjf0m7z1xgkwfpcyy632g829imjgb9"; procMacro = true; + libName = "tokio_macros"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3829,6 +3860,7 @@ rec { version = "0.23.4"; edition = "2018"; sha256 = "0nfsmmi8l1lgpbfy6079d5i13984djzcxrdr9jc06ghi0cwyhgn4"; + libName = "tokio_rustls"; authors = [ "quininer kel <quininer@live.com>" ]; @@ -3864,9 +3896,10 @@ rec { }; "tokio-stream" = rec { crateName = "tokio-stream"; - version = "0.1.14"; + version = "0.1.16"; edition = "2021"; - sha256 = "0hi8hcwavh5sdi1ivc9qc4yvyr32f153c212dpd7sb366y6rhz1r"; + sha256 = "1wc65gprcsyzqlr0k091glswy96kph90i32gffi4ksyh03hnqkjg"; + libName = "tokio_stream"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3907,9 +3940,10 @@ rec { }; "tokio-util" = rec { crateName = "tokio-util"; - version = "0.7.10"; + version = "0.7.12"; edition = "2021"; - sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + sha256 = "0spc0g4irbnf2flgag22gfii87avqzibwfm0si0d1g0k9ijw7rv1"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3935,13 +3969,6 @@ rec { packageId = "tokio"; features = [ "sync" ]; } - { - name = "tracing"; - packageId = "tracing"; - optional = true; - usesDefaultFeatures = false; - features = [ "std" ]; - } ]; devDependencies = [ { @@ -3952,7 +3979,6 @@ rec { ]; features = { "__docs_rs" = [ "futures-util" ]; - "codec" = [ "tracing" ]; "compat" = [ "futures-io" ]; "full" = [ "codec" "compat" "io-util" "time" "net" "rt" ]; "futures-io" = [ "dep:futures-io" ]; @@ -3965,7 +3991,7 @@ rec { "time" = [ "tokio/time" "slab" ]; "tracing" = [ "dep:tracing" ]; }; - resolvedDefaultFeatures = [ "codec" "default" "tracing" ]; + resolvedDefaultFeatures = [ "codec" "default" "io" ]; }; "tower" = rec { crateName = "tower"; @@ -4057,9 +4083,10 @@ rec { }; "tower-layer" = rec { crateName = "tower-layer"; - version = "0.3.2"; + version = "0.3.3"; edition = "2018"; - sha256 = "1l7i17k9vlssrdg4s3b0ia5jjkmmxsvv8s9y9ih0jfi8ssz8s362"; + sha256 = "03kq92fdzxin51w8iqix06dcfgydyvx7yr6izjq0p626v9n2l70j"; + libName = "tower_layer"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -4067,9 +4094,10 @@ rec { }; "tower-service" = rec { crateName = "tower-service"; - version = "0.3.2"; + version = "0.3.3"; edition = "2018"; - sha256 = "0lmfzmmvid2yp2l36mbavhmqgsvzqf7r2wiwz73ml4xmwaf1rg5n"; + sha256 = "1hzfkvkci33ra94xjx64vv3pp0sq346w06fpkcdwjcid7zhvdycd"; + libName = "tower_service"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -4128,6 +4156,7 @@ rec { edition = "2018"; sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; procMacro = true; + libName = "tracing_attributes"; authors = [ "Tokio Contributors <team@tokio.rs>" "Eliza Weisman <eliza@buoyant.io>" @@ -4156,6 +4185,7 @@ rec { version = "0.1.32"; edition = "2018"; sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -4183,9 +4213,10 @@ rec { }; "tracing-log" = rec { crateName = "tracing-log"; - version = "0.1.4"; + version = "0.2.0"; edition = "2018"; - sha256 = "1wmxawaz94sk52i4vs2wg5d5clyks972rqskrvc93rxl14ki2lgp"; + sha256 = "1hs77z026k730ij1a9dhahzrl0s073gfa2hm5p0fbl0b80gmz1gf"; + libName = "tracing_log"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -4205,8 +4236,7 @@ rec { ]; features = { "ahash" = [ "dep:ahash" ]; - "default" = [ "log-tracer" "trace-logger" "std" ]; - "env_logger" = [ "dep:env_logger" ]; + "default" = [ "log-tracer" "std" ]; "interest-cache" = [ "lru" "ahash" ]; "lru" = [ "dep:lru" ]; "std" = [ "log/std" ]; @@ -4218,6 +4248,7 @@ rec { version = "0.1.3"; edition = "2018"; sha256 = "1qfr0va69djvxqvjrx4vqq7p6myy414lx4w1f6amcn0hfwqj2sxw"; + libName = "tracing_serde"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -4239,9 +4270,10 @@ rec { }; "tracing-subscriber" = rec { crateName = "tracing-subscriber"; - version = "0.3.17"; + version = "0.3.18"; edition = "2018"; - sha256 = "0xvwfpmb943hdy4gzyn7a2azgigf30mfd1kx10gyh5gr6yy539ih"; + sha256 = "12vs1bwk4kig1l2qqjbbn2nm5amwiqmkcmnznylzmnfvjy6083xd"; + libName = "tracing_subscriber"; authors = [ "Eliza Weisman <eliza@buoyant.io>" "David Barsky <me@davidbarsky.com>" @@ -4304,6 +4336,7 @@ rec { ]; features = { "ansi" = [ "fmt" "nu-ansi-term" ]; + "chrono" = [ "dep:chrono" ]; "default" = [ "smallvec" "fmt" "ansi" "tracing-log" "std" ]; "env-filter" = [ "matchers" "regex" "once_cell" "tracing" "std" "thread_local" ]; "fmt" = [ "registry" "std" ]; @@ -4333,9 +4366,10 @@ rec { }; "try-lock" = rec { crateName = "try-lock"; - version = "0.2.4"; + version = "0.2.5"; edition = "2015"; - sha256 = "1vc15paa4zi06ixsxihwbvfn24d708nsyg1ncgqwcrn42byyqa1m"; + sha256 = "0jqijrrvm1pyq34zn1jmy2vihd4jcrjlvsh4alkjahhssjnsn8g4"; + libName = "try_lock"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -4352,12 +4386,7 @@ rec { requiredFeatures = [ ]; } ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./.; } - else ./.; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./.; }; dependencies = [ { name = "aws_lambda_events"; @@ -4459,9 +4488,10 @@ rec { }; "unicode-ident" = rec { crateName = "unicode-ident"; - version = "1.0.12"; + version = "1.0.13"; edition = "2018"; - sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + sha256 = "1zm1xylzsdfvm2a5ib9li3g5pp7qnkv4amhspydvgbmd9k6mc6z9"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -4503,9 +4533,9 @@ rec { }; "version_check" = rec { crateName = "version_check"; - version = "0.9.4"; + version = "0.9.5"; edition = "2015"; - sha256 = "0gs8grwdlgh0xq660d7wr80x14vxbizmd8dbp29p2pdncx8lp1s9"; + sha256 = "0nhhi4i5x89gm911azqbn7avs9mdacw2i3vcz3cnmz3mv4rqz4hb"; authors = [ "Sergio Benitez <sb@sergio.bz>" ]; @@ -4546,9 +4576,10 @@ rec { }; "wasm-bindgen" = rec { crateName = "wasm-bindgen"; - version = "0.2.88"; - edition = "2018"; - sha256 = "1khgsh4z9bga35mjhg41dl7523i69ffc5m8ckhqaw6ssyabc5bkx"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0bpbvmxhil380gpv53smaypl8wc7sy7rq8apxfw349pn78v1x38j"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -4558,6 +4589,10 @@ rec { packageId = "cfg-if"; } { + name = "once_cell"; + packageId = "once_cell"; + } + { name = "wasm-bindgen-macro"; packageId = "wasm-bindgen-macro"; } @@ -4565,7 +4600,6 @@ rec { features = { "default" = [ "spans" "std" ]; "enable-interning" = [ "std" ]; - "gg-alloc" = [ "wasm-bindgen-test/gg-alloc" ]; "serde" = [ "dep:serde" ]; "serde-serialize" = [ "serde" "serde_json" "std" ]; "serde_json" = [ "dep:serde_json" ]; @@ -4577,9 +4611,10 @@ rec { }; "wasm-bindgen-backend" = rec { crateName = "wasm-bindgen-backend"; - version = "0.2.88"; - edition = "2018"; - sha256 = "05zj8yl243rvs87rhicq2l1d6443lnm6k90khf744khf9ikg95z3"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0n53wgy78bgzgjwk0z69zbspzhv8p2a4zh69s4fzvpqdrb9x8vfb"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -4621,10 +4656,11 @@ rec { }; "wasm-bindgen-macro" = rec { crateName = "wasm-bindgen-macro"; - version = "0.2.88"; - edition = "2018"; - sha256 = "1chn3wgw9awmvs0fpmazbqyc5rwfgy3pj7lzwczmzb887dxh2qar"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0mic8b2vab1a91m6x3hjxkwz23094bq1cwhnszarsnlggyz894z7"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -4646,9 +4682,10 @@ rec { }; "wasm-bindgen-macro-support" = rec { crateName = "wasm-bindgen-macro-support"; - version = "0.2.88"; - edition = "2018"; - sha256 = "01rrzg3y1apqygsjz1jg0n7p831nm4kdyxmxyl85x7v6mf6kndf5"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0s7g6glb85lyx2pj83shbmg4d50mvqhb2c2qk2j28yigaxbspii6"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -4664,7 +4701,7 @@ rec { { name = "syn"; packageId = "syn"; - features = [ "visit" "full" ]; + features = [ "visit" "visit-mut" "full" ]; } { name = "wasm-bindgen-backend"; @@ -4683,10 +4720,11 @@ rec { }; "wasm-bindgen-shared" = rec { crateName = "wasm-bindgen-shared"; - version = "0.2.88"; - edition = "2018"; + version = "0.2.95"; + edition = "2021"; links = "wasm_bindgen"; - sha256 = "02vmw2rzsla1qm0zgfng4kqz52xn8k54v8ads4g1macv09fnq10d"; + sha256 = "1386q7mvv5ky003hcc6yyxpid3y1m7fy0l920i3z3ab60vqhkz35"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -4694,9 +4732,10 @@ rec { }; "web-sys" = rec { crateName = "web-sys"; - version = "0.3.65"; - edition = "2018"; - sha256 = "11ba406ca9qssc21c37v49sn2y2gsdn6c3nva4hjf8v3yv2rkd2x"; + version = "0.3.72"; + edition = "2021"; + sha256 = "04k19hilj9r8sx6q20fz853149gfpmf83yk2zvq0s14c2288nj7n"; + libName = "web_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -4807,8 +4846,6 @@ rec { "FontFaceSet" = [ "EventTarget" ]; "FontFaceSetLoadEvent" = [ "Event" ]; "GainNode" = [ "AudioNode" "EventTarget" ]; - "GamepadAxisMoveEvent" = [ "Event" "GamepadEvent" ]; - "GamepadButtonEvent" = [ "Event" "GamepadEvent" ]; "GamepadEvent" = [ "Event" ]; "GpuDevice" = [ "EventTarget" ]; "GpuInternalError" = [ "GpuError" ]; @@ -4908,7 +4945,9 @@ rec { "IirFilterNode" = [ "AudioNode" "EventTarget" ]; "ImageCaptureErrorEvent" = [ "Event" ]; "ImageTrack" = [ "EventTarget" ]; + "InputDeviceInfo" = [ "MediaDeviceInfo" ]; "InputEvent" = [ "Event" "UiEvent" ]; + "KeyFrameRequestEvent" = [ "Event" ]; "KeyboardEvent" = [ "Event" "UiEvent" ]; "KeyframeEffect" = [ "AnimationEffect" ]; "LocalMediaStream" = [ "EventTarget" "MediaStream" ]; @@ -4979,10 +5018,15 @@ rec { "RtcDataChannel" = [ "EventTarget" ]; "RtcDataChannelEvent" = [ "Event" ]; "RtcPeerConnection" = [ "EventTarget" ]; + "RtcPeerConnectionIceErrorEvent" = [ "Event" ]; "RtcPeerConnectionIceEvent" = [ "Event" ]; + "RtcRtpScriptTransformer" = [ "EventTarget" ]; "RtcTrackEvent" = [ "Event" ]; + "RtcTransformEvent" = [ "Event" ]; "RtcdtmfSender" = [ "EventTarget" ]; "RtcdtmfToneChangeEvent" = [ "Event" ]; + "SFrameTransform" = [ "EventTarget" ]; + "SFrameTransformErrorEvent" = [ "Event" ]; "Screen" = [ "EventTarget" ]; "ScreenOrientation" = [ "EventTarget" ]; "ScriptProcessorNode" = [ "AudioNode" "EventTarget" ]; @@ -5112,6 +5156,7 @@ rec { "TextTrackCue" = [ "EventTarget" ]; "TextTrackList" = [ "EventTarget" ]; "TimeEvent" = [ "Event" ]; + "ToggleEvent" = [ "Event" ]; "TouchEvent" = [ "Event" "UiEvent" ]; "TrackEvent" = [ "Event" ]; "TransitionEvent" = [ "Event" ]; @@ -5123,6 +5168,7 @@ rec { "ValueEvent" = [ "Event" ]; "VideoStreamTrack" = [ "EventTarget" "MediaStreamTrack" ]; "VideoTrackList" = [ "EventTarget" ]; + "VisualViewport" = [ "EventTarget" ]; "VrDisplay" = [ "EventTarget" ]; "VttCue" = [ "EventTarget" "TextTrackCue" ]; "WakeLockSentinel" = [ "EventTarget" ]; @@ -5172,7 +5218,7 @@ rec { dependencies = [ { name = "ring"; - packageId = "ring 0.17.5"; + packageId = "ring 0.17.8"; usesDefaultFeatures = false; } { @@ -5198,24 +5244,25 @@ rec { { name = "winapi-i686-pc-windows-gnu"; packageId = "winapi-i686-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "i686-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnu"); } { name = "winapi-x86_64-pc-windows-gnu"; packageId = "winapi-x86_64-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnu"); } ]; features = { "debug" = [ "impl-debug" ]; }; - resolvedDefaultFeatures = [ "consoleapi" "errhandlingapi" "fileapi" "handleapi" "knownfolders" "ntsecapi" "objbase" "processenv" "shlobj" "winbase" "winerror" "ws2ipdef" "ws2tcpip" "wtypesbase" ]; + resolvedDefaultFeatures = [ "consoleapi" "errhandlingapi" "fileapi" "handleapi" "knownfolders" "ntsecapi" "objbase" "processenv" "shlobj" "winbase" "winerror" "wtypesbase" ]; }; "winapi-i686-pc-windows-gnu" = rec { crateName = "winapi-i686-pc-windows-gnu"; version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -5226,6 +5273,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -5233,33 +5281,35 @@ rec { }; "windows-core" = rec { crateName = "windows-core"; - version = "0.51.1"; + version = "0.52.0"; edition = "2021"; - sha256 = "0r1f57hsshsghjyc7ypp2s0i78f7b1vr93w68sdb8baxyf2czy7i"; + sha256 = "1nc3qv7sy24x0nlnb32f7alzpd6f72l4p24vl65vydbyil669ark"; + libName = "windows_core"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets"; + packageId = "windows-targets 0.52.6"; } ]; features = { }; resolvedDefaultFeatures = [ "default" ]; }; - "windows-sys" = rec { + "windows-sys 0.48.0" = rec { crateName = "windows-sys"; version = "0.48.0"; edition = "2018"; sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; + libName = "windows_sys"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets"; + packageId = "windows-targets 0.48.5"; } ]; features = { @@ -5539,56 +5589,617 @@ rec { "Win32_Web" = [ "Win32" ]; "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; }; - resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Security_Authentication" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_Security_Cryptography" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Console" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_Memory" "Win32_System_Pipes" "Win32_System_SystemInformation" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "default" ]; + resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Security" "Win32_System" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_Memory" "Win32_System_SystemInformation" "default" ]; }; - "windows-targets" = rec { + "windows-sys 0.52.0" = rec { + crateName = "windows-sys"; + version = "0.52.0"; + edition = "2021"; + sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + libName = "windows_sys"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + } + ]; + features = { + "Wdk_Foundation" = [ "Wdk" ]; + "Wdk_Graphics" = [ "Wdk" ]; + "Wdk_Graphics_Direct3D" = [ "Wdk_Graphics" ]; + "Wdk_Storage" = [ "Wdk" ]; + "Wdk_Storage_FileSystem" = [ "Wdk_Storage" ]; + "Wdk_Storage_FileSystem_Minifilters" = [ "Wdk_Storage_FileSystem" ]; + "Wdk_System" = [ "Wdk" ]; + "Wdk_System_IO" = [ "Wdk_System" ]; + "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; + "Wdk_System_Registry" = [ "Wdk_System" ]; + "Wdk_System_SystemInformation" = [ "Wdk_System" ]; + "Wdk_System_SystemServices" = [ "Wdk_System" ]; + "Wdk_System_Threading" = [ "Wdk_System" ]; + "Win32_Data" = [ "Win32" ]; + "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; + "Win32_Data_RightsManagement" = [ "Win32_Data" ]; + "Win32_Devices" = [ "Win32" ]; + "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; + "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; + "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; + "Win32_Devices_Communication" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; + "Win32_Devices_Display" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; + "Win32_Devices_Fax" = [ "Win32_Devices" ]; + "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; + "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; + "Win32_Devices_Properties" = [ "Win32_Devices" ]; + "Win32_Devices_Pwm" = [ "Win32_Devices" ]; + "Win32_Devices_Sensors" = [ "Win32_Devices" ]; + "Win32_Devices_SerialCommunication" = [ "Win32_Devices" ]; + "Win32_Devices_Tapi" = [ "Win32_Devices" ]; + "Win32_Devices_Usb" = [ "Win32_Devices" ]; + "Win32_Devices_WebServicesOnDevices" = [ "Win32_Devices" ]; + "Win32_Foundation" = [ "Win32" ]; + "Win32_Gaming" = [ "Win32" ]; + "Win32_Globalization" = [ "Win32" ]; + "Win32_Graphics" = [ "Win32" ]; + "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; + "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; + "Win32_Graphics_GdiPlus" = [ "Win32_Graphics" ]; + "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; + "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing_PrintTicket" = [ "Win32_Graphics_Printing" ]; + "Win32_Management" = [ "Win32" ]; + "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; + "Win32_Media" = [ "Win32" ]; + "Win32_Media_Audio" = [ "Win32_Media" ]; + "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; + "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; + "Win32_Media_Multimedia" = [ "Win32_Media" ]; + "Win32_Media_Streaming" = [ "Win32_Media" ]; + "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; + "Win32_NetworkManagement" = [ "Win32" ]; + "Win32_NetworkManagement_Dhcp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Snmp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; + "Win32_Networking" = [ "Win32" ]; + "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; + "Win32_Networking_Clustering" = [ "Win32_Networking" ]; + "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; + "Win32_Networking_Ldap" = [ "Win32_Networking" ]; + "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; + "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; + "Win32_Networking_WinInet" = [ "Win32_Networking" ]; + "Win32_Networking_WinSock" = [ "Win32_Networking" ]; + "Win32_Networking_WindowsWebServices" = [ "Win32_Networking" ]; + "Win32_Security" = [ "Win32" ]; + "Win32_Security_AppLocker" = [ "Win32_Security" ]; + "Win32_Security_Authentication" = [ "Win32_Security" ]; + "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; + "Win32_Security_Authorization" = [ "Win32_Security" ]; + "Win32_Security_Credentials" = [ "Win32_Security" ]; + "Win32_Security_Cryptography" = [ "Win32_Security" ]; + "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Certificates" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Sip" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_UI" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_DiagnosticDataQuery" = [ "Win32_Security" ]; + "Win32_Security_DirectoryServices" = [ "Win32_Security" ]; + "Win32_Security_EnterpriseData" = [ "Win32_Security" ]; + "Win32_Security_ExtensibleAuthenticationProtocol" = [ "Win32_Security" ]; + "Win32_Security_Isolation" = [ "Win32_Security" ]; + "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; + "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; + "Win32_Security_WinTrust" = [ "Win32_Security" ]; + "Win32_Security_WinWlx" = [ "Win32_Security" ]; + "Win32_Storage" = [ "Win32" ]; + "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; + "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; + "Win32_Storage_Compression" = [ "Win32_Storage" ]; + "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; + "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_Imapi" = [ "Win32_Storage" ]; + "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; + "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; + "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; + "Win32_Storage_Jet" = [ "Win32_Storage" ]; + "Win32_Storage_Nvme" = [ "Win32_Storage" ]; + "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; + "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; + "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; + "Win32_Storage_Vhd" = [ "Win32_Storage" ]; + "Win32_Storage_Xps" = [ "Win32_Storage" ]; + "Win32_System" = [ "Win32" ]; + "Win32_System_AddressBook" = [ "Win32_System" ]; + "Win32_System_Antimalware" = [ "Win32_System" ]; + "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; + "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; + "Win32_System_ClrHosting" = [ "Win32_System" ]; + "Win32_System_Com" = [ "Win32_System" ]; + "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; + "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; + "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; + "Win32_System_ComponentServices" = [ "Win32_System" ]; + "Win32_System_Console" = [ "Win32_System" ]; + "Win32_System_CorrelationVector" = [ "Win32_System" ]; + "Win32_System_DataExchange" = [ "Win32_System" ]; + "Win32_System_DeploymentServices" = [ "Win32_System" ]; + "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; + "Win32_System_Diagnostics" = [ "Win32_System" ]; + "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug_Extensions" = [ "Win32_System_Diagnostics_Debug" ]; + "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; + "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; + "Win32_System_Environment" = [ "Win32_System" ]; + "Win32_System_ErrorReporting" = [ "Win32_System" ]; + "Win32_System_EventCollector" = [ "Win32_System" ]; + "Win32_System_EventLog" = [ "Win32_System" ]; + "Win32_System_EventNotificationService" = [ "Win32_System" ]; + "Win32_System_GroupPolicy" = [ "Win32_System" ]; + "Win32_System_HostCompute" = [ "Win32_System" ]; + "Win32_System_HostComputeNetwork" = [ "Win32_System" ]; + "Win32_System_HostComputeSystem" = [ "Win32_System" ]; + "Win32_System_Hypervisor" = [ "Win32_System" ]; + "Win32_System_IO" = [ "Win32_System" ]; + "Win32_System_Iis" = [ "Win32_System" ]; + "Win32_System_Ioctl" = [ "Win32_System" ]; + "Win32_System_JobObjects" = [ "Win32_System" ]; + "Win32_System_Js" = [ "Win32_System" ]; + "Win32_System_Kernel" = [ "Win32_System" ]; + "Win32_System_LibraryLoader" = [ "Win32_System" ]; + "Win32_System_Mailslots" = [ "Win32_System" ]; + "Win32_System_Mapi" = [ "Win32_System" ]; + "Win32_System_Memory" = [ "Win32_System" ]; + "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; + "Win32_System_MessageQueuing" = [ "Win32_System" ]; + "Win32_System_MixedReality" = [ "Win32_System" ]; + "Win32_System_Ole" = [ "Win32_System" ]; + "Win32_System_PasswordManagement" = [ "Win32_System" ]; + "Win32_System_Performance" = [ "Win32_System" ]; + "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; + "Win32_System_Pipes" = [ "Win32_System" ]; + "Win32_System_Power" = [ "Win32_System" ]; + "Win32_System_ProcessStatus" = [ "Win32_System" ]; + "Win32_System_Recovery" = [ "Win32_System" ]; + "Win32_System_Registry" = [ "Win32_System" ]; + "Win32_System_RemoteDesktop" = [ "Win32_System" ]; + "Win32_System_RemoteManagement" = [ "Win32_System" ]; + "Win32_System_RestartManager" = [ "Win32_System" ]; + "Win32_System_Restore" = [ "Win32_System" ]; + "Win32_System_Rpc" = [ "Win32_System" ]; + "Win32_System_Search" = [ "Win32_System" ]; + "Win32_System_Search_Common" = [ "Win32_System_Search" ]; + "Win32_System_SecurityCenter" = [ "Win32_System" ]; + "Win32_System_Services" = [ "Win32_System" ]; + "Win32_System_SetupAndMigration" = [ "Win32_System" ]; + "Win32_System_Shutdown" = [ "Win32_System" ]; + "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; + "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; + "Win32_System_SystemInformation" = [ "Win32_System" ]; + "Win32_System_SystemServices" = [ "Win32_System" ]; + "Win32_System_Threading" = [ "Win32_System" ]; + "Win32_System_Time" = [ "Win32_System" ]; + "Win32_System_TpmBaseServices" = [ "Win32_System" ]; + "Win32_System_UserAccessLogging" = [ "Win32_System" ]; + "Win32_System_Variant" = [ "Win32_System" ]; + "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; + "Win32_System_WindowsProgramming" = [ "Win32_System" ]; + "Win32_System_Wmi" = [ "Win32_System" ]; + "Win32_UI" = [ "Win32" ]; + "Win32_UI_Accessibility" = [ "Win32_UI" ]; + "Win32_UI_ColorSystem" = [ "Win32_UI" ]; + "Win32_UI_Controls" = [ "Win32_UI" ]; + "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; + "Win32_UI_HiDpi" = [ "Win32_UI" ]; + "Win32_UI_Input" = [ "Win32_UI" ]; + "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; + "Win32_UI_InteractionContext" = [ "Win32_UI" ]; + "Win32_UI_Magnification" = [ "Win32_UI" ]; + "Win32_UI_Shell" = [ "Win32_UI" ]; + "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; + "Win32_UI_TabletPC" = [ "Win32_UI" ]; + "Win32_UI_TextServices" = [ "Win32_UI" ]; + "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; + "Win32_Web" = [ "Win32" ]; + "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; + }; + resolvedDefaultFeatures = [ "Wdk" "Wdk_Foundation" "Wdk_Storage" "Wdk_Storage_FileSystem" "Wdk_System" "Wdk_System_IO" "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Console" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "default" ]; + }; + "windows-sys 0.59.0" = rec { + crateName = "windows-sys"; + version = "0.59.0"; + edition = "2021"; + sha256 = "0fw5672ziw8b3zpmnbp9pdv1famk74f1l9fcbc3zsrzdg56vqf0y"; + libName = "windows_sys"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + } + ]; + features = { + "Wdk" = [ "Win32_Foundation" ]; + "Wdk_Devices" = [ "Wdk" ]; + "Wdk_Devices_Bluetooth" = [ "Wdk_Devices" ]; + "Wdk_Devices_HumanInterfaceDevice" = [ "Wdk_Devices" ]; + "Wdk_Foundation" = [ "Wdk" ]; + "Wdk_Graphics" = [ "Wdk" ]; + "Wdk_Graphics_Direct3D" = [ "Wdk_Graphics" ]; + "Wdk_NetworkManagement" = [ "Wdk" ]; + "Wdk_NetworkManagement_Ndis" = [ "Wdk_NetworkManagement" ]; + "Wdk_NetworkManagement_WindowsFilteringPlatform" = [ "Wdk_NetworkManagement" ]; + "Wdk_Storage" = [ "Wdk" ]; + "Wdk_Storage_FileSystem" = [ "Wdk_Storage" ]; + "Wdk_Storage_FileSystem_Minifilters" = [ "Wdk_Storage_FileSystem" ]; + "Wdk_System" = [ "Wdk" ]; + "Wdk_System_IO" = [ "Wdk_System" ]; + "Wdk_System_Memory" = [ "Wdk_System" ]; + "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; + "Wdk_System_Registry" = [ "Wdk_System" ]; + "Wdk_System_SystemInformation" = [ "Wdk_System" ]; + "Wdk_System_SystemServices" = [ "Wdk_System" ]; + "Wdk_System_Threading" = [ "Wdk_System" ]; + "Win32" = [ "Win32_Foundation" ]; + "Win32_Data" = [ "Win32" ]; + "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; + "Win32_Data_RightsManagement" = [ "Win32_Data" ]; + "Win32_Devices" = [ "Win32" ]; + "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; + "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; + "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; + "Win32_Devices_Communication" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; + "Win32_Devices_Display" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; + "Win32_Devices_Fax" = [ "Win32_Devices" ]; + "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; + "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; + "Win32_Devices_Properties" = [ "Win32_Devices" ]; + "Win32_Devices_Pwm" = [ "Win32_Devices" ]; + "Win32_Devices_Sensors" = [ "Win32_Devices" ]; + "Win32_Devices_SerialCommunication" = [ "Win32_Devices" ]; + "Win32_Devices_Tapi" = [ "Win32_Devices" ]; + "Win32_Devices_Usb" = [ "Win32_Devices" ]; + "Win32_Devices_WebServicesOnDevices" = [ "Win32_Devices" ]; + "Win32_Foundation" = [ "Win32" ]; + "Win32_Gaming" = [ "Win32" ]; + "Win32_Globalization" = [ "Win32" ]; + "Win32_Graphics" = [ "Win32" ]; + "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; + "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; + "Win32_Graphics_GdiPlus" = [ "Win32_Graphics" ]; + "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; + "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing_PrintTicket" = [ "Win32_Graphics_Printing" ]; + "Win32_Management" = [ "Win32" ]; + "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; + "Win32_Media" = [ "Win32" ]; + "Win32_Media_Audio" = [ "Win32_Media" ]; + "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; + "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; + "Win32_Media_Multimedia" = [ "Win32_Media" ]; + "Win32_Media_Streaming" = [ "Win32_Media" ]; + "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; + "Win32_NetworkManagement" = [ "Win32" ]; + "Win32_NetworkManagement_Dhcp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Snmp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; + "Win32_Networking" = [ "Win32" ]; + "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; + "Win32_Networking_Clustering" = [ "Win32_Networking" ]; + "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; + "Win32_Networking_Ldap" = [ "Win32_Networking" ]; + "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; + "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; + "Win32_Networking_WinInet" = [ "Win32_Networking" ]; + "Win32_Networking_WinSock" = [ "Win32_Networking" ]; + "Win32_Networking_WindowsWebServices" = [ "Win32_Networking" ]; + "Win32_Security" = [ "Win32" ]; + "Win32_Security_AppLocker" = [ "Win32_Security" ]; + "Win32_Security_Authentication" = [ "Win32_Security" ]; + "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; + "Win32_Security_Authorization" = [ "Win32_Security" ]; + "Win32_Security_Credentials" = [ "Win32_Security" ]; + "Win32_Security_Cryptography" = [ "Win32_Security" ]; + "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Certificates" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Sip" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_UI" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_DiagnosticDataQuery" = [ "Win32_Security" ]; + "Win32_Security_DirectoryServices" = [ "Win32_Security" ]; + "Win32_Security_EnterpriseData" = [ "Win32_Security" ]; + "Win32_Security_ExtensibleAuthenticationProtocol" = [ "Win32_Security" ]; + "Win32_Security_Isolation" = [ "Win32_Security" ]; + "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; + "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; + "Win32_Security_WinTrust" = [ "Win32_Security" ]; + "Win32_Security_WinWlx" = [ "Win32_Security" ]; + "Win32_Storage" = [ "Win32" ]; + "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; + "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; + "Win32_Storage_Compression" = [ "Win32_Storage" ]; + "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; + "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_Imapi" = [ "Win32_Storage" ]; + "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; + "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; + "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; + "Win32_Storage_Jet" = [ "Win32_Storage" ]; + "Win32_Storage_Nvme" = [ "Win32_Storage" ]; + "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; + "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; + "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; + "Win32_Storage_Vhd" = [ "Win32_Storage" ]; + "Win32_Storage_Xps" = [ "Win32_Storage" ]; + "Win32_System" = [ "Win32" ]; + "Win32_System_AddressBook" = [ "Win32_System" ]; + "Win32_System_Antimalware" = [ "Win32_System" ]; + "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; + "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; + "Win32_System_ClrHosting" = [ "Win32_System" ]; + "Win32_System_Com" = [ "Win32_System" ]; + "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; + "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; + "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; + "Win32_System_ComponentServices" = [ "Win32_System" ]; + "Win32_System_Console" = [ "Win32_System" ]; + "Win32_System_CorrelationVector" = [ "Win32_System" ]; + "Win32_System_DataExchange" = [ "Win32_System" ]; + "Win32_System_DeploymentServices" = [ "Win32_System" ]; + "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; + "Win32_System_Diagnostics" = [ "Win32_System" ]; + "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug_Extensions" = [ "Win32_System_Diagnostics_Debug" ]; + "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_TraceLogging" = [ "Win32_System_Diagnostics" ]; + "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; + "Win32_System_Environment" = [ "Win32_System" ]; + "Win32_System_ErrorReporting" = [ "Win32_System" ]; + "Win32_System_EventCollector" = [ "Win32_System" ]; + "Win32_System_EventLog" = [ "Win32_System" ]; + "Win32_System_EventNotificationService" = [ "Win32_System" ]; + "Win32_System_GroupPolicy" = [ "Win32_System" ]; + "Win32_System_HostCompute" = [ "Win32_System" ]; + "Win32_System_HostComputeNetwork" = [ "Win32_System" ]; + "Win32_System_HostComputeSystem" = [ "Win32_System" ]; + "Win32_System_Hypervisor" = [ "Win32_System" ]; + "Win32_System_IO" = [ "Win32_System" ]; + "Win32_System_Iis" = [ "Win32_System" ]; + "Win32_System_Ioctl" = [ "Win32_System" ]; + "Win32_System_JobObjects" = [ "Win32_System" ]; + "Win32_System_Js" = [ "Win32_System" ]; + "Win32_System_Kernel" = [ "Win32_System" ]; + "Win32_System_LibraryLoader" = [ "Win32_System" ]; + "Win32_System_Mailslots" = [ "Win32_System" ]; + "Win32_System_Mapi" = [ "Win32_System" ]; + "Win32_System_Memory" = [ "Win32_System" ]; + "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; + "Win32_System_MessageQueuing" = [ "Win32_System" ]; + "Win32_System_MixedReality" = [ "Win32_System" ]; + "Win32_System_Ole" = [ "Win32_System" ]; + "Win32_System_PasswordManagement" = [ "Win32_System" ]; + "Win32_System_Performance" = [ "Win32_System" ]; + "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; + "Win32_System_Pipes" = [ "Win32_System" ]; + "Win32_System_Power" = [ "Win32_System" ]; + "Win32_System_ProcessStatus" = [ "Win32_System" ]; + "Win32_System_Recovery" = [ "Win32_System" ]; + "Win32_System_Registry" = [ "Win32_System" ]; + "Win32_System_RemoteDesktop" = [ "Win32_System" ]; + "Win32_System_RemoteManagement" = [ "Win32_System" ]; + "Win32_System_RestartManager" = [ "Win32_System" ]; + "Win32_System_Restore" = [ "Win32_System" ]; + "Win32_System_Rpc" = [ "Win32_System" ]; + "Win32_System_Search" = [ "Win32_System" ]; + "Win32_System_Search_Common" = [ "Win32_System_Search" ]; + "Win32_System_SecurityCenter" = [ "Win32_System" ]; + "Win32_System_Services" = [ "Win32_System" ]; + "Win32_System_SetupAndMigration" = [ "Win32_System" ]; + "Win32_System_Shutdown" = [ "Win32_System" ]; + "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; + "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; + "Win32_System_SystemInformation" = [ "Win32_System" ]; + "Win32_System_SystemServices" = [ "Win32_System" ]; + "Win32_System_Threading" = [ "Win32_System" ]; + "Win32_System_Time" = [ "Win32_System" ]; + "Win32_System_TpmBaseServices" = [ "Win32_System" ]; + "Win32_System_UserAccessLogging" = [ "Win32_System" ]; + "Win32_System_Variant" = [ "Win32_System" ]; + "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; + "Win32_System_WindowsProgramming" = [ "Win32_System" ]; + "Win32_System_Wmi" = [ "Win32_System" ]; + "Win32_UI" = [ "Win32" ]; + "Win32_UI_Accessibility" = [ "Win32_UI" ]; + "Win32_UI_ColorSystem" = [ "Win32_UI" ]; + "Win32_UI_Controls" = [ "Win32_UI" ]; + "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; + "Win32_UI_HiDpi" = [ "Win32_UI" ]; + "Win32_UI_Input" = [ "Win32_UI" ]; + "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; + "Win32_UI_InteractionContext" = [ "Win32_UI" ]; + "Win32_UI_Magnification" = [ "Win32_UI" ]; + "Win32_UI_Shell" = [ "Win32_UI" ]; + "Win32_UI_Shell_Common" = [ "Win32_UI_Shell" ]; + "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; + "Win32_UI_TabletPC" = [ "Win32_UI" ]; + "Win32_UI_TextServices" = [ "Win32_UI" ]; + "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; + "Win32_Web" = [ "Win32" ]; + "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; + }; + resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Security" "Win32_Security_Authentication" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_Security_Cryptography" "Win32_System" "Win32_System_LibraryLoader" "Win32_System_Memory" "Win32_System_SystemInformation" "default" ]; + }; + "windows-targets 0.48.5" = rec { crateName = "windows-targets"; version = "0.48.5"; edition = "2018"; sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + libName = "windows_targets"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows_aarch64_gnullvm"; - packageId = "windows_aarch64_gnullvm"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + packageId = "windows_aarch64_gnullvm 0.48.5"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); } { name = "windows_aarch64_msvc"; - packageId = "windows_aarch64_msvc"; + packageId = "windows_aarch64_msvc 0.48.5"; target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_i686_gnu"; - packageId = "windows_i686_gnu"; + packageId = "windows_i686_gnu 0.48.5"; target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_i686_msvc"; - packageId = "windows_i686_msvc"; + packageId = "windows_i686_msvc 0.48.5"; target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnu"; - packageId = "windows_x86_64_gnu"; + packageId = "windows_x86_64_gnu 0.48.5"; target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnullvm"; - packageId = "windows_x86_64_gnullvm"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); + packageId = "windows_x86_64_gnullvm 0.48.5"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); } { name = "windows_x86_64_msvc"; - packageId = "windows_x86_64_msvc"; + packageId = "windows_x86_64_msvc 0.48.5"; target = { target, features }: (("x86_64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } ]; }; - "windows_aarch64_gnullvm" = rec { + "windows-targets 0.52.6" = rec { + crateName = "windows-targets"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0wwrx625nwlfp7k93r2rra568gad1mwd888h1jwnl0vfg5r4ywlv"; + libName = "windows_targets"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows_aarch64_gnullvm"; + packageId = "windows_aarch64_gnullvm 0.52.6"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); + } + { + name = "windows_aarch64_msvc"; + packageId = "windows_aarch64_msvc 0.52.6"; + target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_i686_gnu"; + packageId = "windows_i686_gnu 0.52.6"; + target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_i686_gnullvm"; + packageId = "windows_i686_gnullvm"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnullvm"); + } + { + name = "windows_i686_msvc"; + packageId = "windows_i686_msvc 0.52.6"; + target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_x86_64_gnu"; + packageId = "windows_x86_64_gnu 0.52.6"; + target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); + } + { + name = "windows_x86_64_gnullvm"; + packageId = "windows_x86_64_gnullvm 0.52.6"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); + } + { + name = "windows_x86_64_msvc"; + packageId = "windows_x86_64_msvc 0.52.6"; + target = { target, features }: ((("x86_64" == target."arch" or null) || ("arm64ec" == target."arch" or null)) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + } + ]; + + }; + "windows_aarch64_gnullvm 0.48.5" = rec { crateName = "windows_aarch64_gnullvm"; version = "0.48.5"; edition = "2018"; @@ -5598,7 +6209,17 @@ rec { ]; }; - "windows_aarch64_msvc" = rec { + "windows_aarch64_gnullvm 0.52.6" = rec { + crateName = "windows_aarch64_gnullvm"; + version = "0.52.6"; + edition = "2021"; + sha256 = "1lrcq38cr2arvmz19v32qaggvj8bh1640mdm9c2fr877h0hn591j"; + authors = [ + "Microsoft" + ]; + + }; + "windows_aarch64_msvc 0.48.5" = rec { crateName = "windows_aarch64_msvc"; version = "0.48.5"; edition = "2018"; @@ -5608,7 +6229,17 @@ rec { ]; }; - "windows_i686_gnu" = rec { + "windows_aarch64_msvc 0.52.6" = rec { + crateName = "windows_aarch64_msvc"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0sfl0nysnz32yyfh773hpi49b1q700ah6y7sacmjbqjjn5xjmv09"; + authors = [ + "Microsoft" + ]; + + }; + "windows_i686_gnu 0.48.5" = rec { crateName = "windows_i686_gnu"; version = "0.48.5"; edition = "2018"; @@ -5618,7 +6249,27 @@ rec { ]; }; - "windows_i686_msvc" = rec { + "windows_i686_gnu 0.52.6" = rec { + crateName = "windows_i686_gnu"; + version = "0.52.6"; + edition = "2021"; + sha256 = "02zspglbykh1jh9pi7gn8g1f97jh1rrccni9ivmrfbl0mgamm6wf"; + authors = [ + "Microsoft" + ]; + + }; + "windows_i686_gnullvm" = rec { + crateName = "windows_i686_gnullvm"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0rpdx1537mw6slcpqa0rm3qixmsb79nbhqy5fsm3q2q9ik9m5vhf"; + authors = [ + "Microsoft" + ]; + + }; + "windows_i686_msvc 0.48.5" = rec { crateName = "windows_i686_msvc"; version = "0.48.5"; edition = "2018"; @@ -5628,7 +6279,17 @@ rec { ]; }; - "windows_x86_64_gnu" = rec { + "windows_i686_msvc 0.52.6" = rec { + crateName = "windows_i686_msvc"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0rkcqmp4zzmfvrrrx01260q3xkpzi6fzi2x2pgdcdry50ny4h294"; + authors = [ + "Microsoft" + ]; + + }; + "windows_x86_64_gnu 0.48.5" = rec { crateName = "windows_x86_64_gnu"; version = "0.48.5"; edition = "2018"; @@ -5638,7 +6299,17 @@ rec { ]; }; - "windows_x86_64_gnullvm" = rec { + "windows_x86_64_gnu 0.52.6" = rec { + crateName = "windows_x86_64_gnu"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0y0sifqcb56a56mvn7xjgs8g43p33mfqkd8wj1yhrgxzma05qyhl"; + authors = [ + "Microsoft" + ]; + + }; + "windows_x86_64_gnullvm 0.48.5" = rec { crateName = "windows_x86_64_gnullvm"; version = "0.48.5"; edition = "2018"; @@ -5648,7 +6319,17 @@ rec { ]; }; - "windows_x86_64_msvc" = rec { + "windows_x86_64_gnullvm 0.52.6" = rec { + crateName = "windows_x86_64_gnullvm"; + version = "0.52.6"; + edition = "2021"; + sha256 = "03gda7zjx1qh8k9nnlgb7m3w3s1xkysg55hkd1wjch8pqhyv5m94"; + authors = [ + "Microsoft" + ]; + + }; + "windows_x86_64_msvc 0.48.5" = rec { crateName = "windows_x86_64_msvc"; version = "0.48.5"; edition = "2018"; @@ -5658,12 +6339,22 @@ rec { ]; }; + "windows_x86_64_msvc 0.52.6" = rec { + crateName = "windows_x86_64_msvc"; + version = "0.52.6"; + edition = "2021"; + sha256 = "1v7rb5cibyzx8vak29pdrk8nx9hycsjs4w0jgms08qk49jl6v7sq"; + authors = [ + "Microsoft" + ]; + + }; "xml-rs" = rec { crateName = "xml-rs"; - version = "0.8.19"; + version = "0.8.22"; edition = "2021"; crateBin = [ ]; - sha256 = "0nnpvk3fv32hgh7vs9gbg2swmzxx5yz73f4b7rak7q39q2x9rjqg"; + sha256 = "09pg779vjh0xp3ph10j4wy1ihz8pzvxm1qf1jqw0jnmsghpjwkmg"; libName = "xml"; authors = [ "Vladimir Matveev <vmatveev@citrine.cc>" @@ -5672,9 +6363,9 @@ rec { }; "zeroize" = rec { crateName = "zeroize"; - version = "1.6.0"; + version = "1.8.1"; edition = "2021"; - sha256 = "1ndar43r58zbmasjhrhgas168vxb4i0rwbkcnszhjybwpbqmc29a"; + sha256 = "1pjdrmjwmszpxfd7r860jx54cyk94qk59x13sc307cvr5256glyf"; authors = [ "The RustCrypto Project Developers" ]; @@ -5722,6 +6413,7 @@ rec { version = "4.1.3+zstd.1.5.1"; edition = "2018"; sha256 = "0yfvqzzkbj871f2vaikal5rm2gf60p1mdzp3jk3w5hmkkywq37g9"; + libName = "zstd_safe"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -5756,6 +6448,7 @@ rec { edition = "2018"; links = "zstd"; sha256 = "17xcr0mw8ps9hlc8m0dzj7yd52lb9r9ic9fbpxa4994yilj2zbrd"; + libName = "zstd_sys"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -5794,14 +6487,11 @@ rec { fuchsia = true; test = false; - /* We are choosing an arbitrary rust version to grab `lib` from, - which is unfortunate, but `lib` has been version-agnostic the - whole time so this is good enough for now. - */ - os = pkgs.rust.lib.toTargetOs platform; - arch = pkgs.rust.lib.toTargetArch platform; - family = pkgs.rust.lib.toTargetFamily platform; - vendor = pkgs.rust.lib.toTargetVendor platform; + inherit (platform.rust.platform) + arch + os + vendor; + family = platform.rust.platform.target-family; env = "gnu"; endian = if platform.parsed.cpu.significantByte.name == "littleEndian" @@ -5878,6 +6568,7 @@ rec { ( _: { buildTests = true; + release = false; } ); # If the user hasn't set any pre/post commands, we don't want to @@ -5890,51 +6581,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; - export RUST_BACKTRACE=1 + inherit (crate) src; - # recreate a file hierarchy as when running tests with cargo + inherit testCrateFlags; - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # TODO(raitobezarius): I believe there could be more edge cases if `crate.sourceRoot` - # do exist but it's very hard to reason about them, so let's wait until the first bug report. - mkdir -p source/ - cd source/ + buildInputs = testInputs; - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + buildPhase = '' + set -e + export RUST_BACKTRACE=1 - # build outputs - testRoot=target/debug - mkdir -p $testRoot + # build outputs + testRoot=target/debug + mkdir -p $testRoot - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { @@ -6043,7 +6724,7 @@ rec { let self = { crates = lib.mapAttrs (packageId: value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs; - target = makeTarget pkgs.stdenv.hostPlatform; + target = makeTarget stdenv.hostPlatform; build = mkBuiltByPackageIdByPkgs pkgs.buildPackages; }; in @@ -6118,8 +6799,6 @@ rec { buildRustCrateForPkgsFunc pkgs ( crateConfig // { - # https://github.com/NixOS/nixpkgs/issues/218712 - dontStrip = stdenv.hostPlatform.isDarwin; src = crateConfig.src or ( pkgs.fetchurl rec { name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz"; diff --git a/tvix/tools/turbofetch/Cargo.toml b/users/edef/turbofetch/Cargo.toml index 6b2f0e752020..65a7be9a55b0 100644 --- a/tvix/tools/turbofetch/Cargo.toml +++ b/users/edef/turbofetch/Cargo.toml @@ -10,7 +10,7 @@ members = ["."] [dependencies] aws_lambda_events = { version = "0.11.1", default-features = false, features = ["lambda_function_urls"] } bytes = "1.5.0" -data-encoding = "2.4.0" +data-encoding = "2.6.0" futures = { version = "0.3.30", default-features = false, features = ["std"] } httparse = "1.8.0" hyper = { version = "0.14.27", default-features = false } diff --git a/tvix/tools/turbofetch/OWNERS b/users/edef/turbofetch/OWNERS index b9bc074a8020..b9bc074a8020 100644 --- a/tvix/tools/turbofetch/OWNERS +++ b/users/edef/turbofetch/OWNERS diff --git a/users/edef/turbofetch/default.nix b/users/edef/turbofetch/default.nix new file mode 100644 index 000000000000..a98b2f0b4330 --- /dev/null +++ b/users/edef/turbofetch/default.nix @@ -0,0 +1,11 @@ +{ pkgs, depot, ... }: + +(pkgs.callPackage ./Cargo.nix { + defaultCrateOverrides = (depot.tvix.utils.defaultCrateOverridesForPkgs pkgs) // { + turbofetch = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + }; +}).rootCrate.build.overrideAttrs { + meta.ci.extraSteps.crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; +} diff --git a/tvix/tools/turbofetch/deploy.sh b/users/edef/turbofetch/deploy.sh index 65564ce2ed7f..65564ce2ed7f 100755 --- a/tvix/tools/turbofetch/deploy.sh +++ b/users/edef/turbofetch/deploy.sh diff --git a/tvix/tools/turbofetch/src/buffer.rs b/users/edef/turbofetch/src/buffer.rs index d6ff93e3cfe7..d6ff93e3cfe7 100644 --- a/tvix/tools/turbofetch/src/buffer.rs +++ b/users/edef/turbofetch/src/buffer.rs diff --git a/tvix/tools/turbofetch/src/lib.rs b/users/edef/turbofetch/src/lib.rs index 4b62fa4d75e7..4b62fa4d75e7 100644 --- a/tvix/tools/turbofetch/src/lib.rs +++ b/users/edef/turbofetch/src/lib.rs diff --git a/tvix/tools/turbofetch/src/main.rs b/users/edef/turbofetch/src/main.rs index 4b3a50eb3941..4b3a50eb3941 100644 --- a/tvix/tools/turbofetch/src/main.rs +++ b/users/edef/turbofetch/src/main.rs diff --git a/tvix/tools/weave/Cargo.lock b/users/edef/weave/Cargo.lock index 46a90cb4822f..734f12d4e699 100644 --- a/tvix/tools/weave/Cargo.lock +++ b/users/edef/weave/Cargo.lock @@ -4,24 +4,24 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" -version = "0.8.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", @@ -32,9 +32,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -77,18 +77,18 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" dependencies = [ "backtrace", ] [[package]] name = "argminmax" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202108b46429b765ef483f8a24d5c46f48c14acfdacc086dd4ab6dddf6bcdbd2" +checksum = "52424b59d69d69d5056d508b260553afd91c57e21849579cd1f50ee8b8b88eaa" dependencies = [ "num-traits", ] @@ -100,6 +100,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf7d0a018de4f6aa429b9d33d69edf69072b1c5b1cb8d3e4a5f7ef898fc3eb76" [[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] name = "arrow-format" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -111,9 +117,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -122,24 +128,24 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] @@ -159,23 +165,23 @@ checksum = "9ae037714f313c1353189ead58ef9eec30a8e8dc101b2622d461418fd59e28a9" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] @@ -192,15 +198,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -213,9 +213,9 @@ dependencies = [ [[package]] name = "brotli" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -234,55 +234,62 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", - "regex-automata", + "regex-automata 0.4.8", "serde", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.14.2" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea31d69bda4949c1c1562c1e6f042a1caefac98cdc8a298260a2ff41c1e2d42b" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.5.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" +checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] -name = "bytes" +name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.0.83" +version = "1.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "58e804ac3194a48bb129643eb1d62fcc20d18c6b8c181704489353d13120bcd1" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -293,26 +300,39 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "windows-targets 0.52.0", + "windows-targets", ] [[package]] name = "comfy-table" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" +checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" dependencies = [ "crossterm", "strum", - "strum_macros", + "strum_macros 0.26.4", + "unicode-width", +] + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", "unicode-width", + "windows-sys", ] [[package]] @@ -323,33 +343,33 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -384,9 +404,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crossterm" @@ -394,7 +414,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.4.2", + "bitflags", "crossterm_winapi", "libc", "parking_lot", @@ -422,16 +442,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -445,20 +464,20 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", @@ -476,9 +495,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "ed25519" @@ -506,20 +525,37 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "enum-primitive-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c" +dependencies = [ + "num-traits", + "quote", + "syn 2.0.79", +] [[package]] name = "enum_dispatch" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] @@ -548,15 +584,15 @@ checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c" [[package]] name = "fiat-crypto" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -570,9 +606,9 @@ checksum = "ee1b05cbd864bcaecbd3455d6d967862d446e4ebfc3c2e5e5b9841e53cba6673" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -585,9 +621,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -595,15 +631,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -612,38 +648,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -669,9 +705,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "js-sys", @@ -682,9 +718,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -694,9 +730,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -704,16 +740,28 @@ dependencies = [ ] [[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] name = "hermit-abi" -version = "0.3.5" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "home" @@ -721,14 +769,14 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -749,43 +797,72 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.0", +] + +[[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", + "vt100", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.68" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] [[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] name = "libc" -version = "0.2.153" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libm" @@ -794,10 +871,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] +name = "libmimalloc-sys" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] + +[[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -805,35 +892,43 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lz4" -version = "1.24.0" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +checksum = "4d1febb2b4a79ddd1980eede06a8f7902197960aa0383ffcfdd62fe723036725" dependencies = [ - "libc", "lz4-sys", ] [[package]] name = "lz4-sys" -version = "1.9.4" +version = "1.11.1+lz4-1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" dependencies = [ "cc", "libc", ] [[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -845,6 +940,15 @@ dependencies = [ ] [[package]] +name = "mimalloc" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -852,29 +956,30 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.10" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "multiversion" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2c7b9d7fe61760ce5ea19532ead98541f6b4c495d87247aff9826445cf6872a" +checksum = "c4851161a11d3ad0bf9402d90ffc3967bf231768bfd7aeb61755ad06dbf1a142" dependencies = [ "multiversion-macros", "target-features", @@ -882,9 +987,9 @@ dependencies = [ [[package]] name = "multiversion-macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a83d8500ed06d68877e9de1dde76c1dbb83885dcdbda4ef44ccbc3fbda2ac8" +checksum = "79a74ddee9e0c27d2578323c13905793e91622148f138ba29738f9dddb835e90" dependencies = [ "proc-macro2", "quote", @@ -896,17 +1001,34 @@ dependencies = [ name = "nix-compat" version = "0.1.0" dependencies = [ - "bitflags 2.4.2", + "bitflags", "bstr", + "bytes", "data-encoding", "ed25519", "ed25519-dalek", + "enum-primitive-derive", "glob", + "mimalloc", + "nix-compat-derive", "nom", + "num-traits", + "pin-project-lite", "serde", "serde_json", "sha2", "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "nix-compat-derive" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", ] [[package]] @@ -938,54 +1060,57 @@ dependencies = [ ] [[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "number_prefix" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.2" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] -name = "owning_ref" -version = "0.4.1" +name = "overload" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce" -dependencies = [ - "stable_deref_trait", -] +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -993,15 +1118,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets", ] [[package]] @@ -1022,9 +1147,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1044,9 +1169,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "planus" @@ -1058,12 +1183,6 @@ dependencies = [ ] [[package]] -name = "platforms" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" - -[[package]] name = "polars" version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1097,7 +1216,7 @@ dependencies = [ "foreign_vec", "futures", "getrandom", - "hashbrown", + "hashbrown 0.14.5", "itoa", "lz4", "multiversion", @@ -1132,12 +1251,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0f5efe734b6cbe5f97ea769be8360df5324fade396f1f3f5ad7fe9360ca4a23" dependencies = [ "ahash", - "bitflags 2.4.2", + "bitflags", "bytemuck", "chrono", "comfy-table", "either", - "hashbrown", + "hashbrown 0.14.5", "indexmap", "num-traits", "once_cell", @@ -1210,7 +1329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d7105b40905bb38e8fc4a7fd736594b7491baa12fad3ac492969ca221a1b5d5" dependencies = [ "ahash", - "bitflags 2.4.2", + "bitflags", "glob", "once_cell", "polars-arrow", @@ -1236,7 +1355,7 @@ dependencies = [ "argminmax", "bytemuck", "either", - "hashbrown", + "hashbrown 0.14.5", "indexmap", "memchr", "num-traits", @@ -1286,7 +1405,7 @@ dependencies = [ "crossbeam-channel", "crossbeam-queue", "enum_dispatch", - "hashbrown", + "hashbrown 0.14.5", "num-traits", "polars-arrow", "polars-compute", @@ -1321,7 +1440,7 @@ dependencies = [ "rayon", "regex", "smartstring", - "strum_macros", + "strum_macros 0.25.3", "version_check", ] @@ -1380,7 +1499,7 @@ checksum = "b174ca4a77ad47d7b91a0460aaae65bbf874c8bfbaaa5308675dadef3976bbda" dependencies = [ "ahash", "bytemuck", - "hashbrown", + "hashbrown 0.14.5", "indexmap", "num-traits", "once_cell", @@ -1392,25 +1511,34 @@ dependencies = [ ] [[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + +[[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1457,9 +1585,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -1477,68 +1605,98 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.5", ] [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "safer_owning_ref" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af21b9de2df966f61c07b5b541c81c98225b86e48ababd43366a642654de30ef" +dependencies = [ + "stable_deref_trait", +] [[package]] name = "scopeguard" @@ -1548,9 +1706,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "seq-macro" @@ -1560,31 +1718,32 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.196" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "serde_json" -version = "1.0.113" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -1601,15 +1760,21 @@ dependencies = [ ] [[package]] -name = "signal-hook-registry" -version = "1.4.1" +name = "sharded-slab" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ - "libc", + "lazy_static", ] [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "signature" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1620,9 +1785,9 @@ dependencies = [ [[package]] name = "simdutf8" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "slab" @@ -1635,9 +1800,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smartstring" @@ -1658,12 +1823,12 @@ checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1720,9 +1885,9 @@ checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" [[package]] name = "strum" -version = "0.25.0" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" [[package]] name = "strum_macros" @@ -1730,18 +1895,31 @@ version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", - "syn 2.0.48", + "syn 2.0.79", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.79", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -1756,9 +1934,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -1767,9 +1945,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.30.5" +version = "0.30.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb4f3438c8f6389c864e61221cbc97e9bca98b4daf39a5beb7bea660f528bb2" +checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" dependencies = [ "cfg-if", "core-foundation-sys", @@ -1781,65 +1959,72 @@ dependencies = [ [[package]] name = "target-features" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb5fa503293557c5158bd215fdc225695e567a77e453f5d4452a50a193969bd" +checksum = "c1bbb9f3c5c463a01705937a24fdabc5047929ac764b2d5b9cf681c1f5041ed5" [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", ] [[package]] name = "tokio" -version = "1.36.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", - "parking_lot", "pin-project-lite", - "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -1849,6 +2034,91 @@ dependencies = [ ] [[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-indicatif" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069580424efe11d97c3fef4197fa98c004fa26672cc71ad8770d224e23b1951d" +dependencies = [ + "indicatif", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tvix-tracing" +version = "0.1.0" +dependencies = [ + "indicatif", + "thiserror", + "tokio", + "tracing", + "tracing-indicatif", + "tracing-subscriber", +] + +[[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1856,21 +2126,66 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vt100" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84cd863bf0db7e392ba3bd04994be3473491b31e66340672af5d11943c6274de" +dependencies = [ + "itoa", + "log", + "unicode-width", + "vte", +] + +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "arrayvec", + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" +dependencies = [ + "proc-macro2", + "quote", +] [[package]] name = "wasi" @@ -1880,34 +2195,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1915,34 +2231,37 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "weave" version = "0.1.0" dependencies = [ "anyhow", - "hashbrown", + "hashbrown 0.14.5", "nix-compat", - "owning_ref", "polars", "rayon", - "tokio", + "rustc-hash", + "safer_owning_ref", + "tracing", + "tracing-indicatif", + "tvix-tracing", ] [[package]] @@ -1974,7 +2293,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core", - "windows-targets 0.52.0", + "windows-targets", ] [[package]] @@ -1983,16 +2302,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", + "windows-targets", ] [[package]] @@ -2001,178 +2311,129 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] -name = "windows_i686_msvc" -version = "0.48.5" +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "xxhash-rust" -version = "0.8.8" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53be06678ed9e83edb1745eb72efc0bbcd7b5c3c35711a860906aed827a13d61" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.79", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zstd" -version = "0.13.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.0.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/tvix/tools/weave/Cargo.nix b/users/edef/weave/Cargo.nix index 650b655a2df0..b10bdfb7688c 100644 --- a/tvix/tools/weave/Cargo.nix +++ b/users/edef/weave/Cargo.nix @@ -1,4 +1,4 @@ -# This file was @generated by crate2nix 0.13.0 with the command: +# This file was @generated by crate2nix 0.14.1 with the command: # "generate" "--all-features" # See https://github.com/kolloch/crate2nix for more info. @@ -13,6 +13,8 @@ , rootFeatures ? [ "default" ] # If true, throw errors instead of issueing deprecation warnings. , strictDeprecation ? false + # Elements to add to the `-C target-feature=` argument passed to `rustc` + # (separated by `,`, prefixed with `+`). # Used for conditional compilation based on CPU feature detection. , targetFeatures ? [ ] # Whether to perform release builds: longer compile times, faster binaries. @@ -83,9 +85,10 @@ rec { crates = { "addr2line" = rec { crateName = "addr2line"; - version = "0.21.0"; + version = "0.24.2"; edition = "2018"; - sha256 = "1jx0k3iwyqr8klqbzk6kjvr496yd94aspis10vwsj5wy7gib4c4a"; + crateBin = [ ]; + sha256 = "1hd1i57zxgz08j6h5qrhsnm2fi0bcqvsh389fw400xm3arz2ggnz"; dependencies = [ { name = "gimli"; @@ -95,28 +98,29 @@ rec { } ]; features = { + "all" = [ "bin" ]; "alloc" = [ "dep:alloc" ]; + "bin" = [ "loader" "rustc-demangle" "cpp_demangle" "fallible-iterator" "smallvec" "dep:clap" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; "cpp_demangle" = [ "dep:cpp_demangle" ]; - "default" = [ "rustc-demangle" "cpp_demangle" "std-object" "fallible-iterator" "smallvec" "memmap2" ]; + "default" = [ "rustc-demangle" "cpp_demangle" "loader" "fallible-iterator" "smallvec" ]; "fallible-iterator" = [ "dep:fallible-iterator" ]; - "memmap2" = [ "dep:memmap2" ]; - "object" = [ "dep:object" ]; + "loader" = [ "std" "dep:object" "dep:memmap2" "dep:typed-arena" ]; "rustc-demangle" = [ "dep:rustc-demangle" ]; "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "gimli/rustc-dep-of-std" ]; "smallvec" = [ "dep:smallvec" ]; "std" = [ "gimli/std" ]; - "std-object" = [ "std" "object" "object/std" "object/compression" "gimli/endian-reader" ]; }; }; - "adler" = rec { - crateName = "adler"; - version = "1.0.2"; - edition = "2015"; - sha256 = "1zim79cvzd5yrkzl3nyfx0avijwgk9fqv3yrscdy1cc79ih02qpj"; + "adler2" = rec { + crateName = "adler2"; + version = "2.0.0"; + edition = "2021"; + sha256 = "09r6drylvgy8vv8k20lnbvwq8gp09h7smfn6h1rxsy15pgh629si"; authors = [ "Jonas Schievink <jonasschievink@gmail.com>" + "oyvindln <oyvindln@users.noreply.github.com>" ]; features = { "compiler_builtins" = [ "dep:compiler_builtins" ]; @@ -127,9 +131,9 @@ rec { }; "ahash" = rec { crateName = "ahash"; - version = "0.8.7"; + version = "0.8.11"; edition = "2018"; - sha256 = "008xw6gigwnf0q01ic4ar2y4dqfnzn3kyys6vd4cvfa3imjakhvp"; + sha256 = "04chdfkls5xmhp1d48gnjsmglbqibizs3bpbj6rsj604m10si7g8"; authors = [ "Tom Kaitchuck <Tom.Kaitchuck@gmail.com>" ]; @@ -176,9 +180,9 @@ rec { }; "aho-corasick" = rec { crateName = "aho-corasick"; - version = "1.1.2"; + version = "1.1.3"; edition = "2021"; - sha256 = "1w510wnixvlgimkx1zjbvlxh6xps2vjgfqgwf5a6adlbjp5rv5mj"; + sha256 = "05mrpkvdgp5d20y2p989f187ry9diliijgwrs254fs9s1m1x6q4f"; libName = "aho_corasick"; authors = [ "Andrew Gallant <jamslam@gmail.com>" @@ -205,6 +209,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1cy6r2sfv5y5cigv86vms7n5nlwhx1rbyxwcraqnmm1rxiib2yyc"; + libName = "alloc_no_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -216,6 +221,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1kkfbld20ab4165p29v172h8g0wvq8i06z8vnng14whw0isq5ywl"; + libName = "alloc_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -229,9 +235,10 @@ rec { }; "allocator-api2" = rec { crateName = "allocator-api2"; - version = "0.2.16"; + version = "0.2.18"; edition = "2018"; - sha256 = "1iayppgq4wqbfbfcqmsbwgamj0s65012sskfvyx07pxavk3gyhh9"; + sha256 = "0kr6lfnxvnj164j1x38g97qjlhb7akppqzvgfs0697140ixbav2w"; + libName = "allocator_api2"; authors = [ "Zakarum <zaq.dev@icloud.com>" ]; @@ -247,6 +254,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9"; + libName = "android_tzdata"; authors = [ "RumovZ" ]; @@ -270,9 +278,9 @@ rec { }; "anyhow" = rec { crateName = "anyhow"; - version = "1.0.79"; + version = "1.0.89"; edition = "2018"; - sha256 = "1ji5irqiwr8yprgqj8zvnli7zd7fz9kzaiddq44jnrl2l289h3h8"; + sha256 = "1xh1vg89n56h6nqikcmgbpmkixjds33492klrp9m96xrbmhgizc6"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -291,9 +299,9 @@ rec { }; "argminmax" = rec { crateName = "argminmax"; - version = "0.6.1"; + version = "0.6.2"; edition = "2021"; - sha256 = "1lnvpkvdsvdbsinhik6srx5c2j3gqkaj92iz93pnbdr9cjs0h890"; + sha256 = "1alfp2wfh3pms6f5fj8qw9birndgac2jd2shdl2xascxsrclnhjj"; authors = [ "Jeroen Van Der Donckt" ]; @@ -318,13 +326,30 @@ rec { version = "0.2.0"; edition = "2021"; sha256 = "0xpbqf7qkvzplpjd7f0wbcf2n1v9vygdccwxkd1amxp4il0hlzdz"; + libName = "array_init_cursor"; }; + "arrayvec" = rec { + crateName = "arrayvec"; + version = "0.7.6"; + edition = "2018"; + sha256 = "0l1fz4ccgv6pm609rif37sl5nv5k6lbzi7kkppgzqzh1vwix20kw"; + authors = [ + "bluss" + ]; + features = { + "borsh" = [ "dep:borsh" ]; + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + }; "arrow-format" = rec { crateName = "arrow-format"; version = "0.8.1"; edition = "2018"; sha256 = "1irj67p6c224dzw86jr7j3z9r5zfid52gy6ml8rdqk4r2si4x207"; + libName = "arrow_format"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" ]; @@ -357,9 +382,10 @@ rec { }; "async-stream" = rec { crateName = "async-stream"; - version = "0.3.5"; - edition = "2018"; - sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + version = "0.3.6"; + edition = "2021"; + sha256 = "0xl4zqncrdmw2g6241wgr11dxdg4h7byy6bz3l6si03qyfk72nhb"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -381,10 +407,11 @@ rec { }; "async-stream-impl" = rec { crateName = "async-stream-impl"; - version = "0.3.5"; - edition = "2018"; - sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; + version = "0.3.6"; + edition = "2021"; + sha256 = "0kaplfb5axsvf1gfs2gk6c4zx6zcsns0yf3ssk7iwni7bphlvhn7"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -399,7 +426,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" "visit-mut" ]; } ]; @@ -407,10 +434,11 @@ rec { }; "async-trait" = rec { crateName = "async-trait"; - version = "0.1.77"; + version = "0.1.83"; edition = "2021"; - sha256 = "1adf1jh2yg39rkpmqjqyr9xyd6849p0d95425i6imgbhx0syx069"; + sha256 = "1p8q8gm4fv2fdka8hwy2w3f8df7p5inixqi7rlmbnky3wmysw73j"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -425,8 +453,9 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; - features = [ "full" "visit-mut" ]; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "proc-macro" "visit-mut" ]; } ]; @@ -468,9 +497,9 @@ rec { }; "autocfg" = rec { crateName = "autocfg"; - version = "1.1.0"; + version = "1.4.0"; edition = "2015"; - sha256 = "1ylp3cb47ylzabimazvbz9ms6ap784zhb6syaz6c1jqpmcmq0s6l"; + sha256 = "09lz3by90d2hphbq56znag9v87gfpd9gb8nr82hll8z6x2nhprdc"; authors = [ "Josh Stone <cuviper@gmail.com>" ]; @@ -478,9 +507,9 @@ rec { }; "backtrace" = rec { crateName = "backtrace"; - version = "0.3.69"; - edition = "2018"; - sha256 = "0dsq23dhw4pfndkx2nsa1ml2g31idm7ss7ljxp8d57avygivg290"; + version = "0.3.74"; + edition = "2021"; + sha256 = "06pfif7nwx66qf2zaanc2fcq7m64i91ki9imw9xd3bnz5hrwp0ld"; authors = [ "The Rust Project Developers" ]; @@ -512,28 +541,23 @@ rec { packageId = "object"; usesDefaultFeatures = false; target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); - features = [ "read_core" "elf" "macho" "pe" "unaligned" "archive" ]; + features = [ "read_core" "elf" "macho" "pe" "xcoff" "unaligned" "archive" ]; } { name = "rustc-demangle"; packageId = "rustc-demangle"; } - ]; - buildDependencies = [ { - name = "cc"; - packageId = "cc"; + name = "windows-targets"; + packageId = "windows-targets"; + target = { target, features }: (target."windows" or false); } ]; features = { "cpp_demangle" = [ "dep:cpp_demangle" ]; "default" = [ "std" ]; - "rustc-serialize" = [ "dep:rustc-serialize" ]; "serde" = [ "dep:serde" ]; - "serialize-rustc" = [ "rustc-serialize" ]; "serialize-serde" = [ "serde" ]; - "verify-winapi" = [ "winapi/dbghelp" "winapi/handleapi" "winapi/libloaderapi" "winapi/memoryapi" "winapi/minwindef" "winapi/processthreadsapi" "winapi/synchapi" "winapi/tlhelp32" "winapi/winbase" "winapi/winnt" ]; - "winapi" = [ "dep:winapi" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; @@ -565,26 +589,11 @@ rec { }; resolvedDefaultFeatures = [ "alloc" ]; }; - "bitflags 1.3.2" = rec { - crateName = "bitflags"; - version = "1.3.2"; - edition = "2018"; - sha256 = "12ki6w8gn1ldq7yz9y680llwk5gmrhrzszaa17g1sbrw2r2qvwxy"; - authors = [ - "The Rust Project Developers" - ]; - features = { - "compiler_builtins" = [ "dep:compiler_builtins" ]; - "core" = [ "dep:core" ]; - "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; - }; - resolvedDefaultFeatures = [ "default" ]; - }; - "bitflags 2.4.2" = rec { + "bitflags" = rec { crateName = "bitflags"; - version = "2.4.2"; + version = "2.6.0"; edition = "2021"; - sha256 = "1pqd142hyqlzr7p9djxq2ff0jx07a2sb2xp9lhw69cbf80s0jmzd"; + sha256 = "1pkidwzn3hnxlsl8zizh0bncgbjnw7c41cx7bby26ncbzmiznj5h"; authors = [ "The Rust Project Developers" ]; @@ -602,6 +611,7 @@ rec { version = "0.10.4"; edition = "2018"; sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -615,10 +625,10 @@ rec { }; "brotli" = rec { crateName = "brotli"; - version = "3.4.0"; + version = "3.5.0"; edition = "2015"; crateBin = [ ]; - sha256 = "03qhcq09a6f8y4gm0bmsn7jrq5804cwpkcx3fyay1g7lgsj78q2i"; + sha256 = "14f34ml3i8qbnh4hhlv5r6j10bkx420gspsl1cgznl1wqrdx4h6n"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" "The Brotli Authors" @@ -657,6 +667,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "0kyyh9701dwqzwvn2frff4ww0zibikqd1s1xvl7n1pfpc3z4lbjf"; + libName = "brotli_decompressor"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" "The Brotli Authors" @@ -682,9 +693,9 @@ rec { }; "bstr" = rec { crateName = "bstr"; - version = "1.9.0"; + version = "1.10.0"; edition = "2021"; - sha256 = "1p6hzf3wqwwynv6w4pn17jg21amfafph9kb5sfvf1idlli8h13y4"; + sha256 = "036wwrchd5gq3q4k6w1j2bfl2bk2ff8c0dsa9y7w7aw7nf7knwj0"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -696,7 +707,7 @@ rec { } { name = "regex-automata"; - packageId = "regex-automata"; + packageId = "regex-automata 0.4.8"; optional = true; usesDefaultFeatures = false; features = [ "dfa-search" ]; @@ -719,22 +730,23 @@ rec { }; "bumpalo" = rec { crateName = "bumpalo"; - version = "3.14.0"; + version = "3.16.0"; edition = "2021"; - sha256 = "1v4arnv9kwk54v5d0qqpv4vyw2sgr660nk0w3apzixi1cm3yfc3z"; + sha256 = "0b015qb4knwanbdlp1x48pkb4pm57b8gidbhhhxr900q2wb6fabr"; authors = [ "Nick Fitzgerald <fitzgen@gmail.com>" ]; features = { "allocator-api2" = [ "dep:allocator-api2" ]; + "serde" = [ "dep:serde" ]; }; resolvedDefaultFeatures = [ "default" ]; }; "bytemuck" = rec { crateName = "bytemuck"; - version = "1.14.2"; + version = "1.18.0"; edition = "2018"; - sha256 = "0aylwb0l3zx2c212k2nwik4zmbhw5826y7icav0w2ja9vadxccga"; + sha256 = "1bp2s9wn0gjsaygv21nsbfpf854vl897ll6sqpfn3naaannv1fwl"; authors = [ "Lokathor <zefria@gmail.com>" ]; @@ -749,14 +761,15 @@ rec { "bytemuck_derive" = [ "dep:bytemuck_derive" ]; "derive" = [ "bytemuck_derive" ]; "extern_crate_std" = [ "extern_crate_alloc" ]; + "latest_stable_rust" = [ "aarch64_simd" "align_offset" "const_zeroed" "derive" "min_const_generics" "must_cast" "wasm_simd" "zeroable_atomics" "zeroable_maybe_uninit" ]; }; resolvedDefaultFeatures = [ "bytemuck_derive" "derive" "extern_crate_alloc" ]; }; "bytemuck_derive" = rec { crateName = "bytemuck_derive"; - version = "1.5.0"; + version = "1.8.0"; edition = "2018"; - sha256 = "1cgj75df2v32l4fmvnp25xxkkz4lp6hz76f7hfhd55wgbzmvfnln"; + sha256 = "1v5r33dgl12rqbvh440fdjxmxxr49qpzmg6vpw5jzdbcjk6w7z5w"; procMacro = true; authors = [ "Lokathor <zefria@gmail.com>" @@ -772,16 +785,28 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; } ]; }; + "byteorder" = rec { + crateName = "byteorder"; + version = "1.5.0"; + edition = "2021"; + sha256 = "0jzncxyf404mwqdbspihyzpkndfgda450l0893pz5xj685cg5l0z"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + }; + }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.7.2"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "1wzs7l57iwqmrszdpr2mmqf1b1hgvpxafc30imxhnry0zfl9m3a2"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -794,10 +819,9 @@ rec { }; "cc" = rec { crateName = "cc"; - version = "1.0.83"; + version = "1.1.29"; edition = "2018"; - crateBin = [ ]; - sha256 = "1l643zidlb5iy1dskc5ggqs4wqa29a02f44piczqc8zcnsq4y5zi"; + sha256 = "1ldw40qx2lwk9021f64cdf6d286c5zbb2gk456qqp94l66n09s2q"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -806,25 +830,31 @@ rec { name = "jobserver"; packageId = "jobserver"; optional = true; + usesDefaultFeatures = false; } { name = "libc"; packageId = "libc"; + optional = true; usesDefaultFeatures = false; target = { target, features }: (target."unix" or false); } + { + name = "shlex"; + packageId = "shlex"; + } ]; features = { - "jobserver" = [ "dep:jobserver" ]; - "parallel" = [ "jobserver" ]; + "parallel" = [ "dep:libc" "dep:jobserver" ]; }; - resolvedDefaultFeatures = [ "jobserver" "parallel" ]; + resolvedDefaultFeatures = [ "parallel" ]; }; "cfg-if" = rec { crateName = "cfg-if"; version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -836,9 +866,9 @@ rec { }; "chrono" = rec { crateName = "chrono"; - version = "0.4.33"; + version = "0.4.38"; edition = "2021"; - sha256 = "1szr180x4srkwvmzq5ahqnf3m7yjjllfmgp7k3hsrr556l76j4wz"; + sha256 = "009l8vc5p8750vn02z30mblg4pv2qhkbfizhfwmzc6vpy5nr67x2"; dependencies = [ { name = "android-tzdata"; @@ -860,7 +890,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets 0.52.0"; + packageId = "windows-targets"; optional = true; target = { target, features }: (target."windows" or false); } @@ -879,7 +909,6 @@ rec { "rkyv-32" = [ "dep:rkyv" "rkyv?/size_32" ]; "rkyv-64" = [ "dep:rkyv" "rkyv?/size_64" ]; "rkyv-validation" = [ "rkyv?/validation" ]; - "rustc-serialize" = [ "dep:rustc-serialize" ]; "serde" = [ "dep:serde" ]; "std" = [ "alloc" ]; "unstable-locales" = [ "pure-rust-locales" ]; @@ -892,9 +921,10 @@ rec { }; "comfy-table" = rec { crateName = "comfy-table"; - version = "7.1.0"; + version = "7.1.1"; edition = "2021"; - sha256 = "11i6sm6vznv9982hqpbrba43vfd7vv7zqzlywdc4qykvdhyh8r3w"; + sha256 = "1xsjhi63kkzm05im0jwz0z2gprbicz7c5xdgnaczxpipaf8iahdk"; + libName = "comfy_table"; authors = [ "Arne Beer <contact@arne.beer>" ]; @@ -920,7 +950,7 @@ rec { } { name = "strum_macros"; - packageId = "strum_macros"; + packageId = "strum_macros 0.26.4"; } { name = "unicode-width"; @@ -928,20 +958,63 @@ rec { } ]; features = { + "ansi-str" = [ "dep:ansi-str" ]; "console" = [ "dep:console" ]; "crossterm" = [ "dep:crossterm" ]; - "custom_styling" = [ "console" ]; + "custom_styling" = [ "ansi-str" "console" "tty" ]; "default" = [ "tty" ]; "reexport_crossterm" = [ "tty" ]; "tty" = [ "crossterm" ]; }; resolvedDefaultFeatures = [ "crossterm" "tty" ]; }; + "console" = rec { + crateName = "console"; + version = "0.15.8"; + edition = "2018"; + sha256 = "1sz4nl9nz8pkmapqni6py7jxzi7nzqjxzb3ya4kxvmkb0zy867qf"; + authors = [ + "Armin Ronacher <armin.ronacher@active-4.com>" + ]; + dependencies = [ + { + name = "encode_unicode"; + packageId = "encode_unicode"; + target = { target, features }: (target."windows" or false); + } + { + name = "lazy_static"; + packageId = "lazy_static"; + } + { + name = "libc"; + packageId = "libc"; + } + { + name = "unicode-width"; + packageId = "unicode-width"; + optional = true; + } + { + name = "windows-sys"; + packageId = "windows-sys"; + target = { target, features }: (target."windows" or false); + features = [ "Win32_Foundation" "Win32_System_Console" "Win32_Storage_FileSystem" "Win32_UI_Input_KeyboardAndMouse" ]; + } + ]; + features = { + "default" = [ "unicode-width" "ansi-parsing" ]; + "unicode-width" = [ "dep:unicode-width" ]; + "windows-console-colors" = [ "ansi-parsing" ]; + }; + resolvedDefaultFeatures = [ "ansi-parsing" "unicode-width" ]; + }; "const-oid" = rec { crateName = "const-oid"; version = "0.9.6"; edition = "2021"; sha256 = "1y0jnqaq7p2wvspnx7qj76m7hjcqpz73qzvr9l2p9n2s51vr6if2"; + libName = "const_oid"; authors = [ "RustCrypto Developers" ]; @@ -951,9 +1024,10 @@ rec { }; "core-foundation-sys" = rec { crateName = "core-foundation-sys"; - version = "0.8.6"; + version = "0.8.7"; edition = "2018"; - sha256 = "13w6sdf06r0hn7bx2b45zxsg1mm2phz34jikm6xc5qrbr6djpsh6"; + sha256 = "12w8j73lazxmr1z0h98hf3z623kl8ms7g07jch7n4p8f9nwlhdkp"; + libName = "core_foundation_sys"; authors = [ "The Servo Project Developers" ]; @@ -964,9 +1038,9 @@ rec { }; "cpufeatures" = rec { crateName = "cpufeatures"; - version = "0.2.12"; + version = "0.2.14"; edition = "2018"; - sha256 = "012m7rrak4girqlii3jnqwrr73gv1i980q4wra5yyyhvzwk5xzjk"; + sha256 = "1q3qd9qkw94vs7n5i0y3zz2cqgzcxvdgyb54ryngwmjhfbgrg1k0"; authors = [ "RustCrypto Developers" ]; @@ -974,7 +1048,7 @@ rec { { name = "libc"; packageId = "libc"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-linux-android"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-linux-android"); } { name = "libc"; @@ -996,9 +1070,9 @@ rec { }; "crc32fast" = rec { crateName = "crc32fast"; - version = "1.3.2"; + version = "1.4.2"; edition = "2015"; - sha256 = "03c8f29yx293yf43xar946xbls1g60c207m9drf8ilqhr25vsh5m"; + sha256 = "1czp7vif73b8xslr3c9yxysmh9ws2r8824qda7j47ffs9pcnjxx9"; authors = [ "Sam Rijs <srijs@airpost.net>" "Alex Crichton <alex@alexcrichton.com>" @@ -1016,9 +1090,10 @@ rec { }; "crossbeam-channel" = rec { crateName = "crossbeam-channel"; - version = "0.5.11"; + version = "0.5.13"; edition = "2021"; - sha256 = "16v48qdflpw3hgdik70bhsj7hympna79q7ci47rw0mlgnxsw2v8p"; + sha256 = "1wkx45r34v7g3wyi3lg2wz536lrrrab4h4hh741shfhr8rlhsj1k"; + libName = "crossbeam_channel"; dependencies = [ { name = "crossbeam-utils"; @@ -1037,6 +1112,7 @@ rec { version = "0.8.5"; edition = "2021"; sha256 = "03bp38ljx4wj6vvy4fbhx41q8f585zyqix6pncz1mkz93z08qgv1"; + libName = "crossbeam_deque"; dependencies = [ { name = "crossbeam-epoch"; @@ -1060,6 +1136,7 @@ rec { version = "0.9.18"; edition = "2021"; sha256 = "03j2np8llwf376m3fxqx859mgp9f83hj1w34153c7a9c7i5ar0jv"; + libName = "crossbeam_epoch"; dependencies = [ { name = "crossbeam-utils"; @@ -1081,6 +1158,7 @@ rec { version = "0.3.11"; edition = "2021"; sha256 = "0d8y8y3z48r9javzj67v3p2yfswd278myz1j9vzc4sp7snslc0yz"; + libName = "crossbeam_queue"; dependencies = [ { name = "crossbeam-utils"; @@ -1097,9 +1175,10 @@ rec { }; "crossbeam-utils" = rec { crateName = "crossbeam-utils"; - version = "0.8.19"; + version = "0.8.20"; edition = "2021"; - sha256 = "0iakrb1b8fjqrag7wphl94d10irhbh2fw1g444xslsywqyn3p3i4"; + sha256 = "100fksq5mm1n7zj242cclkw6yf7a4a8ix3lvpfkhxvdhbda9kv12"; + libName = "crossbeam_utils"; features = { "default" = [ "std" ]; "loom" = [ "dep:loom" ]; @@ -1117,7 +1196,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags"; } { name = "crossterm_winapi"; @@ -1176,6 +1255,7 @@ rec { version = "0.1.6"; edition = "2018"; sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; authors = [ "RustCrypto Developers" ]; @@ -1198,9 +1278,10 @@ rec { }; "curve25519-dalek" = rec { crateName = "curve25519-dalek"; - version = "4.1.2"; + version = "4.1.3"; edition = "2021"; - sha256 = "0j7kqchcgycs4a11gvlda93h9w2jr05nn4hjpfyh2kn94a4pnrqa"; + sha256 = "1gmjb9dsknrr8lypmhkyjd67p1arb8mbfamlwxm7vph38my8pywp"; + libName = "curve25519_dalek"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -1246,10 +1327,6 @@ rec { ]; buildDependencies = [ { - name = "platforms"; - packageId = "platforms"; - } - { name = "rustc_version"; packageId = "rustc_version"; } @@ -1273,6 +1350,7 @@ rec { edition = "2021"; sha256 = "1cry71xxrr0mcy5my3fb502cwfxy6822k4pm19cwrilrg7hq4s7l"; procMacro = true; + libName = "curve25519_dalek_derive"; dependencies = [ { name = "proc-macro2"; @@ -1284,7 +1362,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -1292,9 +1370,10 @@ rec { }; "data-encoding" = rec { crateName = "data-encoding"; - version = "2.5.0"; + version = "2.6.0"; edition = "2018"; - sha256 = "1rcbnwfmfxhlshzbn3r7srm3azqha3mn33yxyqxkzz2wpqcjm5ky"; + sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -1306,9 +1385,9 @@ rec { }; "der" = rec { crateName = "der"; - version = "0.7.8"; + version = "0.7.9"; edition = "2021"; - sha256 = "070bwiyr80800h31c5zd96ckkgagfjgnrrdmz3dzg2lccsd3dypz"; + sha256 = "1h4vzjfa1lczxdf8avfj9qlwh1qianqlxdy1g5rn762qnvkzhnzm"; authors = [ "RustCrypto Developers" ]; @@ -1375,9 +1454,10 @@ rec { }; "dyn-clone" = rec { crateName = "dyn-clone"; - version = "1.0.16"; + version = "1.0.17"; edition = "2018"; - sha256 = "0pa9kas6a241pbx0q82ipwi4f7m7wwyzkkc725caky24gl4j4nsl"; + sha256 = "09cig7dgg6jnqa10p4233nd8wllbjf4ffsw7wj0m4lwa5w3z0vhd"; + libName = "dyn_clone"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -1420,6 +1500,7 @@ rec { version = "2.1.1"; edition = "2021"; sha256 = "0w88cafwglg9hjizldbmlza0ns3hls81zk1bcih3m5m3h67algaa"; + libName = "ed25519_dalek"; authors = [ "isis lovecruft <isis@patternsinthevoid.net>" "Tony Arcieri <bascule@gmail.com>" @@ -1494,9 +1575,9 @@ rec { }; "either" = rec { crateName = "either"; - version = "1.9.0"; + version = "1.13.0"; edition = "2018"; - sha256 = "01qy3anr7jal5lpc20791vxrw0nl6vksb5j7x56q2fycgcyy8sm2"; + sha256 = "1w2c1mybrd7vljyxk77y9f4w9dyjrmp3yp82mk7bcm8848fazcb0"; authors = [ "bluss" ]; @@ -1506,11 +1587,53 @@ rec { }; resolvedDefaultFeatures = [ "default" "use_std" ]; }; + "encode_unicode" = rec { + crateName = "encode_unicode"; + version = "0.3.6"; + edition = "2015"; + sha256 = "07w3vzrhxh9lpjgsg2y5bwzfar2aq35mdznvcp3zjl0ssj7d4mx3"; + authors = [ + "Torbjørn Birch Moltu <t.b.moltu@lyse.net>" + ]; + features = { + "ascii" = [ "dep:ascii" ]; + "clippy" = [ "dep:clippy" ]; + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "enum-primitive-derive" = rec { + crateName = "enum-primitive-derive"; + version = "0.3.0"; + edition = "2018"; + sha256 = "0k6wcf58h5kh64yq5nfq71va53kaya0kzxwsjwbgwm2n2zd9axxs"; + procMacro = true; + libName = "enum_primitive_derive"; + authors = [ + "Doug Goldstein <cardoe@cardoe.com>" + ]; + dependencies = [ + { + name = "num-traits"; + packageId = "num-traits"; + usesDefaultFeatures = false; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + } + ]; + + }; "enum_dispatch" = rec { crateName = "enum_dispatch"; - version = "0.3.12"; + version = "0.3.13"; edition = "2018"; - sha256 = "03l998igqfzkykmj8i5qlbwhv2id9jn98fkkl82lv3dvg0q32cwg"; + sha256 = "1kby2jz173ggg7wk41vjsskmkdyx7749ll8lhqhv6mb5qqmww65a"; procMacro = true; authors = [ "Anton Lazarev <https://antonok.com>" @@ -1530,7 +1653,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -1562,6 +1685,7 @@ rec { version = "0.1.9"; edition = "2015"; sha256 = "0nj6j26p71bjy8h42x6jahx1hn0ng6mc2miwpgwnp8vnwqf4jq3k"; + libName = "fallible_streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -1572,6 +1696,7 @@ rec { version = "0.2.0"; edition = "2018"; sha256 = "0g7kfll3xyh99kc7r352lhljnwvgayxxa6saifb6725inikmyxlm"; + libName = "fast_float"; authors = [ "Ivan Smirnov <i.s.smirnov@gmail.com>" ]; @@ -1582,9 +1707,10 @@ rec { }; "fiat-crypto" = rec { crateName = "fiat-crypto"; - version = "0.2.6"; + version = "0.2.9"; edition = "2018"; - sha256 = "10hkkkjynhibvchznkxx81gwxqarn9i5sgz40d6xxb8xzhsz8xhn"; + sha256 = "07c1vknddv3ak7w89n85ik0g34nzzpms6yb845vrjnv9m4csbpi8"; + libName = "fiat_crypto"; authors = [ "Fiat Crypto library authors <jgross@mit.edu>" ]; @@ -1594,9 +1720,9 @@ rec { }; "flate2" = rec { crateName = "flate2"; - version = "1.0.28"; + version = "1.0.34"; edition = "2018"; - sha256 = "03llhsh4gqdirnfxxb9g2w9n0721dyn4yjir3pz7z4vjaxb3yc26"; + sha256 = "1w1nf2ap4q1sq1v6v951011wcvljk449ap7q7jnnjf8hvjs8kdd1"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Josh Triplett <josh@joshtriplett.org>" @@ -1627,6 +1753,7 @@ rec { "cloudflare_zlib" = [ "any_zlib" "cloudflare-zlib-sys" ]; "default" = [ "rust_backend" ]; "libz-ng-sys" = [ "dep:libz-ng-sys" ]; + "libz-rs-sys" = [ "dep:libz-rs-sys" ]; "libz-sys" = [ "dep:libz-sys" ]; "miniz-sys" = [ "rust_backend" ]; "miniz_oxide" = [ "dep:miniz_oxide" ]; @@ -1635,6 +1762,7 @@ rec { "zlib-default" = [ "any_zlib" "libz-sys/default" ]; "zlib-ng" = [ "any_zlib" "libz-ng-sys" ]; "zlib-ng-compat" = [ "zlib" "libz-sys/zlib-ng" ]; + "zlib-rs" = [ "any_zlib" "libz-rs-sys" ]; }; resolvedDefaultFeatures = [ "any_impl" "miniz_oxide" "rust_backend" ]; }; @@ -1650,9 +1778,9 @@ rec { }; "futures" = rec { crateName = "futures"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1c04g14bccmprwsvx2j9m2blhwrynq7vhl151lsvcv4gi0b6jp34"; + sha256 = "0xh8ddbkm9jy8kc5gbvjp9a4b6rqqxvc8471yb2qaz5wm2qhgg35"; dependencies = [ { name = "futures-channel"; @@ -1711,9 +1839,10 @@ rec { }; "futures-channel" = rec { crateName = "futures-channel"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "0y6b7xxqdjm9hlcjpakcg41qfl7lihf6gavk8fyqijsxhvbzgj7a"; + sha256 = "040vpqpqlbk099razq8lyn74m0f161zd0rp36hciqrwcg2zibzrd"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -1738,9 +1867,10 @@ rec { }; "futures-core" = rec { crateName = "futures-core"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "07aslayrn3lbggj54kci0ishmd1pr367fp7iks7adia1p05miinz"; + sha256 = "0gk6yrxgi5ihfanm2y431jadrll00n5ifhnpx090c2f2q1cr1wh5"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -1750,9 +1880,10 @@ rec { }; "futures-executor" = rec { crateName = "futures-executor"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "07dh08gs9vfll2h36kq32q9xd86xm6lyl9xikmmwlkqnmrrgqxm5"; + sha256 = "17vcci6mdfzx4gbk0wx64chr2f13wwwpvyf3xd5fb1gmjzcx2a0y"; + libName = "futures_executor"; dependencies = [ { name = "futures-core"; @@ -1780,9 +1911,10 @@ rec { }; "futures-io" = rec { crateName = "futures-io"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1hgh25isvsr4ybibywhr4dpys8mjnscw4wfxxwca70cn1gi26im4"; + sha256 = "1ikmw1yfbgvsychmsihdkwa8a1knank2d9a8dk01mbjar9w1np4y"; + libName = "futures_io"; features = { "default" = [ "std" ]; }; @@ -1790,10 +1922,11 @@ rec { }; "futures-macro" = rec { crateName = "futures-macro"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1b49qh9d402y8nka4q6wvvj0c88qq91wbr192mdn5h54nzs0qxc7"; + sha256 = "0l1n7kqzwwmgiznn0ywdc5i24z72zvh9q1dwps54mimppi7f6bhn"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -1805,7 +1938,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -1813,9 +1946,10 @@ rec { }; "futures-sink" = rec { crateName = "futures-sink"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1dag8xyyaya8n8mh8smx7x6w2dpmafg2din145v973a3hw7f1f4z"; + sha256 = "1xyly6naq6aqm52d5rh236snm08kw8zadydwqz8bip70s6vzlxg5"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1824,9 +1958,10 @@ rec { }; "futures-task" = rec { crateName = "futures-task"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "013h1724454hj8qczp8vvs10qfiqrxr937qsrv6rhii68ahlzn1q"; + sha256 = "124rv4n90f5xwfsm9qw6y99755y021cmi5dhzh253s920z77s3zr"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1835,9 +1970,10 @@ rec { }; "futures-util" = rec { crateName = "futures-util"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "0j0xqhcir1zf2dcbpd421kgw6wvsk0rpxflylcysn1rlp3g02r1x"; + sha256 = "10aa1ar8bgkgbr4wzxlidkqkcxf77gffyj8j7768h831pcaq784z"; + libName = "futures_util"; dependencies = [ { name = "futures-channel"; @@ -1948,9 +2084,9 @@ rec { }; "getrandom" = rec { crateName = "getrandom"; - version = "0.2.12"; + version = "0.2.15"; edition = "2018"; - sha256 = "1d8jb9bv38nkwlqqdjcav6gxckgwc9g30pm3qq506rvncpm9400r"; + sha256 = "1mzlnrb3dgyd1fb84gvw10pyr8wdqdl4ry4sr64i1s8an66pqmn4"; authors = [ "The Rand Project Developers" ]; @@ -1997,9 +2133,9 @@ rec { }; "gimli" = rec { crateName = "gimli"; - version = "0.28.1"; + version = "0.31.1"; edition = "2018"; - sha256 = "0lv23wc8rxvmjia3mcxc6hj9vkqnv1bqq0h8nzjcgf71mrxx6wa2"; + sha256 = "0gvqc0ramx8szv76jhfd4dms0zyamvlg4whhiz11j34hh3dqxqh7"; features = { "default" = [ "read-all" "write" ]; "endian-reader" = [ "read" "dep:stable_deref_trait" ]; @@ -2022,11 +2158,11 @@ rec { ]; }; - "hashbrown" = rec { + "hashbrown 0.14.5" = rec { crateName = "hashbrown"; - version = "0.14.3"; + version = "0.14.5"; edition = "2021"; - sha256 = "012nywlg0lj9kwanh69my5x67vjlfmzfi9a0rq4qvis2j8fil3r9"; + sha256 = "1wa1vy1xs3mp11bn3z9dv0jricgr6a2j0zkf1g19yz3vw4il89z5"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -2070,9 +2206,32 @@ rec { "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" ]; "serde" = [ "dep:serde" ]; }; - resolvedDefaultFeatures = [ "ahash" "allocator-api2" "default" "inline-more" "raw" "rayon" ]; + resolvedDefaultFeatures = [ "ahash" "allocator-api2" "default" "inline-more" "rayon" ]; }; - "heck" = rec { + "hashbrown 0.15.0" = rec { + crateName = "hashbrown"; + version = "0.15.0"; + edition = "2021"; + sha256 = "1yx4xq091s7i6mw6bn77k8cp4jrpcac149xr32rg8szqsj27y20y"; + authors = [ + "Amanieu d'Antras <amanieu@gmail.com>" + ]; + features = { + "alloc" = [ "dep:alloc" ]; + "allocator-api2" = [ "dep:allocator-api2" ]; + "borsh" = [ "dep:borsh" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "default-hasher" "inline-more" "allocator-api2" "equivalent" "raw-entry" ]; + "default-hasher" = [ "dep:foldhash" ]; + "equivalent" = [ "dep:equivalent" ]; + "nightly" = [ "allocator-api2?/nightly" "bumpalo/allocator_api" ]; + "rayon" = [ "dep:rayon" ]; + "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" "raw-entry" ]; + "serde" = [ "dep:serde" ]; + }; + }; + "heck 0.4.1" = rec { crateName = "heck"; version = "0.4.1"; edition = "2018"; @@ -2086,11 +2245,19 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; + "heck 0.5.0" = rec { + crateName = "heck"; + version = "0.5.0"; + edition = "2021"; + sha256 = "1sjmpsdl8czyh9ywl3qcsfsq9a307dg4ni2vnlwgnzzqhc4y0113"; + + }; "hermit-abi" = rec { crateName = "hermit-abi"; - version = "0.3.5"; + version = "0.3.9"; edition = "2021"; - sha256 = "1hw2bxkzyvr0rbnpj0lkasi8h8qf3lyb63hp760cn22fjqaj3inh"; + sha256 = "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -2113,7 +2280,7 @@ rec { dependencies = [ { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; + packageId = "windows-sys"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_UI_Shell" "Win32_System_Com" ]; } @@ -2122,9 +2289,10 @@ rec { }; "iana-time-zone" = rec { crateName = "iana-time-zone"; - version = "0.1.60"; + version = "0.1.61"; edition = "2018"; - sha256 = "0hdid5xz3jznm04lysjm3vi93h3c523w0hcc3xba47jl3ddbpzz7"; + sha256 = "085jjsls330yj1fnwykfzmb2f10zp6l7w4fhq81ng81574ghhpi3"; + libName = "iana_time_zone"; authors = [ "Andrew Straw <strawman@astraw.com>" "René Kijewski <rene.kijewski@fu-berlin.de>" @@ -2149,12 +2317,12 @@ rec { { name = "js-sys"; packageId = "js-sys"; - target = { target, features }: ("wasm32" == target."arch" or null); + target = { target, features }: (("wasm32" == target."arch" or null) && ("unknown" == target."os" or null)); } { name = "wasm-bindgen"; packageId = "wasm-bindgen"; - target = { target, features }: ("wasm32" == target."arch" or null); + target = { target, features }: (("wasm32" == target."arch" or null) && ("unknown" == target."os" or null)); } { name = "windows-core"; @@ -2170,6 +2338,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k"; + libName = "iana_time_zone_haiku"; authors = [ "René Kijewski <crates.io@k6i.de>" ]; @@ -2183,9 +2352,9 @@ rec { }; "indexmap" = rec { crateName = "indexmap"; - version = "2.2.2"; + version = "2.6.0"; edition = "2021"; - sha256 = "087mafd9f98rp1xk2jc1rsp5yyqz63yi30cy8yx6c8s14bj2ljw2"; + sha256 = "1nmrwn8lbs19gkvhxaawffzbvrpyrb5y3drcrr645x957kz0fybh"; dependencies = [ { name = "equivalent"; @@ -2194,13 +2363,13 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.15.0"; usesDefaultFeatures = false; - features = [ "raw" ]; } ]; features = { "arbitrary" = [ "dep:arbitrary" ]; + "borsh" = [ "dep:borsh" ]; "default" = [ "std" ]; "quickcheck" = [ "dep:quickcheck" ]; "rayon" = [ "dep:rayon" ]; @@ -2209,11 +2378,82 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; + "indicatif" = rec { + crateName = "indicatif"; + version = "0.17.8"; + edition = "2021"; + sha256 = "18xyqxw9i5x4sbpzckhfz3nm984iq9r7nbi2lk76nz888n7mlfkn"; + dependencies = [ + { + name = "console"; + packageId = "console"; + usesDefaultFeatures = false; + features = [ "ansi-parsing" ]; + } + { + name = "instant"; + packageId = "instant"; + target = { target, features }: ("wasm32" == target."arch" or null); + } + { + name = "number_prefix"; + packageId = "number_prefix"; + } + { + name = "portable-atomic"; + packageId = "portable-atomic"; + } + { + name = "unicode-width"; + packageId = "unicode-width"; + optional = true; + } + { + name = "vt100"; + packageId = "vt100"; + optional = true; + } + ]; + features = { + "default" = [ "unicode-width" "console/unicode-width" ]; + "futures" = [ "dep:futures-core" ]; + "improved_unicode" = [ "unicode-segmentation" "unicode-width" "console/unicode-width" ]; + "in_memory" = [ "vt100" ]; + "rayon" = [ "dep:rayon" ]; + "tokio" = [ "dep:tokio" ]; + "unicode-segmentation" = [ "dep:unicode-segmentation" ]; + "unicode-width" = [ "dep:unicode-width" ]; + "vt100" = [ "dep:vt100" ]; + }; + resolvedDefaultFeatures = [ "default" "in_memory" "unicode-width" "vt100" ]; + }; + "instant" = rec { + crateName = "instant"; + version = "0.1.13"; + edition = "2018"; + sha256 = "08h27kzvb5jw74mh0ajv0nv9ggwvgqm8ynjsn2sa9jsks4cjh970"; + authors = [ + "sebcrozet <developer@crozet.re>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + ]; + features = { + "js-sys" = [ "dep:js-sys" ]; + "stdweb" = [ "dep:stdweb" ]; + "wasm-bindgen" = [ "js-sys" "wasm-bindgen_rs" "web-sys" ]; + "wasm-bindgen_rs" = [ "dep:wasm-bindgen_rs" ]; + "web-sys" = [ "dep:web-sys" ]; + }; + }; "itoa" = rec { crateName = "itoa"; - version = "1.0.10"; + version = "1.0.11"; edition = "2018"; - sha256 = "0k7xjfki7mnv6yzjrbnbnjllg86acmbnk4izz2jmm1hx2wd6v95i"; + sha256 = "0nv9cqjwzr3q58qz84dcz63ggc54yhf1yqar1m858m1kfd4g3wa9"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -2223,9 +2463,9 @@ rec { }; "jobserver" = rec { crateName = "jobserver"; - version = "0.1.27"; - edition = "2018"; - sha256 = "0z9w6vfqwbr6hfk9yaw7kydlh6f7k39xdlszxlh39in4acwzcdwc"; + version = "0.1.32"; + edition = "2021"; + sha256 = "1l2k50qmj84x9mn39ivjz76alqmx72jhm12rw33zx9xnpv5xpla8"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -2240,9 +2480,10 @@ rec { }; "js-sys" = rec { crateName = "js-sys"; - version = "0.3.68"; - edition = "2018"; - sha256 = "1vm98fhnhs4w6yakchi9ip7ar95900k9vkr24a21qlwd6r5xlv20"; + version = "0.3.72"; + edition = "2021"; + sha256 = "1a8r61hbgw5kmscgj3g5pzg2ywlnswvljy0l592v0xdxlayz323a"; + libName = "js_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -2254,11 +2495,24 @@ rec { ]; }; + "lazy_static" = rec { + crateName = "lazy_static"; + version = "1.5.0"; + edition = "2015"; + sha256 = "1zk6dqqni0193xg6iijh7i3i44sryglwgvx20spdvwk3r6sbrlmv"; + authors = [ + "Marvin Löbel <loebel.marvin@gmail.com>" + ]; + features = { + "spin" = [ "dep:spin" ]; + "spin_no_std" = [ "spin" ]; + }; + }; "libc" = rec { crateName = "libc"; - version = "0.2.153"; + version = "0.2.159"; edition = "2015"; - sha256 = "1gg7m1ils5dms5miq9fyllrcp0jxnbpgkx71chd2i0lafa8qy6cw"; + sha256 = "1i9xpia0hn1y8dws7all8rqng6h3lc8ymlgslnljcvm376jrf7an"; authors = [ "The Rust Project Developers" ]; @@ -2284,11 +2538,38 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; + "libmimalloc-sys" = rec { + crateName = "libmimalloc-sys"; + version = "0.1.39"; + edition = "2018"; + links = "mimalloc"; + sha256 = "0i3b0dzz7cp0ik7ys66q92r16va78gwlbrnxhj5fnkdxsc8niai3"; + libName = "libmimalloc_sys"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cty" = [ "dep:cty" ]; + "extended" = [ "cty" ]; + }; + }; "lock_api" = rec { crateName = "lock_api"; - version = "0.4.11"; - edition = "2018"; - sha256 = "0iggx0h4jx63xm35861106af3jkxq06fpqhpkhgw0axi2n38y5iw"; + version = "0.4.12"; + edition = "2021"; + sha256 = "05qvxa6g27yyva25a5ghsg85apdxkvr77yhkyhapj6r8vnf8pbq7"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -2314,29 +2595,33 @@ rec { }; "log" = rec { crateName = "log"; - version = "0.4.20"; - edition = "2015"; - sha256 = "13rf7wphnwd61vazpxr7fiycin6cb1g8fmvgqg18i464p0y1drmm"; + version = "0.4.22"; + edition = "2021"; + sha256 = "093vs0wkm1rgyykk7fjbqp2lwizbixac1w52gv109p5r4jh0p9x7"; authors = [ "The Rust Project Developers" ]; features = { - "kv_unstable" = [ "value-bag" ]; - "kv_unstable_serde" = [ "kv_unstable_std" "value-bag/serde" "serde" ]; - "kv_unstable_std" = [ "std" "kv_unstable" "value-bag/error" ]; - "kv_unstable_sval" = [ "kv_unstable" "value-bag/sval" "sval" "sval_ref" ]; + "kv_serde" = [ "kv_std" "value-bag/serde" "serde" ]; + "kv_std" = [ "std" "kv" "value-bag/error" ]; + "kv_sval" = [ "kv" "value-bag/sval" "sval" "sval_ref" ]; + "kv_unstable" = [ "kv" "value-bag" ]; + "kv_unstable_serde" = [ "kv_serde" "kv_unstable_std" ]; + "kv_unstable_std" = [ "kv_std" "kv_unstable" ]; + "kv_unstable_sval" = [ "kv_sval" "kv_unstable" ]; "serde" = [ "dep:serde" ]; "sval" = [ "dep:sval" ]; "sval_ref" = [ "dep:sval_ref" ]; "value-bag" = [ "dep:value-bag" ]; }; + resolvedDefaultFeatures = [ "std" ]; }; "lz4" = rec { crateName = "lz4"; - version = "1.24.0"; + version = "1.28.0"; edition = "2018"; crateBin = [ ]; - sha256 = "1wad97k0asgvaj16ydd09gqs2yvgaanzcvqglrhffv7kdpc2v7ky"; + sha256 = "09b70ciyfbynzpy3yf501ab9f8chyyl0dppfh0cxv7d7njrfn7sd"; authors = [ "Jens Heyens <jens.heyens@ewetel.net>" "Artem V. Navrotskiy <bozaro@buzzsoft.ru>" @@ -2344,10 +2629,6 @@ rec { ]; dependencies = [ { - name = "libc"; - packageId = "libc"; - } - { name = "lz4-sys"; packageId = "lz4-sys"; } @@ -2356,10 +2637,11 @@ rec { }; "lz4-sys" = rec { crateName = "lz4-sys"; - version = "1.9.4"; + version = "1.11.1+lz4-1.10.0"; edition = "2015"; links = "lz4"; - sha256 = "0059ik4xlvnss5qfh6l691psk4g3350ljxaykzv10yr0gqqppljp"; + sha256 = "1rhqnhwq05fmlc2q39ipsq0vpi0xf6w6p22j6q5x637dqvbc1n3b"; + libName = "lz4_sys"; authors = [ "Jens Heyens <jens.heyens@ewetel.net>" "Artem V. Navrotskiy <bozaro@buzzsoft.ru>" @@ -2379,11 +2661,27 @@ rec { ]; }; + "matchers" = rec { + crateName = "matchers"; + version = "0.1.0"; + edition = "2018"; + sha256 = "0n2mbk7lg2vf962c8xwzdq96yrc9i0p8dbmm4wa1nnkcp1dhfqw2"; + authors = [ + "Eliza Weisman <eliza@buoyant.io>" + ]; + dependencies = [ + { + name = "regex-automata"; + packageId = "regex-automata 0.1.10"; + } + ]; + + }; "memchr" = rec { crateName = "memchr"; - version = "2.7.1"; + version = "2.7.4"; edition = "2021"; - sha256 = "0jf1kicqa4vs9lyzj4v4y1p90q0dh87hvhsdd5xvhnp527sw8gaj"; + sha256 = "18z32bhxrax0fnjikv475z7ii718hq457qwmaryixfxsl2qrmjkq"; authors = [ "Andrew Gallant <jamslam@gmail.com>" "bluss" @@ -2419,11 +2717,40 @@ rec { "stable_deref_trait" = [ "dep:stable_deref_trait" ]; }; }; + "mimalloc" = rec { + crateName = "mimalloc"; + version = "0.1.43"; + edition = "2018"; + sha256 = "0csnyrxc16i592gm5ffham07jyj2w98qsh9jyy1rv59lmr8474b8"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + "Vincent Rouillé <vincent@speedy37.fr>" + "Thom Chiovoloni <chiovolonit@gmail.com>" + ]; + dependencies = [ + { + name = "libmimalloc-sys"; + packageId = "libmimalloc-sys"; + usesDefaultFeatures = false; + } + ]; + features = { + "debug" = [ "libmimalloc-sys/debug" ]; + "debug_in_debug" = [ "libmimalloc-sys/debug_in_debug" ]; + "extended" = [ "libmimalloc-sys/extended" ]; + "local_dynamic_tls" = [ "libmimalloc-sys/local_dynamic_tls" ]; + "no_thp" = [ "libmimalloc-sys/no_thp" ]; + "override" = [ "libmimalloc-sys/override" ]; + "secure" = [ "libmimalloc-sys/secure" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; "minimal-lexical" = rec { crateName = "minimal-lexical"; version = "0.2.1"; edition = "2018"; sha256 = "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8"; + libName = "minimal_lexical"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2434,17 +2761,17 @@ rec { }; "miniz_oxide" = rec { crateName = "miniz_oxide"; - version = "0.7.2"; - edition = "2018"; - sha256 = "19qlxb21s6kabgqq61mk7kd1qk2invyygj076jz6i1gj2lz1z0cx"; + version = "0.8.0"; + edition = "2021"; + sha256 = "1wadxkg6a6z4lr7kskapj5d8pxlx7cp1ifw4daqnkzqjxych5n72"; authors = [ "Frommi <daniil.liferenko@gmail.com>" "oyvindln <oyvindln@users.noreply.github.com>" ]; dependencies = [ { - name = "adler"; - packageId = "adler"; + name = "adler2"; + packageId = "adler2"; usesDefaultFeatures = false; } ]; @@ -2453,7 +2780,7 @@ rec { "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; "default" = [ "with-alloc" ]; - "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler/rustc-dep-of-std" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler2/rustc-dep-of-std" ]; "simd" = [ "simd-adler32" ]; "simd-adler32" = [ "dep:simd-adler32" ]; }; @@ -2461,9 +2788,9 @@ rec { }; "mio" = rec { crateName = "mio"; - version = "0.8.10"; - edition = "2018"; - sha256 = "02gyaxvaia9zzi4drrw59k9s0j6pa5d1y2kv7iplwjipdqlhngcg"; + version = "1.0.2"; + edition = "2021"; + sha256 = "1v1cnnn44awxbcfm4zlavwgkvbyg7gp5zzjm8mqf1apkrwflvq40"; authors = [ "Carl Lerche <me@carllerche.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -2471,6 +2798,12 @@ rec { ]; dependencies = [ { + name = "hermit-abi"; + packageId = "hermit-abi"; + rename = "libc"; + target = { target, features }: ("hermit" == target."os" or null); + } + { name = "libc"; packageId = "libc"; target = { target, features }: ("wasi" == target."os" or null); @@ -2487,9 +2820,9 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys"; target = { target, features }: (target."windows" or false); - features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; + features = [ "Wdk_Foundation" "Wdk_Storage_FileSystem" "Wdk_System_IO" "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; } ]; features = { @@ -2501,9 +2834,9 @@ rec { }; "multiversion" = rec { crateName = "multiversion"; - version = "0.7.3"; + version = "0.7.4"; edition = "2021"; - sha256 = "0al7yrf489lqzxx291sx9566n7slk2njwlqrxbjhqxk1zvbvkixj"; + sha256 = "0hm1y7dhdbam2yvaxmxzd0bj7gv777y0zn82jjzx0fhxl5hi31f4"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -2526,10 +2859,11 @@ rec { }; "multiversion-macros" = rec { crateName = "multiversion-macros"; - version = "0.7.3"; + version = "0.7.4"; edition = "2021"; - sha256 = "1j1avbxw7jscyi7dmnywhlwbiny1fvg1vpp9fy4dc1pd022kva16"; + sha256 = "142yhgdxvy9qjyi8n4wg2hi1dsckay816g1jg0jpvhp0x7g4v9vr"; procMacro = true; + libName = "multiversion_macros"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -2562,16 +2896,12 @@ rec { version = "0.1.0"; edition = "2021"; crateBin = [ ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ../../nix-compat; } - else ../../nix-compat; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat; }; + libName = "nix_compat"; dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags"; } { name = "bstr"; @@ -2579,6 +2909,11 @@ rec { features = [ "alloc" "unicode" "serde" ]; } { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { name = "data-encoding"; packageId = "data-encoding"; } @@ -2591,14 +2926,36 @@ rec { packageId = "ed25519-dalek"; } { + name = "enum-primitive-derive"; + packageId = "enum-primitive-derive"; + } + { name = "glob"; packageId = "glob"; } { + name = "mimalloc"; + packageId = "mimalloc"; + } + { + name = "nix-compat-derive"; + packageId = "nix-compat-derive"; + optional = true; + } + { name = "nom"; packageId = "nom"; } { + name = "num-traits"; + packageId = "num-traits"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + optional = true; + } + { name = "serde"; packageId = "serde"; features = [ "derive" ]; @@ -2615,17 +2972,63 @@ rec { name = "thiserror"; packageId = "thiserror"; } + { + name = "tokio"; + packageId = "tokio"; + optional = true; + features = [ "io-util" "macros" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } ]; devDependencies = [ { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "serde_json"; packageId = "serde_json"; } ]; features = { - "async" = [ "futures-util" ]; - "futures-util" = [ "dep:futures-util" ]; + "async" = [ "tokio" ]; + "bytes" = [ "dep:bytes" ]; + "default" = [ "async" "wire" "nix-compat-derive" ]; + "nix-compat-derive" = [ "dep:nix-compat-derive" ]; + "pin-project-lite" = [ "dep:pin-project-lite" ]; + "tokio" = [ "dep:tokio" ]; + "wire" = [ "tokio" "pin-project-lite" "bytes" ]; }; + resolvedDefaultFeatures = [ "async" "bytes" "default" "nix-compat-derive" "pin-project-lite" "tokio" "wire" ]; + }; + "nix-compat-derive" = rec { + crateName = "nix-compat-derive"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat-derive; }; + procMacro = true; + libName = "nix_compat_derive"; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + features = [ "proc-macro" ]; + } + { + name = "quote"; + packageId = "quote"; + features = [ "proc-macro" ]; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "full" "extra-traits" ]; + } + ]; + }; "nom" = rec { crateName = "nom"; @@ -2692,11 +3095,41 @@ rec { }; resolvedDefaultFeatures = [ "default" "user" ]; }; + "nu-ansi-term" = rec { + crateName = "nu-ansi-term"; + version = "0.46.0"; + edition = "2018"; + sha256 = "115sywxh53p190lyw97alm14nc004qj5jm5lvdj608z84rbida3p"; + libName = "nu_ansi_term"; + authors = [ + "ogham@bsago.me" + "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>" + "Josh Triplett <josh@joshtriplett.org>" + "The Nushell Project Developers" + ]; + dependencies = [ + { + name = "overload"; + packageId = "overload"; + } + { + name = "winapi"; + packageId = "winapi"; + target = { target, features }: ("windows" == target."os" or null); + features = [ "consoleapi" "errhandlingapi" "fileapi" "handleapi" "processenv" ]; + } + ]; + features = { + "derive_serde_style" = [ "serde" ]; + "serde" = [ "dep:serde" ]; + }; + }; "num-traits" = rec { crateName = "num-traits"; - version = "0.2.18"; - edition = "2018"; - sha256 = "0yjib8p2p9kzmaz48xwhs69w5dh1wipph9jgnillzd2x33jz03fs"; + version = "0.2.19"; + edition = "2021"; + sha256 = "0h984rhdkkqd4ny9cif7y2azl3xdfb7768hb9irhpsch4q3gq787"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -2719,33 +3152,24 @@ rec { }; resolvedDefaultFeatures = [ "default" "libm" "std" ]; }; - "num_cpus" = rec { - crateName = "num_cpus"; - version = "1.16.0"; + "number_prefix" = rec { + crateName = "number_prefix"; + version = "0.4.0"; edition = "2015"; - sha256 = "0hra6ihpnh06dvfvz9ipscys0xfqa9ca9hzp384d5m02ssvgqqa1"; + sha256 = "1wvh13wvlajqxkb1filsfzbrnq0vrmrw298v2j3sy82z1rm282w3"; authors = [ - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "hermit-abi"; - packageId = "hermit-abi"; - target = { target, features }: ("hermit" == target."os" or null); - } - { - name = "libc"; - packageId = "libc"; - target = { target, features }: (!(target."windows" or false)); - } + "Benjamin Sago <ogham@bsago.me>" ]; - + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; }; "object" = rec { crateName = "object"; - version = "0.32.2"; + version = "0.36.5"; edition = "2018"; - sha256 = "0hc4cjwyngiy6k51hlzrlsxgv5z25vv7c2cp0ky1lckfic0259m6"; + sha256 = "0gk8lhbs229c68lapq6w6qmnm4jkj48hrcw5ilfyswy514nhmpxf"; dependencies = [ { name = "memchr"; @@ -2754,13 +3178,15 @@ rec { } ]; features = { - "all" = [ "read" "write" "std" "compression" "wasm" ]; + "all" = [ "read" "write" "build" "std" "compression" "wasm" ]; "alloc" = [ "dep:alloc" ]; + "build" = [ "build_core" "write_std" "elf" ]; + "build_core" = [ "read_core" "write_core" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "compression" = [ "dep:flate2" "dep:ruzstd" "std" ]; "core" = [ "dep:core" ]; "default" = [ "read" "compression" ]; - "doc" = [ "read_core" "write_std" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; + "doc" = [ "read_core" "write_std" "build_core" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; "pe" = [ "coff" ]; "read" = [ "read_core" "archive" "coff" "elf" "macho" "pe" "xcoff" "unaligned" ]; "rustc-dep-of-std" = [ "core" "compiler_builtins" "alloc" "memchr/rustc-dep-of-std" ]; @@ -2771,13 +3197,13 @@ rec { "write_core" = [ "dep:crc32fast" "dep:indexmap" "dep:hashbrown" ]; "write_std" = [ "write_core" "std" "indexmap?/std" "crc32fast?/std" ]; }; - resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" ]; + resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" "xcoff" ]; }; "once_cell" = rec { crateName = "once_cell"; - version = "1.19.0"; + version = "1.20.2"; edition = "2021"; - sha256 = "14kvw7px5z96dk4dwdm1r9cqhhy2cyj1l5n5b29mynbb8yr15nrz"; + sha256 = "0xb7rw1aqr7pa4z3b00y7786gyf8awx2gca3md73afy76dzgwq8j"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" ]; @@ -2792,27 +3218,21 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "race" "std" ]; }; - "owning_ref" = rec { - crateName = "owning_ref"; - version = "0.4.1"; - edition = "2015"; - sha256 = "1kjj9m28wjv452jw49p1mp3d8ql058x78v4bz00avr7rvsnmpxbg"; + "overload" = rec { + crateName = "overload"; + version = "0.1.1"; + edition = "2018"; + sha256 = "0fdgbaqwknillagy1xq7xfgv60qdbk010diwl7s1p0qx7hb16n5i"; authors = [ - "Marvin Löbel <loebel.marvin@gmail.com>" - ]; - dependencies = [ - { - name = "stable_deref_trait"; - packageId = "stable_deref_trait"; - } + "Daniel Salvadori <danaugrs@gmail.com>" ]; }; "parking_lot" = rec { crateName = "parking_lot"; - version = "0.12.1"; - edition = "2018"; - sha256 = "13r2xk7mnxfc5g0g6dkdxqdqad99j7s7z8zhzz4npw5r0g0v4hip"; + version = "0.12.3"; + edition = "2021"; + sha256 = "09ws9g6245iiq8z975h8ycf818a66q3c6zv4b5h8skpm7hc1igzi"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -2837,9 +3257,9 @@ rec { }; "parking_lot_core" = rec { crateName = "parking_lot_core"; - version = "0.9.9"; - edition = "2018"; - sha256 = "13h0imw1aq86wj28gxkblhkzx6z1gk8q18n0v76qmmj6cliajhjc"; + version = "0.9.10"; + edition = "2021"; + sha256 = "1y3cf9ld9ijf7i4igwzffcn0xl16dxyn4c5bwgjck1dkgabiyh0y"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -2864,7 +3284,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets 0.48.5"; + packageId = "windows-targets"; target = { target, features }: (target."windows" or false); } ]; @@ -2880,6 +3300,7 @@ rec { version = "0.2.4"; edition = "2021"; sha256 = "07wf6wf4jrxlq5p3xldxsnabp7jl06my2qp7kiwy9m3x2r5wac8i"; + libName = "parquet_format_safe"; authors = [ "Apache Thrift contributors <dev@thrift.apache.org>" "Jorge Leitao <jorgecarleitao@gmail.com>" @@ -2909,6 +3330,7 @@ rec { version = "2.3.1"; edition = "2018"; sha256 = "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -2920,9 +3342,10 @@ rec { }; "pin-project-lite" = rec { crateName = "pin-project-lite"; - version = "0.2.13"; + version = "0.2.14"; edition = "2018"; - sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + sha256 = "00nx3f04agwjlsmd3mc5rx5haibj2v8q9b52b0kwn63wcv4nz9mx"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -2930,6 +3353,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -2971,9 +3395,10 @@ rec { }; "pkg-config" = rec { crateName = "pkg-config"; - version = "0.3.29"; - edition = "2015"; - sha256 = "1jy6158v1316khkpmq2sjj1vgbnbnw51wffx7p0k0l9h9vlys019"; + version = "0.3.31"; + edition = "2018"; + sha256 = "1wk6yp2phl91795ia0lwkr3wl4a9xkrympvhqq8cxk4d75hwhglm"; + libName = "pkg_config"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -2995,21 +3420,6 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "platforms" = rec { - crateName = "platforms"; - version = "3.3.0"; - edition = "2018"; - sha256 = "0k7q6pigmnvgpfasvssb12m2pv3pc94zrhrfg9by3h3wmhyfqvb2"; - authors = [ - "Tony Arcieri <bascule@gmail.com>" - "Sergey \"Shnatsel\" Davidoff <shnatsel@gmail.com>" - ]; - features = { - "default" = [ "std" ]; - "serde" = [ "dep:serde" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "polars" = rec { crateName = "polars"; version = "0.36.2"; @@ -3209,13 +3619,14 @@ rec { "unique_counts" = [ "polars-ops/unique_counts" "polars-lazy?/unique_counts" ]; "zip_with" = [ "polars-core/zip_with" ]; }; - resolvedDefaultFeatures = [ "csv" "default" "docs" "dtype-date" "dtype-datetime" "dtype-duration" "dtype-slim" "fmt" "parquet" "polars-io" "polars-ops" "polars-time" "temporal" "zip_with" ]; + resolvedDefaultFeatures = [ "csv" "default" "docs" "dtype-date" "dtype-datetime" "dtype-duration" "dtype-slim" "fmt" "lazy" "parquet" "polars-io" "polars-lazy" "polars-ops" "polars-time" "streaming" "temporal" "zip_with" ]; }; "polars-arrow" = rec { crateName = "polars-arrow"; version = "0.36.2"; edition = "2021"; sha256 = "0vxql6amvwyp6qj0w87vm21y33qa0i61pshs4ry7ixwgd4ps0s6f"; + libName = "polars_arrow"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -3277,12 +3688,12 @@ rec { { name = "getrandom"; packageId = "getrandom"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "wasm32-unknown-unknown"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "wasm32-unknown-unknown"); features = [ "js" ]; } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.14.5"; features = [ "rayon" "ahash" ]; } { @@ -3394,6 +3805,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1pa4l1w41gdzdff81ih1z05z3gz568k81i6flibbca8v2igvqkxi"; + libName = "polars_compute"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3433,6 +3845,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "08sar9h97znpb8ziyvrrvvx28lyzc21vwsd7gvwybjxn6kkyzxfh"; + libName = "polars_core"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3443,7 +3856,7 @@ rec { } { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags"; } { name = "bytemuck"; @@ -3469,7 +3882,7 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.14.5"; features = [ "rayon" "ahash" ]; } { @@ -3593,6 +4006,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "11m80a899kp45b3dz9jbvrn5001hw8izbdp7d2czrswrixwdx5k3"; + libName = "polars_error"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3629,6 +4043,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1smamd34ghlxyxdd4aqdplk7k8xm1l626brmzlc4fvwlx3pmh13x"; + libName = "polars_io"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3825,6 +4240,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1mdml4hs574njb23mb9gl6x92x2bb4vdfzsazkl3ifq516s0awcx"; + libName = "polars_lazy"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3835,7 +4251,7 @@ rec { } { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags"; } { name = "glob"; @@ -4012,13 +4428,14 @@ rec { "true_div" = [ "polars-plan/true_div" ]; "unique_counts" = [ "polars-plan/unique_counts" ]; }; - resolvedDefaultFeatures = [ "abs" "cross_join" "csv" "cum_agg" "dtype-date" "dtype-datetime" "dtype-duration" "dtype-i16" "dtype-i8" "dtype-time" "is_in" "log" "meta" "parquet" "polars-time" "regex" "round_series" "strings" "temporal" "trigonometry" ]; + resolvedDefaultFeatures = [ "abs" "chunked_ids" "cross_join" "csv" "cum_agg" "dtype-date" "dtype-datetime" "dtype-duration" "dtype-i16" "dtype-i8" "dtype-time" "is_in" "log" "meta" "parquet" "polars-pipe" "polars-time" "regex" "round_series" "streaming" "strings" "temporal" "trigonometry" ]; }; "polars-ops" = rec { crateName = "polars-ops"; version = "0.36.2"; edition = "2021"; sha256 = "13m7dh4vpdmcah04a7kql933l7y7045f0hybbmgff4dbav2ay29f"; + libName = "polars_ops"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4044,7 +4461,7 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.14.5"; features = [ "rayon" "ahash" ]; } { @@ -4163,13 +4580,14 @@ rec { "timezones" = [ "chrono-tz" "chrono" ]; "unicode-reverse" = [ "dep:unicode-reverse" ]; }; - resolvedDefaultFeatures = [ "abs" "cross_join" "cum_agg" "dtype-date" "dtype-datetime" "dtype-duration" "is_in" "log" "round_series" "search_sorted" "strings" ]; + resolvedDefaultFeatures = [ "abs" "chunked_ids" "cross_join" "cum_agg" "dtype-date" "dtype-datetime" "dtype-duration" "is_in" "log" "round_series" "search_sorted" "strings" ]; }; "polars-parquet" = rec { crateName = "polars-parquet"; version = "0.36.2"; edition = "2021"; sha256 = "0gay037sw5hcg2q93pxcfh7krcchl1px8g838d8vhjpnn5klv8kv"; + libName = "polars_parquet"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -4290,6 +4708,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "00217q51mnq7i57k3sax293xnwghm5hridbpgl11fffcfg8fmdyr"; + libName = "polars_pipe"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4308,7 +4727,7 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.14.5"; features = [ "rayon" "ahash" ]; } { @@ -4403,6 +4822,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1l5ca38v7ksq4595wdr6wsd74pdgszwivq9y8wfc6l6h4ib1fjiq"; + libName = "polars_plan"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4480,7 +4900,7 @@ rec { } { name = "strum_macros"; - packageId = "strum_macros"; + packageId = "strum_macros 0.25.3"; } ]; buildDependencies = [ @@ -4584,13 +5004,14 @@ rec { "top_k" = [ "polars-ops/top_k" ]; "unique_counts" = [ "polars-ops/unique_counts" ]; }; - resolvedDefaultFeatures = [ "abs" "cross_join" "csv" "cum_agg" "dtype-date" "dtype-datetime" "dtype-duration" "dtype-i16" "dtype-i8" "dtype-time" "is_in" "log" "meta" "parquet" "polars-parquet" "polars-time" "regex" "round_series" "strings" "temporal" "trigonometry" ]; + resolvedDefaultFeatures = [ "abs" "chunked_ids" "cross_join" "csv" "cum_agg" "dtype-date" "dtype-datetime" "dtype-duration" "dtype-i16" "dtype-i8" "dtype-time" "is_in" "log" "meta" "parquet" "polars-parquet" "polars-time" "regex" "round_series" "streaming" "strings" "temporal" "trigonometry" ]; }; "polars-row" = rec { crateName = "polars-row"; version = "0.36.2"; edition = "2021"; sha256 = "0by7x6jlj5dwr3f1gj49v8w65l3kpqhwhzb9qzlv6gdqrdx2ycij"; + libName = "polars_row"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4620,6 +5041,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1dcmm993gycw75a6c5hxcr6h2cy6fa2r3hsbx19h9zgxvxnlq2wz"; + libName = "polars_sql"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4684,6 +5106,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1l24fmpv5v1qshxfd4592z8x6bnjlwy4njhf9rcbdlbbr6gn9qny"; + libName = "polars_time"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4762,6 +5185,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1nmvfqwyzbaxcw457amspz479y5vcnpalq043awxfixdfx5clx5i"; + libName = "polars_utils"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4777,7 +5201,7 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.14.5"; features = [ "rayon" "ahash" ]; } { @@ -4824,14 +5248,35 @@ rec { }; resolvedDefaultFeatures = [ "sysinfo" ]; }; + "portable-atomic" = rec { + crateName = "portable-atomic"; + version = "1.9.0"; + edition = "2018"; + sha256 = "1cmd87qj90panwsi350djb8lsxdryqkkxmimjcz7a1nsysini76c"; + libName = "portable_atomic"; + features = { + "critical-section" = [ "dep:critical-section" ]; + "default" = [ "fallback" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "fallback" ]; + }; "ppv-lite86" = rec { crateName = "ppv-lite86"; - version = "0.2.17"; - edition = "2018"; - sha256 = "1pp6g52aw970adv3x2310n7glqnji96z0a9wiamzw89ibf0ayh2v"; + version = "0.2.20"; + edition = "2021"; + sha256 = "017ax9ssdnpww7nrl1hvqh2lzncpv04nnsibmnw9nxjnaqlpp5bp"; + libName = "ppv_lite86"; authors = [ "The CryptoCorrosion Contributors" ]; + dependencies = [ + { + name = "zerocopy"; + packageId = "zerocopy"; + features = [ "simd" "derive" ]; + } + ]; features = { "default" = [ "std" ]; }; @@ -4839,9 +5284,10 @@ rec { }; "proc-macro2" = rec { crateName = "proc-macro2"; - version = "1.0.78"; + version = "1.0.87"; edition = "2021"; - sha256 = "1bjak27pqdn4f4ih1c9nr3manzyavsgqmf76ygw9k76q8pb2lhp2"; + sha256 = "16mifsq1nqzk81qm82aszib44jsd23gpqic5z4kbmzpnvjhdmr5k"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -4859,9 +5305,9 @@ rec { }; "quote" = rec { crateName = "quote"; - version = "1.0.35"; + version = "1.0.37"; edition = "2018"; - sha256 = "1vv8r2ncaz4pqdr78x7f138ka595sp2ncr1sa2plm4zxbsmwj7i9"; + sha256 = "1brklraw2g34bxy9y4q1nbrccn7bv36ylihv12c9vlcii55x7fdm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5017,9 +5463,9 @@ rec { }; "rayon" = rec { crateName = "rayon"; - version = "1.8.1"; + version = "1.10.0"; edition = "2021"; - sha256 = "0lg0488xwpj5jsfz2gfczcrpclbjl8221mj5vdrhg8bp3883fwps"; + sha256 = "1ylgnzwgllajalr4v00y4kj22klq2jbwllm70aha232iah0sc65l"; authors = [ "Niko Matsakis <niko@alum.mit.edu>" "Josh Stone <cuviper@gmail.com>" @@ -5045,6 +5491,7 @@ rec { edition = "2021"; links = "rayon-core"; sha256 = "1qpwim68ai5h0j7axa8ai8z0payaawv3id0lrgkqmapx7lx8fr8l"; + libName = "rayon_core"; authors = [ "Niko Matsakis <niko@alum.mit.edu>" "Josh Stone <cuviper@gmail.com>" @@ -5065,9 +5512,9 @@ rec { }; "redox_syscall" = rec { crateName = "redox_syscall"; - version = "0.4.1"; - edition = "2018"; - sha256 = "1aiifyz5dnybfvkk4cdab9p2kmphag1yad6iknc7aszlxxldf8j7"; + version = "0.5.7"; + edition = "2021"; + sha256 = "07vpgfr6a04k0x19zqr1xdlqm6fncik3zydbdi3f5g3l5k7zwvcv"; libName = "syscall"; authors = [ "Jeremy Soller <jackpot51@gmail.com>" @@ -5075,19 +5522,21 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 1.3.2"; + packageId = "bitflags"; } ]; features = { "core" = [ "dep:core" ]; + "default" = [ "userspace" ]; "rustc-dep-of-std" = [ "core" "bitflags/rustc-dep-of-std" ]; }; + resolvedDefaultFeatures = [ "default" "userspace" ]; }; "regex" = rec { crateName = "regex"; - version = "1.10.3"; + version = "1.11.0"; edition = "2021"; - sha256 = "05cvihqy0wgnh9i8a9y2n803n5azg2h0b7nlqy6rsvxhy00vwbdn"; + sha256 = "1n5imk7yxam409ik5nagsjpwqvbg3f0g0mznd5drf549x1g0w81q"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -5107,13 +5556,13 @@ rec { } { name = "regex-automata"; - packageId = "regex-automata"; + packageId = "regex-automata 0.4.8"; usesDefaultFeatures = false; features = [ "alloc" "syntax" "meta" "nfa-pikevm" ]; } { name = "regex-syntax"; - packageId = "regex-syntax"; + packageId = "regex-syntax 0.8.5"; usesDefaultFeatures = false; } ]; @@ -5141,11 +5590,37 @@ rec { }; resolvedDefaultFeatures = [ "default" "perf" "perf-backtrack" "perf-cache" "perf-dfa" "perf-inline" "perf-literal" "perf-onepass" "std" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; }; - "regex-automata" = rec { + "regex-automata 0.1.10" = rec { crateName = "regex-automata"; - version = "0.4.5"; + version = "0.1.10"; + edition = "2015"; + sha256 = "0ci1hvbzhrfby5fdpf4ganhf7kla58acad9i1ff1p34dzdrhs8vc"; + libName = "regex_automata"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "regex-syntax"; + packageId = "regex-syntax 0.6.29"; + optional = true; + } + ]; + features = { + "default" = [ "std" ]; + "fst" = [ "dep:fst" ]; + "regex-syntax" = [ "dep:regex-syntax" ]; + "std" = [ "regex-syntax" ]; + "transducer" = [ "std" "fst" ]; + }; + resolvedDefaultFeatures = [ "default" "regex-syntax" "std" ]; + }; + "regex-automata 0.4.8" = rec { + crateName = "regex-automata"; + version = "0.4.8"; edition = "2021"; - sha256 = "1karc80mx15z435rm1jg3sqylnc58nxi15gqypcd1inkzzpqgfav"; + sha256 = "18wd530ndrmygi6xnz3sp345qi0hy2kdbsa89182nwbl6br5i1rn"; + libName = "regex_automata"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -5165,7 +5640,7 @@ rec { } { name = "regex-syntax"; - packageId = "regex-syntax"; + packageId = "regex-syntax 0.8.5"; optional = true; usesDefaultFeatures = false; } @@ -5201,11 +5676,27 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "dfa-onepass" "dfa-search" "hybrid" "meta" "nfa-backtrack" "nfa-pikevm" "nfa-thompson" "perf-inline" "perf-literal" "perf-literal-multisubstring" "perf-literal-substring" "std" "syntax" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" "unicode-word-boundary" ]; }; - "regex-syntax" = rec { + "regex-syntax 0.6.29" = rec { crateName = "regex-syntax"; - version = "0.8.2"; + version = "0.6.29"; + edition = "2018"; + sha256 = "1qgj49vm6y3zn1hi09x91jvgkl2b1fiaq402skj83280ggfwcqpi"; + libName = "regex_syntax"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "default" = [ "unicode" ]; + "unicode" = [ "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; + }; + resolvedDefaultFeatures = [ "default" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; + }; + "regex-syntax 0.8.5" = rec { + crateName = "regex-syntax"; + version = "0.8.5"; edition = "2021"; - sha256 = "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360"; + sha256 = "0p41p3hj9ww7blnbwbj9h7rwxzxg0c1hvrdycgys8rxyhqqw859b"; + libName = "regex_syntax"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -5219,9 +5710,10 @@ rec { }; "rustc-demangle" = rec { crateName = "rustc-demangle"; - version = "0.1.23"; + version = "0.1.24"; edition = "2015"; - sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + sha256 = "07zysaafgrkzy2rjgwqdj2a8qdpsm6zv6f5pgpk9x0lm40z9b6vi"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -5231,15 +5723,26 @@ rec { "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; }; }; + "rustc-hash" = rec { + crateName = "rustc-hash"; + version = "2.0.0"; + edition = "2021"; + sha256 = "0lni0lf846bzrf3jvci6jaf4142n1mdqxvcpczk5ch9pfgyk8c2q"; + libName = "rustc_hash"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "default" = [ "std" ]; + "rand" = [ "dep:rand" "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; "rustc_version" = rec { crateName = "rustc_version"; - version = "0.4.0"; + version = "0.4.1"; edition = "2018"; - sha256 = "0rpk9rcdk405xhbmgclsh4pai0svn49x35aggl4nhbkd4a2zb85z"; - authors = [ - "Dirkjan Ochtman <dirkjan@ochtman.nl>" - "Marvin Löbel <loebel.marvin@gmail.com>" - ]; + sha256 = "14lvdsmr5si5qbqzrajgb6vfn69k0sfygrvfvr2mps26xwi3mjyg"; dependencies = [ { name = "semver"; @@ -5250,9 +5753,9 @@ rec { }; "rustversion" = rec { crateName = "rustversion"; - version = "1.0.14"; + version = "1.0.17"; edition = "2018"; - sha256 = "1x1pz1yynk5xzzrazk2svmidj69jhz89dz5vrc28sixl20x1iz3z"; + sha256 = "1mm3fckyvb0l2209in1n2k05sws5d9mpkszbnwhq3pkq8apjhpcm"; procMacro = true; build = "build/build.rs"; authors = [ @@ -5262,9 +5765,9 @@ rec { }; "ryu" = rec { crateName = "ryu"; - version = "1.0.16"; + version = "1.0.18"; edition = "2018"; - sha256 = "0k7b90xr48ag5bzmfjp82rljasw2fx28xr3bg1lrpx7b5sljm3gr"; + sha256 = "17xx2s8j1lln7iackzd9p0sv546vjq71i779gphjq923vjh5pjzk"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5272,6 +5775,24 @@ rec { "no-panic" = [ "dep:no-panic" ]; }; }; + "safer_owning_ref" = rec { + crateName = "safer_owning_ref"; + version = "0.5.0"; + edition = "2015"; + sha256 = "1vrhvra2cr3a6r1vvflawj35n8lq3k443ddm0wfgcrpr5pgbj8dg"; + libName = "owning_ref"; + authors = [ + "Marvin Löbel <loebel.marvin@gmail.com>" + "Noam Ta Shma noam.tashma@gmail.com" + ]; + dependencies = [ + { + name = "stable_deref_trait"; + packageId = "stable_deref_trait"; + } + ]; + + }; "scopeguard" = rec { crateName = "scopeguard"; version = "1.2.0"; @@ -5286,9 +5807,9 @@ rec { }; "semver" = rec { crateName = "semver"; - version = "1.0.21"; + version = "1.0.23"; edition = "2018"; - sha256 = "1c49snqlfcx93xym1cgwx8zcspmyyxm37xa2fyfgjx1vhalxfzmr"; + sha256 = "12wqpxfflclbq4dv8sa6gchdh92ahhwn4ci1ls22wlby3h57wsb1"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5304,6 +5825,7 @@ rec { edition = "2018"; sha256 = "1d50kbaslrrd0374ivx15jg57f03y5xzil1wd2ajlvajzlkbzw53"; procMacro = true; + libName = "seq_macro"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5311,9 +5833,9 @@ rec { }; "serde" = rec { crateName = "serde"; - version = "1.0.196"; + version = "1.0.210"; edition = "2018"; - sha256 = "0civrvhbwwk442xhlkfdkkdn478by486qxmackq6k3501zk2c047"; + sha256 = "0flc0z8wgax1k4j5bf2zyq48bgzyv425jkd5w0i6wbh7f8j5kqy8"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -5345,9 +5867,9 @@ rec { }; "serde_derive" = rec { crateName = "serde_derive"; - version = "1.0.196"; + version = "1.0.210"; edition = "2015"; - sha256 = "0rybziqrfaxkaxrybkhrps7zv3ibxnjdk0fwais16zayr5h57j1k"; + sha256 = "07yzy4wafk79ps0hmbqmsqh5xjna4pm4q57wc847bb8gl3nh4f94"; procMacro = true; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" @@ -5368,7 +5890,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; usesDefaultFeatures = false; features = [ "clone-impls" "derive" "parsing" "printing" "proc-macro" ]; } @@ -5378,9 +5900,9 @@ rec { }; "serde_json" = rec { crateName = "serde_json"; - version = "1.0.113"; + version = "1.0.128"; edition = "2021"; - sha256 = "0ycaiff7ar4qx5sy9kvi1kv9rnnfl15kcfmhxiiwknn3n5q1p039"; + sha256 = "1n43nia50ybpcfmh3gcw4lcc627qsg9nyakzwgkk9pm10xklbxbg"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -5391,6 +5913,11 @@ rec { packageId = "itoa"; } { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + { name = "ryu"; packageId = "ryu"; } @@ -5412,7 +5939,7 @@ rec { "default" = [ "std" ]; "indexmap" = [ "dep:indexmap" ]; "preserve_order" = [ "indexmap" "std" ]; - "std" = [ "serde/std" ]; + "std" = [ "memchr/std" "serde/std" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; @@ -5456,22 +5983,42 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "signal-hook-registry" = rec { - crateName = "signal-hook-registry"; - version = "1.4.1"; - edition = "2015"; - sha256 = "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq"; + "sharded-slab" = rec { + crateName = "sharded-slab"; + version = "0.1.7"; + edition = "2018"; + sha256 = "1xipjr4nqsgw34k7a2cgj9zaasl2ds6jwn89886kww93d32a637l"; + libName = "sharded_slab"; authors = [ - "Michal 'vorner' Vaner <vorner@vorner.cz>" - "Masaki Hara <ackie.h.gmai@gmail.com>" + "Eliza Weisman <eliza@buoyant.io>" ]; dependencies = [ { - name = "libc"; - packageId = "libc"; + name = "lazy_static"; + packageId = "lazy_static"; } ]; - + features = { + "loom" = [ "dep:loom" ]; + }; + }; + "shlex" = rec { + crateName = "shlex"; + version = "1.3.0"; + edition = "2015"; + sha256 = "0r1y6bv26c1scpxvhg2cabimrmwgbp4p3wy6syj9n0c4s3q2znhg"; + authors = [ + "comex <comexk@gmail.com>" + "Fenhl <fenhl@fenhl.net>" + "Adrian Taylor <adetaylor@chromium.org>" + "Alex Touchet <alextouchet@outlook.com>" + "Daniel Parks <dp+git@oxidized.org>" + "Garrett Berg <googberg@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; }; "signature" = rec { crateName = "signature"; @@ -5499,9 +6046,9 @@ rec { }; "simdutf8" = rec { crateName = "simdutf8"; - version = "0.1.4"; + version = "0.1.5"; edition = "2018"; - sha256 = "0fi6zvnldaw7g726wnm9vvpv4s89s5jsk7fgp3rg2l99amw64zzj"; + sha256 = "0vmpf7xaa0dnaikib5jlx6y4dxd3hxqz6l830qb079g7wcsgxag3"; authors = [ "Hans Kratz <hans@appfour.com>" ]; @@ -5532,9 +6079,9 @@ rec { }; "smallvec" = rec { crateName = "smallvec"; - version = "1.13.1"; + version = "1.13.2"; edition = "2018"; - sha256 = "1mzk9j117pn3k1gabys0b7nz8cdjsx5xc6q7fwnm8r0an62d7v76"; + sha256 = "0rsw5samawl3wsw6glrsb127rx6sh89a8wyikicw6dkdcjd1lpiw"; authors = [ "The Servo Project Developers" ]; @@ -5590,9 +6137,9 @@ rec { }; "socket2" = rec { crateName = "socket2"; - version = "0.5.5"; + version = "0.5.7"; edition = "2021"; - sha256 = "1sgq315f1njky114ip7wcy83qlphv9qclprfjwvxcpfblmcsqpvv"; + sha256 = "070r941wbq76xpy039an4pyiy3rfj7mp7pvibf1rcri9njq5wc6f"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -5605,7 +6152,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_System_IO" "Win32_System_Threading" "Win32_System_WindowsProgramming" ]; } @@ -5699,6 +6246,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "1wscqj3s30qknda778wf7z99mknk65p0h9hhs658l4pvkfqw6v5z"; + libName = "streaming_decompression"; dependencies = [ { name = "fallible-streaming-iterator"; @@ -5712,6 +6260,7 @@ rec { version = "0.1.9"; edition = "2021"; sha256 = "0845zdv8qb7zwqzglpqc0830i43xh3fb6vqms155wz85qfvk28ib"; + libName = "streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -5731,9 +6280,9 @@ rec { }; "strum" = rec { crateName = "strum"; - version = "0.25.0"; + version = "0.26.3"; edition = "2018"; - sha256 = "09g1q55ms8vax1z0mxlbva3vm8n2r1179kfvbccnkjcidzm58399"; + sha256 = "01lgl6jvrf4j28v5kmx9bp480ygf1nhvac8b4p7rcj9hxw50zv4g"; authors = [ "Peter Glotfelty <peter.glotfelty@microsoft.com>" ]; @@ -5745,7 +6294,7 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "strum_macros" = rec { + "strum_macros 0.25.3" = rec { crateName = "strum_macros"; version = "0.25.3"; edition = "2018"; @@ -5757,7 +6306,41 @@ rec { dependencies = [ { name = "heck"; - packageId = "heck"; + packageId = "heck 0.4.1"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "rustversion"; + packageId = "rustversion"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + features = [ "parsing" "extra-traits" ]; + } + ]; + + }; + "strum_macros 0.26.4" = rec { + crateName = "strum_macros"; + version = "0.26.4"; + edition = "2018"; + sha256 = "1gl1wmq24b8md527cpyd5bw9rkbqldd7k1h38kf5ajd2ln2ywssc"; + procMacro = true; + authors = [ + "Peter Glotfelty <peter.glotfelty@microsoft.com>" + ]; + dependencies = [ + { + name = "heck"; + packageId = "heck 0.5.0"; } { name = "proc-macro2"; @@ -5773,7 +6356,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "parsing" "extra-traits" ]; } ]; @@ -5781,9 +6364,9 @@ rec { }; "subtle" = rec { crateName = "subtle"; - version = "2.5.0"; + version = "2.6.1"; edition = "2018"; - sha256 = "1g2yjs7gffgmdvkkq0wrrh0pxds3q0dv6dhkw9cdpbib656xdkc1"; + sha256 = "14ijxaymghbl1p0wql9cib5zlwiina7kall6w7g89csprkgbvhhk"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -5826,11 +6409,11 @@ rec { }; resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit-mut" ]; }; - "syn 2.0.48" = rec { + "syn 2.0.79" = rec { crateName = "syn"; - version = "2.0.48"; + version = "2.0.79"; edition = "2021"; - sha256 = "0gqgfygmrxmp8q32lia9p294kdd501ybn6kn2h4gqza0irik2d8g"; + sha256 = "147mk4sgigmvsb9l8qzj199ygf0fgb0bphwdsghn8205pz82q4w9"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5853,18 +6436,17 @@ rec { ]; features = { "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; - "printing" = [ "quote" ]; - "proc-macro" = [ "proc-macro2/proc-macro" "quote/proc-macro" ]; - "quote" = [ "dep:quote" ]; + "printing" = [ "dep:quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; "test" = [ "syn-test-suite/all-features" ]; }; - resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit" "visit-mut" ]; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; }; "sysinfo" = rec { crateName = "sysinfo"; - version = "0.30.5"; + version = "0.30.13"; edition = "2018"; - sha256 = "1clba87ndskvxddrmwysnjccm6vyr75j24p6ck48jqwgii1z7d0z"; + sha256 = "1csbkx1hdlacgzw5ynjyfvgc1xg58w3h1rgh5gm2pysmxvd4snqa"; authors = [ "Guillaume Gomez <guillaume1.gomez@gmail.com>" ]; @@ -5911,9 +6493,10 @@ rec { }; "target-features" = rec { crateName = "target-features"; - version = "0.1.5"; + version = "0.1.6"; edition = "2021"; - sha256 = "1gb974chm9aj8ifkyibylxkyb5an4bf5y8dxb18pqmck698gmdfg"; + sha256 = "1m8y0ksw30gnkidjsjvnmhlpj165mgyj8ylk0lbs0qy4qprvkfy1"; + libName = "target_features"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -5921,9 +6504,9 @@ rec { }; "thiserror" = rec { crateName = "thiserror"; - version = "1.0.56"; + version = "1.0.64"; edition = "2021"; - sha256 = "1b9hnzngjan4d89zjs16i01bcpcnvdwklyh73lj16xk28p37hhym"; + sha256 = "114s8lmssxl0c2480s671am88vzlasbaikxbvfv8pyqrq6mzh2nm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5937,10 +6520,11 @@ rec { }; "thiserror-impl" = rec { crateName = "thiserror-impl"; - version = "1.0.56"; + version = "1.0.64"; edition = "2021"; - sha256 = "0w9ldp8fa574ilz4dn7y7scpcq66vdjy59qal8qdpwsh7faal3zs"; + sha256 = "1hvzmjx9iamln854l74qyhs0jl2pg3hhqzpqm9p8gszmf9v4x408"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5955,16 +6539,36 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; } ]; }; + "thread_local" = rec { + crateName = "thread_local"; + version = "1.1.8"; + edition = "2021"; + sha256 = "173i5lyjh011gsimk21np9jn8al18rxsrkjli20a7b8ks2xgk7lb"; + authors = [ + "Amanieu d'Antras <amanieu@gmail.com>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + ]; + features = { }; + }; "tokio" = rec { crateName = "tokio"; - version = "1.36.0"; + version = "1.40.0"; edition = "2021"; - sha256 = "0c89p36zbd4abr1z3l5mipp43x7z4c9b4vp4s6r8y0gs2mjmya31"; + sha256 = "166rllhfkyqp0fs7sxn6crv74iizi4wzd3cvxkcpmlk52qip1c72"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -5992,26 +6596,10 @@ rec { usesDefaultFeatures = false; } { - name = "num_cpus"; - packageId = "num_cpus"; - optional = true; - } - { - name = "parking_lot"; - packageId = "parking_lot"; - optional = true; - } - { name = "pin-project-lite"; packageId = "pin-project-lite"; } { - name = "signal-hook-registry"; - packageId = "signal-hook-registry"; - optional = true; - target = { target, features }: (target."unix" or false); - } - { name = "socket2"; packageId = "socket2"; optional = true; @@ -6025,7 +6613,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys"; optional = true; target = { target, features }: (target."windows" or false); } @@ -6043,7 +6631,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Security_Authorization" ]; } @@ -6056,10 +6644,9 @@ rec { "macros" = [ "tokio-macros" ]; "mio" = [ "dep:mio" ]; "net" = [ "libc" "mio/os-poll" "mio/os-ext" "mio/net" "socket2" "windows-sys/Win32_Foundation" "windows-sys/Win32_Security" "windows-sys/Win32_Storage_FileSystem" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_System_SystemServices" ]; - "num_cpus" = [ "dep:num_cpus" ]; "parking_lot" = [ "dep:parking_lot" ]; "process" = [ "bytes" "libc" "mio/os-poll" "mio/os-ext" "mio/net" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Threading" "windows-sys/Win32_System_WindowsProgramming" ]; - "rt-multi-thread" = [ "num_cpus" "rt" ]; + "rt-multi-thread" = [ "rt" ]; "signal" = [ "libc" "mio/os-poll" "mio/net" "mio/os-ext" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Console" ]; "signal-hook-registry" = [ "dep:signal-hook-registry" ]; "socket2" = [ "dep:socket2" ]; @@ -6068,14 +6655,15 @@ rec { "tracing" = [ "dep:tracing" ]; "windows-sys" = [ "dep:windows-sys" ]; }; - resolvedDefaultFeatures = [ "bytes" "default" "fs" "full" "io-std" "io-util" "libc" "macros" "mio" "net" "num_cpus" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "time" "tokio-macros" "windows-sys" ]; + resolvedDefaultFeatures = [ "bytes" "default" "io-util" "libc" "macros" "mio" "net" "rt" "rt-multi-thread" "socket2" "sync" "time" "tokio-macros" "windows-sys" ]; }; "tokio-macros" = rec { crateName = "tokio-macros"; - version = "2.2.0"; + version = "2.4.0"; edition = "2021"; - sha256 = "0fwjy4vdx1h9pi4g2nml72wi0fr27b5m954p13ji9anyy8l1x2jv"; + sha256 = "0lnpg14h1v3fh2jvnc8cz7cjf0m7z1xgkwfpcyy632g829imjgb9"; procMacro = true; + libName = "tokio_macros"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -6090,7 +6678,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" ]; } ]; @@ -6098,9 +6686,10 @@ rec { }; "tokio-util" = rec { crateName = "tokio-util"; - version = "0.7.10"; + version = "0.7.12"; edition = "2021"; - sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + sha256 = "0spc0g4irbnf2flgag22gfii87avqzibwfm0si0d1g0k9ijw7rv1"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -6136,7 +6725,6 @@ rec { ]; features = { "__docs_rs" = [ "futures-util" ]; - "codec" = [ "tracing" ]; "compat" = [ "futures-io" ]; "full" = [ "codec" "compat" "io-util" "time" "net" "rt" ]; "futures-io" = [ "dep:futures-io" ]; @@ -6151,6 +6739,320 @@ rec { }; resolvedDefaultFeatures = [ "default" "io" "io-util" ]; }; + "tracing" = rec { + crateName = "tracing"; + version = "0.1.40"; + edition = "2018"; + sha256 = "1vv48dac9zgj9650pg2b4d0j3w6f3x9gbggf43scq5hrlysklln3"; + authors = [ + "Eliza Weisman <eliza@buoyant.io>" + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tracing-attributes"; + packageId = "tracing-attributes"; + optional = true; + } + { + name = "tracing-core"; + packageId = "tracing-core"; + usesDefaultFeatures = false; + } + ]; + features = { + "attributes" = [ "tracing-attributes" ]; + "default" = [ "std" "attributes" ]; + "log" = [ "dep:log" ]; + "log-always" = [ "log" ]; + "std" = [ "tracing-core/std" ]; + "tracing-attributes" = [ "dep:tracing-attributes" ]; + "valuable" = [ "tracing-core/valuable" ]; + }; + resolvedDefaultFeatures = [ "attributes" "default" "max_level_trace" "release_max_level_debug" "std" "tracing-attributes" ]; + }; + "tracing-attributes" = rec { + crateName = "tracing-attributes"; + version = "0.1.27"; + edition = "2018"; + sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; + procMacro = true; + libName = "tracing_attributes"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + "Eliza Weisman <eliza@buoyant.io>" + "David Barsky <dbarsky@amazon.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.79"; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "visit-mut" "clone-impls" "extra-traits" "proc-macro" ]; + } + ]; + features = { }; + }; + "tracing-core" = rec { + crateName = "tracing-core"; + version = "0.1.32"; + edition = "2018"; + sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "once_cell"; + packageId = "once_cell"; + optional = true; + } + { + name = "valuable"; + packageId = "valuable"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: (target."tracing_unstable" or false); + } + ]; + features = { + "default" = [ "std" "valuable/std" ]; + "once_cell" = [ "dep:once_cell" ]; + "std" = [ "once_cell" ]; + "valuable" = [ "dep:valuable" ]; + }; + resolvedDefaultFeatures = [ "default" "once_cell" "std" "valuable" ]; + }; + "tracing-indicatif" = rec { + crateName = "tracing-indicatif"; + version = "0.3.6"; + edition = "2021"; + sha256 = "07cmn4ilw8hdfzc1mirccwkgl160k3x9fhgg7xydj4gy9r181586"; + libName = "tracing_indicatif"; + dependencies = [ + { + name = "indicatif"; + packageId = "indicatif"; + features = [ "in_memory" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "tracing-core"; + packageId = "tracing-core"; + } + { + name = "tracing-subscriber"; + packageId = "tracing-subscriber"; + } + ]; + + }; + "tracing-log" = rec { + crateName = "tracing-log"; + version = "0.2.0"; + edition = "2018"; + sha256 = "1hs77z026k730ij1a9dhahzrl0s073gfa2hm5p0fbl0b80gmz1gf"; + libName = "tracing_log"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "log"; + packageId = "log"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "tracing-core"; + packageId = "tracing-core"; + } + ]; + features = { + "ahash" = [ "dep:ahash" ]; + "default" = [ "log-tracer" "std" ]; + "interest-cache" = [ "lru" "ahash" ]; + "lru" = [ "dep:lru" ]; + "std" = [ "log/std" ]; + }; + resolvedDefaultFeatures = [ "log-tracer" "std" ]; + }; + "tracing-subscriber" = rec { + crateName = "tracing-subscriber"; + version = "0.3.18"; + edition = "2018"; + sha256 = "12vs1bwk4kig1l2qqjbbn2nm5amwiqmkcmnznylzmnfvjy6083xd"; + libName = "tracing_subscriber"; + authors = [ + "Eliza Weisman <eliza@buoyant.io>" + "David Barsky <me@davidbarsky.com>" + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "matchers"; + packageId = "matchers"; + optional = true; + } + { + name = "nu-ansi-term"; + packageId = "nu-ansi-term"; + optional = true; + } + { + name = "once_cell"; + packageId = "once_cell"; + optional = true; + } + { + name = "regex"; + packageId = "regex"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" "unicode-case" "unicode-perl" ]; + } + { + name = "sharded-slab"; + packageId = "sharded-slab"; + optional = true; + } + { + name = "smallvec"; + packageId = "smallvec"; + optional = true; + } + { + name = "thread_local"; + packageId = "thread_local"; + optional = true; + } + { + name = "tracing"; + packageId = "tracing"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "tracing-core"; + packageId = "tracing-core"; + usesDefaultFeatures = false; + } + { + name = "tracing-log"; + packageId = "tracing-log"; + optional = true; + usesDefaultFeatures = false; + features = [ "log-tracer" "std" ]; + } + ]; + devDependencies = [ + { + name = "regex"; + packageId = "regex"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "tracing-log"; + packageId = "tracing-log"; + } + ]; + features = { + "ansi" = [ "fmt" "nu-ansi-term" ]; + "chrono" = [ "dep:chrono" ]; + "default" = [ "smallvec" "fmt" "ansi" "tracing-log" "std" ]; + "env-filter" = [ "matchers" "regex" "once_cell" "tracing" "std" "thread_local" ]; + "fmt" = [ "registry" "std" ]; + "json" = [ "tracing-serde" "serde" "serde_json" ]; + "local-time" = [ "time/local-offset" ]; + "matchers" = [ "dep:matchers" ]; + "nu-ansi-term" = [ "dep:nu-ansi-term" ]; + "once_cell" = [ "dep:once_cell" ]; + "parking_lot" = [ "dep:parking_lot" ]; + "regex" = [ "dep:regex" ]; + "registry" = [ "sharded-slab" "thread_local" "std" ]; + "serde" = [ "dep:serde" ]; + "serde_json" = [ "dep:serde_json" ]; + "sharded-slab" = [ "dep:sharded-slab" ]; + "smallvec" = [ "dep:smallvec" ]; + "std" = [ "alloc" "tracing-core/std" ]; + "thread_local" = [ "dep:thread_local" ]; + "time" = [ "dep:time" ]; + "tracing" = [ "dep:tracing" ]; + "tracing-log" = [ "dep:tracing-log" ]; + "tracing-serde" = [ "dep:tracing-serde" ]; + "valuable" = [ "tracing-core/valuable" "valuable_crate" "valuable-serde" "tracing-serde/valuable" ]; + "valuable-serde" = [ "dep:valuable-serde" ]; + "valuable_crate" = [ "dep:valuable_crate" ]; + }; + resolvedDefaultFeatures = [ "alloc" "ansi" "default" "env-filter" "fmt" "matchers" "nu-ansi-term" "once_cell" "regex" "registry" "sharded-slab" "smallvec" "std" "thread_local" "tracing" "tracing-log" ]; + }; + "tvix-tracing" = rec { + crateName = "tvix-tracing"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/tracing; }; + libName = "tvix_tracing"; + dependencies = [ + { + name = "indicatif"; + packageId = "indicatif"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "sync" "rt" ]; + } + { + name = "tracing"; + packageId = "tracing"; + features = [ "max_level_trace" "release_max_level_debug" ]; + } + { + name = "tracing-indicatif"; + packageId = "tracing-indicatif"; + } + { + name = "tracing-subscriber"; + packageId = "tracing-subscriber"; + features = [ "env-filter" ]; + } + ]; + features = { + "axum" = [ "dep:axum" ]; + "otlp" = [ "dep:tracing-opentelemetry" "dep:opentelemetry" "dep:opentelemetry-otlp" "dep:opentelemetry_sdk" "dep:opentelemetry-http" "reqwest-tracing?/opentelemetry_0_22" ]; + "reqwest" = [ "dep:reqwest-tracing" ]; + "tonic" = [ "dep:tonic" "dep:http" ]; + "tracy" = [ "dep:tracing-tracy" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; "typenum" = rec { crateName = "typenum"; version = "1.17.0"; @@ -6168,9 +7070,10 @@ rec { }; "unicode-ident" = rec { crateName = "unicode-ident"; - version = "1.0.12"; + version = "1.0.13"; edition = "2018"; - sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + sha256 = "1zm1xylzsdfvm2a5ib9li3g5pp7qnkv4amhspydvgbmd9k6mc6z9"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -6178,9 +7081,10 @@ rec { }; "unicode-width" = rec { crateName = "unicode-width"; - version = "0.1.11"; - edition = "2015"; - sha256 = "11ds4ydhg8g7l06rlmh712q41qsrd0j0h00n1jm74kww3kqk65z5"; + version = "0.1.14"; + edition = "2021"; + sha256 = "1bzn2zv0gp8xxbxbhifw778a7fc93pa6a1kj24jgg9msj07f7mkx"; + libName = "unicode_width"; authors = [ "kwantam <kwantam@gmail.com>" "Manish Goregaokar <manishsmail@gmail.com>" @@ -6188,21 +7092,138 @@ rec { features = { "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; + "default" = [ "cjk" ]; "rustc-dep-of-std" = [ "std" "core" "compiler_builtins" ]; "std" = [ "dep:std" ]; }; + resolvedDefaultFeatures = [ "cjk" "default" ]; + }; + "utf8parse" = rec { + crateName = "utf8parse"; + version = "0.2.2"; + edition = "2018"; + sha256 = "088807qwjq46azicqwbhlmzwrbkz7l4hpw43sdkdyyk524vdxaq6"; + authors = [ + "Joe Wilm <joe@jwilm.com>" + "Christian Duerr <contact@christianduerr.com>" + ]; + features = { }; resolvedDefaultFeatures = [ "default" ]; }; + "valuable" = rec { + crateName = "valuable"; + version = "0.1.0"; + edition = "2018"; + sha256 = "0v9gp3nkjbl30z0fd56d8mx7w1csk86wwjhfjhr400wh9mfpw2w3"; + features = { + "default" = [ "std" ]; + "derive" = [ "valuable-derive" ]; + "std" = [ "alloc" ]; + "valuable-derive" = [ "dep:valuable-derive" ]; + }; + resolvedDefaultFeatures = [ "alloc" "std" ]; + }; "version_check" = rec { crateName = "version_check"; - version = "0.9.4"; + version = "0.9.5"; edition = "2015"; - sha256 = "0gs8grwdlgh0xq660d7wr80x14vxbizmd8dbp29p2pdncx8lp1s9"; + sha256 = "0nhhi4i5x89gm911azqbn7avs9mdacw2i3vcz3cnmz3mv4rqz4hb"; authors = [ "Sergio Benitez <sb@sergio.bz>" ]; }; + "vt100" = rec { + crateName = "vt100"; + version = "0.15.2"; + edition = "2021"; + sha256 = "1pklc8y984axmxr0cd363srr2d27wd5rj15xlcmkjznvy0xqdkc4"; + authors = [ + "Jesse Luehrs <doy@tozt.net>" + ]; + dependencies = [ + { + name = "itoa"; + packageId = "itoa"; + } + { + name = "log"; + packageId = "log"; + } + { + name = "unicode-width"; + packageId = "unicode-width"; + } + { + name = "vte"; + packageId = "vte"; + } + ]; + devDependencies = [ + { + name = "vte"; + packageId = "vte"; + } + ]; + + }; + "vte" = rec { + crateName = "vte"; + version = "0.11.1"; + edition = "2021"; + sha256 = "15r1ff4j8ndqj9vsyil3wqwxhhl7jsz5g58f31n0h1wlpxgjn0pm"; + authors = [ + "Joe Wilm <joe@jwilm.com>" + "Christian Duerr <contact@christianduerr.com>" + ]; + dependencies = [ + { + name = "arrayvec"; + packageId = "arrayvec"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "utf8parse"; + packageId = "utf8parse"; + } + { + name = "vte_generate_state_changes"; + packageId = "vte_generate_state_changes"; + } + ]; + features = { + "ansi" = [ "log" ]; + "arrayvec" = [ "dep:arrayvec" ]; + "default" = [ "no_std" ]; + "log" = [ "dep:log" ]; + "nightly" = [ "utf8parse/nightly" ]; + "no_std" = [ "arrayvec" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "arrayvec" "default" "no_std" ]; + }; + "vte_generate_state_changes" = rec { + crateName = "vte_generate_state_changes"; + version = "0.1.2"; + edition = "2018"; + sha256 = "0biwgpcji3w4llz7h4bi8c2rwqchm9gmyr7dnjki1m853gp9ndif"; + procMacro = true; + authors = [ + "Christian Duerr <contact@christianduerr.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + ]; + + }; "wasi" = rec { crateName = "wasi"; version = "0.11.0+wasi-snapshot-preview1"; @@ -6222,9 +7243,10 @@ rec { }; "wasm-bindgen" = rec { crateName = "wasm-bindgen"; - version = "0.2.91"; - edition = "2018"; - sha256 = "0zwbb07ln4m5hh6axamc701nnj090nd66syxbf6bagzf189j9qf1"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0bpbvmxhil380gpv53smaypl8wc7sy7rq8apxfw349pn78v1x38j"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -6234,6 +7256,10 @@ rec { packageId = "cfg-if"; } { + name = "once_cell"; + packageId = "once_cell"; + } + { name = "wasm-bindgen-macro"; packageId = "wasm-bindgen-macro"; } @@ -6241,7 +7267,6 @@ rec { features = { "default" = [ "spans" "std" ]; "enable-interning" = [ "std" ]; - "gg-alloc" = [ "wasm-bindgen-test/gg-alloc" ]; "serde" = [ "dep:serde" ]; "serde-serialize" = [ "serde" "serde_json" "std" ]; "serde_json" = [ "dep:serde_json" ]; @@ -6253,9 +7278,10 @@ rec { }; "wasm-bindgen-backend" = rec { crateName = "wasm-bindgen-backend"; - version = "0.2.91"; - edition = "2018"; - sha256 = "02zpi9sjzhd8kfv1yj9m1bs4a41ik9ii5bc8hjf60arm1j8f3ry9"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0n53wgy78bgzgjwk0z69zbspzhv8p2a4zh69s4fzvpqdrb9x8vfb"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -6282,7 +7308,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; features = [ "full" ]; } { @@ -6297,10 +7323,11 @@ rec { }; "wasm-bindgen-macro" = rec { crateName = "wasm-bindgen-macro"; - version = "0.2.91"; - edition = "2018"; - sha256 = "1va6dilw9kcnvsg5043h5b9mwc5sgq0lyhj9fif2n62qsgigj2mk"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0mic8b2vab1a91m6x3hjxkwz23094bq1cwhnszarsnlggyz894z7"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -6322,9 +7349,10 @@ rec { }; "wasm-bindgen-macro-support" = rec { crateName = "wasm-bindgen-macro-support"; - version = "0.2.91"; - edition = "2018"; - sha256 = "0rlyl3yzwbcnc691mvx78m1wbqf1qs52mlc3g88bh7ihwrdk4bv4"; + version = "0.2.95"; + edition = "2021"; + sha256 = "0s7g6glb85lyx2pj83shbmg4d50mvqhb2c2qk2j28yigaxbspii6"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -6339,8 +7367,8 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; - features = [ "visit" "full" ]; + packageId = "syn 2.0.79"; + features = [ "visit" "visit-mut" "full" ]; } { name = "wasm-bindgen-backend"; @@ -6359,10 +7387,11 @@ rec { }; "wasm-bindgen-shared" = rec { crateName = "wasm-bindgen-shared"; - version = "0.2.91"; - edition = "2018"; + version = "0.2.95"; + edition = "2021"; links = "wasm_bindgen"; - sha256 = "0f4qmjv57ppwi4xpdxgcd77vz9vmvlrnybg8dj430hzhvk96n62g"; + sha256 = "1386q7mvv5ky003hcc6yyxpid3y1m7fy0l920i3z3ab60vqhkz35"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -6384,12 +7413,7 @@ rec { requiredFeatures = [ ]; } ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./.; } - else ./.; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./.; }; dependencies = [ { name = "anyhow"; @@ -6398,29 +7422,40 @@ rec { } { name = "hashbrown"; - packageId = "hashbrown"; + packageId = "hashbrown 0.14.5"; } { name = "nix-compat"; packageId = "nix-compat"; } { - name = "owning_ref"; - packageId = "owning_ref"; - } - { name = "polars"; packageId = "polars"; - features = [ "parquet" ]; + features = [ "parquet" "lazy" "streaming" ]; } { name = "rayon"; packageId = "rayon"; } { - name = "tokio"; - packageId = "tokio"; - features = [ "full" ]; + name = "rustc-hash"; + packageId = "rustc-hash"; + } + { + name = "safer_owning_ref"; + packageId = "safer_owning_ref"; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "tracing-indicatif"; + packageId = "tracing-indicatif"; + } + { + name = "tvix-tracing"; + packageId = "tvix-tracing"; } ]; @@ -6437,24 +7472,25 @@ rec { { name = "winapi-i686-pc-windows-gnu"; packageId = "winapi-i686-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "i686-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnu"); } { name = "winapi-x86_64-pc-windows-gnu"; packageId = "winapi-x86_64-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnu"); } ]; features = { "debug" = [ "impl-debug" ]; }; - resolvedDefaultFeatures = [ "cfg" "consoleapi" "evntrace" "handleapi" "impl-default" "in6addr" "inaddr" "minwinbase" "ntsecapi" "processenv" "synchapi" "winbase" "windef" "winerror" "winioctl" "winuser" ]; + resolvedDefaultFeatures = [ "cfg" "consoleapi" "errhandlingapi" "evntrace" "fileapi" "handleapi" "impl-default" "in6addr" "inaddr" "minwinbase" "ntsecapi" "processenv" "synchapi" "winbase" "windef" "winerror" "winioctl" "winuser" ]; }; "winapi-i686-pc-windows-gnu" = rec { crateName = "winapi-i686-pc-windows-gnu"; version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -6465,6 +7501,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -6485,7 +7522,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets 0.52.0"; + packageId = "windows-targets"; } ]; features = { @@ -7156,323 +8193,32 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "1nc3qv7sy24x0nlnb32f7alzpd6f72l4p24vl65vydbyil669ark"; + libName = "windows_core"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets 0.52.0"; + packageId = "windows-targets"; } ]; features = { }; resolvedDefaultFeatures = [ "default" ]; }; - "windows-sys 0.48.0" = rec { - crateName = "windows-sys"; - version = "0.48.0"; - edition = "2018"; - sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; - authors = [ - "Microsoft" - ]; - dependencies = [ - { - name = "windows-targets"; - packageId = "windows-targets 0.48.5"; - } - ]; - features = { - "Wdk_System" = [ "Wdk" ]; - "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; - "Win32_Data" = [ "Win32" ]; - "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; - "Win32_Data_RightsManagement" = [ "Win32_Data" ]; - "Win32_Data_Xml" = [ "Win32_Data" ]; - "Win32_Data_Xml_MsXml" = [ "Win32_Data_Xml" ]; - "Win32_Data_Xml_XmlLite" = [ "Win32_Data_Xml" ]; - "Win32_Devices" = [ "Win32" ]; - "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; - "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; - "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; - "Win32_Devices_Communication" = [ "Win32_Devices" ]; - "Win32_Devices_DeviceAccess" = [ "Win32_Devices" ]; - "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; - "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; - "Win32_Devices_Display" = [ "Win32_Devices" ]; - "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; - "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; - "Win32_Devices_Fax" = [ "Win32_Devices" ]; - "Win32_Devices_FunctionDiscovery" = [ "Win32_Devices" ]; - "Win32_Devices_Geolocation" = [ "Win32_Devices" ]; - "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; - "Win32_Devices_ImageAcquisition" = [ "Win32_Devices" ]; - "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; - "Win32_Devices_Properties" = [ "Win32_Devices" ]; - "Win32_Devices_Pwm" = [ "Win32_Devices" ]; - "Win32_Devices_Sensors" = [ "Win32_Devices" ]; - "Win32_Devices_SerialCommunication" = [ "Win32_Devices" ]; - "Win32_Devices_Tapi" = [ "Win32_Devices" ]; - "Win32_Devices_Usb" = [ "Win32_Devices" ]; - "Win32_Devices_WebServicesOnDevices" = [ "Win32_Devices" ]; - "Win32_Foundation" = [ "Win32" ]; - "Win32_Gaming" = [ "Win32" ]; - "Win32_Globalization" = [ "Win32" ]; - "Win32_Graphics" = [ "Win32" ]; - "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; - "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; - "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; - "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; - "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; - "Win32_Graphics_Printing_PrintTicket" = [ "Win32_Graphics_Printing" ]; - "Win32_Management" = [ "Win32" ]; - "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; - "Win32_Media" = [ "Win32" ]; - "Win32_Media_Audio" = [ "Win32_Media" ]; - "Win32_Media_Audio_Apo" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_DirectMusic" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_Endpoints" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_XAudio2" = [ "Win32_Media_Audio" ]; - "Win32_Media_DeviceManager" = [ "Win32_Media" ]; - "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; - "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; - "Win32_Media_LibrarySharingServices" = [ "Win32_Media" ]; - "Win32_Media_MediaPlayer" = [ "Win32_Media" ]; - "Win32_Media_Multimedia" = [ "Win32_Media" ]; - "Win32_Media_Speech" = [ "Win32_Media" ]; - "Win32_Media_Streaming" = [ "Win32_Media" ]; - "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; - "Win32_NetworkManagement" = [ "Win32" ]; - "Win32_NetworkManagement_Dhcp" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_MobileBroadband" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetworkPolicyServer" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Snmp" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsConnectNow" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; - "Win32_Networking" = [ "Win32" ]; - "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; - "Win32_Networking_BackgroundIntelligentTransferService" = [ "Win32_Networking" ]; - "Win32_Networking_Clustering" = [ "Win32_Networking" ]; - "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; - "Win32_Networking_Ldap" = [ "Win32_Networking" ]; - "Win32_Networking_NetworkListManager" = [ "Win32_Networking" ]; - "Win32_Networking_RemoteDifferentialCompression" = [ "Win32_Networking" ]; - "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; - "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; - "Win32_Networking_WinInet" = [ "Win32_Networking" ]; - "Win32_Networking_WinSock" = [ "Win32_Networking" ]; - "Win32_Networking_WindowsWebServices" = [ "Win32_Networking" ]; - "Win32_Security" = [ "Win32" ]; - "Win32_Security_AppLocker" = [ "Win32_Security" ]; - "Win32_Security_Authentication" = [ "Win32_Security" ]; - "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; - "Win32_Security_Authentication_Identity_Provider" = [ "Win32_Security_Authentication_Identity" ]; - "Win32_Security_Authorization" = [ "Win32_Security" ]; - "Win32_Security_Authorization_UI" = [ "Win32_Security_Authorization" ]; - "Win32_Security_ConfigurationSnapin" = [ "Win32_Security" ]; - "Win32_Security_Credentials" = [ "Win32_Security" ]; - "Win32_Security_Cryptography" = [ "Win32_Security" ]; - "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_Cryptography_Certificates" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_Cryptography_Sip" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_Cryptography_UI" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_DiagnosticDataQuery" = [ "Win32_Security" ]; - "Win32_Security_DirectoryServices" = [ "Win32_Security" ]; - "Win32_Security_EnterpriseData" = [ "Win32_Security" ]; - "Win32_Security_ExtensibleAuthenticationProtocol" = [ "Win32_Security" ]; - "Win32_Security_Isolation" = [ "Win32_Security" ]; - "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; - "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; - "Win32_Security_Tpm" = [ "Win32_Security" ]; - "Win32_Security_WinTrust" = [ "Win32_Security" ]; - "Win32_Security_WinWlx" = [ "Win32_Security" ]; - "Win32_Storage" = [ "Win32" ]; - "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; - "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; - "Win32_Storage_Compression" = [ "Win32_Storage" ]; - "Win32_Storage_DataDeduplication" = [ "Win32_Storage" ]; - "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; - "Win32_Storage_EnhancedStorage" = [ "Win32_Storage" ]; - "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; - "Win32_Storage_FileServerResourceManager" = [ "Win32_Storage" ]; - "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; - "Win32_Storage_Imapi" = [ "Win32_Storage" ]; - "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; - "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; - "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; - "Win32_Storage_Jet" = [ "Win32_Storage" ]; - "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; - "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; - "Win32_Storage_Packaging" = [ "Win32_Storage" ]; - "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; - "Win32_Storage_Packaging_Opc" = [ "Win32_Storage_Packaging" ]; - "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; - "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; - "Win32_Storage_Vhd" = [ "Win32_Storage" ]; - "Win32_Storage_VirtualDiskService" = [ "Win32_Storage" ]; - "Win32_Storage_Vss" = [ "Win32_Storage" ]; - "Win32_Storage_Xps" = [ "Win32_Storage" ]; - "Win32_Storage_Xps_Printing" = [ "Win32_Storage_Xps" ]; - "Win32_System" = [ "Win32" ]; - "Win32_System_AddressBook" = [ "Win32_System" ]; - "Win32_System_Antimalware" = [ "Win32_System" ]; - "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; - "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; - "Win32_System_AssessmentTool" = [ "Win32_System" ]; - "Win32_System_ClrHosting" = [ "Win32_System" ]; - "Win32_System_Com" = [ "Win32_System" ]; - "Win32_System_Com_CallObj" = [ "Win32_System_Com" ]; - "Win32_System_Com_ChannelCredentials" = [ "Win32_System_Com" ]; - "Win32_System_Com_Events" = [ "Win32_System_Com" ]; - "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; - "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; - "Win32_System_Com_UI" = [ "Win32_System_Com" ]; - "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; - "Win32_System_ComponentServices" = [ "Win32_System" ]; - "Win32_System_Console" = [ "Win32_System" ]; - "Win32_System_Contacts" = [ "Win32_System" ]; - "Win32_System_CorrelationVector" = [ "Win32_System" ]; - "Win32_System_DataExchange" = [ "Win32_System" ]; - "Win32_System_DeploymentServices" = [ "Win32_System" ]; - "Win32_System_DesktopSharing" = [ "Win32_System" ]; - "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; - "Win32_System_Diagnostics" = [ "Win32_System" ]; - "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_ClrProfiling" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_Debug_ActiveScript" = [ "Win32_System_Diagnostics_Debug" ]; - "Win32_System_Diagnostics_Debug_Extensions" = [ "Win32_System_Diagnostics_Debug" ]; - "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; - "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; - "Win32_System_Environment" = [ "Win32_System" ]; - "Win32_System_ErrorReporting" = [ "Win32_System" ]; - "Win32_System_EventCollector" = [ "Win32_System" ]; - "Win32_System_EventLog" = [ "Win32_System" ]; - "Win32_System_EventNotificationService" = [ "Win32_System" ]; - "Win32_System_GroupPolicy" = [ "Win32_System" ]; - "Win32_System_HostCompute" = [ "Win32_System" ]; - "Win32_System_HostComputeNetwork" = [ "Win32_System" ]; - "Win32_System_HostComputeSystem" = [ "Win32_System" ]; - "Win32_System_Hypervisor" = [ "Win32_System" ]; - "Win32_System_IO" = [ "Win32_System" ]; - "Win32_System_Iis" = [ "Win32_System" ]; - "Win32_System_Ioctl" = [ "Win32_System" ]; - "Win32_System_JobObjects" = [ "Win32_System" ]; - "Win32_System_Js" = [ "Win32_System" ]; - "Win32_System_Kernel" = [ "Win32_System" ]; - "Win32_System_LibraryLoader" = [ "Win32_System" ]; - "Win32_System_Mailslots" = [ "Win32_System" ]; - "Win32_System_Mapi" = [ "Win32_System" ]; - "Win32_System_Memory" = [ "Win32_System" ]; - "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; - "Win32_System_MessageQueuing" = [ "Win32_System" ]; - "Win32_System_MixedReality" = [ "Win32_System" ]; - "Win32_System_Mmc" = [ "Win32_System" ]; - "Win32_System_Ole" = [ "Win32_System" ]; - "Win32_System_ParentalControls" = [ "Win32_System" ]; - "Win32_System_PasswordManagement" = [ "Win32_System" ]; - "Win32_System_Performance" = [ "Win32_System" ]; - "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; - "Win32_System_Pipes" = [ "Win32_System" ]; - "Win32_System_Power" = [ "Win32_System" ]; - "Win32_System_ProcessStatus" = [ "Win32_System" ]; - "Win32_System_RealTimeCommunications" = [ "Win32_System" ]; - "Win32_System_Recovery" = [ "Win32_System" ]; - "Win32_System_Registry" = [ "Win32_System" ]; - "Win32_System_RemoteAssistance" = [ "Win32_System" ]; - "Win32_System_RemoteDesktop" = [ "Win32_System" ]; - "Win32_System_RemoteManagement" = [ "Win32_System" ]; - "Win32_System_RestartManager" = [ "Win32_System" ]; - "Win32_System_Restore" = [ "Win32_System" ]; - "Win32_System_Rpc" = [ "Win32_System" ]; - "Win32_System_Search" = [ "Win32_System" ]; - "Win32_System_Search_Common" = [ "Win32_System_Search" ]; - "Win32_System_SecurityCenter" = [ "Win32_System" ]; - "Win32_System_ServerBackup" = [ "Win32_System" ]; - "Win32_System_Services" = [ "Win32_System" ]; - "Win32_System_SettingsManagementInfrastructure" = [ "Win32_System" ]; - "Win32_System_SetupAndMigration" = [ "Win32_System" ]; - "Win32_System_Shutdown" = [ "Win32_System" ]; - "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; - "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; - "Win32_System_SystemInformation" = [ "Win32_System" ]; - "Win32_System_SystemServices" = [ "Win32_System" ]; - "Win32_System_TaskScheduler" = [ "Win32_System" ]; - "Win32_System_Threading" = [ "Win32_System" ]; - "Win32_System_Time" = [ "Win32_System" ]; - "Win32_System_TpmBaseServices" = [ "Win32_System" ]; - "Win32_System_UpdateAgent" = [ "Win32_System" ]; - "Win32_System_UpdateAssessment" = [ "Win32_System" ]; - "Win32_System_UserAccessLogging" = [ "Win32_System" ]; - "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; - "Win32_System_WindowsProgramming" = [ "Win32_System" ]; - "Win32_System_WindowsSync" = [ "Win32_System" ]; - "Win32_System_Wmi" = [ "Win32_System" ]; - "Win32_UI" = [ "Win32" ]; - "Win32_UI_Accessibility" = [ "Win32_UI" ]; - "Win32_UI_Animation" = [ "Win32_UI" ]; - "Win32_UI_ColorSystem" = [ "Win32_UI" ]; - "Win32_UI_Controls" = [ "Win32_UI" ]; - "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; - "Win32_UI_Controls_RichEdit" = [ "Win32_UI_Controls" ]; - "Win32_UI_HiDpi" = [ "Win32_UI" ]; - "Win32_UI_Input" = [ "Win32_UI" ]; - "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Ink" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Radial" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; - "Win32_UI_InteractionContext" = [ "Win32_UI" ]; - "Win32_UI_LegacyWindowsEnvironmentFeatures" = [ "Win32_UI" ]; - "Win32_UI_Magnification" = [ "Win32_UI" ]; - "Win32_UI_Notifications" = [ "Win32_UI" ]; - "Win32_UI_Ribbon" = [ "Win32_UI" ]; - "Win32_UI_Shell" = [ "Win32_UI" ]; - "Win32_UI_Shell_Common" = [ "Win32_UI_Shell" ]; - "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; - "Win32_UI_TabletPC" = [ "Win32_UI" ]; - "Win32_UI_TextServices" = [ "Win32_UI" ]; - "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; - "Win32_UI_Wpf" = [ "Win32_UI" ]; - "Win32_Web" = [ "Win32" ]; - "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; - }; - resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Console" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "default" ]; - }; - "windows-sys 0.52.0" = rec { + "windows-sys" = rec { crateName = "windows-sys"; version = "0.52.0"; edition = "2021"; sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + libName = "windows_sys"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets 0.52.0"; + packageId = "windows-targets"; } ]; features = { @@ -7706,237 +8452,136 @@ rec { "Win32_Web" = [ "Win32" ]; "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; }; - resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_System" "Win32_System_Com" "Win32_UI" "Win32_UI_Shell" "default" ]; + resolvedDefaultFeatures = [ "Wdk" "Wdk_Foundation" "Wdk_Storage" "Wdk_Storage_FileSystem" "Wdk_System" "Wdk_System_IO" "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Com" "Win32_System_Console" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "Win32_UI" "Win32_UI_Input" "Win32_UI_Input_KeyboardAndMouse" "Win32_UI_Shell" "default" ]; }; - "windows-targets 0.48.5" = rec { + "windows-targets" = rec { crateName = "windows-targets"; - version = "0.48.5"; - edition = "2018"; - sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0wwrx625nwlfp7k93r2rra568gad1mwd888h1jwnl0vfg5r4ywlv"; + libName = "windows_targets"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows_aarch64_gnullvm"; - packageId = "windows_aarch64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + packageId = "windows_aarch64_gnullvm"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); } { name = "windows_aarch64_msvc"; - packageId = "windows_aarch64_msvc 0.48.5"; + packageId = "windows_aarch64_msvc"; target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_i686_gnu"; - packageId = "windows_i686_gnu 0.48.5"; - target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!(target."windows_raw_dylib" or false))); - } - { - name = "windows_i686_msvc"; - packageId = "windows_i686_msvc 0.48.5"; - target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); - } - { - name = "windows_x86_64_gnu"; - packageId = "windows_x86_64_gnu 0.48.5"; - target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); - } - { - name = "windows_x86_64_gnullvm"; - packageId = "windows_x86_64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); - } - { - name = "windows_x86_64_msvc"; - packageId = "windows_x86_64_msvc 0.48.5"; - target = { target, features }: (("x86_64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); - } - ]; - - }; - "windows-targets 0.52.0" = rec { - crateName = "windows-targets"; - version = "0.52.0"; - edition = "2021"; - sha256 = "1kg7a27ynzw8zz3krdgy6w5gbqcji27j1sz4p7xk2j5j8082064a"; - authors = [ - "Microsoft" - ]; - dependencies = [ - { - name = "windows_aarch64_gnullvm"; - packageId = "windows_aarch64_gnullvm 0.52.0"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + packageId = "windows_i686_gnu"; + target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); } { - name = "windows_aarch64_msvc"; - packageId = "windows_aarch64_msvc 0.52.0"; - target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); - } - { - name = "windows_i686_gnu"; - packageId = "windows_i686_gnu 0.52.0"; - target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + name = "windows_i686_gnullvm"; + packageId = "windows_i686_gnullvm"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnullvm"); } { name = "windows_i686_msvc"; - packageId = "windows_i686_msvc 0.52.0"; + packageId = "windows_i686_msvc"; target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnu"; - packageId = "windows_x86_64_gnu 0.52.0"; + packageId = "windows_x86_64_gnu"; target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnullvm"; - packageId = "windows_x86_64_gnullvm 0.52.0"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); + packageId = "windows_x86_64_gnullvm"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); } { name = "windows_x86_64_msvc"; - packageId = "windows_x86_64_msvc 0.52.0"; - target = { target, features }: (("x86_64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + packageId = "windows_x86_64_msvc"; + target = { target, features }: ((("x86_64" == target."arch" or null) || ("arm64ec" == target."arch" or null)) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } ]; }; - "windows_aarch64_gnullvm 0.48.5" = rec { - crateName = "windows_aarch64_gnullvm"; - version = "0.48.5"; - edition = "2018"; - sha256 = "1n05v7qblg1ci3i567inc7xrkmywczxrs1z3lj3rkkxw18py6f1b"; - authors = [ - "Microsoft" - ]; - - }; - "windows_aarch64_gnullvm 0.52.0" = rec { + "windows_aarch64_gnullvm" = rec { crateName = "windows_aarch64_gnullvm"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "1shmn1kbdc0bpphcxz0vlph96bxz0h1jlmh93s9agf2dbpin8xyb"; + sha256 = "1lrcq38cr2arvmz19v32qaggvj8bh1640mdm9c2fr877h0hn591j"; authors = [ "Microsoft" ]; }; - "windows_aarch64_msvc 0.48.5" = rec { + "windows_aarch64_msvc" = rec { crateName = "windows_aarch64_msvc"; - version = "0.48.5"; - edition = "2018"; - sha256 = "1g5l4ry968p73g6bg6jgyvy9lb8fyhcs54067yzxpcpkf44k2dfw"; - authors = [ - "Microsoft" - ]; - - }; - "windows_aarch64_msvc 0.52.0" = rec { - crateName = "windows_aarch64_msvc"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "1vvmy1ypvzdvxn9yf0b8ygfl85gl2gpcyvsvqppsmlpisil07amv"; + sha256 = "0sfl0nysnz32yyfh773hpi49b1q700ah6y7sacmjbqjjn5xjmv09"; authors = [ "Microsoft" ]; }; - "windows_i686_gnu 0.48.5" = rec { + "windows_i686_gnu" = rec { crateName = "windows_i686_gnu"; - version = "0.48.5"; - edition = "2018"; - sha256 = "0gklnglwd9ilqx7ac3cn8hbhkraqisd0n83jxzf9837nvvkiand7"; - authors = [ - "Microsoft" - ]; - - }; - "windows_i686_gnu 0.52.0" = rec { - crateName = "windows_i686_gnu"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "04zkglz4p3pjsns5gbz85v4s5aw102raz4spj4b0lmm33z5kg1m2"; + sha256 = "02zspglbykh1jh9pi7gn8g1f97jh1rrccni9ivmrfbl0mgamm6wf"; authors = [ "Microsoft" ]; }; - "windows_i686_msvc 0.48.5" = rec { - crateName = "windows_i686_msvc"; - version = "0.48.5"; - edition = "2018"; - sha256 = "01m4rik437dl9rdf0ndnm2syh10hizvq0dajdkv2fjqcywrw4mcg"; + "windows_i686_gnullvm" = rec { + crateName = "windows_i686_gnullvm"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0rpdx1537mw6slcpqa0rm3qixmsb79nbhqy5fsm3q2q9ik9m5vhf"; authors = [ "Microsoft" ]; }; - "windows_i686_msvc 0.52.0" = rec { + "windows_i686_msvc" = rec { crateName = "windows_i686_msvc"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "16kvmbvx0vr0zbgnaz6nsks9ycvfh5xp05bjrhq65kj623iyirgz"; + sha256 = "0rkcqmp4zzmfvrrrx01260q3xkpzi6fzi2x2pgdcdry50ny4h294"; authors = [ "Microsoft" ]; }; - "windows_x86_64_gnu 0.48.5" = rec { + "windows_x86_64_gnu" = rec { crateName = "windows_x86_64_gnu"; - version = "0.48.5"; - edition = "2018"; - sha256 = "13kiqqcvz2vnyxzydjh73hwgigsdr2z1xpzx313kxll34nyhmm2k"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_gnu 0.52.0" = rec { - crateName = "windows_x86_64_gnu"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "1zdy4qn178sil5sdm63lm7f0kkcjg6gvdwmcprd2yjmwn8ns6vrx"; + sha256 = "0y0sifqcb56a56mvn7xjgs8g43p33mfqkd8wj1yhrgxzma05qyhl"; authors = [ "Microsoft" ]; }; - "windows_x86_64_gnullvm 0.48.5" = rec { + "windows_x86_64_gnullvm" = rec { crateName = "windows_x86_64_gnullvm"; - version = "0.48.5"; - edition = "2018"; - sha256 = "1k24810wfbgz8k48c2yknqjmiigmql6kk3knmddkv8k8g1v54yqb"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_gnullvm 0.52.0" = rec { - crateName = "windows_x86_64_gnullvm"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "17lllq4l2k1lqgcnw1cccphxp9vs7inq99kjlm2lfl9zklg7wr8s"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_msvc 0.48.5" = rec { - crateName = "windows_x86_64_msvc"; - version = "0.48.5"; - edition = "2018"; - sha256 = "0f4mdp895kkjh9zv8dxvn4pc10xr7839lf5pa9l0193i2pkgr57d"; + sha256 = "03gda7zjx1qh8k9nnlgb7m3w3s1xkysg55hkd1wjch8pqhyv5m94"; authors = [ "Microsoft" ]; }; - "windows_x86_64_msvc 0.52.0" = rec { + "windows_x86_64_msvc" = rec { crateName = "windows_x86_64_msvc"; - version = "0.52.0"; + version = "0.52.6"; edition = "2021"; - sha256 = "012wfq37f18c09ij5m6rniw7xxn5fcvrxbqd0wd8vgnl3hfn9yfz"; + sha256 = "1v7rb5cibyzx8vak29pdrk8nx9hycsjs4w0jgms08qk49jl6v7sq"; authors = [ "Microsoft" ]; @@ -7944,9 +8589,10 @@ rec { }; "xxhash-rust" = rec { crateName = "xxhash-rust"; - version = "0.8.8"; + version = "0.8.12"; edition = "2018"; - sha256 = "0q9xl4kxibh61631lw9m7if7pkdvq3pp5ss52zdkxs6rirkhdgjk"; + sha256 = "1139skyp136z8710r916kb1djp7f7flfly31zccqi5800isvyp3a"; + libName = "xxhash_rust"; authors = [ "Douman <douman@gmx.se>" ]; @@ -7955,14 +8601,20 @@ rec { }; "zerocopy" = rec { crateName = "zerocopy"; - version = "0.7.32"; + version = "0.7.35"; edition = "2018"; - sha256 = "1ghnfxw69kx5d1aqfd5fsfrra9dgpz17yqx84nd4ryjk3sbd7m3l"; + sha256 = "1w36q7b9il2flg0qskapgi9ymgg7p985vniqd09vi0mwib8lz6qv"; authors = [ "Joshua Liebow-Feeser <joshlf@google.com>" ]; dependencies = [ { + name = "byteorder"; + packageId = "byteorder"; + optional = true; + usesDefaultFeatures = false; + } + { name = "zerocopy-derive"; packageId = "zerocopy-derive"; optional = true; @@ -7987,14 +8639,15 @@ rec { "simd-nightly" = [ "simd" ]; "zerocopy-derive" = [ "dep:zerocopy-derive" ]; }; - resolvedDefaultFeatures = [ "simd" ]; + resolvedDefaultFeatures = [ "byteorder" "default" "derive" "simd" "zerocopy-derive" ]; }; "zerocopy-derive" = rec { crateName = "zerocopy-derive"; - version = "0.7.32"; + version = "0.7.35"; edition = "2018"; - sha256 = "19nj11md42aijyqnfx8pa647fjzhz537xyc624rajwwfrn6b3qcw"; + sha256 = "0gnf2ap2y92nwdalzz3x7142f2b83sni66l39vxp2ijd6j080kzs"; procMacro = true; + libName = "zerocopy_derive"; authors = [ "Joshua Liebow-Feeser <joshlf@google.com>" ]; @@ -8009,16 +8662,16 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.79"; } ]; }; "zeroize" = rec { crateName = "zeroize"; - version = "1.7.0"; + version = "1.8.1"; edition = "2021"; - sha256 = "0bfvby7k9pdp6623p98yz2irqnamcyzpn7zh20nqmdn68b0lwnsj"; + sha256 = "1pjdrmjwmszpxfd7r860jx54cyk94qk59x13sc307cvr5256glyf"; authors = [ "The RustCrypto Project Developers" ]; @@ -8033,9 +8686,9 @@ rec { }; "zstd" = rec { crateName = "zstd"; - version = "0.13.0"; + version = "0.13.2"; edition = "2018"; - sha256 = "0401q54s9r35x2i7m1kwppgkj79g0pb6xz3xpby7qlkdb44k7yxz"; + sha256 = "1ygkr6wspm9clbp7ykyl0rv69cfsf9q4lic9wcqiwn34lrwbgwpw"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -8066,9 +8719,10 @@ rec { }; "zstd-safe" = rec { crateName = "zstd-safe"; - version = "7.0.0"; + version = "7.2.1"; edition = "2018"; - sha256 = "0gpav2lcibrpmyslmjkcn3w0w64qif3jjljd2h8lr4p249s7qx23"; + sha256 = "0nch85m5cr493y26yvndm6a8j6sd9mxpr2awrim3dslcnr6sp8sl"; + libName = "zstd_safe"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -8098,10 +8752,11 @@ rec { }; "zstd-sys" = rec { crateName = "zstd-sys"; - version = "2.0.9+zstd.1.5.5"; + version = "2.0.13+zstd.1.5.6"; edition = "2018"; links = "zstd"; - sha256 = "0mk6a2367swdi22zg03lcackpnvgq96d7120awd4i83lm2lfy5ly"; + sha256 = "1almbackh06am0d2kc4a089n3al91jg3ahgg9kcrg3zfrwhhzzrq"; + libName = "zstd_sys"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -8137,14 +8792,11 @@ rec { fuchsia = true; test = false; - /* We are choosing an arbitrary rust version to grab `lib` from, - which is unfortunate, but `lib` has been version-agnostic the - whole time so this is good enough for now. - */ - os = pkgs.rust.lib.toTargetOs platform; - arch = pkgs.rust.lib.toTargetArch platform; - family = pkgs.rust.lib.toTargetFamily platform; - vendor = pkgs.rust.lib.toTargetVendor platform; + inherit (platform.rust.platform) + arch + os + vendor; + family = platform.rust.platform.target-family; env = "gnu"; endian = if platform.parsed.cpu.significantByte.name == "littleEndian" @@ -8221,6 +8873,7 @@ rec { ( _: { buildTests = true; + release = false; } ); # If the user hasn't set any pre/post commands, we don't want to @@ -8233,51 +8886,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; - export RUST_BACKTRACE=1 + inherit (crate) src; - # recreate a file hierarchy as when running tests with cargo + inherit testCrateFlags; - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # TODO(raitobezarius): I believe there could be more edge cases if `crate.sourceRoot` - # do exist but it's very hard to reason about them, so let's wait until the first bug report. - mkdir -p source/ - cd source/ + buildInputs = testInputs; - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + buildPhase = '' + set -e + export RUST_BACKTRACE=1 - # build outputs - testRoot=target/debug - mkdir -p $testRoot + # build outputs + testRoot=target/debug + mkdir -p $testRoot - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { @@ -8386,7 +9029,7 @@ rec { let self = { crates = lib.mapAttrs (packageId: value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs; - target = makeTarget pkgs.stdenv.hostPlatform; + target = makeTarget stdenv.hostPlatform; build = mkBuiltByPackageIdByPkgs pkgs.buildPackages; }; in @@ -8461,8 +9104,6 @@ rec { buildRustCrateForPkgsFunc pkgs ( crateConfig // { - # https://github.com/NixOS/nixpkgs/issues/218712 - dontStrip = stdenv.hostPlatform.isDarwin; src = crateConfig.src or ( pkgs.fetchurl rec { name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz"; diff --git a/tvix/tools/weave/Cargo.toml b/users/edef/weave/Cargo.toml index 7c6c2d2f0cf6..936428526046 100644 --- a/tvix/tools/weave/Cargo.toml +++ b/users/edef/weave/Cargo.toml @@ -10,11 +10,14 @@ members = ["."] [dependencies] anyhow = { version = "1.0.79", features = ["backtrace"] } hashbrown = "0.14.3" -nix-compat = { version = "0.1.0", path = "../../nix-compat" } -owning_ref = "0.4.1" +nix-compat = { version = "0.1.0", path = "../../../tvix/nix-compat" } +safer_owning_ref = "0.5.0" rayon = "1.8.1" -tokio = { version = "1.36.0", features = ["full"] } +rustc-hash = "2.0.0" +tvix-tracing = { version = "0.1.0", path = "../../../tvix/tracing" } +tracing = "0.1.40" +tracing-indicatif = "0.3.6" [dependencies.polars] version = "0.36.2" -features = ["parquet"] +features = ["parquet", "lazy", "streaming"] diff --git a/tvix/tools/weave/OWNERS b/users/edef/weave/OWNERS index b9bc074a8020..b9bc074a8020 100644 --- a/tvix/tools/weave/OWNERS +++ b/users/edef/weave/OWNERS diff --git a/users/edef/weave/default.nix b/users/edef/weave/default.nix new file mode 100644 index 000000000000..3d979b6d3327 --- /dev/null +++ b/users/edef/weave/default.nix @@ -0,0 +1,11 @@ +{ pkgs, depot, ... }: + +(pkgs.callPackage ./Cargo.nix { + defaultCrateOverrides = (depot.tvix.utils.defaultCrateOverridesForPkgs pkgs) // { + weave = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + }; +}).rootCrate.build.overrideAttrs { + meta.ci.extraSteps.crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; +} diff --git a/users/edef/weave/src/bin/swizzle.rs b/users/edef/weave/src/bin/swizzle.rs new file mode 100644 index 000000000000..840a53454f57 --- /dev/null +++ b/users/edef/weave/src/bin/swizzle.rs @@ -0,0 +1,118 @@ +//! Swizzle reads a `narinfo.parquet` file, usually produced by `narinfo2parquet`. +//! +//! It swizzles the reference list, ie it converts the references from absolute, +//! global identifiers (store path hashes) to indices into the `store_path_hash` +//! column (ie, row numbers), so that we can later walk the reference graph +//! efficiently. +//! +//! Path hashes are represented as non-null, 20-byte `Binary` values. +//! The indices are represented as 32-bit unsigned integers, with in-band nulls +//! represented by [INDEX_NULL] (the all-1 bit pattern), to permit swizzling +//! partial datasets. +//! +//! In essence, it converts from names to pointers, so that `weave` can simply +//! chase pointers to trace the live set. This replaces an `O(log(n))` lookup +//! with `O(1)` indexing, and produces a much denser representation that actually +//! fits in memory. +//! +//! The in-memory representation is at least 80% smaller, and the indices compress +//! well in Parquet due to both temporal locality of reference and the power law +//! distribution of reference "popularity". +//! +//! Only two columns are read from `narinfo.parquet`: +//! +//! * `store_path_hash :: PathHash` +//! * `references :: List[PathHash]` +//! +//! Output is written to `narinfo-references.parquet` in the form of a single +//! `List[u32]` column, `reference_idxs`. +//! +//! This file is inherently bound to the corresponding `narinfo.parquet`, +//! since it essentially contains pointers into this file. + +use anyhow::Result; +use hashbrown::HashTable; +use polars::{ + lazy::dsl::{col, SpecialEq}, + prelude::*, +}; +use tracing::info_span; +use tracing_indicatif::span_ext::IndicatifSpanExt as _; + +use weave::{as_fixed_binary, hash64, leak, load_ph_array, INDEX_NULL}; + +#[tracing::instrument] +fn main() -> Result<()> { + let _tracing = tvix_tracing::TracingBuilder::default() + .enable_progressbar() + .build()?; + + let ph_array: &'static [[u8; 20]] = leak(load_ph_array()?); + + // TODO(edef): re-parallelise this + // We originally parallelised on chunks, but ph_array is only a single chunk, due to how Parquet loading works. + // TODO(edef): outline the 64-bit hash prefix? it's an indirection, but it saves ~2G of memory + let ph_map: &'static HashTable<(u64, u32)> = { + let span = info_span!("ph_map", indicatif.pb_show = tracing::field::Empty).entered(); + span.pb_set_message("build index"); + span.pb_start(); + + let mut ph_map = HashTable::with_capacity(ph_array.len()); + + for (offset, item) in ph_array.iter().enumerate() { + let offset = offset as u32; + let hash = hash64(item); + ph_map.insert_unique(hash, (hash, offset), |&(hash, _)| hash); + } + + &*Box::leak(Box::new(ph_map)) + }; + + let ph_to_idx = |key: &[u8; 20]| -> u32 { + let hash = hash64(key); + ph_map + .find(hash, |&(candidate_hash, candidate_index)| { + candidate_hash == hash && &ph_array[candidate_index as usize] == key + }) + .map(|&(_, index)| index) + .unwrap_or(INDEX_NULL) + }; + + { + let span = info_span!("swizzle_refs", indicatif.pb_show = tracing::field::Empty).entered(); + span.pb_set_message("swizzle references"); + span.pb_start(); + + LazyFrame::scan_parquet("narinfo.parquet", ScanArgsParquet::default())? + .with_column( + col("references") + .map( + move |series: Series| -> PolarsResult<Option<Series>> { + Ok(Some( + series + .list()? + .apply_to_inner(&|series: Series| -> PolarsResult<Series> { + let series = series.binary()?; + let mut out: Vec<u32> = Vec::with_capacity(series.len()); + out.extend( + as_fixed_binary(series).flatten().map(ph_to_idx), + ); + Ok(Series::from_vec("reference_idxs", out)) + })? + .into_series(), + )) + }, + SpecialEq::from_type(DataType::List(DataType::UInt32.into())), + ) + .alias("reference_idxs"), + ) + .select([col("reference_idxs")]) + .with_streaming(true) + .sink_parquet( + "narinfo-references.parquet".into(), + ParquetWriteOptions::default(), + )?; + }; + + Ok(()) +} diff --git a/tvix/tools/weave/src/lib.rs b/users/edef/weave/src/lib.rs index bc2221bf5c9b..ff5bf9232676 100644 --- a/tvix/tools/weave/src/lib.rs +++ b/users/edef/weave/src/lib.rs @@ -1,6 +1,14 @@ use anyhow::Result; +use owning_ref::{ArcRef, OwningRef}; use rayon::prelude::*; -use std::{fs::File, ops::Range, slice}; +use std::{ + fs::File, + mem, + ops::{Deref, Range}, + slice, + sync::Arc, +}; +use tracing_indicatif::span_ext::IndicatifSpanExt as _; use polars::{ datatypes::BinaryChunked, @@ -8,11 +16,11 @@ use polars::{ prelude::{ParquetReader, SerReader}, }; -pub use crate::bytes::*; -mod bytes; +/// An shared `[[u8; N]]` backed by a Polars [Buffer]. +pub type FixedBytes<const N: usize> = + ArcRef<'static, polars::export::arrow::buffer::Bytes<u8>, [[u8; N]]>; pub const INDEX_NULL: u32 = !0; -pub const DONE: &str = "\u{2714}"; /// A terrific hash function, turning 20 bytes of cryptographic hash /// into 8 bytes of cryptographic hash. @@ -22,10 +30,25 @@ pub fn hash64(h: &[u8; 20]) -> u64 { u64::from_ne_bytes(buf) } +pub fn leak<O, T: ?Sized>(r: OwningRef<Arc<O>, T>) -> &T { + // SAFETY: Either `ptr` points into the `Arc`, which lives until `r` is dropped, + // or it points at something else entirely which lives at least as long. + unsafe { + let ptr: *const T = r.deref(); + mem::forget(r); + &*ptr + } +} + /// Read a dense `store_path_hash` array from `narinfo.parquet`, /// returning it as an owned [FixedBytes]. +#[tracing::instrument(fields(indicatif.pb_show = tracing::field::Empty))] pub fn load_ph_array() -> Result<FixedBytes<20>> { - eprint!("… load store_path_hash\r"); + let span = tracing::Span::current(); + + span.pb_set_message("load store_path_hash"); + span.pb_start(); + // TODO(edef): this could use a further pushdown, since polars is more hindrance than help here // We know this has to fit in memory (we can't mmap it without further encoding constraints), // and we want a single `Vec<[u8; 20]>` of the data. @@ -39,7 +62,6 @@ pub fn load_ph_array() -> Result<FixedBytes<20>> { ); u32::try_from(ph_array.len()).expect("dataset exceeds 2^32"); - eprintln!("{DONE}"); Ok(ph_array) } @@ -47,7 +69,7 @@ pub fn load_ph_array() -> Result<FixedBytes<20>> { /// Iterator over `&[[u8; N]]` from a dense [BinaryChunked]. pub fn as_fixed_binary<const N: usize>( chunked: &BinaryChunked, -) -> impl Iterator<Item = &[[u8; N]]> + DoubleEndedIterator { +) -> impl DoubleEndedIterator<Item = &[[u8; N]]> { chunked.downcast_iter().map(|array| { let range = assert_fixed_dense::<N>(array); exact_chunks(&array.values()[range]).unwrap() @@ -60,10 +82,15 @@ fn into_fixed_binary_rechunk<const N: usize>(chunked: &BinaryChunked) -> FixedBy let chunked = chunked.rechunk(); let mut iter = chunked.downcast_iter(); let array = iter.next().unwrap(); + assert!(iter.next().is_none()); + + let (buf, off, len) = { + let range = assert_fixed_dense::<N>(array); + array.values().clone().sliced(range.start, range.len()) + } + .into_inner(); - let range = assert_fixed_dense::<N>(array); - Bytes(array.values().clone().sliced(range.start, range.len())) - .map(|buf| exact_chunks(buf).unwrap()) + ArcRef::new(buf).map(|bytes| exact_chunks(&bytes[off..off + len]).unwrap()) } /// Ensures that the supplied Arrow array consists of densely packed bytestrings of length `N`. diff --git a/users/edef/weave/src/main.rs b/users/edef/weave/src/main.rs new file mode 100644 index 000000000000..b1dd27d8c1af --- /dev/null +++ b/users/edef/weave/src/main.rs @@ -0,0 +1,262 @@ +//! Weave resolves a list of roots from `releases.parquet` against `narinfo.parquet`, +//! and then uses the reference graph from the accompanying `narinfo-references.parquet` +//! produced by `swizzle` to collect the closure of the roots. +//! +//! They are written to `live_idxs.parquet`, which only has one column, representing +//! the row numbers in `narinfo.parquet` corresponding to live paths. + +use anyhow::Result; +use hashbrown::{hash_table, HashTable}; +use rayon::prelude::*; +use rustc_hash::FxHashSet; +use std::{ + collections::BTreeMap, + fs::File, + ops::Index, + sync::atomic::{AtomicU32, Ordering}, +}; +use tracing::{info_span, warn}; +use tracing_indicatif::span_ext::IndicatifSpanExt; + +use polars::{ + datatypes::StaticArray, + export::arrow::{array::UInt32Array, offset::OffsetsBuffer}, + lazy::dsl::col, + prelude::*, +}; + +use weave::{as_fixed_binary, hash64, INDEX_NULL}; + +#[tracing::instrument] +fn main() -> Result<()> { + let _tracing = tvix_tracing::TracingBuilder::default() + .enable_progressbar() + .build()?; + + let roots: PathSet32 = { + let span = info_span!("parse_roots", indicatif.pb_show = tracing::field::Empty).entered(); + span.pb_set_message("parse roots"); + span.pb_start(); + + as_fixed_binary::<20>( + LazyFrame::scan_parquet("releases.parquet", ScanArgsParquet::default())? + .explode([col("store_path_hash")]) + .select([col("store_path_hash")]) + .collect()? + .column("store_path_hash")? + .binary()?, + ) + .flatten() + .collect() + }; + + { + let span = info_span!("resolve_roots", indicatif.pb_show = tracing::field::Empty).entered(); + span.pb_set_message("resolve roots"); + span.pb_start(); + + weave::load_ph_array()? + .into_par_iter() + .enumerate() + .for_each(|(idx, h)| { + if let Some(idx_slot) = roots.find(h) { + assert_eq!( + idx_slot.swap(idx as u32, Ordering::Relaxed), + INDEX_NULL, + "duplicate entry" + ); + } + }); + } + + let mut todo = FxHashSet::default(); + todo.reserve(roots.len()); + { + let mut unknown_roots = 0usize; + for (_, idx) in roots.table { + let idx = idx.into_inner(); + if idx == INDEX_NULL { + unknown_roots += 1; + continue; + } + todo.insert(idx); + } + + if unknown_roots != 0 { + warn!("skipping {unknown_roots} unknown roots"); + } + } + + let ri_array; + let ri_array = { + let span = info_span!( + "load_reference_idxs", + indicatif.pb_show = tracing::field::Empty + ) + .entered(); + span.pb_set_message("load reference_idxs"); + span.pb_start(); + + ri_array = ParquetReader::new(File::open("narinfo-references.parquet")?) + .finish()? + .column("reference_idxs")? + .list()? + .clone(); + + ChunkedList::new(ri_array.downcast_iter().map(|chunk| { + ( + chunk.offsets(), + chunk + .values() + .as_any() + .downcast_ref::<UInt32Array>() + .unwrap() + .as_slice() + .unwrap(), + ) + })) + }; + + let mut seen = todo.clone(); + { + let span = info_span!("mark", indicatif.pb_show = tracing::field::Empty).entered(); + span.pb_set_message("marking"); + span.pb_set_style(&tvix_tracing::PB_PROGRESS_STYLE); + + while !todo.is_empty() { + span.pb_set_length(seen.len() as u64); + span.pb_set_position(seen.len().saturating_sub(todo.len()) as u64); + + todo = todo + .par_iter() + .flat_map(|&parent| { + if parent == INDEX_NULL { + return FxHashSet::default(); + } + + ri_array[parent as usize] + .iter() + .cloned() + .filter(|child| !seen.contains(child)) + .collect::<FxHashSet<u32>>() + }) + .collect(); + + for &index in &todo { + seen.insert(index); + } + } + + span.pb_set_length(seen.len() as u64); + span.pb_set_position(seen.len() as u64); + + if seen.remove(&INDEX_NULL) { + warn!("WARNING: missing edges"); + } + } + + let seen = { + let span = info_span!("gather_live", indicatif.pb_show = tracing::field::Empty).entered(); + span.pb_set_message("gathering live set"); + + let mut seen: Vec<u32> = seen.into_iter().collect(); + seen.par_sort(); + seen + }; + + { + let span = info_span!("write_output", indicatif.pb_show = tracing::field::Empty).entered(); + span.pb_set_message("writing output"); + span.pb_start(); + + ParquetWriter::new(File::create("live_idxs.parquet")?).finish(&mut df! { + "live_idx" => seen, + }?)?; + } + + Ok(()) +} + +struct PathSet32 { + table: HashTable<([u8; 20], AtomicU32)>, +} + +impl PathSet32 { + fn with_capacity(capacity: usize) -> Self { + Self { + table: HashTable::with_capacity(capacity), + } + } + + fn insert(&mut self, value: &[u8; 20]) -> bool { + let hash = hash64(value); + + match self + .table + .entry(hash, |(x, _)| x == value, |(x, _)| hash64(x)) + { + hash_table::Entry::Occupied(_) => false, + hash_table::Entry::Vacant(entry) => { + entry.insert((*value, AtomicU32::new(INDEX_NULL))); + true + } + } + } + + fn find(&self, value: &[u8; 20]) -> Option<&AtomicU32> { + let hash = hash64(value); + self.table + .find(hash, |(x, _)| x == value) + .as_ref() + .map(|(_, x)| x) + } + + fn len(&self) -> usize { + self.table.len() + } +} + +impl<'a> FromIterator<&'a [u8; 20]> for PathSet32 { + fn from_iter<T: IntoIterator<Item = &'a [u8; 20]>>(iter: T) -> Self { + let iter = iter.into_iter(); + let mut this = Self::with_capacity(iter.size_hint().0); + + for item in iter { + this.insert(item); + } + + this.table.shrink_to_fit(|(x, _)| hash64(x)); + this + } +} + +struct ChunkedList<'a, T> { + by_offset: BTreeMap<usize, (&'a OffsetsBuffer<i64>, &'a [T])>, +} + +impl<'a, T> ChunkedList<'a, T> { + fn new(chunks: impl IntoIterator<Item = (&'a OffsetsBuffer<i64>, &'a [T])>) -> Self { + let mut next_offset = 0usize; + ChunkedList { + by_offset: chunks + .into_iter() + .map(|(offsets, values)| { + let offset = next_offset; + next_offset = next_offset.checked_add(offsets.len_proxy()).unwrap(); + + (offset, (offsets, values)) + }) + .collect(), + } + } +} + +impl<'a, T> Index<usize> for ChunkedList<'a, T> { + type Output = [T]; + + fn index(&self, index: usize) -> &Self::Output { + let (&base, &(offsets, values)) = self.by_offset.range(..=index).next_back().unwrap(); + let (start, end) = offsets.start_end(index - base); + &values[start..end] + } +} diff --git a/users/emery/OWNERS b/users/emery/OWNERS new file mode 100644 index 000000000000..9e052507d2da --- /dev/null +++ b/users/emery/OWNERS @@ -0,0 +1,3 @@ +set noparent + +emery diff --git a/users/emery/eaglemode/default.nix b/users/emery/eaglemode/default.nix new file mode 100644 index 000000000000..471e8eda67f7 --- /dev/null +++ b/users/emery/eaglemode/default.nix @@ -0,0 +1,13 @@ +# Derivation for my fully configured Eagle Mode. +{ depot, ... }: + +let + config = depot.tools.eaglemode.etcDir { + extraPaths = [ + depot.tools.eaglemode.commands.B + depot.tools.eaglemode.plugins.avif + depot.tools.eaglemode.plugins.qoi + ]; + }; +in +depot.tools.eaglemode.withConfig { inherit config; } diff --git a/users/emery/pkgs/syndicate-server.nix b/users/emery/pkgs/syndicate-server.nix new file mode 100644 index 000000000000..e8bf73836f24 --- /dev/null +++ b/users/emery/pkgs/syndicate-server.nix @@ -0,0 +1,34 @@ +{ pkgs, ... }: + +let + inherit (pkgs) + rustPlatform + rust-bin + fetchFromGitea + pkg-config + openssl + ; +in + +rustPlatform.buildRustPackage rec { + pname = "syndicate-server"; + version = "0.46.0"; + src = fetchFromGitea { + domain = "git.syndicate-lang.org"; + owner = "syndicate-lang"; + repo = "syndicate-rs"; + rev = "${pname}-v${version}"; + sha256 = "sha256-bTteZIlBSoQ1o5shgd9NeKVvEhZTyG3i2zbeVojWiO8="; + }; + cargoHash = "sha256-SIpdFXTk6MC/drjCLaaa49BbGsvCMNbPGCfTxAlCo9c="; + nativeBuildInputs = [ pkg-config ]; + buildInputs = [ openssl ]; + + RUSTC_BOOTSTRAP = 1; + + meta = { + description = "Syndicate broker server"; + homepage = "https://git.syndicate-lang.org/syndicate-lang/syndicate-rs/"; + mainProgram = "syndicate-server"; + }; +} diff --git a/users/emery/workman-cyrillic.xkb b/users/emery/workman-cyrillic.xkb new file mode 100644 index 000000000000..f6783bab7b81 --- /dev/null +++ b/users/emery/workman-cyrillic.xkb @@ -0,0 +1,118 @@ +# Workman with phonetic transliteration layer for Cyrllic. +# Switch layers using Shift+CapsLock. + +partial alphanumeric_keys +xkb_symbols "workman-emery" { + + name[Group1]= "Emery"; + + include "us(euro)" + + // Alphanumeric section + key <AE01> { [ 1, exclam ] }; + key <AE02> { [ 2, at ] }; + key <AE03> { [ 3, numbersign ] }; + key <AE04> { [ 4, dollar ] }; + key <AE05> { [ 5, percent ] }; + key <AE06> { [ 6, asciicircum ] }; + key <AE07> { [ 7, ampersand ] }; + key <AE08> { [ 8, asterisk ] }; + key <AE09> { [ 9, parenleft ] }; + key <AE10> { [ 0, parenright ] }; + + key <AD01> { + [ q, Q, adiaeresis, Adiaeresis ], + [ U044B, U042B, U044c, U042C ] }; # Ñ‹ Ы ÑŒ Ь + key <AD02> { + [ d, D, U0111, U0111 ], # d D Ä‘ Ä‘ + [ U0434, U0414, U0452, U0402 ] }; # д Д Ñ’ Ђ + key <AD03> { + [ r, R, U20AC, U20AC ], + [ U0440, U0420, U20AC, U20AC ] }; # Ñ€ Ð + key <AD04> { + [ w, W, aring, Aring ], + [ U0447, U0427, U045B, U040B ] }; # ч Ч Ñ› Ћ + key <AD05> { + [ b, B, b, B ], + [ U0431, U0411 ]}; # б Б + key <AD06> { + [ j, J, U0135, U0134 ], # j J ĵ Ä´ + [ U0458, U0408 ]}; # ј Ј + key <AD07> { + [ f, F, 0x1002200, F ], # f F ∀ F + [ U0444, U0424, U0473, U0472 ]}; # Ñ„ Ф ѳ Ѳ + key <AD08> { + [ u, U, U016D, U016C ], + [ U0443, U0423, U045E, U040E ] }; # у У Ñž ÐŽ + key <AD09> { + [ p, P, sterling, sterling ], + [ U043F, U041F, sterling, sterling ] }; # п П + key <AD10> { + [ semicolon, colon, paragraph, degree ] }; + + key <AC01> { + [ a, A, adiaeresis, Adiaeresis ], + [ U0430, U0410, U2248, U00B6 ] # а Р≈ ¶ + }; + key <AC02> { + [ s, S, U0161, U0160 ], + [ U0441, U0421, U0448, U0428 ] # Ñ Ð¡ ш Ш + }; + key <AC03> { + [ h, H, U010D, U010C ], + [ U0445, U0425 , U044B, U042B ] }; # Ñ… Ð¥ + key <AC04> { + [ t, T, thorn, THORN ], + [ U0442, U0422] }; # Ñ‚ Т + key <AC05> { + [ g, G, U011D, U011C ], + [ U0433, U0413 ] }; # г Г + key <AC06> { + [ y, Y, udiaeresis, Udiaeresis ], + [ U044f, U042f, U044D, U042D ] }; # Ñ Ð¯ Ñ Ð + key <AC07> { + [ n, N, ntilde, Ntilde ], + [ U043D, U041D, U045A, U040A ] }; # н Ð Ñš Њ + key <AC08> { + [ e, E, ediaeresis, Ediaeresis ], + [ U0435, U0415, U0451, U0401 ] }; # е Е Ñ‘ Ð + key <AC09> { + [ o, O, odiaeresis, Odiaeresis ], + [ U043E, U041E, U044E, U042E ] }; # о О ÑŽ Ю + key <AC10> { + [ i, I, idiaeresis, Idiaeresis ], + [ U0438, U0418, U0439, U0419 ] }; # и И й + key <AC11> { + [], + [ U0447, U0427, U045B, U040B ] }; # ч Ч Ñ› Ћ + + key <AB01> { + [ z, Z, U017E, U017D ], + [ U0437, U0417, U0436, U0416 ] }; # з З ж Ж + key <AB02> { + [ x, X, x, X ], + [ U045F, U040F ] }; # ÑŸ Ð + key <AB03> { + [ m, M, mu, mu ], + [ U043C, U041C, mu, mu ] }; # м Ðœ + key <AB04> { + [ c, C, U0107, U0106 ], + [ U0446, U0426, U00A9, U2103 ] }; # ц Ц © ℃ + key <AB05> { + [ v, V, v, V ], + [ U0432, U0412 ]}; # в Ð’ + key <AB06> { + [ k, K, oe, OE ], + [ U043A, U041A ] }; # к К + key <AB07> { + [ l, L, U01C9, U01C8 ], + [ U043B, U041B, U0459, U0409 ] }; # л Л Ñ™ Љ + key <AB08> { [ comma, less, ellipsis, guillemotleft ] }; + key <AB09> { [ period, greater, ellipsis, guillemotright ] }; + // End alphanumeric section + + key <CAPS> { [ BackSpace, ISO_Next_Group ] }; + + key <SPCE> { [ space, minus, space, space ] }; + include "level3(ralt_switch)" +}; diff --git a/users/flokli/archeology/default.nix b/users/flokli/archeology/default.nix index d642399cbe68..690944403b97 100644 --- a/users/flokli/archeology/default.nix +++ b/users/flokli/archeology/default.nix @@ -10,7 +10,7 @@ let ''; # clickhouse has a very odd AWS config concept. # Configure it to be a bit more sane. - clickhoseLocalFixedAWS = pkgs.runCommand "clickhouse-local-fixed" + clickhouseLocalFixedAWS = pkgs.runCommand "clickhouse-local-fixed" { nativeBuildInputs = [ pkgs.makeWrapper ]; } '' @@ -21,19 +21,19 @@ let in depot.nix.readTree.drvTargets { - inherit clickhoseLocalFixedAWS; + inherit clickhouseLocalFixedAWS; parse-bucket-logs = pkgs.runCommand "archeology-parse-bucket-logs" { nativeBuildInputs = [ pkgs.makeWrapper ]; } '' mkdir -p $out/bin makeWrapper ${(pkgs.writers.writeRust "parse-bucket-logs-unwrapped" {} ./parse_bucket_logs.rs)} $out/bin/archeology-parse-bucket-logs \ - --prefix PATH : ${pkgs.lib.makeBinPath [ clickhoseLocalFixedAWS ]} + --prefix PATH : ${pkgs.lib.makeBinPath [ clickhouseLocalFixedAWS ]} ''; shell = pkgs.mkShell { name = "archeology-shell"; - packages = with pkgs; [ awscli2 clickhoseLocalFixedAWS rust-analyzer rustc rustfmt ]; + packages = with pkgs; [ awscli2 clickhouseLocalFixedAWS rust-analyzer rustc rustfmt ]; AWS_PROFILE = "sso"; AWS_CONFIG_FILE = pkgs.writeText "aws-config" '' diff --git a/users/flokli/ipu6-softisp/config.nix b/users/flokli/ipu6-softisp/config.nix index 95cb3e5c2563..0e47c88fbbad 100644 --- a/users/flokli/ipu6-softisp/config.nix +++ b/users/flokli/ipu6-softisp/config.nix @@ -12,27 +12,9 @@ let # but manually piped to git and back, as some renames were not processed properly. # It was later refreshed with https://patchwork.libcamera.org/cover/19663/ patches = old.patches or [ ] ++ [ - ./libcamera/0001-libcamera-pipeline-simple-fix-size-adjustment-in-val.patch - ./libcamera/0002-libcamera-internal-Move-dma_heaps.-h-cpp-to-common-d.patch - ./libcamera/0003-libcamera-dma_heaps-extend-DmaHeap-class-to-support-.patch - ./libcamera/0004-libcamera-internal-Move-SharedMemObject-class-to-a-c.patch - ./libcamera/0005-libcamera-shared_mem_object-reorganize-the-code-and-.patch - ./libcamera/0006-libcamera-software_isp-Add-SwStatsCpu-class.patch - ./libcamera/0007-libcamera-software_isp-Add-Debayer-base-class.patch - ./libcamera/0008-libcamera-software_isp-Add-DebayerCpu-class.patch - ./libcamera/0009-libcamera-ipa-add-Soft-IPA.patch - ./libcamera/0010-libcamera-introduce-SoftwareIsp.patch - ./libcamera/0011-libcamera-pipeline-simple-rename-converterBuffers_-a.patch - ./libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch - ./libcamera/0013-libcamera-swstats_cpu-Add-support-for-8-10-and-12-bp.patch - ./libcamera/0014-libcamera-debayer_cpu-Add-support-for-8-10-and-12-bp.patch - ./libcamera/0015-libcamera-debayer_cpu-Add-BGR888-output-support.patch - ./libcamera/0016-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch - ./libcamera/0017-libcamera-Add-Software-ISP-benchmarking-documentatio.patch - ./libcamera/0018-libcamera-software_isp-Apply-black-level-compensatio.patch - ./libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch - ./libcamera/0020-ov01a1s-HACK.patch - ./libcamera/0021-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch + ./libcamera/0001-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch + ./libcamera/0002-ov01a1s-HACK.patch + ./libcamera/0003-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch ]; }); diff --git a/users/flokli/ipu6-softisp/default.nix b/users/flokli/ipu6-softisp/default.nix index 1f603dbb4283..ab129d1bc85e 100644 --- a/users/flokli/ipu6-softisp/default.nix +++ b/users/flokli/ipu6-softisp/default.nix @@ -11,8 +11,8 @@ let systemFor = sys: (depot.ops.nixos.nixosFor sys).system; in -depot.nix.readTree.drvTargets rec { - testSystem = systemFor ({ modulesPath, pkgs, ... }: { +(depot.nix.readTree.drvTargets rec { + testSystem = (systemFor ({ modulesPath, pkgs, ... }: { imports = [ # Import the module, this is something a user would do in their config. ./config.nix @@ -39,19 +39,22 @@ depot.nix.readTree.drvTargets rec { # Shut off the warning. system.stateVersion = "24.05"; - }); + })) // { + # 2024-07-28 aspen: The patches no longer cleanly apply on upstream + meta.broken = true; + }; # Make sure the firmware requested by the driver is present in our firmware. - # We do have a .xz suffix here, but that's fine, since request_firmware does - # check ${name}.xz too in case CONFIG_FW_LOADER_COMPRESS is set. + # We do have a .zst suffix here, but that's fine, since request_firmware does + # check ${name}.zst too in case CONFIG_FW_LOADER_COMPRESS is set. # The path needs to be kept in sync with the ones used in the kernel patch. checkFirmware = pkgs.runCommand "check-firmware" { } '' - stat ${testSystem}/firmware/intel/ipu/ipu6se_fw.bin.xz - stat ${testSystem}/firmware/intel/ipu/ipu6ep_fw.bin.xz - stat ${testSystem}/firmware/intel/ipu/ipu6_fw.bin.xz - stat ${testSystem}/firmware/intel/ipu/ipu6epmtl_fw.bin.xz + stat ${testSystem}/firmware/intel/ipu/ipu6se_fw.bin.zst + stat ${testSystem}/firmware/intel/ipu/ipu6ep_fw.bin.zst + stat ${testSystem}/firmware/intel/ipu/ipu6_fw.bin.zst + stat ${testSystem}/firmware/intel/ipu/ipu6epmtl_fw.bin.zst # all good, succeed build touch $out ''; -} +}) diff --git a/users/flokli/ipu6-softisp/kernel/softisp.patch b/users/flokli/ipu6-softisp/kernel/softisp.patch index 8731ed914c1d..e1395bbb135f 100644 --- a/users/flokli/ipu6-softisp/kernel/softisp.patch +++ b/users/flokli/ipu6-softisp/kernel/softisp.patch @@ -1,16249 +1,7 @@ -From 037f05a9772f3243907bb826e913971ee20e9487 Mon Sep 17 00:00:00 2001 -From: Sakari Ailus <sakari.ailus@linux.intel.com> -Date: Tue, 8 Aug 2023 10:55:31 +0300 -Subject: [PATCH 01/33] media: mc: Add INTERNAL pad flag - -Internal source pads will be used as routing endpoints in V4L2 -[GS]_ROUTING IOCTLs, to indicate that the stream begins in the entity. - -Also prevent creating links to pads that have been flagged as internal. - -Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> ---- - Documentation/userspace-api/media/glossary.rst | 6 ++++++ - Documentation/userspace-api/media/mediactl/media-types.rst | 6 ++++++ - drivers/media/mc/mc-entity.c | 6 +++++- - include/uapi/linux/media.h | 1 + - 4 files changed, 18 insertions(+), 1 deletion(-) - -diff --git a/Documentation/userspace-api/media/glossary.rst b/Documentation/userspace-api/media/glossary.rst -index 96a360edbf3b..f7b99a4527c7 100644 ---- a/Documentation/userspace-api/media/glossary.rst -+++ b/Documentation/userspace-api/media/glossary.rst -@@ -173,6 +173,12 @@ Glossary - An integrated circuit that integrates all components of a computer - or other electronic systems. - -+_media-glossary-stream: -+ Stream -+ A distinct flow of data (image data or metadata) over a media pipeline -+ from source to sink. A source may be e.g. an image sensor and a sink -+ e.g. a memory buffer. -+ - V4L2 API - **V4L2 userspace API** - -diff --git a/Documentation/userspace-api/media/mediactl/media-types.rst b/Documentation/userspace-api/media/mediactl/media-types.rst -index 0ffeece1e0c8..28941da27790 100644 ---- a/Documentation/userspace-api/media/mediactl/media-types.rst -+++ b/Documentation/userspace-api/media/mediactl/media-types.rst -@@ -361,6 +361,7 @@ Types and flags used to represent the media graph elements - .. _MEDIA-PAD-FL-SINK: - .. _MEDIA-PAD-FL-SOURCE: - .. _MEDIA-PAD-FL-MUST-CONNECT: -+.. _MEDIA-PAD-FL-INTERNAL: - - .. flat-table:: Media pad flags - :header-rows: 0 -@@ -382,6 +383,11 @@ Types and flags used to represent the media graph elements - when this flag isn't set; the absence of the flag doesn't imply - there is none. - -+ * - ``MEDIA_PAD_FL_INTERNAL`` -+ - The internal flag indicates an internal pad that has no external -+ connections. Such a pad shall not be connected with a link. The -+ internal flag indicates that the :ref:``stream -+ <media-glossary-stream>`` either starts or ends in the entity. - - One and only one of ``MEDIA_PAD_FL_SINK`` and ``MEDIA_PAD_FL_SOURCE`` - must be set for every pad. -diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c -index 543a392f8635..1fc80fd3e5e3 100644 ---- a/drivers/media/mc/mc-entity.c -+++ b/drivers/media/mc/mc-entity.c -@@ -1075,7 +1075,8 @@ int media_get_pad_index(struct media_entity *entity, u32 pad_type, - - for (i = 0; i < entity->num_pads; i++) { - if ((entity->pads[i].flags & -- (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)) != pad_type) -+ (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE | -+ MEDIA_PAD_FL_INTERNAL)) != pad_type) - continue; - - if (entity->pads[i].sig_type == sig_type) -@@ -1098,6 +1099,9 @@ media_create_pad_link(struct media_entity *source, u16 source_pad, - return -EINVAL; - if (WARN_ON(!(source->pads[source_pad].flags & MEDIA_PAD_FL_SOURCE))) - return -EINVAL; -+ if (WARN_ON(source->pads[source_pad].flags & MEDIA_PAD_FL_SOURCE && -+ source->pads[source_pad].flags & MEDIA_PAD_FL_INTERNAL)) -+ return -EINVAL; - if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK))) - return -EINVAL; - -diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h -index 1c80b1d6bbaf..80cfd12a43fc 100644 ---- a/include/uapi/linux/media.h -+++ b/include/uapi/linux/media.h -@@ -208,6 +208,7 @@ struct media_entity_desc { - #define MEDIA_PAD_FL_SINK (1U << 0) - #define MEDIA_PAD_FL_SOURCE (1U << 1) - #define MEDIA_PAD_FL_MUST_CONNECT (1U << 2) -+#define MEDIA_PAD_FL_INTERNAL (1U << 3) - - struct media_pad_desc { - __u32 entity; /* entity ID */ --- -2.43.2 - - -From 5f0cdae874f1c0237936c2c12a9fc019b93de4c9 Mon Sep 17 00:00:00 2001 -From: Sakari Ailus <sakari.ailus@linux.intel.com> -Date: Tue, 8 Aug 2023 10:55:32 +0300 -Subject: [PATCH 02/33] media: uapi: Add generic serial metadata mbus formats - -Add generic serial metadata mbus formats. These formats describe data -width and packing but not the content itself. The reason for specifying -such formats is that the formats as such are fairly device specific but -they are still handled by CSI-2 receiver drivers that should not be aware -of device specific formats. What makes generic metadata formats possible -is that these formats are parsed by software only, after capturing the -data to system memory. - -Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> ---- - .../media/v4l/subdev-formats.rst | 257 ++++++++++++++++++ - include/uapi/linux/media-bus-format.h | 9 + - 2 files changed, 266 insertions(+) - -diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst -index eb3cd20b0cf2..7d107873cddd 100644 ---- a/Documentation/userspace-api/media/v4l/subdev-formats.rst -+++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst -@@ -8306,3 +8306,260 @@ The following table lists the existing metadata formats. - both sides of the link and the bus format is a fixed - metadata format that is not configurable from userspace. - Width and height will be set to 0 for this format. -+ -+Generic Serial Metadata Formats -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ -+Generic serial metadata formats are used on serial busses where the actual data -+content is more or less device specific but the data is transmitted and received -+by multiple devices that do not process the data in any way, simply writing -+it to system memory for processing in software at the end of the pipeline. -+ -+The more specific variant describing the actual data is used on the internal -+source pad of the originating sub-device. -+ -+"b" in an array cell signifies a byte of data, followed by the number of byte -+and finally the bit number in subscript. "p" indicates a padding bit. -+ -+.. _media-bus-format-generic-meta: -+ -+.. cssclass: longtable -+ -+.. flat-table:: Generic Serial Metadata Formats -+ :header-rows: 2 -+ :stub-columns: 0 -+ -+ * - Identifier -+ - Code -+ - -+ - :cspan:`23` Data organization -+ * - -+ - -+ - Bit -+ - 23 -+ - 22 -+ - 21 -+ - 20 -+ - 19 -+ - 18 -+ - 17 -+ - 16 -+ - 15 -+ - 14 -+ - 13 -+ - 12 -+ - 11 -+ - 10 -+ - 9 -+ - 8 -+ - 7 -+ - 6 -+ - 5 -+ - 4 -+ - 3 -+ - 2 -+ - 1 -+ - 0 -+ * .. _MEDIA-BUS-FMT-META-8: -+ -+ - MEDIA_BUS_FMT_META_8 -+ - 0x8001 -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - b0\ :sub:`7` -+ - b0\ :sub:`6` -+ - b0\ :sub:`5` -+ - b0\ :sub:`4` -+ - b0\ :sub:`3` -+ - b0\ :sub:`2` -+ - b0\ :sub:`1` -+ - b0\ :sub:`0` -+ * .. _MEDIA-BUS-FMT-META-10: -+ -+ - MEDIA_BUS_FMT_META_10 -+ - 0x8002 -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - b0\ :sub:`7` -+ - b0\ :sub:`6` -+ - b0\ :sub:`5` -+ - b0\ :sub:`4` -+ - b0\ :sub:`3` -+ - b0\ :sub:`2` -+ - b0\ :sub:`1` -+ - b0\ :sub:`0` -+ - p -+ - p -+ * .. _MEDIA-BUS-FMT-META-12: -+ -+ - MEDIA_BUS_FMT_META_12 -+ - 0x8003 -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - b0\ :sub:`7` -+ - b0\ :sub:`6` -+ - b0\ :sub:`5` -+ - b0\ :sub:`4` -+ - b0\ :sub:`3` -+ - b0\ :sub:`2` -+ - b0\ :sub:`1` -+ - b0\ :sub:`0` -+ - p -+ - p -+ - p -+ - p -+ * .. _MEDIA-BUS-FMT-META-14: -+ -+ - MEDIA_BUS_FMT_META_14 -+ - 0x8004 -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - b0\ :sub:`7` -+ - b0\ :sub:`6` -+ - b0\ :sub:`5` -+ - b0\ :sub:`4` -+ - b0\ :sub:`3` -+ - b0\ :sub:`2` -+ - b0\ :sub:`1` -+ - b0\ :sub:`0` -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ * .. _MEDIA-BUS-FMT-META-16: -+ -+ - MEDIA_BUS_FMT_META_16 -+ - 0x8005 -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - -+ - b0\ :sub:`7` -+ - b0\ :sub:`6` -+ - b0\ :sub:`5` -+ - b0\ :sub:`4` -+ - b0\ :sub:`3` -+ - b0\ :sub:`2` -+ - b0\ :sub:`1` -+ - b0\ :sub:`0` -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ * .. _MEDIA-BUS-FMT-META-20: -+ -+ - MEDIA_BUS_FMT_META_20 -+ - 0x8007 -+ - -+ - -+ - -+ - -+ - -+ - b0\ :sub:`7` -+ - b0\ :sub:`6` -+ - b0\ :sub:`5` -+ - b0\ :sub:`4` -+ - b0\ :sub:`3` -+ - b0\ :sub:`2` -+ - b0\ :sub:`1` -+ - b0\ :sub:`0` -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ * .. _MEDIA-BUS-FMT-META-24: -+ -+ - MEDIA_BUS_FMT_META_24 -+ - 0x8009 -+ - -+ - b0\ :sub:`7` -+ - b0\ :sub:`6` -+ - b0\ :sub:`5` -+ - b0\ :sub:`4` -+ - b0\ :sub:`3` -+ - b0\ :sub:`2` -+ - b0\ :sub:`1` -+ - b0\ :sub:`0` -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -+ - p -diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h -index f05f747e444d..d4c1d991014b 100644 ---- a/include/uapi/linux/media-bus-format.h -+++ b/include/uapi/linux/media-bus-format.h -@@ -174,4 +174,13 @@ - */ - #define MEDIA_BUS_FMT_METADATA_FIXED 0x7001 - -+/* Generic line based metadata formats for serial buses. Next is 0x8008. */ -+#define MEDIA_BUS_FMT_META_8 0x8001 -+#define MEDIA_BUS_FMT_META_10 0x8002 -+#define MEDIA_BUS_FMT_META_12 0x8003 -+#define MEDIA_BUS_FMT_META_14 0x8004 -+#define MEDIA_BUS_FMT_META_16 0x8005 -+#define MEDIA_BUS_FMT_META_20 0x8006 -+#define MEDIA_BUS_FMT_META_24 0x8007 -+ - #endif /* __LINUX_MEDIA_BUS_FORMAT_H */ --- -2.43.2 - - -From 8af4eeaee34159605ec86b57fa638a82fd968f31 Mon Sep 17 00:00:00 2001 -From: Sakari Ailus <sakari.ailus@linux.intel.com> -Date: Tue, 8 Aug 2023 10:55:33 +0300 -Subject: [PATCH 03/33] media: uapi: Document which mbus format fields are - valid for metadata - -Now that metadata mbus formats have been added, it is necessary to define -which fields in struct v4l2_mbus_format are applicable to them (not many). - -Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> ---- - include/uapi/linux/v4l2-mediabus.h | 18 ++++++++++++------ - 1 file changed, 12 insertions(+), 6 deletions(-) - -diff --git a/include/uapi/linux/v4l2-mediabus.h b/include/uapi/linux/v4l2-mediabus.h -index 6b07b73473b5..3cadb3b58b85 100644 ---- a/include/uapi/linux/v4l2-mediabus.h -+++ b/include/uapi/linux/v4l2-mediabus.h -@@ -19,12 +19,18 @@ - * @width: image width - * @height: image height - * @code: data format code (from enum v4l2_mbus_pixelcode) -- * @field: used interlacing type (from enum v4l2_field) -- * @colorspace: colorspace of the data (from enum v4l2_colorspace) -- * @ycbcr_enc: YCbCr encoding of the data (from enum v4l2_ycbcr_encoding) -- * @hsv_enc: HSV encoding of the data (from enum v4l2_hsv_encoding) -- * @quantization: quantization of the data (from enum v4l2_quantization) -- * @xfer_func: transfer function of the data (from enum v4l2_xfer_func) -+ * @field: used interlacing type (from enum v4l2_field), not applicable -+ * to metadata mbus codes -+ * @colorspace: colorspace of the data (from enum v4l2_colorspace), zero on -+ * metadata mbus codes -+ * @ycbcr_enc: YCbCr encoding of the data (from enum v4l2_ycbcr_encoding), zero -+ * on metadata mbus codes -+ * @hsv_enc: HSV encoding of the data (from enum v4l2_hsv_encoding), zero on -+ * metadata mbus codes -+ * @quantization: quantization of the data (from enum v4l2_quantization), zero -+ * on metadata mbus codes -+ * @xfer_func: transfer function of the data (from enum v4l2_xfer_func), zero -+ * on metadata mbus codes - * @flags: flags (V4L2_MBUS_FRAMEFMT_*) - * @reserved: reserved bytes that can be later used - */ --- -2.43.2 - - -From ed5884d40def9adfa77841427e52733746158a77 Mon Sep 17 00:00:00 2001 -From: Sakari Ailus <sakari.ailus@linux.intel.com> -Date: Tue, 8 Aug 2023 10:55:34 +0300 -Subject: [PATCH 04/33] media: uapi: Add a macro to tell whether an mbus code - is metadata - -Add a macro to tell whether a given mbus code is metadata. - -Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> ---- - include/uapi/linux/media-bus-format.h | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h -index d4c1d991014b..6fcd7d276bc6 100644 ---- a/include/uapi/linux/media-bus-format.h -+++ b/include/uapi/linux/media-bus-format.h -@@ -183,4 +183,7 @@ - #define MEDIA_BUS_FMT_META_20 0x8006 - #define MEDIA_BUS_FMT_META_24 0x8007 - -+#define MEDIA_BUS_FMT_IS_META(code) \ -+ ((code) & 0xf000 == 0x7000 || (code) & 0xf000 == 0x8000) -+ - #endif /* __LINUX_MEDIA_BUS_FORMAT_H */ --- -2.43.2 - - -From c0e682a815c5baf012c8963968385c197e7e0943 Mon Sep 17 00:00:00 2001 -From: Sakari Ailus <sakari.ailus@linux.intel.com> -Date: Tue, 8 Aug 2023 10:55:35 +0300 -Subject: [PATCH 05/33] media: uapi: Add generic 8-bit metadata format - definitions - -Generic 8-bit metadata formats define the in-memory data layout but not -the format of the data itself. The reasoning for having such formats is to -allow CSI-2 receiver drivers to receive and DMA drivers to write the data -to memory without knowing a large number of device specific formats. - -These formats may be used only in conjunction of a Media controller -pipeline where the internal pad of the source sub-device defines the -specific format of the data (using an mbus code). - -Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> ---- - .../userspace-api/media/v4l/meta-formats.rst | 1 + - .../media/v4l/metafmt-generic.rst | 331 ++++++++++++++++++ - drivers/media/v4l2-core/v4l2-ioctl.c | 8 + - include/uapi/linux/videodev2.h | 9 + - 4 files changed, 349 insertions(+) - create mode 100644 Documentation/userspace-api/media/v4l/metafmt-generic.rst - -diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst b/Documentation/userspace-api/media/v4l/meta-formats.rst -index 0bb61fc5bc00..919f595576b9 100644 ---- a/Documentation/userspace-api/media/v4l/meta-formats.rst -+++ b/Documentation/userspace-api/media/v4l/meta-formats.rst -@@ -19,3 +19,4 @@ These formats are used for the :ref:`metadata` interface only. - metafmt-vsp1-hgo - metafmt-vsp1-hgt - metafmt-vivid -+ metafmt-generic -diff --git a/Documentation/userspace-api/media/v4l/metafmt-generic.rst b/Documentation/userspace-api/media/v4l/metafmt-generic.rst -new file mode 100644 -index 000000000000..a27bfc721edf ---- /dev/null -+++ b/Documentation/userspace-api/media/v4l/metafmt-generic.rst -@@ -0,0 +1,331 @@ -+.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later -+ -+************************************************************************************************************************************************************************************************************************************************************************************************************************** -+V4L2_META_FMT_GENERIC_8 ('MET8'), V4L2_META_FMT_GENERIC_CSI2_10 ('MC1A'), V4L2_META_FMT_GENERIC_CSI2_12 ('MC1C'), V4L2_META_FMT_GENERIC_CSI2_14 ('MC1E'), V4L2_META_FMT_GENERIC_CSI2_16 ('MC1G'), V4L2_META_FMT_GENERIC_CSI2_20 ('MC1K'), V4L2_META_FMT_GENERIC_CSI2_24 ('MC1O'), V4L2_META_FMT_GENERIC_CSI2_2_24 ('MC2O') -+************************************************************************************************************************************************************************************************************************************************************************************************************************** -+ -+ -+Generic line-based metadata formats -+ -+ -+Description -+=========== -+ -+These generic line-based metadata formats define the memory layout of the data -+without defining the format or meaning of the metadata itself. These formats may -+only be used with a Media controller pipeline where the more specific format is -+defined in an :ref:`internal source pad <MEDIA-PAD-FL-INTERNAL>` of the source -+sub-device. See also :ref:`source routes <v4l2-subdev-source-routes>`. -+ -+.. _v4l2-meta-fmt-generic-8: -+ -+V4L2_META_FMT_GENERIC_8 -+----------------------- -+ -+The V4L2_META_FMT_GENERIC_8 format is a plain 8-bit metadata format. -+ -+This format is also used on CSI-2 on both 8 bits per sample as well as on -+16 bits per sample when two bytes of metadata are packed into one sample. -+ -+**Byte Order Of V4L2_META_FMT_GENERIC_8.** -+Each cell is one byte. "M" denotes a byte of metadata. -+ -+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}| -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 12 8 8 8 8 -+ -+ * - start + 0: -+ - M\ :sub:`00` -+ - M\ :sub:`10` -+ - M\ :sub:`20` -+ - M\ :sub:`30` -+ * - start + 4: -+ - M\ :sub:`01` -+ - M\ :sub:`11` -+ - M\ :sub:`21` -+ - M\ :sub:`31` -+ -+.. _v4l2-meta-fmt-generic-csi2-10: -+ -+V4L2_META_FMT_GENERIC_CSI2_10 -+----------------------------- -+ -+V4L2_META_FMT_GENERIC_CSI2_10 contains packed 8-bit generic metadata, 10 bits -+for each 8 bits of data. Every four bytes of metadata is followed by a single -+byte of padding. The way the data is stored follows the CSI-2 specification. -+ -+This format is also used on CSI-2 on 20 bits per sample format that packs two -+bytes of metadata into one sample. -+ -+This format is little endian. -+ -+**Byte Order Of V4L2_META_FMT_GENERIC_CSI2_10.** -+Each cell is one byte. "M" denotes a byte of metadata and "p" a byte of padding. -+ -+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{.8cm}| -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 12 8 8 8 8 8 -+ -+ * - start + 0: -+ - M\ :sub:`00` -+ - M\ :sub:`10` -+ - M\ :sub:`20` -+ - M\ :sub:`30` -+ - p -+ * - start + 5: -+ - M\ :sub:`01` -+ - M\ :sub:`11` -+ - M\ :sub:`21` -+ - M\ :sub:`31` -+ - p -+ -+.. _v4l2-meta-fmt-generic-csi2-12: -+ -+V4L2_META_FMT_GENERIC_CSI2_12 -+----------------------------- -+ -+V4L2_META_FMT_GENERIC_CSI2_12 contains packed 8-bit generic metadata, 12 bits -+for each 8 bits of data. Every four bytes of metadata is followed by two bytes -+of padding. The way the data is stored follows the CSI-2 specification. -+ -+This format is little endian. -+ -+**Byte Order Of V4L2_META_FMT_GENERIC_CSI2_12.** -+Each cell is one byte. "M" denotes a byte of metadata and "p" a byte of padding. -+ -+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{.8cm}|p{.8cm}| -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 12 8 8 8 8 8 8 -+ -+ * - start + 0: -+ - M\ :sub:`00` -+ - M\ :sub:`10` -+ - M\ :sub:`20` -+ - M\ :sub:`30` -+ - p -+ - p -+ * - start + 6: -+ - M\ :sub:`01` -+ - M\ :sub:`11` -+ - M\ :sub:`21` -+ - M\ :sub:`31` -+ - p -+ - p -+ -+.. _v4l2-meta-fmt-generic-csi2-14: -+ -+V4L2_META_FMT_GENERIC_CSI2_14 -+----------------------------- -+ -+V4L2_META_FMT_GENERIC_CSI2_14 contains packed 8-bit generic metadata, 14 bits -+for each 8 bits of data. Every four bytes of metadata is followed by three -+bytes of padding. The way the data is stored follows the CSI-2 specification. -+ -+This format is little endian. -+ -+**Byte Order Of V4L2_META_FMT_GENERIC_CSI2_14.** -+Each cell is one byte. "M" denotes a byte of metadata and "p" a byte of padding. -+ -+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{.8cm}|p{.8cm}|p{.8cm}| -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 12 8 8 8 8 8 8 8 -+ -+ * - start + 0: -+ - M\ :sub:`00` -+ - M\ :sub:`10` -+ - M\ :sub:`20` -+ - M\ :sub:`30` -+ - p -+ - p -+ - p -+ * - start + 7: -+ - M\ :sub:`01` -+ - M\ :sub:`11` -+ - M\ :sub:`21` -+ - M\ :sub:`31` -+ - p -+ - p -+ - p -+ -+.. _v4l2-meta-fmt-generic-csi2-16: -+ -+V4L2_META_FMT_GENERIC_CSI2_16 -+----------------------------- -+ -+V4L2_META_FMT_GENERIC_CSI2_16 contains packed 8-bit generic metadata, 16 bits -+for each 8 bits of data. Every byte of metadata is followed by one byte of -+padding. The way the data is stored follows the CSI-2 specification. -+ -+This format is little endian. -+ -+**Byte Order Of V4L2_META_FMT_GENERIC_CSI2_16.** -+Each cell is one byte. "M" denotes a byte of metadata and "p" a byte of padding. -+ -+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{1.2cm}|p{.8cm}| -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 12 8 8 8 8 8 8 8 8 -+ -+ * - start + 0: -+ - M\ :sub:`00` -+ - p -+ - M\ :sub:`10` -+ - p -+ - M\ :sub:`20` -+ - p -+ - M\ :sub:`30` -+ - p -+ * - start + 8: -+ - M\ :sub:`01` -+ - p -+ - M\ :sub:`11` -+ - p -+ - M\ :sub:`21` -+ - p -+ - M\ :sub:`31` -+ - p -+ -+.. _v4l2-meta-fmt-generic-csi2-20: -+ -+V4L2_META_FMT_GENERIC_CSI2_20 -+----------------------------- -+ -+V4L2_META_FMT_GENERIC_CSI2_20 contains packed 8-bit generic metadata, 20 bits -+for each 8 bits of data. Every byte of metadata is followed by alternating one -+and two bytes of padding. The way the data is stored follows the CSI-2 -+specification. -+ -+This format is little endian. -+ -+**Byte Order Of V4L2_META_FMT_GENERIC_CSI2_20.** -+Each cell is one byte. "M" denotes a byte of metadata and "p" a byte of padding. -+ -+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{.8cm}| -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 12 8 8 8 8 8 8 8 8 8 8 -+ -+ * - start + 0: -+ - M\ :sub:`00` -+ - p -+ - M\ :sub:`10` -+ - p -+ - p -+ - M\ :sub:`20` -+ - p -+ - M\ :sub:`30` -+ - p -+ - p -+ * - start + 10: -+ - M\ :sub:`01` -+ - p -+ - M\ :sub:`11` -+ - p -+ - p -+ - M\ :sub:`21` -+ - p -+ - M\ :sub:`31` -+ - p -+ - p -+ -+.. _v4l2-meta-fmt-generic-csi2-24: -+ -+V4L2_META_FMT_GENERIC_CSI2_24 -+----------------------------- -+ -+V4L2_META_FMT_GENERIC_CSI2_24 contains packed 8-bit generic metadata, 24 bits -+for each 8 bits of data. Every byte of metadata is followed by two bytes of -+padding. The way the data is stored follows the CSI-2 specification. -+ -+This format is little endian. -+ -+**Byte Order Of V4L2_META_FMT_GENERIC_CSI2_24.** -+Each cell is one byte. "M" denotes a byte of metadata and "p" a byte of padding. -+ -+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{.8cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{.8cm}|p{1.2cm}|p{.8cm}|p{.8cm}| -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 12 8 8 8 8 8 8 8 8 8 8 8 8 -+ -+ * - start + 0: -+ - M\ :sub:`00` -+ - p -+ - p -+ - M\ :sub:`10` -+ - p -+ - p -+ - M\ :sub:`20` -+ - p -+ - p -+ - M\ :sub:`30` -+ - p -+ - p -+ * - start + 12: -+ - M\ :sub:`01` -+ - p -+ - p -+ - M\ :sub:`11` -+ - p -+ - p -+ - M\ :sub:`21` -+ - p -+ - p -+ - M\ :sub:`31` -+ - p -+ - p -+ -+.. _v4l2-meta-fmt-generic-csi2-2-24: -+ -+V4L2_META_FMT_GENERIC_CSI2_2_24 -+------------------------------- -+ -+V4L2_META_FMT_GENERIC_CSI2_2_24 contains packed 8-bit generic metadata, 24 bits -+for each two times 8 bits of data. Every two bytes of metadata are followed by -+one byte of padding. The way the data is stored follows the CSI-2 -+specification. -+ -+This format is little endian. -+ -+**Byte Order Of V4L2_META_FMT_GENERIC_CSI2_2_24.** -+Each cell is one byte. "M" denotes a byte of metadata and "p" a byte of padding. -+ -+.. tabularcolumns:: |p{2.4cm}|p{1.2cm}|p{1.2cm}|p{.8cm}|p{1.2cm}|p{1.2cm}|p{.8cm}| -+ -+.. flat-table:: -+ :header-rows: 0 -+ :stub-columns: 0 -+ :widths: 12 8 8 8 8 8 8 -+ -+ * - start + 0: -+ - M\ :sub:`00` -+ - M\ :sub:`10` -+ - p -+ - M\ :sub:`20` -+ - M\ :sub:`30` -+ - p -+ * - start + 6: -+ - M\ :sub:`01` -+ - M\ :sub:`11` -+ - p -+ - M\ :sub:`21` -+ - M\ :sub:`31` -+ - p -+ -diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c -index 33076af4dfdb..4eb3db1773e1 100644 ---- a/drivers/media/v4l2-core/v4l2-ioctl.c -+++ b/drivers/media/v4l2-core/v4l2-ioctl.c -@@ -1452,6 +1452,14 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) - case V4L2_PIX_FMT_Y210: descr = "10-bit YUYV Packed"; break; - case V4L2_PIX_FMT_Y212: descr = "12-bit YUYV Packed"; break; - case V4L2_PIX_FMT_Y216: descr = "16-bit YUYV Packed"; break; -+ case V4L2_META_FMT_GENERIC_8: descr = "8-bit Generic Metadata"; break; -+ case V4L2_META_FMT_GENERIC_CSI2_10: descr = "8b Generic Meta, 10b CSI-2"; break; -+ case V4L2_META_FMT_GENERIC_CSI2_12: descr = "8b Generic Meta, 12b CSI-2"; break; -+ case V4L2_META_FMT_GENERIC_CSI2_14: descr = "8b Generic Meta, 14b CSI-2"; break; -+ case V4L2_META_FMT_GENERIC_CSI2_16: descr = "8b Generic Meta, 16b CSI-2"; break; -+ case V4L2_META_FMT_GENERIC_CSI2_20: descr = "8b Generic Meta, 20b CSI-2"; break; -+ case V4L2_META_FMT_GENERIC_CSI2_24: descr = "8b Generic Meta, 24b CSI-2"; break; -+ case V4L2_META_FMT_GENERIC_CSI2_2_24: descr = "2x8b Generic Meta, 24b CSI-2"; break; - - default: - /* Compressed formats */ -diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h -index 68e7ac178cc2..2c4e03d47789 100644 ---- a/include/uapi/linux/videodev2.h -+++ b/include/uapi/linux/videodev2.h -@@ -839,6 +839,15 @@ struct v4l2_pix_format { - #define V4L2_META_FMT_RK_ISP1_PARAMS v4l2_fourcc('R', 'K', '1', 'P') /* Rockchip ISP1 3A Parameters */ - #define V4L2_META_FMT_RK_ISP1_STAT_3A v4l2_fourcc('R', 'K', '1', 'S') /* Rockchip ISP1 3A Statistics */ - -+#define V4L2_META_FMT_GENERIC_8 v4l2_fourcc('M', 'E', 'T', '8') /* Generic 8-bit metadata */ -+#define V4L2_META_FMT_GENERIC_CSI2_10 v4l2_fourcc('M', 'C', '1', 'A') /* 10-bit CSI-2 packed 8-bit metadata */ -+#define V4L2_META_FMT_GENERIC_CSI2_12 v4l2_fourcc('M', 'C', '1', 'C') /* 12-bit CSI-2 packed 8-bit metadata */ -+#define V4L2_META_FMT_GENERIC_CSI2_14 v4l2_fourcc('M', 'C', '1', 'E') /* 14-bit CSI-2 packed 8-bit metadata */ -+#define V4L2_META_FMT_GENERIC_CSI2_16 v4l2_fourcc('M', 'C', '1', 'G') /* 16-bit CSI-2 packed 8-bit metadata */ -+#define V4L2_META_FMT_GENERIC_CSI2_20 v4l2_fourcc('M', 'C', '1', 'K') /* 20-bit CSI-2 packed 8-bit metadata */ -+#define V4L2_META_FMT_GENERIC_CSI2_24 v4l2_fourcc('M', 'C', '1', 'O') /* 24-bit CSI-2 packed 8-bit metadata */ -+#define V4L2_META_FMT_GENERIC_CSI2_2_24 v4l2_fourcc('M', 'C', '2', 'O') /* 2 bytes of 8-bit metadata, 24-bit CSI-2 packed */ -+ - /* priv field value to indicates that subsequent fields are valid. */ - #define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe - --- -2.43.2 - - -From 453627c23062ff0aa01e0e46e3b7922ddf82f998 Mon Sep 17 00:00:00 2001 -From: Sakari Ailus <sakari.ailus@linux.intel.com> -Date: Tue, 8 Aug 2023 10:55:36 +0300 -Subject: [PATCH 06/33] media: v4l: Support line-based metadata capture - -many camera sensors, among other devices, transmit embedded data and image -data for each CSI-2 frame. This embedded data typically contains register -configuration of the sensor that has been used to capture the image data -of the same frame. - -The embedded data is received by the CSI-2 receiver and has the same -properties as the image data, including that it is line based: it has -width, height and bytesperline (stride). - -Add these fields to struct v4l2_meta_format and document them. - -Also add V4L2_FMT_FLAG_META_LINE_BASED to tell a given format is -line-based i.e. these fields of struct v4l2_meta_format are valid for it. - -Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> ---- - .../userspace-api/media/v4l/dev-meta.rst | 15 +++++++++++++++ - .../userspace-api/media/v4l/vidioc-enum-fmt.rst | 7 +++++++ - .../media/videodev2.h.rst.exceptions | 1 + - drivers/media/v4l2-core/v4l2-ioctl.c | 5 +++-- - include/uapi/linux/videodev2.h | 10 ++++++++++ - 5 files changed, 36 insertions(+), 2 deletions(-) - -diff --git a/Documentation/userspace-api/media/v4l/dev-meta.rst b/Documentation/userspace-api/media/v4l/dev-meta.rst -index 0e7e1ee1471a..4b24bae6e171 100644 ---- a/Documentation/userspace-api/media/v4l/dev-meta.rst -+++ b/Documentation/userspace-api/media/v4l/dev-meta.rst -@@ -65,3 +65,18 @@ to 0. - - ``buffersize`` - - Maximum buffer size in bytes required for data. The value is set by the - driver. -+ * - __u32 -+ - ``width`` -+ - Width of a line of metadata in samples. Valid when :c:type`v4l2_fmtdesc` -+ flag ``V4L2_FMT_FLAG_META_LINE_BASED`` is set, otherwise zero. See -+ :c:func:`VIDIOC_ENUM_FMT`. -+ * - __u32 -+ - ``height`` -+ - Number of rows of metadata. Valid when :c:type`v4l2_fmtdesc` flag -+ ``V4L2_FMT_FLAG_META_LINE_BASED`` is set, otherwise zero. See -+ :c:func:`VIDIOC_ENUM_FMT`. -+ * - __u32 -+ - ``bytesperline`` -+ - Offset in bytes between the beginning of two consecutive lines. Valid -+ when :c:type`v4l2_fmtdesc` flag ``V4L2_FMT_FLAG_META_LINE_BASED`` is -+ set, otherwise zero. See :c:func:`VIDIOC_ENUM_FMT`. -diff --git a/Documentation/userspace-api/media/v4l/vidioc-enum-fmt.rst b/Documentation/userspace-api/media/v4l/vidioc-enum-fmt.rst -index 000c154b0f98..6d7664345a4e 100644 ---- a/Documentation/userspace-api/media/v4l/vidioc-enum-fmt.rst -+++ b/Documentation/userspace-api/media/v4l/vidioc-enum-fmt.rst -@@ -227,6 +227,13 @@ the ``mbus_code`` field is handled differently: - The application can ask to configure the quantization of the capture - device when calling the :ref:`VIDIOC_S_FMT <VIDIOC_G_FMT>` ioctl with - :ref:`V4L2_PIX_FMT_FLAG_SET_CSC <v4l2-pix-fmt-flag-set-csc>` set. -+ * - ``V4L2_FMT_FLAG_META_LINE_BASED`` -+ - 0x0200 -+ - The metadata format is line-based. In this case the ``width``, -+ ``height`` and ``bytesperline`` fields of :c:type:`v4l2_meta_format` are -+ valid. The buffer consists of ``height`` lines, each having ``width`` -+ bytes of data and offset between the beginning of each two consecutive -+ lines is ``bytesperline``. - - Return Value - ============ -diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions -index 3e58aac4ef0b..bdc628e8c1d6 100644 ---- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions -+++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions -@@ -215,6 +215,7 @@ replace define V4L2_FMT_FLAG_CSC_XFER_FUNC fmtdesc-flags - replace define V4L2_FMT_FLAG_CSC_YCBCR_ENC fmtdesc-flags - replace define V4L2_FMT_FLAG_CSC_HSV_ENC fmtdesc-flags - replace define V4L2_FMT_FLAG_CSC_QUANTIZATION fmtdesc-flags -+replace define V4L2_FMT_FLAG_META_LINE_BASED fmtdesc-flags - - # V4L2 timecode types - replace define V4L2_TC_TYPE_24FPS timecode-type -diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c -index 4eb3db1773e1..1fcec1515bcc 100644 ---- a/drivers/media/v4l2-core/v4l2-ioctl.c -+++ b/drivers/media/v4l2-core/v4l2-ioctl.c -@@ -343,8 +343,9 @@ static void v4l_print_format(const void *arg, bool write_only) - case V4L2_BUF_TYPE_META_OUTPUT: - meta = &p->fmt.meta; - pixelformat = meta->dataformat; -- pr_cont(", dataformat=%p4cc, buffersize=%u\n", -- &pixelformat, meta->buffersize); -+ pr_cont(", dataformat=%p4cc, buffersize=%u, width=%u, height=%u, bytesperline=%u\n", -+ &pixelformat, meta->buffersize, meta->width, -+ meta->height, meta->bytesperline); - break; - } - } -diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h -index 2c4e03d47789..48fb44772098 100644 ---- a/include/uapi/linux/videodev2.h -+++ b/include/uapi/linux/videodev2.h -@@ -878,6 +878,7 @@ struct v4l2_fmtdesc { - #define V4L2_FMT_FLAG_CSC_YCBCR_ENC 0x0080 - #define V4L2_FMT_FLAG_CSC_HSV_ENC V4L2_FMT_FLAG_CSC_YCBCR_ENC - #define V4L2_FMT_FLAG_CSC_QUANTIZATION 0x0100 -+#define V4L2_FMT_FLAG_META_LINE_BASED 0x0200 - - /* Frame Size and frame rate enumeration */ - /* -@@ -2424,10 +2425,19 @@ struct v4l2_sdr_format { - * struct v4l2_meta_format - metadata format definition - * @dataformat: little endian four character code (fourcc) - * @buffersize: maximum size in bytes required for data -+ * @width: number of bytes of data per line (valid for line based -+ * formats only, see format documentation) -+ * @height: number of lines of data per buffer (valid for line based -+ * formats only) -+ * @bytesperline: offset between the beginnings of two adjacent lines in -+ * bytes (valid for line based formats only) - */ - struct v4l2_meta_format { - __u32 dataformat; - __u32 buffersize; -+ __u32 width; -+ __u32 height; -+ __u32 bytesperline; - } __attribute__ ((packed)); - - /** --- -2.43.2 - - -From 090bb3894bda739ff06e8a431815210b731056b7 Mon Sep 17 00:00:00 2001 -From: Sakari Ailus <sakari.ailus@linux.intel.com> -Date: Tue, 8 Aug 2023 10:55:37 +0300 -Subject: [PATCH 07/33] media: Add media bus codes for MIPI CCS embedded data - -Add new MIPI CCS embedded data media bus formats. - -Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> ---- - .../media/v4l/subdev-formats.rst | 32 +++++++++++++++++++ - include/uapi/linux/media-bus-format.h | 10 +++++- - 2 files changed, 41 insertions(+), 1 deletion(-) - -diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst -index 7d107873cddd..7afb057a09c5 100644 ---- a/Documentation/userspace-api/media/v4l/subdev-formats.rst -+++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst -@@ -8563,3 +8563,35 @@ and finally the bit number in subscript. "p" indicates a padding bit. - - p - - p - - p -+ -+MIPI CCS Embedded Data Formats -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+ -+`MIPI CCS <https://www.mipi.org/specifications/camera-command-set>`_ defines an -+metadata format for sensor embedded data, which is used to store the register -+configuration used for capturing a given frame. The format is defined in the CCS -+specification. -+ -+The bit depth of the CCS embedded data matches the pixel data bit depth -+configured on the sensor. The formats used and their corresponding generic -+formats are listed in the table below. -+ -+.. flat-table: CCS embedded data mbus formats and corresponding generic formats -+ :header-rows: 1 -+ -+ * - CCS embedded data mbus format -+ - Generic metadata format -+ * - MEDIA_BUS_FMT_CCS_EMBEDDED_8 -+ - MEDIA_BUS_FMT_META_8 -+ * - MEDIA_BUS_FMT_CCS_EMBEDDED_10 -+ - MEDIA_BUS_FMT_META_10 -+ * - MEDIA_BUS_FMT_CCS_EMBEDDED_12 -+ - MEDIA_BUS_FMT_META_12 -+ * - MEDIA_BUS_FMT_CCS_EMBEDDED_14 -+ - MEDIA_BUS_FMT_META_14 -+ * - MEDIA_BUS_FMT_CCS_EMBEDDED_16 -+ - MEDIA_BUS_FMT_META_16 -+ * - MEDIA_BUS_FMT_CCS_EMBEDDED_20 -+ - MEDIA_BUS_FMT_META_20 -+ * - MEDIA_BUS_FMT_CCS_EMBEDDED_24 -+ - MEDIA_BUS_FMT_META_24 -diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h -index 6fcd7d276bc6..d5014ef3c43a 100644 ---- a/include/uapi/linux/media-bus-format.h -+++ b/include/uapi/linux/media-bus-format.h -@@ -183,7 +183,15 @@ - #define MEDIA_BUS_FMT_META_20 0x8006 - #define MEDIA_BUS_FMT_META_24 0x8007 - -+/* Specific metadata formats. Next is 0x9008. */ -+#define MEDIA_BUS_FMT_CCS_EMBEDDED_8 0x9001 -+#define MEDIA_BUS_FMT_CCS_EMBEDDED_10 0x9002 -+#define MEDIA_BUS_FMT_CCS_EMBEDDED_12 0x9003 -+#define MEDIA_BUS_FMT_CCS_EMBEDDED_14 0x9004 -+#define MEDIA_BUS_FMT_CCS_EMBEDDED_16 0x9005 -+#define MEDIA_BUS_FMT_CCS_EMBEDDED_20 0x9006 -+#define MEDIA_BUS_FMT_CCS_EMBEDDED_24 0x9007 -+ - #define MEDIA_BUS_FMT_IS_META(code) \ - ((code) & 0xf000 == 0x7000 || (code) & 0xf000 == 0x8000) -- - #endif /* __LINUX_MEDIA_BUS_FORMAT_H */ --- -2.43.2 - - -From 44f8084f055969874d2216ba4e6e225046931e73 Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:15 +0800 -Subject: [PATCH 08/33] media: intel/ipu6: add Intel IPU6 PCI device driver - -Intel Image Processing Unit 6th Gen includes input and processing systems -but the hardware presents itself as a single PCI device in system. - -IPU6 PCI device driver basically does PCI configurations and load -the firmware binary, initialises IPU virtual bus, and sets up platform -specific variants to support multiple IPU6 devices in single device -driver. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - .../media/pci/intel/ipu6/ipu6-platform-regs.h | 179 ++++ - drivers/media/pci/intel/ipu6/ipu6.c | 966 ++++++++++++++++++ - drivers/media/pci/intel/ipu6/ipu6.h | 356 +++++++ - 3 files changed, 1501 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-platform-regs.h - create mode 100644 drivers/media/pci/intel/ipu6/ipu6.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6.h - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-platform-regs.h b/drivers/media/pci/intel/ipu6/ipu6-platform-regs.h -new file mode 100644 -index 000000000000..cae26009c9fc ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-platform-regs.h -@@ -0,0 +1,179 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2018 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_PLATFORM_REGS_H -+#define IPU6_PLATFORM_REGS_H -+ -+#include <linux/bits.h> -+ -+/* -+ * IPU6 uses uniform address within IPU6, therefore all subsystem registers -+ * locates in one single space starts from 0 but in different sctions with -+ * different addresses, the subsystem offsets are defined to 0 as the -+ * register definition will have the address offset to 0. -+ */ -+#define IPU6_UNIFIED_OFFSET 0 -+ -+#define IPU6_ISYS_IOMMU0_OFFSET 0x2e0000 -+#define IPU6_ISYS_IOMMU1_OFFSET 0x2e0500 -+#define IPU6_ISYS_IOMMUI_OFFSET 0x2e0a00 -+ -+#define IPU6_PSYS_IOMMU0_OFFSET 0x1b0000 -+#define IPU6_PSYS_IOMMU1_OFFSET 0x1b0700 -+#define IPU6_PSYS_IOMMU1R_OFFSET 0x1b0e00 -+#define IPU6_PSYS_IOMMUI_OFFSET 0x1b1500 -+ -+/* the offset from IOMMU base register */ -+#define IPU6_MMU_L1_STREAM_ID_REG_OFFSET 0x0c -+#define IPU6_MMU_L2_STREAM_ID_REG_OFFSET 0x4c -+#define IPU6_PSYS_MMU1W_L2_STREAM_ID_REG_OFFSET 0x8c -+ -+#define IPU6_MMU_INFO_OFFSET 0x8 -+ -+#define IPU6_ISYS_SPC_OFFSET 0x210000 -+ -+#define IPU6SE_PSYS_SPC_OFFSET 0x110000 -+#define IPU6_PSYS_SPC_OFFSET 0x118000 -+ -+#define IPU6_ISYS_DMEM_OFFSET 0x200000 -+#define IPU6_PSYS_DMEM_OFFSET 0x100000 -+ -+#define IPU6_REG_ISYS_UNISPART_IRQ_EDGE 0x27c000 -+#define IPU6_REG_ISYS_UNISPART_IRQ_MASK 0x27c004 -+#define IPU6_REG_ISYS_UNISPART_IRQ_STATUS 0x27c008 -+#define IPU6_REG_ISYS_UNISPART_IRQ_CLEAR 0x27c00c -+#define IPU6_REG_ISYS_UNISPART_IRQ_ENABLE 0x27c010 -+#define IPU6_REG_ISYS_UNISPART_IRQ_LEVEL_NOT_PULSE 0x27c014 -+#define IPU6_REG_ISYS_UNISPART_SW_IRQ_REG 0x27c414 -+#define IPU6_REG_ISYS_UNISPART_SW_IRQ_MUX_REG 0x27c418 -+#define IPU6_ISYS_UNISPART_IRQ_CSI0 BIT(2) -+#define IPU6_ISYS_UNISPART_IRQ_CSI1 BIT(3) -+#define IPU6_ISYS_UNISPART_IRQ_SW BIT(22) -+ -+#define IPU6_REG_ISYS_ISL_TOP_IRQ_EDGE 0x2b0200 -+#define IPU6_REG_ISYS_ISL_TOP_IRQ_MASK 0x2b0204 -+#define IPU6_REG_ISYS_ISL_TOP_IRQ_STATUS 0x2b0208 -+#define IPU6_REG_ISYS_ISL_TOP_IRQ_CLEAR 0x2b020c -+#define IPU6_REG_ISYS_ISL_TOP_IRQ_ENABLE 0x2b0210 -+#define IPU6_REG_ISYS_ISL_TOP_IRQ_LEVEL_NOT_PULSE 0x2b0214 -+ -+#define IPU6_REG_ISYS_CMPR_TOP_IRQ_EDGE 0x2d2100 -+#define IPU6_REG_ISYS_CMPR_TOP_IRQ_MASK 0x2d2104 -+#define IPU6_REG_ISYS_CMPR_TOP_IRQ_STATUS 0x2d2108 -+#define IPU6_REG_ISYS_CMPR_TOP_IRQ_CLEAR 0x2d210c -+#define IPU6_REG_ISYS_CMPR_TOP_IRQ_ENABLE 0x2d2110 -+#define IPU6_REG_ISYS_CMPR_TOP_IRQ_LEVEL_NOT_PULSE 0x2d2114 -+ -+/* CDC Burst collector thresholds for isys - 3 FIFOs i = 0..2 */ -+#define IPU6_REG_ISYS_CDC_THRESHOLD(i) (0x27c400 + ((i) * 4)) -+ -+#define IPU6_CSI_IRQ_NUM_PER_PIPE 4 -+#define IPU6SE_ISYS_CSI_PORT_NUM 4 -+#define IPU6_ISYS_CSI_PORT_NUM 8 -+ -+#define IPU6_ISYS_CSI_PORT_IRQ(irq_num) BIT(irq_num) -+ -+/* PKG DIR OFFSET in IMR in secure mode */ -+#define IPU6_PKG_DIR_IMR_OFFSET 0x40 -+ -+#define IPU6_ISYS_REG_SPC_STATUS_CTRL 0x0 -+ -+#define IPU6_ISYS_SPC_STATUS_START BIT(1) -+#define IPU6_ISYS_SPC_STATUS_RUN BIT(3) -+#define IPU6_ISYS_SPC_STATUS_READY BIT(5) -+#define IPU6_ISYS_SPC_STATUS_CTRL_ICACHE_INVALIDATE BIT(12) -+#define IPU6_ISYS_SPC_STATUS_ICACHE_PREFETCH BIT(13) -+ -+#define IPU6_PSYS_REG_SPC_STATUS_CTRL 0x0 -+#define IPU6_PSYS_REG_SPC_START_PC 0x4 -+#define IPU6_PSYS_REG_SPC_ICACHE_BASE 0x10 -+#define IPU6_REG_PSYS_INFO_SEG_0_CONFIG_ICACHE_MASTER 0x14 -+ -+#define IPU6_PSYS_SPC_STATUS_START BIT(1) -+#define IPU6_PSYS_SPC_STATUS_RUN BIT(3) -+#define IPU6_PSYS_SPC_STATUS_READY BIT(5) -+#define IPU6_PSYS_SPC_STATUS_CTRL_ICACHE_INVALIDATE BIT(12) -+#define IPU6_PSYS_SPC_STATUS_ICACHE_PREFETCH BIT(13) -+ -+#define IPU6_PSYS_REG_SPP0_STATUS_CTRL 0x20000 -+ -+#define IPU6_INFO_ENABLE_SNOOP BIT(0) -+#define IPU6_INFO_DEC_FORCE_FLUSH BIT(1) -+#define IPU6_INFO_DEC_PASS_THROUGH BIT(2) -+#define IPU6_INFO_ZLW BIT(3) -+#define IPU6_INFO_REQUEST_DESTINATION_IOSF BIT(9) -+#define IPU6_INFO_IMR_BASE BIT(10) -+#define IPU6_INFO_IMR_DESTINED BIT(11) -+ -+#define IPU6_INFO_REQUEST_DESTINATION_PRIMARY IPU6_INFO_REQUEST_DESTINATION_IOSF -+ -+/* -+ * s2m_pixel_soc_pixel_remapping is dedicated for the enabling of the -+ * pixel s2m remp ability.Remap here means that s2m rearange the order -+ * of the pixels in each 4 pixels group. -+ * For examle, mirroring remping means that if input's 4 first pixels -+ * are 1 2 3 4 then in output we should see 4 3 2 1 in this 4 first pixels. -+ * 0xE4 is from s2m MAS document. It means no remapping. -+ */ -+#define S2M_PIXEL_SOC_PIXEL_REMAPPING_FLAG_NO_REMAPPING 0xe4 -+/* -+ * csi_be_soc_pixel_remapping is for the enabling of the pixel remapping. -+ * This remapping is exactly like the stream2mmio remapping. -+ */ -+#define CSI_BE_SOC_PIXEL_REMAPPING_FLAG_NO_REMAPPING 0xe4 -+ -+#define IPU6_REG_DMA_TOP_AB_GROUP1_BASE_ADDR 0x1ae000 -+#define IPU6_REG_DMA_TOP_AB_GROUP2_BASE_ADDR 0x1af000 -+#define IPU6_REG_DMA_TOP_AB_RING_MIN_OFFSET(n) (0x4 + (n) * 0xc) -+#define IPU6_REG_DMA_TOP_AB_RING_MAX_OFFSET(n) (0x8 + (n) * 0xc) -+#define IPU6_REG_DMA_TOP_AB_RING_ACCESS_OFFSET(n) (0xc + (n) * 0xc) -+ -+enum ipu6_device_ab_group1_target_id { -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R0_SPC_DMEM, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R1_SPC_DMEM, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R2_SPC_DMEM, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R3_SPC_STATUS_REG, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R4_SPC_MASTER_BASE_ADDR, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R5_SPC_PC_STALL, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R6_SPC_EQ, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R7_SPC_RESERVED, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R8_SPC_RESERVED, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R9_SPP0, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R10_SPP1, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R11_CENTRAL_R1, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R12_IRQ, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R13_CENTRAL_R2, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R14_DMA, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R15_DMA, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R16_GP, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R17_ZLW_INSERTER, -+ IPU6_DEVICE_AB_GROUP1_TARGET_ID_R18_AB, -+}; -+ -+enum nci_ab_access_mode { -+ NCI_AB_ACCESS_MODE_RW, /* read & write */ -+ NCI_AB_ACCESS_MODE_RO, /* read only */ -+ NCI_AB_ACCESS_MODE_WO, /* write only */ -+ NCI_AB_ACCESS_MODE_NA, /* No access at all */ -+}; -+ -+/* IRQ-related registers in PSYS */ -+#define IPU6_REG_PSYS_GPDEV_IRQ_EDGE 0x1aa200 -+#define IPU6_REG_PSYS_GPDEV_IRQ_MASK 0x1aa204 -+#define IPU6_REG_PSYS_GPDEV_IRQ_STATUS 0x1aa208 -+#define IPU6_REG_PSYS_GPDEV_IRQ_CLEAR 0x1aa20c -+#define IPU6_REG_PSYS_GPDEV_IRQ_ENABLE 0x1aa210 -+#define IPU6_REG_PSYS_GPDEV_IRQ_LEVEL_NOT_PULSE 0x1aa214 -+/* There are 8 FW interrupts, n = 0..7 */ -+#define IPU6_PSYS_GPDEV_FWIRQ0 5 -+#define IPU6_PSYS_GPDEV_FWIRQ1 6 -+#define IPU6_PSYS_GPDEV_FWIRQ2 7 -+#define IPU6_PSYS_GPDEV_FWIRQ3 8 -+#define IPU6_PSYS_GPDEV_FWIRQ4 9 -+#define IPU6_PSYS_GPDEV_FWIRQ5 10 -+#define IPU6_PSYS_GPDEV_FWIRQ6 11 -+#define IPU6_PSYS_GPDEV_FWIRQ7 12 -+#define IPU6_PSYS_GPDEV_IRQ_FWIRQ(n) BIT(n) -+#define IPU6_REG_PSYS_GPDEV_FWIRQ(n) (4 * (n) + 0x1aa100) -+ -+#endif /* IPU6_PLATFORM_REGS_H */ -diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c -new file mode 100644 -index 000000000000..abd40a783729 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6.c -@@ -0,0 +1,966 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/bitfield.h> -+#include <linux/bits.h> -+#include <linux/dma-mapping.h> -+#include <linux/err.h> -+#include <linux/firmware.h> -+#include <linux/kernel.h> -+#include <linux/interrupt.h> -+#include <linux/io.h> -+#include <linux/list.h> -+#include <linux/module.h> -+#include <linux/pci-ats.h> -+#include <linux/pm_runtime.h> -+#include <linux/property.h> -+#include <linux/scatterlist.h> -+#include <linux/slab.h> -+#include <linux/types.h> -+ -+#include <media/ipu-bridge.h> -+ -+#include "ipu6.h" -+#include "ipu6-bus.h" -+#include "ipu6-buttress.h" -+#include "ipu6-cpd.h" -+#include "ipu6-isys.h" -+#include "ipu6-mmu.h" -+#include "ipu6-platform-buttress-regs.h" -+#include "ipu6-platform-isys-csi2-reg.h" -+#include "ipu6-platform-regs.h" -+ -+#define IPU6_PCI_BAR 0 -+ -+struct ipu6_cell_program { -+ u32 magic_number; -+ -+ u32 blob_offset; -+ u32 blob_size; -+ -+ u32 start[3]; -+ -+ u32 icache_source; -+ u32 icache_target; -+ u32 icache_size; -+ -+ u32 pmem_source; -+ u32 pmem_target; -+ u32 pmem_size; -+ -+ u32 data_source; -+ u32 data_target; -+ u32 data_size; -+ -+ u32 bss_target; -+ u32 bss_size; -+ -+ u32 cell_id; -+ u32 regs_addr; -+ -+ u32 cell_pmem_data_bus_address; -+ u32 cell_dmem_data_bus_address; -+ u32 cell_pmem_control_bus_address; -+ u32 cell_dmem_control_bus_address; -+ -+ u32 next; -+ u32 dummy[2]; -+}; -+ -+static u32 ipu6se_csi_offsets[] = { -+ IPU6_CSI_PORT_A_ADDR_OFFSET, -+ IPU6_CSI_PORT_B_ADDR_OFFSET, -+ IPU6_CSI_PORT_C_ADDR_OFFSET, -+ IPU6_CSI_PORT_D_ADDR_OFFSET -+}; -+ -+/* -+ * IPU6 on TGL support maximum 8 csi2 ports -+ * IPU6SE on JSL and IPU6EP on ADL support maximum 4 csi2 ports -+ * IPU6EP on MTL support maximum 6 csi2 ports -+ */ -+static u32 ipu6_tgl_csi_offsets[] = { -+ IPU6_CSI_PORT_A_ADDR_OFFSET, -+ IPU6_CSI_PORT_B_ADDR_OFFSET, -+ IPU6_CSI_PORT_C_ADDR_OFFSET, -+ IPU6_CSI_PORT_D_ADDR_OFFSET, -+ IPU6_CSI_PORT_E_ADDR_OFFSET, -+ IPU6_CSI_PORT_F_ADDR_OFFSET, -+ IPU6_CSI_PORT_G_ADDR_OFFSET, -+ IPU6_CSI_PORT_H_ADDR_OFFSET -+}; -+ -+static u32 ipu6ep_mtl_csi_offsets[] = { -+ IPU6_CSI_PORT_A_ADDR_OFFSET, -+ IPU6_CSI_PORT_B_ADDR_OFFSET, -+ IPU6_CSI_PORT_C_ADDR_OFFSET, -+ IPU6_CSI_PORT_D_ADDR_OFFSET, -+ IPU6_CSI_PORT_E_ADDR_OFFSET, -+ IPU6_CSI_PORT_F_ADDR_OFFSET -+}; -+ -+static u32 ipu6_csi_offsets[] = { -+ IPU6_CSI_PORT_A_ADDR_OFFSET, -+ IPU6_CSI_PORT_B_ADDR_OFFSET, -+ IPU6_CSI_PORT_C_ADDR_OFFSET, -+ IPU6_CSI_PORT_D_ADDR_OFFSET -+}; -+ -+static struct ipu6_isys_internal_pdata isys_ipdata = { -+ .hw_variant = { -+ .offset = IPU6_UNIFIED_OFFSET, -+ .nr_mmus = 3, -+ .mmu_hw = { -+ { -+ .offset = IPU6_ISYS_IOMMU0_OFFSET, -+ .info_bits = IPU6_INFO_REQUEST_DESTINATION_IOSF, -+ .nr_l1streams = 16, -+ .l1_block_sz = { -+ 3, 8, 2, 2, 2, 2, 2, 2, 1, 1, -+ 1, 1, 1, 1, 1, 1 -+ }, -+ .nr_l2streams = 16, -+ .l2_block_sz = { -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2 -+ }, -+ .insert_read_before_invalidate = false, -+ .l1_stream_id_reg_offset = -+ IPU6_MMU_L1_STREAM_ID_REG_OFFSET, -+ .l2_stream_id_reg_offset = -+ IPU6_MMU_L2_STREAM_ID_REG_OFFSET, -+ }, -+ { -+ .offset = IPU6_ISYS_IOMMU1_OFFSET, -+ .info_bits = 0, -+ .nr_l1streams = 16, -+ .l1_block_sz = { -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 1, 1, 4 -+ }, -+ .nr_l2streams = 16, -+ .l2_block_sz = { -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2 -+ }, -+ .insert_read_before_invalidate = false, -+ .l1_stream_id_reg_offset = -+ IPU6_MMU_L1_STREAM_ID_REG_OFFSET, -+ .l2_stream_id_reg_offset = -+ IPU6_MMU_L2_STREAM_ID_REG_OFFSET, -+ }, -+ { -+ .offset = IPU6_ISYS_IOMMUI_OFFSET, -+ .info_bits = 0, -+ .nr_l1streams = 0, -+ .nr_l2streams = 0, -+ .insert_read_before_invalidate = false, -+ }, -+ }, -+ .cdc_fifos = 3, -+ .cdc_fifo_threshold = {6, 8, 2}, -+ .dmem_offset = IPU6_ISYS_DMEM_OFFSET, -+ .spc_offset = IPU6_ISYS_SPC_OFFSET, -+ }, -+ .isys_dma_overshoot = IPU6_ISYS_OVERALLOC_MIN, -+}; -+ -+static struct ipu6_psys_internal_pdata psys_ipdata = { -+ .hw_variant = { -+ .offset = IPU6_UNIFIED_OFFSET, -+ .nr_mmus = 4, -+ .mmu_hw = { -+ { -+ .offset = IPU6_PSYS_IOMMU0_OFFSET, -+ .info_bits = -+ IPU6_INFO_REQUEST_DESTINATION_IOSF, -+ .nr_l1streams = 16, -+ .l1_block_sz = { -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2 -+ }, -+ .nr_l2streams = 16, -+ .l2_block_sz = { -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2 -+ }, -+ .insert_read_before_invalidate = false, -+ .l1_stream_id_reg_offset = -+ IPU6_MMU_L1_STREAM_ID_REG_OFFSET, -+ .l2_stream_id_reg_offset = -+ IPU6_MMU_L2_STREAM_ID_REG_OFFSET, -+ }, -+ { -+ .offset = IPU6_PSYS_IOMMU1_OFFSET, -+ .info_bits = 0, -+ .nr_l1streams = 32, -+ .l1_block_sz = { -+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 10, -+ 5, 4, 14, 6, 4, 14, 6, 4, 8, -+ 4, 2, 1, 1, 1, 1, 14 -+ }, -+ .nr_l2streams = 32, -+ .l2_block_sz = { -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2 -+ }, -+ .insert_read_before_invalidate = false, -+ .l1_stream_id_reg_offset = -+ IPU6_MMU_L1_STREAM_ID_REG_OFFSET, -+ .l2_stream_id_reg_offset = -+ IPU6_PSYS_MMU1W_L2_STREAM_ID_REG_OFFSET, -+ }, -+ { -+ .offset = IPU6_PSYS_IOMMU1R_OFFSET, -+ .info_bits = 0, -+ .nr_l1streams = 16, -+ .l1_block_sz = { -+ 1, 4, 4, 4, 4, 16, 8, 4, 32, -+ 16, 16, 2, 2, 2, 1, 12 -+ }, -+ .nr_l2streams = 16, -+ .l2_block_sz = { -+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 2, 2, 2 -+ }, -+ .insert_read_before_invalidate = false, -+ .l1_stream_id_reg_offset = -+ IPU6_MMU_L1_STREAM_ID_REG_OFFSET, -+ .l2_stream_id_reg_offset = -+ IPU6_MMU_L2_STREAM_ID_REG_OFFSET, -+ }, -+ { -+ .offset = IPU6_PSYS_IOMMUI_OFFSET, -+ .info_bits = 0, -+ .nr_l1streams = 0, -+ .nr_l2streams = 0, -+ .insert_read_before_invalidate = false, -+ }, -+ }, -+ .dmem_offset = IPU6_PSYS_DMEM_OFFSET, -+ }, -+}; -+ -+static const struct ipu6_buttress_ctrl isys_buttress_ctrl = { -+ .ratio = IPU6_IS_FREQ_CTL_DEFAULT_RATIO, -+ .qos_floor = IPU6_IS_FREQ_CTL_DEFAULT_QOS_FLOOR_RATIO, -+ .freq_ctl = IPU6_BUTTRESS_REG_IS_FREQ_CTL, -+ .pwr_sts_shift = IPU6_BUTTRESS_PWR_STATE_IS_PWR_SHIFT, -+ .pwr_sts_mask = IPU6_BUTTRESS_PWR_STATE_IS_PWR_MASK, -+ .pwr_sts_on = IPU6_BUTTRESS_PWR_STATE_UP_DONE, -+ .pwr_sts_off = IPU6_BUTTRESS_PWR_STATE_DN_DONE, -+}; -+ -+static const struct ipu6_buttress_ctrl psys_buttress_ctrl = { -+ .ratio = IPU6_PS_FREQ_CTL_DEFAULT_RATIO, -+ .qos_floor = IPU6_PS_FREQ_CTL_DEFAULT_QOS_FLOOR_RATIO, -+ .freq_ctl = IPU6_BUTTRESS_REG_PS_FREQ_CTL, -+ .pwr_sts_shift = IPU6_BUTTRESS_PWR_STATE_PS_PWR_SHIFT, -+ .pwr_sts_mask = IPU6_BUTTRESS_PWR_STATE_PS_PWR_MASK, -+ .pwr_sts_on = IPU6_BUTTRESS_PWR_STATE_UP_DONE, -+ .pwr_sts_off = IPU6_BUTTRESS_PWR_STATE_DN_DONE, -+}; -+ -+static void -+ipu6_pkg_dir_configure_spc(struct ipu6_device *isp, -+ const struct ipu6_hw_variants *hw_variant, -+ int pkg_dir_idx, void __iomem *base, -+ u64 *pkg_dir, dma_addr_t pkg_dir_vied_address) -+{ -+ struct ipu6_cell_program *prog; -+ void __iomem *spc_base; -+ u32 server_fw_addr; -+ dma_addr_t dma_addr; -+ u32 pg_offset; -+ -+ server_fw_addr = lower_32_bits(*(pkg_dir + (pkg_dir_idx + 1) * 2)); -+ if (pkg_dir_idx == IPU6_CPD_PKG_DIR_ISYS_SERVER_IDX) -+ dma_addr = sg_dma_address(isp->isys->fw_sgt.sgl); -+ else -+ dma_addr = sg_dma_address(isp->psys->fw_sgt.sgl); -+ -+ pg_offset = server_fw_addr - dma_addr; -+ prog = (struct ipu6_cell_program *)((u64)isp->cpd_fw->data + pg_offset); -+ spc_base = base + prog->regs_addr; -+ if (spc_base != (base + hw_variant->spc_offset)) -+ dev_warn(&isp->pdev->dev, -+ "SPC reg addr %p not matching value from CPD %p\n", -+ base + hw_variant->spc_offset, spc_base); -+ writel(server_fw_addr + prog->blob_offset + -+ prog->icache_source, spc_base + IPU6_PSYS_REG_SPC_ICACHE_BASE); -+ writel(IPU6_INFO_REQUEST_DESTINATION_IOSF, -+ spc_base + IPU6_REG_PSYS_INFO_SEG_0_CONFIG_ICACHE_MASTER); -+ writel(prog->start[1], spc_base + IPU6_PSYS_REG_SPC_START_PC); -+ writel(pkg_dir_vied_address, base + hw_variant->dmem_offset); -+} -+ -+void ipu6_configure_spc(struct ipu6_device *isp, -+ const struct ipu6_hw_variants *hw_variant, -+ int pkg_dir_idx, void __iomem *base, u64 *pkg_dir, -+ dma_addr_t pkg_dir_dma_addr) -+{ -+ void __iomem *dmem_base = base + hw_variant->dmem_offset; -+ void __iomem *spc_regs_base = base + hw_variant->spc_offset; -+ u32 val; -+ -+ val = readl(spc_regs_base + IPU6_PSYS_REG_SPC_STATUS_CTRL); -+ val |= IPU6_PSYS_SPC_STATUS_CTRL_ICACHE_INVALIDATE; -+ writel(val, spc_regs_base + IPU6_PSYS_REG_SPC_STATUS_CTRL); -+ -+ if (isp->secure_mode) -+ writel(IPU6_PKG_DIR_IMR_OFFSET, dmem_base); -+ else -+ ipu6_pkg_dir_configure_spc(isp, hw_variant, pkg_dir_idx, base, -+ pkg_dir, pkg_dir_dma_addr); -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_configure_spc, INTEL_IPU6); -+ -+static void ipu6_internal_pdata_init(struct ipu6_device *isp) -+{ -+ u8 hw_ver = isp->hw_ver; -+ -+ isys_ipdata.num_parallel_streams = IPU6_ISYS_NUM_STREAMS; -+ isys_ipdata.sram_gran_shift = IPU6_SRAM_GRANULARITY_SHIFT; -+ isys_ipdata.sram_gran_size = IPU6_SRAM_GRANULARITY_SIZE; -+ isys_ipdata.max_sram_size = IPU6_MAX_SRAM_SIZE; -+ isys_ipdata.sensor_type_start = IPU6_FW_ISYS_SENSOR_TYPE_START; -+ isys_ipdata.sensor_type_end = IPU6_FW_ISYS_SENSOR_TYPE_END; -+ isys_ipdata.max_streams = IPU6_ISYS_NUM_STREAMS; -+ isys_ipdata.max_send_queues = IPU6_N_MAX_SEND_QUEUES; -+ isys_ipdata.max_sram_blocks = IPU6_NOF_SRAM_BLOCKS_MAX; -+ isys_ipdata.max_devq_size = IPU6_DEV_SEND_QUEUE_SIZE; -+ isys_ipdata.csi2.nports = ARRAY_SIZE(ipu6_csi_offsets); -+ isys_ipdata.csi2.offsets = ipu6_csi_offsets; -+ isys_ipdata.csi2.irq_mask = IPU6_CSI_RX_ERROR_IRQ_MASK; -+ isys_ipdata.csi2.ctrl0_irq_edge = IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_EDGE; -+ isys_ipdata.csi2.ctrl0_irq_clear = -+ IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_CLEAR; -+ isys_ipdata.csi2.ctrl0_irq_mask = IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_MASK; -+ isys_ipdata.csi2.ctrl0_irq_enable = -+ IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_ENABLE; -+ isys_ipdata.csi2.ctrl0_irq_status = -+ IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_STATUS; -+ isys_ipdata.csi2.ctrl0_irq_lnp = -+ IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_LEVEL_NOT_PULSE; -+ isys_ipdata.enhanced_iwake = is_ipu6ep_mtl(hw_ver) || is_ipu6ep(hw_ver); -+ psys_ipdata.hw_variant.spc_offset = IPU6_PSYS_SPC_OFFSET; -+ isys_ipdata.csi2.fw_access_port_ofs = CSI_REG_HUB_FW_ACCESS_PORT_OFS; -+ -+ if (is_ipu6ep(hw_ver)) { -+ isys_ipdata.ltr = IPU6EP_LTR_VALUE; -+ isys_ipdata.memopen_threshold = IPU6EP_MIN_MEMOPEN_TH; -+ } -+ -+ if (is_ipu6_tgl(hw_ver)) { -+ isys_ipdata.csi2.nports = ARRAY_SIZE(ipu6_tgl_csi_offsets); -+ isys_ipdata.csi2.offsets = ipu6_tgl_csi_offsets; -+ } -+ -+ if (is_ipu6ep_mtl(hw_ver)) { -+ isys_ipdata.csi2.nports = ARRAY_SIZE(ipu6ep_mtl_csi_offsets); -+ isys_ipdata.csi2.offsets = ipu6ep_mtl_csi_offsets; -+ -+ isys_ipdata.csi2.ctrl0_irq_edge = -+ IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_EDGE; -+ isys_ipdata.csi2.ctrl0_irq_clear = -+ IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_CLEAR; -+ isys_ipdata.csi2.ctrl0_irq_mask = -+ IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_MASK; -+ isys_ipdata.csi2.ctrl0_irq_enable = -+ IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_ENABLE; -+ isys_ipdata.csi2.ctrl0_irq_lnp = -+ IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_LEVEL_NOT_PULSE; -+ isys_ipdata.csi2.ctrl0_irq_status = -+ IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_STATUS; -+ isys_ipdata.csi2.fw_access_port_ofs = -+ CSI_REG_HUB_FW_ACCESS_PORT_V6OFS; -+ isys_ipdata.ltr = IPU6EP_MTL_LTR_VALUE; -+ isys_ipdata.memopen_threshold = IPU6EP_MTL_MIN_MEMOPEN_TH; -+ } -+ -+ if (is_ipu6se(hw_ver)) { -+ isys_ipdata.csi2.nports = ARRAY_SIZE(ipu6se_csi_offsets); -+ isys_ipdata.csi2.irq_mask = IPU6SE_CSI_RX_ERROR_IRQ_MASK; -+ isys_ipdata.csi2.offsets = ipu6se_csi_offsets; -+ isys_ipdata.num_parallel_streams = IPU6SE_ISYS_NUM_STREAMS; -+ isys_ipdata.sram_gran_shift = IPU6SE_SRAM_GRANULARITY_SHIFT; -+ isys_ipdata.sram_gran_size = IPU6SE_SRAM_GRANULARITY_SIZE; -+ isys_ipdata.max_sram_size = IPU6SE_MAX_SRAM_SIZE; -+ isys_ipdata.sensor_type_start = -+ IPU6SE_FW_ISYS_SENSOR_TYPE_START; -+ isys_ipdata.sensor_type_end = IPU6SE_FW_ISYS_SENSOR_TYPE_END; -+ isys_ipdata.max_streams = IPU6SE_ISYS_NUM_STREAMS; -+ isys_ipdata.max_send_queues = IPU6SE_N_MAX_SEND_QUEUES; -+ isys_ipdata.max_sram_blocks = IPU6SE_NOF_SRAM_BLOCKS_MAX; -+ isys_ipdata.max_devq_size = IPU6SE_DEV_SEND_QUEUE_SIZE; -+ psys_ipdata.hw_variant.spc_offset = IPU6SE_PSYS_SPC_OFFSET; -+ } -+} -+ -+static int ipu6_isys_check_fwnode_graph(struct fwnode_handle *fwnode) -+{ -+ struct fwnode_handle *endpoint; -+ -+ if (IS_ERR_OR_NULL(fwnode)) -+ return -EINVAL; -+ -+ endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL); -+ if (endpoint) { -+ fwnode_handle_put(endpoint); -+ return 0; -+ } -+ -+ return ipu6_isys_check_fwnode_graph(fwnode->secondary); -+} -+ -+static struct ipu6_bus_device * -+ipu6_isys_init(struct pci_dev *pdev, struct device *parent, -+ struct ipu6_buttress_ctrl *ctrl, void __iomem *base, -+ const struct ipu6_isys_internal_pdata *ipdata) -+{ -+ struct device *dev = &pdev->dev; -+ struct fwnode_handle *fwnode = dev_fwnode(dev); -+ struct ipu6_bus_device *isys_adev; -+ struct ipu6_isys_pdata *pdata; -+ int ret; -+ -+ /* check fwnode at first, fallback into bridge if no fwnode graph */ -+ ret = ipu6_isys_check_fwnode_graph(fwnode); -+ if (ret) { -+ if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary)) { -+ dev_err(dev, -+ "fwnode graph has no endpoints connection\n"); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ ret = ipu_bridge_init(dev, ipu_bridge_parse_ssdb); -+ if (ret) { -+ dev_err_probe(dev, ret, "IPU6 bridge init failed\n"); -+ return ERR_PTR(ret); -+ } -+ } -+ -+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); -+ if (!pdata) -+ return ERR_PTR(-ENOMEM); -+ -+ pdata->base = base; -+ pdata->ipdata = ipdata; -+ -+ isys_adev = ipu6_bus_initialize_device(pdev, parent, pdata, ctrl, -+ IPU6_ISYS_NAME); -+ if (IS_ERR(isys_adev)) { -+ dev_err_probe(dev, PTR_ERR(isys_adev), -+ "ipu6_bus_initialize_device isys failed\n"); -+ kfree(pdata); -+ return ERR_CAST(isys_adev); -+ } -+ -+ isys_adev->mmu = ipu6_mmu_init(dev, base, ISYS_MMID, -+ &ipdata->hw_variant); -+ if (IS_ERR(isys_adev->mmu)) { -+ dev_err_probe(dev, PTR_ERR(isys_adev), -+ "ipu6_mmu_init(isys_adev->mmu) failed\n"); -+ put_device(&isys_adev->auxdev.dev); -+ kfree(pdata); -+ return ERR_CAST(isys_adev->mmu); -+ } -+ -+ isys_adev->mmu->dev = &isys_adev->auxdev.dev; -+ -+ ret = ipu6_bus_add_device(isys_adev); -+ if (ret) { -+ kfree(pdata); -+ return ERR_PTR(ret); -+ } -+ -+ return isys_adev; -+} -+ -+static struct ipu6_bus_device * -+ipu6_psys_init(struct pci_dev *pdev, struct device *parent, -+ struct ipu6_buttress_ctrl *ctrl, void __iomem *base, -+ const struct ipu6_psys_internal_pdata *ipdata) -+{ -+ struct ipu6_bus_device *psys_adev; -+ struct ipu6_psys_pdata *pdata; -+ int ret; -+ -+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); -+ if (!pdata) -+ return ERR_PTR(-ENOMEM); -+ -+ pdata->base = base; -+ pdata->ipdata = ipdata; -+ -+ psys_adev = ipu6_bus_initialize_device(pdev, parent, pdata, ctrl, -+ IPU6_PSYS_NAME); -+ if (IS_ERR(psys_adev)) { -+ dev_err_probe(&pdev->dev, PTR_ERR(psys_adev), -+ "ipu6_bus_initialize_device psys failed\n"); -+ kfree(pdata); -+ return ERR_CAST(psys_adev); -+ } -+ -+ psys_adev->mmu = ipu6_mmu_init(&pdev->dev, base, PSYS_MMID, -+ &ipdata->hw_variant); -+ if (IS_ERR(psys_adev->mmu)) { -+ dev_err_probe(&pdev->dev, PTR_ERR(psys_adev), -+ "ipu6_mmu_init(psys_adev->mmu) failed\n"); -+ put_device(&psys_adev->auxdev.dev); -+ kfree(pdata); -+ return ERR_CAST(psys_adev->mmu); -+ } -+ -+ psys_adev->mmu->dev = &psys_adev->auxdev.dev; -+ -+ ret = ipu6_bus_add_device(psys_adev); -+ if (ret) { -+ kfree(pdata); -+ return ERR_PTR(ret); -+ } -+ -+ return psys_adev; -+} -+ -+static int ipu6_pci_config_setup(struct pci_dev *dev, u8 hw_ver) -+{ -+ int ret; -+ -+ /* disable IPU6 PCI ATS on mtl ES2 */ -+ if (is_ipu6ep_mtl(hw_ver) && boot_cpu_data.x86_stepping == 0x2 && -+ pci_ats_supported(dev)) -+ pci_disable_ats(dev); -+ -+ /* No PCI msi capability for IPU6EP */ -+ if (is_ipu6ep(hw_ver) || is_ipu6ep_mtl(hw_ver)) { -+ /* likely do nothing as msi not enabled by default */ -+ pci_disable_msi(dev); -+ return 0; -+ } -+ -+ ret = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_MSI); -+ if (ret < 0) -+ return dev_err_probe(&dev->dev, ret, "Request msi failed"); -+ -+ return 0; -+} -+ -+static void ipu6_configure_vc_mechanism(struct ipu6_device *isp) -+{ -+ u32 val = readl(isp->base + BUTTRESS_REG_BTRS_CTRL); -+ -+ if (IPU6_BTRS_ARB_STALL_MODE_VC0 == IPU6_BTRS_ARB_MODE_TYPE_STALL) -+ val |= BUTTRESS_REG_BTRS_CTRL_STALL_MODE_VC0; -+ else -+ val &= ~BUTTRESS_REG_BTRS_CTRL_STALL_MODE_VC0; -+ -+ if (IPU6_BTRS_ARB_STALL_MODE_VC1 == IPU6_BTRS_ARB_MODE_TYPE_STALL) -+ val |= BUTTRESS_REG_BTRS_CTRL_STALL_MODE_VC1; -+ else -+ val &= ~BUTTRESS_REG_BTRS_CTRL_STALL_MODE_VC1; -+ -+ writel(val, isp->base + BUTTRESS_REG_BTRS_CTRL); -+} -+ -+static int request_cpd_fw(const struct firmware **firmware_p, const char *name, -+ struct device *device) -+{ -+ const struct firmware *fw; -+ struct firmware *dst; -+ int ret = 0; -+ -+ ret = request_firmware(&fw, name, device); -+ if (ret) -+ return ret; -+ -+ if (is_vmalloc_addr(fw->data)) { -+ *firmware_p = fw; -+ return 0; -+ } -+ -+ dst = kzalloc(sizeof(*dst), GFP_KERNEL); -+ if (!dst) { -+ ret = -ENOMEM; -+ goto release_firmware; -+ } -+ -+ dst->size = fw->size; -+ dst->data = vmalloc(fw->size); -+ if (!dst->data) { -+ kfree(dst); -+ ret = -ENOMEM; -+ goto release_firmware; -+ } -+ -+ memcpy((void *)dst->data, fw->data, fw->size); -+ *firmware_p = dst; -+ -+release_firmware: -+ release_firmware(fw); -+ -+ return ret; -+} -+ -+static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ struct ipu6_buttress_ctrl *isys_ctrl = NULL, *psys_ctrl = NULL; -+ struct device *dev = &pdev->dev; -+ void __iomem *isys_base = NULL; -+ void __iomem *psys_base = NULL; -+ struct ipu6_device *isp; -+ phys_addr_t phys; -+ u32 val, version, sku_id; -+ int ret; -+ -+ isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL); -+ if (!isp) -+ return -ENOMEM; -+ -+ isp->pdev = pdev; -+ INIT_LIST_HEAD(&isp->devices); -+ -+ ret = pcim_enable_device(pdev); -+ if (ret) -+ return dev_err_probe(dev, ret, "Enable PCI device failed\n"); -+ -+ phys = pci_resource_start(pdev, IPU6_PCI_BAR); -+ dev_dbg(dev, "IPU6 PCI bar[%u] = %pa\n", IPU6_PCI_BAR, &phys); -+ -+ ret = pcim_iomap_regions(pdev, 1 << IPU6_PCI_BAR, pci_name(pdev)); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to I/O mem remappinp\n"); -+ -+ isp->base = pcim_iomap_table(pdev)[IPU6_PCI_BAR]; -+ pci_set_drvdata(pdev, isp); -+ pci_set_master(pdev); -+ -+ isp->cpd_metadata_cmpnt_size = sizeof(struct ipu6_cpd_metadata_cmpnt); -+ switch (id->device) { -+ case PCI_DEVICE_ID_INTEL_IPU6: -+ isp->hw_ver = IPU6_VER_6; -+ isp->cpd_fw_name = IPU6_FIRMWARE_NAME; -+ break; -+ case PCI_DEVICE_ID_INTEL_IPU6SE: -+ isp->hw_ver = IPU6_VER_6SE; -+ isp->cpd_fw_name = IPU6SE_FIRMWARE_NAME; -+ isp->cpd_metadata_cmpnt_size = -+ sizeof(struct ipu6se_cpd_metadata_cmpnt); -+ break; -+ case PCI_DEVICE_ID_INTEL_IPU6EP_ADLP: -+ case PCI_DEVICE_ID_INTEL_IPU6EP_ADLN: -+ case PCI_DEVICE_ID_INTEL_IPU6EP_RPLP: -+ isp->hw_ver = IPU6_VER_6EP; -+ isp->cpd_fw_name = IPU6EP_FIRMWARE_NAME; -+ break; -+ case PCI_DEVICE_ID_INTEL_IPU6EP_MTL: -+ isp->hw_ver = IPU6_VER_6EP_MTL; -+ isp->cpd_fw_name = IPU6EPMTL_FIRMWARE_NAME; -+ break; -+ default: -+ return dev_err_probe(dev, -ENODEV, -+ "Unsupported IPU6 device %x\n", -+ id->device); -+ } -+ -+ ipu6_internal_pdata_init(isp); -+ -+ isys_base = isp->base + isys_ipdata.hw_variant.offset; -+ psys_base = isp->base + psys_ipdata.hw_variant.offset; -+ -+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(39)); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to set DMA mask\n"); -+ -+ ret = dma_set_max_seg_size(dev, UINT_MAX); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to set max_seg_size\n"); -+ -+ ret = ipu6_pci_config_setup(pdev, isp->hw_ver); -+ if (ret) -+ return ret; -+ -+ ret = ipu6_buttress_init(isp); -+ if (ret) -+ return ret; -+ -+ ret = request_cpd_fw(&isp->cpd_fw, isp->cpd_fw_name, dev); -+ if (ret) { -+ dev_err_probe(&isp->pdev->dev, ret, -+ "Requesting signed firmware %s failed\n", -+ isp->cpd_fw_name); -+ goto buttress_exit; -+ } -+ -+ ret = ipu6_cpd_validate_cpd_file(isp, isp->cpd_fw->data, -+ isp->cpd_fw->size); -+ if (ret) { -+ dev_err_probe(&isp->pdev->dev, ret, -+ "Failed to validate cpd\n"); -+ goto out_ipu6_bus_del_devices; -+ } -+ -+ isys_ctrl = devm_kmemdup(dev, &isys_buttress_ctrl, -+ sizeof(isys_buttress_ctrl), GFP_KERNEL); -+ if (!isys_ctrl) { -+ ret = -ENOMEM; -+ goto out_ipu6_bus_del_devices; -+ } -+ -+ isp->isys = ipu6_isys_init(pdev, dev, isys_ctrl, isys_base, -+ &isys_ipdata); -+ if (IS_ERR(isp->isys)) { -+ ret = PTR_ERR(isp->isys); -+ goto out_ipu6_bus_del_devices; -+ } -+ -+ psys_ctrl = devm_kmemdup(dev, &psys_buttress_ctrl, -+ sizeof(psys_buttress_ctrl), GFP_KERNEL); -+ if (!psys_ctrl) { -+ ret = -ENOMEM; -+ goto out_ipu6_bus_del_devices; -+ } -+ -+ isp->psys = ipu6_psys_init(pdev, &isp->isys->auxdev.dev, psys_ctrl, -+ psys_base, &psys_ipdata); -+ if (IS_ERR(isp->psys)) { -+ ret = PTR_ERR(isp->psys); -+ goto out_ipu6_bus_del_devices; -+ } -+ -+ ret = pm_runtime_resume_and_get(&isp->psys->auxdev.dev); -+ if (ret < 0) -+ goto out_ipu6_bus_del_devices; -+ -+ ret = ipu6_mmu_hw_init(isp->psys->mmu); -+ if (ret) { -+ dev_err_probe(&isp->pdev->dev, ret, -+ "Failed to set MMU hardware\n"); -+ goto out_ipu6_bus_del_devices; -+ } -+ -+ ret = ipu6_buttress_map_fw_image(isp->psys, isp->cpd_fw, -+ &isp->psys->fw_sgt); -+ if (ret) { -+ dev_err_probe(&isp->pdev->dev, ret, "failed to map fw image\n"); -+ goto out_ipu6_bus_del_devices; -+ } -+ -+ ret = ipu6_cpd_create_pkg_dir(isp->psys, isp->cpd_fw->data); -+ if (ret) { -+ dev_err_probe(&isp->pdev->dev, ret, -+ "failed to create pkg dir\n"); -+ goto out_ipu6_bus_del_devices; -+ } -+ -+ ret = devm_request_threaded_irq(dev, pdev->irq, ipu6_buttress_isr, -+ ipu6_buttress_isr_threaded, -+ IRQF_SHARED, IPU6_NAME, isp); -+ if (ret) { -+ dev_err_probe(dev, ret, "Requesting irq failed\n"); -+ goto out_ipu6_bus_del_devices; -+ } -+ -+ ret = ipu6_buttress_authenticate(isp); -+ if (ret) { -+ dev_err_probe(&isp->pdev->dev, ret, -+ "FW authentication failed\n"); -+ goto out_free_irq; -+ } -+ -+ ipu6_mmu_hw_cleanup(isp->psys->mmu); -+ pm_runtime_put(&isp->psys->auxdev.dev); -+ -+ /* Configure the arbitration mechanisms for VC requests */ -+ ipu6_configure_vc_mechanism(isp); -+ -+ val = readl(isp->base + BUTTRESS_REG_SKU); -+ sku_id = FIELD_GET(GENMASK(6, 4), val); -+ version = FIELD_GET(GENMASK(3, 0), val); -+ dev_info(dev, "IPU%u-v%u[%x] hardware version %d\n", version, sku_id, -+ pdev->device, isp->hw_ver); -+ -+ pm_runtime_put_noidle(dev); -+ pm_runtime_allow(dev); -+ -+ isp->bus_ready_to_probe = true; -+ -+ return 0; -+ -+out_free_irq: -+ devm_free_irq(dev, pdev->irq, isp); -+out_ipu6_bus_del_devices: -+ if (isp->psys) { -+ ipu6_cpd_free_pkg_dir(isp->psys); -+ ipu6_buttress_unmap_fw_image(isp->psys, &isp->psys->fw_sgt); -+ } -+ if (!IS_ERR_OR_NULL(isp->psys) && !IS_ERR_OR_NULL(isp->psys->mmu)) -+ ipu6_mmu_cleanup(isp->psys->mmu); -+ if (!IS_ERR_OR_NULL(isp->isys) && !IS_ERR_OR_NULL(isp->isys->mmu)) -+ ipu6_mmu_cleanup(isp->isys->mmu); -+ ipu6_bus_del_devices(pdev); -+ release_firmware(isp->cpd_fw); -+buttress_exit: -+ ipu6_buttress_exit(isp); -+ -+ return ret; -+} -+ -+static void ipu6_pci_remove(struct pci_dev *pdev) -+{ -+ struct ipu6_device *isp = pci_get_drvdata(pdev); -+ struct ipu6_mmu *isys_mmu = isp->isys->mmu; -+ struct ipu6_mmu *psys_mmu = isp->psys->mmu; -+ -+ devm_free_irq(&pdev->dev, pdev->irq, isp); -+ ipu6_cpd_free_pkg_dir(isp->psys); -+ -+ ipu6_buttress_unmap_fw_image(isp->psys, &isp->psys->fw_sgt); -+ ipu6_buttress_exit(isp); -+ -+ ipu6_bus_del_devices(pdev); -+ -+ pm_runtime_forbid(&pdev->dev); -+ pm_runtime_get_noresume(&pdev->dev); -+ -+ pci_release_regions(pdev); -+ pci_disable_device(pdev); -+ -+ release_firmware(isp->cpd_fw); -+ -+ ipu6_mmu_cleanup(psys_mmu); -+ ipu6_mmu_cleanup(isys_mmu); -+} -+ -+static void ipu6_pci_reset_prepare(struct pci_dev *pdev) -+{ -+ struct ipu6_device *isp = pci_get_drvdata(pdev); -+ -+ pm_runtime_forbid(&isp->pdev->dev); -+} -+ -+static void ipu6_pci_reset_done(struct pci_dev *pdev) -+{ -+ struct ipu6_device *isp = pci_get_drvdata(pdev); -+ -+ ipu6_buttress_restore(isp); -+ if (isp->secure_mode) -+ ipu6_buttress_reset_authentication(isp); -+ -+ isp->need_ipc_reset = true; -+ pm_runtime_allow(&isp->pdev->dev); -+} -+ -+/* -+ * PCI base driver code requires driver to provide these to enable -+ * PCI device level PM state transitions (D0<->D3) -+ */ -+static int ipu6_suspend(struct device *dev) -+{ -+ return 0; -+} -+ -+static int ipu6_resume(struct device *dev) -+{ -+ struct pci_dev *pdev = to_pci_dev(dev); -+ struct ipu6_device *isp = pci_get_drvdata(pdev); -+ struct ipu6_buttress *b = &isp->buttress; -+ int ret; -+ -+ /* Configure the arbitration mechanisms for VC requests */ -+ ipu6_configure_vc_mechanism(isp); -+ -+ isp->secure_mode = ipu6_buttress_get_secure_mode(isp); -+ dev_info(dev, "IPU6 in %s mode\n", -+ isp->secure_mode ? "secure" : "non-secure"); -+ -+ ipu6_buttress_restore(isp); -+ -+ ret = ipu6_buttress_ipc_reset(isp, &b->cse); -+ if (ret) -+ dev_err(&isp->pdev->dev, "IPC reset protocol failed!\n"); -+ -+ ret = pm_runtime_resume_and_get(&isp->psys->auxdev.dev); -+ if (ret < 0) { -+ dev_err(&isp->psys->auxdev.dev, "Failed to get runtime PM\n"); -+ return 0; -+ } -+ -+ ret = ipu6_buttress_authenticate(isp); -+ if (ret) -+ dev_err(&isp->pdev->dev, "FW authentication failed(%d)\n", ret); -+ -+ pm_runtime_put(&isp->psys->auxdev.dev); -+ -+ return 0; -+} -+ -+static int ipu6_runtime_resume(struct device *dev) -+{ -+ struct pci_dev *pdev = to_pci_dev(dev); -+ struct ipu6_device *isp = pci_get_drvdata(pdev); -+ int ret; -+ -+ ipu6_configure_vc_mechanism(isp); -+ ipu6_buttress_restore(isp); -+ -+ if (isp->need_ipc_reset) { -+ struct ipu6_buttress *b = &isp->buttress; -+ -+ isp->need_ipc_reset = false; -+ ret = ipu6_buttress_ipc_reset(isp, &b->cse); -+ if (ret) -+ dev_err(&isp->pdev->dev, "IPC reset protocol failed\n"); -+ } -+ -+ return 0; -+} -+ -+static const struct dev_pm_ops ipu6_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(&ipu6_suspend, &ipu6_resume) -+ SET_RUNTIME_PM_OPS(&ipu6_suspend, &ipu6_runtime_resume, NULL) -+}; -+ -+static const struct pci_device_id ipu6_pci_tbl[] = { -+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6) }, -+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6SE) }, -+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6EP_ADLP) }, -+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6EP_ADLN) }, -+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6EP_RPLP) }, -+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6EP_MTL) }, -+ { } -+}; -+MODULE_DEVICE_TABLE(pci, ipu6_pci_tbl); -+ -+static const struct pci_error_handlers pci_err_handlers = { -+ .reset_prepare = ipu6_pci_reset_prepare, -+ .reset_done = ipu6_pci_reset_done, -+}; -+ -+static struct pci_driver ipu6_pci_driver = { -+ .name = IPU6_NAME, -+ .id_table = ipu6_pci_tbl, -+ .probe = ipu6_pci_probe, -+ .remove = ipu6_pci_remove, -+ .driver = { -+ .pm = pm_ptr(&ipu6_pm_ops), -+ }, -+ .err_handler = &pci_err_handlers, -+}; -+ -+module_pci_driver(ipu6_pci_driver); -+ -+MODULE_IMPORT_NS(INTEL_IPU_BRIDGE); -+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>"); -+MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@intel.com>"); -+MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>"); -+MODULE_AUTHOR("Qingwu Zhang <qingwu.zhang@intel.com>"); -+MODULE_AUTHOR("Yunliang Ding <yunliang.ding@intel.com>"); -+MODULE_AUTHOR("Hongju Wang <hongju.wang@intel.com>"); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Intel IPU6 PCI driver"); -diff --git a/drivers/media/pci/intel/ipu6/ipu6.h b/drivers/media/pci/intel/ipu6/ipu6.h -new file mode 100644 -index 000000000000..04e7e7e61ca5 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6.h -@@ -0,0 +1,356 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_H -+#define IPU6_H -+ -+#include <linux/list.h> -+#include <linux/pci.h> -+#include <linux/types.h> -+ -+#include "ipu6-buttress.h" -+ -+struct firmware; -+struct pci_dev; -+struct ipu6_bus_device; -+ -+#define PCI_DEVICE_ID_INTEL_IPU6 0x9a19 -+#define PCI_DEVICE_ID_INTEL_IPU6SE 0x4e19 -+#define PCI_DEVICE_ID_INTEL_IPU6EP_ADLP 0x465d -+#define PCI_DEVICE_ID_INTEL_IPU6EP_ADLN 0x462e -+#define PCI_DEVICE_ID_INTEL_IPU6EP_RPLP 0xa75d -+#define PCI_DEVICE_ID_INTEL_IPU6EP_MTL 0x7d19 -+ -+#define IPU6_NAME "intel-ipu6" -+#define IPU6_MEDIA_DEV_MODEL_NAME "ipu6" -+ -+#define IPU6SE_FIRMWARE_NAME "intel/ipu6se_fw.bin" -+#define IPU6EP_FIRMWARE_NAME "intel/ipu6ep_fw.bin" -+#define IPU6_FIRMWARE_NAME "intel/ipu6_fw.bin" -+#define IPU6EPMTL_FIRMWARE_NAME "intel/ipu6epmtl_fw.bin" -+ -+enum ipu6_version { -+ IPU6_VER_INVALID = 0, -+ IPU6_VER_6 = 1, -+ IPU6_VER_6SE = 3, -+ IPU6_VER_6EP = 5, -+ IPU6_VER_6EP_MTL = 6, -+}; -+ -+/* -+ * IPU6 - TGL -+ * IPU6SE - JSL -+ * IPU6EP - ADL/RPL -+ * IPU6EP_MTL - MTL -+ */ -+static inline bool is_ipu6se(u8 hw_ver) -+{ -+ return hw_ver == IPU6_VER_6SE; -+} -+ -+static inline bool is_ipu6ep(u8 hw_ver) -+{ -+ return hw_ver == IPU6_VER_6EP; -+} -+ -+static inline bool is_ipu6ep_mtl(u8 hw_ver) -+{ -+ return hw_ver == IPU6_VER_6EP_MTL; -+} -+ -+static inline bool is_ipu6_tgl(u8 hw_ver) -+{ -+ return hw_ver == IPU6_VER_6; -+} -+ -+/* -+ * ISYS DMA can overshoot. For higher resolutions over allocation is one line -+ * but it must be at minimum 1024 bytes. Value could be different in -+ * different versions / generations thus provide it via platform data. -+ */ -+#define IPU6_ISYS_OVERALLOC_MIN 1024 -+ -+/* Physical pages in GDA is 128, page size is 2K for IPU6, 1K for others */ -+#define IPU6_DEVICE_GDA_NR_PAGES 128 -+ -+/* Virtualization factor to calculate the available virtual pages */ -+#define IPU6_DEVICE_GDA_VIRT_FACTOR 32 -+ -+#define NR_OF_MMU_RESOURCES 2 -+ -+struct ipu6_device { -+ struct pci_dev *pdev; -+ struct list_head devices; -+ struct ipu6_bus_device *isys; -+ struct ipu6_bus_device *psys; -+ struct ipu6_buttress buttress; -+ -+ const struct firmware *cpd_fw; -+ const char *cpd_fw_name; -+ u32 cpd_metadata_cmpnt_size; -+ -+ void __iomem *base; -+ bool need_ipc_reset; -+ bool secure_mode; -+ u8 hw_ver; -+ bool bus_ready_to_probe; -+}; -+ -+#define IPU6_ISYS_NAME "isys" -+#define IPU6_PSYS_NAME "psys" -+ -+#define IPU6_MMU_MAX_DEVICES 4 -+#define IPU6_MMU_ADDR_BITS 32 -+/* The firmware is accessible within the first 2 GiB only in non-secure mode. */ -+#define IPU6_MMU_ADDR_BITS_NON_SECURE 31 -+ -+#define IPU6_MMU_MAX_TLB_L1_STREAMS 32 -+#define IPU6_MMU_MAX_TLB_L2_STREAMS 32 -+#define IPU6_MAX_LI_BLOCK_ADDR 128 -+#define IPU6_MAX_L2_BLOCK_ADDR 64 -+ -+#define IPU6_ISYS_MAX_CSI2_LEGACY_PORTS 4 -+#define IPU6_ISYS_MAX_CSI2_COMBO_PORTS 2 -+ -+#define IPU6_MAX_FRAME_COUNTER 0xff -+ -+#define IPU6SE_ISYS_NUM_STREAMS IPU6SE_NONSECURE_STREAM_ID_MAX -+#define IPU6_ISYS_NUM_STREAMS IPU6_NONSECURE_STREAM_ID_MAX -+ -+/* -+ * To maximize the IOSF utlization, IPU6 need to send requests in bursts. -+ * At the DMA interface with the buttress, there are CDC FIFOs with burst -+ * collection capability. CDC FIFO burst collectors have a configurable -+ * threshold and is configured based on the outcome of performance measurements. -+ * -+ * isys has 3 ports with IOSF interface for VC0, VC1 and VC2 -+ * psys has 4 ports with IOSF interface for VC0, VC1w, VC1r and VC2 -+ * -+ * Threshold values are pre-defined and are arrived at after performance -+ * evaluations on a type of IPU6 -+ */ -+#define IPU6_MAX_VC_IOSF_PORTS 4 -+ -+/* -+ * IPU6 must configure correct arbitration mechanism related to the IOSF VC -+ * requests. There are two options per VC0 and VC1 - > 0 means rearbitrate on -+ * stall and 1 means stall until the request is completed. -+ */ -+#define IPU6_BTRS_ARB_MODE_TYPE_REARB 0 -+#define IPU6_BTRS_ARB_MODE_TYPE_STALL 1 -+ -+/* Currently chosen arbitration mechanism for VC0 */ -+#define IPU6_BTRS_ARB_STALL_MODE_VC0 \ -+ IPU6_BTRS_ARB_MODE_TYPE_REARB -+ -+/* Currently chosen arbitration mechanism for VC1 */ -+#define IPU6_BTRS_ARB_STALL_MODE_VC1 \ -+ IPU6_BTRS_ARB_MODE_TYPE_REARB -+ -+/* -+ * MMU Invalidation HW bug workaround by ZLW mechanism -+ * -+ * Old IPU6 MMUV2 has a bug in the invalidation mechanism which might result in -+ * wrong translation or replication of the translation. This will cause data -+ * corruption. So we cannot directly use the MMU V2 invalidation registers -+ * to invalidate the MMU. Instead, whenever an invalidate is called, we need to -+ * clear the TLB by evicting all the valid translations by filling it with trash -+ * buffer (which is guaranteed not to be used by any other processes). ZLW is -+ * used to fill the L1 and L2 caches with the trash buffer translations. ZLW -+ * or Zero length write, is pre-fetch mechanism to pre-fetch the pages in -+ * advance to the L1 and L2 caches without triggering any memory operations. -+ * -+ * In MMU V2, L1 -> 16 streams and 64 blocks, maximum 16 blocks per stream -+ * One L1 block has 16 entries, hence points to 16 * 4K pages -+ * L2 -> 16 streams and 32 blocks. 2 blocks per streams -+ * One L2 block maps to 1024 L1 entries, hence points to 4MB address range -+ * 2 blocks per L2 stream means, 1 stream points to 8MB range -+ * -+ * As we need to clear the caches and 8MB being the biggest cache size, we need -+ * to have trash buffer which points to 8MB address range. As these trash -+ * buffers are not used for any memory transactions, we need only the least -+ * amount of physical memory. So we reserve 8MB IOVA address range but only -+ * one page is reserved from physical memory. Each of this 8MB IOVA address -+ * range is then mapped to the same physical memory page. -+ */ -+/* One L2 entry maps 1024 L1 entries and one L1 entry per page */ -+#define IPU6_MMUV2_L2_RANGE (1024 * PAGE_SIZE) -+/* Max L2 blocks per stream */ -+#define IPU6_MMUV2_MAX_L2_BLOCKS 2 -+/* Max L1 blocks per stream */ -+#define IPU6_MMUV2_MAX_L1_BLOCKS 16 -+#define IPU6_MMUV2_TRASH_RANGE (IPU6_MMUV2_L2_RANGE * IPU6_MMUV2_MAX_L2_BLOCKS) -+/* Entries per L1 block */ -+#define MMUV2_ENTRIES_PER_L1_BLOCK 16 -+#define MMUV2_TRASH_L1_BLOCK_OFFSET (MMUV2_ENTRIES_PER_L1_BLOCK * PAGE_SIZE) -+#define MMUV2_TRASH_L2_BLOCK_OFFSET IPU6_MMUV2_L2_RANGE -+ -+/* -+ * In some of the IPU6 MMUs, there is provision to configure L1 and L2 page -+ * table caches. Both these L1 and L2 caches are divided into multiple sections -+ * called streams. There is maximum 16 streams for both caches. Each of these -+ * sections are subdivided into multiple blocks. When nr_l1streams = 0 and -+ * nr_l2streams = 0, means the MMU is of type MMU_V1 and do not support -+ * L1/L2 page table caches. -+ * -+ * L1 stream per block sizes are configurable and varies per usecase. -+ * L2 has constant block sizes - 2 blocks per stream. -+ * -+ * MMU1 support pre-fetching of the pages to have less cache lookup misses. To -+ * enable the pre-fetching, MMU1 AT (Address Translator) device registers -+ * need to be configured. -+ * -+ * There are four types of memory accesses which requires ZLW configuration. -+ * ZLW(Zero Length Write) is a mechanism to enable VT-d pre-fetching on IOMMU. -+ * -+ * 1. Sequential Access or 1D mode -+ * Set ZLW_EN -> 1 -+ * set ZLW_PAGE_CROSS_1D -> 1 -+ * Set ZLW_N to "N" pages so that ZLW will be inserte N pages ahead where -+ * N is pre-defined and hardcoded in the platform data -+ * Set ZLW_2D -> 0 -+ * -+ * 2. ZLW 2D mode -+ * Set ZLW_EN -> 1 -+ * set ZLW_PAGE_CROSS_1D -> 1, -+ * Set ZLW_N -> 0 -+ * Set ZLW_2D -> 1 -+ * -+ * 3. ZLW Enable (no 1D or 2D mode) -+ * Set ZLW_EN -> 1 -+ * set ZLW_PAGE_CROSS_1D -> 0, -+ * Set ZLW_N -> 0 -+ * Set ZLW_2D -> 0 -+ * -+ * 4. ZLW disable -+ * Set ZLW_EN -> 0 -+ * set ZLW_PAGE_CROSS_1D -> 0, -+ * Set ZLW_N -> 0 -+ * Set ZLW_2D -> 0 -+ * -+ * To configure the ZLW for the above memory access, four registers are -+ * available. Hence to track these four settings, we have the following entries -+ * in the struct ipu6_mmu_hw. Each of these entries are per stream and -+ * available only for the L1 streams. -+ * -+ * a. l1_zlw_en -> To track zlw enabled per stream (ZLW_EN) -+ * b. l1_zlw_1d_mode -> Track 1D mode per stream. ZLW inserted at page boundary -+ * c. l1_ins_zlw_ahead_pages -> to track how advance the ZLW need to be inserted -+ * Insert ZLW request N pages ahead address. -+ * d. l1_zlw_2d_mode -> To track 2D mode per stream (ZLW_2D) -+ * -+ * -+ * Currently L1/L2 streams, blocks, AT ZLW configurations etc. are pre-defined -+ * as per the usecase specific calculations. Any change to this pre-defined -+ * table has to happen in sync with IPU6 FW. -+ */ -+struct ipu6_mmu_hw { -+ union { -+ unsigned long offset; -+ void __iomem *base; -+ }; -+ u32 info_bits; -+ u8 nr_l1streams; -+ /* -+ * L1 has variable blocks per stream - total of 64 blocks and maximum of -+ * 16 blocks per stream. Configurable by using the block start address -+ * per stream. Block start address is calculated from the block size -+ */ -+ u8 l1_block_sz[IPU6_MMU_MAX_TLB_L1_STREAMS]; -+ /* Is ZLW is enabled in each stream */ -+ bool l1_zlw_en[IPU6_MMU_MAX_TLB_L1_STREAMS]; -+ bool l1_zlw_1d_mode[IPU6_MMU_MAX_TLB_L1_STREAMS]; -+ u8 l1_ins_zlw_ahead_pages[IPU6_MMU_MAX_TLB_L1_STREAMS]; -+ bool l1_zlw_2d_mode[IPU6_MMU_MAX_TLB_L1_STREAMS]; -+ -+ u32 l1_stream_id_reg_offset; -+ u32 l2_stream_id_reg_offset; -+ -+ u8 nr_l2streams; -+ /* -+ * L2 has fixed 2 blocks per stream. Block address is calculated -+ * from the block size -+ */ -+ u8 l2_block_sz[IPU6_MMU_MAX_TLB_L2_STREAMS]; -+ /* flag to track if WA is needed for successive invalidate HW bug */ -+ bool insert_read_before_invalidate; -+}; -+ -+struct ipu6_mmu_pdata { -+ u32 nr_mmus; -+ struct ipu6_mmu_hw mmu_hw[IPU6_MMU_MAX_DEVICES]; -+ int mmid; -+}; -+ -+struct ipu6_isys_csi2_pdata { -+ void __iomem *base; -+}; -+ -+struct ipu6_isys_internal_csi2_pdata { -+ u32 nports; -+ u32 irq_mask; -+ u32 *offsets; -+ u32 ctrl0_irq_edge; -+ u32 ctrl0_irq_clear; -+ u32 ctrl0_irq_mask; -+ u32 ctrl0_irq_enable; -+ u32 ctrl0_irq_lnp; -+ u32 ctrl0_irq_status; -+ u32 fw_access_port_ofs; -+}; -+ -+struct ipu6_isys_internal_tpg_pdata { -+ u32 ntpgs; -+ u32 *offsets; -+ u32 *sels; -+}; -+ -+struct ipu6_hw_variants { -+ unsigned long offset; -+ u32 nr_mmus; -+ struct ipu6_mmu_hw mmu_hw[IPU6_MMU_MAX_DEVICES]; -+ u8 cdc_fifos; -+ u8 cdc_fifo_threshold[IPU6_MAX_VC_IOSF_PORTS]; -+ u32 dmem_offset; -+ u32 spc_offset; -+}; -+ -+struct ipu6_isys_internal_pdata { -+ struct ipu6_isys_internal_csi2_pdata csi2; -+ struct ipu6_hw_variants hw_variant; -+ u32 num_parallel_streams; -+ u32 isys_dma_overshoot; -+ u32 sram_gran_shift; -+ u32 sram_gran_size; -+ u32 max_sram_size; -+ u32 max_streams; -+ u32 max_send_queues; -+ u32 max_sram_blocks; -+ u32 max_devq_size; -+ u32 sensor_type_start; -+ u32 sensor_type_end; -+ u32 ltr; -+ u32 memopen_threshold; -+ bool enhanced_iwake; -+}; -+ -+struct ipu6_isys_pdata { -+ void __iomem *base; -+ const struct ipu6_isys_internal_pdata *ipdata; -+}; -+ -+struct ipu6_psys_internal_pdata { -+ struct ipu6_hw_variants hw_variant; -+}; -+ -+struct ipu6_psys_pdata { -+ void __iomem *base; -+ const struct ipu6_psys_internal_pdata *ipdata; -+}; -+ -+int ipu6_fw_authenticate(void *data, u64 val); -+void ipu6_configure_spc(struct ipu6_device *isp, -+ const struct ipu6_hw_variants *hw_variant, -+ int pkg_dir_idx, void __iomem *base, u64 *pkg_dir, -+ dma_addr_t pkg_dir_dma_addr); -+#endif /* IPU6_H */ --- -2.43.2 - - -From f52c1b80222269f99d52b0af5937995e22c9ed6d Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:16 +0800 -Subject: [PATCH 09/33] media: intel/ipu6: add IPU auxiliary devices - -Even the IPU input system and processing system are in a single PCI -device, each system has its own power sequence, the processing system -power up depends on the input system power up. - -Besides, input system and processing system have their own MMU -hardware for IPU DMA address mapping. - -Register the IS/PS devices on auxiliary bus and attach power domain -to implement the power sequence dependency. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - drivers/media/pci/intel/ipu6/ipu6-bus.c | 165 ++++++++++++++++++++++++ - drivers/media/pci/intel/ipu6/ipu6-bus.h | 58 +++++++++ - 2 files changed, 223 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-bus.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-bus.h - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-bus.c b/drivers/media/pci/intel/ipu6/ipu6-bus.c -new file mode 100644 -index 000000000000..e81b9a6518a1 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-bus.c -@@ -0,0 +1,165 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/auxiliary_bus.h> -+#include <linux/device.h> -+#include <linux/dma-mapping.h> -+#include <linux/err.h> -+#include <linux/list.h> -+#include <linux/mutex.h> -+#include <linux/pci.h> -+#include <linux/pm_domain.h> -+#include <linux/pm_runtime.h> -+#include <linux/slab.h> -+ -+#include "ipu6.h" -+#include "ipu6-bus.h" -+#include "ipu6-buttress.h" -+#include "ipu6-dma.h" -+ -+static int bus_pm_runtime_suspend(struct device *dev) -+{ -+ struct ipu6_bus_device *adev = to_ipu6_bus_device(dev); -+ int ret; -+ -+ ret = pm_generic_runtime_suspend(dev); -+ if (ret) -+ return ret; -+ -+ ret = ipu6_buttress_power(dev, adev->ctrl, false); -+ if (!ret) -+ return 0; -+ -+ dev_err(dev, "power down failed!\n"); -+ -+ /* Powering down failed, attempt to resume device now */ -+ ret = pm_generic_runtime_resume(dev); -+ if (!ret) -+ return -EBUSY; -+ -+ return -EIO; -+} -+ -+static int bus_pm_runtime_resume(struct device *dev) -+{ -+ struct ipu6_bus_device *adev = to_ipu6_bus_device(dev); -+ int ret; -+ -+ ret = ipu6_buttress_power(dev, adev->ctrl, true); -+ if (ret) -+ return ret; -+ -+ ret = pm_generic_runtime_resume(dev); -+ if (ret) -+ goto out_err; -+ -+ return 0; -+ -+out_err: -+ ipu6_buttress_power(dev, adev->ctrl, false); -+ -+ return -EBUSY; -+} -+ -+static struct dev_pm_domain ipu6_bus_pm_domain = { -+ .ops = { -+ .runtime_suspend = bus_pm_runtime_suspend, -+ .runtime_resume = bus_pm_runtime_resume, -+ }, -+}; -+ -+static DEFINE_MUTEX(ipu6_bus_mutex); -+ -+static void ipu6_bus_release(struct device *dev) -+{ -+ struct ipu6_bus_device *adev = to_ipu6_bus_device(dev); -+ -+ kfree(adev->pdata); -+ kfree(adev); -+} -+ -+struct ipu6_bus_device * -+ipu6_bus_initialize_device(struct pci_dev *pdev, struct device *parent, -+ void *pdata, struct ipu6_buttress_ctrl *ctrl, -+ char *name) -+{ -+ struct auxiliary_device *auxdev; -+ struct ipu6_bus_device *adev; -+ struct ipu6_device *isp = pci_get_drvdata(pdev); -+ int ret; -+ -+ adev = kzalloc(sizeof(*adev), GFP_KERNEL); -+ if (!adev) -+ return ERR_PTR(-ENOMEM); -+ -+ adev->dma_mask = DMA_BIT_MASK(isp->secure_mode ? IPU6_MMU_ADDR_BITS : -+ IPU6_MMU_ADDR_BITS_NON_SECURE); -+ adev->isp = isp; -+ adev->ctrl = ctrl; -+ adev->pdata = pdata; -+ auxdev = &adev->auxdev; -+ auxdev->name = name; -+ auxdev->id = (pci_domain_nr(pdev->bus) << 16) | -+ PCI_DEVID(pdev->bus->number, pdev->devfn); -+ -+ auxdev->dev.parent = parent; -+ auxdev->dev.release = ipu6_bus_release; -+ auxdev->dev.dma_ops = &ipu6_dma_ops; -+ auxdev->dev.dma_mask = &adev->dma_mask; -+ auxdev->dev.dma_parms = pdev->dev.dma_parms; -+ auxdev->dev.coherent_dma_mask = adev->dma_mask; -+ -+ ret = auxiliary_device_init(auxdev); -+ if (ret < 0) { -+ dev_err(&isp->pdev->dev, "auxiliary device init failed (%d)\n", -+ ret); -+ kfree(adev); -+ return ERR_PTR(ret); -+ } -+ -+ dev_pm_domain_set(&auxdev->dev, &ipu6_bus_pm_domain); -+ -+ pm_runtime_forbid(&adev->auxdev.dev); -+ pm_runtime_enable(&adev->auxdev.dev); -+ -+ return adev; -+} -+ -+int ipu6_bus_add_device(struct ipu6_bus_device *adev) -+{ -+ struct auxiliary_device *auxdev = &adev->auxdev; -+ int ret; -+ -+ ret = auxiliary_device_add(auxdev); -+ if (ret) { -+ auxiliary_device_uninit(auxdev); -+ return ret; -+ } -+ -+ mutex_lock(&ipu6_bus_mutex); -+ list_add(&adev->list, &adev->isp->devices); -+ mutex_unlock(&ipu6_bus_mutex); -+ -+ pm_runtime_allow(&auxdev->dev); -+ -+ return 0; -+} -+ -+void ipu6_bus_del_devices(struct pci_dev *pdev) -+{ -+ struct ipu6_device *isp = pci_get_drvdata(pdev); -+ struct ipu6_bus_device *adev, *save; -+ -+ mutex_lock(&ipu6_bus_mutex); -+ -+ list_for_each_entry_safe(adev, save, &isp->devices, list) { -+ pm_runtime_disable(&adev->auxdev.dev); -+ list_del(&adev->list); -+ auxiliary_device_delete(&adev->auxdev); -+ auxiliary_device_uninit(&adev->auxdev); -+ } -+ -+ mutex_unlock(&ipu6_bus_mutex); -+} -diff --git a/drivers/media/pci/intel/ipu6/ipu6-bus.h b/drivers/media/pci/intel/ipu6/ipu6-bus.h -new file mode 100644 -index 000000000000..d46181354836 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-bus.h -@@ -0,0 +1,58 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_BUS_H -+#define IPU6_BUS_H -+ -+#include <linux/auxiliary_bus.h> -+#include <linux/container_of.h> -+#include <linux/device.h> -+#include <linux/irqreturn.h> -+#include <linux/list.h> -+#include <linux/scatterlist.h> -+#include <linux/types.h> -+ -+struct firmware; -+struct pci_dev; -+ -+#define IPU6_BUS_NAME IPU6_NAME "-bus" -+ -+struct ipu6_buttress_ctrl; -+ -+struct ipu6_bus_device { -+ struct auxiliary_device auxdev; -+ struct auxiliary_driver *auxdrv; -+ const struct ipu6_auxdrv_data *auxdrv_data; -+ struct list_head list; -+ void *pdata; -+ struct ipu6_mmu *mmu; -+ struct ipu6_device *isp; -+ struct ipu6_buttress_ctrl *ctrl; -+ u64 dma_mask; -+ const struct firmware *fw; -+ struct sg_table fw_sgt; -+ u64 *pkg_dir; -+ dma_addr_t pkg_dir_dma_addr; -+ unsigned int pkg_dir_size; -+}; -+ -+struct ipu6_auxdrv_data { -+ irqreturn_t (*isr)(struct ipu6_bus_device *adev); -+ irqreturn_t (*isr_threaded)(struct ipu6_bus_device *adev); -+ bool wake_isr_thread; -+}; -+ -+#define to_ipu6_bus_device(_dev) \ -+ container_of(to_auxiliary_dev(_dev), struct ipu6_bus_device, auxdev) -+#define auxdev_to_adev(_auxdev) \ -+ container_of(_auxdev, struct ipu6_bus_device, auxdev) -+#define ipu6_bus_get_drvdata(adev) dev_get_drvdata(&(adev)->auxdev.dev) -+ -+struct ipu6_bus_device * -+ipu6_bus_initialize_device(struct pci_dev *pdev, struct device *parent, -+ void *pdata, struct ipu6_buttress_ctrl *ctrl, -+ char *name); -+int ipu6_bus_add_device(struct ipu6_bus_device *adev); -+void ipu6_bus_del_devices(struct pci_dev *pdev); -+ -+#endif --- -2.43.2 - - -From a74d85716ec13ff2f55997c73c9f06367174d7a6 Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:17 +0800 -Subject: [PATCH 10/33] media: intel/ipu6: add IPU6 buttress interface driver - -The IPU6 buttress is the interface between IPU device (input system -and processing system) with rest of the SoC. It contains overall IPU -hardware control registers, these control registers are used as the -interfaces with the Intel Converged Security Engine and Punit to do -firmware authentication and power management. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - drivers/media/pci/intel/ipu6/ipu6-buttress.c | 912 ++++++++++++++++++ - drivers/media/pci/intel/ipu6/ipu6-buttress.h | 102 ++ - .../intel/ipu6/ipu6-platform-buttress-regs.h | 232 +++++ - 3 files changed, 1246 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-buttress.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-buttress.h - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.c b/drivers/media/pci/intel/ipu6/ipu6-buttress.c -new file mode 100644 -index 000000000000..2f73302812f3 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.c -@@ -0,0 +1,912 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/bitfield.h> -+#include <linux/bits.h> -+#include <linux/completion.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <linux/dma-mapping.h> -+#include <linux/firmware.h> -+#include <linux/interrupt.h> -+#include <linux/iopoll.h> -+#include <linux/math64.h> -+#include <linux/mm.h> -+#include <linux/mutex.h> -+#include <linux/pci.h> -+#include <linux/pfn.h> -+#include <linux/pm_runtime.h> -+#include <linux/scatterlist.h> -+#include <linux/slab.h> -+#include <linux/time64.h> -+ -+#include "ipu6.h" -+#include "ipu6-bus.h" -+#include "ipu6-buttress.h" -+#include "ipu6-platform-buttress-regs.h" -+ -+#define BOOTLOADER_STATUS_OFFSET 0x15c -+ -+#define BOOTLOADER_MAGIC_KEY 0xb00710ad -+ -+#define ENTRY BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE1 -+#define EXIT BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE2 -+#define QUERY BUTTRESS_IU2CSECSR_IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE -+ -+#define BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX 10 -+ -+#define BUTTRESS_POWER_TIMEOUT_US (200 * USEC_PER_MSEC) -+ -+#define BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US (5 * USEC_PER_SEC) -+#define BUTTRESS_CSE_AUTHENTICATE_TIMEOUT_US (10 * USEC_PER_SEC) -+#define BUTTRESS_CSE_FWRESET_TIMEOUT_US (100 * USEC_PER_MSEC) -+ -+#define BUTTRESS_IPC_TX_TIMEOUT_MS MSEC_PER_SEC -+#define BUTTRESS_IPC_RX_TIMEOUT_MS MSEC_PER_SEC -+#define BUTTRESS_IPC_VALIDITY_TIMEOUT_US (1 * USEC_PER_SEC) -+#define BUTTRESS_TSC_SYNC_TIMEOUT_US (5 * USEC_PER_MSEC) -+ -+#define BUTTRESS_IPC_RESET_RETRY 2000 -+#define BUTTRESS_CSE_IPC_RESET_RETRY 4 -+#define BUTTRESS_IPC_CMD_SEND_RETRY 1 -+ -+#define BUTTRESS_MAX_CONSECUTIVE_IRQS 100 -+ -+static const u32 ipu6_adev_irq_mask[2] = { -+ BUTTRESS_ISR_IS_IRQ, -+ BUTTRESS_ISR_PS_IRQ -+}; -+ -+int ipu6_buttress_ipc_reset(struct ipu6_device *isp, -+ struct ipu6_buttress_ipc *ipc) -+{ -+ unsigned int retries = BUTTRESS_IPC_RESET_RETRY; -+ struct ipu6_buttress *b = &isp->buttress; -+ u32 val = 0, csr_in_clr; -+ -+ if (!isp->secure_mode) { -+ dev_dbg(&isp->pdev->dev, "Skip IPC reset for non-secure mode"); -+ return 0; -+ } -+ -+ mutex_lock(&b->ipc_mutex); -+ -+ /* Clear-by-1 CSR (all bits), corresponding internal states. */ -+ val = readl(isp->base + ipc->csr_in); -+ writel(val, isp->base + ipc->csr_in); -+ -+ /* Set peer CSR bit IPC_PEER_COMP_ACTIONS_RST_PHASE1 */ -+ writel(ENTRY, isp->base + ipc->csr_out); -+ /* -+ * Clear-by-1 all CSR bits EXCEPT following -+ * bits: -+ * A. IPC_PEER_COMP_ACTIONS_RST_PHASE1. -+ * B. IPC_PEER_COMP_ACTIONS_RST_PHASE2. -+ * C. Possibly custom bits, depending on -+ * their role. -+ */ -+ csr_in_clr = BUTTRESS_IU2CSECSR_IPC_PEER_DEASSERTED_REG_VALID_REQ | -+ BUTTRESS_IU2CSECSR_IPC_PEER_ACKED_REG_VALID | -+ BUTTRESS_IU2CSECSR_IPC_PEER_ASSERTED_REG_VALID_REQ | QUERY; -+ -+ do { -+ usleep_range(400, 500); -+ val = readl(isp->base + ipc->csr_in); -+ switch (val) { -+ case ENTRY | EXIT: -+ case ENTRY | EXIT | QUERY: -+ /* -+ * 1) Clear-by-1 CSR bits -+ * (IPC_PEER_COMP_ACTIONS_RST_PHASE1, -+ * IPC_PEER_COMP_ACTIONS_RST_PHASE2). -+ * 2) Set peer CSR bit -+ * IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE. -+ */ -+ writel(ENTRY | EXIT, isp->base + ipc->csr_in); -+ writel(QUERY, isp->base + ipc->csr_out); -+ break; -+ case ENTRY: -+ case ENTRY | QUERY: -+ /* -+ * 1) Clear-by-1 CSR bits -+ * (IPC_PEER_COMP_ACTIONS_RST_PHASE1, -+ * IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE). -+ * 2) Set peer CSR bit -+ * IPC_PEER_COMP_ACTIONS_RST_PHASE1. -+ */ -+ writel(ENTRY | QUERY, isp->base + ipc->csr_in); -+ writel(ENTRY, isp->base + ipc->csr_out); -+ break; -+ case EXIT: -+ case EXIT | QUERY: -+ /* -+ * Clear-by-1 CSR bit -+ * IPC_PEER_COMP_ACTIONS_RST_PHASE2. -+ * 1) Clear incoming doorbell. -+ * 2) Clear-by-1 all CSR bits EXCEPT following -+ * bits: -+ * A. IPC_PEER_COMP_ACTIONS_RST_PHASE1. -+ * B. IPC_PEER_COMP_ACTIONS_RST_PHASE2. -+ * C. Possibly custom bits, depending on -+ * their role. -+ * 3) Set peer CSR bit -+ * IPC_PEER_COMP_ACTIONS_RST_PHASE2. -+ */ -+ writel(EXIT, isp->base + ipc->csr_in); -+ writel(0, isp->base + ipc->db0_in); -+ writel(csr_in_clr, isp->base + ipc->csr_in); -+ writel(EXIT, isp->base + ipc->csr_out); -+ -+ /* -+ * Read csr_in again to make sure if RST_PHASE2 is done. -+ * If csr_in is QUERY, it should be handled again. -+ */ -+ usleep_range(200, 300); -+ val = readl(isp->base + ipc->csr_in); -+ if (val & QUERY) { -+ dev_dbg(&isp->pdev->dev, -+ "RST_PHASE2 retry csr_in = %x\n", val); -+ break; -+ } -+ mutex_unlock(&b->ipc_mutex); -+ return 0; -+ case QUERY: -+ /* -+ * 1) Clear-by-1 CSR bit -+ * IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE. -+ * 2) Set peer CSR bit -+ * IPC_PEER_COMP_ACTIONS_RST_PHASE1 -+ */ -+ writel(QUERY, isp->base + ipc->csr_in); -+ writel(ENTRY, isp->base + ipc->csr_out); -+ break; -+ default: -+ dev_warn_ratelimited(&isp->pdev->dev, -+ "Unexpected CSR 0x%x\n", val); -+ break; -+ } -+ } while (retries--); -+ -+ mutex_unlock(&b->ipc_mutex); -+ dev_err(&isp->pdev->dev, "Timed out while waiting for CSE\n"); -+ -+ return -ETIMEDOUT; -+} -+ -+static void ipu6_buttress_ipc_validity_close(struct ipu6_device *isp, -+ struct ipu6_buttress_ipc *ipc) -+{ -+ writel(BUTTRESS_IU2CSECSR_IPC_PEER_DEASSERTED_REG_VALID_REQ, -+ isp->base + ipc->csr_out); -+} -+ -+static int -+ipu6_buttress_ipc_validity_open(struct ipu6_device *isp, -+ struct ipu6_buttress_ipc *ipc) -+{ -+ unsigned int mask = BUTTRESS_IU2CSECSR_IPC_PEER_ACKED_REG_VALID; -+ void __iomem *addr; -+ int ret; -+ u32 val; -+ -+ writel(BUTTRESS_IU2CSECSR_IPC_PEER_ASSERTED_REG_VALID_REQ, -+ isp->base + ipc->csr_out); -+ -+ addr = isp->base + ipc->csr_in; -+ ret = readl_poll_timeout(addr, val, val & mask, 200, -+ BUTTRESS_IPC_VALIDITY_TIMEOUT_US); -+ if (ret) { -+ dev_err(&isp->pdev->dev, "CSE validity timeout 0x%x\n", val); -+ ipu6_buttress_ipc_validity_close(isp, ipc); -+ } -+ -+ return ret; -+} -+ -+static void ipu6_buttress_ipc_recv(struct ipu6_device *isp, -+ struct ipu6_buttress_ipc *ipc, u32 *ipc_msg) -+{ -+ if (ipc_msg) -+ *ipc_msg = readl(isp->base + ipc->data0_in); -+ writel(0, isp->base + ipc->db0_in); -+} -+ -+static int ipu6_buttress_ipc_send_bulk(struct ipu6_device *isp, -+ enum ipu6_buttress_ipc_domain ipc_domain, -+ struct ipu6_ipc_buttress_bulk_msg *msgs, -+ u32 size) -+{ -+ unsigned long tx_timeout_jiffies, rx_timeout_jiffies; -+ unsigned int i, retry = BUTTRESS_IPC_CMD_SEND_RETRY; -+ struct ipu6_buttress *b = &isp->buttress; -+ struct ipu6_buttress_ipc *ipc; -+ u32 val; -+ int ret; -+ int tout; -+ -+ ipc = ipc_domain == IPU6_BUTTRESS_IPC_CSE ? &b->cse : &b->ish; -+ -+ mutex_lock(&b->ipc_mutex); -+ -+ ret = ipu6_buttress_ipc_validity_open(isp, ipc); -+ if (ret) { -+ dev_err(&isp->pdev->dev, "IPC validity open failed\n"); -+ goto out; -+ } -+ -+ tx_timeout_jiffies = msecs_to_jiffies(BUTTRESS_IPC_TX_TIMEOUT_MS); -+ rx_timeout_jiffies = msecs_to_jiffies(BUTTRESS_IPC_RX_TIMEOUT_MS); -+ -+ for (i = 0; i < size; i++) { -+ reinit_completion(&ipc->send_complete); -+ if (msgs[i].require_resp) -+ reinit_completion(&ipc->recv_complete); -+ -+ dev_dbg(&isp->pdev->dev, "bulk IPC command: 0x%x\n", -+ msgs[i].cmd); -+ writel(msgs[i].cmd, isp->base + ipc->data0_out); -+ val = BUTTRESS_IU2CSEDB0_BUSY | msgs[i].cmd_size; -+ writel(val, isp->base + ipc->db0_out); -+ -+ tout = wait_for_completion_timeout(&ipc->send_complete, -+ tx_timeout_jiffies); -+ if (!tout) { -+ dev_err(&isp->pdev->dev, "send IPC response timeout\n"); -+ if (!retry--) { -+ ret = -ETIMEDOUT; -+ goto out; -+ } -+ -+ /* Try again if CSE is not responding on first try */ -+ writel(0, isp->base + ipc->db0_out); -+ i--; -+ continue; -+ } -+ -+ retry = BUTTRESS_IPC_CMD_SEND_RETRY; -+ -+ if (!msgs[i].require_resp) -+ continue; -+ -+ tout = wait_for_completion_timeout(&ipc->recv_complete, -+ rx_timeout_jiffies); -+ if (!tout) { -+ dev_err(&isp->pdev->dev, "recv IPC response timeout\n"); -+ ret = -ETIMEDOUT; -+ goto out; -+ } -+ -+ if (ipc->nack_mask && -+ (ipc->recv_data & ipc->nack_mask) == ipc->nack) { -+ dev_err(&isp->pdev->dev, -+ "IPC NACK for cmd 0x%x\n", msgs[i].cmd); -+ ret = -EIO; -+ goto out; -+ } -+ -+ if (ipc->recv_data != msgs[i].expected_resp) { -+ dev_err(&isp->pdev->dev, -+ "expected resp: 0x%x, IPC response: 0x%x ", -+ msgs[i].expected_resp, ipc->recv_data); -+ ret = -EIO; -+ goto out; -+ } -+ } -+ -+ dev_dbg(&isp->pdev->dev, "bulk IPC commands done\n"); -+ -+out: -+ ipu6_buttress_ipc_validity_close(isp, ipc); -+ mutex_unlock(&b->ipc_mutex); -+ return ret; -+} -+ -+static int -+ipu6_buttress_ipc_send(struct ipu6_device *isp, -+ enum ipu6_buttress_ipc_domain ipc_domain, -+ u32 ipc_msg, u32 size, bool require_resp, -+ u32 expected_resp) -+{ -+ struct ipu6_ipc_buttress_bulk_msg msg = { -+ .cmd = ipc_msg, -+ .cmd_size = size, -+ .require_resp = require_resp, -+ .expected_resp = expected_resp, -+ }; -+ -+ return ipu6_buttress_ipc_send_bulk(isp, ipc_domain, &msg, 1); -+} -+ -+static irqreturn_t ipu6_buttress_call_isr(struct ipu6_bus_device *adev) -+{ -+ irqreturn_t ret = IRQ_WAKE_THREAD; -+ -+ if (!adev || !adev->auxdrv || !adev->auxdrv_data) -+ return IRQ_NONE; -+ -+ if (adev->auxdrv_data->isr) -+ ret = adev->auxdrv_data->isr(adev); -+ -+ if (ret == IRQ_WAKE_THREAD && !adev->auxdrv_data->isr_threaded) -+ ret = IRQ_NONE; -+ -+ return ret; -+} -+ -+irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr) -+{ -+ struct ipu6_device *isp = isp_ptr; -+ struct ipu6_bus_device *adev[] = { isp->isys, isp->psys }; -+ struct ipu6_buttress *b = &isp->buttress; -+ u32 reg_irq_sts = BUTTRESS_REG_ISR_STATUS; -+ irqreturn_t ret = IRQ_NONE; -+ u32 disable_irqs = 0; -+ u32 irq_status; -+ u32 i, count = 0; -+ -+ pm_runtime_get_noresume(&isp->pdev->dev); -+ -+ irq_status = readl(isp->base + reg_irq_sts); -+ if (!irq_status) { -+ pm_runtime_put_noidle(&isp->pdev->dev); -+ return IRQ_NONE; -+ } -+ -+ do { -+ writel(irq_status, isp->base + BUTTRESS_REG_ISR_CLEAR); -+ -+ for (i = 0; i < ARRAY_SIZE(ipu6_adev_irq_mask); i++) { -+ irqreturn_t r = ipu6_buttress_call_isr(adev[i]); -+ -+ if (!(irq_status & ipu6_adev_irq_mask[i])) -+ continue; -+ -+ if (r == IRQ_WAKE_THREAD) { -+ ret = IRQ_WAKE_THREAD; -+ disable_irqs |= ipu6_adev_irq_mask[i]; -+ } else if (ret == IRQ_NONE && r == IRQ_HANDLED) { -+ ret = IRQ_HANDLED; -+ } -+ } -+ -+ if ((irq_status & BUTTRESS_EVENT) && ret == IRQ_NONE) -+ ret = IRQ_HANDLED; -+ -+ if (irq_status & BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING) { -+ dev_dbg(&isp->pdev->dev, -+ "BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING\n"); -+ ipu6_buttress_ipc_recv(isp, &b->cse, &b->cse.recv_data); -+ complete(&b->cse.recv_complete); -+ } -+ -+ if (irq_status & BUTTRESS_ISR_IPC_FROM_ISH_IS_WAITING) { -+ dev_dbg(&isp->pdev->dev, -+ "BUTTRESS_ISR_IPC_FROM_ISH_IS_WAITING\n"); -+ ipu6_buttress_ipc_recv(isp, &b->ish, &b->ish.recv_data); -+ complete(&b->ish.recv_complete); -+ } -+ -+ if (irq_status & BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE) { -+ dev_dbg(&isp->pdev->dev, -+ "BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE\n"); -+ complete(&b->cse.send_complete); -+ } -+ -+ if (irq_status & BUTTRESS_ISR_IPC_EXEC_DONE_BY_ISH) { -+ dev_dbg(&isp->pdev->dev, -+ "BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE\n"); -+ complete(&b->ish.send_complete); -+ } -+ -+ if (irq_status & BUTTRESS_ISR_SAI_VIOLATION && -+ ipu6_buttress_get_secure_mode(isp)) -+ dev_err(&isp->pdev->dev, -+ "BUTTRESS_ISR_SAI_VIOLATION\n"); -+ -+ if (irq_status & (BUTTRESS_ISR_IS_FATAL_MEM_ERR | -+ BUTTRESS_ISR_PS_FATAL_MEM_ERR)) -+ dev_err(&isp->pdev->dev, -+ "BUTTRESS_ISR_FATAL_MEM_ERR\n"); -+ -+ if (irq_status & BUTTRESS_ISR_UFI_ERROR) -+ dev_err(&isp->pdev->dev, "BUTTRESS_ISR_UFI_ERROR\n"); -+ -+ if (++count == BUTTRESS_MAX_CONSECUTIVE_IRQS) { -+ dev_err(&isp->pdev->dev, "too many consecutive IRQs\n"); -+ ret = IRQ_NONE; -+ break; -+ } -+ -+ irq_status = readl(isp->base + reg_irq_sts); -+ } while (irq_status); -+ -+ if (disable_irqs) -+ writel(BUTTRESS_IRQS & ~disable_irqs, -+ isp->base + BUTTRESS_REG_ISR_ENABLE); -+ -+ pm_runtime_put(&isp->pdev->dev); -+ -+ return ret; -+} -+ -+irqreturn_t ipu6_buttress_isr_threaded(int irq, void *isp_ptr) -+{ -+ struct ipu6_device *isp = isp_ptr; -+ struct ipu6_bus_device *adev[] = { isp->isys, isp->psys }; -+ const struct ipu6_auxdrv_data *drv_data = NULL; -+ irqreturn_t ret = IRQ_NONE; -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(ipu6_adev_irq_mask) && adev[i]; i++) { -+ drv_data = adev[i]->auxdrv_data; -+ if (!drv_data) -+ continue; -+ -+ if (drv_data->wake_isr_thread && -+ drv_data->isr_threaded(adev[i]) == IRQ_HANDLED) -+ ret = IRQ_HANDLED; -+ } -+ -+ writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_ENABLE); -+ -+ return ret; -+} -+ -+int ipu6_buttress_power(struct device *dev, struct ipu6_buttress_ctrl *ctrl, -+ bool on) -+{ -+ struct ipu6_device *isp = to_ipu6_bus_device(dev)->isp; -+ u32 pwr_sts, val; -+ int ret; -+ -+ if (!ctrl) -+ return 0; -+ -+ mutex_lock(&isp->buttress.power_mutex); -+ -+ if (!on) { -+ val = 0; -+ pwr_sts = ctrl->pwr_sts_off << ctrl->pwr_sts_shift; -+ } else { -+ val = BUTTRESS_FREQ_CTL_START | -+ FIELD_PREP(BUTTRESS_FREQ_CTL_RATIO_MASK, -+ ctrl->ratio) | -+ FIELD_PREP(BUTTRESS_FREQ_CTL_QOS_FLOOR_MASK, -+ ctrl->qos_floor) | -+ BUTTRESS_FREQ_CTL_ICCMAX_LEVEL; -+ -+ pwr_sts = ctrl->pwr_sts_on << ctrl->pwr_sts_shift; -+ } -+ -+ writel(val, isp->base + ctrl->freq_ctl); -+ -+ ret = readl_poll_timeout(isp->base + BUTTRESS_REG_PWR_STATE, -+ val, (val & ctrl->pwr_sts_mask) == pwr_sts, -+ 100, BUTTRESS_POWER_TIMEOUT_US); -+ if (ret) -+ dev_err(&isp->pdev->dev, -+ "Change power status timeout with 0x%x\n", val); -+ -+ ctrl->started = !ret && on; -+ -+ mutex_unlock(&isp->buttress.power_mutex); -+ -+ return ret; -+} -+ -+bool ipu6_buttress_get_secure_mode(struct ipu6_device *isp) -+{ -+ u32 val; -+ -+ val = readl(isp->base + BUTTRESS_REG_SECURITY_CTL); -+ -+ return val & BUTTRESS_SECURITY_CTL_FW_SECURE_MODE; -+} -+ -+bool ipu6_buttress_auth_done(struct ipu6_device *isp) -+{ -+ u32 val; -+ -+ if (!isp->secure_mode) -+ return true; -+ -+ val = readl(isp->base + BUTTRESS_REG_SECURITY_CTL); -+ val = FIELD_GET(BUTTRESS_SECURITY_CTL_FW_SETUP_MASK, val); -+ -+ return val == BUTTRESS_SECURITY_CTL_AUTH_DONE; -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_auth_done, INTEL_IPU6); -+ -+int ipu6_buttress_reset_authentication(struct ipu6_device *isp) -+{ -+ int ret; -+ u32 val; -+ -+ if (!isp->secure_mode) { -+ dev_dbg(&isp->pdev->dev, "Skip auth for non-secure mode\n"); -+ return 0; -+ } -+ -+ writel(BUTTRESS_FW_RESET_CTL_START, isp->base + -+ BUTTRESS_REG_FW_RESET_CTL); -+ -+ ret = readl_poll_timeout(isp->base + BUTTRESS_REG_FW_RESET_CTL, val, -+ val & BUTTRESS_FW_RESET_CTL_DONE, 500, -+ BUTTRESS_CSE_FWRESET_TIMEOUT_US); -+ if (ret) { -+ dev_err(&isp->pdev->dev, -+ "Time out while resetting authentication state\n"); -+ return ret; -+ } -+ -+ dev_dbg(&isp->pdev->dev, "FW reset for authentication done\n"); -+ writel(0, isp->base + BUTTRESS_REG_FW_RESET_CTL); -+ /* leave some time for HW restore */ -+ usleep_range(800, 1000); -+ -+ return 0; -+} -+ -+int ipu6_buttress_map_fw_image(struct ipu6_bus_device *sys, -+ const struct firmware *fw, struct sg_table *sgt) -+{ -+ struct page **pages; -+ const void *addr; -+ unsigned long n_pages; -+ unsigned int i; -+ int ret; -+ -+ n_pages = PHYS_PFN(PAGE_ALIGN(fw->size)); -+ -+ pages = kmalloc_array(n_pages, sizeof(*pages), GFP_KERNEL); -+ if (!pages) -+ return -ENOMEM; -+ -+ addr = fw->data; -+ for (i = 0; i < n_pages; i++) { -+ struct page *p = vmalloc_to_page(addr); -+ -+ if (!p) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ pages[i] = p; -+ addr += PAGE_SIZE; -+ } -+ -+ ret = sg_alloc_table_from_pages(sgt, pages, n_pages, 0, fw->size, -+ GFP_KERNEL); -+ if (ret) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ ret = dma_map_sgtable(&sys->auxdev.dev, sgt, DMA_TO_DEVICE, 0); -+ if (ret < 0) { -+ ret = -ENOMEM; -+ sg_free_table(sgt); -+ goto out; -+ } -+ -+ dma_sync_sgtable_for_device(&sys->auxdev.dev, sgt, DMA_TO_DEVICE); -+ -+out: -+ kfree(pages); -+ -+ return ret; -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_map_fw_image, INTEL_IPU6); -+ -+void ipu6_buttress_unmap_fw_image(struct ipu6_bus_device *sys, -+ struct sg_table *sgt) -+{ -+ dma_unmap_sgtable(&sys->auxdev.dev, sgt, DMA_TO_DEVICE, 0); -+ sg_free_table(sgt); -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_unmap_fw_image, INTEL_IPU6); -+ -+int ipu6_buttress_authenticate(struct ipu6_device *isp) -+{ -+ struct ipu6_buttress *b = &isp->buttress; -+ struct ipu6_psys_pdata *psys_pdata; -+ u32 data, mask, done, fail; -+ int ret; -+ -+ if (!isp->secure_mode) { -+ dev_dbg(&isp->pdev->dev, "Skip auth for non-secure mode\n"); -+ return 0; -+ } -+ -+ psys_pdata = isp->psys->pdata; -+ -+ mutex_lock(&b->auth_mutex); -+ -+ if (ipu6_buttress_auth_done(isp)) { -+ ret = 0; -+ goto out_unlock; -+ } -+ -+ /* -+ * Write address of FIT table to FW_SOURCE register -+ * Let's use fw address. I.e. not using FIT table yet -+ */ -+ data = lower_32_bits(isp->psys->pkg_dir_dma_addr); -+ writel(data, isp->base + BUTTRESS_REG_FW_SOURCE_BASE_LO); -+ -+ data = upper_32_bits(isp->psys->pkg_dir_dma_addr); -+ writel(data, isp->base + BUTTRESS_REG_FW_SOURCE_BASE_HI); -+ -+ /* -+ * Write boot_load into IU2CSEDATA0 -+ * Write sizeof(boot_load) | 0x2 << CLIENT_ID to -+ * IU2CSEDB.IU2CSECMD and set IU2CSEDB.IU2CSEBUSY as -+ */ -+ dev_info(&isp->pdev->dev, "Sending BOOT_LOAD to CSE\n"); -+ -+ ret = ipu6_buttress_ipc_send(isp, IPU6_BUTTRESS_IPC_CSE, -+ BUTTRESS_IU2CSEDATA0_IPC_BOOT_LOAD, -+ 1, true, -+ BUTTRESS_CSE2IUDATA0_IPC_BOOT_LOAD_DONE); -+ if (ret) { -+ dev_err(&isp->pdev->dev, "CSE boot_load failed\n"); -+ goto out_unlock; -+ } -+ -+ mask = BUTTRESS_SECURITY_CTL_FW_SETUP_MASK; -+ done = BUTTRESS_SECURITY_CTL_FW_SETUP_DONE; -+ fail = BUTTRESS_SECURITY_CTL_AUTH_FAILED; -+ ret = readl_poll_timeout(isp->base + BUTTRESS_REG_SECURITY_CTL, data, -+ ((data & mask) == done || -+ (data & mask) == fail), 500, -+ BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US); -+ if (ret) { -+ dev_err(&isp->pdev->dev, "CSE boot_load timeout\n"); -+ goto out_unlock; -+ } -+ -+ if ((data & mask) == fail) { -+ dev_err(&isp->pdev->dev, "CSE auth failed\n"); -+ ret = -EINVAL; -+ goto out_unlock; -+ } -+ -+ ret = readl_poll_timeout(psys_pdata->base + BOOTLOADER_STATUS_OFFSET, -+ data, data == BOOTLOADER_MAGIC_KEY, 500, -+ BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US); -+ if (ret) { -+ dev_err(&isp->pdev->dev, "Unexpected magic number 0x%x\n", -+ data); -+ goto out_unlock; -+ } -+ -+ /* -+ * Write authenticate_run into IU2CSEDATA0 -+ * Write sizeof(boot_load) | 0x2 << CLIENT_ID to -+ * IU2CSEDB.IU2CSECMD and set IU2CSEDB.IU2CSEBUSY as -+ */ -+ dev_info(&isp->pdev->dev, "Sending AUTHENTICATE_RUN to CSE\n"); -+ ret = ipu6_buttress_ipc_send(isp, IPU6_BUTTRESS_IPC_CSE, -+ BUTTRESS_IU2CSEDATA0_IPC_AUTH_RUN, -+ 1, true, -+ BUTTRESS_CSE2IUDATA0_IPC_AUTH_RUN_DONE); -+ if (ret) { -+ dev_err(&isp->pdev->dev, "CSE authenticate_run failed\n"); -+ goto out_unlock; -+ } -+ -+ done = BUTTRESS_SECURITY_CTL_AUTH_DONE; -+ ret = readl_poll_timeout(isp->base + BUTTRESS_REG_SECURITY_CTL, data, -+ ((data & mask) == done || -+ (data & mask) == fail), 500, -+ BUTTRESS_CSE_AUTHENTICATE_TIMEOUT_US); -+ if (ret) { -+ dev_err(&isp->pdev->dev, "CSE authenticate timeout\n"); -+ goto out_unlock; -+ } -+ -+ if ((data & mask) == fail) { -+ dev_err(&isp->pdev->dev, "CSE boot_load failed\n"); -+ ret = -EINVAL; -+ goto out_unlock; -+ } -+ -+ dev_info(&isp->pdev->dev, "CSE authenticate_run done\n"); -+ -+out_unlock: -+ mutex_unlock(&b->auth_mutex); -+ -+ return ret; -+} -+ -+static int ipu6_buttress_send_tsc_request(struct ipu6_device *isp) -+{ -+ u32 val, mask, done; -+ int ret; -+ -+ mask = BUTTRESS_PWR_STATE_HH_STATUS_MASK; -+ -+ writel(BUTTRESS_FABRIC_CMD_START_TSC_SYNC, -+ isp->base + BUTTRESS_REG_FABRIC_CMD); -+ -+ val = readl(isp->base + BUTTRESS_REG_PWR_STATE); -+ val = FIELD_GET(mask, val); -+ if (val == BUTTRESS_PWR_STATE_HH_STATE_ERR) { -+ dev_err(&isp->pdev->dev, "Start tsc sync failed\n"); -+ return -EINVAL; -+ } -+ -+ done = BUTTRESS_PWR_STATE_HH_STATE_DONE; -+ ret = readl_poll_timeout(isp->base + BUTTRESS_REG_PWR_STATE, val, -+ FIELD_GET(mask, val) == done, 500, -+ BUTTRESS_TSC_SYNC_TIMEOUT_US); -+ if (ret) -+ dev_err(&isp->pdev->dev, "Start tsc sync timeout\n"); -+ -+ return ret; -+} -+ -+int ipu6_buttress_start_tsc_sync(struct ipu6_device *isp) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX; i++) { -+ u32 val; -+ int ret; -+ -+ ret = ipu6_buttress_send_tsc_request(isp); -+ if (ret != -ETIMEDOUT) -+ return ret; -+ -+ val = readl(isp->base + BUTTRESS_REG_TSW_CTL); -+ val = val | BUTTRESS_TSW_CTL_SOFT_RESET; -+ writel(val, isp->base + BUTTRESS_REG_TSW_CTL); -+ val = val & ~BUTTRESS_TSW_CTL_SOFT_RESET; -+ writel(val, isp->base + BUTTRESS_REG_TSW_CTL); -+ } -+ -+ dev_err(&isp->pdev->dev, "TSC sync failed (timeout)\n"); -+ -+ return -ETIMEDOUT; -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_start_tsc_sync, INTEL_IPU6); -+ -+void ipu6_buttress_tsc_read(struct ipu6_device *isp, u64 *val) -+{ -+ u32 tsc_hi_1, tsc_hi_2, tsc_lo; -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ tsc_hi_1 = readl(isp->base + BUTTRESS_REG_TSC_HI); -+ tsc_lo = readl(isp->base + BUTTRESS_REG_TSC_LO); -+ tsc_hi_2 = readl(isp->base + BUTTRESS_REG_TSC_HI); -+ if (tsc_hi_1 == tsc_hi_2) { -+ *val = (u64)tsc_hi_1 << 32 | tsc_lo; -+ } else { -+ /* Check if TSC has rolled over */ -+ if (tsc_lo & BIT(31)) -+ *val = (u64)tsc_hi_1 << 32 | tsc_lo; -+ else -+ *val = (u64)tsc_hi_2 << 32 | tsc_lo; -+ } -+ local_irq_restore(flags); -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_read, INTEL_IPU6); -+ -+u64 ipu6_buttress_tsc_ticks_to_ns(u64 ticks, const struct ipu6_device *isp) -+{ -+ u64 ns = ticks * 10000; -+ -+ /* -+ * converting TSC tick count to ns is calculated by: -+ * Example (TSC clock frequency is 19.2MHz): -+ * ns = ticks * 1000 000 000 / 19.2Mhz -+ * = ticks * 1000 000 000 / 19200000Hz -+ * = ticks * 10000 / 192 ns -+ */ -+ return div_u64(ns, isp->buttress.ref_clk); -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_ticks_to_ns, INTEL_IPU6); -+ -+void ipu6_buttress_restore(struct ipu6_device *isp) -+{ -+ struct ipu6_buttress *b = &isp->buttress; -+ -+ writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_CLEAR); -+ writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_ENABLE); -+ writel(b->wdt_cached_value, isp->base + BUTTRESS_REG_WDT); -+} -+ -+int ipu6_buttress_init(struct ipu6_device *isp) -+{ -+ int ret, ipc_reset_retry = BUTTRESS_CSE_IPC_RESET_RETRY; -+ struct ipu6_buttress *b = &isp->buttress; -+ u32 val; -+ -+ mutex_init(&b->power_mutex); -+ mutex_init(&b->auth_mutex); -+ mutex_init(&b->cons_mutex); -+ mutex_init(&b->ipc_mutex); -+ init_completion(&b->ish.send_complete); -+ init_completion(&b->cse.send_complete); -+ init_completion(&b->ish.recv_complete); -+ init_completion(&b->cse.recv_complete); -+ -+ b->cse.nack = BUTTRESS_CSE2IUDATA0_IPC_NACK; -+ b->cse.nack_mask = BUTTRESS_CSE2IUDATA0_IPC_NACK_MASK; -+ b->cse.csr_in = BUTTRESS_REG_CSE2IUCSR; -+ b->cse.csr_out = BUTTRESS_REG_IU2CSECSR; -+ b->cse.db0_in = BUTTRESS_REG_CSE2IUDB0; -+ b->cse.db0_out = BUTTRESS_REG_IU2CSEDB0; -+ b->cse.data0_in = BUTTRESS_REG_CSE2IUDATA0; -+ b->cse.data0_out = BUTTRESS_REG_IU2CSEDATA0; -+ -+ /* no ISH on IPU6 */ -+ memset(&b->ish, 0, sizeof(b->ish)); -+ INIT_LIST_HEAD(&b->constraints); -+ -+ isp->secure_mode = ipu6_buttress_get_secure_mode(isp); -+ dev_info(&isp->pdev->dev, "IPU6 in %s mode touch 0x%x mask 0x%x\n", -+ isp->secure_mode ? "secure" : "non-secure", -+ readl(isp->base + BUTTRESS_REG_SECURITY_TOUCH), -+ readl(isp->base + BUTTRESS_REG_CAMERA_MASK)); -+ -+ b->wdt_cached_value = readl(isp->base + BUTTRESS_REG_WDT); -+ writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_CLEAR); -+ writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_ENABLE); -+ -+ /* get ref_clk frequency by reading the indication in btrs control */ -+ val = readl(isp->base + BUTTRESS_REG_BTRS_CTRL); -+ val = FIELD_GET(BUTTRESS_REG_BTRS_CTRL_REF_CLK_IND, val); -+ -+ switch (val) { -+ case 0x0: -+ b->ref_clk = 240; -+ break; -+ case 0x1: -+ b->ref_clk = 192; -+ break; -+ case 0x2: -+ b->ref_clk = 384; -+ break; -+ default: -+ dev_warn(&isp->pdev->dev, -+ "Unsupported ref clock, use 19.2Mhz by default.\n"); -+ b->ref_clk = 192; -+ break; -+ } -+ -+ /* Retry couple of times in case of CSE initialization is delayed */ -+ do { -+ ret = ipu6_buttress_ipc_reset(isp, &b->cse); -+ if (ret) { -+ dev_warn(&isp->pdev->dev, -+ "IPC reset protocol failed, retrying\n"); -+ } else { -+ dev_dbg(&isp->pdev->dev, "IPC reset done\n"); -+ return 0; -+ } -+ } while (ipc_reset_retry--); -+ -+ dev_err(&isp->pdev->dev, "IPC reset protocol failed\n"); -+ -+ mutex_destroy(&b->power_mutex); -+ mutex_destroy(&b->auth_mutex); -+ mutex_destroy(&b->cons_mutex); -+ mutex_destroy(&b->ipc_mutex); -+ -+ return ret; -+} -+ -+void ipu6_buttress_exit(struct ipu6_device *isp) -+{ -+ struct ipu6_buttress *b = &isp->buttress; -+ -+ writel(0, isp->base + BUTTRESS_REG_ISR_ENABLE); -+ -+ mutex_destroy(&b->power_mutex); -+ mutex_destroy(&b->auth_mutex); -+ mutex_destroy(&b->cons_mutex); -+ mutex_destroy(&b->ipc_mutex); -+} -diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.h b/drivers/media/pci/intel/ipu6/ipu6-buttress.h -new file mode 100644 -index 000000000000..558e1d70f4af ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.h -@@ -0,0 +1,102 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_BUTTRESS_H -+#define IPU6_BUTTRESS_H -+ -+#include <linux/completion.h> -+#include <linux/irqreturn.h> -+#include <linux/list.h> -+#include <linux/mutex.h> -+ -+struct device; -+struct firmware; -+struct ipu6_device; -+struct ipu6_bus_device; -+ -+#define BUTTRESS_PS_FREQ_STEP 25U -+#define BUTTRESS_MIN_FORCE_PS_FREQ (BUTTRESS_PS_FREQ_STEP * 8) -+#define BUTTRESS_MAX_FORCE_PS_FREQ (BUTTRESS_PS_FREQ_STEP * 32) -+ -+#define BUTTRESS_IS_FREQ_STEP 25U -+#define BUTTRESS_MIN_FORCE_IS_FREQ (BUTTRESS_IS_FREQ_STEP * 8) -+#define BUTTRESS_MAX_FORCE_IS_FREQ (BUTTRESS_IS_FREQ_STEP * 22) -+ -+struct ipu6_buttress_ctrl { -+ u32 freq_ctl, pwr_sts_shift, pwr_sts_mask, pwr_sts_on, pwr_sts_off; -+ unsigned int ratio; -+ unsigned int qos_floor; -+ bool started; -+}; -+ -+struct ipu6_buttress_ipc { -+ struct completion send_complete; -+ struct completion recv_complete; -+ u32 nack; -+ u32 nack_mask; -+ u32 recv_data; -+ u32 csr_out; -+ u32 csr_in; -+ u32 db0_in; -+ u32 db0_out; -+ u32 data0_out; -+ u32 data0_in; -+}; -+ -+struct ipu6_buttress { -+ struct mutex power_mutex, auth_mutex, cons_mutex, ipc_mutex; -+ struct ipu6_buttress_ipc cse; -+ struct ipu6_buttress_ipc ish; -+ struct list_head constraints; -+ u32 wdt_cached_value; -+ bool force_suspend; -+ u32 ref_clk; -+}; -+ -+struct ipu6_buttress_sensor_clk_freq { -+ unsigned int rate; -+ unsigned int val; -+}; -+ -+enum ipu6_buttress_ipc_domain { -+ IPU6_BUTTRESS_IPC_CSE, -+ IPU6_BUTTRESS_IPC_ISH, -+}; -+ -+struct ipu6_buttress_constraint { -+ struct list_head list; -+ unsigned int min_freq; -+}; -+ -+struct ipu6_ipc_buttress_bulk_msg { -+ u32 cmd; -+ u32 expected_resp; -+ bool require_resp; -+ u8 cmd_size; -+}; -+ -+int ipu6_buttress_ipc_reset(struct ipu6_device *isp, -+ struct ipu6_buttress_ipc *ipc); -+int ipu6_buttress_map_fw_image(struct ipu6_bus_device *sys, -+ const struct firmware *fw, -+ struct sg_table *sgt); -+void ipu6_buttress_unmap_fw_image(struct ipu6_bus_device *sys, -+ struct sg_table *sgt); -+int ipu6_buttress_power(struct device *dev, struct ipu6_buttress_ctrl *ctrl, -+ bool on); -+bool ipu6_buttress_get_secure_mode(struct ipu6_device *isp); -+int ipu6_buttress_authenticate(struct ipu6_device *isp); -+int ipu6_buttress_reset_authentication(struct ipu6_device *isp); -+bool ipu6_buttress_auth_done(struct ipu6_device *isp); -+int ipu6_buttress_start_tsc_sync(struct ipu6_device *isp); -+void ipu6_buttress_tsc_read(struct ipu6_device *isp, u64 *val); -+u64 ipu6_buttress_tsc_ticks_to_ns(u64 ticks, const struct ipu6_device *isp); -+ -+irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr); -+irqreturn_t ipu6_buttress_isr_threaded(int irq, void *isp_ptr); -+int ipu6_buttress_init(struct ipu6_device *isp); -+void ipu6_buttress_exit(struct ipu6_device *isp); -+void ipu6_buttress_csi_port_config(struct ipu6_device *isp, -+ u32 legacy, u32 combo); -+void ipu6_buttress_restore(struct ipu6_device *isp); -+#endif /* IPU6_BUTTRESS_H */ -diff --git a/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h b/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h -new file mode 100644 -index 000000000000..87239af96502 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h -@@ -0,0 +1,232 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2023 Intel Corporation */ -+ -+#ifndef IPU6_PLATFORM_BUTTRESS_REGS_H -+#define IPU6_PLATFORM_BUTTRESS_REGS_H -+ -+#include <linux/bits.h> -+ -+/* IS_WORKPOINT_REQ */ -+#define IPU6_BUTTRESS_REG_IS_FREQ_CTL 0x34 -+/* PS_WORKPOINT_REQ */ -+#define IPU6_BUTTRESS_REG_PS_FREQ_CTL 0x38 -+ -+#define IPU6_IS_FREQ_MAX 533 -+#define IPU6_IS_FREQ_MIN 200 -+#define IPU6_PS_FREQ_MAX 450 -+#define IPU6_IS_FREQ_RATIO_BASE 25 -+#define IPU6_PS_FREQ_RATIO_BASE 25 -+ -+/* should be tuned for real silicon */ -+#define IPU6_IS_FREQ_CTL_DEFAULT_RATIO 0x08 -+#define IPU6SE_IS_FREQ_CTL_DEFAULT_RATIO 0x0a -+#define IPU6_PS_FREQ_CTL_DEFAULT_RATIO 0x0d -+ -+#define IPU6_IS_FREQ_CTL_DEFAULT_QOS_FLOOR_RATIO 0x10 -+#define IPU6_PS_FREQ_CTL_DEFAULT_QOS_FLOOR_RATIO 0x0708 -+ -+#define IPU6_BUTTRESS_PWR_STATE_IS_PWR_SHIFT 3 -+#define IPU6_BUTTRESS_PWR_STATE_IS_PWR_MASK GENMASK(4, 3) -+ -+#define IPU6_BUTTRESS_PWR_STATE_PS_PWR_SHIFT 6 -+#define IPU6_BUTTRESS_PWR_STATE_PS_PWR_MASK GENMASK(7, 6) -+ -+#define IPU6_BUTTRESS_PWR_STATE_DN_DONE 0x0 -+#define IPU6_BUTTRESS_PWR_STATE_UP_PROCESS 0x1 -+#define IPU6_BUTTRESS_PWR_STATE_DN_PROCESS 0x2 -+#define IPU6_BUTTRESS_PWR_STATE_UP_DONE 0x3 -+ -+#define IPU6_BUTTRESS_REG_FPGA_SUPPORT_0 0x270 -+#define IPU6_BUTTRESS_REG_FPGA_SUPPORT_1 0x274 -+#define IPU6_BUTTRESS_REG_FPGA_SUPPORT_2 0x278 -+#define IPU6_BUTTRESS_REG_FPGA_SUPPORT_3 0x27c -+#define IPU6_BUTTRESS_REG_FPGA_SUPPORT_4 0x280 -+#define IPU6_BUTTRESS_REG_FPGA_SUPPORT_5 0x284 -+#define IPU6_BUTTRESS_REG_FPGA_SUPPORT_6 0x288 -+#define IPU6_BUTTRESS_REG_FPGA_SUPPORT_7 0x28c -+ -+#define BUTTRESS_REG_WDT 0x8 -+#define BUTTRESS_REG_BTRS_CTRL 0xc -+#define BUTTRESS_REG_BTRS_CTRL_STALL_MODE_VC0 BIT(0) -+#define BUTTRESS_REG_BTRS_CTRL_STALL_MODE_VC1 BIT(1) -+#define BUTTRESS_REG_BTRS_CTRL_REF_CLK_IND GENMASK(9, 8) -+ -+#define BUTTRESS_REG_FW_RESET_CTL 0x30 -+#define BUTTRESS_FW_RESET_CTL_START BIT(0) -+#define BUTTRESS_FW_RESET_CTL_DONE BIT(1) -+ -+#define BUTTRESS_REG_IS_FREQ_CTL 0x34 -+#define BUTTRESS_REG_PS_FREQ_CTL 0x38 -+ -+#define BUTTRESS_FREQ_CTL_START BIT(31) -+#define BUTTRESS_FREQ_CTL_ICCMAX_LEVEL GENMASK(19, 16) -+#define BUTTRESS_FREQ_CTL_QOS_FLOOR_MASK GENMASK(15, 8) -+#define BUTTRESS_FREQ_CTL_RATIO_MASK GENMASK(7, 0) -+ -+#define BUTTRESS_REG_PWR_STATE 0x5c -+ -+#define BUTTRESS_PWR_STATE_RESET 0x0 -+#define BUTTRESS_PWR_STATE_PWR_ON_DONE 0x1 -+#define BUTTRESS_PWR_STATE_PWR_RDY 0x3 -+#define BUTTRESS_PWR_STATE_PWR_IDLE 0x4 -+ -+#define BUTTRESS_PWR_STATE_HH_STATUS_MASK GENMASK(12, 11) -+ -+enum { -+ BUTTRESS_PWR_STATE_HH_STATE_IDLE, -+ BUTTRESS_PWR_STATE_HH_STATE_IN_PRGS, -+ BUTTRESS_PWR_STATE_HH_STATE_DONE, -+ BUTTRESS_PWR_STATE_HH_STATE_ERR, -+}; -+ -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_MASK GENMASK(23, 19) -+ -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_IDLE 0x0 -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_WAIT_4_PLL_CMP 0x1 -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_WAIT_4_CLKACK 0x2 -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_WAIT_4_PG_ACK 0x3 -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_RST_ASSRT_CYCLES 0x4 -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_STOP_CLK_CYCLES1 0x5 -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_STOP_CLK_CYCLES2 0x6 -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_RST_DEASSRT_CYCLES 0x7 -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_WAIT_4_FUSE_WR_CMP 0x8 -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_BRK_POINT 0x9 -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_IS_RDY 0xa -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_HALT_HALTED 0xb -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_RST_DURATION_CNT3 0xc -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_WAIT_4_CLKACK_PD 0xd -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_PD_BRK_POINT 0xe -+#define BUTTRESS_PWR_STATE_IS_PWR_FSM_WAIT_4_PD_PG_ACK0 0xf -+ -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_MASK GENMASK(28, 24) -+ -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_IDLE 0x0 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_PU_PLL_IP_RDY 0x1 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_RO_PRE_CNT_EXH 0x2 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_PU_VGI_PWRGOOD 0x3 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_RO_POST_CNT_EXH 0x4 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WR_PLL_RATIO 0x5 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_PU_PLL_CMP 0x6 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_PU_CLKACK 0x7 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_RST_ASSRT_CYCLES 0x8 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_STOP_CLK_CYCLES1 0x9 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_STOP_CLK_CYCLES2 0xa -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_RST_DEASSRT_CYCLES 0xb -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_PU_BRK_PNT 0xc -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_FUSE_ACCPT 0xd -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_PS_PWR_UP 0xf -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_4_HALTED 0x10 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_RESET_CNT3 0x11 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_PD_CLKACK 0x12 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_PD_OFF_IND 0x13 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_DVFS_PH4 0x14 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_DVFS_PLL_CMP 0x15 -+#define BUTTRESS_PWR_STATE_PS_PWR_FSM_WAIT_DVFS_CLKACK 0x16 -+ -+#define BUTTRESS_REG_SECURITY_CTL 0x300 -+#define BUTTRESS_REG_SKU 0x314 -+#define BUTTRESS_REG_SECURITY_TOUCH 0x318 -+#define BUTTRESS_REG_CAMERA_MASK 0x84 -+ -+#define BUTTRESS_SECURITY_CTL_FW_SECURE_MODE BIT(16) -+#define BUTTRESS_SECURITY_CTL_FW_SETUP_MASK GENMASK(4, 0) -+ -+#define BUTTRESS_SECURITY_CTL_FW_SETUP_DONE BIT(0) -+#define BUTTRESS_SECURITY_CTL_AUTH_DONE BIT(1) -+#define BUTTRESS_SECURITY_CTL_AUTH_FAILED BIT(3) -+ -+#define BUTTRESS_REG_FW_SOURCE_BASE_LO 0x78 -+#define BUTTRESS_REG_FW_SOURCE_BASE_HI 0x7C -+#define BUTTRESS_REG_FW_SOURCE_SIZE 0x80 -+ -+#define BUTTRESS_REG_ISR_STATUS 0x90 -+#define BUTTRESS_REG_ISR_ENABLED_STATUS 0x94 -+#define BUTTRESS_REG_ISR_ENABLE 0x98 -+#define BUTTRESS_REG_ISR_CLEAR 0x9C -+ -+#define BUTTRESS_ISR_IS_IRQ BIT(0) -+#define BUTTRESS_ISR_PS_IRQ BIT(1) -+#define BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE BIT(2) -+#define BUTTRESS_ISR_IPC_EXEC_DONE_BY_ISH BIT(3) -+#define BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING BIT(4) -+#define BUTTRESS_ISR_IPC_FROM_ISH_IS_WAITING BIT(5) -+#define BUTTRESS_ISR_CSE_CSR_SET BIT(6) -+#define BUTTRESS_ISR_ISH_CSR_SET BIT(7) -+#define BUTTRESS_ISR_SPURIOUS_CMP BIT(8) -+#define BUTTRESS_ISR_WATCHDOG_EXPIRED BIT(9) -+#define BUTTRESS_ISR_PUNIT_2_IUNIT_IRQ BIT(10) -+#define BUTTRESS_ISR_SAI_VIOLATION BIT(11) -+#define BUTTRESS_ISR_HW_ASSERTION BIT(12) -+#define BUTTRESS_ISR_IS_CORRECTABLE_MEM_ERR BIT(13) -+#define BUTTRESS_ISR_IS_FATAL_MEM_ERR BIT(14) -+#define BUTTRESS_ISR_IS_NON_FATAL_MEM_ERR BIT(15) -+#define BUTTRESS_ISR_PS_CORRECTABLE_MEM_ERR BIT(16) -+#define BUTTRESS_ISR_PS_FATAL_MEM_ERR BIT(17) -+#define BUTTRESS_ISR_PS_NON_FATAL_MEM_ERR BIT(18) -+#define BUTTRESS_ISR_PS_FAST_THROTTLE BIT(19) -+#define BUTTRESS_ISR_UFI_ERROR BIT(20) -+ -+#define BUTTRESS_REG_IU2CSEDB0 0x100 -+ -+#define BUTTRESS_IU2CSEDB0_BUSY BIT(31) -+#define BUTTRESS_IU2CSEDB0_IPC_CLIENT_ID_VAL 2 -+ -+#define BUTTRESS_REG_IU2CSEDATA0 0x104 -+ -+#define BUTTRESS_IU2CSEDATA0_IPC_BOOT_LOAD 1 -+#define BUTTRESS_IU2CSEDATA0_IPC_AUTH_RUN 2 -+#define BUTTRESS_IU2CSEDATA0_IPC_AUTH_REPLACE 3 -+#define BUTTRESS_IU2CSEDATA0_IPC_UPDATE_SECURE_TOUCH 16 -+ -+#define BUTTRESS_CSE2IUDATA0_IPC_BOOT_LOAD_DONE BIT(0) -+#define BUTTRESS_CSE2IUDATA0_IPC_AUTH_RUN_DONE BIT(1) -+#define BUTTRESS_CSE2IUDATA0_IPC_AUTH_REPLACE_DONE BIT(2) -+#define BUTTRESS_CSE2IUDATA0_IPC_UPDATE_SECURE_TOUCH_DONE BIT(4) -+ -+#define BUTTRESS_REG_IU2CSECSR 0x108 -+ -+#define BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE1 BIT(0) -+#define BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE2 BIT(1) -+#define BUTTRESS_IU2CSECSR_IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE BIT(2) -+#define BUTTRESS_IU2CSECSR_IPC_PEER_ASSERTED_REG_VALID_REQ BIT(3) -+#define BUTTRESS_IU2CSECSR_IPC_PEER_ACKED_REG_VALID BIT(4) -+#define BUTTRESS_IU2CSECSR_IPC_PEER_DEASSERTED_REG_VALID_REQ BIT(5) -+ -+#define BUTTRESS_REG_CSE2IUDB0 0x304 -+#define BUTTRESS_REG_CSE2IUCSR 0x30C -+#define BUTTRESS_REG_CSE2IUDATA0 0x308 -+ -+/* 0x20 == NACK, 0xf == unknown command */ -+#define BUTTRESS_CSE2IUDATA0_IPC_NACK 0xf20 -+#define BUTTRESS_CSE2IUDATA0_IPC_NACK_MASK GENMASK(15, 0) -+ -+#define BUTTRESS_REG_ISH2IUCSR 0x50 -+#define BUTTRESS_REG_ISH2IUDB0 0x54 -+#define BUTTRESS_REG_ISH2IUDATA0 0x58 -+ -+#define BUTTRESS_REG_IU2ISHDB0 0x10C -+#define BUTTRESS_REG_IU2ISHDATA0 0x110 -+#define BUTTRESS_REG_IU2ISHDATA1 0x114 -+#define BUTTRESS_REG_IU2ISHCSR 0x118 -+ -+#define BUTTRESS_REG_FABRIC_CMD 0x88 -+ -+#define BUTTRESS_FABRIC_CMD_START_TSC_SYNC BIT(0) -+#define BUTTRESS_FABRIC_CMD_IS_DRAIN BIT(4) -+ -+#define BUTTRESS_REG_TSW_CTL 0x120 -+#define BUTTRESS_TSW_CTL_SOFT_RESET BIT(8) -+ -+#define BUTTRESS_REG_TSC_LO 0x164 -+#define BUTTRESS_REG_TSC_HI 0x168 -+ -+#define BUTTRESS_IRQS (BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING | \ -+ BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE | \ -+ BUTTRESS_ISR_IS_IRQ | BUTTRESS_ISR_PS_IRQ) -+ -+#define BUTTRESS_EVENT (BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING | \ -+ BUTTRESS_ISR_IPC_FROM_ISH_IS_WAITING | \ -+ BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE | \ -+ BUTTRESS_ISR_IPC_EXEC_DONE_BY_ISH | \ -+ BUTTRESS_ISR_SAI_VIOLATION) -+#endif /* IPU6_PLATFORM_BUTTRESS_REGS_H */ --- -2.43.2 - - -From 12bd5bdd53a7c829cc5cd61a6887f89ffb036f8f Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:18 +0800 -Subject: [PATCH 11/33] media: intel/ipu6: CPD parsing for get firmware - components - -For IPU6, firmware is generated and released as signed -Code Partition Directory (CPD) format file, which is aligned with -the SPI flash code partition definition. CPD format include CPD -header, manifest, metadata and module data. Driver can parse them -according to the CPD layout to acquire each component. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - drivers/media/pci/intel/ipu6/ipu6-cpd.c | 362 ++++++++++++++++++++++++ - drivers/media/pci/intel/ipu6/ipu6-cpd.h | 105 +++++++ - 2 files changed, 467 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-cpd.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-cpd.h - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-cpd.c b/drivers/media/pci/intel/ipu6/ipu6-cpd.c -new file mode 100644 -index 000000000000..b0ffd04c4cd3 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-cpd.c -@@ -0,0 +1,362 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/bitfield.h> -+#include <linux/bits.h> -+#include <linux/err.h> -+#include <linux/dma-mapping.h> -+#include <linux/gfp_types.h> -+#include <linux/math64.h> -+#include <linux/sizes.h> -+#include <linux/types.h> -+ -+#include "ipu6.h" -+#include "ipu6-bus.h" -+#include "ipu6-cpd.h" -+ -+/* 15 entries + header*/ -+#define MAX_PKG_DIR_ENT_CNT 16 -+/* 2 qword per entry/header */ -+#define PKG_DIR_ENT_LEN 2 -+/* PKG_DIR size in bytes */ -+#define PKG_DIR_SIZE ((MAX_PKG_DIR_ENT_CNT) * \ -+ (PKG_DIR_ENT_LEN) * sizeof(u64)) -+/* _IUPKDR_ */ -+#define PKG_DIR_HDR_MARK 0x5f4955504b44525fULL -+ -+/* $CPD */ -+#define CPD_HDR_MARK 0x44504324 -+ -+#define MAX_MANIFEST_SIZE (SZ_2K * sizeof(u32)) -+#define MAX_METADATA_SIZE SZ_64K -+ -+#define MAX_COMPONENT_ID 127 -+#define MAX_COMPONENT_VERSION 0xffff -+ -+#define MANIFEST_IDX 0 -+#define METADATA_IDX 1 -+#define MODULEDATA_IDX 2 -+/* -+ * PKG_DIR Entry (type == id) -+ * 63:56 55 54:48 47:32 31:24 23:0 -+ * Rsvd Rsvd Type Version Rsvd Size -+ */ -+#define PKG_DIR_SIZE_MASK GENMASK(23, 0) -+#define PKG_DIR_VERSION_MASK GENMASK(47, 32) -+#define PKG_DIR_TYPE_MASK GENMASK(54, 48) -+ -+static inline const struct ipu6_cpd_ent *ipu6_cpd_get_entry(const void *cpd, -+ u8 idx) -+{ -+ const struct ipu6_cpd_hdr *cpd_hdr = cpd; -+ const struct ipu6_cpd_ent *ent; -+ -+ ent = (const struct ipu6_cpd_ent *)((const u8 *)cpd + cpd_hdr->hdr_len); -+ return ent + idx; -+} -+ -+#define ipu6_cpd_get_manifest(cpd) ipu6_cpd_get_entry(cpd, MANIFEST_IDX) -+#define ipu6_cpd_get_metadata(cpd) ipu6_cpd_get_entry(cpd, METADATA_IDX) -+#define ipu6_cpd_get_moduledata(cpd) ipu6_cpd_get_entry(cpd, MODULEDATA_IDX) -+ -+static const struct ipu6_cpd_metadata_cmpnt_hdr * -+ipu6_cpd_metadata_get_cmpnt(struct ipu6_device *isp, const void *metadata, -+ unsigned int metadata_size, u8 idx) -+{ -+ size_t extn_size = sizeof(struct ipu6_cpd_metadata_extn); -+ size_t cmpnt_count = metadata_size - extn_size; -+ -+ cmpnt_count = div_u64(cmpnt_count, isp->cpd_metadata_cmpnt_size); -+ -+ if (idx > MAX_COMPONENT_ID || idx >= cmpnt_count) { -+ dev_err(&isp->pdev->dev, "Component index out of range (%d)\n", -+ idx); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ return metadata + extn_size + idx * isp->cpd_metadata_cmpnt_size; -+} -+ -+static u32 ipu6_cpd_metadata_cmpnt_version(struct ipu6_device *isp, -+ const void *metadata, -+ unsigned int metadata_size, u8 idx) -+{ -+ const struct ipu6_cpd_metadata_cmpnt_hdr *cmpnt; -+ -+ cmpnt = ipu6_cpd_metadata_get_cmpnt(isp, metadata, metadata_size, idx); -+ if (IS_ERR(cmpnt)) -+ return PTR_ERR(cmpnt); -+ -+ return cmpnt->ver; -+} -+ -+static int ipu6_cpd_metadata_get_cmpnt_id(struct ipu6_device *isp, -+ const void *metadata, -+ unsigned int metadata_size, u8 idx) -+{ -+ const struct ipu6_cpd_metadata_cmpnt_hdr *cmpnt; -+ -+ cmpnt = ipu6_cpd_metadata_get_cmpnt(isp, metadata, metadata_size, idx); -+ if (IS_ERR(cmpnt)) -+ return PTR_ERR(cmpnt); -+ -+ return cmpnt->id; -+} -+ -+static int ipu6_cpd_parse_module_data(struct ipu6_device *isp, -+ const void *module_data, -+ unsigned int module_data_size, -+ dma_addr_t dma_addr_module_data, -+ u64 *pkg_dir, const void *metadata, -+ unsigned int metadata_size) -+{ -+ const struct ipu6_cpd_module_data_hdr *module_data_hdr; -+ const struct ipu6_cpd_hdr *dir_hdr; -+ const struct ipu6_cpd_ent *dir_ent; -+ unsigned int i; -+ u8 len; -+ -+ if (!module_data) -+ return -EINVAL; -+ -+ module_data_hdr = module_data; -+ dir_hdr = module_data + module_data_hdr->hdr_len; -+ len = dir_hdr->hdr_len; -+ dir_ent = (const struct ipu6_cpd_ent *)(((u8 *)dir_hdr) + len); -+ -+ pkg_dir[0] = PKG_DIR_HDR_MARK; -+ /* pkg_dir entry count = component count + pkg_dir header */ -+ pkg_dir[1] = dir_hdr->ent_cnt + 1; -+ -+ for (i = 0; i < dir_hdr->ent_cnt; i++, dir_ent++) { -+ u64 *p = &pkg_dir[PKG_DIR_ENT_LEN * (1 + i)]; -+ int ver, id; -+ -+ *p++ = dma_addr_module_data + dir_ent->offset; -+ id = ipu6_cpd_metadata_get_cmpnt_id(isp, metadata, -+ metadata_size, i); -+ if (id < 0 || id > MAX_COMPONENT_ID) { -+ dev_err(&isp->pdev->dev, "Invalid CPD component id\n"); -+ return -EINVAL; -+ } -+ -+ ver = ipu6_cpd_metadata_cmpnt_version(isp, metadata, -+ metadata_size, i); -+ if (ver < 0 || ver > MAX_COMPONENT_VERSION) { -+ dev_err(&isp->pdev->dev, -+ "Invalid CPD component version\n"); -+ return -EINVAL; -+ } -+ -+ *p = FIELD_PREP(PKG_DIR_SIZE_MASK, dir_ent->len) | -+ FIELD_PREP(PKG_DIR_TYPE_MASK, id) | -+ FIELD_PREP(PKG_DIR_VERSION_MASK, ver); -+ } -+ -+ return 0; -+} -+ -+int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src) -+{ -+ dma_addr_t dma_addr_src = sg_dma_address(adev->fw_sgt.sgl); -+ const struct ipu6_cpd_ent *ent, *man_ent, *met_ent; -+ struct device *dev = &adev->auxdev.dev; -+ struct ipu6_device *isp = adev->isp; -+ unsigned int man_sz, met_sz; -+ void *pkg_dir_pos; -+ int ret; -+ -+ man_ent = ipu6_cpd_get_manifest(src); -+ man_sz = man_ent->len; -+ -+ met_ent = ipu6_cpd_get_metadata(src); -+ met_sz = met_ent->len; -+ -+ adev->pkg_dir_size = PKG_DIR_SIZE + man_sz + met_sz; -+ adev->pkg_dir = dma_alloc_attrs(dev, adev->pkg_dir_size, -+ &adev->pkg_dir_dma_addr, GFP_KERNEL, 0); -+ if (!adev->pkg_dir) -+ return -ENOMEM; -+ -+ /* -+ * pkg_dir entry/header: -+ * qword | 63:56 | 55 | 54:48 | 47:32 | 31:24 | 23:0 -+ * N Address/Offset/"_IUPKDR_" -+ * N + 1 | rsvd | rsvd | type | ver | rsvd | size -+ * -+ * We can ignore other fields that size in N + 1 qword as they -+ * are 0 anyway. Just setting size for now. -+ */ -+ -+ ent = ipu6_cpd_get_moduledata(src); -+ -+ ret = ipu6_cpd_parse_module_data(isp, src + ent->offset, -+ ent->len, dma_addr_src + ent->offset, -+ adev->pkg_dir, src + met_ent->offset, -+ met_ent->len); -+ if (ret) { -+ dev_err(&isp->pdev->dev, "Failed to parse module data\n"); -+ dma_free_attrs(dev, adev->pkg_dir_size, -+ adev->pkg_dir, adev->pkg_dir_dma_addr, 0); -+ return ret; -+ } -+ -+ /* Copy manifest after pkg_dir */ -+ pkg_dir_pos = adev->pkg_dir + PKG_DIR_ENT_LEN * MAX_PKG_DIR_ENT_CNT; -+ memcpy(pkg_dir_pos, src + man_ent->offset, man_sz); -+ -+ /* Copy metadata after manifest */ -+ pkg_dir_pos += man_sz; -+ memcpy(pkg_dir_pos, src + met_ent->offset, met_sz); -+ -+ dma_sync_single_range_for_device(dev, adev->pkg_dir_dma_addr, -+ 0, adev->pkg_dir_size, DMA_TO_DEVICE); -+ -+ return 0; -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_cpd_create_pkg_dir, INTEL_IPU6); -+ -+void ipu6_cpd_free_pkg_dir(struct ipu6_bus_device *adev) -+{ -+ dma_free_attrs(&adev->auxdev.dev, adev->pkg_dir_size, adev->pkg_dir, -+ adev->pkg_dir_dma_addr, 0); -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_cpd_free_pkg_dir, INTEL_IPU6); -+ -+static int ipu6_cpd_validate_cpd(struct ipu6_device *isp, const void *cpd, -+ unsigned long cpd_size, -+ unsigned long data_size) -+{ -+ const struct ipu6_cpd_hdr *cpd_hdr = cpd; -+ const struct ipu6_cpd_ent *ent; -+ unsigned int i; -+ u8 len; -+ -+ len = cpd_hdr->hdr_len; -+ -+ /* Ensure cpd hdr is within moduledata */ -+ if (cpd_size < len) { -+ dev_err(&isp->pdev->dev, "Invalid CPD moduledata size\n"); -+ return -EINVAL; -+ } -+ -+ /* Sanity check for CPD header */ -+ if ((cpd_size - len) / sizeof(*ent) < cpd_hdr->ent_cnt) { -+ dev_err(&isp->pdev->dev, "Invalid CPD header\n"); -+ return -EINVAL; -+ } -+ -+ /* Ensure that all entries are within moduledata */ -+ ent = (const struct ipu6_cpd_ent *)(((const u8 *)cpd_hdr) + len); -+ for (i = 0; i < cpd_hdr->ent_cnt; i++, ent++) { -+ if (data_size < ent->offset || -+ data_size - ent->offset < ent->len) { -+ dev_err(&isp->pdev->dev, "Invalid CPD entry (%d)\n", i); -+ return -EINVAL; -+ } -+ } -+ -+ return 0; -+} -+ -+static int ipu6_cpd_validate_moduledata(struct ipu6_device *isp, -+ const void *moduledata, -+ u32 moduledata_size) -+{ -+ const struct ipu6_cpd_module_data_hdr *mod_hdr = moduledata; -+ int ret; -+ -+ /* Ensure moduledata hdr is within moduledata */ -+ if (moduledata_size < sizeof(*mod_hdr) || -+ moduledata_size < mod_hdr->hdr_len) { -+ dev_err(&isp->pdev->dev, "Invalid CPD moduledata size\n"); -+ return -EINVAL; -+ } -+ -+ dev_info(&isp->pdev->dev, "FW version: %x\n", mod_hdr->fw_pkg_date); -+ ret = ipu6_cpd_validate_cpd(isp, moduledata + mod_hdr->hdr_len, -+ moduledata_size - mod_hdr->hdr_len, -+ moduledata_size); -+ if (ret) { -+ dev_err(&isp->pdev->dev, "Invalid CPD in moduledata\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int ipu6_cpd_validate_metadata(struct ipu6_device *isp, -+ const void *metadata, u32 meta_size) -+{ -+ const struct ipu6_cpd_metadata_extn *extn = metadata; -+ -+ /* Sanity check for metadata size */ -+ if (meta_size < sizeof(*extn) || meta_size > MAX_METADATA_SIZE) { -+ dev_err(&isp->pdev->dev, "Invalid CPD metadata\n"); -+ return -EINVAL; -+ } -+ -+ /* Validate extension and image types */ -+ if (extn->extn_type != IPU6_CPD_METADATA_EXTN_TYPE_IUNIT || -+ extn->img_type != IPU6_CPD_METADATA_IMAGE_TYPE_MAIN_FIRMWARE) { -+ dev_err(&isp->pdev->dev, -+ "Invalid CPD metadata descriptor img_type (%d)\n", -+ extn->img_type); -+ return -EINVAL; -+ } -+ -+ /* Validate metadata size multiple of metadata components */ -+ if ((meta_size - sizeof(*extn)) % isp->cpd_metadata_cmpnt_size) { -+ dev_err(&isp->pdev->dev, "Invalid CPD metadata size\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+int ipu6_cpd_validate_cpd_file(struct ipu6_device *isp, const void *cpd_file, -+ unsigned long cpd_file_size) -+{ -+ const struct ipu6_cpd_hdr *hdr = cpd_file; -+ const struct ipu6_cpd_ent *ent; -+ int ret; -+ -+ ret = ipu6_cpd_validate_cpd(isp, cpd_file, cpd_file_size, -+ cpd_file_size); -+ if (ret) { -+ dev_err(&isp->pdev->dev, "Invalid CPD in file\n"); -+ return ret; -+ } -+ -+ /* Check for CPD file marker */ -+ if (hdr->hdr_mark != CPD_HDR_MARK) { -+ dev_err(&isp->pdev->dev, "Invalid CPD header\n"); -+ return -EINVAL; -+ } -+ -+ /* Sanity check for manifest size */ -+ ent = ipu6_cpd_get_manifest(cpd_file); -+ if (ent->len > MAX_MANIFEST_SIZE) { -+ dev_err(&isp->pdev->dev, "Invalid CPD manifest size\n"); -+ return -EINVAL; -+ } -+ -+ /* Validate metadata */ -+ ent = ipu6_cpd_get_metadata(cpd_file); -+ ret = ipu6_cpd_validate_metadata(isp, cpd_file + ent->offset, ent->len); -+ if (ret) { -+ dev_err(&isp->pdev->dev, "Invalid CPD metadata\n"); -+ return ret; -+ } -+ -+ /* Validate moduledata */ -+ ent = ipu6_cpd_get_moduledata(cpd_file); -+ ret = ipu6_cpd_validate_moduledata(isp, cpd_file + ent->offset, -+ ent->len); -+ if (ret) -+ dev_err(&isp->pdev->dev, "Invalid CPD moduledata\n"); -+ -+ return ret; -+} -diff --git a/drivers/media/pci/intel/ipu6/ipu6-cpd.h b/drivers/media/pci/intel/ipu6/ipu6-cpd.h -new file mode 100644 -index 000000000000..37465d507386 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-cpd.h -@@ -0,0 +1,105 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2015 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_CPD_H -+#define IPU6_CPD_H -+ -+struct ipu6_device; -+struct ipu6_bus_device; -+ -+#define IPU6_CPD_SIZE_OF_FW_ARCH_VERSION 7 -+#define IPU6_CPD_SIZE_OF_SYSTEM_VERSION 11 -+#define IPU6_CPD_SIZE_OF_COMPONENT_NAME 12 -+ -+#define IPU6_CPD_METADATA_EXTN_TYPE_IUNIT 0x10 -+ -+#define IPU6_CPD_METADATA_IMAGE_TYPE_RESERVED 0 -+#define IPU6_CPD_METADATA_IMAGE_TYPE_BOOTLOADER 1 -+#define IPU6_CPD_METADATA_IMAGE_TYPE_MAIN_FIRMWARE 2 -+ -+#define IPU6_CPD_PKG_DIR_PSYS_SERVER_IDX 0 -+#define IPU6_CPD_PKG_DIR_ISYS_SERVER_IDX 1 -+ -+#define IPU6_CPD_PKG_DIR_CLIENT_PG_TYPE 3 -+ -+#define IPU6_CPD_METADATA_HASH_KEY_SIZE 48 -+#define IPU6SE_CPD_METADATA_HASH_KEY_SIZE 32 -+ -+struct ipu6_cpd_module_data_hdr { -+ u32 hdr_len; -+ u32 endian; -+ u32 fw_pkg_date; -+ u32 hive_sdk_date; -+ u32 compiler_date; -+ u32 target_platform_type; -+ u8 sys_ver[IPU6_CPD_SIZE_OF_SYSTEM_VERSION]; -+ u8 fw_arch_ver[IPU6_CPD_SIZE_OF_FW_ARCH_VERSION]; -+ u8 rsvd[2]; -+} __packed; -+ -+/* -+ * ipu6_cpd_hdr structure updated as the chksum and -+ * sub_partition_name is unused on host side -+ * CSE layout version 1.6 for IPU6SE (hdr_len = 0x10) -+ * CSE layout version 1.7 for IPU6 (hdr_len = 0x14) -+ */ -+struct ipu6_cpd_hdr { -+ u32 hdr_mark; -+ u32 ent_cnt; -+ u8 hdr_ver; -+ u8 ent_ver; -+ u8 hdr_len; -+} __packed; -+ -+struct ipu6_cpd_ent { -+ u8 name[IPU6_CPD_SIZE_OF_COMPONENT_NAME]; -+ u32 offset; -+ u32 len; -+ u8 rsvd[4]; -+} __packed; -+ -+struct ipu6_cpd_metadata_cmpnt_hdr { -+ u32 id; -+ u32 size; -+ u32 ver; -+} __packed; -+ -+struct ipu6_cpd_metadata_cmpnt { -+ struct ipu6_cpd_metadata_cmpnt_hdr hdr; -+ u8 sha2_hash[IPU6_CPD_METADATA_HASH_KEY_SIZE]; -+ u32 entry_point; -+ u32 icache_base_offs; -+ u8 attrs[16]; -+} __packed; -+ -+struct ipu6se_cpd_metadata_cmpnt { -+ struct ipu6_cpd_metadata_cmpnt_hdr hdr; -+ u8 sha2_hash[IPU6SE_CPD_METADATA_HASH_KEY_SIZE]; -+ u32 entry_point; -+ u32 icache_base_offs; -+ u8 attrs[16]; -+} __packed; -+ -+struct ipu6_cpd_metadata_extn { -+ u32 extn_type; -+ u32 len; -+ u32 img_type; -+ u8 rsvd[16]; -+} __packed; -+ -+struct ipu6_cpd_client_pkg_hdr { -+ u32 prog_list_offs; -+ u32 prog_list_size; -+ u32 prog_desc_offs; -+ u32 prog_desc_size; -+ u32 pg_manifest_offs; -+ u32 pg_manifest_size; -+ u32 prog_bin_offs; -+ u32 prog_bin_size; -+} __packed; -+ -+int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src); -+void ipu6_cpd_free_pkg_dir(struct ipu6_bus_device *adev); -+int ipu6_cpd_validate_cpd_file(struct ipu6_device *isp, const void *cpd_file, -+ unsigned long cpd_file_size); -+#endif /* IPU6_CPD_H */ --- -2.43.2 - - -From 86b4cd540a9cb10de7a521882495f5eba6cc919f Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:19 +0800 -Subject: [PATCH 12/33] media: intel/ipu6: add IPU6 DMA mapping API and MMU - table - -he Intel IPU6 has an internal microcontroller (scalar processor, SP) which -is used to execute the firmware. The SP can access IPU internal memory and -map system DRAM to its an internal 32-bit virtual address space. - -This patch adds a driver for the IPU MMU and a DMA mapping implementation -using the internal MMU. The system IOMMU may be used besides the IPU MMU. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - drivers/media/pci/intel/ipu6/ipu6-dma.c | 502 ++++++++++++++ - drivers/media/pci/intel/ipu6/ipu6-dma.h | 19 + - drivers/media/pci/intel/ipu6/ipu6-mmu.c | 845 ++++++++++++++++++++++++ - drivers/media/pci/intel/ipu6/ipu6-mmu.h | 73 ++ - 4 files changed, 1439 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-dma.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-dma.h - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-mmu.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-mmu.h - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-dma.c b/drivers/media/pci/intel/ipu6/ipu6-dma.c -new file mode 100644 -index 000000000000..3d77c6e5a45e ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-dma.c -@@ -0,0 +1,502 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/cacheflush.h> -+#include <linux/dma-mapping.h> -+#include <linux/iova.h> -+#include <linux/list.h> -+#include <linux/mm.h> -+#include <linux/vmalloc.h> -+#include <linux/scatterlist.h> -+#include <linux/slab.h> -+#include <linux/types.h> -+ -+#include "ipu6.h" -+#include "ipu6-bus.h" -+#include "ipu6-dma.h" -+#include "ipu6-mmu.h" -+ -+struct vm_info { -+ struct list_head list; -+ struct page **pages; -+ dma_addr_t ipu6_iova; -+ void *vaddr; -+ unsigned long size; -+}; -+ -+static struct vm_info *get_vm_info(struct ipu6_mmu *mmu, dma_addr_t iova) -+{ -+ struct vm_info *info, *save; -+ -+ list_for_each_entry_safe(info, save, &mmu->vma_list, list) { -+ if (iova >= info->ipu6_iova && -+ iova < (info->ipu6_iova + info->size)) -+ return info; -+ } -+ -+ return NULL; -+} -+ -+static void __dma_clear_buffer(struct page *page, size_t size, -+ unsigned long attrs) -+{ -+ void *ptr; -+ -+ if (!page) -+ return; -+ /* -+ * Ensure that the allocated pages are zeroed, and that any data -+ * lurking in the kernel direct-mapped region is invalidated. -+ */ -+ ptr = page_address(page); -+ memset(ptr, 0, size); -+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) -+ clflush_cache_range(ptr, size); -+} -+ -+static struct page **__dma_alloc_buffer(struct device *dev, size_t size, -+ gfp_t gfp, unsigned long attrs) -+{ -+ int count = PHYS_PFN(size); -+ int array_size = count * sizeof(struct page *); -+ struct page **pages; -+ int i = 0; -+ -+ pages = kvzalloc(array_size, GFP_KERNEL); -+ if (!pages) -+ return NULL; -+ -+ gfp |= __GFP_NOWARN; -+ -+ while (count) { -+ int j, order = __fls(count); -+ -+ pages[i] = alloc_pages(gfp, order); -+ while (!pages[i] && order) -+ pages[i] = alloc_pages(gfp, --order); -+ if (!pages[i]) -+ goto error; -+ -+ if (order) { -+ split_page(pages[i], order); -+ j = 1 << order; -+ while (j--) -+ pages[i + j] = pages[i] + j; -+ } -+ -+ __dma_clear_buffer(pages[i], PAGE_SIZE << order, attrs); -+ i += 1 << order; -+ count -= 1 << order; -+ } -+ -+ return pages; -+error: -+ while (i--) -+ if (pages[i]) -+ __free_pages(pages[i], 0); -+ kvfree(pages); -+ return NULL; -+} -+ -+static void __dma_free_buffer(struct device *dev, struct page **pages, -+ size_t size, unsigned long attrs) -+{ -+ int count = PHYS_PFN(size); -+ unsigned int i; -+ -+ for (i = 0; i < count && pages[i]; i++) { -+ __dma_clear_buffer(pages[i], PAGE_SIZE, attrs); -+ __free_pages(pages[i], 0); -+ } -+ -+ kvfree(pages); -+} -+ -+static void ipu6_dma_sync_single_for_cpu(struct device *dev, -+ dma_addr_t dma_handle, -+ size_t size, -+ enum dma_data_direction dir) -+{ -+ void *vaddr; -+ u32 offset; -+ struct vm_info *info; -+ struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; -+ -+ info = get_vm_info(mmu, dma_handle); -+ if (WARN_ON(!info)) -+ return; -+ -+ offset = dma_handle - info->ipu6_iova; -+ if (WARN_ON(size > (info->size - offset))) -+ return; -+ -+ vaddr = info->vaddr + offset; -+ clflush_cache_range(vaddr, size); -+} -+ -+static void ipu6_dma_sync_sg_for_cpu(struct device *dev, -+ struct scatterlist *sglist, -+ int nents, enum dma_data_direction dir) -+{ -+ struct scatterlist *sg; -+ int i; -+ -+ for_each_sg(sglist, sg, nents, i) -+ clflush_cache_range(page_to_virt(sg_page(sg)), sg->length); -+} -+ -+static void *ipu6_dma_alloc(struct device *dev, size_t size, -+ dma_addr_t *dma_handle, gfp_t gfp, -+ unsigned long attrs) -+{ -+ struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; -+ struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev; -+ dma_addr_t pci_dma_addr, ipu6_iova; -+ struct vm_info *info; -+ unsigned long count; -+ struct page **pages; -+ struct iova *iova; -+ unsigned int i; -+ int ret; -+ -+ info = kzalloc(sizeof(*info), GFP_KERNEL); -+ if (!info) -+ return NULL; -+ -+ size = PAGE_ALIGN(size); -+ count = PHYS_PFN(size); -+ -+ iova = alloc_iova(&mmu->dmap->iovad, count, -+ PHYS_PFN(dma_get_mask(dev)), 0); -+ if (!iova) -+ goto out_kfree; -+ -+ pages = __dma_alloc_buffer(dev, size, gfp, attrs); -+ if (!pages) -+ goto out_free_iova; -+ -+ dev_dbg(dev, "dma_alloc: size %zu iova low pfn %lu, high pfn %lu\n", -+ size, iova->pfn_lo, iova->pfn_hi); -+ for (i = 0; iova->pfn_lo + i <= iova->pfn_hi; i++) { -+ pci_dma_addr = dma_map_page_attrs(&pdev->dev, pages[i], 0, -+ PAGE_SIZE, DMA_BIDIRECTIONAL, -+ attrs); -+ dev_dbg(dev, "dma_alloc: mapped pci_dma_addr %pad\n", -+ &pci_dma_addr); -+ if (dma_mapping_error(&pdev->dev, pci_dma_addr)) { -+ dev_err(dev, "pci_dma_mapping for page[%d] failed", i); -+ goto out_unmap; -+ } -+ -+ ret = ipu6_mmu_map(mmu->dmap->mmu_info, -+ PFN_PHYS(iova->pfn_lo + i), pci_dma_addr, -+ PAGE_SIZE); -+ if (ret) { -+ dev_err(dev, "ipu6_mmu_map for pci_dma[%d] %pad failed", -+ i, &pci_dma_addr); -+ dma_unmap_page_attrs(&pdev->dev, pci_dma_addr, -+ PAGE_SIZE, DMA_BIDIRECTIONAL, -+ attrs); -+ goto out_unmap; -+ } -+ } -+ -+ info->vaddr = vmap(pages, count, VM_USERMAP, PAGE_KERNEL); -+ if (!info->vaddr) -+ goto out_unmap; -+ -+ *dma_handle = PFN_PHYS(iova->pfn_lo); -+ -+ info->pages = pages; -+ info->ipu6_iova = *dma_handle; -+ info->size = size; -+ list_add(&info->list, &mmu->vma_list); -+ -+ return info->vaddr; -+ -+out_unmap: -+ while (i--) { -+ ipu6_iova = PFN_PHYS(iova->pfn_lo + i); -+ pci_dma_addr = ipu6_mmu_iova_to_phys(mmu->dmap->mmu_info, -+ ipu6_iova); -+ dma_unmap_page_attrs(&pdev->dev, pci_dma_addr, PAGE_SIZE, -+ DMA_BIDIRECTIONAL, attrs); -+ -+ ipu6_mmu_unmap(mmu->dmap->mmu_info, ipu6_iova, PAGE_SIZE); -+ } -+ -+ __dma_free_buffer(dev, pages, size, attrs); -+ -+out_free_iova: -+ __free_iova(&mmu->dmap->iovad, iova); -+out_kfree: -+ kfree(info); -+ -+ return NULL; -+} -+ -+static void ipu6_dma_free(struct device *dev, size_t size, void *vaddr, -+ dma_addr_t dma_handle, -+ unsigned long attrs) -+{ -+ struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; -+ struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev; -+ struct iova *iova = find_iova(&mmu->dmap->iovad, PHYS_PFN(dma_handle)); -+ dma_addr_t pci_dma_addr, ipu6_iova; -+ struct vm_info *info; -+ struct page **pages; -+ unsigned int i; -+ -+ if (WARN_ON(!iova)) -+ return; -+ -+ info = get_vm_info(mmu, dma_handle); -+ if (WARN_ON(!info)) -+ return; -+ -+ if (WARN_ON(!info->vaddr)) -+ return; -+ -+ if (WARN_ON(!info->pages)) -+ return; -+ -+ list_del(&info->list); -+ -+ size = PAGE_ALIGN(size); -+ -+ pages = info->pages; -+ -+ vunmap(vaddr); -+ -+ for (i = 0; i < PHYS_PFN(size); i++) { -+ ipu6_iova = PFN_PHYS(iova->pfn_lo + i); -+ pci_dma_addr = ipu6_mmu_iova_to_phys(mmu->dmap->mmu_info, -+ ipu6_iova); -+ dma_unmap_page_attrs(&pdev->dev, pci_dma_addr, PAGE_SIZE, -+ DMA_BIDIRECTIONAL, attrs); -+ } -+ -+ ipu6_mmu_unmap(mmu->dmap->mmu_info, PFN_PHYS(iova->pfn_lo), -+ PFN_PHYS(iova_size(iova))); -+ -+ __dma_free_buffer(dev, pages, size, attrs); -+ -+ mmu->tlb_invalidate(mmu); -+ -+ __free_iova(&mmu->dmap->iovad, iova); -+ -+ kfree(info); -+} -+ -+static int ipu6_dma_mmap(struct device *dev, struct vm_area_struct *vma, -+ void *addr, dma_addr_t iova, size_t size, -+ unsigned long attrs) -+{ -+ struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; -+ size_t count = PHYS_PFN(PAGE_ALIGN(size)); -+ struct vm_info *info; -+ size_t i; -+ int ret; -+ -+ info = get_vm_info(mmu, iova); -+ if (!info) -+ return -EFAULT; -+ -+ if (!info->vaddr) -+ return -EFAULT; -+ -+ if (vma->vm_start & ~PAGE_MASK) -+ return -EINVAL; -+ -+ if (size > info->size) -+ return -EFAULT; -+ -+ for (i = 0; i < count; i++) { -+ ret = vm_insert_page(vma, vma->vm_start + PFN_PHYS(i), -+ info->pages[i]); -+ if (ret < 0) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void ipu6_dma_unmap_sg(struct device *dev, -+ struct scatterlist *sglist, -+ int nents, enum dma_data_direction dir, -+ unsigned long attrs) -+{ -+ struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev; -+ struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; -+ struct iova *iova = find_iova(&mmu->dmap->iovad, -+ PHYS_PFN(sg_dma_address(sglist))); -+ int i, npages, count; -+ struct scatterlist *sg; -+ dma_addr_t pci_dma_addr; -+ -+ if (!nents) -+ return; -+ -+ if (WARN_ON(!iova)) -+ return; -+ -+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) -+ ipu6_dma_sync_sg_for_cpu(dev, sglist, nents, DMA_BIDIRECTIONAL); -+ -+ /* get the nents as orig_nents given by caller */ -+ count = 0; -+ npages = iova_size(iova); -+ for_each_sg(sglist, sg, nents, i) { -+ if (sg_dma_len(sg) == 0 || -+ sg_dma_address(sg) == DMA_MAPPING_ERROR) -+ break; -+ -+ npages -= PHYS_PFN(PAGE_ALIGN(sg_dma_len(sg))); -+ count++; -+ if (npages <= 0) -+ break; -+ } -+ -+ /* -+ * Before IPU6 mmu unmap, return the pci dma address back to sg -+ * assume the nents is less than orig_nents as the least granule -+ * is 1 SZ_4K page -+ */ -+ dev_dbg(dev, "trying to unmap concatenated %u ents\n", count); -+ for_each_sg(sglist, sg, count, i) { -+ dev_dbg(dev, "ipu unmap sg[%d] %pad\n", i, &sg_dma_address(sg)); -+ pci_dma_addr = ipu6_mmu_iova_to_phys(mmu->dmap->mmu_info, -+ sg_dma_address(sg)); -+ dev_dbg(dev, "return pci_dma_addr %pad back to sg[%d]\n", -+ &pci_dma_addr, i); -+ sg_dma_address(sg) = pci_dma_addr; -+ } -+ -+ dev_dbg(dev, "ipu6_mmu_unmap low pfn %lu high pfn %lu\n", -+ iova->pfn_lo, iova->pfn_hi); -+ ipu6_mmu_unmap(mmu->dmap->mmu_info, PFN_PHYS(iova->pfn_lo), -+ PFN_PHYS(iova_size(iova))); -+ -+ mmu->tlb_invalidate(mmu); -+ -+ dma_unmap_sg_attrs(&pdev->dev, sglist, nents, dir, attrs); -+ -+ __free_iova(&mmu->dmap->iovad, iova); -+} -+ -+static int ipu6_dma_map_sg(struct device *dev, struct scatterlist *sglist, -+ int nents, enum dma_data_direction dir, -+ unsigned long attrs) -+{ -+ struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; -+ struct pci_dev *pdev = to_ipu6_bus_device(dev)->isp->pdev; -+ struct scatterlist *sg; -+ struct iova *iova; -+ size_t npages = 0; -+ unsigned long iova_addr; -+ int i, count; -+ -+ for_each_sg(sglist, sg, nents, i) { -+ if (sg->offset) { -+ dev_err(dev, "Unsupported non-zero sg[%d].offset %x\n", -+ i, sg->offset); -+ return -EFAULT; -+ } -+ } -+ -+ dev_dbg(dev, "pci_dma_map_sg trying to map %d ents\n", nents); -+ count = dma_map_sg_attrs(&pdev->dev, sglist, nents, dir, attrs); -+ if (count <= 0) { -+ dev_err(dev, "pci_dma_map_sg %d ents failed\n", nents); -+ return 0; -+ } -+ -+ dev_dbg(dev, "pci_dma_map_sg %d ents mapped\n", count); -+ -+ for_each_sg(sglist, sg, count, i) -+ npages += PHYS_PFN(PAGE_ALIGN(sg_dma_len(sg))); -+ -+ iova = alloc_iova(&mmu->dmap->iovad, npages, -+ PHYS_PFN(dma_get_mask(dev)), 0); -+ if (!iova) -+ return 0; -+ -+ dev_dbg(dev, "dmamap: iova low pfn %lu, high pfn %lu\n", iova->pfn_lo, -+ iova->pfn_hi); -+ -+ iova_addr = iova->pfn_lo; -+ for_each_sg(sglist, sg, count, i) { -+ int ret; -+ -+ dev_dbg(dev, "mapping entry %d: iova 0x%llx phy %pad size %d\n", -+ i, PFN_PHYS(iova_addr), &sg_dma_address(sg), -+ sg_dma_len(sg)); -+ -+ ret = ipu6_mmu_map(mmu->dmap->mmu_info, PFN_PHYS(iova_addr), -+ sg_dma_address(sg), -+ PAGE_ALIGN(sg_dma_len(sg))); -+ if (ret) -+ goto out_fail; -+ -+ sg_dma_address(sg) = PFN_PHYS(iova_addr); -+ -+ iova_addr += PHYS_PFN(PAGE_ALIGN(sg_dma_len(sg))); -+ } -+ -+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0) -+ ipu6_dma_sync_sg_for_cpu(dev, sglist, nents, DMA_BIDIRECTIONAL); -+ -+ return count; -+ -+out_fail: -+ ipu6_dma_unmap_sg(dev, sglist, i, dir, attrs); -+ -+ return 0; -+} -+ -+/* -+ * Create scatter-list for the already allocated DMA buffer -+ */ -+static int ipu6_dma_get_sgtable(struct device *dev, struct sg_table *sgt, -+ void *cpu_addr, dma_addr_t handle, size_t size, -+ unsigned long attrs) -+{ -+ struct ipu6_mmu *mmu = to_ipu6_bus_device(dev)->mmu; -+ struct vm_info *info; -+ int n_pages; -+ int ret = 0; -+ -+ info = get_vm_info(mmu, handle); -+ if (!info) -+ return -EFAULT; -+ -+ if (!info->vaddr) -+ return -EFAULT; -+ -+ if (WARN_ON(!info->pages)) -+ return -ENOMEM; -+ -+ n_pages = PHYS_PFN(PAGE_ALIGN(size)); -+ -+ ret = sg_alloc_table_from_pages(sgt, info->pages, n_pages, 0, size, -+ GFP_KERNEL); -+ if (ret) -+ dev_warn(dev, "IPU6 get sgt table failed\n"); -+ -+ return ret; -+} -+ -+const struct dma_map_ops ipu6_dma_ops = { -+ .alloc = ipu6_dma_alloc, -+ .free = ipu6_dma_free, -+ .mmap = ipu6_dma_mmap, -+ .map_sg = ipu6_dma_map_sg, -+ .unmap_sg = ipu6_dma_unmap_sg, -+ .sync_single_for_cpu = ipu6_dma_sync_single_for_cpu, -+ .sync_single_for_device = ipu6_dma_sync_single_for_cpu, -+ .sync_sg_for_cpu = ipu6_dma_sync_sg_for_cpu, -+ .sync_sg_for_device = ipu6_dma_sync_sg_for_cpu, -+ .get_sgtable = ipu6_dma_get_sgtable, -+}; -diff --git a/drivers/media/pci/intel/ipu6/ipu6-dma.h b/drivers/media/pci/intel/ipu6/ipu6-dma.h -new file mode 100644 -index 000000000000..c75ad2462368 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-dma.h -@@ -0,0 +1,19 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_DMA_H -+#define IPU6_DMA_H -+ -+#include <linux/dma-map-ops.h> -+#include <linux/iova.h> -+ -+struct ipu6_mmu_info; -+ -+struct ipu6_dma_mapping { -+ struct ipu6_mmu_info *mmu_info; -+ struct iova_domain iovad; -+}; -+ -+extern const struct dma_map_ops ipu6_dma_ops; -+ -+#endif /* IPU6_DMA_H */ -diff --git a/drivers/media/pci/intel/ipu6/ipu6-mmu.c b/drivers/media/pci/intel/ipu6/ipu6-mmu.c -new file mode 100644 -index 000000000000..dc16d45187a8 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-mmu.c -@@ -0,0 +1,845 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+#include <asm/barrier.h> -+ -+#include <linux/align.h> -+#include <linux/atomic.h> -+#include <linux/bitops.h> -+#include <linux/bits.h> -+#include <linux/bug.h> -+#include <linux/cacheflush.h> -+#include <linux/dma-mapping.h> -+#include <linux/err.h> -+#include <linux/gfp.h> -+#include <linux/io.h> -+#include <linux/iova.h> -+#include <linux/math.h> -+#include <linux/minmax.h> -+#include <linux/mm.h> -+#include <linux/pfn.h> -+#include <linux/slab.h> -+#include <linux/spinlock.h> -+#include <linux/types.h> -+ -+#include "ipu6.h" -+#include "ipu6-dma.h" -+#include "ipu6-mmu.h" -+#include "ipu6-platform-regs.h" -+ -+#define ISP_PAGE_SHIFT 12 -+#define ISP_PAGE_SIZE BIT(ISP_PAGE_SHIFT) -+#define ISP_PAGE_MASK (~(ISP_PAGE_SIZE - 1)) -+ -+#define ISP_L1PT_SHIFT 22 -+#define ISP_L1PT_MASK (~((1U << ISP_L1PT_SHIFT) - 1)) -+ -+#define ISP_L2PT_SHIFT 12 -+#define ISP_L2PT_MASK (~(ISP_L1PT_MASK | (~(ISP_PAGE_MASK)))) -+ -+#define ISP_L1PT_PTES 1024 -+#define ISP_L2PT_PTES 1024 -+ -+#define ISP_PADDR_SHIFT 12 -+ -+#define REG_TLB_INVALIDATE 0x0000 -+ -+#define REG_L1_PHYS 0x0004 /* 27-bit pfn */ -+#define REG_INFO 0x0008 -+ -+#define TBL_PHYS_ADDR(a) ((phys_addr_t)(a) << ISP_PADDR_SHIFT) -+ -+static void tlb_invalidate(struct ipu6_mmu *mmu) -+{ -+ unsigned long flags; -+ unsigned int i; -+ -+ spin_lock_irqsave(&mmu->ready_lock, flags); -+ if (!mmu->ready) { -+ spin_unlock_irqrestore(&mmu->ready_lock, flags); -+ return; -+ } -+ -+ for (i = 0; i < mmu->nr_mmus; i++) { -+ /* -+ * To avoid the HW bug induced dead lock in some of the IPU6 -+ * MMUs on successive invalidate calls, we need to first do a -+ * read to the page table base before writing the invalidate -+ * register. MMUs which need to implement this WA, will have -+ * the insert_read_before_invalidate flags set as true. -+ * Disregard the return value of the read. -+ */ -+ if (mmu->mmu_hw[i].insert_read_before_invalidate) -+ readl(mmu->mmu_hw[i].base + REG_L1_PHYS); -+ -+ writel(0xffffffff, mmu->mmu_hw[i].base + -+ REG_TLB_INVALIDATE); -+ /* -+ * The TLB invalidation is a "single cycle" (IOMMU clock cycles) -+ * When the actual MMIO write reaches the IPU6 TLB Invalidate -+ * register, wmb() will force the TLB invalidate out if the CPU -+ * attempts to update the IOMMU page table (or sooner). -+ */ -+ wmb(); -+ } -+ spin_unlock_irqrestore(&mmu->ready_lock, flags); -+} -+ -+#ifdef DEBUG -+static void page_table_dump(struct ipu6_mmu_info *mmu_info) -+{ -+ u32 l1_idx; -+ -+ dev_dbg(mmu_info->dev, "begin IOMMU page table dump\n"); -+ -+ for (l1_idx = 0; l1_idx < ISP_L1PT_PTES; l1_idx++) { -+ u32 l2_idx; -+ u32 iova = (phys_addr_t)l1_idx << ISP_L1PT_SHIFT; -+ -+ if (mmu_info->l1_pt[l1_idx] == mmu_info->dummy_l2_pteval) -+ continue; -+ dev_dbg(mmu_info->dev, -+ "l1 entry %u; iovas 0x%8.8x-0x%8.8x, at %pa\n", -+ l1_idx, iova, iova + ISP_PAGE_SIZE, -+ TBL_PHYS_ADDR(mmu_info->l1_pt[l1_idx])); -+ -+ for (l2_idx = 0; l2_idx < ISP_L2PT_PTES; l2_idx++) { -+ u32 *l2_pt = mmu_info->l2_pts[l1_idx]; -+ u32 iova2 = iova + (l2_idx << ISP_L2PT_SHIFT); -+ -+ if (l2_pt[l2_idx] == mmu_info->dummy_page_pteval) -+ continue; -+ -+ dev_dbg(mmu_info->dev, -+ "\tl2 entry %u; iova 0x%8.8x, phys %pa\n", -+ l2_idx, iova2, -+ TBL_PHYS_ADDR(l2_pt[l2_idx])); -+ } -+ } -+ -+ dev_dbg(mmu_info->dev, "end IOMMU page table dump\n"); -+} -+#endif /* DEBUG */ -+ -+static dma_addr_t map_single(struct ipu6_mmu_info *mmu_info, void *ptr) -+{ -+ dma_addr_t dma; -+ -+ dma = dma_map_single(mmu_info->dev, ptr, PAGE_SIZE, DMA_BIDIRECTIONAL); -+ if (dma_mapping_error(mmu_info->dev, dma)) -+ return 0; -+ -+ return dma; -+} -+ -+static int get_dummy_page(struct ipu6_mmu_info *mmu_info) -+{ -+ void *pt = (void *)get_zeroed_page(GFP_ATOMIC | GFP_DMA32); -+ dma_addr_t dma; -+ -+ if (!pt) -+ return -ENOMEM; -+ -+ dev_dbg(mmu_info->dev, "dummy_page: get_zeroed_page() == %p\n", pt); -+ -+ dma = map_single(mmu_info, pt); -+ if (!dma) { -+ dev_err(mmu_info->dev, "Failed to map dummy page\n"); -+ goto err_free_page; -+ } -+ -+ mmu_info->dummy_page = pt; -+ mmu_info->dummy_page_pteval = dma >> ISP_PAGE_SHIFT; -+ -+ return 0; -+ -+err_free_page: -+ free_page((unsigned long)pt); -+ return -ENOMEM; -+} -+ -+static void free_dummy_page(struct ipu6_mmu_info *mmu_info) -+{ -+ dma_unmap_single(mmu_info->dev, -+ TBL_PHYS_ADDR(mmu_info->dummy_page_pteval), -+ PAGE_SIZE, DMA_BIDIRECTIONAL); -+ free_page((unsigned long)mmu_info->dummy_page); -+} -+ -+static int alloc_dummy_l2_pt(struct ipu6_mmu_info *mmu_info) -+{ -+ u32 *pt = (u32 *)get_zeroed_page(GFP_ATOMIC | GFP_DMA32); -+ dma_addr_t dma; -+ unsigned int i; -+ -+ if (!pt) -+ return -ENOMEM; -+ -+ dev_dbg(mmu_info->dev, "dummy_l2: get_zeroed_page() = %p\n", pt); -+ -+ dma = map_single(mmu_info, pt); -+ if (!dma) { -+ dev_err(mmu_info->dev, "Failed to map l2pt page\n"); -+ goto err_free_page; -+ } -+ -+ for (i = 0; i < ISP_L2PT_PTES; i++) -+ pt[i] = mmu_info->dummy_page_pteval; -+ -+ mmu_info->dummy_l2_pt = pt; -+ mmu_info->dummy_l2_pteval = dma >> ISP_PAGE_SHIFT; -+ -+ return 0; -+ -+err_free_page: -+ free_page((unsigned long)pt); -+ return -ENOMEM; -+} -+ -+static void free_dummy_l2_pt(struct ipu6_mmu_info *mmu_info) -+{ -+ dma_unmap_single(mmu_info->dev, -+ TBL_PHYS_ADDR(mmu_info->dummy_l2_pteval), -+ PAGE_SIZE, DMA_BIDIRECTIONAL); -+ free_page((unsigned long)mmu_info->dummy_l2_pt); -+} -+ -+static u32 *alloc_l1_pt(struct ipu6_mmu_info *mmu_info) -+{ -+ u32 *pt = (u32 *)get_zeroed_page(GFP_ATOMIC | GFP_DMA32); -+ dma_addr_t dma; -+ unsigned int i; -+ -+ if (!pt) -+ return NULL; -+ -+ dev_dbg(mmu_info->dev, "alloc_l1: get_zeroed_page() = %p\n", pt); -+ -+ for (i = 0; i < ISP_L1PT_PTES; i++) -+ pt[i] = mmu_info->dummy_l2_pteval; -+ -+ dma = map_single(mmu_info, pt); -+ if (!dma) { -+ dev_err(mmu_info->dev, "Failed to map l1pt page\n"); -+ goto err_free_page; -+ } -+ -+ mmu_info->l1_pt_dma = dma >> ISP_PADDR_SHIFT; -+ dev_dbg(mmu_info->dev, "l1 pt %p mapped at %llx\n", pt, dma); -+ -+ return pt; -+ -+err_free_page: -+ free_page((unsigned long)pt); -+ return NULL; -+} -+ -+static u32 *alloc_l2_pt(struct ipu6_mmu_info *mmu_info) -+{ -+ u32 *pt = (u32 *)get_zeroed_page(GFP_ATOMIC | GFP_DMA32); -+ unsigned int i; -+ -+ if (!pt) -+ return NULL; -+ -+ dev_dbg(mmu_info->dev, "alloc_l2: get_zeroed_page() = %p\n", pt); -+ -+ for (i = 0; i < ISP_L1PT_PTES; i++) -+ pt[i] = mmu_info->dummy_page_pteval; -+ -+ return pt; -+} -+ -+static int l2_map(struct ipu6_mmu_info *mmu_info, unsigned long iova, -+ phys_addr_t paddr, size_t size) -+{ -+ u32 l1_idx = iova >> ISP_L1PT_SHIFT; -+ u32 iova_start = iova; -+ u32 *l2_pt, *l2_virt; -+ unsigned int l2_idx; -+ unsigned long flags; -+ dma_addr_t dma; -+ u32 l1_entry; -+ -+ dev_dbg(mmu_info->dev, -+ "mapping l2 page table for l1 index %u (iova %8.8x)\n", -+ l1_idx, (u32)iova); -+ -+ spin_lock_irqsave(&mmu_info->lock, flags); -+ l1_entry = mmu_info->l1_pt[l1_idx]; -+ if (l1_entry == mmu_info->dummy_l2_pteval) { -+ l2_virt = mmu_info->l2_pts[l1_idx]; -+ if (likely(!l2_virt)) { -+ l2_virt = alloc_l2_pt(mmu_info); -+ if (!l2_virt) { -+ spin_unlock_irqrestore(&mmu_info->lock, flags); -+ return -ENOMEM; -+ } -+ } -+ -+ dma = map_single(mmu_info, l2_virt); -+ if (!dma) { -+ dev_err(mmu_info->dev, "Failed to map l2pt page\n"); -+ free_page((unsigned long)l2_virt); -+ spin_unlock_irqrestore(&mmu_info->lock, flags); -+ return -EINVAL; -+ } -+ -+ l1_entry = dma >> ISP_PADDR_SHIFT; -+ -+ dev_dbg(mmu_info->dev, "page for l1_idx %u %p allocated\n", -+ l1_idx, l2_virt); -+ mmu_info->l1_pt[l1_idx] = l1_entry; -+ mmu_info->l2_pts[l1_idx] = l2_virt; -+ clflush_cache_range((void *)&mmu_info->l1_pt[l1_idx], -+ sizeof(mmu_info->l1_pt[l1_idx])); -+ } -+ -+ l2_pt = mmu_info->l2_pts[l1_idx]; -+ -+ dev_dbg(mmu_info->dev, "l2_pt at %p with dma 0x%x\n", l2_pt, l1_entry); -+ -+ paddr = ALIGN(paddr, ISP_PAGE_SIZE); -+ -+ l2_idx = (iova_start & ISP_L2PT_MASK) >> ISP_L2PT_SHIFT; -+ -+ dev_dbg(mmu_info->dev, "l2_idx %u, phys 0x%8.8x\n", l2_idx, -+ l2_pt[l2_idx]); -+ if (l2_pt[l2_idx] != mmu_info->dummy_page_pteval) { -+ spin_unlock_irqrestore(&mmu_info->lock, flags); -+ return -EINVAL; -+ } -+ -+ l2_pt[l2_idx] = paddr >> ISP_PADDR_SHIFT; -+ -+ clflush_cache_range((void *)&l2_pt[l2_idx], sizeof(l2_pt[l2_idx])); -+ spin_unlock_irqrestore(&mmu_info->lock, flags); -+ -+ dev_dbg(mmu_info->dev, "l2 index %u mapped as 0x%8.8x\n", l2_idx, -+ l2_pt[l2_idx]); -+ -+ return 0; -+} -+ -+static int __ipu6_mmu_map(struct ipu6_mmu_info *mmu_info, unsigned long iova, -+ phys_addr_t paddr, size_t size) -+{ -+ u32 iova_start = round_down(iova, ISP_PAGE_SIZE); -+ u32 iova_end = ALIGN(iova + size, ISP_PAGE_SIZE); -+ -+ dev_dbg(mmu_info->dev, -+ "mapping iova 0x%8.8x--0x%8.8x, size %zu at paddr 0x%10.10llx\n", -+ iova_start, iova_end, size, paddr); -+ -+ return l2_map(mmu_info, iova_start, paddr, size); -+} -+ -+static size_t l2_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova, -+ phys_addr_t dummy, size_t size) -+{ -+ u32 l1_idx = iova >> ISP_L1PT_SHIFT; -+ u32 iova_start = iova; -+ unsigned int l2_idx; -+ size_t unmapped = 0; -+ unsigned long flags; -+ u32 *l2_pt; -+ -+ dev_dbg(mmu_info->dev, "unmapping l2 page table for l1 index %u (iova 0x%8.8lx)\n", -+ l1_idx, iova); -+ -+ spin_lock_irqsave(&mmu_info->lock, flags); -+ if (mmu_info->l1_pt[l1_idx] == mmu_info->dummy_l2_pteval) { -+ spin_unlock_irqrestore(&mmu_info->lock, flags); -+ dev_err(mmu_info->dev, -+ "unmap iova 0x%8.8lx l1 idx %u which was not mapped\n", -+ iova, l1_idx); -+ return 0; -+ } -+ -+ for (l2_idx = (iova_start & ISP_L2PT_MASK) >> ISP_L2PT_SHIFT; -+ (iova_start & ISP_L1PT_MASK) + (l2_idx << ISP_PAGE_SHIFT) -+ < iova_start + size && l2_idx < ISP_L2PT_PTES; l2_idx++) { -+ l2_pt = mmu_info->l2_pts[l1_idx]; -+ dev_dbg(mmu_info->dev, -+ "unmap l2 index %u with pteval 0x%10.10llx\n", -+ l2_idx, TBL_PHYS_ADDR(l2_pt[l2_idx])); -+ l2_pt[l2_idx] = mmu_info->dummy_page_pteval; -+ -+ clflush_cache_range((void *)&l2_pt[l2_idx], -+ sizeof(l2_pt[l2_idx])); -+ unmapped++; -+ } -+ spin_unlock_irqrestore(&mmu_info->lock, flags); -+ -+ return unmapped << ISP_PAGE_SHIFT; -+} -+ -+static size_t __ipu6_mmu_unmap(struct ipu6_mmu_info *mmu_info, -+ unsigned long iova, size_t size) -+{ -+ return l2_unmap(mmu_info, iova, 0, size); -+} -+ -+static int allocate_trash_buffer(struct ipu6_mmu *mmu) -+{ -+ unsigned int n_pages = PHYS_PFN(PAGE_ALIGN(IPU6_MMUV2_TRASH_RANGE)); -+ struct iova *iova; -+ unsigned int i; -+ dma_addr_t dma; -+ unsigned long iova_addr; -+ int ret; -+ -+ /* Allocate 8MB in iova range */ -+ iova = alloc_iova(&mmu->dmap->iovad, n_pages, -+ PHYS_PFN(mmu->dmap->mmu_info->aperture_end), 0); -+ if (!iova) { -+ dev_err(mmu->dev, "cannot allocate iova range for trash\n"); -+ return -ENOMEM; -+ } -+ -+ dma = dma_map_page(mmu->dmap->mmu_info->dev, mmu->trash_page, 0, -+ PAGE_SIZE, DMA_BIDIRECTIONAL); -+ if (dma_mapping_error(mmu->dmap->mmu_info->dev, dma)) { -+ dev_err(mmu->dmap->mmu_info->dev, "Failed to map trash page\n"); -+ ret = -ENOMEM; -+ goto out_free_iova; -+ } -+ -+ mmu->pci_trash_page = dma; -+ -+ /* -+ * Map the 8MB iova address range to the same physical trash page -+ * mmu->trash_page which is already reserved at the probe -+ */ -+ iova_addr = iova->pfn_lo; -+ for (i = 0; i < n_pages; i++) { -+ ret = ipu6_mmu_map(mmu->dmap->mmu_info, PFN_PHYS(iova_addr), -+ mmu->pci_trash_page, PAGE_SIZE); -+ if (ret) { -+ dev_err(mmu->dev, -+ "mapping trash buffer range failed\n"); -+ goto out_unmap; -+ } -+ -+ iova_addr++; -+ } -+ -+ mmu->iova_trash_page = PFN_PHYS(iova->pfn_lo); -+ dev_dbg(mmu->dev, "iova trash buffer for MMUID: %d is %u\n", -+ mmu->mmid, (unsigned int)mmu->iova_trash_page); -+ return 0; -+ -+out_unmap: -+ ipu6_mmu_unmap(mmu->dmap->mmu_info, PFN_PHYS(iova->pfn_lo), -+ PFN_PHYS(iova_size(iova))); -+ dma_unmap_page(mmu->dmap->mmu_info->dev, mmu->pci_trash_page, -+ PAGE_SIZE, DMA_BIDIRECTIONAL); -+out_free_iova: -+ __free_iova(&mmu->dmap->iovad, iova); -+ return ret; -+} -+ -+int ipu6_mmu_hw_init(struct ipu6_mmu *mmu) -+{ -+ struct ipu6_mmu_info *mmu_info; -+ unsigned long flags; -+ unsigned int i; -+ -+ mmu_info = mmu->dmap->mmu_info; -+ -+ /* Initialise the each MMU HW block */ -+ for (i = 0; i < mmu->nr_mmus; i++) { -+ struct ipu6_mmu_hw *mmu_hw = &mmu->mmu_hw[i]; -+ unsigned int j; -+ u16 block_addr; -+ -+ /* Write page table address per MMU */ -+ writel((phys_addr_t)mmu_info->l1_pt_dma, -+ mmu->mmu_hw[i].base + REG_L1_PHYS); -+ -+ /* Set info bits per MMU */ -+ writel(mmu->mmu_hw[i].info_bits, -+ mmu->mmu_hw[i].base + REG_INFO); -+ -+ /* Configure MMU TLB stream configuration for L1 */ -+ for (j = 0, block_addr = 0; j < mmu_hw->nr_l1streams; -+ block_addr += mmu->mmu_hw[i].l1_block_sz[j], j++) { -+ if (block_addr > IPU6_MAX_LI_BLOCK_ADDR) { -+ dev_err(mmu->dev, "invalid L1 configuration\n"); -+ return -EINVAL; -+ } -+ -+ /* Write block start address for each streams */ -+ writel(block_addr, mmu_hw->base + -+ mmu_hw->l1_stream_id_reg_offset + 4 * j); -+ } -+ -+ /* Configure MMU TLB stream configuration for L2 */ -+ for (j = 0, block_addr = 0; j < mmu_hw->nr_l2streams; -+ block_addr += mmu->mmu_hw[i].l2_block_sz[j], j++) { -+ if (block_addr > IPU6_MAX_L2_BLOCK_ADDR) { -+ dev_err(mmu->dev, "invalid L2 configuration\n"); -+ return -EINVAL; -+ } -+ -+ writel(block_addr, mmu_hw->base + -+ mmu_hw->l2_stream_id_reg_offset + 4 * j); -+ } -+ } -+ -+ if (!mmu->trash_page) { -+ int ret; -+ -+ mmu->trash_page = alloc_page(GFP_KERNEL); -+ if (!mmu->trash_page) { -+ dev_err(mmu->dev, "insufficient memory for trash buffer\n"); -+ return -ENOMEM; -+ } -+ -+ ret = allocate_trash_buffer(mmu); -+ if (ret) { -+ __free_page(mmu->trash_page); -+ mmu->trash_page = NULL; -+ dev_err(mmu->dev, "trash buffer allocation failed\n"); -+ return ret; -+ } -+ } -+ -+ spin_lock_irqsave(&mmu->ready_lock, flags); -+ mmu->ready = true; -+ spin_unlock_irqrestore(&mmu->ready_lock, flags); -+ -+ return 0; -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_init, INTEL_IPU6); -+ -+static struct ipu6_mmu_info *ipu6_mmu_alloc(struct ipu6_device *isp) -+{ -+ struct ipu6_mmu_info *mmu_info; -+ int ret; -+ -+ mmu_info = kzalloc(sizeof(*mmu_info), GFP_KERNEL); -+ if (!mmu_info) -+ return NULL; -+ -+ mmu_info->aperture_start = 0; -+ mmu_info->aperture_end = DMA_BIT_MASK(isp->secure_mode ? -+ IPU6_MMU_ADDR_BITS : -+ IPU6_MMU_ADDR_BITS_NON_SECURE); -+ mmu_info->pgsize_bitmap = SZ_4K; -+ mmu_info->dev = &isp->pdev->dev; -+ -+ ret = get_dummy_page(mmu_info); -+ if (ret) -+ goto err_free_info; -+ -+ ret = alloc_dummy_l2_pt(mmu_info); -+ if (ret) -+ goto err_free_dummy_page; -+ -+ mmu_info->l2_pts = vzalloc(ISP_L2PT_PTES * sizeof(*mmu_info->l2_pts)); -+ if (!mmu_info->l2_pts) -+ goto err_free_dummy_l2_pt; -+ -+ /* -+ * We always map the L1 page table (a single page as well as -+ * the L2 page tables). -+ */ -+ mmu_info->l1_pt = alloc_l1_pt(mmu_info); -+ if (!mmu_info->l1_pt) -+ goto err_free_l2_pts; -+ -+ spin_lock_init(&mmu_info->lock); -+ -+ dev_dbg(mmu_info->dev, "domain initialised\n"); -+ -+ return mmu_info; -+ -+err_free_l2_pts: -+ vfree(mmu_info->l2_pts); -+err_free_dummy_l2_pt: -+ free_dummy_l2_pt(mmu_info); -+err_free_dummy_page: -+ free_dummy_page(mmu_info); -+err_free_info: -+ kfree(mmu_info); -+ -+ return NULL; -+} -+ -+void ipu6_mmu_hw_cleanup(struct ipu6_mmu *mmu) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&mmu->ready_lock, flags); -+ mmu->ready = false; -+ spin_unlock_irqrestore(&mmu->ready_lock, flags); -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_cleanup, INTEL_IPU6); -+ -+static struct ipu6_dma_mapping *alloc_dma_mapping(struct ipu6_device *isp) -+{ -+ struct ipu6_dma_mapping *dmap; -+ -+ dmap = kzalloc(sizeof(*dmap), GFP_KERNEL); -+ if (!dmap) -+ return NULL; -+ -+ dmap->mmu_info = ipu6_mmu_alloc(isp); -+ if (!dmap->mmu_info) { -+ kfree(dmap); -+ return NULL; -+ } -+ -+ init_iova_domain(&dmap->iovad, SZ_4K, 1); -+ dmap->mmu_info->dmap = dmap; -+ -+ dev_dbg(&isp->pdev->dev, "alloc mapping\n"); -+ -+ iova_cache_get(); -+ -+ return dmap; -+} -+ -+phys_addr_t ipu6_mmu_iova_to_phys(struct ipu6_mmu_info *mmu_info, -+ dma_addr_t iova) -+{ -+ phys_addr_t phy_addr; -+ unsigned long flags; -+ u32 *l2_pt; -+ -+ spin_lock_irqsave(&mmu_info->lock, flags); -+ l2_pt = mmu_info->l2_pts[iova >> ISP_L1PT_SHIFT]; -+ phy_addr = (phys_addr_t)l2_pt[(iova & ISP_L2PT_MASK) >> ISP_L2PT_SHIFT]; -+ phy_addr <<= ISP_PAGE_SHIFT; -+ spin_unlock_irqrestore(&mmu_info->lock, flags); -+ -+ return phy_addr; -+} -+ -+static size_t ipu6_mmu_pgsize(unsigned long pgsize_bitmap, -+ unsigned long addr_merge, size_t size) -+{ -+ unsigned int pgsize_idx; -+ size_t pgsize; -+ -+ /* Max page size that still fits into 'size' */ -+ pgsize_idx = __fls(size); -+ -+ if (likely(addr_merge)) { -+ /* Max page size allowed by address */ -+ unsigned int align_pgsize_idx = __ffs(addr_merge); -+ -+ pgsize_idx = min(pgsize_idx, align_pgsize_idx); -+ } -+ -+ pgsize = (1UL << (pgsize_idx + 1)) - 1; -+ pgsize &= pgsize_bitmap; -+ -+ WARN_ON(!pgsize); -+ -+ /* pick the biggest page */ -+ pgsize_idx = __fls(pgsize); -+ pgsize = 1UL << pgsize_idx; -+ -+ return pgsize; -+} -+ -+size_t ipu6_mmu_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova, -+ size_t size) -+{ -+ size_t unmapped_page, unmapped = 0; -+ unsigned int min_pagesz; -+ -+ /* find out the minimum page size supported */ -+ min_pagesz = 1 << __ffs(mmu_info->pgsize_bitmap); -+ -+ /* -+ * The virtual address and the size of the mapping must be -+ * aligned (at least) to the size of the smallest page supported -+ * by the hardware -+ */ -+ if (!IS_ALIGNED(iova | size, min_pagesz)) { -+ dev_err(NULL, "unaligned: iova 0x%lx size 0x%zx min_pagesz 0x%x\n", -+ iova, size, min_pagesz); -+ return -EINVAL; -+ } -+ -+ /* -+ * Keep iterating until we either unmap 'size' bytes (or more) -+ * or we hit an area that isn't mapped. -+ */ -+ while (unmapped < size) { -+ size_t pgsize = ipu6_mmu_pgsize(mmu_info->pgsize_bitmap, -+ iova, size - unmapped); -+ -+ unmapped_page = __ipu6_mmu_unmap(mmu_info, iova, pgsize); -+ if (!unmapped_page) -+ break; -+ -+ dev_dbg(mmu_info->dev, "unmapped: iova 0x%lx size 0x%zx\n", -+ iova, unmapped_page); -+ -+ iova += unmapped_page; -+ unmapped += unmapped_page; -+ } -+ -+ return unmapped; -+} -+ -+int ipu6_mmu_map(struct ipu6_mmu_info *mmu_info, unsigned long iova, -+ phys_addr_t paddr, size_t size) -+{ -+ unsigned long orig_iova = iova; -+ unsigned int min_pagesz; -+ size_t orig_size = size; -+ int ret = 0; -+ -+ if (mmu_info->pgsize_bitmap == 0UL) -+ return -ENODEV; -+ -+ /* find out the minimum page size supported */ -+ min_pagesz = 1 << __ffs(mmu_info->pgsize_bitmap); -+ -+ /* -+ * both the virtual address and the physical one, as well as -+ * the size of the mapping, must be aligned (at least) to the -+ * size of the smallest page supported by the hardware -+ */ -+ if (!IS_ALIGNED(iova | paddr | size, min_pagesz)) { -+ dev_err(mmu_info->dev, -+ "unaligned: iova %lx pa %pa size %zx min_pagesz %x\n", -+ iova, &paddr, size, min_pagesz); -+ return -EINVAL; -+ } -+ -+ dev_dbg(mmu_info->dev, "map: iova 0x%lx pa %pa size 0x%zx\n", -+ iova, &paddr, size); -+ -+ while (size) { -+ size_t pgsize = ipu6_mmu_pgsize(mmu_info->pgsize_bitmap, -+ iova | paddr, size); -+ -+ dev_dbg(mmu_info->dev, -+ "mapping: iova 0x%lx pa %pa pgsize 0x%zx\n", -+ iova, &paddr, pgsize); -+ -+ ret = __ipu6_mmu_map(mmu_info, iova, paddr, pgsize); -+ if (ret) -+ break; -+ -+ iova += pgsize; -+ paddr += pgsize; -+ size -= pgsize; -+ } -+ -+ /* unroll mapping in case something went wrong */ -+ if (ret) -+ ipu6_mmu_unmap(mmu_info, orig_iova, orig_size - size); -+ -+ return ret; -+} -+ -+static void ipu6_mmu_destroy(struct ipu6_mmu *mmu) -+{ -+ struct ipu6_dma_mapping *dmap = mmu->dmap; -+ struct ipu6_mmu_info *mmu_info = dmap->mmu_info; -+ struct iova *iova; -+ u32 l1_idx; -+ -+ if (mmu->iova_trash_page) { -+ iova = find_iova(&dmap->iovad, PHYS_PFN(mmu->iova_trash_page)); -+ if (iova) { -+ /* unmap and free the trash buffer iova */ -+ ipu6_mmu_unmap(mmu_info, PFN_PHYS(iova->pfn_lo), -+ PFN_PHYS(iova_size(iova))); -+ __free_iova(&dmap->iovad, iova); -+ } else { -+ dev_err(mmu->dev, "trash buffer iova not found.\n"); -+ } -+ -+ mmu->iova_trash_page = 0; -+ dma_unmap_page(mmu_info->dev, mmu->pci_trash_page, -+ PAGE_SIZE, DMA_BIDIRECTIONAL); -+ mmu->pci_trash_page = 0; -+ __free_page(mmu->trash_page); -+ } -+ -+ for (l1_idx = 0; l1_idx < ISP_L1PT_PTES; l1_idx++) { -+ if (mmu_info->l1_pt[l1_idx] != mmu_info->dummy_l2_pteval) { -+ dma_unmap_single(mmu_info->dev, -+ TBL_PHYS_ADDR(mmu_info->l1_pt[l1_idx]), -+ PAGE_SIZE, DMA_BIDIRECTIONAL); -+ free_page((unsigned long)mmu_info->l2_pts[l1_idx]); -+ } -+ } -+ -+ vfree(mmu_info->l2_pts); -+ free_dummy_page(mmu_info); -+ dma_unmap_single(mmu_info->dev, TBL_PHYS_ADDR(mmu_info->l1_pt_dma), -+ PAGE_SIZE, DMA_BIDIRECTIONAL); -+ free_page((unsigned long)mmu_info->dummy_l2_pt); -+ free_page((unsigned long)mmu_info->l1_pt); -+ kfree(mmu_info); -+} -+ -+struct ipu6_mmu *ipu6_mmu_init(struct device *dev, -+ void __iomem *base, int mmid, -+ const struct ipu6_hw_variants *hw) -+{ -+ struct ipu6_device *isp = pci_get_drvdata(to_pci_dev(dev)); -+ struct ipu6_mmu_pdata *pdata; -+ struct ipu6_mmu *mmu; -+ unsigned int i; -+ -+ if (hw->nr_mmus > IPU6_MMU_MAX_DEVICES) -+ return ERR_PTR(-EINVAL); -+ -+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); -+ if (!pdata) -+ return ERR_PTR(-ENOMEM); -+ -+ for (i = 0; i < hw->nr_mmus; i++) { -+ struct ipu6_mmu_hw *pdata_mmu = &pdata->mmu_hw[i]; -+ const struct ipu6_mmu_hw *src_mmu = &hw->mmu_hw[i]; -+ -+ if (src_mmu->nr_l1streams > IPU6_MMU_MAX_TLB_L1_STREAMS || -+ src_mmu->nr_l2streams > IPU6_MMU_MAX_TLB_L2_STREAMS) -+ return ERR_PTR(-EINVAL); -+ -+ *pdata_mmu = *src_mmu; -+ pdata_mmu->base = base + src_mmu->offset; -+ } -+ -+ mmu = devm_kzalloc(dev, sizeof(*mmu), GFP_KERNEL); -+ if (!mmu) -+ return ERR_PTR(-ENOMEM); -+ -+ mmu->mmid = mmid; -+ mmu->mmu_hw = pdata->mmu_hw; -+ mmu->nr_mmus = hw->nr_mmus; -+ mmu->tlb_invalidate = tlb_invalidate; -+ mmu->ready = false; -+ INIT_LIST_HEAD(&mmu->vma_list); -+ spin_lock_init(&mmu->ready_lock); -+ -+ mmu->dmap = alloc_dma_mapping(isp); -+ if (!mmu->dmap) { -+ dev_err(dev, "can't alloc dma mapping\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ return mmu; -+} -+ -+void ipu6_mmu_cleanup(struct ipu6_mmu *mmu) -+{ -+ struct ipu6_dma_mapping *dmap = mmu->dmap; -+ -+ ipu6_mmu_destroy(mmu); -+ mmu->dmap = NULL; -+ iova_cache_put(); -+ put_iova_domain(&dmap->iovad); -+ kfree(dmap); -+} -diff --git a/drivers/media/pci/intel/ipu6/ipu6-mmu.h b/drivers/media/pci/intel/ipu6/ipu6-mmu.h -new file mode 100644 -index 000000000000..95df7931a2e5 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-mmu.h -@@ -0,0 +1,73 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_MMU_H -+#define IPU6_MMU_H -+ -+#define ISYS_MMID 1 -+#define PSYS_MMID 0 -+ -+#include <linux/list.h> -+#include <linux/spinlock_types.h> -+#include <linux/types.h> -+ -+struct device; -+struct page; -+struct ipu6_hw_variants; -+ -+struct ipu6_mmu_info { -+ struct device *dev; -+ -+ u32 *l1_pt; -+ u32 l1_pt_dma; -+ u32 **l2_pts; -+ -+ u32 *dummy_l2_pt; -+ u32 dummy_l2_pteval; -+ void *dummy_page; -+ u32 dummy_page_pteval; -+ -+ dma_addr_t aperture_start; -+ dma_addr_t aperture_end; -+ unsigned long pgsize_bitmap; -+ -+ spinlock_t lock; /* Serialize access to users */ -+ struct ipu6_dma_mapping *dmap; -+}; -+ -+struct ipu6_mmu { -+ struct list_head node; -+ -+ struct ipu6_mmu_hw *mmu_hw; -+ unsigned int nr_mmus; -+ unsigned int mmid; -+ -+ phys_addr_t pgtbl; -+ struct device *dev; -+ -+ struct ipu6_dma_mapping *dmap; -+ struct list_head vma_list; -+ -+ struct page *trash_page; -+ dma_addr_t pci_trash_page; /* IOVA from PCI DMA services (parent) */ -+ dma_addr_t iova_trash_page; /* IOVA for IPU6 child nodes to use */ -+ -+ bool ready; -+ spinlock_t ready_lock; /* Serialize access to bool ready */ -+ -+ void (*tlb_invalidate)(struct ipu6_mmu *mmu); -+}; -+ -+struct ipu6_mmu *ipu6_mmu_init(struct device *dev, -+ void __iomem *base, int mmid, -+ const struct ipu6_hw_variants *hw); -+void ipu6_mmu_cleanup(struct ipu6_mmu *mmu); -+int ipu6_mmu_hw_init(struct ipu6_mmu *mmu); -+void ipu6_mmu_hw_cleanup(struct ipu6_mmu *mmu); -+int ipu6_mmu_map(struct ipu6_mmu_info *mmu_info, unsigned long iova, -+ phys_addr_t paddr, size_t size); -+size_t ipu6_mmu_unmap(struct ipu6_mmu_info *mmu_info, unsigned long iova, -+ size_t size); -+phys_addr_t ipu6_mmu_iova_to_phys(struct ipu6_mmu_info *mmu_info, -+ dma_addr_t iova); -+#endif --- -2.43.2 - - -From a4363013580d8a552e8084faedbb98bd2482c057 Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:20 +0800 -Subject: [PATCH 13/33] media: intel/ipu6: add syscom interfaces between - firmware and driver - -Syscom is an inter-process(or) communication mechanism between an IPU -and host. Syscom uses message queues for message exchange between IPU -and host. Each message queue has its consumer and producer, host queue -messages to firmware as the producer and then firmware to dequeue the -messages as consumer and vice versa. IPU and host use shared registers -or memory to reside the read and write indices which are updated by -consumer and producer. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - drivers/media/pci/intel/ipu6/ipu6-fw-com.c | 413 +++++++++++++++++++++ - drivers/media/pci/intel/ipu6/ipu6-fw-com.h | 47 +++ - 2 files changed, 460 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-fw-com.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-fw-com.h - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-com.c b/drivers/media/pci/intel/ipu6/ipu6-fw-com.c -new file mode 100644 -index 000000000000..0f893f44e04c ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-com.c -@@ -0,0 +1,413 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/device.h> -+#include <linux/dma-mapping.h> -+#include <linux/io.h> -+#include <linux/math.h> -+#include <linux/overflow.h> -+#include <linux/slab.h> -+#include <linux/types.h> -+ -+#include "ipu6-bus.h" -+#include "ipu6-fw-com.h" -+ -+/* -+ * FWCOM layer is a shared resource between FW and driver. It consist -+ * of token queues to both send and receive directions. Queue is simply -+ * an array of structures with read and write indexes to the queue. -+ * There are 1...n queues to both directions. Queues locates in -+ * system RAM and are mapped to ISP MMU so that both CPU and ISP can -+ * see the same buffer. Indexes are located in ISP DMEM so that FW code -+ * can poll those with very low latency and cost. CPU access to indexes is -+ * more costly but that happens only at message sending time and -+ * interrupt triggered message handling. CPU doesn't need to poll indexes. -+ * wr_reg / rd_reg are offsets to those dmem location. They are not -+ * the indexes itself. -+ */ -+ -+/* Shared structure between driver and FW - do not modify */ -+struct ipu6_fw_sys_queue { -+ u64 host_address; -+ u32 vied_address; -+ u32 size; -+ u32 token_size; -+ u32 wr_reg; /* reg number in subsystem's regmem */ -+ u32 rd_reg; -+ u32 _align; -+} __packed; -+ -+struct ipu6_fw_sys_queue_res { -+ u64 host_address; -+ u32 vied_address; -+ u32 reg; -+} __packed; -+ -+enum syscom_state { -+ /* Program load or explicit host setting should init to this */ -+ SYSCOM_STATE_UNINIT = 0x57a7e000, -+ /* SP Syscom sets this when it is ready for use */ -+ SYSCOM_STATE_READY = 0x57a7e001, -+ /* SP Syscom sets this when no more syscom accesses will happen */ -+ SYSCOM_STATE_INACTIVE = 0x57a7e002, -+}; -+ -+enum syscom_cmd { -+ /* Program load or explicit host setting should init to this */ -+ SYSCOM_COMMAND_UNINIT = 0x57a7f000, -+ /* Host Syscom requests syscom to become inactive */ -+ SYSCOM_COMMAND_INACTIVE = 0x57a7f001, -+}; -+ -+/* firmware config: data that sent from the host to SP via DDR */ -+/* Cell copies data into a context */ -+ -+struct ipu6_fw_syscom_config { -+ u32 firmware_address; -+ -+ u32 num_input_queues; -+ u32 num_output_queues; -+ -+ /* ISP pointers to an array of ipu6_fw_sys_queue structures */ -+ u32 input_queue; -+ u32 output_queue; -+ -+ /* ISYS / PSYS private data */ -+ u32 specific_addr; -+ u32 specific_size; -+}; -+ -+struct ipu6_fw_com_context { -+ struct ipu6_bus_device *adev; -+ void __iomem *dmem_addr; -+ int (*cell_ready)(struct ipu6_bus_device *adev); -+ void (*cell_start)(struct ipu6_bus_device *adev); -+ -+ void *dma_buffer; -+ dma_addr_t dma_addr; -+ unsigned int dma_size; -+ unsigned long attrs; -+ -+ struct ipu6_fw_sys_queue *input_queue; /* array of host to SP queues */ -+ struct ipu6_fw_sys_queue *output_queue; /* array of SP to host */ -+ -+ u32 config_vied_addr; -+ -+ unsigned int buttress_boot_offset; -+ void __iomem *base_addr; -+}; -+ -+#define FW_COM_WR_REG 0 -+#define FW_COM_RD_REG 4 -+ -+#define REGMEM_OFFSET 0 -+#define TUNIT_MAGIC_PATTERN 0x5a5a5a5a -+ -+enum regmem_id { -+ /* pass pkg_dir address to SPC in non-secure mode */ -+ PKG_DIR_ADDR_REG = 0, -+ /* Tunit CFG blob for secure - provided by host.*/ -+ TUNIT_CFG_DWR_REG = 1, -+ /* syscom commands - modified by the host */ -+ SYSCOM_COMMAND_REG = 2, -+ /* Store interrupt status - updated by SP */ -+ SYSCOM_IRQ_REG = 3, -+ /* first syscom queue pointer register */ -+ SYSCOM_QPR_BASE_REG = 4 -+}; -+ -+#define BUTTRESS_FW_BOOT_PARAMS_0 0x4000 -+#define BUTTRESS_FW_BOOT_PARAM_REG(base, offset, id) \ -+ ((base) + BUTTRESS_FW_BOOT_PARAMS_0 + ((offset) + (id)) * 4) -+ -+enum buttress_syscom_id { -+ /* pass syscom configuration to SPC */ -+ SYSCOM_CONFIG_ID = 0, -+ /* syscom state - modified by SP */ -+ SYSCOM_STATE_ID = 1, -+ /* syscom vtl0 addr mask */ -+ SYSCOM_VTL0_ADDR_MASK_ID = 2, -+ SYSCOM_ID_MAX -+}; -+ -+static void ipu6_sys_queue_init(struct ipu6_fw_sys_queue *q, unsigned int size, -+ unsigned int token_size, -+ struct ipu6_fw_sys_queue_res *res) -+{ -+ unsigned int buf_size = (size + 1) * token_size; -+ -+ q->size = size + 1; -+ q->token_size = token_size; -+ -+ /* acquire the shared buffer space */ -+ q->host_address = res->host_address; -+ res->host_address += buf_size; -+ q->vied_address = res->vied_address; -+ res->vied_address += buf_size; -+ -+ /* acquire the shared read and writer pointers */ -+ q->wr_reg = res->reg; -+ res->reg++; -+ q->rd_reg = res->reg; -+ res->reg++; -+} -+ -+void *ipu6_fw_com_prepare(struct ipu6_fw_com_cfg *cfg, -+ struct ipu6_bus_device *adev, void __iomem *base) -+{ -+ size_t conf_size, inq_size, outq_size, specific_size; -+ struct ipu6_fw_syscom_config *config_host_addr; -+ unsigned int sizeinput = 0, sizeoutput = 0; -+ struct ipu6_fw_sys_queue_res res; -+ struct ipu6_fw_com_context *ctx; -+ struct device *dev = &adev->auxdev.dev; -+ size_t sizeall, offset; -+ unsigned long attrs = 0; -+ void *specific_host_addr; -+ unsigned int i; -+ -+ if (!cfg || !cfg->cell_start || !cfg->cell_ready) -+ return NULL; -+ -+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); -+ if (!ctx) -+ return NULL; -+ ctx->dmem_addr = base + cfg->dmem_addr + REGMEM_OFFSET; -+ ctx->adev = adev; -+ ctx->cell_start = cfg->cell_start; -+ ctx->cell_ready = cfg->cell_ready; -+ ctx->buttress_boot_offset = cfg->buttress_boot_offset; -+ ctx->base_addr = base; -+ -+ /* -+ * Allocate DMA mapped memory. Allocate one big chunk. -+ */ -+ /* Base cfg for FW */ -+ conf_size = roundup(sizeof(struct ipu6_fw_syscom_config), 8); -+ /* Descriptions of the queues */ -+ inq_size = size_mul(cfg->num_input_queues, -+ sizeof(struct ipu6_fw_sys_queue)); -+ outq_size = size_mul(cfg->num_output_queues, -+ sizeof(struct ipu6_fw_sys_queue)); -+ /* FW specific information structure */ -+ specific_size = roundup(cfg->specific_size, 8); -+ -+ sizeall = conf_size + inq_size + outq_size + specific_size; -+ -+ for (i = 0; i < cfg->num_input_queues; i++) -+ sizeinput += size_mul(cfg->input[i].queue_size + 1, -+ cfg->input[i].token_size); -+ -+ for (i = 0; i < cfg->num_output_queues; i++) -+ sizeoutput += size_mul(cfg->output[i].queue_size + 1, -+ cfg->output[i].token_size); -+ -+ sizeall += sizeinput + sizeoutput; -+ -+ ctx->dma_buffer = dma_alloc_attrs(dev, sizeall, &ctx->dma_addr, -+ GFP_KERNEL, attrs); -+ ctx->attrs = attrs; -+ if (!ctx->dma_buffer) { -+ dev_err(dev, "failed to allocate dma memory\n"); -+ kfree(ctx); -+ return NULL; -+ } -+ -+ ctx->dma_size = sizeall; -+ -+ config_host_addr = ctx->dma_buffer; -+ ctx->config_vied_addr = ctx->dma_addr; -+ -+ offset = conf_size; -+ ctx->input_queue = ctx->dma_buffer + offset; -+ config_host_addr->input_queue = ctx->dma_addr + offset; -+ config_host_addr->num_input_queues = cfg->num_input_queues; -+ -+ offset += inq_size; -+ ctx->output_queue = ctx->dma_buffer + offset; -+ config_host_addr->output_queue = ctx->dma_addr + offset; -+ config_host_addr->num_output_queues = cfg->num_output_queues; -+ -+ /* copy firmware specific data */ -+ offset += outq_size; -+ specific_host_addr = ctx->dma_buffer + offset; -+ config_host_addr->specific_addr = ctx->dma_addr + offset; -+ config_host_addr->specific_size = cfg->specific_size; -+ if (cfg->specific_addr && cfg->specific_size) -+ memcpy(specific_host_addr, cfg->specific_addr, -+ cfg->specific_size); -+ -+ /* initialize input queues */ -+ offset += specific_size; -+ res.reg = SYSCOM_QPR_BASE_REG; -+ res.host_address = (u64)(ctx->dma_buffer + offset); -+ res.vied_address = ctx->dma_addr + offset; -+ for (i = 0; i < cfg->num_input_queues; i++) -+ ipu6_sys_queue_init(ctx->input_queue + i, -+ cfg->input[i].queue_size, -+ cfg->input[i].token_size, &res); -+ -+ /* initialize output queues */ -+ offset += sizeinput; -+ res.host_address = (u64)(ctx->dma_buffer + offset); -+ res.vied_address = ctx->dma_addr + offset; -+ for (i = 0; i < cfg->num_output_queues; i++) { -+ ipu6_sys_queue_init(ctx->output_queue + i, -+ cfg->output[i].queue_size, -+ cfg->output[i].token_size, &res); -+ } -+ -+ return ctx; -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_prepare, INTEL_IPU6); -+ -+int ipu6_fw_com_open(struct ipu6_fw_com_context *ctx) -+{ -+ /* write magic pattern to disable the tunit trace */ -+ writel(TUNIT_MAGIC_PATTERN, ctx->dmem_addr + TUNIT_CFG_DWR_REG * 4); -+ /* Check if SP is in valid state */ -+ if (!ctx->cell_ready(ctx->adev)) -+ return -EIO; -+ -+ /* store syscom uninitialized command */ -+ writel(SYSCOM_COMMAND_UNINIT, ctx->dmem_addr + SYSCOM_COMMAND_REG * 4); -+ -+ /* store syscom uninitialized state */ -+ writel(SYSCOM_STATE_UNINIT, -+ BUTTRESS_FW_BOOT_PARAM_REG(ctx->base_addr, -+ ctx->buttress_boot_offset, -+ SYSCOM_STATE_ID)); -+ -+ /* store firmware configuration address */ -+ writel(ctx->config_vied_addr, -+ BUTTRESS_FW_BOOT_PARAM_REG(ctx->base_addr, -+ ctx->buttress_boot_offset, -+ SYSCOM_CONFIG_ID)); -+ ctx->cell_start(ctx->adev); -+ -+ return 0; -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_open, INTEL_IPU6); -+ -+int ipu6_fw_com_close(struct ipu6_fw_com_context *ctx) -+{ -+ int state; -+ -+ state = readl(BUTTRESS_FW_BOOT_PARAM_REG(ctx->base_addr, -+ ctx->buttress_boot_offset, -+ SYSCOM_STATE_ID)); -+ if (state != SYSCOM_STATE_READY) -+ return -EBUSY; -+ -+ /* set close request flag */ -+ writel(SYSCOM_COMMAND_INACTIVE, ctx->dmem_addr + -+ SYSCOM_COMMAND_REG * 4); -+ -+ return 0; -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_close, INTEL_IPU6); -+ -+int ipu6_fw_com_release(struct ipu6_fw_com_context *ctx, unsigned int force) -+{ -+ /* check if release is forced, an verify cell state if it is not */ -+ if (!force && !ctx->cell_ready(ctx->adev)) -+ return -EBUSY; -+ -+ dma_free_attrs(&ctx->adev->auxdev.dev, ctx->dma_size, -+ ctx->dma_buffer, ctx->dma_addr, ctx->attrs); -+ kfree(ctx); -+ return 0; -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_release, INTEL_IPU6); -+ -+bool ipu6_fw_com_ready(struct ipu6_fw_com_context *ctx) -+{ -+ int state; -+ -+ state = readl(BUTTRESS_FW_BOOT_PARAM_REG(ctx->base_addr, -+ ctx->buttress_boot_offset, -+ SYSCOM_STATE_ID)); -+ -+ return state == SYSCOM_STATE_READY; -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_ready, INTEL_IPU6); -+ -+void *ipu6_send_get_token(struct ipu6_fw_com_context *ctx, int q_nbr) -+{ -+ struct ipu6_fw_sys_queue *q = &ctx->input_queue[q_nbr]; -+ void __iomem *q_dmem = ctx->dmem_addr + q->wr_reg * 4; -+ unsigned int wr, rd; -+ unsigned int packets; -+ unsigned int index; -+ -+ wr = readl(q_dmem + FW_COM_WR_REG); -+ rd = readl(q_dmem + FW_COM_RD_REG); -+ -+ if (WARN_ON_ONCE(wr >= q->size || rd >= q->size)) -+ return NULL; -+ -+ if (wr < rd) -+ packets = rd - wr - 1; -+ else -+ packets = q->size - (wr - rd + 1); -+ -+ if (!packets) -+ return NULL; -+ -+ index = readl(q_dmem + FW_COM_WR_REG); -+ -+ return (void *)(q->host_address + index * q->token_size); -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_send_get_token, INTEL_IPU6); -+ -+void ipu6_send_put_token(struct ipu6_fw_com_context *ctx, int q_nbr) -+{ -+ struct ipu6_fw_sys_queue *q = &ctx->input_queue[q_nbr]; -+ void __iomem *q_dmem = ctx->dmem_addr + q->wr_reg * 4; -+ unsigned int wr = readl(q_dmem + FW_COM_WR_REG) + 1; -+ -+ if (wr >= q->size) -+ wr = 0; -+ -+ writel(wr, q_dmem + FW_COM_WR_REG); -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_send_put_token, INTEL_IPU6); -+ -+void *ipu6_recv_get_token(struct ipu6_fw_com_context *ctx, int q_nbr) -+{ -+ struct ipu6_fw_sys_queue *q = &ctx->output_queue[q_nbr]; -+ void __iomem *q_dmem = ctx->dmem_addr + q->wr_reg * 4; -+ unsigned int wr, rd; -+ unsigned int packets; -+ -+ wr = readl(q_dmem + FW_COM_WR_REG); -+ rd = readl(q_dmem + FW_COM_RD_REG); -+ -+ if (WARN_ON_ONCE(wr >= q->size || rd >= q->size)) -+ return NULL; -+ -+ if (wr < rd) -+ wr += q->size; -+ -+ packets = wr - rd; -+ if (!packets) -+ return NULL; -+ -+ return (void *)(q->host_address + rd * q->token_size); -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_recv_get_token, INTEL_IPU6); -+ -+void ipu6_recv_put_token(struct ipu6_fw_com_context *ctx, int q_nbr) -+{ -+ struct ipu6_fw_sys_queue *q = &ctx->output_queue[q_nbr]; -+ void __iomem *q_dmem = ctx->dmem_addr + q->wr_reg * 4; -+ unsigned int rd = readl(q_dmem + FW_COM_RD_REG) + 1; -+ -+ if (rd >= q->size) -+ rd = 0; -+ -+ writel(rd, q_dmem + FW_COM_RD_REG); -+} -+EXPORT_SYMBOL_NS_GPL(ipu6_recv_put_token, INTEL_IPU6); -diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-com.h b/drivers/media/pci/intel/ipu6/ipu6-fw-com.h -new file mode 100644 -index 000000000000..660c406b3ac9 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-com.h -@@ -0,0 +1,47 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_FW_COM_H -+#define IPU6_FW_COM_H -+ -+struct ipu6_fw_com_context; -+struct ipu6_bus_device; -+ -+struct ipu6_fw_syscom_queue_config { -+ unsigned int queue_size; /* tokens per queue */ -+ unsigned int token_size; /* bytes per token */ -+}; -+ -+#define SYSCOM_BUTTRESS_FW_PARAMS_ISYS_OFFSET 0 -+ -+struct ipu6_fw_com_cfg { -+ unsigned int num_input_queues; -+ unsigned int num_output_queues; -+ struct ipu6_fw_syscom_queue_config *input; -+ struct ipu6_fw_syscom_queue_config *output; -+ -+ unsigned int dmem_addr; -+ -+ /* firmware-specific configuration data */ -+ void *specific_addr; -+ unsigned int specific_size; -+ int (*cell_ready)(struct ipu6_bus_device *adev); -+ void (*cell_start)(struct ipu6_bus_device *adev); -+ -+ unsigned int buttress_boot_offset; -+}; -+ -+void *ipu6_fw_com_prepare(struct ipu6_fw_com_cfg *cfg, -+ struct ipu6_bus_device *adev, void __iomem *base); -+ -+int ipu6_fw_com_open(struct ipu6_fw_com_context *ctx); -+bool ipu6_fw_com_ready(struct ipu6_fw_com_context *ctx); -+int ipu6_fw_com_close(struct ipu6_fw_com_context *ctx); -+int ipu6_fw_com_release(struct ipu6_fw_com_context *ctx, unsigned int force); -+ -+void *ipu6_recv_get_token(struct ipu6_fw_com_context *ctx, int q_nbr); -+void ipu6_recv_put_token(struct ipu6_fw_com_context *ctx, int q_nbr); -+void *ipu6_send_get_token(struct ipu6_fw_com_context *ctx, int q_nbr); -+void ipu6_send_put_token(struct ipu6_fw_com_context *ctx, int q_nbr); -+ -+#endif --- -2.43.2 - - -From e690b8a96eb4fbe1d948ad80047a9af7c601b761 Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:21 +0800 -Subject: [PATCH 14/33] media: intel/ipu6: input system ABI between firmware - and driver - -Implement the input system firmware ABIs between the firmware and -driver - include stream configuration, control command, capture -request and response, etc. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - drivers/media/pci/intel/ipu6/ipu6-fw-isys.c | 487 +++++++++++++++++ - drivers/media/pci/intel/ipu6/ipu6-fw-isys.h | 573 ++++++++++++++++++++ - 2 files changed, 1060 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-fw-isys.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-fw-isys.h - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c -new file mode 100644 -index 000000000000..e06c1c955d38 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c -@@ -0,0 +1,487 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/cacheflush.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <linux/io.h> -+#include <linux/spinlock.h> -+#include <linux/types.h> -+ -+#include "ipu6-bus.h" -+#include "ipu6-fw-com.h" -+#include "ipu6-isys.h" -+#include "ipu6-platform-isys-csi2-reg.h" -+#include "ipu6-platform-regs.h" -+ -+static const char send_msg_types[N_IPU6_FW_ISYS_SEND_TYPE][32] = { -+ "STREAM_OPEN", -+ "STREAM_START", -+ "STREAM_START_AND_CAPTURE", -+ "STREAM_CAPTURE", -+ "STREAM_STOP", -+ "STREAM_FLUSH", -+ "STREAM_CLOSE" -+}; -+ -+static int handle_proxy_response(struct ipu6_isys *isys, unsigned int req_id) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ struct ipu6_fw_isys_proxy_resp_info_abi *resp; -+ int ret; -+ -+ resp = ipu6_recv_get_token(isys->fwcom, IPU6_BASE_PROXY_RECV_QUEUES); -+ if (!resp) -+ return 1; -+ -+ dev_dbg(dev, "Proxy response: id %u, error %u, details %u\n", -+ resp->request_id, resp->error_info.error, -+ resp->error_info.error_details); -+ -+ ret = req_id == resp->request_id ? 0 : -EIO; -+ -+ ipu6_recv_put_token(isys->fwcom, IPU6_BASE_PROXY_RECV_QUEUES); -+ -+ return ret; -+} -+ -+int ipu6_fw_isys_send_proxy_token(struct ipu6_isys *isys, -+ unsigned int req_id, -+ unsigned int index, -+ unsigned int offset, u32 value) -+{ -+ struct ipu6_fw_com_context *ctx = isys->fwcom; -+ struct device *dev = &isys->adev->auxdev.dev; -+ struct ipu6_fw_proxy_send_queue_token *token; -+ unsigned int timeout = 1000; -+ int ret; -+ -+ dev_dbg(dev, -+ "proxy send: req_id 0x%x, index %d, offset 0x%x, value 0x%x\n", -+ req_id, index, offset, value); -+ -+ token = ipu6_send_get_token(ctx, IPU6_BASE_PROXY_SEND_QUEUES); -+ if (!token) -+ return -EBUSY; -+ -+ token->request_id = req_id; -+ token->region_index = index; -+ token->offset = offset; -+ token->value = value; -+ ipu6_send_put_token(ctx, IPU6_BASE_PROXY_SEND_QUEUES); -+ -+ do { -+ usleep_range(100, 110); -+ ret = handle_proxy_response(isys, req_id); -+ if (!ret) -+ break; -+ if (ret == -EIO) { -+ dev_err(dev, "Proxy respond with unexpected id\n"); -+ break; -+ } -+ timeout--; -+ } while (ret && timeout); -+ -+ if (!timeout) -+ dev_err(dev, "Proxy response timed out\n"); -+ -+ return ret; -+} -+ -+int ipu6_fw_isys_complex_cmd(struct ipu6_isys *isys, -+ const unsigned int stream_handle, -+ void *cpu_mapped_buf, -+ dma_addr_t dma_mapped_buf, -+ size_t size, u16 send_type) -+{ -+ struct ipu6_fw_com_context *ctx = isys->fwcom; -+ struct device *dev = &isys->adev->auxdev.dev; -+ struct ipu6_fw_send_queue_token *token; -+ -+ if (send_type >= N_IPU6_FW_ISYS_SEND_TYPE) -+ return -EINVAL; -+ -+ dev_dbg(dev, "send_token: %s\n", send_msg_types[send_type]); -+ -+ /* -+ * Time to flush cache in case we have some payload. Not all messages -+ * have that -+ */ -+ if (cpu_mapped_buf) -+ clflush_cache_range(cpu_mapped_buf, size); -+ -+ token = ipu6_send_get_token(ctx, -+ stream_handle + IPU6_BASE_MSG_SEND_QUEUES); -+ if (!token) -+ return -EBUSY; -+ -+ token->payload = dma_mapped_buf; -+ token->buf_handle = (unsigned long)cpu_mapped_buf; -+ token->send_type = send_type; -+ -+ ipu6_send_put_token(ctx, stream_handle + IPU6_BASE_MSG_SEND_QUEUES); -+ -+ return 0; -+} -+ -+int ipu6_fw_isys_simple_cmd(struct ipu6_isys *isys, -+ const unsigned int stream_handle, u16 send_type) -+{ -+ return ipu6_fw_isys_complex_cmd(isys, stream_handle, NULL, 0, 0, -+ send_type); -+} -+ -+int ipu6_fw_isys_close(struct ipu6_isys *isys) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ int retry = IPU6_ISYS_CLOSE_RETRY; -+ unsigned long flags; -+ void *fwcom; -+ int ret; -+ -+ /* -+ * Stop the isys fw. Actual close takes -+ * some time as the FW must stop its actions including code fetch -+ * to SP icache. -+ * spinlock to wait the interrupt handler to be finished -+ */ -+ spin_lock_irqsave(&isys->power_lock, flags); -+ ret = ipu6_fw_com_close(isys->fwcom); -+ fwcom = isys->fwcom; -+ isys->fwcom = NULL; -+ spin_unlock_irqrestore(&isys->power_lock, flags); -+ if (ret) -+ dev_err(dev, "Device close failure: %d\n", ret); -+ -+ /* release probably fails if the close failed. Let's try still */ -+ do { -+ usleep_range(400, 500); -+ ret = ipu6_fw_com_release(fwcom, 0); -+ retry--; -+ } while (ret && retry); -+ -+ if (ret) { -+ dev_err(dev, "Device release time out %d\n", ret); -+ spin_lock_irqsave(&isys->power_lock, flags); -+ isys->fwcom = fwcom; -+ spin_unlock_irqrestore(&isys->power_lock, flags); -+ } -+ -+ return ret; -+} -+ -+void ipu6_fw_isys_cleanup(struct ipu6_isys *isys) -+{ -+ int ret; -+ -+ ret = ipu6_fw_com_release(isys->fwcom, 1); -+ if (ret < 0) -+ dev_warn(&isys->adev->auxdev.dev, -+ "Device busy, fw_com release failed."); -+ isys->fwcom = NULL; -+} -+ -+static void start_sp(struct ipu6_bus_device *adev) -+{ -+ struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev); -+ void __iomem *spc_regs_base = isys->pdata->base + -+ isys->pdata->ipdata->hw_variant.spc_offset; -+ u32 val = IPU6_ISYS_SPC_STATUS_START | -+ IPU6_ISYS_SPC_STATUS_RUN | -+ IPU6_ISYS_SPC_STATUS_CTRL_ICACHE_INVALIDATE; -+ -+ val |= isys->icache_prefetch ? IPU6_ISYS_SPC_STATUS_ICACHE_PREFETCH : 0; -+ -+ writel(val, spc_regs_base + IPU6_ISYS_REG_SPC_STATUS_CTRL); -+} -+ -+static int query_sp(struct ipu6_bus_device *adev) -+{ -+ struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev); -+ void __iomem *spc_regs_base = isys->pdata->base + -+ isys->pdata->ipdata->hw_variant.spc_offset; -+ u32 val; -+ -+ val = readl(spc_regs_base + IPU6_ISYS_REG_SPC_STATUS_CTRL); -+ /* return true when READY == 1, START == 0 */ -+ val &= IPU6_ISYS_SPC_STATUS_READY | IPU6_ISYS_SPC_STATUS_START; -+ -+ return val == IPU6_ISYS_SPC_STATUS_READY; -+} -+ -+static int ipu6_isys_fwcom_cfg_init(struct ipu6_isys *isys, -+ struct ipu6_fw_com_cfg *fwcom, -+ unsigned int num_streams) -+{ -+ unsigned int max_send_queues, max_sram_blocks, max_devq_size; -+ struct ipu6_fw_syscom_queue_config *input_queue_cfg; -+ struct ipu6_fw_syscom_queue_config *output_queue_cfg; -+ struct device *dev = &isys->adev->auxdev.dev; -+ int type_proxy = IPU6_FW_ISYS_QUEUE_TYPE_PROXY; -+ int type_dev = IPU6_FW_ISYS_QUEUE_TYPE_DEV; -+ int type_msg = IPU6_FW_ISYS_QUEUE_TYPE_MSG; -+ int base_dev_send = IPU6_BASE_DEV_SEND_QUEUES; -+ int base_msg_send = IPU6_BASE_MSG_SEND_QUEUES; -+ int base_msg_recv = IPU6_BASE_MSG_RECV_QUEUES; -+ struct ipu6_fw_isys_fw_config *isys_fw_cfg; -+ u32 num_in_message_queues; -+ unsigned int max_streams; -+ unsigned int size; -+ unsigned int i; -+ -+ max_streams = isys->pdata->ipdata->max_streams; -+ max_send_queues = isys->pdata->ipdata->max_send_queues; -+ max_sram_blocks = isys->pdata->ipdata->max_sram_blocks; -+ max_devq_size = isys->pdata->ipdata->max_devq_size; -+ num_in_message_queues = clamp(num_streams, 1U, max_streams); -+ isys_fw_cfg = devm_kzalloc(dev, sizeof(*isys_fw_cfg), GFP_KERNEL); -+ if (!isys_fw_cfg) -+ return -ENOMEM; -+ -+ isys_fw_cfg->num_send_queues[type_proxy] = IPU6_N_MAX_PROXY_SEND_QUEUES; -+ isys_fw_cfg->num_send_queues[type_dev] = IPU6_N_MAX_DEV_SEND_QUEUES; -+ isys_fw_cfg->num_send_queues[type_msg] = num_in_message_queues; -+ isys_fw_cfg->num_recv_queues[type_proxy] = IPU6_N_MAX_PROXY_RECV_QUEUES; -+ /* Common msg/dev return queue */ -+ isys_fw_cfg->num_recv_queues[type_dev] = 0; -+ isys_fw_cfg->num_recv_queues[type_msg] = 1; -+ -+ size = sizeof(*input_queue_cfg) * max_send_queues; -+ input_queue_cfg = devm_kzalloc(dev, size, GFP_KERNEL); -+ if (!input_queue_cfg) -+ return -ENOMEM; -+ -+ size = sizeof(*output_queue_cfg) * IPU6_N_MAX_RECV_QUEUES; -+ output_queue_cfg = devm_kzalloc(dev, size, GFP_KERNEL); -+ if (!output_queue_cfg) -+ return -ENOMEM; -+ -+ fwcom->input = input_queue_cfg; -+ fwcom->output = output_queue_cfg; -+ -+ fwcom->num_input_queues = isys_fw_cfg->num_send_queues[type_proxy] + -+ isys_fw_cfg->num_send_queues[type_dev] + -+ isys_fw_cfg->num_send_queues[type_msg]; -+ -+ fwcom->num_output_queues = isys_fw_cfg->num_recv_queues[type_proxy] + -+ isys_fw_cfg->num_recv_queues[type_dev] + -+ isys_fw_cfg->num_recv_queues[type_msg]; -+ -+ /* SRAM partitioning. Equal partitioning is set. */ -+ for (i = 0; i < max_sram_blocks; i++) { -+ if (i < num_in_message_queues) -+ isys_fw_cfg->buffer_partition.num_gda_pages[i] = -+ (IPU6_DEVICE_GDA_NR_PAGES * -+ IPU6_DEVICE_GDA_VIRT_FACTOR) / -+ num_in_message_queues; -+ else -+ isys_fw_cfg->buffer_partition.num_gda_pages[i] = 0; -+ } -+ -+ /* FW assumes proxy interface at fwcom queue 0 */ -+ for (i = 0; i < isys_fw_cfg->num_send_queues[type_proxy]; i++) { -+ input_queue_cfg[i].token_size = -+ sizeof(struct ipu6_fw_proxy_send_queue_token); -+ input_queue_cfg[i].queue_size = IPU6_ISYS_SIZE_PROXY_SEND_QUEUE; -+ } -+ -+ for (i = 0; i < isys_fw_cfg->num_send_queues[type_dev]; i++) { -+ input_queue_cfg[base_dev_send + i].token_size = -+ sizeof(struct ipu6_fw_send_queue_token); -+ input_queue_cfg[base_dev_send + i].queue_size = max_devq_size; -+ } -+ -+ for (i = 0; i < isys_fw_cfg->num_send_queues[type_msg]; i++) { -+ input_queue_cfg[base_msg_send + i].token_size = -+ sizeof(struct ipu6_fw_send_queue_token); -+ input_queue_cfg[base_msg_send + i].queue_size = -+ IPU6_ISYS_SIZE_SEND_QUEUE; -+ } -+ -+ for (i = 0; i < isys_fw_cfg->num_recv_queues[type_proxy]; i++) { -+ output_queue_cfg[i].token_size = -+ sizeof(struct ipu6_fw_proxy_resp_queue_token); -+ output_queue_cfg[i].queue_size = -+ IPU6_ISYS_SIZE_PROXY_RECV_QUEUE; -+ } -+ /* There is no recv DEV queue */ -+ for (i = 0; i < isys_fw_cfg->num_recv_queues[type_msg]; i++) { -+ output_queue_cfg[base_msg_recv + i].token_size = -+ sizeof(struct ipu6_fw_resp_queue_token); -+ output_queue_cfg[base_msg_recv + i].queue_size = -+ IPU6_ISYS_SIZE_RECV_QUEUE; -+ } -+ -+ fwcom->dmem_addr = isys->pdata->ipdata->hw_variant.dmem_offset; -+ fwcom->specific_addr = isys_fw_cfg; -+ fwcom->specific_size = sizeof(*isys_fw_cfg); -+ -+ return 0; -+} -+ -+int ipu6_fw_isys_init(struct ipu6_isys *isys, unsigned int num_streams) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ int retry = IPU6_ISYS_OPEN_RETRY; -+ struct ipu6_fw_com_cfg fwcom = { -+ .cell_start = start_sp, -+ .cell_ready = query_sp, -+ .buttress_boot_offset = SYSCOM_BUTTRESS_FW_PARAMS_ISYS_OFFSET, -+ }; -+ int ret; -+ -+ ipu6_isys_fwcom_cfg_init(isys, &fwcom, num_streams); -+ -+ isys->fwcom = ipu6_fw_com_prepare(&fwcom, isys->adev, -+ isys->pdata->base); -+ if (!isys->fwcom) { -+ dev_err(dev, "isys fw com prepare failed\n"); -+ return -EIO; -+ } -+ -+ ret = ipu6_fw_com_open(isys->fwcom); -+ if (ret) { -+ dev_err(dev, "isys fw com open failed %d\n", ret); -+ return ret; -+ } -+ -+ do { -+ usleep_range(400, 500); -+ if (ipu6_fw_com_ready(isys->fwcom)) -+ break; -+ retry--; -+ } while (retry > 0); -+ -+ if (!retry) { -+ dev_err(dev, "isys port open ready failed %d\n", ret); -+ ipu6_fw_isys_close(isys); -+ ret = -EIO; -+ } -+ -+ return ret; -+} -+ -+struct ipu6_fw_isys_resp_info_abi * -+ipu6_fw_isys_get_resp(void *context, unsigned int queue) -+{ -+ return ipu6_recv_get_token(context, queue); -+} -+ -+void ipu6_fw_isys_put_resp(void *context, unsigned int queue) -+{ -+ ipu6_recv_put_token(context, queue); -+} -+ -+void ipu6_fw_isys_dump_stream_cfg(struct device *dev, -+ struct ipu6_fw_isys_stream_cfg_data_abi *cfg) -+{ -+ unsigned int i; -+ -+ dev_dbg(dev, "-----------------------------------------------------\n"); -+ dev_dbg(dev, "IPU6_FW_ISYS_STREAM_CFG_DATA\n"); -+ -+ dev_dbg(dev, "compfmt = %d\n", cfg->vc); -+ dev_dbg(dev, "src = %d\n", cfg->src); -+ dev_dbg(dev, "vc = %d\n", cfg->vc); -+ dev_dbg(dev, "isl_use = %d\n", cfg->isl_use); -+ dev_dbg(dev, "sensor_type = %d\n", cfg->sensor_type); -+ -+ dev_dbg(dev, "send_irq_sof_discarded = %d\n", -+ cfg->send_irq_sof_discarded); -+ dev_dbg(dev, "send_irq_eof_discarded = %d\n", -+ cfg->send_irq_eof_discarded); -+ dev_dbg(dev, "send_resp_sof_discarded = %d\n", -+ cfg->send_resp_sof_discarded); -+ dev_dbg(dev, "send_resp_eof_discarded = %d\n", -+ cfg->send_resp_eof_discarded); -+ -+ dev_dbg(dev, "crop:\n"); -+ dev_dbg(dev, "\t.left_top = [%d, %d]\n", cfg->crop.left_offset, -+ cfg->crop.top_offset); -+ dev_dbg(dev, "\t.right_bottom = [%d, %d]\n", cfg->crop.right_offset, -+ cfg->crop.bottom_offset); -+ -+ dev_dbg(dev, "nof_input_pins = %d\n", cfg->nof_input_pins); -+ for (i = 0; i < cfg->nof_input_pins; i++) { -+ dev_dbg(dev, "input pin[%d]:\n", i); -+ dev_dbg(dev, "\t.dt = 0x%0x\n", cfg->input_pins[i].dt); -+ dev_dbg(dev, "\t.mipi_store_mode = %d\n", -+ cfg->input_pins[i].mipi_store_mode); -+ dev_dbg(dev, "\t.bits_per_pix = %d\n", -+ cfg->input_pins[i].bits_per_pix); -+ dev_dbg(dev, "\t.mapped_dt = 0x%0x\n", -+ cfg->input_pins[i].mapped_dt); -+ dev_dbg(dev, "\t.input_res = %dx%d\n", -+ cfg->input_pins[i].input_res.width, -+ cfg->input_pins[i].input_res.height); -+ dev_dbg(dev, "\t.mipi_decompression = %d\n", -+ cfg->input_pins[i].mipi_decompression); -+ dev_dbg(dev, "\t.capture_mode = %d\n", -+ cfg->input_pins[i].capture_mode); -+ } -+ -+ dev_dbg(dev, "nof_output_pins = %d\n", cfg->nof_output_pins); -+ for (i = 0; i < cfg->nof_output_pins; i++) { -+ dev_dbg(dev, "output_pin[%d]:\n", i); -+ dev_dbg(dev, "\t.input_pin_id = %d\n", -+ cfg->output_pins[i].input_pin_id); -+ dev_dbg(dev, "\t.output_res = %dx%d\n", -+ cfg->output_pins[i].output_res.width, -+ cfg->output_pins[i].output_res.height); -+ dev_dbg(dev, "\t.stride = %d\n", cfg->output_pins[i].stride); -+ dev_dbg(dev, "\t.pt = %d\n", cfg->output_pins[i].pt); -+ dev_dbg(dev, "\t.payload_buf_size = %d\n", -+ cfg->output_pins[i].payload_buf_size); -+ dev_dbg(dev, "\t.ft = %d\n", cfg->output_pins[i].ft); -+ dev_dbg(dev, "\t.watermark_in_lines = %d\n", -+ cfg->output_pins[i].watermark_in_lines); -+ dev_dbg(dev, "\t.send_irq = %d\n", -+ cfg->output_pins[i].send_irq); -+ dev_dbg(dev, "\t.reserve_compression = %d\n", -+ cfg->output_pins[i].reserve_compression); -+ dev_dbg(dev, "\t.snoopable = %d\n", -+ cfg->output_pins[i].snoopable); -+ dev_dbg(dev, "\t.error_handling_enable = %d\n", -+ cfg->output_pins[i].error_handling_enable); -+ dev_dbg(dev, "\t.sensor_type = %d\n", -+ cfg->output_pins[i].sensor_type); -+ } -+ dev_dbg(dev, "-----------------------------------------------------\n"); -+} -+ -+void -+ipu6_fw_isys_dump_frame_buff_set(struct device *dev, -+ struct ipu6_fw_isys_frame_buff_set_abi *buf, -+ unsigned int outputs) -+{ -+ unsigned int i; -+ -+ dev_dbg(dev, "-----------------------------------------------------\n"); -+ dev_dbg(dev, "IPU6_FW_ISYS_FRAME_BUFF_SET\n"); -+ -+ for (i = 0; i < outputs; i++) { -+ dev_dbg(dev, "output_pin[%d]:\n", i); -+ dev_dbg(dev, "\t.out_buf_id = %llu\n", -+ buf->output_pins[i].out_buf_id); -+ dev_dbg(dev, "\t.addr = 0x%x\n", buf->output_pins[i].addr); -+ dev_dbg(dev, "\t.compress = %d\n", -+ buf->output_pins[i].compress); -+ } -+ -+ dev_dbg(dev, "send_irq_sof = 0x%x\n", buf->send_irq_sof); -+ dev_dbg(dev, "send_irq_eof = 0x%x\n", buf->send_irq_eof); -+ dev_dbg(dev, "send_resp_sof = 0x%x\n", buf->send_resp_sof); -+ dev_dbg(dev, "send_resp_eof = 0x%x\n", buf->send_resp_eof); -+ dev_dbg(dev, "send_irq_capture_ack = 0x%x\n", -+ buf->send_irq_capture_ack); -+ dev_dbg(dev, "send_irq_capture_done = 0x%x\n", -+ buf->send_irq_capture_done); -+ dev_dbg(dev, "send_resp_capture_ack = 0x%x\n", -+ buf->send_resp_capture_ack); -+ dev_dbg(dev, "send_resp_capture_done = 0x%x\n", -+ buf->send_resp_capture_done); -+ -+ dev_dbg(dev, "-----------------------------------------------------\n"); -+} -diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.h b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.h -new file mode 100644 -index 000000000000..a7ffa0e22bf0 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.h -@@ -0,0 +1,573 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_FW_ISYS_H -+#define IPU6_FW_ISYS_H -+ -+#include <linux/types.h> -+ -+struct device; -+struct ipu6_isys; -+ -+/* Max number of Input/Output Pins */ -+#define IPU6_MAX_IPINS 4 -+ -+#define IPU6_MAX_OPINS ((IPU6_MAX_IPINS) + 1) -+ -+#define IPU6_STREAM_ID_MAX 16 -+#define IPU6_NONSECURE_STREAM_ID_MAX 12 -+#define IPU6_DEV_SEND_QUEUE_SIZE (IPU6_STREAM_ID_MAX) -+#define IPU6_NOF_SRAM_BLOCKS_MAX (IPU6_STREAM_ID_MAX) -+#define IPU6_N_MAX_MSG_SEND_QUEUES (IPU6_STREAM_ID_MAX) -+#define IPU6SE_STREAM_ID_MAX 8 -+#define IPU6SE_NONSECURE_STREAM_ID_MAX 4 -+#define IPU6SE_DEV_SEND_QUEUE_SIZE (IPU6SE_STREAM_ID_MAX) -+#define IPU6SE_NOF_SRAM_BLOCKS_MAX (IPU6SE_STREAM_ID_MAX) -+#define IPU6SE_N_MAX_MSG_SEND_QUEUES (IPU6SE_STREAM_ID_MAX) -+ -+/* Single return queue for all streams/commands type */ -+#define IPU6_N_MAX_MSG_RECV_QUEUES 1 -+/* Single device queue for high priority commands (bypass in-order queue) */ -+#define IPU6_N_MAX_DEV_SEND_QUEUES 1 -+/* Single dedicated send queue for proxy interface */ -+#define IPU6_N_MAX_PROXY_SEND_QUEUES 1 -+/* Single dedicated recv queue for proxy interface */ -+#define IPU6_N_MAX_PROXY_RECV_QUEUES 1 -+/* Send queues layout */ -+#define IPU6_BASE_PROXY_SEND_QUEUES 0 -+#define IPU6_BASE_DEV_SEND_QUEUES \ -+ (IPU6_BASE_PROXY_SEND_QUEUES + IPU6_N_MAX_PROXY_SEND_QUEUES) -+#define IPU6_BASE_MSG_SEND_QUEUES \ -+ (IPU6_BASE_DEV_SEND_QUEUES + IPU6_N_MAX_DEV_SEND_QUEUES) -+/* Recv queues layout */ -+#define IPU6_BASE_PROXY_RECV_QUEUES 0 -+#define IPU6_BASE_MSG_RECV_QUEUES \ -+ (IPU6_BASE_PROXY_RECV_QUEUES + IPU6_N_MAX_PROXY_RECV_QUEUES) -+#define IPU6_N_MAX_RECV_QUEUES \ -+ (IPU6_BASE_MSG_RECV_QUEUES + IPU6_N_MAX_MSG_RECV_QUEUES) -+ -+#define IPU6_N_MAX_SEND_QUEUES \ -+ (IPU6_BASE_MSG_SEND_QUEUES + IPU6_N_MAX_MSG_SEND_QUEUES) -+#define IPU6SE_N_MAX_SEND_QUEUES \ -+ (IPU6_BASE_MSG_SEND_QUEUES + IPU6SE_N_MAX_MSG_SEND_QUEUES) -+ -+/* Max number of supported input pins routed in ISL */ -+#define IPU6_MAX_IPINS_IN_ISL 2 -+ -+/* Max number of planes for frame formats supported by the FW */ -+#define IPU6_PIN_PLANES_MAX 4 -+ -+#define IPU6_FW_ISYS_SENSOR_TYPE_START 14 -+#define IPU6_FW_ISYS_SENSOR_TYPE_END 19 -+#define IPU6SE_FW_ISYS_SENSOR_TYPE_START 6 -+#define IPU6SE_FW_ISYS_SENSOR_TYPE_END 11 -+/* -+ * Device close takes some time from last ack message to actual stopping -+ * of the SP processor. As long as the SP processor runs we can't proceed with -+ * clean up of resources. -+ */ -+#define IPU6_ISYS_OPEN_RETRY 2000 -+#define IPU6_ISYS_CLOSE_RETRY 2000 -+#define IPU6_FW_CALL_TIMEOUT_JIFFIES msecs_to_jiffies(2000) -+ -+enum ipu6_fw_isys_resp_type { -+ IPU6_FW_ISYS_RESP_TYPE_STREAM_OPEN_DONE = 0, -+ IPU6_FW_ISYS_RESP_TYPE_STREAM_START_ACK, -+ IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_ACK, -+ IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_ACK, -+ IPU6_FW_ISYS_RESP_TYPE_STREAM_STOP_ACK, -+ IPU6_FW_ISYS_RESP_TYPE_STREAM_FLUSH_ACK, -+ IPU6_FW_ISYS_RESP_TYPE_STREAM_CLOSE_ACK, -+ IPU6_FW_ISYS_RESP_TYPE_PIN_DATA_READY, -+ IPU6_FW_ISYS_RESP_TYPE_PIN_DATA_WATERMARK, -+ IPU6_FW_ISYS_RESP_TYPE_FRAME_SOF, -+ IPU6_FW_ISYS_RESP_TYPE_FRAME_EOF, -+ IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_DONE, -+ IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_DONE, -+ IPU6_FW_ISYS_RESP_TYPE_PIN_DATA_SKIPPED, -+ IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_SKIPPED, -+ IPU6_FW_ISYS_RESP_TYPE_FRAME_SOF_DISCARDED, -+ IPU6_FW_ISYS_RESP_TYPE_FRAME_EOF_DISCARDED, -+ IPU6_FW_ISYS_RESP_TYPE_STATS_DATA_READY, -+ N_IPU6_FW_ISYS_RESP_TYPE -+}; -+ -+enum ipu6_fw_isys_send_type { -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_OPEN = 0, -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_START, -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_START_AND_CAPTURE, -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_CAPTURE, -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_STOP, -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_FLUSH, -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_CLOSE, -+ N_IPU6_FW_ISYS_SEND_TYPE -+}; -+ -+enum ipu6_fw_isys_queue_type { -+ IPU6_FW_ISYS_QUEUE_TYPE_PROXY = 0, -+ IPU6_FW_ISYS_QUEUE_TYPE_DEV, -+ IPU6_FW_ISYS_QUEUE_TYPE_MSG, -+ N_IPU6_FW_ISYS_QUEUE_TYPE -+}; -+ -+enum ipu6_fw_isys_stream_source { -+ IPU6_FW_ISYS_STREAM_SRC_PORT_0 = 0, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_1, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_2, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_3, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_4, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_5, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_6, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_7, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_8, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_9, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_10, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_11, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_12, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_13, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_14, -+ IPU6_FW_ISYS_STREAM_SRC_PORT_15, -+ IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_0, -+ IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_1, -+ IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_2, -+ IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_3, -+ IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_4, -+ IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_5, -+ IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_6, -+ IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_7, -+ IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_8, -+ IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_9, -+ N_IPU6_FW_ISYS_STREAM_SRC -+}; -+ -+#define IPU6_FW_ISYS_STREAM_SRC_CSI2_PORT0 IPU6_FW_ISYS_STREAM_SRC_PORT_0 -+#define IPU6_FW_ISYS_STREAM_SRC_CSI2_PORT1 IPU6_FW_ISYS_STREAM_SRC_PORT_1 -+#define IPU6_FW_ISYS_STREAM_SRC_CSI2_PORT2 IPU6_FW_ISYS_STREAM_SRC_PORT_2 -+#define IPU6_FW_ISYS_STREAM_SRC_CSI2_PORT3 IPU6_FW_ISYS_STREAM_SRC_PORT_3 -+ -+#define IPU6_FW_ISYS_STREAM_SRC_CSI2_3PH_PORTA IPU6_FW_ISYS_STREAM_SRC_PORT_4 -+#define IPU6_FW_ISYS_STREAM_SRC_CSI2_3PH_PORTB IPU6_FW_ISYS_STREAM_SRC_PORT_5 -+#define IPU6_FW_ISYS_STREAM_SRC_CSI2_3PH_CPHY_PORT0 \ -+ IPU6_FW_ISYS_STREAM_SRC_PORT_6 -+#define IPU6_FW_ISYS_STREAM_SRC_CSI2_3PH_CPHY_PORT1 \ -+ IPU6_FW_ISYS_STREAM_SRC_PORT_7 -+#define IPU6_FW_ISYS_STREAM_SRC_CSI2_3PH_CPHY_PORT2 \ -+ IPU6_FW_ISYS_STREAM_SRC_PORT_8 -+#define IPU6_FW_ISYS_STREAM_SRC_CSI2_3PH_CPHY_PORT3 \ -+ IPU6_FW_ISYS_STREAM_SRC_PORT_9 -+ -+#define IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_PORT0 IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_0 -+#define IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_PORT1 IPU6_FW_ISYS_STREAM_SRC_MIPIGEN_1 -+ -+/** -+ * enum ipu6_fw_isys_mipi_vc: MIPI csi2 spec -+ * supports up to 4 virtual per physical channel -+ */ -+enum ipu6_fw_isys_mipi_vc { -+ IPU6_FW_ISYS_MIPI_VC_0 = 0, -+ IPU6_FW_ISYS_MIPI_VC_1, -+ IPU6_FW_ISYS_MIPI_VC_2, -+ IPU6_FW_ISYS_MIPI_VC_3, -+ N_IPU6_FW_ISYS_MIPI_VC -+}; -+ -+enum ipu6_fw_isys_frame_format_type { -+ IPU6_FW_ISYS_FRAME_FORMAT_NV11 = 0, /* 12 bit YUV 411, Y, UV plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_NV12, /* 12 bit YUV 420, Y, UV plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_NV12_16, /* 16 bit YUV 420, Y, UV plane */ -+ /* 12 bit YUV 420, Intel proprietary tiled format */ -+ IPU6_FW_ISYS_FRAME_FORMAT_NV12_TILEY, -+ -+ IPU6_FW_ISYS_FRAME_FORMAT_NV16, /* 16 bit YUV 422, Y, UV plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_NV21, /* 12 bit YUV 420, Y, VU plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_NV61, /* 16 bit YUV 422, Y, VU plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YV12, /* 12 bit YUV 420, Y, V, U plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YV16, /* 16 bit YUV 422, Y, V, U plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YUV420, /* 12 bit YUV 420, Y, U, V plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YUV420_10, /* yuv420, 10 bits per subpixel */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YUV420_12, /* yuv420, 12 bits per subpixel */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YUV420_14, /* yuv420, 14 bits per subpixel */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YUV420_16, /* yuv420, 16 bits per subpixel */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YUV422, /* 16 bit YUV 422, Y, U, V plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YUV422_16, /* yuv422, 16 bits per subpixel */ -+ IPU6_FW_ISYS_FRAME_FORMAT_UYVY, /* 16 bit YUV 422, UYVY interleaved */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YUYV, /* 16 bit YUV 422, YUYV interleaved */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YUV444, /* 24 bit YUV 444, Y, U, V plane */ -+ /* Internal format, 2 y lines followed by a uvinterleaved line */ -+ IPU6_FW_ISYS_FRAME_FORMAT_YUV_LINE, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW8, /* RAW8, 1 plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW10, /* RAW10, 1 plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW12, /* RAW12, 1 plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW14, /* RAW14, 1 plane */ -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW16, /* RAW16, 1 plane */ -+ /** -+ * 16 bit RGB, 1 plane. Each 3 sub pixels are packed into one 16 bit -+ * value, 5 bits for R, 6 bits for G and 5 bits for B. -+ */ -+ IPU6_FW_ISYS_FRAME_FORMAT_RGB565, -+ IPU6_FW_ISYS_FRAME_FORMAT_PLANAR_RGB888, /* 24 bit RGB, 3 planes */ -+ IPU6_FW_ISYS_FRAME_FORMAT_RGBA888, /* 32 bit RGBA, 1 plane, A=Alpha */ -+ IPU6_FW_ISYS_FRAME_FORMAT_QPLANE6, /* Internal, for advanced ISP */ -+ IPU6_FW_ISYS_FRAME_FORMAT_BINARY_8, /* byte stream, used for jpeg. */ -+ N_IPU6_FW_ISYS_FRAME_FORMAT -+}; -+ -+#define IPU6_FW_ISYS_FRAME_FORMAT_RAW (IPU6_FW_ISYS_FRAME_FORMAT_RAW16) -+ -+enum ipu6_fw_isys_pin_type { -+ /* captured as MIPI packets */ -+ IPU6_FW_ISYS_PIN_TYPE_MIPI = 0, -+ /* captured through the SoC path */ -+ IPU6_FW_ISYS_PIN_TYPE_RAW_SOC = 3, -+}; -+ -+/** -+ * enum ipu6_fw_isys_mipi_store_mode. Describes if long MIPI packets reach -+ * MIPI SRAM with the long packet header or -+ * if not, then only option is to capture it with pin type MIPI. -+ */ -+enum ipu6_fw_isys_mipi_store_mode { -+ IPU6_FW_ISYS_MIPI_STORE_MODE_NORMAL = 0, -+ IPU6_FW_ISYS_MIPI_STORE_MODE_DISCARD_LONG_HEADER, -+ N_IPU6_FW_ISYS_MIPI_STORE_MODE -+}; -+ -+enum ipu6_fw_isys_capture_mode { -+ IPU6_FW_ISYS_CAPTURE_MODE_REGULAR = 0, -+ IPU6_FW_ISYS_CAPTURE_MODE_BURST, -+ N_IPU6_FW_ISYS_CAPTURE_MODE, -+}; -+ -+enum ipu6_fw_isys_sensor_mode { -+ IPU6_FW_ISYS_SENSOR_MODE_NORMAL = 0, -+ IPU6_FW_ISYS_SENSOR_MODE_TOBII, -+ N_IPU6_FW_ISYS_SENSOR_MODE, -+}; -+ -+enum ipu6_fw_isys_error { -+ IPU6_FW_ISYS_ERROR_NONE = 0, -+ IPU6_FW_ISYS_ERROR_FW_INTERNAL_CONSISTENCY, -+ IPU6_FW_ISYS_ERROR_HW_CONSISTENCY, -+ IPU6_FW_ISYS_ERROR_DRIVER_INVALID_COMMAND_SEQUENCE, -+ IPU6_FW_ISYS_ERROR_DRIVER_INVALID_DEVICE_CONFIGURATION, -+ IPU6_FW_ISYS_ERROR_DRIVER_INVALID_STREAM_CONFIGURATION, -+ IPU6_FW_ISYS_ERROR_DRIVER_INVALID_FRAME_CONFIGURATION, -+ IPU6_FW_ISYS_ERROR_INSUFFICIENT_RESOURCES, -+ IPU6_FW_ISYS_ERROR_HW_REPORTED_STR2MMIO, -+ IPU6_FW_ISYS_ERROR_HW_REPORTED_SIG2CIO, -+ IPU6_FW_ISYS_ERROR_SENSOR_FW_SYNC, -+ IPU6_FW_ISYS_ERROR_STREAM_IN_SUSPENSION, -+ IPU6_FW_ISYS_ERROR_RESPONSE_QUEUE_FULL, -+ N_IPU6_FW_ISYS_ERROR -+}; -+ -+enum ipu6_fw_proxy_error { -+ IPU6_FW_PROXY_ERROR_NONE = 0, -+ IPU6_FW_PROXY_ERROR_INVALID_WRITE_REGION, -+ IPU6_FW_PROXY_ERROR_INVALID_WRITE_OFFSET, -+ N_IPU6_FW_PROXY_ERROR -+}; -+ -+/* firmware ABI structure below are aligned in firmware, no need pack */ -+struct ipu6_fw_isys_buffer_partition_abi { -+ u32 num_gda_pages[IPU6_STREAM_ID_MAX]; -+}; -+ -+struct ipu6_fw_isys_fw_config { -+ struct ipu6_fw_isys_buffer_partition_abi buffer_partition; -+ u32 num_send_queues[N_IPU6_FW_ISYS_QUEUE_TYPE]; -+ u32 num_recv_queues[N_IPU6_FW_ISYS_QUEUE_TYPE]; -+}; -+ -+/** -+ * struct ipu6_fw_isys_resolution_abi: Generic resolution structure. -+ */ -+struct ipu6_fw_isys_resolution_abi { -+ u32 width; -+ u32 height; -+}; -+ -+/** -+ * struct ipu6_fw_isys_output_pin_payload_abi -+ * @out_buf_id: Points to output pin buffer - buffer identifier -+ * @addr: Points to output pin buffer - CSS Virtual Address -+ * @compress: Request frame compression (1), or not (0) -+ */ -+struct ipu6_fw_isys_output_pin_payload_abi { -+ u64 out_buf_id; -+ u32 addr; -+ u32 compress; -+}; -+ -+/** -+ * struct ipu6_fw_isys_output_pin_info_abi -+ * @output_res: output pin resolution -+ * @stride: output stride in Bytes (not valid for statistics) -+ * @watermark_in_lines: pin watermark level in lines -+ * @payload_buf_size: minimum size in Bytes of all buffers that will be -+ * supplied for capture on this pin -+ * @send_irq: assert if pin event should trigger irq -+ * @pt: pin type -real format "enum ipu6_fw_isys_pin_type" -+ * @ft: frame format type -real format "enum ipu6_fw_isys_frame_format_type" -+ * @input_pin_id: related input pin id -+ * @reserve_compression: reserve compression resources for pin -+ */ -+struct ipu6_fw_isys_output_pin_info_abi { -+ struct ipu6_fw_isys_resolution_abi output_res; -+ u32 stride; -+ u32 watermark_in_lines; -+ u32 payload_buf_size; -+ u32 ts_offsets[IPU6_PIN_PLANES_MAX]; -+ u32 s2m_pixel_soc_pixel_remapping; -+ u32 csi_be_soc_pixel_remapping; -+ u8 send_irq; -+ u8 input_pin_id; -+ u8 pt; -+ u8 ft; -+ u8 reserved; -+ u8 reserve_compression; -+ u8 snoopable; -+ u8 error_handling_enable; -+ u32 sensor_type; -+}; -+ -+/** -+ * struct ipu6_fw_isys_input_pin_info_abi -+ * @input_res: input resolution -+ * @dt: mipi data type ((enum ipu6_fw_isys_mipi_data_type) -+ * @mipi_store_mode: defines if legacy long packet header will be stored or -+ * discarded if discarded, output pin type for this -+ * input pin can only be MIPI -+ * (enum ipu6_fw_isys_mipi_store_mode) -+ * @bits_per_pix: native bits per pixel -+ * @mapped_dt: actual data type from sensor -+ * @mipi_decompression: defines which compression will be in mipi backend -+ * @crop_first_and_last_lines Control whether to crop the -+ * first and last line of the -+ * input image. Crop done by HW -+ * device. -+ * @capture_mode: mode of capture, regular or burst, default value is regular -+ */ -+struct ipu6_fw_isys_input_pin_info_abi { -+ struct ipu6_fw_isys_resolution_abi input_res; -+ u8 dt; -+ u8 mipi_store_mode; -+ u8 bits_per_pix; -+ u8 mapped_dt; -+ u8 mipi_decompression; -+ u8 crop_first_and_last_lines; -+ u8 capture_mode; -+ u8 reserved; -+}; -+ -+/** -+ * struct ipu6_fw_isys_cropping_abi - cropping coordinates -+ */ -+struct ipu6_fw_isys_cropping_abi { -+ s32 top_offset; -+ s32 left_offset; -+ s32 bottom_offset; -+ s32 right_offset; -+}; -+ -+/** -+ * struct ipu6_fw_isys_stream_cfg_data_abi -+ * ISYS stream configuration data structure -+ * @crop: for extended use and is not used in FW currently -+ * @input_pins: input pin descriptors -+ * @output_pins: output pin descriptors -+ * @compfmt: de-compression setting for User Defined Data -+ * @nof_input_pins: number of input pins -+ * @nof_output_pins: number of output pins -+ * @send_irq_sof_discarded: send irq on discarded frame sof response -+ * - if '1' it will override the send_resp_sof_discarded -+ * and send the response -+ * - if '0' the send_resp_sof_discarded will determine -+ * whether to send the response -+ * @send_irq_eof_discarded: send irq on discarded frame eof response -+ * - if '1' it will override the send_resp_eof_discarded -+ * and send the response -+ * - if '0' the send_resp_eof_discarded will determine -+ * whether to send the response -+ * @send_resp_sof_discarded: send response for discarded frame sof detected, -+ * used only when send_irq_sof_discarded is '0' -+ * @send_resp_eof_discarded: send response for discarded frame eof detected, -+ * used only when send_irq_eof_discarded is '0' -+ * @src: Stream source index e.g. MIPI_generator_0, CSI2-rx_1 -+ * @vc: MIPI Virtual Channel (up to 4 virtual per physical channel) -+ * @isl_use: indicates whether stream requires ISL and how -+ * @sensor_type: type of connected sensor, tobii or others, default is 0 -+ */ -+struct ipu6_fw_isys_stream_cfg_data_abi { -+ struct ipu6_fw_isys_cropping_abi crop; -+ struct ipu6_fw_isys_input_pin_info_abi input_pins[IPU6_MAX_IPINS]; -+ struct ipu6_fw_isys_output_pin_info_abi output_pins[IPU6_MAX_OPINS]; -+ u32 compfmt; -+ u8 nof_input_pins; -+ u8 nof_output_pins; -+ u8 send_irq_sof_discarded; -+ u8 send_irq_eof_discarded; -+ u8 send_resp_sof_discarded; -+ u8 send_resp_eof_discarded; -+ u8 src; -+ u8 vc; -+ u8 isl_use; -+ u8 sensor_type; -+ u8 reserved; -+ u8 reserved2; -+}; -+ -+/** -+ * struct ipu6_fw_isys_frame_buff_set - frame buffer set -+ * @output_pins: output pin addresses -+ * @send_irq_sof: send irq on frame sof response -+ * - if '1' it will override the send_resp_sof and -+ * send the response -+ * - if '0' the send_resp_sof will determine whether to -+ * send the response -+ * @send_irq_eof: send irq on frame eof response -+ * - if '1' it will override the send_resp_eof and -+ * send the response -+ * - if '0' the send_resp_eof will determine whether to -+ * send the response -+ * @send_resp_sof: send response for frame sof detected, -+ * used only when send_irq_sof is '0' -+ * @send_resp_eof: send response for frame eof detected, -+ * used only when send_irq_eof is '0' -+ * @send_resp_capture_ack: send response for capture ack event -+ * @send_resp_capture_done: send response for capture done event -+ */ -+struct ipu6_fw_isys_frame_buff_set_abi { -+ struct ipu6_fw_isys_output_pin_payload_abi output_pins[IPU6_MAX_OPINS]; -+ u8 send_irq_sof; -+ u8 send_irq_eof; -+ u8 send_irq_capture_ack; -+ u8 send_irq_capture_done; -+ u8 send_resp_sof; -+ u8 send_resp_eof; -+ u8 send_resp_capture_ack; -+ u8 send_resp_capture_done; -+ u8 reserved[8]; -+}; -+ -+/** -+ * struct ipu6_fw_isys_error_info_abi -+ * @error: error code if something went wrong -+ * @error_details: depending on error code, it may contain additional error info -+ */ -+struct ipu6_fw_isys_error_info_abi { -+ u32 error; -+ u32 error_details; -+}; -+ -+/** -+ * struct ipu6_fw_isys_resp_info_comm -+ * @pin: this var is only valid for pin event related responses, -+ * contains pin addresses -+ * @error_info: error information from the FW -+ * @timestamp: Time information for event if available -+ * @stream_handle: stream id the response corresponds to -+ * @type: response type (enum ipu6_fw_isys_resp_type) -+ * @pin_id: pin id that the pin payload corresponds to -+ */ -+struct ipu6_fw_isys_resp_info_abi { -+ u64 buf_id; -+ struct ipu6_fw_isys_output_pin_payload_abi pin; -+ struct ipu6_fw_isys_error_info_abi error_info; -+ u32 timestamp[2]; -+ u8 stream_handle; -+ u8 type; -+ u8 pin_id; -+ u8 reserved; -+ u32 reserved2; -+}; -+ -+/** -+ * struct ipu6_fw_isys_proxy_error_info_comm -+ * @proxy_error: error code if something went wrong -+ * @proxy_error_details: depending on error code, it may contain additional -+ * error info -+ */ -+struct ipu6_fw_isys_proxy_error_info_abi { -+ u32 error; -+ u32 error_details; -+}; -+ -+struct ipu6_fw_isys_proxy_resp_info_abi { -+ u32 request_id; -+ struct ipu6_fw_isys_proxy_error_info_abi error_info; -+}; -+ -+/** -+ * struct ipu6_fw_proxy_write_queue_token -+ * @request_id: update id for the specific proxy write request -+ * @region_index: Region id for the proxy write request -+ * @offset: Offset of the write request according to the base address -+ * of the region -+ * @value: Value that is requested to be written with the proxy write request -+ */ -+struct ipu6_fw_proxy_write_queue_token { -+ u32 request_id; -+ u32 region_index; -+ u32 offset; -+ u32 value; -+}; -+ -+/** -+ * struct ipu6_fw_resp_queue_token -+ */ -+struct ipu6_fw_resp_queue_token { -+ struct ipu6_fw_isys_resp_info_abi resp_info; -+}; -+ -+/** -+ * struct ipu6_fw_send_queue_token -+ */ -+struct ipu6_fw_send_queue_token { -+ u64 buf_handle; -+ u32 payload; -+ u16 send_type; -+ u16 stream_id; -+}; -+ -+/** -+ * struct ipu6_fw_proxy_resp_queue_token -+ */ -+struct ipu6_fw_proxy_resp_queue_token { -+ struct ipu6_fw_isys_proxy_resp_info_abi proxy_resp_info; -+}; -+ -+/** -+ * struct ipu6_fw_proxy_send_queue_token -+ */ -+struct ipu6_fw_proxy_send_queue_token { -+ u32 request_id; -+ u32 region_index; -+ u32 offset; -+ u32 value; -+}; -+ -+void -+ipu6_fw_isys_dump_stream_cfg(struct device *dev, -+ struct ipu6_fw_isys_stream_cfg_data_abi *cfg); -+void -+ipu6_fw_isys_dump_frame_buff_set(struct device *dev, -+ struct ipu6_fw_isys_frame_buff_set_abi *buf, -+ unsigned int outputs); -+int ipu6_fw_isys_init(struct ipu6_isys *isys, unsigned int num_streams); -+int ipu6_fw_isys_close(struct ipu6_isys *isys); -+int ipu6_fw_isys_simple_cmd(struct ipu6_isys *isys, -+ const unsigned int stream_handle, u16 send_type); -+int ipu6_fw_isys_complex_cmd(struct ipu6_isys *isys, -+ const unsigned int stream_handle, -+ void *cpu_mapped_buf, dma_addr_t dma_mapped_buf, -+ size_t size, u16 send_type); -+int ipu6_fw_isys_send_proxy_token(struct ipu6_isys *isys, -+ unsigned int req_id, -+ unsigned int index, -+ unsigned int offset, u32 value); -+void ipu6_fw_isys_cleanup(struct ipu6_isys *isys); -+struct ipu6_fw_isys_resp_info_abi * -+ipu6_fw_isys_get_resp(void *context, unsigned int queue); -+void ipu6_fw_isys_put_resp(void *context, unsigned int queue); -+#endif --- -2.43.2 - - -From e69a245fa4db99e5983170aab73f962dc99d3149 Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:22 +0800 -Subject: [PATCH 15/33] media: intel/ipu6: add IPU6 CSI2 receiver v4l2 - sub-device - -Input system CSI2 receiver is exposed as a v4l2 sub-device. -Each CSI2 sub-device represent one single CSI2 hardware port -which be linked with external sub-device such camera sensor -by linked with ISYS CSI2's sink pad. CSI2 source pad is linked -to the sink pad of video capture device. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 666 ++++++++++++++++++ - drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h | 81 +++ - .../media/pci/intel/ipu6/ipu6-isys-subdev.c | 381 ++++++++++ - .../media/pci/intel/ipu6/ipu6-isys-subdev.h | 61 ++ - .../intel/ipu6/ipu6-platform-isys-csi2-reg.h | 189 +++++ - 5 files changed, 1378 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-platform-isys-csi2-reg.h - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c -new file mode 100644 -index 000000000000..ac9fa3e0d7ab ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c -@@ -0,0 +1,666 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/atomic.h> -+#include <linux/bitfield.h> -+#include <linux/bits.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <linux/err.h> -+#include <linux/io.h> -+#include <linux/minmax.h> -+#include <linux/sprintf.h> -+ -+#include <media/media-entity.h> -+#include <media/v4l2-ctrls.h> -+#include <media/v4l2-device.h> -+#include <media/v4l2-event.h> -+#include <media/v4l2-subdev.h> -+ -+#include "ipu6-bus.h" -+#include "ipu6-isys.h" -+#include "ipu6-isys-csi2.h" -+#include "ipu6-isys-subdev.h" -+#include "ipu6-platform-isys-csi2-reg.h" -+ -+static const u32 csi2_supported_codes[] = { -+ MEDIA_BUS_FMT_RGB565_1X16, -+ MEDIA_BUS_FMT_RGB888_1X24, -+ MEDIA_BUS_FMT_UYVY8_1X16, -+ MEDIA_BUS_FMT_YUYV8_1X16, -+ MEDIA_BUS_FMT_SBGGR10_1X10, -+ MEDIA_BUS_FMT_SGBRG10_1X10, -+ MEDIA_BUS_FMT_SGRBG10_1X10, -+ MEDIA_BUS_FMT_SRGGB10_1X10, -+ MEDIA_BUS_FMT_SBGGR12_1X12, -+ MEDIA_BUS_FMT_SGBRG12_1X12, -+ MEDIA_BUS_FMT_SGRBG12_1X12, -+ MEDIA_BUS_FMT_SRGGB12_1X12, -+ MEDIA_BUS_FMT_SBGGR8_1X8, -+ MEDIA_BUS_FMT_SGBRG8_1X8, -+ MEDIA_BUS_FMT_SGRBG8_1X8, -+ MEDIA_BUS_FMT_SRGGB8_1X8, -+ 0 -+}; -+ -+/* -+ * Strings corresponding to CSI-2 receiver errors are here. -+ * Corresponding macros are defined in the header file. -+ */ -+static const struct ipu6_csi2_error dphy_rx_errors[] = { -+ { "Single packet header error corrected", true }, -+ { "Multiple packet header errors detected", true }, -+ { "Payload checksum (CRC) error", true }, -+ { "Transfer FIFO overflow", false }, -+ { "Reserved short packet data type detected", true }, -+ { "Reserved long packet data type detected", true }, -+ { "Incomplete long packet detected", false }, -+ { "Frame sync error", false }, -+ { "Line sync error", false }, -+ { "DPHY recoverable synchronization error", true }, -+ { "DPHY fatal error", false }, -+ { "DPHY elastic FIFO overflow", false }, -+ { "Inter-frame short packet discarded", true }, -+ { "Inter-frame long packet discarded", true }, -+ { "MIPI pktgen overflow", false }, -+ { "MIPI pktgen data loss", false }, -+ { "FIFO overflow", false }, -+ { "Lane deskew", false }, -+ { "SOT sync error", false }, -+ { "HSIDLE detected", false } -+}; -+ -+s64 ipu6_isys_csi2_get_link_freq(struct ipu6_isys_csi2 *csi2) -+{ -+ struct media_pad *src_pad; -+ struct v4l2_subdev *ext_sd; -+ struct device *dev; -+ -+ if (!csi2) -+ return -EINVAL; -+ -+ dev = &csi2->isys->adev->auxdev.dev; -+ src_pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity); -+ if (IS_ERR_OR_NULL(src_pad)) { -+ dev_err(dev, "can't get source pad of %s\n", csi2->asd.sd.name); -+ return -ENOLINK; -+ } -+ -+ ext_sd = media_entity_to_v4l2_subdev(src_pad->entity); -+ if (WARN(!ext_sd, "Failed to get subdev for %s\n", csi2->asd.sd.name)) -+ return -ENODEV; -+ -+ return v4l2_get_link_freq(ext_sd->ctrl_handler, 0, 0); -+} -+ -+static int csi2_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, -+ struct v4l2_event_subscription *sub) -+{ -+ struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd); -+ struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd); -+ struct device *dev = &csi2->isys->adev->auxdev.dev; -+ -+ dev_dbg(dev, "csi2 subscribe event(type %u id %u)\n", -+ sub->type, sub->id); -+ -+ switch (sub->type) { -+ case V4L2_EVENT_FRAME_SYNC: -+ return v4l2_event_subscribe(fh, sub, 10, NULL); -+ case V4L2_EVENT_CTRL: -+ return v4l2_ctrl_subscribe_event(fh, sub); -+ default: -+ return -EINVAL; -+ } -+} -+ -+static const struct v4l2_subdev_core_ops csi2_sd_core_ops = { -+ .subscribe_event = csi2_subscribe_event, -+ .unsubscribe_event = v4l2_event_subdev_unsubscribe, -+}; -+ -+/* -+ * The input system CSI2+ receiver has several -+ * parameters affecting the receiver timings. These depend -+ * on the MIPI bus frequency F in Hz (sensor transmitter rate) -+ * as follows: -+ * register value = (A/1e9 + B * UI) / COUNT_ACC -+ * where -+ * UI = 1 / (2 * F) in seconds -+ * COUNT_ACC = counter accuracy in seconds -+ * COUNT_ACC = 0.125 ns = 1 / 8 ns, ACCINV = 8. -+ * -+ * A and B are coefficients from the table below, -+ * depending whether the register minimum or maximum value is -+ * calculated. -+ * Minimum Maximum -+ * Clock lane A B A B -+ * reg_rx_csi_dly_cnt_termen_clane 0 0 38 0 -+ * reg_rx_csi_dly_cnt_settle_clane 95 -8 300 -16 -+ * Data lanes -+ * reg_rx_csi_dly_cnt_termen_dlane0 0 0 35 4 -+ * reg_rx_csi_dly_cnt_settle_dlane0 85 -2 145 -6 -+ * reg_rx_csi_dly_cnt_termen_dlane1 0 0 35 4 -+ * reg_rx_csi_dly_cnt_settle_dlane1 85 -2 145 -6 -+ * reg_rx_csi_dly_cnt_termen_dlane2 0 0 35 4 -+ * reg_rx_csi_dly_cnt_settle_dlane2 85 -2 145 -6 -+ * reg_rx_csi_dly_cnt_termen_dlane3 0 0 35 4 -+ * reg_rx_csi_dly_cnt_settle_dlane3 85 -2 145 -6 -+ * -+ * We use the minimum values of both A and B. -+ */ -+ -+#define DIV_SHIFT 8 -+#define CSI2_ACCINV 8 -+ -+static u32 calc_timing(s32 a, s32 b, s64 link_freq, s32 accinv) -+{ -+ return accinv * a + (accinv * b * (500000000 >> DIV_SHIFT) -+ / (s32)(link_freq >> DIV_SHIFT)); -+} -+ -+static int -+ipu6_isys_csi2_calc_timing(struct ipu6_isys_csi2 *csi2, -+ struct ipu6_isys_csi2_timing *timing, s32 accinv) -+{ -+ struct device *dev = &csi2->isys->adev->auxdev.dev; -+ s64 link_freq; -+ -+ link_freq = ipu6_isys_csi2_get_link_freq(csi2); -+ if (link_freq < 0) -+ return link_freq; -+ -+ timing->ctermen = calc_timing(CSI2_CSI_RX_DLY_CNT_TERMEN_CLANE_A, -+ CSI2_CSI_RX_DLY_CNT_TERMEN_CLANE_B, -+ link_freq, accinv); -+ timing->csettle = calc_timing(CSI2_CSI_RX_DLY_CNT_SETTLE_CLANE_A, -+ CSI2_CSI_RX_DLY_CNT_SETTLE_CLANE_B, -+ link_freq, accinv); -+ timing->dtermen = calc_timing(CSI2_CSI_RX_DLY_CNT_TERMEN_DLANE_A, -+ CSI2_CSI_RX_DLY_CNT_TERMEN_DLANE_B, -+ link_freq, accinv); -+ timing->dsettle = calc_timing(CSI2_CSI_RX_DLY_CNT_SETTLE_DLANE_A, -+ CSI2_CSI_RX_DLY_CNT_SETTLE_DLANE_B, -+ link_freq, accinv); -+ -+ dev_dbg(dev, "ctermen %u csettle %u dtermen %u dsettle %u\n", -+ timing->ctermen, timing->csettle, -+ timing->dtermen, timing->dsettle); -+ -+ return 0; -+} -+ -+void ipu6_isys_register_errors(struct ipu6_isys_csi2 *csi2) -+{ -+ u32 irq = readl(csi2->base + CSI_PORT_REG_BASE_IRQ_CSI + -+ CSI_PORT_REG_BASE_IRQ_STATUS_OFFSET); -+ struct ipu6_isys *isys = csi2->isys; -+ u32 mask; -+ -+ mask = isys->pdata->ipdata->csi2.irq_mask; -+ writel(irq & mask, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI + -+ CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET); -+ csi2->receiver_errors |= irq & mask; -+} -+ -+void ipu6_isys_csi2_error(struct ipu6_isys_csi2 *csi2) -+{ -+ struct device *dev = &csi2->isys->adev->auxdev.dev; -+ const struct ipu6_csi2_error *errors; -+ u32 status; -+ u32 i; -+ -+ /* register errors once more in case of interrupts are disabled */ -+ ipu6_isys_register_errors(csi2); -+ status = csi2->receiver_errors; -+ csi2->receiver_errors = 0; -+ errors = dphy_rx_errors; -+ -+ for (i = 0; i < CSI_RX_NUM_ERRORS_IN_IRQ; i++) { -+ if (status & BIT(i)) -+ dev_err_ratelimited(dev, "csi2-%i error: %s\n", -+ csi2->port, errors[i].error_string); -+ } -+} -+ -+static int ipu6_isys_csi2_set_stream(struct v4l2_subdev *sd, -+ const struct ipu6_isys_csi2_timing *timing, -+ unsigned int nlanes, int enable) -+{ -+ struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd); -+ struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd); -+ struct ipu6_isys *isys = csi2->isys; -+ struct device *dev = &isys->adev->auxdev.dev; -+ struct ipu6_isys_csi2_config cfg; -+ unsigned int nports; -+ int ret = 0; -+ u32 mask = 0; -+ u32 i; -+ -+ dev_dbg(dev, "stream %s CSI2-%u with %u lanes\n", enable ? "on" : "off", -+ csi2->port, nlanes); -+ -+ cfg.port = csi2->port; -+ cfg.nlanes = nlanes; -+ -+ mask = isys->pdata->ipdata->csi2.irq_mask; -+ nports = isys->pdata->ipdata->csi2.nports; -+ -+ if (!enable) { -+ writel(0, csi2->base + CSI_REG_CSI_FE_ENABLE); -+ writel(0, csi2->base + CSI_REG_PPI2CSI_ENABLE); -+ -+ writel(0, -+ csi2->base + CSI_PORT_REG_BASE_IRQ_CSI + -+ CSI_PORT_REG_BASE_IRQ_ENABLE_OFFSET); -+ writel(mask, -+ csi2->base + CSI_PORT_REG_BASE_IRQ_CSI + -+ CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET); -+ writel(0, -+ csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC + -+ CSI_PORT_REG_BASE_IRQ_ENABLE_OFFSET); -+ writel(0xffffffff, -+ csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC + -+ CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET); -+ -+ isys->phy_set_power(isys, &cfg, timing, false); -+ -+ writel(0, isys->pdata->base + CSI_REG_HUB_FW_ACCESS_PORT -+ (isys->pdata->ipdata->csi2.fw_access_port_ofs, -+ csi2->port)); -+ writel(0, isys->pdata->base + -+ CSI_REG_HUB_DRV_ACCESS_PORT(csi2->port)); -+ -+ return ret; -+ } -+ -+ /* reset port reset */ -+ writel(0x1, csi2->base + CSI_REG_PORT_GPREG_SRST); -+ usleep_range(100, 200); -+ writel(0x0, csi2->base + CSI_REG_PORT_GPREG_SRST); -+ -+ /* enable port clock */ -+ for (i = 0; i < nports; i++) { -+ writel(1, isys->pdata->base + CSI_REG_HUB_DRV_ACCESS_PORT(i)); -+ writel(1, isys->pdata->base + CSI_REG_HUB_FW_ACCESS_PORT -+ (isys->pdata->ipdata->csi2.fw_access_port_ofs, i)); -+ } -+ -+ /* enable all error related irq */ -+ writel(mask, -+ csi2->base + CSI_PORT_REG_BASE_IRQ_CSI + -+ CSI_PORT_REG_BASE_IRQ_STATUS_OFFSET); -+ writel(mask, -+ csi2->base + CSI_PORT_REG_BASE_IRQ_CSI + -+ CSI_PORT_REG_BASE_IRQ_MASK_OFFSET); -+ writel(mask, -+ csi2->base + CSI_PORT_REG_BASE_IRQ_CSI + -+ CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET); -+ writel(mask, -+ csi2->base + CSI_PORT_REG_BASE_IRQ_CSI + -+ CSI_PORT_REG_BASE_IRQ_LEVEL_NOT_PULSE_OFFSET); -+ writel(mask, -+ csi2->base + CSI_PORT_REG_BASE_IRQ_CSI + -+ CSI_PORT_REG_BASE_IRQ_ENABLE_OFFSET); -+ -+ /* -+ * Using event from firmware instead of irq to handle CSI2 sync event -+ * which can reduce system wakeups. If CSI2 sync irq enabled, we need -+ * disable the firmware CSI2 sync event to avoid duplicate handling. -+ */ -+ writel(0xffffffff, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC + -+ CSI_PORT_REG_BASE_IRQ_STATUS_OFFSET); -+ writel(0, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC + -+ CSI_PORT_REG_BASE_IRQ_MASK_OFFSET); -+ writel(0xffffffff, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC + -+ CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET); -+ writel(0, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC + -+ CSI_PORT_REG_BASE_IRQ_LEVEL_NOT_PULSE_OFFSET); -+ writel(0xffffffff, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC + -+ CSI_PORT_REG_BASE_IRQ_ENABLE_OFFSET); -+ -+ /* configure to enable FE and PPI2CSI */ -+ writel(0, csi2->base + CSI_REG_CSI_FE_MODE); -+ writel(CSI_SENSOR_INPUT, csi2->base + CSI_REG_CSI_FE_MUX_CTRL); -+ writel(CSI_CNTR_SENSOR_LINE_ID | CSI_CNTR_SENSOR_FRAME_ID, -+ csi2->base + CSI_REG_CSI_FE_SYNC_CNTR_SEL); -+ writel(FIELD_PREP(PPI_INTF_CONFIG_NOF_ENABLED_DLANES_MASK, nlanes - 1), -+ csi2->base + CSI_REG_PPI2CSI_CONFIG_PPI_INTF); -+ -+ writel(1, csi2->base + CSI_REG_PPI2CSI_ENABLE); -+ writel(1, csi2->base + CSI_REG_CSI_FE_ENABLE); -+ -+ ret = isys->phy_set_power(isys, &cfg, timing, true); -+ if (ret) -+ dev_err(dev, "csi-%d phy power up failed %d\n", csi2->port, -+ ret); -+ -+ return ret; -+} -+ -+static int set_stream(struct v4l2_subdev *sd, int enable) -+{ -+ struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd); -+ struct ipu6_isys_csi2 *csi2 = to_ipu6_isys_csi2(asd); -+ struct device *dev = &csi2->isys->adev->auxdev.dev; -+ struct ipu6_isys_csi2_timing timing = { }; -+ unsigned int nlanes; -+ int ret; -+ -+ dev_dbg(dev, "csi2 stream %s callback\n", enable ? "on" : "off"); -+ -+ if (!enable) { -+ csi2->stream_count--; -+ if (csi2->stream_count) -+ return 0; -+ -+ ipu6_isys_csi2_set_stream(sd, &timing, 0, enable); -+ return 0; -+ } -+ -+ if (csi2->stream_count) { -+ csi2->stream_count++; -+ return 0; -+ } -+ -+ nlanes = csi2->nlanes; -+ -+ ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV); -+ if (ret) -+ return ret; -+ -+ ret = ipu6_isys_csi2_set_stream(sd, &timing, nlanes, enable); -+ if (ret) -+ return ret; -+ -+ csi2->stream_count++; -+ -+ return 0; -+} -+ -+static int ipu6_isys_csi2_set_sel(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state, -+ struct v4l2_subdev_selection *sel) -+{ -+ struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd); -+ struct device *dev = &asd->isys->adev->auxdev.dev; -+ struct v4l2_mbus_framefmt *sink_ffmt; -+ struct v4l2_mbus_framefmt *src_ffmt; -+ struct v4l2_rect *crop; -+ -+ if (sel->pad == CSI2_PAD_SINK || sel->target != V4L2_SEL_TGT_CROP) -+ return -EINVAL; -+ -+ sink_ffmt = v4l2_subdev_state_get_opposite_stream_format(state, -+ sel->pad, -+ sel->stream); -+ if (!sink_ffmt) -+ return -EINVAL; -+ -+ src_ffmt = v4l2_subdev_state_get_stream_format(state, sel->pad, -+ sel->stream); -+ if (!src_ffmt) -+ return -EINVAL; -+ -+ crop = v4l2_subdev_state_get_stream_crop(state, sel->pad, sel->stream); -+ if (!crop) -+ return -EINVAL; -+ -+ /* Only vertical cropping is supported */ -+ sel->r.left = 0; -+ sel->r.width = sink_ffmt->width; -+ /* Non-bayer formats can't be single line cropped */ -+ if (!ipu6_isys_is_bayer_format(sink_ffmt->code)) -+ sel->r.top &= ~1; -+ sel->r.height = clamp(sel->r.height & ~1, IPU6_ISYS_MIN_HEIGHT, -+ sink_ffmt->height - sel->r.top); -+ *crop = sel->r; -+ -+ /* update source pad format */ -+ src_ffmt->width = sel->r.width; -+ src_ffmt->height = sel->r.height; -+ if (ipu6_isys_is_bayer_format(sink_ffmt->code)) -+ src_ffmt->code = ipu6_isys_convert_bayer_order(sink_ffmt->code, -+ sel->r.left, -+ sel->r.top); -+ dev_dbg(dev, "set crop for %s sel: %d,%d,%d,%d code: 0x%x\n", -+ sd->name, sel->r.left, sel->r.top, sel->r.width, sel->r.height, -+ src_ffmt->code); -+ -+ return 0; -+} -+ -+static int ipu6_isys_csi2_get_sel(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state, -+ struct v4l2_subdev_selection *sel) -+{ -+ struct v4l2_mbus_framefmt *sink_ffmt; -+ struct v4l2_rect *crop; -+ int ret = 0; -+ -+ if (sd->entity.pads[sel->pad].flags & MEDIA_PAD_FL_SINK) -+ return -EINVAL; -+ -+ sink_ffmt = v4l2_subdev_state_get_opposite_stream_format(state, -+ sel->pad, -+ sel->stream); -+ if (!sink_ffmt) -+ return -EINVAL; -+ -+ crop = v4l2_subdev_state_get_stream_crop(state, sel->pad, sel->stream); -+ if (!crop) -+ return -EINVAL; -+ -+ switch (sel->target) { -+ case V4L2_SEL_TGT_CROP_DEFAULT: -+ case V4L2_SEL_TGT_CROP_BOUNDS: -+ sel->r.left = 0; -+ sel->r.top = 0; -+ sel->r.width = sink_ffmt->width; -+ sel->r.height = sink_ffmt->height; -+ break; -+ case V4L2_SEL_TGT_CROP: -+ sel->r = *crop; -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static const struct v4l2_subdev_video_ops csi2_sd_video_ops = { -+ .s_stream = set_stream, -+}; -+ -+static const struct v4l2_subdev_pad_ops csi2_sd_pad_ops = { -+ .init_cfg = ipu6_isys_subdev_init_cfg, -+ .get_fmt = v4l2_subdev_get_fmt, -+ .set_fmt = ipu6_isys_subdev_set_fmt, -+ .get_selection = ipu6_isys_csi2_get_sel, -+ .set_selection = ipu6_isys_csi2_set_sel, -+ .enum_mbus_code = ipu6_isys_subdev_enum_mbus_code, -+ .set_routing = ipu6_isys_subdev_set_routing, -+}; -+ -+static const struct v4l2_subdev_ops csi2_sd_ops = { -+ .core = &csi2_sd_core_ops, -+ .video = &csi2_sd_video_ops, -+ .pad = &csi2_sd_pad_ops, -+}; -+ -+static const struct media_entity_operations csi2_entity_ops = { -+ .link_validate = v4l2_subdev_link_validate, -+ .has_pad_interdep = v4l2_subdev_has_pad_interdep, -+}; -+ -+void ipu6_isys_csi2_cleanup(struct ipu6_isys_csi2 *csi2) -+{ -+ if (!csi2->isys) -+ return; -+ -+ v4l2_device_unregister_subdev(&csi2->asd.sd); -+ v4l2_subdev_cleanup(&csi2->asd.sd); -+ ipu6_isys_subdev_cleanup(&csi2->asd); -+ csi2->isys = NULL; -+} -+ -+int ipu6_isys_csi2_init(struct ipu6_isys_csi2 *csi2, -+ struct ipu6_isys *isys, -+ void __iomem *base, unsigned int index) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ int ret; -+ -+ csi2->isys = isys; -+ csi2->base = base; -+ csi2->port = index; -+ -+ csi2->asd.sd.entity.ops = &csi2_entity_ops; -+ csi2->asd.isys = isys; -+ ret = ipu6_isys_subdev_init(&csi2->asd, &csi2_sd_ops, 0, -+ NR_OF_CSI2_SINK_PADS, NR_OF_CSI2_SRC_PADS); -+ if (ret) -+ goto fail; -+ -+ csi2->asd.source = IPU6_FW_ISYS_STREAM_SRC_CSI2_PORT0 + index; -+ csi2->asd.supported_codes = csi2_supported_codes; -+ snprintf(csi2->asd.sd.name, sizeof(csi2->asd.sd.name), -+ IPU6_ISYS_ENTITY_PREFIX " CSI2 %u", index); -+ v4l2_set_subdevdata(&csi2->asd.sd, &csi2->asd); -+ ret = v4l2_subdev_init_finalize(&csi2->asd.sd); -+ if (ret) { -+ dev_err(dev, "failed to init v4l2 subdev\n"); -+ goto fail; -+ } -+ -+ ret = v4l2_device_register_subdev(&isys->v4l2_dev, &csi2->asd.sd); -+ if (ret) { -+ dev_err(dev, "failed to register v4l2 subdev\n"); -+ goto fail; -+ } -+ -+ return 0; -+ -+fail: -+ ipu6_isys_csi2_cleanup(csi2); -+ -+ return ret; -+} -+ -+void ipu6_isys_csi2_sof_event_by_stream(struct ipu6_isys_stream *stream) -+{ -+ struct video_device *vdev = stream->asd->sd.devnode; -+ struct device *dev = &stream->isys->adev->auxdev.dev; -+ struct ipu6_isys_csi2 *csi2 = ipu6_isys_subdev_to_csi2(stream->asd); -+ struct v4l2_event ev = { -+ .type = V4L2_EVENT_FRAME_SYNC, -+ }; -+ -+ ev.u.frame_sync.frame_sequence = atomic_fetch_inc(&stream->sequence); -+ v4l2_event_queue(vdev, &ev); -+ -+ dev_dbg(dev, "sof_event::csi2-%i sequence: %i, vc: %d\n", -+ csi2->port, ev.u.frame_sync.frame_sequence, stream->vc); -+} -+ -+void ipu6_isys_csi2_eof_event_by_stream(struct ipu6_isys_stream *stream) -+{ -+ struct device *dev = &stream->isys->adev->auxdev.dev; -+ struct ipu6_isys_csi2 *csi2 = ipu6_isys_subdev_to_csi2(stream->asd); -+ u32 frame_sequence = atomic_read(&stream->sequence); -+ -+ dev_dbg(dev, "eof_event::csi2-%i sequence: %i\n", -+ csi2->port, frame_sequence); -+} -+ -+int ipu6_isys_csi2_get_remote_desc(u32 source_stream, -+ struct ipu6_isys_csi2 *csi2, -+ struct media_entity *source_entity, -+ struct v4l2_mbus_frame_desc_entry *entry, -+ int *nr_queues) -+{ -+ struct v4l2_mbus_frame_desc_entry *desc_entry = NULL; -+ struct device *dev = &csi2->isys->adev->auxdev.dev; -+ struct v4l2_mbus_frame_desc desc; -+ struct v4l2_subdev *source; -+ struct media_pad *pad; -+ unsigned int i; -+ int count = 0; -+ int ret; -+ -+ source = media_entity_to_v4l2_subdev(source_entity); -+ if (!source) -+ return -EPIPE; -+ -+ pad = media_pad_remote_pad_first(&csi2->asd.pad[CSI2_PAD_SINK]); -+ if (!pad) -+ return -EPIPE; -+ -+ ret = v4l2_subdev_call(source, pad, get_frame_desc, pad->index, &desc); -+ if (ret) -+ return ret; -+ -+ if (desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) { -+ dev_err(dev, "Unsupported frame descriptor type\n"); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < desc.num_entries; i++) { -+ if (source_stream == desc.entry[i].stream) { -+ desc_entry = &desc.entry[i]; -+ break; -+ } -+ } -+ -+ if (!desc_entry) { -+ dev_err(dev, "Failed to find stream %u from remote subdev\n", -+ source_stream); -+ return -EINVAL; -+ } -+ -+ if (desc_entry->bus.csi2.vc >= NR_OF_CSI2_VC) { -+ dev_err(dev, "invalid vc %d\n", desc_entry->bus.csi2.vc); -+ return -EINVAL; -+ } -+ -+ *entry = *desc_entry; -+ for (i = 0; i < desc.num_entries; i++) { -+ if (entry->bus.csi2.vc == desc.entry[i].bus.csi2.vc) -+ count++; -+ } -+ -+ *nr_queues = count; -+ return 0; -+} -+ -+void ipu6_isys_set_csi2_streams_status(struct ipu6_isys_video *av, bool status) -+{ -+ struct ipu6_isys_stream *stream = av->stream; -+ struct v4l2_subdev *sd = &stream->asd->sd; -+ struct v4l2_subdev_state *state; -+ struct media_pad *r_pad; -+ unsigned int i; -+ u32 r_stream; -+ -+ r_pad = media_pad_remote_pad_first(&av->pad); -+ r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, r_pad->index); -+ -+ state = v4l2_subdev_lock_and_get_active_state(sd); -+ -+ for (i = 0; i < state->stream_configs.num_configs; i++) { -+ struct v4l2_subdev_stream_config *cfg = -+ &state->stream_configs.configs[i]; -+ -+ if (cfg->pad == r_pad->index && r_stream == cfg->stream) { -+ dev_dbg(&av->isys->adev->auxdev.dev, -+ "%s: pad:%u, stream:%u, status:%u\n", -+ sd->entity.name, r_pad->index, r_stream, -+ status); -+ cfg->enabled = status; -+ } -+ } -+ -+ v4l2_subdev_unlock_state(state); -+} -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h -new file mode 100644 -index 000000000000..d4765bae6112 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h -@@ -0,0 +1,81 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_ISYS_CSI2_H -+#define IPU6_ISYS_CSI2_H -+ -+#include <linux/container_of.h> -+ -+#include "ipu6-isys-subdev.h" -+ -+struct media_entity; -+struct v4l2_mbus_frame_desc_entry; -+ -+struct ipu6_isys_video; -+struct ipu6_isys; -+struct ipu6_isys_csi2_pdata; -+struct ipu6_isys_stream; -+ -+#define NR_OF_CSI2_VC 16 -+#define INVALID_VC_ID -1 -+#define NR_OF_CSI2_SINK_PADS 1 -+#define CSI2_PAD_SINK 0 -+#define NR_OF_CSI2_SRC_PADS 8 -+#define CSI2_PAD_SRC 1 -+#define NR_OF_CSI2_PADS (NR_OF_CSI2_SINK_PADS + NR_OF_CSI2_SRC_PADS) -+ -+#define CSI2_CSI_RX_DLY_CNT_TERMEN_CLANE_A 0 -+#define CSI2_CSI_RX_DLY_CNT_TERMEN_CLANE_B 0 -+#define CSI2_CSI_RX_DLY_CNT_SETTLE_CLANE_A 95 -+#define CSI2_CSI_RX_DLY_CNT_SETTLE_CLANE_B -8 -+ -+#define CSI2_CSI_RX_DLY_CNT_TERMEN_DLANE_A 0 -+#define CSI2_CSI_RX_DLY_CNT_TERMEN_DLANE_B 0 -+#define CSI2_CSI_RX_DLY_CNT_SETTLE_DLANE_A 85 -+#define CSI2_CSI_RX_DLY_CNT_SETTLE_DLANE_B -2 -+ -+struct ipu6_isys_csi2 { -+ struct ipu6_isys_subdev asd; -+ struct ipu6_isys_csi2_pdata *pdata; -+ struct ipu6_isys *isys; -+ -+ void __iomem *base; -+ u32 receiver_errors; -+ unsigned int nlanes; -+ unsigned int port; -+ unsigned int stream_count; -+}; -+ -+struct ipu6_isys_csi2_timing { -+ u32 ctermen; -+ u32 csettle; -+ u32 dtermen; -+ u32 dsettle; -+}; -+ -+struct ipu6_csi2_error { -+ const char *error_string; -+ bool is_info_only; -+}; -+ -+#define ipu6_isys_subdev_to_csi2(__sd) \ -+ container_of(__sd, struct ipu6_isys_csi2, asd) -+ -+#define to_ipu6_isys_csi2(__asd) container_of(__asd, struct ipu6_isys_csi2, asd) -+ -+s64 ipu6_isys_csi2_get_link_freq(struct ipu6_isys_csi2 *csi2); -+int ipu6_isys_csi2_init(struct ipu6_isys_csi2 *csi2, struct ipu6_isys *isys, -+ void __iomem *base, unsigned int index); -+void ipu6_isys_csi2_cleanup(struct ipu6_isys_csi2 *csi2); -+void ipu6_isys_csi2_sof_event_by_stream(struct ipu6_isys_stream *stream); -+void ipu6_isys_csi2_eof_event_by_stream(struct ipu6_isys_stream *stream); -+void ipu6_isys_register_errors(struct ipu6_isys_csi2 *csi2); -+void ipu6_isys_csi2_error(struct ipu6_isys_csi2 *csi2); -+int ipu6_isys_csi2_get_remote_desc(u32 source_stream, -+ struct ipu6_isys_csi2 *csi2, -+ struct media_entity *source_entity, -+ struct v4l2_mbus_frame_desc_entry *entry, -+ int *nr_queues); -+void ipu6_isys_set_csi2_streams_status(struct ipu6_isys_video *av, bool status); -+ -+#endif /* IPU6_ISYS_CSI2_H */ -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c -new file mode 100644 -index 000000000000..510c5ca34f9f ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c -@@ -0,0 +1,381 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/bug.h> -+#include <linux/device.h> -+#include <linux/minmax.h> -+ -+#include <media/media-entity.h> -+#include <media/mipi-csi2.h> -+#include <media/v4l2-ctrls.h> -+#include <media/v4l2-subdev.h> -+ -+#include "ipu6-bus.h" -+#include "ipu6-isys.h" -+#include "ipu6-isys-subdev.h" -+ -+unsigned int ipu6_isys_mbus_code_to_bpp(u32 code) -+{ -+ switch (code) { -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ return 24; -+ case MEDIA_BUS_FMT_RGB565_1X16: -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ case MEDIA_BUS_FMT_YUYV8_1X16: -+ return 16; -+ case MEDIA_BUS_FMT_SBGGR12_1X12: -+ case MEDIA_BUS_FMT_SGBRG12_1X12: -+ case MEDIA_BUS_FMT_SGRBG12_1X12: -+ case MEDIA_BUS_FMT_SRGGB12_1X12: -+ return 12; -+ case MEDIA_BUS_FMT_SBGGR10_1X10: -+ case MEDIA_BUS_FMT_SGBRG10_1X10: -+ case MEDIA_BUS_FMT_SGRBG10_1X10: -+ case MEDIA_BUS_FMT_SRGGB10_1X10: -+ return 10; -+ case MEDIA_BUS_FMT_SBGGR8_1X8: -+ case MEDIA_BUS_FMT_SGBRG8_1X8: -+ case MEDIA_BUS_FMT_SGRBG8_1X8: -+ case MEDIA_BUS_FMT_SRGGB8_1X8: -+ return 8; -+ default: -+ WARN_ON(1); -+ return 8; -+ } -+} -+ -+unsigned int ipu6_isys_mbus_code_to_mipi(u32 code) -+{ -+ switch (code) { -+ case MEDIA_BUS_FMT_RGB565_1X16: -+ return MIPI_CSI2_DT_RGB565; -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ return MIPI_CSI2_DT_RGB888; -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ case MEDIA_BUS_FMT_YUYV8_1X16: -+ return MIPI_CSI2_DT_YUV422_8B; -+ case MEDIA_BUS_FMT_SBGGR12_1X12: -+ case MEDIA_BUS_FMT_SGBRG12_1X12: -+ case MEDIA_BUS_FMT_SGRBG12_1X12: -+ case MEDIA_BUS_FMT_SRGGB12_1X12: -+ return MIPI_CSI2_DT_RAW12; -+ case MEDIA_BUS_FMT_SBGGR10_1X10: -+ case MEDIA_BUS_FMT_SGBRG10_1X10: -+ case MEDIA_BUS_FMT_SGRBG10_1X10: -+ case MEDIA_BUS_FMT_SRGGB10_1X10: -+ return MIPI_CSI2_DT_RAW10; -+ case MEDIA_BUS_FMT_SBGGR8_1X8: -+ case MEDIA_BUS_FMT_SGBRG8_1X8: -+ case MEDIA_BUS_FMT_SGRBG8_1X8: -+ case MEDIA_BUS_FMT_SRGGB8_1X8: -+ return MIPI_CSI2_DT_RAW8; -+ default: -+ /* return unavailable MIPI data type - 0x3f */ -+ WARN_ON(1); -+ return 0x3f; -+ } -+} -+ -+bool ipu6_isys_is_bayer_format(u32 code) -+{ -+ switch (ipu6_isys_mbus_code_to_mipi(code)) { -+ case MIPI_CSI2_DT_RAW8: -+ case MIPI_CSI2_DT_RAW10: -+ case MIPI_CSI2_DT_RAW12: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+u32 ipu6_isys_convert_bayer_order(u32 code, int x, int y) -+{ -+ static const u32 code_map[] = { -+ MEDIA_BUS_FMT_SRGGB8_1X8, -+ MEDIA_BUS_FMT_SGRBG8_1X8, -+ MEDIA_BUS_FMT_SGBRG8_1X8, -+ MEDIA_BUS_FMT_SBGGR8_1X8, -+ MEDIA_BUS_FMT_SRGGB10_1X10, -+ MEDIA_BUS_FMT_SGRBG10_1X10, -+ MEDIA_BUS_FMT_SGBRG10_1X10, -+ MEDIA_BUS_FMT_SBGGR10_1X10, -+ MEDIA_BUS_FMT_SRGGB12_1X12, -+ MEDIA_BUS_FMT_SGRBG12_1X12, -+ MEDIA_BUS_FMT_SGBRG12_1X12, -+ MEDIA_BUS_FMT_SBGGR12_1X12 -+ }; -+ u32 i; -+ -+ for (i = 0; i < ARRAY_SIZE(code_map); i++) -+ if (code_map[i] == code) -+ break; -+ -+ if (WARN_ON(i == ARRAY_SIZE(code_map))) -+ return code; -+ -+ return code_map[i ^ (((y & 1) << 1) | (x & 1))]; -+} -+ -+int ipu6_isys_subdev_set_fmt(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state, -+ struct v4l2_subdev_format *format) -+{ -+ struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd); -+ struct v4l2_mbus_framefmt *fmt; -+ struct v4l2_rect *crop; -+ u32 code = asd->supported_codes[0]; -+ u32 other_pad, other_stream; -+ unsigned int i; -+ int ret; -+ -+ /* No transcoding, source and sink formats must match. */ -+ if ((sd->entity.pads[format->pad].flags & MEDIA_PAD_FL_SOURCE) && -+ sd->entity.num_pads > 1) -+ return v4l2_subdev_get_fmt(sd, state, format); -+ -+ format->format.width = clamp(format->format.width, IPU6_ISYS_MIN_WIDTH, -+ IPU6_ISYS_MAX_WIDTH); -+ format->format.height = clamp(format->format.height, -+ IPU6_ISYS_MIN_HEIGHT, -+ IPU6_ISYS_MAX_HEIGHT); -+ -+ for (i = 0; asd->supported_codes[i]; i++) { -+ if (asd->supported_codes[i] == format->format.code) { -+ code = asd->supported_codes[i]; -+ break; -+ } -+ } -+ format->format.code = code; -+ format->format.field = V4L2_FIELD_NONE; -+ -+ /* Store the format and propagate it to the source pad. */ -+ fmt = v4l2_subdev_state_get_stream_format(state, format->pad, -+ format->stream); -+ if (!fmt) -+ return -EINVAL; -+ -+ *fmt = format->format; -+ -+ if (!(sd->entity.pads[format->pad].flags & MEDIA_PAD_FL_SINK)) -+ return 0; -+ -+ /* propagate format to following source pad */ -+ fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad, -+ format->stream); -+ if (!fmt) -+ return -EINVAL; -+ -+ *fmt = format->format; -+ -+ ret = v4l2_subdev_routing_find_opposite_end(&state->routing, -+ format->pad, -+ format->stream, -+ &other_pad, -+ &other_stream); -+ if (ret) -+ return -EINVAL; -+ -+ crop = v4l2_subdev_state_get_stream_crop(state, other_pad, -+ other_stream); -+ /* reset crop */ -+ crop->left = 0; -+ crop->top = 0; -+ crop->width = fmt->width; -+ crop->height = fmt->height; -+ -+ return 0; -+} -+ -+int ipu6_isys_subdev_enum_mbus_code(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state, -+ struct v4l2_subdev_mbus_code_enum *code) -+{ -+ struct ipu6_isys_subdev *asd = to_ipu6_isys_subdev(sd); -+ const u32 *supported_codes = asd->supported_codes; -+ u32 index; -+ -+ for (index = 0; supported_codes[index]; index++) { -+ if (index == code->index) { -+ code->code = supported_codes[index]; -+ return 0; -+ } -+ } -+ -+ return -EINVAL; -+} -+ -+static int subdev_set_routing(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state, -+ struct v4l2_subdev_krouting *routing) -+{ -+ static const struct v4l2_mbus_framefmt format = { -+ .width = 4096, -+ .height = 3072, -+ .code = MEDIA_BUS_FMT_SGRBG10_1X10, -+ .field = V4L2_FIELD_NONE, -+ }; -+ int ret; -+ -+ ret = v4l2_subdev_routing_validate(sd, routing, -+ V4L2_SUBDEV_ROUTING_ONLY_1_TO_1); -+ if (ret) -+ return ret; -+ -+ return v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format); -+} -+ -+int ipu6_isys_get_stream_pad_fmt(struct v4l2_subdev *sd, u32 pad, u32 stream, -+ struct v4l2_mbus_framefmt *format) -+{ -+ struct v4l2_mbus_framefmt *fmt; -+ struct v4l2_subdev_state *state; -+ -+ if (!sd || !format) -+ return -EINVAL; -+ -+ state = v4l2_subdev_lock_and_get_active_state(sd); -+ fmt = v4l2_subdev_state_get_stream_format(state, pad, stream); -+ if (fmt) -+ *format = *fmt; -+ v4l2_subdev_unlock_state(state); -+ -+ return fmt ? 0 : -EINVAL; -+} -+ -+int ipu6_isys_get_stream_pad_crop(struct v4l2_subdev *sd, u32 pad, u32 stream, -+ struct v4l2_rect *crop) -+{ -+ struct v4l2_subdev_state *state; -+ struct v4l2_rect *rect; -+ -+ if (!sd || !crop) -+ return -EINVAL; -+ -+ state = v4l2_subdev_lock_and_get_active_state(sd); -+ rect = v4l2_subdev_state_get_stream_crop(state, pad, stream); -+ if (rect) -+ *crop = *rect; -+ v4l2_subdev_unlock_state(state); -+ -+ return rect ? 0 : -EINVAL; -+} -+ -+u32 ipu6_isys_get_src_stream_by_src_pad(struct v4l2_subdev *sd, u32 pad) -+{ -+ struct v4l2_subdev_state *state; -+ struct v4l2_subdev_route *routes; -+ unsigned int i; -+ u32 source_stream = 0; -+ -+ state = v4l2_subdev_lock_and_get_active_state(sd); -+ if (!state) -+ return 0; -+ -+ routes = state->routing.routes; -+ for (i = 0; i < state->routing.num_routes; i++) { -+ if (routes[i].source_pad == pad) { -+ source_stream = routes[i].source_stream; -+ break; -+ } -+ } -+ -+ v4l2_subdev_unlock_state(state); -+ -+ return source_stream; -+} -+ -+int ipu6_isys_subdev_init_cfg(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state) -+{ -+ struct v4l2_subdev_route route = { -+ .sink_pad = 0, -+ .sink_stream = 0, -+ .source_pad = 1, -+ .source_stream = 0, -+ .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE, -+ }; -+ struct v4l2_subdev_krouting routing = { -+ .num_routes = 1, -+ .routes = &route, -+ }; -+ -+ return subdev_set_routing(sd, state, &routing); -+} -+ -+int ipu6_isys_subdev_set_routing(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state, -+ enum v4l2_subdev_format_whence which, -+ struct v4l2_subdev_krouting *routing) -+{ -+ return subdev_set_routing(sd, state, routing); -+} -+ -+int ipu6_isys_subdev_init(struct ipu6_isys_subdev *asd, -+ const struct v4l2_subdev_ops *ops, -+ unsigned int nr_ctrls, -+ unsigned int num_sink_pads, -+ unsigned int num_source_pads) -+{ -+ unsigned int num_pads = num_sink_pads + num_source_pads; -+ unsigned int i; -+ int ret; -+ -+ v4l2_subdev_init(&asd->sd, ops); -+ -+ asd->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | -+ V4L2_SUBDEV_FL_HAS_EVENTS | -+ V4L2_SUBDEV_FL_STREAMS; -+ asd->sd.owner = THIS_MODULE; -+ asd->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; -+ -+ asd->pad = devm_kcalloc(&asd->isys->adev->auxdev.dev, num_pads, -+ sizeof(*asd->pad), GFP_KERNEL); -+ -+ if (!asd->pad) -+ return -ENOMEM; -+ -+ for (i = 0; i < num_sink_pads; i++) -+ asd->pad[i].flags = MEDIA_PAD_FL_SINK | -+ MEDIA_PAD_FL_MUST_CONNECT; -+ -+ for (i = num_sink_pads; i < num_pads; i++) -+ asd->pad[i].flags = MEDIA_PAD_FL_SOURCE; -+ -+ ret = media_entity_pads_init(&asd->sd.entity, num_pads, asd->pad); -+ if (ret) -+ return ret; -+ -+ if (asd->ctrl_init) { -+ ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, nr_ctrls); -+ if (ret) -+ goto out_media_entity_cleanup; -+ -+ asd->ctrl_init(&asd->sd); -+ if (asd->ctrl_handler.error) { -+ ret = asd->ctrl_handler.error; -+ goto out_v4l2_ctrl_handler_free; -+ } -+ -+ asd->sd.ctrl_handler = &asd->ctrl_handler; -+ } -+ -+ asd->source = -1; -+ -+ return 0; -+ -+out_v4l2_ctrl_handler_free: -+ v4l2_ctrl_handler_free(&asd->ctrl_handler); -+ -+out_media_entity_cleanup: -+ media_entity_cleanup(&asd->sd.entity); -+ -+ return ret; -+} -+ -+void ipu6_isys_subdev_cleanup(struct ipu6_isys_subdev *asd) -+{ -+ media_entity_cleanup(&asd->sd.entity); -+ v4l2_ctrl_handler_free(&asd->ctrl_handler); -+} -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h -new file mode 100644 -index 000000000000..adea2a55761d ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h -@@ -0,0 +1,61 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_ISYS_SUBDEV_H -+#define IPU6_ISYS_SUBDEV_H -+ -+#include <linux/container_of.h> -+ -+#include <media/media-entity.h> -+#include <media/v4l2-ctrls.h> -+#include <media/v4l2-subdev.h> -+ -+struct ipu6_isys; -+ -+struct ipu6_isys_subdev { -+ struct v4l2_subdev sd; -+ struct ipu6_isys *isys; -+ u32 const *supported_codes; -+ struct media_pad *pad; -+ struct v4l2_ctrl_handler ctrl_handler; -+ void (*ctrl_init)(struct v4l2_subdev *sd); -+ int source; /* SSI stream source; -1 if unset */ -+}; -+ -+#define to_ipu6_isys_subdev(__sd) \ -+ container_of(__sd, struct ipu6_isys_subdev, sd) -+ -+unsigned int ipu6_isys_mbus_code_to_bpp(u32 code); -+unsigned int ipu6_isys_mbus_code_to_mipi(u32 code); -+bool ipu6_isys_is_bayer_format(u32 code); -+u32 ipu6_isys_convert_bayer_order(u32 code, int x, int y); -+ -+int ipu6_isys_subdev_set_fmt(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state, -+ struct v4l2_subdev_format *fmt); -+int ipu6_isys_subdev_enum_mbus_code(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state, -+ struct v4l2_subdev_mbus_code_enum -+ *code); -+int ipu6_isys_subdev_link_validate(struct v4l2_subdev *sd, -+ struct media_link *link, -+ struct v4l2_subdev_format *source_fmt, -+ struct v4l2_subdev_format *sink_fmt); -+u32 ipu6_isys_get_src_stream_by_src_pad(struct v4l2_subdev *sd, u32 pad); -+int ipu6_isys_get_stream_pad_fmt(struct v4l2_subdev *sd, u32 pad, u32 stream, -+ struct v4l2_mbus_framefmt *format); -+int ipu6_isys_get_stream_pad_crop(struct v4l2_subdev *sd, u32 pad, u32 stream, -+ struct v4l2_rect *crop); -+int ipu6_isys_subdev_init_cfg(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state); -+int ipu6_isys_subdev_set_routing(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state, -+ enum v4l2_subdev_format_whence which, -+ struct v4l2_subdev_krouting *routing); -+int ipu6_isys_subdev_init(struct ipu6_isys_subdev *asd, -+ const struct v4l2_subdev_ops *ops, -+ unsigned int nr_ctrls, -+ unsigned int num_sink_pads, -+ unsigned int num_source_pads); -+void ipu6_isys_subdev_cleanup(struct ipu6_isys_subdev *asd); -+#endif /* IPU6_ISYS_SUBDEV_H */ -diff --git a/drivers/media/pci/intel/ipu6/ipu6-platform-isys-csi2-reg.h b/drivers/media/pci/intel/ipu6/ipu6-platform-isys-csi2-reg.h -new file mode 100644 -index 000000000000..2034e1109d98 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-platform-isys-csi2-reg.h -@@ -0,0 +1,189 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2023 Intel Corporation */ -+ -+#ifndef IPU6_PLATFORM_ISYS_CSI2_REG_H -+#define IPU6_PLATFORM_ISYS_CSI2_REG_H -+ -+#include <linux/bits.h> -+ -+#define CSI_REG_BASE 0x220000 -+#define CSI_REG_BASE_PORT(id) ((id) * 0x1000) -+ -+#define IPU6_CSI_PORT_A_ADDR_OFFSET \ -+ (CSI_REG_BASE + CSI_REG_BASE_PORT(0)) -+#define IPU6_CSI_PORT_B_ADDR_OFFSET \ -+ (CSI_REG_BASE + CSI_REG_BASE_PORT(1)) -+#define IPU6_CSI_PORT_C_ADDR_OFFSET \ -+ (CSI_REG_BASE + CSI_REG_BASE_PORT(2)) -+#define IPU6_CSI_PORT_D_ADDR_OFFSET \ -+ (CSI_REG_BASE + CSI_REG_BASE_PORT(3)) -+#define IPU6_CSI_PORT_E_ADDR_OFFSET \ -+ (CSI_REG_BASE + CSI_REG_BASE_PORT(4)) -+#define IPU6_CSI_PORT_F_ADDR_OFFSET \ -+ (CSI_REG_BASE + CSI_REG_BASE_PORT(5)) -+#define IPU6_CSI_PORT_G_ADDR_OFFSET \ -+ (CSI_REG_BASE + CSI_REG_BASE_PORT(6)) -+#define IPU6_CSI_PORT_H_ADDR_OFFSET \ -+ (CSI_REG_BASE + CSI_REG_BASE_PORT(7)) -+ -+/* CSI Port Genral Purpose Registers */ -+#define CSI_REG_PORT_GPREG_SRST 0x0 -+#define CSI_REG_PORT_GPREG_CSI2_SLV_REG_SRST 0x4 -+#define CSI_REG_PORT_GPREG_CSI2_PORT_CONTROL 0x8 -+ -+/* -+ * Port IRQs mapping events: -+ * IRQ0 - CSI_FE event -+ * IRQ1 - CSI_SYNC -+ * IRQ2 - S2M_SIDS0TO7 -+ * IRQ3 - S2M_SIDS8TO15 -+ */ -+#define CSI_PORT_REG_BASE_IRQ_CSI 0x80 -+#define CSI_PORT_REG_BASE_IRQ_CSI_SYNC 0xA0 -+#define CSI_PORT_REG_BASE_IRQ_S2M_SIDS0TOS7 0xC0 -+#define CSI_PORT_REG_BASE_IRQ_S2M_SIDS8TOS15 0xE0 -+ -+#define CSI_PORT_REG_BASE_IRQ_EDGE_OFFSET 0x0 -+#define CSI_PORT_REG_BASE_IRQ_MASK_OFFSET 0x4 -+#define CSI_PORT_REG_BASE_IRQ_STATUS_OFFSET 0x8 -+#define CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET 0xc -+#define CSI_PORT_REG_BASE_IRQ_ENABLE_OFFSET 0x10 -+#define CSI_PORT_REG_BASE_IRQ_LEVEL_NOT_PULSE_OFFSET 0x14 -+ -+#define IPU6SE_CSI_RX_ERROR_IRQ_MASK GENMASK(18, 0) -+#define IPU6_CSI_RX_ERROR_IRQ_MASK GENMASK(19, 0) -+ -+#define CSI_RX_NUM_ERRORS_IN_IRQ 20 -+#define CSI_RX_NUM_IRQ 32 -+ -+#define IPU_CSI_RX_IRQ_FS_VC(chn) (1 << ((chn) * 2)) -+#define IPU_CSI_RX_IRQ_FE_VC(chn) (2 << ((chn) * 2)) -+ -+/* PPI2CSI */ -+#define CSI_REG_PPI2CSI_ENABLE 0x200 -+#define CSI_REG_PPI2CSI_CONFIG_PPI_INTF 0x204 -+#define PPI_INTF_CONFIG_NOF_ENABLED_DLANES_MASK GENMASK(4, 3) -+#define CSI_REG_PPI2CSI_CONFIG_CSI_FEATURE 0x208 -+ -+enum CSI_PPI2CSI_CTRL { -+ CSI_PPI2CSI_DISABLE = 0, -+ CSI_PPI2CSI_ENABLE = 1, -+}; -+ -+/* CSI_FE */ -+#define CSI_REG_CSI_FE_ENABLE 0x280 -+#define CSI_REG_CSI_FE_MODE 0x284 -+#define CSI_REG_CSI_FE_MUX_CTRL 0x288 -+#define CSI_REG_CSI_FE_SYNC_CNTR_SEL 0x290 -+ -+enum CSI_FE_ENABLE_TYPE { -+ CSI_FE_DISABLE = 0, -+ CSI_FE_ENABLE = 1, -+}; -+ -+enum CSI_FE_MODE_TYPE { -+ CSI_FE_DPHY_MODE = 0, -+ CSI_FE_CPHY_MODE = 1, -+}; -+ -+enum CSI_FE_INPUT_SELECTOR { -+ CSI_SENSOR_INPUT = 0, -+ CSI_MIPIGEN_INPUT = 1, -+}; -+ -+enum CSI_FE_SYNC_CNTR_SEL_TYPE { -+ CSI_CNTR_SENSOR_LINE_ID = BIT(0), -+ CSI_CNTR_INT_LINE_PKT_ID = ~CSI_CNTR_SENSOR_LINE_ID, -+ CSI_CNTR_SENSOR_FRAME_ID = BIT(1), -+ CSI_CNTR_INT_FRAME_PKT_ID = ~CSI_CNTR_SENSOR_FRAME_ID, -+}; -+ -+/* CSI HUB General Purpose Registers */ -+#define CSI_REG_HUB_GPREG_SRST (CSI_REG_BASE + 0x18000) -+#define CSI_REG_HUB_GPREG_SLV_REG_SRST (CSI_REG_BASE + 0x18004) -+ -+#define CSI_REG_HUB_DRV_ACCESS_PORT(id) (CSI_REG_BASE + 0x18018 + (id) * 4) -+#define CSI_REG_HUB_FW_ACCESS_PORT_OFS 0x17000 -+#define CSI_REG_HUB_FW_ACCESS_PORT_V6OFS 0x16000 -+#define CSI_REG_HUB_FW_ACCESS_PORT(ofs, id) \ -+ (CSI_REG_BASE + (ofs) + (id) * 4) -+ -+enum CSI_PORT_CLK_GATING_SWITCH { -+ CSI_PORT_CLK_GATING_OFF = 0, -+ CSI_PORT_CLK_GATING_ON = 1, -+}; -+ -+#define CSI_REG_BASE_HUB_IRQ 0x18200 -+ -+#define IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_EDGE 0x238200 -+#define IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_MASK 0x238204 -+#define IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_STATUS 0x238208 -+#define IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_CLEAR 0x23820c -+#define IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_ENABLE 0x238210 -+#define IPU6_REG_ISYS_CSI_TOP_CTRL0_IRQ_LEVEL_NOT_PULSE 0x238214 -+ -+#define IPU6_REG_ISYS_CSI_TOP_CTRL1_IRQ_EDGE 0x238220 -+#define IPU6_REG_ISYS_CSI_TOP_CTRL1_IRQ_MASK 0x238224 -+#define IPU6_REG_ISYS_CSI_TOP_CTRL1_IRQ_STATUS 0x238228 -+#define IPU6_REG_ISYS_CSI_TOP_CTRL1_IRQ_CLEAR 0x23822c -+#define IPU6_REG_ISYS_CSI_TOP_CTRL1_IRQ_ENABLE 0x238230 -+#define IPU6_REG_ISYS_CSI_TOP_CTRL1_IRQ_LEVEL_NOT_PULSE 0x238234 -+ -+/* MTL IPU6V6 irq ctrl0 & ctrl1 */ -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_EDGE 0x238700 -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_MASK 0x238704 -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_STATUS 0x238708 -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_CLEAR 0x23870c -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_ENABLE 0x238710 -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL0_IRQ_LEVEL_NOT_PULSE 0x238714 -+ -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL1_IRQ_EDGE 0x238720 -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL1_IRQ_MASK 0x238724 -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL1_IRQ_STATUS 0x238728 -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL1_IRQ_CLEAR 0x23872c -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL1_IRQ_ENABLE 0x238730 -+#define IPU6V6_REG_ISYS_CSI_TOP_CTRL1_IRQ_LEVEL_NOT_PULSE 0x238734 -+ -+/* -+ * 3:0 CSI_PORT.irq_out[3:0] CSI_PORT_CTRL0 IRQ outputs (4bits) -+ * [0] CSI_PORT.IRQ_CTRL0_csi -+ * [1] CSI_PORT.IRQ_CTRL1_csi_sync -+ * [2] CSI_PORT.IRQ_CTRL2_s2m_sids0to7 -+ * [3] CSI_PORT.IRQ_CTRL3_s2m_sids8to15 -+ */ -+#define IPU6_ISYS_UNISPART_IRQ_CSI2(port) \ -+ (0x3 << ((port) * IPU6_CSI_IRQ_NUM_PER_PIPE)) -+ -+/* -+ * ipu6se support 2 front ends, 2 port per front end, 4 ports 0..3 -+ * sip0 - 0, 1 -+ * sip1 - 2, 3 -+ * 0 and 2 support 4 data lanes, 1 and 3 support 2 data lanes -+ * all offset are base from isys base address -+ */ -+ -+#define CSI2_HUB_GPREG_SIP_SRST(sip) (0x238038 + (sip) * 4) -+#define CSI2_HUB_GPREG_SIP_FB_PORT_CFG(sip) (0x238050 + (sip) * 4) -+ -+#define CSI2_HUB_GPREG_DPHY_TIMER_INCR 0x238040 -+#define CSI2_HUB_GPREG_HPLL_FREQ 0x238044 -+#define CSI2_HUB_GPREG_IS_CLK_RATIO 0x238048 -+#define CSI2_HUB_GPREG_HPLL_FREQ_ISCLK_RATE_OVERRIDE 0x23804c -+#define CSI2_HUB_GPREG_PORT_CLKGATING_DISABLE 0x238058 -+#define CSI2_HUB_GPREG_SIP0_CSI_RX_A_CONTROL 0x23805c -+#define CSI2_HUB_GPREG_SIP0_CSI_RX_B_CONTROL 0x238088 -+#define CSI2_HUB_GPREG_SIP1_CSI_RX_A_CONTROL 0x2380a4 -+#define CSI2_HUB_GPREG_SIP1_CSI_RX_B_CONTROL 0x2380d0 -+ -+#define CSI2_SIP_TOP_CSI_RX_BASE(sip) (0x23805c + (sip) * 0x48) -+#define CSI2_SIP_TOP_CSI_RX_PORT_BASE_0(port) (0x23805c + ((port) / 2) * 0x48) -+#define CSI2_SIP_TOP_CSI_RX_PORT_BASE_1(port) (0x238088 + ((port) / 2) * 0x48) -+ -+/* offset from port base */ -+#define CSI2_SIP_TOP_CSI_RX_PORT_CONTROL 0x0 -+#define CSI2_SIP_TOP_CSI_RX_DLY_CNT_TERMEN_CLANE 0x4 -+#define CSI2_SIP_TOP_CSI_RX_DLY_CNT_SETTLE_CLANE 0x8 -+#define CSI2_SIP_TOP_CSI_RX_DLY_CNT_TERMEN_DLANE(lane) (0xc + (lane) * 8) -+#define CSI2_SIP_TOP_CSI_RX_DLY_CNT_SETTLE_DLANE(lane) (0x10 + (lane) * 8) -+ -+#endif /* IPU6_ISYS_CSI2_REG_H */ --- -2.43.2 - - -From 71d3da5e8f1ea094e26030a12ceed4553cbe182a Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:23 +0800 -Subject: [PATCH 16/33] media: intel/ipu6: add the CSI2 DPHY implementation - -IPU6 CSI2 DPHY hardware varies on different platforms, current -IPU6 has three DPHY hardware instance which maybe used on tigerlake, -alderlake, metorlake and jasperlake. MCD DPHY is shipped on tigerlake -and alderlake, DWC DPHY is shipped on metorlake. - -Each PHY has its own register space, input system driver call the -DPHY callback which was set at isys_probe(). - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - .../media/pci/intel/ipu6/ipu6-isys-dwc-phy.c | 536 +++++++++++++ - .../media/pci/intel/ipu6/ipu6-isys-jsl-phy.c | 242 ++++++ - .../media/pci/intel/ipu6/ipu6-isys-mcd-phy.c | 720 ++++++++++++++++++ - 3 files changed, 1498 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys-jsl-phy.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys-mcd-phy.c - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c b/drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c -new file mode 100644 -index 000000000000..a4bb5ff51d4e ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c -@@ -0,0 +1,536 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/bitfield.h> -+#include <linux/bits.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <linux/iopoll.h> -+#include <linux/math64.h> -+ -+#include "ipu6-bus.h" -+#include "ipu6-isys.h" -+#include "ipu6-platform-isys-csi2-reg.h" -+ -+#define IPU6_DWC_DPHY_BASE(i) (0x238038 + 0x34 * (i)) -+#define IPU6_DWC_DPHY_RSTZ 0x00 -+#define IPU6_DWC_DPHY_SHUTDOWNZ 0x04 -+#define IPU6_DWC_DPHY_HSFREQRANGE 0x08 -+#define IPU6_DWC_DPHY_CFGCLKFREQRANGE 0x0c -+#define IPU6_DWC_DPHY_TEST_IFC_ACCESS_MODE 0x10 -+#define IPU6_DWC_DPHY_TEST_IFC_REQ 0x14 -+#define IPU6_DWC_DPHY_TEST_IFC_REQ_COMPLETION 0x18 -+#define IPU6_DWC_DPHY_DFT_CTRL0 0x28 -+#define IPU6_DWC_DPHY_DFT_CTRL1 0x2c -+#define IPU6_DWC_DPHY_DFT_CTRL2 0x30 -+ -+/* -+ * test IFC request definition: -+ * - req: 0 for read, 1 for write -+ * - 12 bits address -+ * - 8bits data (will ignore for read) -+ * --24----16------4-----0 -+ * --|-data-|-addr-|-req-| -+ */ -+#define IFC_REQ(req, addr, data) (FIELD_PREP(GENMASK(23, 16), data) | \ -+ FIELD_PREP(GENMASK(15, 4), addr) | \ -+ FIELD_PREP(GENMASK(1, 0), req)) -+ -+#define TEST_IFC_REQ_READ 0 -+#define TEST_IFC_REQ_WRITE 1 -+#define TEST_IFC_REQ_RESET 2 -+ -+#define TEST_IFC_ACCESS_MODE_FSM 0 -+#define TEST_IFC_ACCESS_MODE_IFC_CTL 1 -+ -+enum phy_fsm_state { -+ PHY_FSM_STATE_POWERON = 0, -+ PHY_FSM_STATE_BGPON = 1, -+ PHY_FSM_STATE_CAL_TYPE = 2, -+ PHY_FSM_STATE_BURNIN_CAL = 3, -+ PHY_FSM_STATE_TERMCAL = 4, -+ PHY_FSM_STATE_OFFSETCAL = 5, -+ PHY_FSM_STATE_OFFSET_LANE = 6, -+ PHY_FSM_STATE_IDLE = 7, -+ PHY_FSM_STATE_ULP = 8, -+ PHY_FSM_STATE_DDLTUNNING = 9, -+ PHY_FSM_STATE_SKEW_BACKWARD = 10, -+ PHY_FSM_STATE_INVALID, -+}; -+ -+static void dwc_dphy_write(struct ipu6_isys *isys, u32 phy_id, u32 addr, -+ u32 data) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *isys_base = isys->pdata->base; -+ void __iomem *base = isys_base + IPU6_DWC_DPHY_BASE(phy_id); -+ -+ dev_dbg(dev, "write: reg 0x%lx = data 0x%x", base + addr - isys_base, -+ data); -+ writel(data, base + addr); -+} -+ -+static u32 dwc_dphy_read(struct ipu6_isys *isys, u32 phy_id, u32 addr) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *isys_base = isys->pdata->base; -+ void __iomem *base = isys_base + IPU6_DWC_DPHY_BASE(phy_id); -+ u32 data; -+ -+ data = readl(base + addr); -+ dev_dbg(dev, "read: reg 0x%lx = data 0x%x", base + addr - isys_base, -+ data); -+ -+ return data; -+} -+ -+static void dwc_dphy_write_mask(struct ipu6_isys *isys, u32 phy_id, u32 addr, -+ u32 data, u8 shift, u8 width) -+{ -+ u32 temp; -+ u32 mask; -+ -+ mask = (1 << width) - 1; -+ temp = dwc_dphy_read(isys, phy_id, addr); -+ temp &= ~(mask << shift); -+ temp |= (data & mask) << shift; -+ dwc_dphy_write(isys, phy_id, addr, temp); -+} -+ -+static u32 __maybe_unused dwc_dphy_read_mask(struct ipu6_isys *isys, u32 phy_id, -+ u32 addr, u8 shift, u8 width) -+{ -+ u32 val; -+ -+ val = dwc_dphy_read(isys, phy_id, addr) >> shift; -+ return val & ((1 << width) - 1); -+} -+ -+#define DWC_DPHY_TIMEOUT (5 * USEC_PER_SEC) -+static int dwc_dphy_ifc_read(struct ipu6_isys *isys, u32 phy_id, u32 addr, -+ u32 *val) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *isys_base = isys->pdata->base; -+ void __iomem *base = isys_base + IPU6_DWC_DPHY_BASE(phy_id); -+ void __iomem *reg; -+ u32 completion; -+ int ret; -+ -+ dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_TEST_IFC_REQ, -+ IFC_REQ(TEST_IFC_REQ_READ, addr, 0)); -+ reg = base + IPU6_DWC_DPHY_TEST_IFC_REQ_COMPLETION; -+ ret = readl_poll_timeout(reg, completion, !(completion & BIT(0)), -+ 10, DWC_DPHY_TIMEOUT); -+ if (ret) { -+ dev_err(dev, "DWC ifc request read timeout\n"); -+ return ret; -+ } -+ -+ *val = completion >> 8 & 0xff; -+ *val = FIELD_GET(GENMASK(15, 8), completion); -+ dev_dbg(dev, "DWC ifc read 0x%x = 0x%x", addr, *val); -+ -+ return 0; -+} -+ -+static int dwc_dphy_ifc_write(struct ipu6_isys *isys, u32 phy_id, u32 addr, -+ u32 data) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *isys_base = isys->pdata->base; -+ void __iomem *base = isys_base + IPU6_DWC_DPHY_BASE(phy_id); -+ void __iomem *reg; -+ u32 completion; -+ int ret; -+ -+ dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_TEST_IFC_REQ, -+ IFC_REQ(TEST_IFC_REQ_WRITE, addr, data)); -+ completion = readl(base + IPU6_DWC_DPHY_TEST_IFC_REQ_COMPLETION); -+ reg = base + IPU6_DWC_DPHY_TEST_IFC_REQ_COMPLETION; -+ ret = readl_poll_timeout(reg, completion, !(completion & BIT(0)), -+ 10, DWC_DPHY_TIMEOUT); -+ if (ret) -+ dev_err(dev, "DWC ifc request write timeout\n"); -+ -+ return ret; -+} -+ -+static void dwc_dphy_ifc_write_mask(struct ipu6_isys *isys, u32 phy_id, -+ u32 addr, u32 data, u8 shift, u8 width) -+{ -+ u32 temp, mask; -+ int ret; -+ -+ ret = dwc_dphy_ifc_read(isys, phy_id, addr, &temp); -+ if (ret) -+ return; -+ -+ mask = (1 << width) - 1; -+ temp &= ~(mask << shift); -+ temp |= (data & mask) << shift; -+ dwc_dphy_ifc_write(isys, phy_id, addr, temp); -+} -+ -+static u32 dwc_dphy_ifc_read_mask(struct ipu6_isys *isys, u32 phy_id, u32 addr, -+ u8 shift, u8 width) -+{ -+ int ret; -+ u32 val; -+ -+ ret = dwc_dphy_ifc_read(isys, phy_id, addr, &val); -+ if (ret) -+ return 0; -+ -+ return ((val >> shift) & ((1 << width) - 1)); -+} -+ -+static int dwc_dphy_pwr_up(struct ipu6_isys *isys, u32 phy_id) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ u32 fsm_state; -+ int ret; -+ -+ dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_RSTZ, 1); -+ usleep_range(10, 20); -+ dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_SHUTDOWNZ, 1); -+ -+ ret = read_poll_timeout(dwc_dphy_ifc_read_mask, fsm_state, -+ (fsm_state == PHY_FSM_STATE_IDLE || -+ fsm_state == PHY_FSM_STATE_ULP), -+ 100, DWC_DPHY_TIMEOUT, false, isys, -+ phy_id, 0x1e, 0, 4); -+ -+ if (ret) -+ dev_err(dev, "Dphy %d power up failed, state 0x%x", phy_id, -+ fsm_state); -+ -+ return ret; -+} -+ -+struct dwc_dphy_freq_range { -+ u8 hsfreq; -+ u16 min; -+ u16 max; -+ u16 default_mbps; -+ u16 osc_freq_target; -+}; -+ -+#define DPHY_FREQ_RANGE_NUM (63) -+#define DPHY_FREQ_RANGE_INVALID_INDEX (0xff) -+static const struct dwc_dphy_freq_range freqranges[DPHY_FREQ_RANGE_NUM] = { -+ {0x00, 80, 97, 80, 335}, -+ {0x10, 80, 107, 90, 335}, -+ {0x20, 84, 118, 100, 335}, -+ {0x30, 93, 128, 110, 335}, -+ {0x01, 103, 139, 120, 335}, -+ {0x11, 112, 149, 130, 335}, -+ {0x21, 122, 160, 140, 335}, -+ {0x31, 131, 170, 150, 335}, -+ {0x02, 141, 181, 160, 335}, -+ {0x12, 150, 191, 170, 335}, -+ {0x22, 160, 202, 180, 335}, -+ {0x32, 169, 212, 190, 335}, -+ {0x03, 183, 228, 205, 335}, -+ {0x13, 198, 244, 220, 335}, -+ {0x23, 212, 259, 235, 335}, -+ {0x33, 226, 275, 250, 335}, -+ {0x04, 250, 301, 275, 335}, -+ {0x14, 274, 328, 300, 335}, -+ {0x25, 297, 354, 325, 335}, -+ {0x35, 321, 380, 350, 335}, -+ {0x05, 369, 433, 400, 335}, -+ {0x16, 416, 485, 450, 335}, -+ {0x26, 464, 538, 500, 335}, -+ {0x37, 511, 590, 550, 335}, -+ {0x07, 559, 643, 600, 335}, -+ {0x18, 606, 695, 650, 335}, -+ {0x28, 654, 748, 700, 335}, -+ {0x39, 701, 800, 750, 335}, -+ {0x09, 749, 853, 800, 335}, -+ {0x19, 796, 905, 850, 335}, -+ {0x29, 844, 958, 900, 335}, -+ {0x3a, 891, 1010, 950, 335}, -+ {0x0a, 939, 1063, 1000, 335}, -+ {0x1a, 986, 1115, 1050, 335}, -+ {0x2a, 1034, 1168, 1100, 335}, -+ {0x3b, 1081, 1220, 1150, 335}, -+ {0x0b, 1129, 1273, 1200, 335}, -+ {0x1b, 1176, 1325, 1250, 335}, -+ {0x2b, 1224, 1378, 1300, 335}, -+ {0x3c, 1271, 1430, 1350, 335}, -+ {0x0c, 1319, 1483, 1400, 335}, -+ {0x1c, 1366, 1535, 1450, 335}, -+ {0x2c, 1414, 1588, 1500, 335}, -+ {0x3d, 1461, 1640, 1550, 208}, -+ {0x0d, 1509, 1693, 1600, 214}, -+ {0x1d, 1556, 1745, 1650, 221}, -+ {0x2e, 1604, 1798, 1700, 228}, -+ {0x3e, 1651, 1850, 1750, 234}, -+ {0x0e, 1699, 1903, 1800, 241}, -+ {0x1e, 1746, 1955, 1850, 248}, -+ {0x2f, 1794, 2008, 1900, 255}, -+ {0x3f, 1841, 2060, 1950, 261}, -+ {0x0f, 1889, 2113, 2000, 268}, -+ {0x40, 1936, 2165, 2050, 275}, -+ {0x41, 1984, 2218, 2100, 281}, -+ {0x42, 2031, 2270, 2150, 288}, -+ {0x43, 2079, 2323, 2200, 294}, -+ {0x44, 2126, 2375, 2250, 302}, -+ {0x45, 2174, 2428, 2300, 308}, -+ {0x46, 2221, 2480, 2350, 315}, -+ {0x47, 2269, 2500, 2400, 321}, -+ {0x48, 2316, 2500, 2450, 328}, -+ {0x49, 2364, 2500, 2500, 335} -+}; -+ -+static u16 get_hsfreq_by_mbps(u32 mbps) -+{ -+ unsigned int i = DPHY_FREQ_RANGE_NUM; -+ -+ while (i--) { -+ if (freqranges[i].default_mbps == mbps || -+ (mbps >= freqranges[i].min && mbps <= freqranges[i].max)) -+ return i; -+ } -+ -+ return DPHY_FREQ_RANGE_INVALID_INDEX; -+} -+ -+static int ipu6_isys_dwc_phy_config(struct ipu6_isys *isys, -+ u32 phy_id, u32 mbps) -+{ -+ struct ipu6_bus_device *adev = isys->adev; -+ struct device *dev = &adev->auxdev.dev; -+ struct ipu6_device *isp = adev->isp; -+ u32 cfg_clk_freqrange; -+ u32 osc_freq_target; -+ u32 index; -+ -+ dev_dbg(dev, "config Dphy %u with %u mbps", phy_id, mbps); -+ -+ index = get_hsfreq_by_mbps(mbps); -+ if (index == DPHY_FREQ_RANGE_INVALID_INDEX) { -+ dev_err(dev, "link freq not found for mbps %u", mbps); -+ return -EINVAL; -+ } -+ -+ dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_HSFREQRANGE, -+ freqranges[index].hsfreq, 0, 7); -+ -+ /* Force termination Calibration */ -+ if (isys->phy_termcal_val) { -+ dwc_dphy_ifc_write_mask(isys, phy_id, 0x20a, 0x1, 0, 1); -+ dwc_dphy_ifc_write_mask(isys, phy_id, 0x209, 0x3, 0, 2); -+ dwc_dphy_ifc_write_mask(isys, phy_id, 0x209, -+ isys->phy_termcal_val, 4, 4); -+ } -+ -+ /* -+ * Enable override to configure the DDL target oscillation -+ * frequency on bit 0 of register 0xe4 -+ */ -+ dwc_dphy_ifc_write_mask(isys, phy_id, 0xe4, 0x1, 0, 1); -+ /* -+ * configure registers 0xe2, 0xe3 with the -+ * appropriate DDL target oscillation frequency -+ * 0x1cc(460) -+ */ -+ osc_freq_target = freqranges[index].osc_freq_target; -+ dwc_dphy_ifc_write_mask(isys, phy_id, 0xe2, -+ osc_freq_target & 0xff, 0, 8); -+ dwc_dphy_ifc_write_mask(isys, phy_id, 0xe3, -+ (osc_freq_target >> 8) & 0xf, 0, 4); -+ -+ if (mbps < 1500) { -+ /* deskew_polarity_rw, for < 1.5Gbps */ -+ dwc_dphy_ifc_write_mask(isys, phy_id, 0x8, 0x1, 5, 1); -+ } -+ -+ /* -+ * Set cfgclkfreqrange[5:0] = round[(Fcfg_clk(MHz)-17)*4] -+ * (38.4 - 17) * 4 = ~85 (0x55) -+ */ -+ cfg_clk_freqrange = (isp->buttress.ref_clk - 170) * 4 / 10; -+ dev_dbg(dev, "ref_clk = %u clk_freqrange = %u", -+ isp->buttress.ref_clk, cfg_clk_freqrange); -+ dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_CFGCLKFREQRANGE, -+ cfg_clk_freqrange, 0, 8); -+ -+ dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_DFT_CTRL2, 0x1, 4, 1); -+ dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_DFT_CTRL2, 0x1, 8, 1); -+ -+ return 0; -+} -+ -+static void ipu6_isys_dwc_phy_aggr_setup(struct ipu6_isys *isys, u32 master, -+ u32 slave, u32 mbps) -+{ -+ /* Config mastermacro */ -+ dwc_dphy_ifc_write_mask(isys, master, 0x133, 0x1, 0, 1); -+ dwc_dphy_ifc_write_mask(isys, slave, 0x133, 0x0, 0, 1); -+ -+ /* Config master PHY clk lane to drive long channel clk */ -+ dwc_dphy_ifc_write_mask(isys, master, 0x307, 0x1, 2, 1); -+ dwc_dphy_ifc_write_mask(isys, slave, 0x307, 0x0, 2, 1); -+ -+ /* Config both PHYs data lanes to get clk from long channel */ -+ dwc_dphy_ifc_write_mask(isys, master, 0x508, 0x1, 5, 1); -+ dwc_dphy_ifc_write_mask(isys, slave, 0x508, 0x1, 5, 1); -+ dwc_dphy_ifc_write_mask(isys, master, 0x708, 0x1, 5, 1); -+ dwc_dphy_ifc_write_mask(isys, slave, 0x708, 0x1, 5, 1); -+ -+ /* Config slave PHY clk lane to bypass long channel clk to DDR clk */ -+ dwc_dphy_ifc_write_mask(isys, master, 0x308, 0x0, 3, 1); -+ dwc_dphy_ifc_write_mask(isys, slave, 0x308, 0x1, 3, 1); -+ -+ /* Override slave PHY clk lane enable (DPHYRXCLK_CLL_demux module) */ -+ dwc_dphy_ifc_write_mask(isys, slave, 0xe0, 0x3, 0, 2); -+ -+ /* Override slave PHY DDR clk lane enable (DPHYHSRX_div124 module) */ -+ dwc_dphy_ifc_write_mask(isys, slave, 0xe1, 0x1, 1, 1); -+ dwc_dphy_ifc_write_mask(isys, slave, 0x307, 0x1, 3, 1); -+ -+ /* Turn off slave PHY LP-RX clk lane */ -+ dwc_dphy_ifc_write_mask(isys, slave, 0x304, 0x1, 7, 1); -+ dwc_dphy_ifc_write_mask(isys, slave, 0x305, 0xa, 0, 5); -+} -+ -+#define PHY_E 4 -+static int ipu6_isys_dwc_phy_powerup_ack(struct ipu6_isys *isys, u32 phy_id) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ u32 rescal_done; -+ int ret; -+ -+ ret = dwc_dphy_pwr_up(isys, phy_id); -+ if (ret != 0) { -+ dev_err(dev, "Dphy %u power up failed(%d)", phy_id, ret); -+ return ret; -+ } -+ -+ /* reset forcerxmode */ -+ dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_DFT_CTRL2, 0, 4, 1); -+ dwc_dphy_write_mask(isys, phy_id, IPU6_DWC_DPHY_DFT_CTRL2, 0, 8, 1); -+ -+ dev_dbg(dev, "Dphy %u is ready!", phy_id); -+ -+ if (phy_id != PHY_E || isys->phy_termcal_val) -+ return 0; -+ -+ usleep_range(100, 200); -+ rescal_done = dwc_dphy_ifc_read_mask(isys, phy_id, 0x221, 7, 1); -+ if (rescal_done) { -+ isys->phy_termcal_val = dwc_dphy_ifc_read_mask(isys, phy_id, -+ 0x220, 2, 4); -+ dev_dbg(dev, "termcal done with value = %u", -+ isys->phy_termcal_val); -+ } -+ -+ return 0; -+} -+ -+static void ipu6_isys_dwc_phy_reset(struct ipu6_isys *isys, u32 phy_id) -+{ -+ dev_dbg(&isys->adev->auxdev.dev, "Reset phy %u", phy_id); -+ -+ dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_SHUTDOWNZ, 0); -+ dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_RSTZ, 0); -+ dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_TEST_IFC_ACCESS_MODE, -+ TEST_IFC_ACCESS_MODE_FSM); -+ dwc_dphy_write(isys, phy_id, IPU6_DWC_DPHY_TEST_IFC_REQ, -+ TEST_IFC_REQ_RESET); -+} -+ -+int ipu6_isys_dwc_phy_set_power(struct ipu6_isys *isys, -+ struct ipu6_isys_csi2_config *cfg, -+ const struct ipu6_isys_csi2_timing *timing, -+ bool on) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *isys_base = isys->pdata->base; -+ u32 phy_id, primary, secondary; -+ u32 nlanes, port, mbps; -+ s64 link_freq; -+ int ret; -+ -+ port = cfg->port; -+ -+ if (!isys_base || port >= isys->pdata->ipdata->csi2.nports) { -+ dev_warn(dev, "invalid port ID %d\n", port); -+ return -EINVAL; -+ } -+ -+ nlanes = cfg->nlanes; -+ /* only port 0, 2 and 4 support 4 lanes */ -+ if (nlanes == 4 && port % 2) { -+ dev_err(dev, "invalid csi-port %u with %u lanes\n", port, -+ nlanes); -+ return -EINVAL; -+ } -+ -+ link_freq = ipu6_isys_csi2_get_link_freq(&isys->csi2[port]); -+ if (link_freq < 0) { -+ dev_err(dev, "get link freq failed(%lld).\n", link_freq); -+ return link_freq; -+ } -+ -+ mbps = div_u64(link_freq, 500000); -+ -+ phy_id = port; -+ primary = port & ~1; -+ secondary = primary + 1; -+ if (on) { -+ if (nlanes == 4) { -+ dev_dbg(dev, "config phy %u and %u in aggr mode\n", -+ primary, secondary); -+ -+ ipu6_isys_dwc_phy_reset(isys, primary); -+ ipu6_isys_dwc_phy_reset(isys, secondary); -+ ipu6_isys_dwc_phy_aggr_setup(isys, primary, -+ secondary, mbps); -+ -+ ret = ipu6_isys_dwc_phy_config(isys, primary, mbps); -+ if (ret) -+ return ret; -+ ret = ipu6_isys_dwc_phy_config(isys, secondary, mbps); -+ if (ret) -+ return ret; -+ -+ ret = ipu6_isys_dwc_phy_powerup_ack(isys, primary); -+ if (ret) -+ return ret; -+ -+ ret = ipu6_isys_dwc_phy_powerup_ack(isys, secondary); -+ return ret; -+ } -+ -+ dev_dbg(dev, "config phy %u with %u lanes in non-aggr mode\n", -+ phy_id, nlanes); -+ -+ ipu6_isys_dwc_phy_reset(isys, phy_id); -+ ret = ipu6_isys_dwc_phy_config(isys, phy_id, mbps); -+ if (ret) -+ return ret; -+ -+ ret = ipu6_isys_dwc_phy_powerup_ack(isys, phy_id); -+ return ret; -+ } -+ -+ if (nlanes == 4) { -+ dev_dbg(dev, "Power down phy %u and phy %u for port %u\n", -+ primary, secondary, port); -+ ipu6_isys_dwc_phy_reset(isys, secondary); -+ ipu6_isys_dwc_phy_reset(isys, primary); -+ -+ return 0; -+ } -+ -+ dev_dbg(dev, "Powerdown phy %u with %u lanes\n", phy_id, nlanes); -+ -+ ipu6_isys_dwc_phy_reset(isys, phy_id); -+ -+ return 0; -+} -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-jsl-phy.c b/drivers/media/pci/intel/ipu6/ipu6-isys-jsl-phy.c -new file mode 100644 -index 000000000000..dcc7743e0cee ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-jsl-phy.c -@@ -0,0 +1,242 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/bitfield.h> -+#include <linux/bits.h> -+#include <linux/device.h> -+#include <linux/io.h> -+ -+#include "ipu6-bus.h" -+#include "ipu6-isys.h" -+#include "ipu6-isys-csi2.h" -+#include "ipu6-platform-isys-csi2-reg.h" -+ -+/* only use BB0, BB2, BB4, and BB6 on PHY0 */ -+#define IPU6SE_ISYS_PHY_BB_NUM 4 -+#define IPU6SE_ISYS_PHY_0_BASE 0x10000 -+ -+#define PHY_CPHY_DLL_OVRD(x) (0x100 + 0x100 * (x)) -+#define PHY_CPHY_RX_CONTROL1(x) (0x110 + 0x100 * (x)) -+#define PHY_DPHY_CFG(x) (0x148 + 0x100 * (x)) -+#define PHY_BB_AFE_CONFIG(x) (0x174 + 0x100 * (x)) -+ -+/* -+ * use port_cfg to configure that which data lanes used -+ * +---------+ +------+ +-----+ -+ * | port0 x4<-----| | | | -+ * | | | port | | | -+ * | port1 x2<-----| | | | -+ * | | | <-| PHY | -+ * | port2 x4<-----| | | | -+ * | | |config| | | -+ * | port3 x2<-----| | | | -+ * +---------+ +------+ +-----+ -+ */ -+static const unsigned int csi2_port_cfg[][3] = { -+ {0, 0, 0x1f}, /* no link */ -+ {4, 0, 0x10}, /* x4 + x4 config */ -+ {2, 0, 0x12}, /* x2 + x2 config */ -+ {1, 0, 0x13}, /* x1 + x1 config */ -+ {2, 1, 0x15}, /* x2x1 + x2x1 config */ -+ {1, 1, 0x16}, /* x1x1 + x1x1 config */ -+ {2, 2, 0x18}, /* x2x2 + x2x2 config */ -+ {1, 2, 0x19} /* x1x2 + x1x2 config */ -+}; -+ -+/* port, nlanes, bbindex, portcfg */ -+static const unsigned int phy_port_cfg[][4] = { -+ /* sip0 */ -+ {0, 1, 0, 0x15}, -+ {0, 2, 0, 0x15}, -+ {0, 4, 0, 0x15}, -+ {0, 4, 2, 0x22}, -+ /* sip1 */ -+ {2, 1, 4, 0x15}, -+ {2, 2, 4, 0x15}, -+ {2, 4, 4, 0x15}, -+ {2, 4, 6, 0x22} -+}; -+ -+static void ipu6_isys_csi2_phy_config_by_port(struct ipu6_isys *isys, -+ unsigned int port, -+ unsigned int nlanes) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *base = isys->adev->isp->base; -+ unsigned int bbnum; -+ u32 val, reg, i; -+ -+ dev_dbg(dev, "port %u with %u lanes", port, nlanes); -+ -+ /* only support <1.5Gbps */ -+ for (i = 0; i < IPU6SE_ISYS_PHY_BB_NUM; i++) { -+ /* cphy_dll_ovrd.crcdc_fsm_dlane0 = 13 */ -+ reg = IPU6SE_ISYS_PHY_0_BASE + PHY_CPHY_DLL_OVRD(i); -+ val = readl(base + reg); -+ val |= FIELD_PREP(GENMASK(6, 1), 13); -+ writel(val, base + reg); -+ -+ /* cphy_rx_control1.en_crc1 = 1 */ -+ reg = IPU6SE_ISYS_PHY_0_BASE + PHY_CPHY_RX_CONTROL1(i); -+ val = readl(base + reg); -+ val |= BIT(31); -+ writel(val, base + reg); -+ -+ /* dphy_cfg.reserved = 1, .lden_from_dll_ovrd_0 = 1 */ -+ reg = IPU6SE_ISYS_PHY_0_BASE + PHY_DPHY_CFG(i); -+ val = readl(base + reg); -+ val |= BIT(25) | BIT(26); -+ writel(val, base + reg); -+ -+ /* cphy_dll_ovrd.lden_crcdc_fsm_dlane0 = 1 */ -+ reg = IPU6SE_ISYS_PHY_0_BASE + PHY_CPHY_DLL_OVRD(i); -+ val = readl(base + reg); -+ val |= BIT(0); -+ writel(val, base + reg); -+ } -+ -+ /* Front end config, use minimal channel loss */ -+ for (i = 0; i < ARRAY_SIZE(phy_port_cfg); i++) { -+ if (phy_port_cfg[i][0] == port && -+ phy_port_cfg[i][1] == nlanes) { -+ bbnum = phy_port_cfg[i][2] / 2; -+ reg = IPU6SE_ISYS_PHY_0_BASE + PHY_BB_AFE_CONFIG(bbnum); -+ val = readl(base + reg); -+ val |= phy_port_cfg[i][3]; -+ writel(val, base + reg); -+ } -+ } -+} -+ -+static void ipu6_isys_csi2_rx_control(struct ipu6_isys *isys) -+{ -+ void __iomem *base = isys->adev->isp->base; -+ u32 val, reg; -+ -+ reg = CSI2_HUB_GPREG_SIP0_CSI_RX_A_CONTROL; -+ val = readl(base + reg); -+ val |= BIT(0); -+ writel(val, base + CSI2_HUB_GPREG_SIP0_CSI_RX_A_CONTROL); -+ -+ reg = CSI2_HUB_GPREG_SIP0_CSI_RX_B_CONTROL; -+ val = readl(base + reg); -+ val |= BIT(0); -+ writel(val, base + CSI2_HUB_GPREG_SIP0_CSI_RX_B_CONTROL); -+ -+ reg = CSI2_HUB_GPREG_SIP1_CSI_RX_A_CONTROL; -+ val = readl(base + reg); -+ val |= BIT(0); -+ writel(val, base + CSI2_HUB_GPREG_SIP1_CSI_RX_A_CONTROL); -+ -+ reg = CSI2_HUB_GPREG_SIP1_CSI_RX_B_CONTROL; -+ val = readl(base + reg); -+ val |= BIT(0); -+ writel(val, base + CSI2_HUB_GPREG_SIP1_CSI_RX_B_CONTROL); -+} -+ -+static int ipu6_isys_csi2_set_port_cfg(struct ipu6_isys *isys, -+ unsigned int port, unsigned int nlanes) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ unsigned int sip = port / 2; -+ unsigned int index; -+ -+ switch (nlanes) { -+ case 1: -+ index = 5; -+ break; -+ case 2: -+ index = 6; -+ break; -+ case 4: -+ index = 1; -+ break; -+ default: -+ dev_err(dev, "lanes nr %u is unsupported\n", nlanes); -+ return -EINVAL; -+ } -+ -+ dev_dbg(dev, "port config for port %u with %u lanes\n", port, nlanes); -+ -+ writel(csi2_port_cfg[index][2], -+ isys->pdata->base + CSI2_HUB_GPREG_SIP_FB_PORT_CFG(sip)); -+ -+ return 0; -+} -+ -+static void -+ipu6_isys_csi2_set_timing(struct ipu6_isys *isys, -+ const struct ipu6_isys_csi2_timing *timing, -+ unsigned int port, unsigned int nlanes) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *reg; -+ u32 port_base; -+ u32 i; -+ -+ port_base = (port % 2) ? CSI2_SIP_TOP_CSI_RX_PORT_BASE_1(port) : -+ CSI2_SIP_TOP_CSI_RX_PORT_BASE_0(port); -+ -+ dev_dbg(dev, "set timing for port %u with %u lanes\n", port, nlanes); -+ -+ reg = isys->pdata->base + port_base; -+ reg += CSI2_SIP_TOP_CSI_RX_DLY_CNT_TERMEN_CLANE; -+ -+ writel(timing->ctermen, reg); -+ -+ reg = isys->pdata->base + port_base; -+ reg += CSI2_SIP_TOP_CSI_RX_DLY_CNT_SETTLE_CLANE; -+ writel(timing->csettle, reg); -+ -+ for (i = 0; i < nlanes; i++) { -+ reg = isys->pdata->base + port_base; -+ reg += CSI2_SIP_TOP_CSI_RX_DLY_CNT_TERMEN_DLANE(i); -+ writel(timing->dtermen, reg); -+ -+ reg = isys->pdata->base + port_base; -+ reg += CSI2_SIP_TOP_CSI_RX_DLY_CNT_SETTLE_DLANE(i); -+ writel(timing->dsettle, reg); -+ } -+} -+ -+#define DPHY_TIMER_INCR 0x28 -+int ipu6_isys_jsl_phy_set_power(struct ipu6_isys *isys, -+ struct ipu6_isys_csi2_config *cfg, -+ const struct ipu6_isys_csi2_timing *timing, -+ bool on) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *isys_base = isys->pdata->base; -+ int ret = 0; -+ u32 nlanes; -+ u32 port; -+ -+ if (!on) -+ return 0; -+ -+ port = cfg->port; -+ nlanes = cfg->nlanes; -+ -+ if (!isys_base || port >= isys->pdata->ipdata->csi2.nports) { -+ dev_warn(dev, "invalid port ID %d\n", port); -+ return -EINVAL; -+ } -+ -+ ipu6_isys_csi2_phy_config_by_port(isys, port, nlanes); -+ -+ writel(DPHY_TIMER_INCR, -+ isys->pdata->base + CSI2_HUB_GPREG_DPHY_TIMER_INCR); -+ -+ /* set port cfg and rx timing */ -+ ipu6_isys_csi2_set_timing(isys, timing, port, nlanes); -+ -+ ret = ipu6_isys_csi2_set_port_cfg(isys, port, nlanes); -+ if (ret) -+ return ret; -+ -+ ipu6_isys_csi2_rx_control(isys); -+ -+ return 0; -+} -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-mcd-phy.c b/drivers/media/pci/intel/ipu6/ipu6-isys-mcd-phy.c -new file mode 100644 -index 000000000000..9abf389a05f1 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-mcd-phy.c -@@ -0,0 +1,720 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/bits.h> -+#include <linux/container_of.h> -+#include <linux/device.h> -+#include <linux/iopoll.h> -+#include <linux/list.h> -+#include <linux/refcount.h> -+#include <linux/time64.h> -+ -+#include <media/v4l2-async.h> -+ -+#include "ipu6.h" -+#include "ipu6-bus.h" -+#include "ipu6-isys.h" -+#include "ipu6-isys-csi2.h" -+#include "ipu6-platform-isys-csi2-reg.h" -+ -+#define CSI_REG_HUB_GPREG_PHY_CTL(id) (CSI_REG_BASE + 0x18008 + (id) * 0x8) -+#define CSI_REG_HUB_GPREG_PHY_CTL_RESET BIT(4) -+#define CSI_REG_HUB_GPREG_PHY_CTL_PWR_EN BIT(0) -+#define CSI_REG_HUB_GPREG_PHY_STATUS(id) (CSI_REG_BASE + 0x1800c + (id) * 0x8) -+#define CSI_REG_HUB_GPREG_PHY_POWER_ACK BIT(0) -+#define CSI_REG_HUB_GPREG_PHY_READY BIT(4) -+ -+#define MCD_PHY_POWER_STATUS_TIMEOUT (200 * USEC_PER_MSEC) -+ -+/* -+ * bridge to phy in buttress reg map, each phy has 16 kbytes -+ * only 2 phys for TGL U and Y -+ */ -+#define IPU6_ISYS_MCD_PHY_BASE(i) (0x10000 + (i) * 0x4000) -+ -+/* -+ * There are 2 MCD DPHY instances on TGL and 1 MCD DPHY instance on ADL. -+ * Each MCD PHY has 12-lanes which has 8 data lanes and 4 clock lanes. -+ * CSI port 1, 3 (5, 7) can support max 2 data lanes. -+ * CSI port 0, 2 (4, 6) can support max 4 data lanes. -+ * PHY configurations are PPI based instead of port. -+ * Left: -+ * +---------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | PPI | PPI5 | PPI4 | PPI3 | PPI2 | PPI1 | PPI0 | -+ * +---------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | x4 | unused | D3 | D2 | C0 | D0 | D1 | -+ * |---------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | x2x2 | C1 | D0 | D1 | C0 | D0 | D1 | -+ * ----------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | x2x1 | C1 | D0 | unused | C0 | D0 | D1 | -+ * +---------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | x1x1 | C1 | D0 | unused | C0 | D0 | unused | -+ * +---------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | x1x2 | C1 | D0 | D1 | C0 | D0 | unused | -+ * +---------+---------+---------+---------+--------+---------+----------+ -+ * -+ * Right: -+ * +---------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | PPI | PPI6 | PPI7 | PPI8 | PPI9 | PPI10 | PPI11 | -+ * +---------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | x4 | D1 | D0 | C2 | D2 | D3 | unused | -+ * |---------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | x2x2 | D1 | D0 | C2 | D1 | D0 | C3 | -+ * ----------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | x2x1 | D1 | D0 | C2 | unused | D0 | C3 | -+ * +---------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | x1x1 | unused | D0 | C2 | unused | D0 | C3 | -+ * +---------+---------+---------+---------+--------+---------+----------+ -+ * | | | | | | | | -+ * | x1x2 | unused | D0 | C2 | D1 | D0 | C3 | -+ * +---------+---------+---------+---------+--------+---------+----------+ -+ * -+ * ppi mapping per phy : -+ * -+ * x4 + x4: -+ * Left : port0 - PPI range {0, 1, 2, 3, 4} -+ * Right: port2 - PPI range {6, 7, 8, 9, 10} -+ * -+ * x4 + x2x2: -+ * Left: port0 - PPI range {0, 1, 2, 3, 4} -+ * Right: port2 - PPI range {6, 7, 8}, port3 - PPI range {9, 10, 11} -+ * -+ * x2x2 + x4: -+ * Left: port0 - PPI range {0, 1, 2}, port1 - PPI range {3, 4, 5} -+ * Right: port2 - PPI range {6, 7, 8, 9, 10} -+ * -+ * x2x2 + x2x2: -+ * Left : port0 - PPI range {0, 1, 2}, port1 - PPI range {3, 4, 5} -+ * Right: port2 - PPI range {6, 7, 8}, port3 - PPI range {9, 10, 11} -+ */ -+ -+struct phy_reg { -+ u32 reg; -+ u32 val; -+}; -+ -+static const struct phy_reg common_init_regs[] = { -+ /* for TGL-U, use 0x80000000 */ -+ {0x00000040, 0x80000000}, -+ {0x00000044, 0x00a80880}, -+ {0x00000044, 0x00b80880}, -+ {0x00000010, 0x0000078c}, -+ {0x00000344, 0x2f4401e2}, -+ {0x00000544, 0x924401e2}, -+ {0x00000744, 0x594401e2}, -+ {0x00000944, 0x624401e2}, -+ {0x00000b44, 0xfc4401e2}, -+ {0x00000d44, 0xc54401e2}, -+ {0x00000f44, 0x034401e2}, -+ {0x00001144, 0x8f4401e2}, -+ {0x00001344, 0x754401e2}, -+ {0x00001544, 0xe94401e2}, -+ {0x00001744, 0xcb4401e2}, -+ {0x00001944, 0xfa4401e2} -+}; -+ -+static const struct phy_reg x1_port0_config_regs[] = { -+ {0x00000694, 0xc80060fa}, -+ {0x00000680, 0x3d4f78ea}, -+ {0x00000690, 0x10a0140b}, -+ {0x000006a8, 0xdf04010a}, -+ {0x00000700, 0x57050060}, -+ {0x00000710, 0x0030001c}, -+ {0x00000738, 0x5f004444}, -+ {0x0000073c, 0x78464204}, -+ {0x00000748, 0x7821f940}, -+ {0x0000074c, 0xb2000433}, -+ {0x00000494, 0xfe6030fa}, -+ {0x00000480, 0x29ef5ed0}, -+ {0x00000490, 0x10a0540b}, -+ {0x000004a8, 0x7a01010a}, -+ {0x00000500, 0xef053460}, -+ {0x00000510, 0xe030101c}, -+ {0x00000538, 0xdf808444}, -+ {0x0000053c, 0xc8422204}, -+ {0x00000540, 0x0180088c}, -+ {0x00000574, 0x00000000}, -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg x1_port1_config_regs[] = { -+ {0x00000c94, 0xc80060fa}, -+ {0x00000c80, 0xcf47abea}, -+ {0x00000c90, 0x10a0840b}, -+ {0x00000ca8, 0xdf04010a}, -+ {0x00000d00, 0x57050060}, -+ {0x00000d10, 0x0030001c}, -+ {0x00000d38, 0x5f004444}, -+ {0x00000d3c, 0x78464204}, -+ {0x00000d48, 0x7821f940}, -+ {0x00000d4c, 0xb2000433}, -+ {0x00000a94, 0xc91030fa}, -+ {0x00000a80, 0x5a166ed0}, -+ {0x00000a90, 0x10a0540b}, -+ {0x00000aa8, 0x5d060100}, -+ {0x00000b00, 0xef053460}, -+ {0x00000b10, 0xa030101c}, -+ {0x00000b38, 0xdf808444}, -+ {0x00000b3c, 0xc8422204}, -+ {0x00000b40, 0x0180088c}, -+ {0x00000b74, 0x00000000}, -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg x1_port2_config_regs[] = { -+ {0x00001294, 0x28f000fa}, -+ {0x00001280, 0x08130cea}, -+ {0x00001290, 0x10a0140b}, -+ {0x000012a8, 0xd704010a}, -+ {0x00001300, 0x8d050060}, -+ {0x00001310, 0x0030001c}, -+ {0x00001338, 0xdf008444}, -+ {0x0000133c, 0x78422204}, -+ {0x00001348, 0x7821f940}, -+ {0x0000134c, 0x5a000433}, -+ {0x00001094, 0x2d20b0fa}, -+ {0x00001080, 0xade75dd0}, -+ {0x00001090, 0x10a0540b}, -+ {0x000010a8, 0xb101010a}, -+ {0x00001100, 0x33053460}, -+ {0x00001110, 0x0030101c}, -+ {0x00001138, 0xdf808444}, -+ {0x0000113c, 0xc8422204}, -+ {0x00001140, 0x8180088c}, -+ {0x00001174, 0x00000000}, -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg x1_port3_config_regs[] = { -+ {0x00001894, 0xc80060fa}, -+ {0x00001880, 0x0f90fd6a}, -+ {0x00001890, 0x10a0840b}, -+ {0x000018a8, 0xdf04010a}, -+ {0x00001900, 0x57050060}, -+ {0x00001910, 0x0030001c}, -+ {0x00001938, 0x5f004444}, -+ {0x0000193c, 0x78464204}, -+ {0x00001948, 0x7821f940}, -+ {0x0000194c, 0xb2000433}, -+ {0x00001694, 0x3050d0fa}, -+ {0x00001680, 0x0ef6d050}, -+ {0x00001690, 0x10a0540b}, -+ {0x000016a8, 0xe301010a}, -+ {0x00001700, 0x69053460}, -+ {0x00001710, 0xa030101c}, -+ {0x00001738, 0xdf808444}, -+ {0x0000173c, 0xc8422204}, -+ {0x00001740, 0x0180088c}, -+ {0x00001774, 0x00000000}, -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg x2_port0_config_regs[] = { -+ {0x00000694, 0xc80060fa}, -+ {0x00000680, 0x3d4f78ea}, -+ {0x00000690, 0x10a0140b}, -+ {0x000006a8, 0xdf04010a}, -+ {0x00000700, 0x57050060}, -+ {0x00000710, 0x0030001c}, -+ {0x00000738, 0x5f004444}, -+ {0x0000073c, 0x78464204}, -+ {0x00000748, 0x7821f940}, -+ {0x0000074c, 0xb2000433}, -+ {0x00000494, 0xc80060fa}, -+ {0x00000480, 0x29ef5ed8}, -+ {0x00000490, 0x10a0540b}, -+ {0x000004a8, 0x7a01010a}, -+ {0x00000500, 0xef053460}, -+ {0x00000510, 0xe030101c}, -+ {0x00000538, 0xdf808444}, -+ {0x0000053c, 0xc8422204}, -+ {0x00000540, 0x0180088c}, -+ {0x00000574, 0x00000000}, -+ {0x00000294, 0xc80060fa}, -+ {0x00000280, 0xcb45b950}, -+ {0x00000290, 0x10a0540b}, -+ {0x000002a8, 0x8c01010a}, -+ {0x00000300, 0xef053460}, -+ {0x00000310, 0x8030101c}, -+ {0x00000338, 0x41808444}, -+ {0x0000033c, 0x32422204}, -+ {0x00000340, 0x0180088c}, -+ {0x00000374, 0x00000000}, -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg x2_port1_config_regs[] = { -+ {0x00000c94, 0xc80060fa}, -+ {0x00000c80, 0xcf47abea}, -+ {0x00000c90, 0x10a0840b}, -+ {0x00000ca8, 0xdf04010a}, -+ {0x00000d00, 0x57050060}, -+ {0x00000d10, 0x0030001c}, -+ {0x00000d38, 0x5f004444}, -+ {0x00000d3c, 0x78464204}, -+ {0x00000d48, 0x7821f940}, -+ {0x00000d4c, 0xb2000433}, -+ {0x00000a94, 0xc80060fa}, -+ {0x00000a80, 0x5a166ed8}, -+ {0x00000a90, 0x10a0540b}, -+ {0x00000aa8, 0x7a01010a}, -+ {0x00000b00, 0xef053460}, -+ {0x00000b10, 0xa030101c}, -+ {0x00000b38, 0xdf808444}, -+ {0x00000b3c, 0xc8422204}, -+ {0x00000b40, 0x0180088c}, -+ {0x00000b74, 0x00000000}, -+ {0x00000894, 0xc80060fa}, -+ {0x00000880, 0x4d4f21d0}, -+ {0x00000890, 0x10a0540b}, -+ {0x000008a8, 0x5601010a}, -+ {0x00000900, 0xef053460}, -+ {0x00000910, 0x8030101c}, -+ {0x00000938, 0xdf808444}, -+ {0x0000093c, 0xc8422204}, -+ {0x00000940, 0x0180088c}, -+ {0x00000974, 0x00000000}, -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg x2_port2_config_regs[] = { -+ {0x00001294, 0xc80060fa}, -+ {0x00001280, 0x08130cea}, -+ {0x00001290, 0x10a0140b}, -+ {0x000012a8, 0xd704010a}, -+ {0x00001300, 0x8d050060}, -+ {0x00001310, 0x0030001c}, -+ {0x00001338, 0xdf008444}, -+ {0x0000133c, 0x78422204}, -+ {0x00001348, 0x7821f940}, -+ {0x0000134c, 0x5a000433}, -+ {0x00001094, 0xc80060fa}, -+ {0x00001080, 0xade75dd8}, -+ {0x00001090, 0x10a0540b}, -+ {0x000010a8, 0xb101010a}, -+ {0x00001100, 0x33053460}, -+ {0x00001110, 0x0030101c}, -+ {0x00001138, 0xdf808444}, -+ {0x0000113c, 0xc8422204}, -+ {0x00001140, 0x8180088c}, -+ {0x00001174, 0x00000000}, -+ {0x00000e94, 0xc80060fa}, -+ {0x00000e80, 0x0fbf16d0}, -+ {0x00000e90, 0x10a0540b}, -+ {0x00000ea8, 0x7a01010a}, -+ {0x00000f00, 0xf5053460}, -+ {0x00000f10, 0xc030101c}, -+ {0x00000f38, 0xdf808444}, -+ {0x00000f3c, 0xc8422204}, -+ {0x00000f40, 0x8180088c}, -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg x2_port3_config_regs[] = { -+ {0x00001894, 0xc80060fa}, -+ {0x00001880, 0x0f90fd6a}, -+ {0x00001890, 0x10a0840b}, -+ {0x000018a8, 0xdf04010a}, -+ {0x00001900, 0x57050060}, -+ {0x00001910, 0x0030001c}, -+ {0x00001938, 0x5f004444}, -+ {0x0000193c, 0x78464204}, -+ {0x00001948, 0x7821f940}, -+ {0x0000194c, 0xb2000433}, -+ {0x00001694, 0xc80060fa}, -+ {0x00001680, 0x0ef6d058}, -+ {0x00001690, 0x10a0540b}, -+ {0x000016a8, 0x7a01010a}, -+ {0x00001700, 0x69053460}, -+ {0x00001710, 0xa030101c}, -+ {0x00001738, 0xdf808444}, -+ {0x0000173c, 0xc8422204}, -+ {0x00001740, 0x0180088c}, -+ {0x00001774, 0x00000000}, -+ {0x00001494, 0xc80060fa}, -+ {0x00001480, 0xf9d34bd0}, -+ {0x00001490, 0x10a0540b}, -+ {0x000014a8, 0x7a01010a}, -+ {0x00001500, 0x1b053460}, -+ {0x00001510, 0x0030101c}, -+ {0x00001538, 0xdf808444}, -+ {0x0000153c, 0xc8422204}, -+ {0x00001540, 0x8180088c}, -+ {0x00001574, 0x00000000}, -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg x4_port0_config_regs[] = { -+ {0x00000694, 0xc80060fa}, -+ {0x00000680, 0x3d4f78fa}, -+ {0x00000690, 0x10a0140b}, -+ {0x000006a8, 0xdf04010a}, -+ {0x00000700, 0x57050060}, -+ {0x00000710, 0x0030001c}, -+ {0x00000738, 0x5f004444}, -+ {0x0000073c, 0x78464204}, -+ {0x00000748, 0x7821f940}, -+ {0x0000074c, 0xb2000433}, -+ {0x00000494, 0xfe6030fa}, -+ {0x00000480, 0x29ef5ed8}, -+ {0x00000490, 0x10a0540b}, -+ {0x000004a8, 0x7a01010a}, -+ {0x00000500, 0xef053460}, -+ {0x00000510, 0xe030101c}, -+ {0x00000538, 0xdf808444}, -+ {0x0000053c, 0xc8422204}, -+ {0x00000540, 0x0180088c}, -+ {0x00000574, 0x00000004}, -+ {0x00000294, 0x23e030fa}, -+ {0x00000280, 0xcb45b950}, -+ {0x00000290, 0x10a0540b}, -+ {0x000002a8, 0x8c01010a}, -+ {0x00000300, 0xef053460}, -+ {0x00000310, 0x8030101c}, -+ {0x00000338, 0x41808444}, -+ {0x0000033c, 0x32422204}, -+ {0x00000340, 0x0180088c}, -+ {0x00000374, 0x00000004}, -+ {0x00000894, 0x5620b0fa}, -+ {0x00000880, 0x4d4f21dc}, -+ {0x00000890, 0x10a0540b}, -+ {0x000008a8, 0x5601010a}, -+ {0x00000900, 0xef053460}, -+ {0x00000910, 0x8030101c}, -+ {0x00000938, 0xdf808444}, -+ {0x0000093c, 0xc8422204}, -+ {0x00000940, 0x0180088c}, -+ {0x00000974, 0x00000004}, -+ {0x00000a94, 0xc91030fa}, -+ {0x00000a80, 0x5a166ecc}, -+ {0x00000a90, 0x10a0540b}, -+ {0x00000aa8, 0x5d01010a}, -+ {0x00000b00, 0xef053460}, -+ {0x00000b10, 0xa030101c}, -+ {0x00000b38, 0xdf808444}, -+ {0x00000b3c, 0xc8422204}, -+ {0x00000b40, 0x0180088c}, -+ {0x00000b74, 0x00000004}, -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg x4_port1_config_regs[] = { -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg x4_port2_config_regs[] = { -+ {0x00001294, 0x28f000fa}, -+ {0x00001280, 0x08130cfa}, -+ {0x00001290, 0x10c0140b}, -+ {0x000012a8, 0xd704010a}, -+ {0x00001300, 0x8d050060}, -+ {0x00001310, 0x0030001c}, -+ {0x00001338, 0xdf008444}, -+ {0x0000133c, 0x78422204}, -+ {0x00001348, 0x7821f940}, -+ {0x0000134c, 0x5a000433}, -+ {0x00001094, 0x2d20b0fa}, -+ {0x00001080, 0xade75dd8}, -+ {0x00001090, 0x10a0540b}, -+ {0x000010a8, 0xb101010a}, -+ {0x00001100, 0x33053460}, -+ {0x00001110, 0x0030101c}, -+ {0x00001138, 0xdf808444}, -+ {0x0000113c, 0xc8422204}, -+ {0x00001140, 0x8180088c}, -+ {0x00001174, 0x00000004}, -+ {0x00000e94, 0xd308d0fa}, -+ {0x00000e80, 0x0fbf16d0}, -+ {0x00000e90, 0x10a0540b}, -+ {0x00000ea8, 0x2c01010a}, -+ {0x00000f00, 0xf5053460}, -+ {0x00000f10, 0xc030101c}, -+ {0x00000f38, 0xdf808444}, -+ {0x00000f3c, 0xc8422204}, -+ {0x00000f40, 0x8180088c}, -+ {0x00000f74, 0x00000004}, -+ {0x00001494, 0x136850fa}, -+ {0x00001480, 0xf9d34bdc}, -+ {0x00001490, 0x10a0540b}, -+ {0x000014a8, 0x5a01010a}, -+ {0x00001500, 0x1b053460}, -+ {0x00001510, 0x0030101c}, -+ {0x00001538, 0xdf808444}, -+ {0x0000153c, 0xc8422204}, -+ {0x00001540, 0x8180088c}, -+ {0x00001574, 0x00000004}, -+ {0x00001694, 0x3050d0fa}, -+ {0x00001680, 0x0ef6d04c}, -+ {0x00001690, 0x10a0540b}, -+ {0x000016a8, 0xe301010a}, -+ {0x00001700, 0x69053460}, -+ {0x00001710, 0xa030101c}, -+ {0x00001738, 0xdf808444}, -+ {0x0000173c, 0xc8422204}, -+ {0x00001740, 0x0180088c}, -+ {0x00001774, 0x00000004}, -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg x4_port3_config_regs[] = { -+ {0x00000000, 0x00000000} -+}; -+ -+static const struct phy_reg *x1_config_regs[4] = { -+ x1_port0_config_regs, -+ x1_port1_config_regs, -+ x1_port2_config_regs, -+ x1_port3_config_regs -+}; -+ -+static const struct phy_reg *x2_config_regs[4] = { -+ x2_port0_config_regs, -+ x2_port1_config_regs, -+ x2_port2_config_regs, -+ x2_port3_config_regs -+}; -+ -+static const struct phy_reg *x4_config_regs[4] = { -+ x4_port0_config_regs, -+ x4_port1_config_regs, -+ x4_port2_config_regs, -+ x4_port3_config_regs -+}; -+ -+static const struct phy_reg **config_regs[3] = { -+ x1_config_regs, -+ x2_config_regs, -+ x4_config_regs -+}; -+ -+static int ipu6_isys_mcd_phy_powerup_ack(struct ipu6_isys *isys, u8 id) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *isys_base = isys->pdata->base; -+ u32 val; -+ int ret; -+ -+ val = readl(isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id)); -+ val |= CSI_REG_HUB_GPREG_PHY_CTL_PWR_EN; -+ writel(val, isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id)); -+ -+ ret = readl_poll_timeout(isys_base + CSI_REG_HUB_GPREG_PHY_STATUS(id), -+ val, val & CSI_REG_HUB_GPREG_PHY_POWER_ACK, -+ 200, MCD_PHY_POWER_STATUS_TIMEOUT); -+ if (ret) -+ dev_err(dev, "PHY%d powerup ack timeout", id); -+ -+ return ret; -+} -+ -+static int ipu6_isys_mcd_phy_powerdown_ack(struct ipu6_isys *isys, u8 id) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *isys_base = isys->pdata->base; -+ u32 val; -+ int ret; -+ -+ writel(0, isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id)); -+ ret = readl_poll_timeout(isys_base + CSI_REG_HUB_GPREG_PHY_STATUS(id), -+ val, !(val & CSI_REG_HUB_GPREG_PHY_POWER_ACK), -+ 200, MCD_PHY_POWER_STATUS_TIMEOUT); -+ if (ret) -+ dev_err(dev, "PHY%d powerdown ack timeout", id); -+ -+ return ret; -+} -+ -+static void ipu6_isys_mcd_phy_reset(struct ipu6_isys *isys, u8 id, bool assert) -+{ -+ void __iomem *isys_base = isys->pdata->base; -+ u32 val; -+ -+ val = readl(isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id)); -+ if (assert) -+ val |= CSI_REG_HUB_GPREG_PHY_CTL_RESET; -+ else -+ val &= ~(CSI_REG_HUB_GPREG_PHY_CTL_RESET); -+ -+ writel(val, isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id)); -+} -+ -+static int ipu6_isys_mcd_phy_ready(struct ipu6_isys *isys, u8 id) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *isys_base = isys->pdata->base; -+ u32 val; -+ int ret; -+ -+ ret = readl_poll_timeout(isys_base + CSI_REG_HUB_GPREG_PHY_STATUS(id), -+ val, val & CSI_REG_HUB_GPREG_PHY_READY, -+ 200, MCD_PHY_POWER_STATUS_TIMEOUT); -+ if (ret) -+ dev_err(dev, "PHY%d ready ack timeout", id); -+ -+ return ret; -+} -+ -+static void ipu6_isys_mcd_phy_common_init(struct ipu6_isys *isys) -+{ -+ struct ipu6_bus_device *adev = isys->adev; -+ struct ipu6_device *isp = adev->isp; -+ void __iomem *isp_base = isp->base; -+ struct sensor_async_sd *s_asd; -+ struct v4l2_async_connection *asc; -+ void __iomem *phy_base; -+ unsigned int i; -+ u8 phy_id; -+ -+ list_for_each_entry(asc, &isys->notifier.done_list, asc_entry) { -+ s_asd = container_of(asc, struct sensor_async_sd, asc); -+ phy_id = s_asd->csi2.port / 4; -+ phy_base = isp_base + IPU6_ISYS_MCD_PHY_BASE(phy_id); -+ -+ for (i = 0; i < ARRAY_SIZE(common_init_regs); i++) -+ writel(common_init_regs[i].val, -+ phy_base + common_init_regs[i].reg); -+ } -+} -+ -+static int ipu6_isys_driver_port_to_phy_port(struct ipu6_isys_csi2_config *cfg) -+{ -+ int phy_port; -+ int ret; -+ -+ if (!(cfg->nlanes == 4 || cfg->nlanes == 2 || cfg->nlanes == 1)) -+ return -EINVAL; -+ -+ /* B,F -> C0 A,E -> C1 C,G -> C2 D,H -> C4 */ -+ /* normalize driver port number */ -+ phy_port = cfg->port % 4; -+ -+ /* swap port number only for A and B */ -+ if (phy_port == 0) -+ phy_port = 1; -+ else if (phy_port == 1) -+ phy_port = 0; -+ -+ ret = phy_port; -+ -+ /* check validity per lane configuration */ -+ if (cfg->nlanes == 4 && !(phy_port == 0 || phy_port == 2)) -+ ret = -EINVAL; -+ else if ((cfg->nlanes == 2 || cfg->nlanes == 1) && -+ !(phy_port >= 0 && phy_port <= 3)) -+ ret = -EINVAL; -+ -+ return ret; -+} -+ -+static int ipu6_isys_mcd_phy_config(struct ipu6_isys *isys) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ struct ipu6_bus_device *adev = isys->adev; -+ const struct phy_reg **phy_config_regs; -+ struct ipu6_device *isp = adev->isp; -+ void __iomem *isp_base = isp->base; -+ struct sensor_async_sd *s_asd; -+ struct ipu6_isys_csi2_config cfg; -+ struct v4l2_async_connection *asc; -+ u8 phy_port, phy_id; -+ unsigned int i; -+ void __iomem *phy_base; -+ -+ list_for_each_entry(asc, &isys->notifier.done_list, asc_entry) { -+ s_asd = container_of(asc, struct sensor_async_sd, asc); -+ cfg.port = s_asd->csi2.port; -+ cfg.nlanes = s_asd->csi2.nlanes; -+ phy_port = ipu6_isys_driver_port_to_phy_port(&cfg); -+ if (phy_port < 0) { -+ dev_err(dev, "invalid port %d for lane %d", cfg.port, -+ cfg.nlanes); -+ return -ENXIO; -+ } -+ -+ phy_id = cfg.port / 4; -+ phy_base = isp_base + IPU6_ISYS_MCD_PHY_BASE(phy_id); -+ dev_dbg(dev, "port%d PHY%u lanes %u\n", cfg.port, phy_id, -+ cfg.nlanes); -+ -+ phy_config_regs = config_regs[cfg.nlanes / 2]; -+ cfg.port = phy_port; -+ for (i = 0; phy_config_regs[cfg.port][i].reg; i++) -+ writel(phy_config_regs[cfg.port][i].val, -+ phy_base + phy_config_regs[cfg.port][i].reg); -+ } -+ -+ return 0; -+} -+ -+#define CSI_MCD_PHY_NUM 2 -+static refcount_t phy_power_ref_count[CSI_MCD_PHY_NUM]; -+ -+int ipu6_isys_mcd_phy_set_power(struct ipu6_isys *isys, -+ struct ipu6_isys_csi2_config *cfg, -+ const struct ipu6_isys_csi2_timing *timing, -+ bool on) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ void __iomem *isys_base = isys->pdata->base; -+ u8 port, phy_id; -+ refcount_t *ref; -+ int ret; -+ -+ port = cfg->port; -+ phy_id = port / 4; -+ -+ ref = &phy_power_ref_count[phy_id]; -+ -+ dev_dbg(dev, "for phy %d port %d, lanes: %d\n", phy_id, port, -+ cfg->nlanes); -+ -+ if (!isys_base || port >= isys->pdata->ipdata->csi2.nports) { -+ dev_warn(dev, "invalid port ID %d\n", port); -+ return -EINVAL; -+ } -+ -+ if (on) { -+ if (refcount_read(ref)) { -+ dev_dbg(dev, "for phy %d is already UP", phy_id); -+ refcount_inc(ref); -+ return 0; -+ } -+ -+ ret = ipu6_isys_mcd_phy_powerup_ack(isys, phy_id); -+ if (ret) -+ return ret; -+ -+ ipu6_isys_mcd_phy_reset(isys, phy_id, 0); -+ ipu6_isys_mcd_phy_common_init(isys); -+ -+ ret = ipu6_isys_mcd_phy_config(isys); -+ if (ret) -+ return ret; -+ -+ ipu6_isys_mcd_phy_reset(isys, phy_id, 1); -+ ret = ipu6_isys_mcd_phy_ready(isys, phy_id); -+ if (ret) -+ return ret; -+ -+ refcount_set(ref, 1); -+ return 0; -+ } -+ -+ if (!refcount_dec_and_test(ref)) -+ return 0; -+ -+ return ipu6_isys_mcd_phy_powerdown_ack(isys, phy_id); -+} --- -2.43.2 - - -From 5d8544bd1d6dc7fce10a3bf01d10d926b8990b54 Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:24 +0800 -Subject: [PATCH 17/33] media: intel/ipu6: add input system driver - -Input system driver do basic isys hardware setup and irq handling -and work with fwnode and v4l2 to register the ISYS v4l2 devices. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/media/pci/intel/ipu6/ipu6-isys.c | 1353 ++++++++++++++++++++++ - drivers/media/pci/intel/ipu6/ipu6-isys.h | 207 ++++ - 2 files changed, 1560 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys.h - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c -new file mode 100644 -index 000000000000..e8983363a0da ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c -@@ -0,0 +1,1353 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/auxiliary_bus.h> -+#include <linux/bitfield.h> -+#include <linux/bits.h> -+#include <linux/completion.h> -+#include <linux/container_of.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <linux/dma-mapping.h> -+#include <linux/err.h> -+#include <linux/firmware.h> -+#include <linux/io.h> -+#include <linux/irqreturn.h> -+#include <linux/list.h> -+#include <linux/module.h> -+#include <linux/mutex.h> -+#include <linux/pci.h> -+#include <linux/pm_runtime.h> -+#include <linux/pm_qos.h> -+#include <linux/slab.h> -+#include <linux/spinlock.h> -+#include <linux/string.h> -+ -+#include <media/ipu-bridge.h> -+#include <media/media-device.h> -+#include <media/media-entity.h> -+#include <media/v4l2-async.h> -+#include <media/v4l2-device.h> -+#include <media/v4l2-fwnode.h> -+ -+#include "ipu6-bus.h" -+#include "ipu6-cpd.h" -+#include "ipu6-isys.h" -+#include "ipu6-isys-csi2.h" -+#include "ipu6-mmu.h" -+#include "ipu6-platform-buttress-regs.h" -+#include "ipu6-platform-isys-csi2-reg.h" -+#include "ipu6-platform-regs.h" -+ -+#define IPU6_BUTTRESS_FABIC_CONTROL 0x68 -+#define GDA_ENABLE_IWAKE_INDEX 2 -+#define GDA_IWAKE_THRESHOLD_INDEX 1 -+#define GDA_IRQ_CRITICAL_THRESHOLD_INDEX 0 -+#define GDA_MEMOPEN_THRESHOLD_INDEX 3 -+#define DEFAULT_DID_RATIO 90 -+#define DEFAULT_IWAKE_THRESHOLD 0x42 -+#define DEFAULT_MEM_OPEN_TIME 10 -+#define ONE_THOUSAND_MICROSECOND 1000 -+/* One page is 2KB, 8 x 16 x 16 = 2048B = 2KB */ -+#define ISF_DMA_TOP_GDA_PROFERTY_PAGE_SIZE 0x800 -+ -+/* LTR & DID value are 10 bit at most */ -+#define LTR_DID_VAL_MAX 1023 -+#define LTR_DEFAULT_VALUE 0x70503c19 -+#define FILL_TIME_DEFAULT_VALUE 0xfff0783c -+#define LTR_DID_PKGC_2R 20 -+#define LTR_SCALE_DEFAULT 5 -+#define LTR_SCALE_1024NS 2 -+#define DID_SCALE_1US 2 -+#define DID_SCALE_32US 3 -+#define REG_PKGC_PMON_CFG 0xb00 -+ -+#define VAL_PKGC_PMON_CFG_RESET 0x38 -+#define VAL_PKGC_PMON_CFG_START 0x7 -+ -+#define IS_PIXEL_BUFFER_PAGES 0x80 -+/* -+ * when iwake mode is disabled, the critical threshold is statically set -+ * to 75% of the IS pixel buffer, criticalThreshold = (128 * 3) / 4 -+ */ -+#define CRITICAL_THRESHOLD_IWAKE_DISABLE (IS_PIXEL_BUFFER_PAGES * 3 / 4) -+ -+union fabric_ctrl { -+ struct { -+ u16 ltr_val : 10; -+ u16 ltr_scale : 3; -+ u16 reserved : 3; -+ u16 did_val : 10; -+ u16 did_scale : 3; -+ u16 reserved2 : 1; -+ u16 keep_power_in_D0 : 1; -+ u16 keep_power_override : 1; -+ } bits; -+ u32 value; -+}; -+ -+enum ltr_did_type { -+ LTR_IWAKE_ON, -+ LTR_IWAKE_OFF, -+ LTR_ISYS_ON, -+ LTR_ISYS_OFF, -+ LTR_ENHANNCE_IWAKE, -+ LTR_TYPE_MAX -+}; -+ -+#define ISYS_PM_QOS_VALUE 300 -+ -+static int isys_isr_one(struct ipu6_bus_device *adev); -+ -+static int -+isys_complete_ext_device_registration(struct ipu6_isys *isys, -+ struct v4l2_subdev *sd, -+ struct ipu6_isys_csi2_config *csi2) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ unsigned int i; -+ int ret; -+ -+ for (i = 0; i < sd->entity.num_pads; i++) { -+ if (sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE) -+ break; -+ } -+ -+ if (i == sd->entity.num_pads) { -+ dev_warn(dev, "no src pad in external entity\n"); -+ ret = -ENOENT; -+ goto unregister_subdev; -+ } -+ -+ ret = media_create_pad_link(&sd->entity, i, -+ &isys->csi2[csi2->port].asd.sd.entity, -+ 0, 0); -+ if (ret) { -+ dev_warn(dev, "can't create link\n"); -+ goto unregister_subdev; -+ } -+ -+ isys->csi2[csi2->port].nlanes = csi2->nlanes; -+ -+ return 0; -+ -+unregister_subdev: -+ v4l2_device_unregister_subdev(sd); -+ -+ return ret; -+} -+ -+static void isys_stream_init(struct ipu6_isys *isys) -+{ -+ u32 i; -+ -+ for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) { -+ mutex_init(&isys->streams[i].mutex); -+ init_completion(&isys->streams[i].stream_open_completion); -+ init_completion(&isys->streams[i].stream_close_completion); -+ init_completion(&isys->streams[i].stream_start_completion); -+ init_completion(&isys->streams[i].stream_stop_completion); -+ INIT_LIST_HEAD(&isys->streams[i].queues); -+ isys->streams[i].isys = isys; -+ isys->streams[i].stream_handle = i; -+ isys->streams[i].vc = INVALID_VC_ID; -+ } -+} -+ -+static void isys_csi2_unregister_subdevices(struct ipu6_isys *isys) -+{ -+ const struct ipu6_isys_internal_csi2_pdata *csi2 = -+ &isys->pdata->ipdata->csi2; -+ unsigned int i; -+ -+ for (i = 0; i < csi2->nports; i++) -+ ipu6_isys_csi2_cleanup(&isys->csi2[i]); -+} -+ -+static int isys_csi2_register_subdevices(struct ipu6_isys *isys) -+{ -+ const struct ipu6_isys_internal_csi2_pdata *csi2_pdata = -+ &isys->pdata->ipdata->csi2; -+ struct device *dev = &isys->adev->auxdev.dev; -+ unsigned int i; -+ int ret; -+ -+ isys->csi2 = devm_kcalloc(dev, csi2_pdata->nports, -+ sizeof(*isys->csi2), GFP_KERNEL); -+ if (!isys->csi2) -+ return -ENOMEM; -+ -+ for (i = 0; i < csi2_pdata->nports; i++) { -+ ret = ipu6_isys_csi2_init(&isys->csi2[i], isys, -+ isys->pdata->base + -+ csi2_pdata->offsets[i], i); -+ if (ret) -+ goto fail; -+ -+ isys->isr_csi2_bits |= IPU6_ISYS_UNISPART_IRQ_CSI2(i); -+ } -+ -+ return 0; -+ -+fail: -+ while (i--) -+ ipu6_isys_csi2_cleanup(&isys->csi2[i]); -+ -+ return ret; -+} -+ -+static int isys_csi2_create_media_links(struct ipu6_isys *isys) -+{ -+ const struct ipu6_isys_internal_csi2_pdata *csi2_pdata = -+ &isys->pdata->ipdata->csi2; -+ struct device *dev = &isys->adev->auxdev.dev; -+ unsigned int i, j, k; -+ int ret; -+ -+ for (i = 0; i < csi2_pdata->nports; i++) { -+ struct media_entity *sd = &isys->csi2[i].asd.sd.entity; -+ -+ for (j = 0; j < NR_OF_VIDEO_DEVICE; j++) { -+ struct media_entity *v = &isys->av[j].vdev.entity; -+ u32 flag = MEDIA_LNK_FL_DYNAMIC; -+ -+ for (k = CSI2_PAD_SRC; k < NR_OF_CSI2_PADS; k++) { -+ ret = media_create_pad_link(sd, k, v, 0, flag); -+ if (ret) { -+ dev_err(dev, "CSI2 can't create link\n"); -+ return ret; -+ } -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static void isys_unregister_video_devices(struct ipu6_isys *isys) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < NR_OF_VIDEO_DEVICE; i++) -+ ipu6_isys_video_cleanup(&isys->av[i]); -+} -+ -+static int isys_register_video_devices(struct ipu6_isys *isys) -+{ -+ unsigned int i; -+ int ret; -+ -+ for (i = 0; i < NR_OF_VIDEO_DEVICE; i++) { -+ snprintf(isys->av[i].vdev.name, sizeof(isys->av[i].vdev.name), -+ IPU6_ISYS_ENTITY_PREFIX " ISYS Capture %u", i); -+ isys->av[i].isys = isys; -+ isys->av[i].aq.vbq.buf_struct_size = -+ sizeof(struct ipu6_isys_video_buffer); -+ isys->av[i].pfmt = &ipu6_isys_pfmts[0]; -+ -+ ret = ipu6_isys_video_init(&isys->av[i]); -+ if (ret) -+ goto fail; -+ } -+ -+ return 0; -+ -+fail: -+ while (i--) -+ ipu6_isys_video_cleanup(&isys->av[i]); -+ -+ return ret; -+} -+ -+void isys_setup_hw(struct ipu6_isys *isys) -+{ -+ void __iomem *base = isys->pdata->base; -+ const u8 *thd = isys->pdata->ipdata->hw_variant.cdc_fifo_threshold; -+ u32 irqs = 0; -+ unsigned int i, nports; -+ -+ nports = isys->pdata->ipdata->csi2.nports; -+ -+ /* Enable irqs for all MIPI ports */ -+ for (i = 0; i < nports; i++) -+ irqs |= IPU6_ISYS_UNISPART_IRQ_CSI2(i); -+ -+ writel(irqs, base + isys->pdata->ipdata->csi2.ctrl0_irq_edge); -+ writel(irqs, base + isys->pdata->ipdata->csi2.ctrl0_irq_lnp); -+ writel(irqs, base + isys->pdata->ipdata->csi2.ctrl0_irq_mask); -+ writel(irqs, base + isys->pdata->ipdata->csi2.ctrl0_irq_enable); -+ writel(GENMASK(19, 0), -+ base + isys->pdata->ipdata->csi2.ctrl0_irq_clear); -+ -+ irqs = ISYS_UNISPART_IRQS; -+ writel(irqs, base + IPU6_REG_ISYS_UNISPART_IRQ_EDGE); -+ writel(irqs, base + IPU6_REG_ISYS_UNISPART_IRQ_LEVEL_NOT_PULSE); -+ writel(GENMASK(28, 0), base + IPU6_REG_ISYS_UNISPART_IRQ_CLEAR); -+ writel(irqs, base + IPU6_REG_ISYS_UNISPART_IRQ_MASK); -+ writel(irqs, base + IPU6_REG_ISYS_UNISPART_IRQ_ENABLE); -+ -+ writel(0, base + IPU6_REG_ISYS_UNISPART_SW_IRQ_REG); -+ writel(0, base + IPU6_REG_ISYS_UNISPART_SW_IRQ_MUX_REG); -+ -+ /* Write CDC FIFO threshold values for isys */ -+ for (i = 0; i < isys->pdata->ipdata->hw_variant.cdc_fifos; i++) -+ writel(thd[i], base + IPU6_REG_ISYS_CDC_THRESHOLD(i)); -+} -+ -+static void ipu6_isys_csi2_isr(struct ipu6_isys_csi2 *csi2) -+{ -+ struct ipu6_isys_stream *stream; -+ unsigned int i; -+ u32 status; -+ int source; -+ -+ ipu6_isys_register_errors(csi2); -+ -+ status = readl(csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC + -+ CSI_PORT_REG_BASE_IRQ_STATUS_OFFSET); -+ -+ writel(status, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC + -+ CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET); -+ -+ source = csi2->asd.source; -+ for (i = 0; i < NR_OF_CSI2_VC; i++) { -+ if (status & IPU_CSI_RX_IRQ_FS_VC(i)) { -+ stream = ipu6_isys_query_stream_by_source(csi2->isys, -+ source, i); -+ if (stream) { -+ ipu6_isys_csi2_sof_event_by_stream(stream); -+ ipu6_isys_put_stream(stream); -+ } -+ } -+ -+ if (status & IPU_CSI_RX_IRQ_FE_VC(i)) { -+ stream = ipu6_isys_query_stream_by_source(csi2->isys, -+ source, i); -+ if (stream) { -+ ipu6_isys_csi2_eof_event_by_stream(stream); -+ ipu6_isys_put_stream(stream); -+ } -+ } -+ } -+} -+ -+irqreturn_t isys_isr(struct ipu6_bus_device *adev) -+{ -+ struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev); -+ void __iomem *base = isys->pdata->base; -+ u32 status_sw, status_csi; -+ u32 ctrl0_status, ctrl0_clear; -+ -+ spin_lock(&isys->power_lock); -+ if (!isys->power) { -+ spin_unlock(&isys->power_lock); -+ return IRQ_NONE; -+ } -+ -+ ctrl0_status = isys->pdata->ipdata->csi2.ctrl0_irq_status; -+ ctrl0_clear = isys->pdata->ipdata->csi2.ctrl0_irq_clear; -+ -+ status_csi = readl(isys->pdata->base + ctrl0_status); -+ status_sw = readl(isys->pdata->base + -+ IPU6_REG_ISYS_UNISPART_IRQ_STATUS); -+ -+ writel(ISYS_UNISPART_IRQS & ~IPU6_ISYS_UNISPART_IRQ_SW, -+ base + IPU6_REG_ISYS_UNISPART_IRQ_MASK); -+ -+ do { -+ writel(status_csi, isys->pdata->base + ctrl0_clear); -+ -+ writel(status_sw, isys->pdata->base + -+ IPU6_REG_ISYS_UNISPART_IRQ_CLEAR); -+ -+ if (isys->isr_csi2_bits & status_csi) { -+ unsigned int i; -+ -+ for (i = 0; i < isys->pdata->ipdata->csi2.nports; i++) { -+ /* irq from not enabled port */ -+ if (!isys->csi2[i].base) -+ continue; -+ if (status_csi & IPU6_ISYS_UNISPART_IRQ_CSI2(i)) -+ ipu6_isys_csi2_isr(&isys->csi2[i]); -+ } -+ } -+ -+ writel(0, base + IPU6_REG_ISYS_UNISPART_SW_IRQ_REG); -+ -+ if (!isys_isr_one(adev)) -+ status_sw = IPU6_ISYS_UNISPART_IRQ_SW; -+ else -+ status_sw = 0; -+ -+ status_csi = readl(isys->pdata->base + ctrl0_status); -+ status_sw |= readl(isys->pdata->base + -+ IPU6_REG_ISYS_UNISPART_IRQ_STATUS); -+ } while ((status_csi & isys->isr_csi2_bits) || -+ (status_sw & IPU6_ISYS_UNISPART_IRQ_SW)); -+ -+ writel(ISYS_UNISPART_IRQS, base + IPU6_REG_ISYS_UNISPART_IRQ_MASK); -+ -+ spin_unlock(&isys->power_lock); -+ -+ return IRQ_HANDLED; -+} -+ -+static void get_lut_ltrdid(struct ipu6_isys *isys, struct ltr_did *pltr_did) -+{ -+ struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark; -+ struct ltr_did ltrdid_default; -+ -+ ltrdid_default.lut_ltr.value = LTR_DEFAULT_VALUE; -+ ltrdid_default.lut_fill_time.value = FILL_TIME_DEFAULT_VALUE; -+ -+ if (iwake_watermark->ltrdid.lut_ltr.value) -+ *pltr_did = iwake_watermark->ltrdid; -+ else -+ *pltr_did = ltrdid_default; -+} -+ -+static int set_iwake_register(struct ipu6_isys *isys, u32 index, u32 value) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ u32 req_id = index; -+ u32 offset = 0; -+ int ret; -+ -+ ret = ipu6_fw_isys_send_proxy_token(isys, req_id, index, offset, value); -+ if (ret) -+ dev_err(dev, "write %d failed %d", index, ret); -+ -+ return ret; -+} -+ -+/* -+ * When input system is powered up and before enabling any new sensor capture, -+ * or after disabling any sensor capture the following values need to be set: -+ * LTR_value = LTR(usec) from calculation; -+ * LTR_scale = 2; -+ * DID_value = DID(usec) from calculation; -+ * DID_scale = 2; -+ * -+ * When input system is powered down, the LTR and DID values -+ * must be returned to the default values: -+ * LTR_value = 1023; -+ * LTR_scale = 5; -+ * DID_value = 1023; -+ * DID_scale = 2; -+ */ -+static void set_iwake_ltrdid(struct ipu6_isys *isys, u16 ltr, u16 did, -+ enum ltr_did_type use) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ u16 ltr_val, ltr_scale = LTR_SCALE_1024NS; -+ u16 did_val, did_scale = DID_SCALE_1US; -+ struct ipu6_device *isp = isys->adev->isp; -+ union fabric_ctrl fc; -+ -+ switch (use) { -+ case LTR_IWAKE_ON: -+ ltr_val = min_t(u16, ltr, (u16)LTR_DID_VAL_MAX); -+ did_val = min_t(u16, did, (u16)LTR_DID_VAL_MAX); -+ ltr_scale = (ltr == LTR_DID_VAL_MAX && -+ did == LTR_DID_VAL_MAX) ? -+ LTR_SCALE_DEFAULT : LTR_SCALE_1024NS; -+ break; -+ case LTR_ISYS_ON: -+ case LTR_IWAKE_OFF: -+ ltr_val = LTR_DID_PKGC_2R; -+ did_val = LTR_DID_PKGC_2R; -+ break; -+ case LTR_ISYS_OFF: -+ ltr_val = LTR_DID_VAL_MAX; -+ did_val = LTR_DID_VAL_MAX; -+ ltr_scale = LTR_SCALE_DEFAULT; -+ break; -+ case LTR_ENHANNCE_IWAKE: -+ if (ltr == LTR_DID_VAL_MAX && did == LTR_DID_VAL_MAX) { -+ ltr_val = LTR_DID_VAL_MAX; -+ did_val = LTR_DID_VAL_MAX; -+ ltr_scale = LTR_SCALE_DEFAULT; -+ } else if (did < ONE_THOUSAND_MICROSECOND) { -+ ltr_val = ltr; -+ did_val = did; -+ } else { -+ ltr_val = ltr; -+ /* div 90% value by 32 to account for scale change */ -+ did_val = did / 32; -+ did_scale = DID_SCALE_32US; -+ } -+ break; -+ default: -+ ltr_val = LTR_DID_VAL_MAX; -+ did_val = LTR_DID_VAL_MAX; -+ ltr_scale = LTR_SCALE_DEFAULT; -+ break; -+ } -+ -+ fc.value = readl(isp->base + IPU6_BUTTRESS_FABIC_CONTROL); -+ fc.bits.ltr_val = ltr_val; -+ fc.bits.ltr_scale = ltr_scale; -+ fc.bits.did_val = did_val; -+ fc.bits.did_scale = did_scale; -+ -+ dev_dbg(dev, "ltr: value %u scale %u, did: value %u scale %u\n", -+ ltr_val, ltr_scale, did_val, did_scale); -+ writel(fc.value, isp->base + IPU6_BUTTRESS_FABIC_CONTROL); -+} -+ -+/* -+ * Driver may clear register GDA_ENABLE_IWAKE before FW configures the -+ * stream for debug purpose. Otherwise driver should not access this register. -+ */ -+static void enable_iwake(struct ipu6_isys *isys, bool enable) -+{ -+ struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark; -+ int ret; -+ -+ mutex_lock(&iwake_watermark->mutex); -+ -+ if (iwake_watermark->iwake_enabled == enable) { -+ mutex_unlock(&iwake_watermark->mutex); -+ return; -+ } -+ -+ ret = set_iwake_register(isys, GDA_ENABLE_IWAKE_INDEX, enable); -+ if (!ret) -+ iwake_watermark->iwake_enabled = enable; -+ -+ mutex_unlock(&iwake_watermark->mutex); -+} -+ -+void update_watermark_setting(struct ipu6_isys *isys) -+{ -+ struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark; -+ u32 iwake_threshold, iwake_critical_threshold, page_num; -+ struct device *dev = &isys->adev->auxdev.dev; -+ u32 calc_fill_time_us = 0, ltr = 0, did = 0; -+ struct video_stream_watermark *p_watermark; -+ enum ltr_did_type ltr_did_type; -+ struct list_head *stream_node; -+ u64 isys_pb_datarate_mbs = 0; -+ u32 mem_open_threshold = 0; -+ struct ltr_did ltrdid; -+ u64 threshold_bytes; -+ u32 max_sram_size; -+ u32 shift; -+ -+ shift = isys->pdata->ipdata->sram_gran_shift; -+ max_sram_size = isys->pdata->ipdata->max_sram_size; -+ -+ mutex_lock(&iwake_watermark->mutex); -+ if (iwake_watermark->force_iwake_disable) { -+ set_iwake_ltrdid(isys, 0, 0, LTR_IWAKE_OFF); -+ set_iwake_register(isys, GDA_IRQ_CRITICAL_THRESHOLD_INDEX, -+ CRITICAL_THRESHOLD_IWAKE_DISABLE); -+ goto unlock_exit; -+ } -+ -+ if (list_empty(&iwake_watermark->video_list)) { -+ isys_pb_datarate_mbs = 0; -+ } else { -+ list_for_each(stream_node, &iwake_watermark->video_list) { -+ p_watermark = list_entry(stream_node, -+ struct video_stream_watermark, -+ stream_node); -+ isys_pb_datarate_mbs += p_watermark->stream_data_rate; -+ } -+ } -+ mutex_unlock(&iwake_watermark->mutex); -+ -+ if (!isys_pb_datarate_mbs) { -+ enable_iwake(isys, false); -+ set_iwake_ltrdid(isys, 0, 0, LTR_IWAKE_OFF); -+ mutex_lock(&iwake_watermark->mutex); -+ set_iwake_register(isys, GDA_IRQ_CRITICAL_THRESHOLD_INDEX, -+ CRITICAL_THRESHOLD_IWAKE_DISABLE); -+ goto unlock_exit; -+ } -+ -+ enable_iwake(isys, true); -+ calc_fill_time_us = max_sram_size / isys_pb_datarate_mbs; -+ -+ if (isys->pdata->ipdata->enhanced_iwake) { -+ ltr = isys->pdata->ipdata->ltr; -+ did = calc_fill_time_us * DEFAULT_DID_RATIO / 100; -+ ltr_did_type = LTR_ENHANNCE_IWAKE; -+ } else { -+ get_lut_ltrdid(isys, <rdid); -+ -+ if (calc_fill_time_us <= ltrdid.lut_fill_time.bits.th0) -+ ltr = 0; -+ else if (calc_fill_time_us <= ltrdid.lut_fill_time.bits.th1) -+ ltr = ltrdid.lut_ltr.bits.val0; -+ else if (calc_fill_time_us <= ltrdid.lut_fill_time.bits.th2) -+ ltr = ltrdid.lut_ltr.bits.val1; -+ else if (calc_fill_time_us <= ltrdid.lut_fill_time.bits.th3) -+ ltr = ltrdid.lut_ltr.bits.val2; -+ else -+ ltr = ltrdid.lut_ltr.bits.val3; -+ -+ did = calc_fill_time_us - ltr; -+ ltr_did_type = LTR_IWAKE_ON; -+ } -+ -+ set_iwake_ltrdid(isys, ltr, did, ltr_did_type); -+ -+ /* calculate iwake threshold with 2KB granularity pages */ -+ threshold_bytes = did * isys_pb_datarate_mbs; -+ iwake_threshold = max_t(u32, 1, threshold_bytes >> shift); -+ iwake_threshold = min_t(u32, iwake_threshold, max_sram_size); -+ -+ mutex_lock(&iwake_watermark->mutex); -+ if (isys->pdata->ipdata->enhanced_iwake) { -+ set_iwake_register(isys, GDA_IWAKE_THRESHOLD_INDEX, -+ DEFAULT_IWAKE_THRESHOLD); -+ /* calculate number of pages that will be filled in 10 usec */ -+ page_num = (DEFAULT_MEM_OPEN_TIME * isys_pb_datarate_mbs) / -+ ISF_DMA_TOP_GDA_PROFERTY_PAGE_SIZE; -+ page_num += ((DEFAULT_MEM_OPEN_TIME * isys_pb_datarate_mbs) % -+ ISF_DMA_TOP_GDA_PROFERTY_PAGE_SIZE) ? 1 : 0; -+ mem_open_threshold = isys->pdata->ipdata->memopen_threshold; -+ mem_open_threshold = max_t(u32, mem_open_threshold, page_num); -+ dev_dbg(dev, "mem_open_threshold: %u\n", mem_open_threshold); -+ set_iwake_register(isys, GDA_MEMOPEN_THRESHOLD_INDEX, -+ mem_open_threshold); -+ } else { -+ set_iwake_register(isys, GDA_IWAKE_THRESHOLD_INDEX, -+ iwake_threshold); -+ } -+ -+ iwake_critical_threshold = iwake_threshold + -+ (IS_PIXEL_BUFFER_PAGES - iwake_threshold) / 2; -+ -+ dev_dbg(dev, "threshold: %u critical: %u\n", iwake_threshold, -+ iwake_critical_threshold); -+ -+ set_iwake_register(isys, GDA_IRQ_CRITICAL_THRESHOLD_INDEX, -+ iwake_critical_threshold); -+ -+ writel(VAL_PKGC_PMON_CFG_RESET, -+ isys->adev->isp->base + REG_PKGC_PMON_CFG); -+ writel(VAL_PKGC_PMON_CFG_START, -+ isys->adev->isp->base + REG_PKGC_PMON_CFG); -+unlock_exit: -+ mutex_unlock(&iwake_watermark->mutex); -+} -+ -+static void isys_iwake_watermark_init(struct ipu6_isys *isys) -+{ -+ struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark; -+ -+ INIT_LIST_HEAD(&iwake_watermark->video_list); -+ mutex_init(&iwake_watermark->mutex); -+ -+ iwake_watermark->ltrdid.lut_ltr.value = 0; -+ iwake_watermark->isys = isys; -+ iwake_watermark->iwake_enabled = false; -+ iwake_watermark->force_iwake_disable = false; -+} -+ -+static void isys_iwake_watermark_cleanup(struct ipu6_isys *isys) -+{ -+ struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark; -+ -+ mutex_lock(&iwake_watermark->mutex); -+ list_del(&iwake_watermark->video_list); -+ mutex_unlock(&iwake_watermark->mutex); -+ -+ mutex_destroy(&iwake_watermark->mutex); -+} -+ -+/* The .bound() notifier callback when a match is found */ -+static int isys_notifier_bound(struct v4l2_async_notifier *notifier, -+ struct v4l2_subdev *sd, -+ struct v4l2_async_connection *asc) -+{ -+ struct ipu6_isys *isys = -+ container_of(notifier, struct ipu6_isys, notifier); -+ struct sensor_async_sd *s_asd = -+ container_of(asc, struct sensor_async_sd, asc); -+ int ret; -+ -+ ret = ipu_bridge_instantiate_vcm(sd->dev); -+ if (ret) { -+ dev_err(&isys->adev->auxdev.dev, "instantiate vcm failed\n"); -+ return ret; -+ } -+ -+ dev_dbg(&isys->adev->auxdev.dev, "bind %s nlanes is %d port is %d\n", -+ sd->name, s_asd->csi2.nlanes, s_asd->csi2.port); -+ ret = isys_complete_ext_device_registration(isys, sd, &s_asd->csi2); -+ if (ret) -+ return ret; -+ -+ return v4l2_device_register_subdev_nodes(&isys->v4l2_dev); -+} -+ -+static int isys_notifier_complete(struct v4l2_async_notifier *notifier) -+{ -+ struct ipu6_isys *isys = -+ container_of(notifier, struct ipu6_isys, notifier); -+ -+ return v4l2_device_register_subdev_nodes(&isys->v4l2_dev); -+} -+ -+static const struct v4l2_async_notifier_operations isys_async_ops = { -+ .bound = isys_notifier_bound, -+ .complete = isys_notifier_complete, -+}; -+ -+#define ISYS_MAX_PORTS 8 -+static int isys_notifier_init(struct ipu6_isys *isys) -+{ -+ struct ipu6_device *isp = isys->adev->isp; -+ struct device *dev = &isp->pdev->dev; -+ unsigned int i; -+ int ret; -+ -+ v4l2_async_nf_init(&isys->notifier, &isys->v4l2_dev); -+ -+ for (i = 0; i < ISYS_MAX_PORTS; i++) { -+ struct v4l2_fwnode_endpoint vep = { -+ .bus_type = V4L2_MBUS_CSI2_DPHY -+ }; -+ struct sensor_async_sd *s_asd; -+ struct fwnode_handle *ep; -+ -+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), i, 0, -+ FWNODE_GRAPH_ENDPOINT_NEXT); -+ if (!ep) -+ continue; -+ -+ ret = v4l2_fwnode_endpoint_parse(ep, &vep); -+ if (ret) { -+ dev_err(dev, "fwnode endpoint parse failed: %d\n", ret); -+ goto err_parse; -+ } -+ -+ s_asd = v4l2_async_nf_add_fwnode_remote(&isys->notifier, ep, -+ struct sensor_async_sd); -+ if (IS_ERR(s_asd)) { -+ ret = PTR_ERR(s_asd); -+ dev_err(dev, "add remove fwnode failed: %d\n", ret); -+ goto err_parse; -+ } -+ -+ s_asd->csi2.port = vep.base.port; -+ s_asd->csi2.nlanes = vep.bus.mipi_csi2.num_data_lanes; -+ -+ dev_dbg(dev, "remote endpoint port %d with %d lanes added\n", -+ s_asd->csi2.port, s_asd->csi2.nlanes); -+ -+ fwnode_handle_put(ep); -+ -+ continue; -+ -+err_parse: -+ fwnode_handle_put(ep); -+ return ret; -+ } -+ -+ isys->notifier.ops = &isys_async_ops; -+ ret = v4l2_async_nf_register(&isys->notifier); -+ if (ret) { -+ dev_err(dev, "failed to register async notifier : %d\n", ret); -+ v4l2_async_nf_cleanup(&isys->notifier); -+ } -+ -+ return ret; -+} -+ -+static void isys_notifier_cleanup(struct ipu6_isys *isys) -+{ -+ v4l2_async_nf_unregister(&isys->notifier); -+ v4l2_async_nf_cleanup(&isys->notifier); -+} -+ -+static int isys_register_devices(struct ipu6_isys *isys) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ struct pci_dev *pdev = isys->adev->isp->pdev; -+ int ret; -+ -+ isys->media_dev.dev = dev; -+ media_device_pci_init(&isys->media_dev, -+ pdev, IPU6_MEDIA_DEV_MODEL_NAME); -+ -+ strscpy(isys->v4l2_dev.name, isys->media_dev.model, -+ sizeof(isys->v4l2_dev.name)); -+ -+ ret = media_device_register(&isys->media_dev); -+ if (ret < 0) -+ goto out_media_device_unregister; -+ -+ isys->v4l2_dev.mdev = &isys->media_dev; -+ isys->v4l2_dev.ctrl_handler = NULL; -+ -+ ret = v4l2_device_register(dev->parent, &isys->v4l2_dev); -+ if (ret < 0) -+ goto out_media_device_unregister; -+ -+ ret = isys_register_video_devices(isys); -+ if (ret) -+ goto out_v4l2_device_unregister; -+ -+ ret = isys_csi2_register_subdevices(isys); -+ if (ret) -+ goto out_isys_unregister_video_device; -+ -+ ret = isys_csi2_create_media_links(isys); -+ if (ret) -+ goto out_isys_unregister_subdevices; -+ -+ ret = isys_notifier_init(isys); -+ if (ret) -+ goto out_isys_unregister_subdevices; -+ -+ return 0; -+ -+out_isys_unregister_subdevices: -+ isys_csi2_unregister_subdevices(isys); -+ -+out_isys_unregister_video_device: -+ isys_unregister_video_devices(isys); -+ -+out_v4l2_device_unregister: -+ v4l2_device_unregister(&isys->v4l2_dev); -+ -+out_media_device_unregister: -+ media_device_unregister(&isys->media_dev); -+ media_device_cleanup(&isys->media_dev); -+ -+ dev_err(dev, "failed to register isys devices\n"); -+ -+ return ret; -+} -+ -+static void isys_unregister_devices(struct ipu6_isys *isys) -+{ -+ isys_unregister_video_devices(isys); -+ isys_csi2_unregister_subdevices(isys); -+ v4l2_device_unregister(&isys->v4l2_dev); -+ media_device_unregister(&isys->media_dev); -+ media_device_cleanup(&isys->media_dev); -+} -+ -+static int isys_runtime_pm_resume(struct device *dev) -+{ -+ struct ipu6_bus_device *adev = to_ipu6_bus_device(dev); -+ struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev); -+ struct ipu6_device *isp = adev->isp; -+ unsigned long flags; -+ int ret; -+ -+ if (!isys) -+ return 0; -+ -+ ret = ipu6_mmu_hw_init(adev->mmu); -+ if (ret) -+ return ret; -+ -+ cpu_latency_qos_update_request(&isys->pm_qos, ISYS_PM_QOS_VALUE); -+ -+ ret = ipu6_buttress_start_tsc_sync(isp); -+ if (ret) -+ return ret; -+ -+ spin_lock_irqsave(&isys->power_lock, flags); -+ isys->power = 1; -+ spin_unlock_irqrestore(&isys->power_lock, flags); -+ -+ isys_setup_hw(isys); -+ -+ set_iwake_ltrdid(isys, 0, 0, LTR_ISYS_ON); -+ -+ return 0; -+} -+ -+static int isys_runtime_pm_suspend(struct device *dev) -+{ -+ struct ipu6_bus_device *adev = to_ipu6_bus_device(dev); -+ struct ipu6_isys *isys; -+ unsigned long flags; -+ -+ isys = dev_get_drvdata(dev); -+ if (!isys) -+ return 0; -+ -+ spin_lock_irqsave(&isys->power_lock, flags); -+ isys->power = 0; -+ spin_unlock_irqrestore(&isys->power_lock, flags); -+ -+ mutex_lock(&isys->mutex); -+ isys->need_reset = false; -+ mutex_unlock(&isys->mutex); -+ -+ isys->phy_termcal_val = 0; -+ cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE); -+ -+ set_iwake_ltrdid(isys, 0, 0, LTR_ISYS_OFF); -+ -+ ipu6_mmu_hw_cleanup(adev->mmu); -+ -+ return 0; -+} -+ -+static int isys_suspend(struct device *dev) -+{ -+ struct ipu6_isys *isys = dev_get_drvdata(dev); -+ -+ /* If stream is open, refuse to suspend */ -+ if (isys->stream_opened) -+ return -EBUSY; -+ -+ return 0; -+} -+ -+static int isys_resume(struct device *dev) -+{ -+ return 0; -+} -+ -+static const struct dev_pm_ops isys_pm_ops = { -+ .runtime_suspend = isys_runtime_pm_suspend, -+ .runtime_resume = isys_runtime_pm_resume, -+ .suspend = isys_suspend, -+ .resume = isys_resume, -+}; -+ -+static void isys_remove(struct auxiliary_device *auxdev) -+{ -+ struct ipu6_bus_device *adev = auxdev_to_adev(auxdev); -+ struct ipu6_isys *isys = dev_get_drvdata(&auxdev->dev); -+ struct ipu6_device *isp = adev->isp; -+ struct isys_fw_msgs *fwmsg, *safe; -+ unsigned int i; -+ -+ list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist, head) -+ dma_free_attrs(&auxdev->dev, sizeof(struct isys_fw_msgs), -+ fwmsg, fwmsg->dma_addr, 0); -+ -+ list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist_fw, head) -+ dma_free_attrs(&auxdev->dev, sizeof(struct isys_fw_msgs), -+ fwmsg, fwmsg->dma_addr, 0); -+ -+ isys_unregister_devices(isys); -+ isys_notifier_cleanup(isys); -+ -+ cpu_latency_qos_remove_request(&isys->pm_qos); -+ -+ if (!isp->secure_mode) { -+ ipu6_cpd_free_pkg_dir(adev); -+ ipu6_buttress_unmap_fw_image(adev, &adev->fw_sgt); -+ release_firmware(adev->fw); -+ } -+ -+ for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) -+ mutex_destroy(&isys->streams[i].mutex); -+ -+ isys_iwake_watermark_cleanup(isys); -+ mutex_destroy(&isys->stream_mutex); -+ mutex_destroy(&isys->mutex); -+} -+ -+static int alloc_fw_msg_bufs(struct ipu6_isys *isys, int amount) -+{ -+ struct device *dev = &isys->adev->auxdev.dev; -+ struct isys_fw_msgs *addr; -+ dma_addr_t dma_addr; -+ unsigned long flags; -+ unsigned int i; -+ -+ for (i = 0; i < amount; i++) { -+ addr = dma_alloc_attrs(dev, sizeof(struct isys_fw_msgs), -+ &dma_addr, GFP_KERNEL, 0); -+ if (!addr) -+ break; -+ addr->dma_addr = dma_addr; -+ -+ spin_lock_irqsave(&isys->listlock, flags); -+ list_add(&addr->head, &isys->framebuflist); -+ spin_unlock_irqrestore(&isys->listlock, flags); -+ } -+ -+ if (i == amount) -+ return 0; -+ -+ spin_lock_irqsave(&isys->listlock, flags); -+ while (!list_empty(&isys->framebuflist)) { -+ addr = list_first_entry(&isys->framebuflist, -+ struct isys_fw_msgs, head); -+ list_del(&addr->head); -+ spin_unlock_irqrestore(&isys->listlock, flags); -+ dma_free_attrs(dev, sizeof(struct isys_fw_msgs), addr, -+ addr->dma_addr, 0); -+ spin_lock_irqsave(&isys->listlock, flags); -+ } -+ spin_unlock_irqrestore(&isys->listlock, flags); -+ -+ return -ENOMEM; -+} -+ -+struct isys_fw_msgs *ipu6_get_fw_msg_buf(struct ipu6_isys_stream *stream) -+{ -+ struct ipu6_isys *isys = stream->isys; -+ struct device *dev = &isys->adev->auxdev.dev; -+ struct isys_fw_msgs *msg; -+ unsigned long flags; -+ int ret; -+ -+ spin_lock_irqsave(&isys->listlock, flags); -+ if (list_empty(&isys->framebuflist)) { -+ spin_unlock_irqrestore(&isys->listlock, flags); -+ dev_dbg(dev, "Frame list empty\n"); -+ -+ ret = alloc_fw_msg_bufs(isys, 5); -+ if (ret < 0) -+ return NULL; -+ -+ spin_lock_irqsave(&isys->listlock, flags); -+ if (list_empty(&isys->framebuflist)) { -+ spin_unlock_irqrestore(&isys->listlock, flags); -+ dev_err(dev, "Frame list empty\n"); -+ return NULL; -+ } -+ } -+ msg = list_last_entry(&isys->framebuflist, struct isys_fw_msgs, head); -+ list_move(&msg->head, &isys->framebuflist_fw); -+ spin_unlock_irqrestore(&isys->listlock, flags); -+ memset(&msg->fw_msg, 0, sizeof(msg->fw_msg)); -+ -+ return msg; -+} -+ -+void ipu6_cleanup_fw_msg_bufs(struct ipu6_isys *isys) -+{ -+ struct isys_fw_msgs *fwmsg, *fwmsg0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&isys->listlock, flags); -+ list_for_each_entry_safe(fwmsg, fwmsg0, &isys->framebuflist_fw, head) -+ list_move(&fwmsg->head, &isys->framebuflist); -+ spin_unlock_irqrestore(&isys->listlock, flags); -+} -+ -+void ipu6_put_fw_msg_buf(struct ipu6_isys *isys, u64 data) -+{ -+ struct isys_fw_msgs *msg; -+ unsigned long flags; -+ u64 *ptr = (u64 *)data; -+ -+ if (!ptr) -+ return; -+ -+ spin_lock_irqsave(&isys->listlock, flags); -+ msg = container_of(ptr, struct isys_fw_msgs, fw_msg.dummy); -+ list_move(&msg->head, &isys->framebuflist); -+ spin_unlock_irqrestore(&isys->listlock, flags); -+} -+ -+static int isys_probe(struct auxiliary_device *auxdev, -+ const struct auxiliary_device_id *auxdev_id) -+{ -+ struct ipu6_bus_device *adev = auxdev_to_adev(auxdev); -+ struct ipu6_device *isp = adev->isp; -+ const struct firmware *fw; -+ struct ipu6_isys *isys; -+ unsigned int i; -+ int ret; -+ -+ if (!isp->bus_ready_to_probe) -+ return -EPROBE_DEFER; -+ -+ isys = devm_kzalloc(&auxdev->dev, sizeof(*isys), GFP_KERNEL); -+ if (!isys) -+ return -ENOMEM; -+ -+ ret = ipu6_mmu_hw_init(adev->mmu); -+ if (ret) -+ return ret; -+ -+ adev->auxdrv_data = -+ (const struct ipu6_auxdrv_data *)auxdev_id->driver_data; -+ adev->auxdrv = to_auxiliary_drv(auxdev->dev.driver); -+ isys->adev = adev; -+ isys->pdata = adev->pdata; -+ -+ /* initial sensor type */ -+ isys->sensor_type = isys->pdata->ipdata->sensor_type_start; -+ -+ spin_lock_init(&isys->streams_lock); -+ spin_lock_init(&isys->power_lock); -+ isys->power = 0; -+ isys->phy_termcal_val = 0; -+ -+ mutex_init(&isys->mutex); -+ mutex_init(&isys->stream_mutex); -+ -+ spin_lock_init(&isys->listlock); -+ INIT_LIST_HEAD(&isys->framebuflist); -+ INIT_LIST_HEAD(&isys->framebuflist_fw); -+ -+ isys->line_align = IPU6_ISYS_2600_MEM_LINE_ALIGN; -+ isys->icache_prefetch = 0; -+ -+ dev_set_drvdata(&auxdev->dev, isys); -+ -+ isys_stream_init(isys); -+ -+ if (!isp->secure_mode) { -+ fw = isp->cpd_fw; -+ ret = ipu6_buttress_map_fw_image(adev, fw, &adev->fw_sgt); -+ if (ret) -+ goto release_firmware; -+ -+ ret = ipu6_cpd_create_pkg_dir(adev, isp->cpd_fw->data); -+ if (ret) -+ goto remove_shared_buffer; -+ } -+ -+ cpu_latency_qos_add_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE); -+ -+ ret = alloc_fw_msg_bufs(isys, 20); -+ if (ret < 0) -+ goto out_remove_pkg_dir_shared_buffer; -+ -+ isys_iwake_watermark_init(isys); -+ -+ if (is_ipu6se(adev->isp->hw_ver)) -+ isys->phy_set_power = ipu6_isys_jsl_phy_set_power; -+ else if (is_ipu6ep_mtl(adev->isp->hw_ver)) -+ isys->phy_set_power = ipu6_isys_dwc_phy_set_power; -+ else -+ isys->phy_set_power = ipu6_isys_mcd_phy_set_power; -+ -+ ret = isys_register_devices(isys); -+ if (ret) -+ goto out_remove_pkg_dir_shared_buffer; -+ -+ ipu6_mmu_hw_cleanup(adev->mmu); -+ -+ return 0; -+ -+out_remove_pkg_dir_shared_buffer: -+ if (!isp->secure_mode) -+ ipu6_cpd_free_pkg_dir(adev); -+remove_shared_buffer: -+ if (!isp->secure_mode) -+ ipu6_buttress_unmap_fw_image(adev, &adev->fw_sgt); -+release_firmware: -+ if (!isp->secure_mode) -+ release_firmware(adev->fw); -+ -+ for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) -+ mutex_destroy(&isys->streams[i].mutex); -+ -+ mutex_destroy(&isys->mutex); -+ mutex_destroy(&isys->stream_mutex); -+ -+ ipu6_mmu_hw_cleanup(adev->mmu); -+ -+ return ret; -+} -+ -+struct fwmsg { -+ int type; -+ char *msg; -+ bool valid_ts; -+}; -+ -+static const struct fwmsg fw_msg[] = { -+ {IPU6_FW_ISYS_RESP_TYPE_STREAM_OPEN_DONE, "STREAM_OPEN_DONE", 0}, -+ {IPU6_FW_ISYS_RESP_TYPE_STREAM_CLOSE_ACK, "STREAM_CLOSE_ACK", 0}, -+ {IPU6_FW_ISYS_RESP_TYPE_STREAM_START_ACK, "STREAM_START_ACK", 0}, -+ {IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_ACK, -+ "STREAM_START_AND_CAPTURE_ACK", 0}, -+ {IPU6_FW_ISYS_RESP_TYPE_STREAM_STOP_ACK, "STREAM_STOP_ACK", 0}, -+ {IPU6_FW_ISYS_RESP_TYPE_STREAM_FLUSH_ACK, "STREAM_FLUSH_ACK", 0}, -+ {IPU6_FW_ISYS_RESP_TYPE_PIN_DATA_READY, "PIN_DATA_READY", 1}, -+ {IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_ACK, "STREAM_CAPTURE_ACK", 0}, -+ {IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_DONE, -+ "STREAM_START_AND_CAPTURE_DONE", 1}, -+ {IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_DONE, "STREAM_CAPTURE_DONE", 1}, -+ {IPU6_FW_ISYS_RESP_TYPE_FRAME_SOF, "FRAME_SOF", 1}, -+ {IPU6_FW_ISYS_RESP_TYPE_FRAME_EOF, "FRAME_EOF", 1}, -+ {IPU6_FW_ISYS_RESP_TYPE_STATS_DATA_READY, "STATS_READY", 1}, -+ {-1, "UNKNOWN MESSAGE", 0} -+}; -+ -+static u32 resp_type_to_index(int type) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(fw_msg); i++) -+ if (fw_msg[i].type == type) -+ return i; -+ -+ return ARRAY_SIZE(fw_msg) - 1; -+} -+ -+static int isys_isr_one(struct ipu6_bus_device *adev) -+{ -+ struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev); -+ struct ipu6_fw_isys_resp_info_abi *resp; -+ struct ipu6_isys_stream *stream; -+ struct ipu6_isys_csi2 *csi2 = NULL; -+ u32 index; -+ u64 ts; -+ -+ if (!isys->fwcom) -+ return 1; -+ -+ resp = ipu6_fw_isys_get_resp(isys->fwcom, IPU6_BASE_MSG_RECV_QUEUES); -+ if (!resp) -+ return 1; -+ -+ ts = (u64)resp->timestamp[1] << 32 | resp->timestamp[0]; -+ -+ index = resp_type_to_index(resp->type); -+ dev_dbg(&adev->auxdev.dev, -+ "FW resp %02d %s, stream %u, ts 0x%16.16llx, pin %d\n", -+ resp->type, fw_msg[index].msg, resp->stream_handle, -+ fw_msg[index].valid_ts ? ts : 0, resp->pin_id); -+ -+ if (resp->error_info.error == IPU6_FW_ISYS_ERROR_STREAM_IN_SUSPENSION) -+ /* Suspension is kind of special case: not enough buffers */ -+ dev_dbg(&adev->auxdev.dev, -+ "FW error resp SUSPENSION, details %d\n", -+ resp->error_info.error_details); -+ else if (resp->error_info.error) -+ dev_dbg(&adev->auxdev.dev, -+ "FW error resp error %d, details %d\n", -+ resp->error_info.error, resp->error_info.error_details); -+ -+ if (resp->stream_handle >= IPU6_ISYS_MAX_STREAMS) { -+ dev_err(&adev->auxdev.dev, "bad stream handle %u\n", -+ resp->stream_handle); -+ goto leave; -+ } -+ -+ stream = ipu6_isys_query_stream_by_handle(isys, resp->stream_handle); -+ if (!stream) { -+ dev_err(&adev->auxdev.dev, "stream of stream_handle %u is unused\n", -+ resp->stream_handle); -+ goto leave; -+ } -+ stream->error = resp->error_info.error; -+ -+ csi2 = ipu6_isys_subdev_to_csi2(stream->asd); -+ -+ switch (resp->type) { -+ case IPU6_FW_ISYS_RESP_TYPE_STREAM_OPEN_DONE: -+ complete(&stream->stream_open_completion); -+ break; -+ case IPU6_FW_ISYS_RESP_TYPE_STREAM_CLOSE_ACK: -+ complete(&stream->stream_close_completion); -+ break; -+ case IPU6_FW_ISYS_RESP_TYPE_STREAM_START_ACK: -+ complete(&stream->stream_start_completion); -+ break; -+ case IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_ACK: -+ complete(&stream->stream_start_completion); -+ break; -+ case IPU6_FW_ISYS_RESP_TYPE_STREAM_STOP_ACK: -+ complete(&stream->stream_stop_completion); -+ break; -+ case IPU6_FW_ISYS_RESP_TYPE_STREAM_FLUSH_ACK: -+ complete(&stream->stream_stop_completion); -+ break; -+ case IPU6_FW_ISYS_RESP_TYPE_PIN_DATA_READY: -+ /* -+ * firmware only release the capture msg until software -+ * get pin_data_ready event -+ */ -+ ipu6_put_fw_msg_buf(ipu6_bus_get_drvdata(adev), resp->buf_id); -+ if (resp->pin_id < IPU6_ISYS_OUTPUT_PINS && -+ stream->output_pins[resp->pin_id].pin_ready) -+ stream->output_pins[resp->pin_id].pin_ready(stream, -+ resp); -+ else -+ dev_warn(&adev->auxdev.dev, -+ "%d:No data pin ready handler for pin id %d\n", -+ resp->stream_handle, resp->pin_id); -+ if (csi2) -+ ipu6_isys_csi2_error(csi2); -+ -+ break; -+ case IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_ACK: -+ break; -+ case IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_DONE: -+ case IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_DONE: -+ break; -+ case IPU6_FW_ISYS_RESP_TYPE_FRAME_SOF: -+ -+ ipu6_isys_csi2_sof_event_by_stream(stream); -+ stream->seq[stream->seq_index].sequence = -+ atomic_read(&stream->sequence) - 1; -+ stream->seq[stream->seq_index].timestamp = ts; -+ dev_dbg(&adev->auxdev.dev, -+ "sof: handle %d: (index %u), timestamp 0x%16.16llx\n", -+ resp->stream_handle, -+ stream->seq[stream->seq_index].sequence, ts); -+ stream->seq_index = (stream->seq_index + 1) -+ % IPU6_ISYS_MAX_PARALLEL_SOF; -+ break; -+ case IPU6_FW_ISYS_RESP_TYPE_FRAME_EOF: -+ ipu6_isys_csi2_eof_event_by_stream(stream); -+ dev_dbg(&adev->auxdev.dev, -+ "eof: handle %d: (index %u), timestamp 0x%16.16llx\n", -+ resp->stream_handle, -+ stream->seq[stream->seq_index].sequence, ts); -+ break; -+ case IPU6_FW_ISYS_RESP_TYPE_STATS_DATA_READY: -+ break; -+ default: -+ dev_err(&adev->auxdev.dev, "%d:unknown response type %u\n", -+ resp->stream_handle, resp->type); -+ break; -+ } -+ -+ ipu6_isys_put_stream(stream); -+leave: -+ ipu6_fw_isys_put_resp(isys->fwcom, IPU6_BASE_MSG_RECV_QUEUES); -+ return 0; -+} -+ -+static const struct ipu6_auxdrv_data ipu6_isys_auxdrv_data = { -+ .isr = isys_isr, -+ .isr_threaded = NULL, -+ .wake_isr_thread = false, -+}; -+ -+static const struct auxiliary_device_id ipu6_isys_id_table[] = { -+ { -+ .name = "intel_ipu6.isys", -+ .driver_data = (kernel_ulong_t)&ipu6_isys_auxdrv_data, -+ }, -+ { } -+}; -+MODULE_DEVICE_TABLE(auxiliary, ipu6_isys_id_table); -+ -+static struct auxiliary_driver isys_driver = { -+ .name = IPU6_ISYS_NAME, -+ .probe = isys_probe, -+ .remove = isys_remove, -+ .id_table = ipu6_isys_id_table, -+ .driver = { -+ .pm = &isys_pm_ops, -+ }, -+}; -+ -+module_auxiliary_driver(isys_driver); -+ -+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>"); -+MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@intel.com>"); -+MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>"); -+MODULE_AUTHOR("Yunliang Ding <yunliang.ding@intel.com>"); -+MODULE_AUTHOR("Hongju Wang <hongju.wang@intel.com>"); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Intel IPU6 input system driver"); -+MODULE_IMPORT_NS(INTEL_IPU6); -+MODULE_IMPORT_NS(INTEL_IPU_BRIDGE); -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.h b/drivers/media/pci/intel/ipu6/ipu6-isys.h -new file mode 100644 -index 000000000000..cf7a90bfedc9 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.h -@@ -0,0 +1,207 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_ISYS_H -+#define IPU6_ISYS_H -+ -+#include <linux/irqreturn.h> -+#include <linux/list.h> -+#include <linux/mutex.h> -+#include <linux/pm_qos.h> -+#include <linux/spinlock_types.h> -+#include <linux/types.h> -+ -+#include <media/media-device.h> -+#include <media/v4l2-async.h> -+#include <media/v4l2-device.h> -+ -+#include "ipu6.h" -+#include "ipu6-fw-isys.h" -+#include "ipu6-isys-csi2.h" -+#include "ipu6-isys-video.h" -+ -+struct ipu6_bus_device; -+ -+#define IPU6_ISYS_ENTITY_PREFIX "Intel IPU6" -+/* FW support max 16 streams */ -+#define IPU6_ISYS_MAX_STREAMS 16 -+#define ISYS_UNISPART_IRQS (IPU6_ISYS_UNISPART_IRQ_SW | \ -+ IPU6_ISYS_UNISPART_IRQ_CSI0 | \ -+ IPU6_ISYS_UNISPART_IRQ_CSI1) -+ -+#define IPU6_ISYS_2600_MEM_LINE_ALIGN 64 -+ -+/* -+ * Current message queue configuration. These must be big enough -+ * so that they never gets full. Queues are located in system memory -+ */ -+#define IPU6_ISYS_SIZE_RECV_QUEUE 40 -+#define IPU6_ISYS_SIZE_SEND_QUEUE 40 -+#define IPU6_ISYS_SIZE_PROXY_RECV_QUEUE 5 -+#define IPU6_ISYS_SIZE_PROXY_SEND_QUEUE 5 -+#define IPU6_ISYS_NUM_RECV_QUEUE 1 -+ -+#define IPU6_ISYS_MIN_WIDTH 1U -+#define IPU6_ISYS_MIN_HEIGHT 1U -+#define IPU6_ISYS_MAX_WIDTH 4672U -+#define IPU6_ISYS_MAX_HEIGHT 3416U -+ -+/* the threshold granularity is 2KB on IPU6 */ -+#define IPU6_SRAM_GRANULARITY_SHIFT 11 -+#define IPU6_SRAM_GRANULARITY_SIZE 2048 -+/* the threshold granularity is 1KB on IPU6SE */ -+#define IPU6SE_SRAM_GRANULARITY_SHIFT 10 -+#define IPU6SE_SRAM_GRANULARITY_SIZE 1024 -+/* IS pixel buffer is 256KB, MaxSRAMSize is 200KB on IPU6 */ -+#define IPU6_MAX_SRAM_SIZE (200 << 10) -+/* IS pixel buffer is 128KB, MaxSRAMSize is 96KB on IPU6SE */ -+#define IPU6SE_MAX_SRAM_SIZE (96 << 10) -+ -+#define IPU6EP_LTR_VALUE 200 -+#define IPU6EP_MIN_MEMOPEN_TH 0x4 -+#define IPU6EP_MTL_LTR_VALUE 1023 -+#define IPU6EP_MTL_MIN_MEMOPEN_TH 0xc -+ -+struct ltr_did { -+ union { -+ u32 value; -+ struct { -+ u8 val0; -+ u8 val1; -+ u8 val2; -+ u8 val3; -+ } bits; -+ } lut_ltr; -+ union { -+ u32 value; -+ struct { -+ u8 th0; -+ u8 th1; -+ u8 th2; -+ u8 th3; -+ } bits; -+ } lut_fill_time; -+}; -+ -+struct isys_iwake_watermark { -+ bool iwake_enabled; -+ bool force_iwake_disable; -+ u32 iwake_threshold; -+ u64 isys_pixelbuffer_datarate; -+ struct ltr_did ltrdid; -+ struct mutex mutex; /* protect whole struct */ -+ struct ipu6_isys *isys; -+ struct list_head video_list; -+}; -+ -+struct ipu6_isys_csi2_config { -+ u32 nlanes; -+ u32 port; -+}; -+ -+struct sensor_async_sd { -+ struct v4l2_async_connection asc; -+ struct ipu6_isys_csi2_config csi2; -+}; -+ -+/* -+ * struct ipu6_isys -+ * -+ * @media_dev: Media device -+ * @v4l2_dev: V4L2 device -+ * @adev: ISYS bus device -+ * @power: Is ISYS powered on or not? -+ * @isr_bits: Which bits does the ISR handle? -+ * @power_lock: Serialise access to power (power state in general) -+ * @csi2_rx_ctrl_cached: cached shared value between all CSI2 receivers -+ * @streams_lock: serialise access to streams -+ * @streams: streams per firmware stream ID -+ * @fwcom: fw communication layer private pointer -+ * or optional external library private pointer -+ * @line_align: line alignment in memory -+ * @phy_termcal_val: the termination calibration value, only used for DWC PHY -+ * @need_reset: Isys requires d0i0->i3 transition -+ * @ref_count: total number of callers fw open -+ * @mutex: serialise access isys video open/release related operations -+ * @stream_mutex: serialise stream start and stop, queueing requests -+ * @pdata: platform data pointer -+ * @csi2: CSI-2 receivers -+ */ -+struct ipu6_isys { -+ struct media_device media_dev; -+ struct v4l2_device v4l2_dev; -+ struct ipu6_bus_device *adev; -+ -+ int power; -+ spinlock_t power_lock; -+ u32 isr_csi2_bits; -+ u32 csi2_rx_ctrl_cached; -+ spinlock_t streams_lock; -+ struct ipu6_isys_stream streams[IPU6_ISYS_MAX_STREAMS]; -+ int streams_ref_count[IPU6_ISYS_MAX_STREAMS]; -+ void *fwcom; -+ unsigned int line_align; -+ u32 phy_termcal_val; -+ bool need_reset; -+ bool icache_prefetch; -+ bool csi2_cse_ipc_not_supported; -+ unsigned int ref_count; -+ unsigned int stream_opened; -+ unsigned int sensor_type; -+ -+ struct mutex mutex; -+ struct mutex stream_mutex; -+ -+ struct ipu6_isys_pdata *pdata; -+ -+ int (*phy_set_power)(struct ipu6_isys *isys, -+ struct ipu6_isys_csi2_config *cfg, -+ const struct ipu6_isys_csi2_timing *timing, -+ bool on); -+ -+ struct ipu6_isys_csi2 *csi2; -+ struct ipu6_isys_video av[NR_OF_VIDEO_DEVICE]; -+ -+ struct pm_qos_request pm_qos; -+ spinlock_t listlock; /* Protect framebuflist */ -+ struct list_head framebuflist; -+ struct list_head framebuflist_fw; -+ struct v4l2_async_notifier notifier; -+ struct isys_iwake_watermark iwake_watermark; -+}; -+ -+struct isys_fw_msgs { -+ union { -+ u64 dummy; -+ struct ipu6_fw_isys_frame_buff_set_abi frame; -+ struct ipu6_fw_isys_stream_cfg_data_abi stream; -+ } fw_msg; -+ struct list_head head; -+ dma_addr_t dma_addr; -+}; -+ -+struct isys_fw_msgs *ipu6_get_fw_msg_buf(struct ipu6_isys_stream *stream); -+void ipu6_put_fw_msg_buf(struct ipu6_isys *isys, u64 data); -+void ipu6_cleanup_fw_msg_bufs(struct ipu6_isys *isys); -+ -+extern const struct v4l2_ioctl_ops ipu6_isys_ioctl_ops; -+ -+void isys_setup_hw(struct ipu6_isys *isys); -+irqreturn_t isys_isr(struct ipu6_bus_device *adev); -+void update_watermark_setting(struct ipu6_isys *isys); -+ -+int ipu6_isys_mcd_phy_set_power(struct ipu6_isys *isys, -+ struct ipu6_isys_csi2_config *cfg, -+ const struct ipu6_isys_csi2_timing *timing, -+ bool on); -+ -+int ipu6_isys_dwc_phy_set_power(struct ipu6_isys *isys, -+ struct ipu6_isys_csi2_config *cfg, -+ const struct ipu6_isys_csi2_timing *timing, -+ bool on); -+ -+int ipu6_isys_jsl_phy_set_power(struct ipu6_isys *isys, -+ struct ipu6_isys_csi2_config *cfg, -+ const struct ipu6_isys_csi2_timing *timing, -+ bool on); -+#endif /* IPU6_ISYS_H */ --- -2.43.2 - - -From 7cdb944c1cc8beb6f61268e2fe177d585fa5f415 Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:25 +0800 -Subject: [PATCH 18/33] media: intel/ipu6: input system video capture nodes - -Register v4l2 video device and setup the vb2 queue to -support basic video capture. Video streaming callback -will trigger the input system driver to construct a -input system stream configuration for firmware based on -data type and stream ID and then queue buffers to firmware -to do capture. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - .../media/pci/intel/ipu6/ipu6-isys-queue.c | 825 +++++++++++ - .../media/pci/intel/ipu6/ipu6-isys-queue.h | 76 + - .../media/pci/intel/ipu6/ipu6-isys-video.c | 1253 +++++++++++++++++ - .../media/pci/intel/ipu6/ipu6-isys-video.h | 136 ++ - 4 files changed, 2290 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys-queue.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys-queue.h - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys-video.c - create mode 100644 drivers/media/pci/intel/ipu6/ipu6-isys-video.h - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c -new file mode 100644 -index 000000000000..735d2d642d87 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c -@@ -0,0 +1,825 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+#include <linux/atomic.h> -+#include <linux/bug.h> -+#include <linux/device.h> -+#include <linux/list.h> -+#include <linux/lockdep.h> -+#include <linux/mutex.h> -+#include <linux/spinlock.h> -+#include <linux/types.h> -+ -+#include <media/media-entity.h> -+#include <media/v4l2-subdev.h> -+#include <media/videobuf2-dma-contig.h> -+#include <media/videobuf2-v4l2.h> -+ -+#include "ipu6-bus.h" -+#include "ipu6-fw-isys.h" -+#include "ipu6-isys.h" -+#include "ipu6-isys-video.h" -+ -+static int queue_setup(struct vb2_queue *q, unsigned int *num_buffers, -+ unsigned int *num_planes, unsigned int sizes[], -+ struct device *alloc_devs[]) -+{ -+ struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(q); -+ struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ bool use_fmt = false; -+ unsigned int i; -+ u32 size; -+ -+ /* num_planes == 0: we're being called through VIDIOC_REQBUFS */ -+ if (!*num_planes) { -+ use_fmt = true; -+ *num_planes = av->mpix.num_planes; -+ } -+ -+ for (i = 0; i < *num_planes; i++) { -+ size = av->mpix.plane_fmt[i].sizeimage; -+ if (use_fmt) { -+ sizes[i] = size; -+ } else if (sizes[i] < size) { -+ dev_err(dev, "%s: queue setup: plane %d size %u < %u\n", -+ av->vdev.name, i, sizes[i], size); -+ return -EINVAL; -+ } -+ -+ alloc_devs[i] = aq->dev; -+ } -+ -+ return 0; -+} -+ -+static int ipu6_isys_buf_prepare(struct vb2_buffer *vb) -+{ -+ struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue); -+ struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ -+ dev_dbg(dev, "buffer: %s: configured size %u, buffer size %lu\n", -+ av->vdev.name, av->mpix.plane_fmt[0].sizeimage, -+ vb2_plane_size(vb, 0)); -+ -+ if (av->mpix.plane_fmt[0].sizeimage > vb2_plane_size(vb, 0)) -+ return -EINVAL; -+ -+ vb2_set_plane_payload(vb, 0, av->mpix.plane_fmt[0].bytesperline * -+ av->mpix.height); -+ vb->planes[0].data_offset = 0; -+ -+ return 0; -+} -+ -+/* -+ * Queue a buffer list back to incoming or active queues. The buffers -+ * are removed from the buffer list. -+ */ -+void ipu6_isys_buffer_list_queue(struct ipu6_isys_buffer_list *bl, -+ unsigned long op_flags, -+ enum vb2_buffer_state state) -+{ -+ struct ipu6_isys_buffer *ib, *ib_safe; -+ unsigned long flags; -+ bool first = true; -+ -+ if (!bl) -+ return; -+ -+ WARN_ON_ONCE(!bl->nbufs); -+ WARN_ON_ONCE(op_flags & IPU6_ISYS_BUFFER_LIST_FL_ACTIVE && -+ op_flags & IPU6_ISYS_BUFFER_LIST_FL_INCOMING); -+ -+ list_for_each_entry_safe(ib, ib_safe, &bl->head, head) { -+ struct ipu6_isys_video *av; -+ struct vb2_buffer *vb = ipu6_isys_buffer_to_vb2_buffer(ib); -+ struct ipu6_isys_queue *aq = -+ vb2_queue_to_isys_queue(vb->vb2_queue); -+ struct device *dev; -+ -+ av = ipu6_isys_queue_to_video(aq); -+ dev = &av->isys->adev->auxdev.dev; -+ spin_lock_irqsave(&aq->lock, flags); -+ list_del(&ib->head); -+ if (op_flags & IPU6_ISYS_BUFFER_LIST_FL_ACTIVE) -+ list_add(&ib->head, &aq->active); -+ else if (op_flags & IPU6_ISYS_BUFFER_LIST_FL_INCOMING) -+ list_add_tail(&ib->head, &aq->incoming); -+ spin_unlock_irqrestore(&aq->lock, flags); -+ -+ if (op_flags & IPU6_ISYS_BUFFER_LIST_FL_SET_STATE) -+ vb2_buffer_done(vb, state); -+ -+ if (first) { -+ dev_dbg(dev, -+ "queue buf list %p flags %lx, s %d, %d bufs\n", -+ bl, op_flags, state, bl->nbufs); -+ first = false; -+ } -+ -+ bl->nbufs--; -+ } -+ -+ WARN_ON(bl->nbufs); -+} -+ -+/* -+ * flush_firmware_streamon_fail() - Flush in cases where requests may -+ * have been queued to firmware and the *firmware streamon fails for a -+ * reason or another. -+ */ -+static void flush_firmware_streamon_fail(struct ipu6_isys_stream *stream) -+{ -+ struct device *dev = &stream->isys->adev->auxdev.dev; -+ struct ipu6_isys_queue *aq; -+ unsigned long flags; -+ -+ lockdep_assert_held(&stream->mutex); -+ -+ list_for_each_entry(aq, &stream->queues, node) { -+ struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); -+ struct ipu6_isys_buffer *ib, *ib_safe; -+ -+ spin_lock_irqsave(&aq->lock, flags); -+ list_for_each_entry_safe(ib, ib_safe, &aq->active, head) { -+ struct vb2_buffer *vb = -+ ipu6_isys_buffer_to_vb2_buffer(ib); -+ -+ list_del(&ib->head); -+ if (av->streaming) { -+ dev_dbg(dev, -+ "%s: queue buffer %u back to incoming\n", -+ av->vdev.name, vb->index); -+ /* Queue already streaming, return to driver. */ -+ list_add(&ib->head, &aq->incoming); -+ continue; -+ } -+ /* Queue not yet streaming, return to user. */ -+ dev_dbg(dev, "%s: return %u back to videobuf2\n", -+ av->vdev.name, vb->index); -+ vb2_buffer_done(ipu6_isys_buffer_to_vb2_buffer(ib), -+ VB2_BUF_STATE_QUEUED); -+ } -+ spin_unlock_irqrestore(&aq->lock, flags); -+ } -+} -+ -+/* -+ * Attempt obtaining a buffer list from the incoming queues, a list of buffers -+ * that contains one entry from each video buffer queue. If a buffer can't be -+ * obtained from every queue, the buffers are returned back to the queue. -+ */ -+static int buffer_list_get(struct ipu6_isys_stream *stream, -+ struct ipu6_isys_buffer_list *bl) -+{ -+ struct device *dev = &stream->isys->adev->auxdev.dev; -+ struct ipu6_isys_queue *aq; -+ unsigned long flags; -+ unsigned long buf_flag = IPU6_ISYS_BUFFER_LIST_FL_INCOMING; -+ -+ bl->nbufs = 0; -+ INIT_LIST_HEAD(&bl->head); -+ -+ list_for_each_entry(aq, &stream->queues, node) { -+ struct ipu6_isys_buffer *ib; -+ -+ spin_lock_irqsave(&aq->lock, flags); -+ if (list_empty(&aq->incoming)) { -+ spin_unlock_irqrestore(&aq->lock, flags); -+ if (!list_empty(&bl->head)) -+ ipu6_isys_buffer_list_queue(bl, buf_flag, 0); -+ return -ENODATA; -+ } -+ -+ ib = list_last_entry(&aq->incoming, -+ struct ipu6_isys_buffer, head); -+ -+ dev_dbg(dev, "buffer: %s: buffer %u\n", -+ ipu6_isys_queue_to_video(aq)->vdev.name, -+ ipu6_isys_buffer_to_vb2_buffer(ib)->index); -+ list_del(&ib->head); -+ list_add(&ib->head, &bl->head); -+ spin_unlock_irqrestore(&aq->lock, flags); -+ -+ bl->nbufs++; -+ } -+ -+ dev_dbg(dev, "get buffer list %p, %u buffers\n", bl, bl->nbufs); -+ -+ return 0; -+} -+ -+static void -+ipu6_isys_buf_to_fw_frame_buf_pin(struct vb2_buffer *vb, -+ struct ipu6_fw_isys_frame_buff_set_abi *set) -+{ -+ struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue); -+ -+ set->output_pins[aq->fw_output].addr = -+ vb2_dma_contig_plane_dma_addr(vb, 0); -+ set->output_pins[aq->fw_output].out_buf_id = vb->index + 1; -+} -+ -+/* -+ * Convert a buffer list to a isys fw ABI framebuffer set. The -+ * buffer list is not modified. -+ */ -+#define IPU6_ISYS_FRAME_NUM_THRESHOLD (30) -+void -+ipu6_isys_buf_to_fw_frame_buf(struct ipu6_fw_isys_frame_buff_set_abi *set, -+ struct ipu6_isys_stream *stream, -+ struct ipu6_isys_buffer_list *bl) -+{ -+ struct ipu6_isys_buffer *ib; -+ -+ WARN_ON(!bl->nbufs); -+ -+ set->send_irq_sof = 1; -+ set->send_resp_sof = 1; -+ set->send_irq_eof = 0; -+ set->send_resp_eof = 0; -+ -+ if (stream->streaming) -+ set->send_irq_capture_ack = 0; -+ else -+ set->send_irq_capture_ack = 1; -+ set->send_irq_capture_done = 0; -+ -+ set->send_resp_capture_ack = 1; -+ set->send_resp_capture_done = 1; -+ if (atomic_read(&stream->sequence) >= IPU6_ISYS_FRAME_NUM_THRESHOLD) { -+ set->send_resp_capture_ack = 0; -+ set->send_resp_capture_done = 0; -+ } -+ -+ list_for_each_entry(ib, &bl->head, head) { -+ struct vb2_buffer *vb = ipu6_isys_buffer_to_vb2_buffer(ib); -+ -+ ipu6_isys_buf_to_fw_frame_buf_pin(vb, set); -+ } -+} -+ -+/* Start streaming for real. The buffer list must be available. */ -+static int ipu6_isys_stream_start(struct ipu6_isys_video *av, -+ struct ipu6_isys_buffer_list *bl, bool error) -+{ -+ struct ipu6_isys_stream *stream = av->stream; -+ struct device *dev = &stream->isys->adev->auxdev.dev; -+ struct ipu6_isys_buffer_list __bl; -+ int ret; -+ -+ mutex_lock(&stream->isys->stream_mutex); -+ ret = ipu6_isys_video_set_streaming(av, 1, bl); -+ mutex_unlock(&stream->isys->stream_mutex); -+ if (ret) -+ goto out_requeue; -+ -+ stream->streaming = 1; -+ -+ bl = &__bl; -+ -+ do { -+ struct ipu6_fw_isys_frame_buff_set_abi *buf = NULL; -+ struct isys_fw_msgs *msg; -+ u16 send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_CAPTURE; -+ -+ ret = buffer_list_get(stream, bl); -+ if (ret < 0) -+ break; -+ -+ msg = ipu6_get_fw_msg_buf(stream); -+ if (!msg) -+ return -ENOMEM; -+ -+ buf = &msg->fw_msg.frame; -+ ipu6_isys_buf_to_fw_frame_buf(buf, stream, bl); -+ ipu6_fw_isys_dump_frame_buff_set(dev, buf, -+ stream->nr_output_pins); -+ ipu6_isys_buffer_list_queue(bl, IPU6_ISYS_BUFFER_LIST_FL_ACTIVE, -+ 0); -+ ret = ipu6_fw_isys_complex_cmd(stream->isys, -+ stream->stream_handle, buf, -+ msg->dma_addr, sizeof(*buf), -+ send_type); -+ } while (!WARN_ON(ret)); -+ -+ return 0; -+ -+out_requeue: -+ if (bl && bl->nbufs) -+ ipu6_isys_buffer_list_queue(bl, -+ (IPU6_ISYS_BUFFER_LIST_FL_INCOMING | -+ error) ? -+ IPU6_ISYS_BUFFER_LIST_FL_SET_STATE : -+ 0, error ? VB2_BUF_STATE_ERROR : -+ VB2_BUF_STATE_QUEUED); -+ flush_firmware_streamon_fail(stream); -+ -+ return ret; -+} -+ -+static void buf_queue(struct vb2_buffer *vb) -+{ -+ struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue); -+ struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); -+ struct vb2_v4l2_buffer *vvb = to_vb2_v4l2_buffer(vb); -+ struct ipu6_isys_video_buffer *ivb = -+ vb2_buffer_to_ipu6_isys_video_buffer(vvb); -+ struct ipu6_isys_buffer *ib = &ivb->ib; -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ struct media_pipeline *media_pipe = -+ media_entity_pipeline(&av->vdev.entity); -+ struct ipu6_fw_isys_frame_buff_set_abi *buf = NULL; -+ struct ipu6_isys_stream *stream = av->stream; -+ struct ipu6_isys_buffer_list bl; -+ struct isys_fw_msgs *msg; -+ unsigned long flags; -+ dma_addr_t dma; -+ unsigned int i; -+ int ret; -+ -+ dev_dbg(dev, "queue buffer %u for %s\n", vb->index, av->vdev.name); -+ -+ for (i = 0; i < vb->num_planes; i++) { -+ dma = vb2_dma_contig_plane_dma_addr(vb, i); -+ dev_dbg(dev, "iova: plane %u iova %pad\n", i, &dma); -+ } -+ -+ spin_lock_irqsave(&aq->lock, flags); -+ list_add(&ib->head, &aq->incoming); -+ spin_unlock_irqrestore(&aq->lock, flags); -+ -+ if (!media_pipe || !vb->vb2_queue->start_streaming_called) { -+ dev_dbg(dev, "media pipeline is not ready for %s\n", -+ av->vdev.name); -+ return; -+ } -+ -+ mutex_lock(&stream->mutex); -+ -+ if (stream->nr_streaming != stream->nr_queues) { -+ dev_dbg(dev, "not streaming yet, adding to incoming\n"); -+ goto out; -+ } -+ -+ /* -+ * We just put one buffer to the incoming list of this queue -+ * (above). Let's see whether all queues in the pipeline would -+ * have a buffer. -+ */ -+ ret = buffer_list_get(stream, &bl); -+ if (ret < 0) { -+ dev_warn(dev, "No buffers available\n"); -+ goto out; -+ } -+ -+ msg = ipu6_get_fw_msg_buf(stream); -+ if (!msg) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ buf = &msg->fw_msg.frame; -+ ipu6_isys_buf_to_fw_frame_buf(buf, stream, &bl); -+ ipu6_fw_isys_dump_frame_buff_set(dev, buf, stream->nr_output_pins); -+ -+ if (!stream->streaming) { -+ ret = ipu6_isys_stream_start(av, &bl, true); -+ if (ret) -+ dev_err(dev, "stream start failed.\n"); -+ goto out; -+ } -+ -+ /* -+ * We must queue the buffers in the buffer list to the -+ * appropriate video buffer queues BEFORE passing them to the -+ * firmware since we could get a buffer event back before we -+ * have queued them ourselves to the active queue. -+ */ -+ ipu6_isys_buffer_list_queue(&bl, IPU6_ISYS_BUFFER_LIST_FL_ACTIVE, 0); -+ -+ ret = ipu6_fw_isys_complex_cmd(stream->isys, stream->stream_handle, -+ buf, msg->dma_addr, sizeof(*buf), -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_CAPTURE); -+ if (ret < 0) -+ dev_err(dev, "send stream capture failed\n"); -+ -+out: -+ mutex_unlock(&stream->mutex); -+} -+ -+static int ipu6_isys_link_fmt_validate(struct ipu6_isys_queue *aq) -+{ -+ struct v4l2_mbus_framefmt format; -+ struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ struct media_pad *remote_pad = -+ media_pad_remote_pad_first(av->vdev.entity.pads); -+ struct v4l2_subdev *sd; -+ u32 r_stream; -+ int ret; -+ -+ if (!remote_pad) -+ return -ENOTCONN; -+ -+ sd = media_entity_to_v4l2_subdev(remote_pad->entity); -+ r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, remote_pad->index); -+ -+ ret = ipu6_isys_get_stream_pad_fmt(sd, remote_pad->index, r_stream, -+ &format); -+ -+ if (ret) { -+ dev_dbg(dev, "failed to get %s: pad %d, stream:%d format\n", -+ sd->entity.name, remote_pad->index, r_stream); -+ return ret; -+ } -+ -+ if (format.width != av->mpix.width || -+ format.height != av->mpix.height) { -+ dev_dbg(dev, "wrong width or height %ux%u (%ux%u expected)\n", -+ av->mpix.width, av->mpix.height, -+ format.width, format.height); -+ return -EINVAL; -+ } -+ -+ if (format.field != av->mpix.field) { -+ dev_dbg(dev, "wrong field value 0x%8.8x (0x%8.8x expected)\n", -+ av->mpix.field, format.field); -+ return -EINVAL; -+ } -+ -+ if (format.code != av->pfmt->code) { -+ dev_dbg(dev, "wrong mbus code 0x%8.8x (0x%8.8x expected)\n", -+ av->pfmt->code, format.code); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static void return_buffers(struct ipu6_isys_queue *aq, -+ enum vb2_buffer_state state) -+{ -+ struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); -+ struct ipu6_isys_buffer *ib; -+ bool need_reset = false; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&aq->lock, flags); -+ while (!list_empty(&aq->incoming)) { -+ struct vb2_buffer *vb; -+ -+ ib = list_first_entry(&aq->incoming, struct ipu6_isys_buffer, -+ head); -+ vb = ipu6_isys_buffer_to_vb2_buffer(ib); -+ list_del(&ib->head); -+ spin_unlock_irqrestore(&aq->lock, flags); -+ -+ vb2_buffer_done(vb, state); -+ -+ spin_lock_irqsave(&aq->lock, flags); -+ } -+ -+ /* -+ * Something went wrong (FW crash / HW hang / not all buffers -+ * returned from isys) if there are still buffers queued in active -+ * queue. We have to clean up places a bit. -+ */ -+ while (!list_empty(&aq->active)) { -+ struct vb2_buffer *vb; -+ -+ ib = list_first_entry(&aq->active, struct ipu6_isys_buffer, -+ head); -+ vb = ipu6_isys_buffer_to_vb2_buffer(ib); -+ -+ list_del(&ib->head); -+ spin_unlock_irqrestore(&aq->lock, flags); -+ -+ vb2_buffer_done(vb, state); -+ -+ spin_lock_irqsave(&aq->lock, flags); -+ need_reset = true; -+ } -+ -+ spin_unlock_irqrestore(&aq->lock, flags); -+ -+ if (need_reset) { -+ mutex_lock(&av->isys->mutex); -+ av->isys->need_reset = true; -+ mutex_unlock(&av->isys->mutex); -+ } -+} -+ -+static void ipu6_isys_stream_cleanup(struct ipu6_isys_video *av) -+{ -+ video_device_pipeline_stop(&av->vdev); -+ ipu6_isys_put_stream(av->stream); -+ av->stream = NULL; -+} -+ -+static int start_streaming(struct vb2_queue *q, unsigned int count) -+{ -+ struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(q); -+ struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ struct ipu6_isys_buffer_list __bl, *bl = NULL; -+ struct ipu6_isys_stream *stream; -+ struct media_entity *source_entity = NULL; -+ int nr_queues, ret; -+ -+ dev_dbg(dev, "stream: %s: width %u, height %u, css pixelformat %u\n", -+ av->vdev.name, av->mpix.width, av->mpix.height, -+ av->pfmt->css_pixelformat); -+ -+ ret = ipu6_isys_setup_video(av, &source_entity, &nr_queues); -+ if (ret < 0) { -+ dev_err(dev, "failed to setup video\n"); -+ goto out_return_buffers; -+ } -+ -+ ret = ipu6_isys_link_fmt_validate(aq); -+ if (ret) { -+ dev_err(dev, -+ "%s: link format validation failed (%d)\n", -+ av->vdev.name, ret); -+ goto out_pipeline_stop; -+ } -+ -+ ret = ipu6_isys_fw_open(av->isys); -+ if (ret) -+ goto out_pipeline_stop; -+ -+ stream = av->stream; -+ mutex_lock(&stream->mutex); -+ if (!stream->nr_streaming) { -+ ret = ipu6_isys_video_prepare_stream(av, source_entity, -+ nr_queues); -+ if (ret) -+ goto out_fw_close; -+ } -+ -+ stream->nr_streaming++; -+ dev_dbg(dev, "queue %u of %u\n", stream->nr_streaming, -+ stream->nr_queues); -+ -+ list_add(&aq->node, &stream->queues); -+ ipu6_isys_set_csi2_streams_status(av, true); -+ ipu6_isys_configure_stream_watermark(av, true); -+ ipu6_isys_update_stream_watermark(av, true); -+ -+ if (stream->nr_streaming != stream->nr_queues) -+ goto out; -+ -+ bl = &__bl; -+ ret = buffer_list_get(stream, bl); -+ if (ret < 0) { -+ dev_dbg(dev, -+ "no buffer available, postponing streamon\n"); -+ goto out; -+ } -+ -+ ret = ipu6_isys_stream_start(av, bl, false); -+ if (ret) -+ goto out_stream_start; -+ -+out: -+ mutex_unlock(&stream->mutex); -+ -+ return 0; -+ -+out_stream_start: -+ list_del(&aq->node); -+ stream->nr_streaming--; -+ -+out_fw_close: -+ mutex_unlock(&stream->mutex); -+ ipu6_isys_fw_close(av->isys); -+ -+out_pipeline_stop: -+ ipu6_isys_stream_cleanup(av); -+ -+out_return_buffers: -+ return_buffers(aq, VB2_BUF_STATE_QUEUED); -+ -+ return ret; -+} -+ -+static void stop_streaming(struct vb2_queue *q) -+{ -+ struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(q); -+ struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); -+ struct ipu6_isys_stream *stream = av->stream; -+ -+ ipu6_isys_set_csi2_streams_status(av, false); -+ -+ mutex_lock(&stream->mutex); -+ -+ ipu6_isys_update_stream_watermark(av, false); -+ -+ mutex_lock(&av->isys->stream_mutex); -+ if (stream->nr_streaming == stream->nr_queues && stream->streaming) -+ ipu6_isys_video_set_streaming(av, 0, NULL); -+ mutex_unlock(&av->isys->stream_mutex); -+ -+ stream->nr_streaming--; -+ list_del(&aq->node); -+ stream->streaming = 0; -+ mutex_unlock(&stream->mutex); -+ -+ ipu6_isys_stream_cleanup(av); -+ -+ return_buffers(aq, VB2_BUF_STATE_ERROR); -+ -+ ipu6_isys_fw_close(av->isys); -+} -+ -+static unsigned int -+get_sof_sequence_by_timestamp(struct ipu6_isys_stream *stream, -+ struct ipu6_fw_isys_resp_info_abi *info) -+{ -+ u64 time = (u64)info->timestamp[1] << 32 | info->timestamp[0]; -+ struct ipu6_isys *isys = stream->isys; -+ struct device *dev = &isys->adev->auxdev.dev; -+ unsigned int i; -+ -+ /* -+ * The timestamp is invalid as no TSC in some FPGA platform, -+ * so get the sequence from pipeline directly in this case. -+ */ -+ if (time == 0) -+ return atomic_read(&stream->sequence) - 1; -+ -+ for (i = 0; i < IPU6_ISYS_MAX_PARALLEL_SOF; i++) -+ if (time == stream->seq[i].timestamp) { -+ dev_dbg(dev, "sof: using seq nr %u for ts %llu\n", -+ stream->seq[i].sequence, time); -+ return stream->seq[i].sequence; -+ } -+ -+ for (i = 0; i < IPU6_ISYS_MAX_PARALLEL_SOF; i++) -+ dev_dbg(dev, "sof: sequence %u, timestamp value %llu\n", -+ stream->seq[i].sequence, stream->seq[i].timestamp); -+ -+ return 0; -+} -+ -+static u64 get_sof_ns_delta(struct ipu6_isys_video *av, -+ struct ipu6_fw_isys_resp_info_abi *info) -+{ -+ struct ipu6_bus_device *adev = av->isys->adev; -+ struct ipu6_device *isp = adev->isp; -+ u64 delta, tsc_now; -+ -+ ipu6_buttress_tsc_read(isp, &tsc_now); -+ if (!tsc_now) -+ return 0; -+ -+ delta = tsc_now - ((u64)info->timestamp[1] << 32 | info->timestamp[0]); -+ -+ return ipu6_buttress_tsc_ticks_to_ns(delta, isp); -+} -+ -+void ipu6_isys_buf_calc_sequence_time(struct ipu6_isys_buffer *ib, -+ struct ipu6_fw_isys_resp_info_abi *info) -+{ -+ struct vb2_buffer *vb = ipu6_isys_buffer_to_vb2_buffer(ib); -+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); -+ struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue); -+ struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ struct ipu6_isys_stream *stream = av->stream; -+ u64 ns; -+ u32 sequence; -+ -+ ns = ktime_get_ns() - get_sof_ns_delta(av, info); -+ sequence = get_sof_sequence_by_timestamp(stream, info); -+ -+ vbuf->vb2_buf.timestamp = ns; -+ vbuf->sequence = sequence; -+ -+ dev_dbg(dev, "buf: %s: buffer done, CPU-timestamp:%lld, sequence:%d\n", -+ av->vdev.name, ktime_get_ns(), sequence); -+ dev_dbg(dev, "index:%d, vbuf timestamp:%lld\n", vb->index, -+ vbuf->vb2_buf.timestamp); -+} -+ -+void ipu6_isys_queue_buf_done(struct ipu6_isys_buffer *ib) -+{ -+ struct vb2_buffer *vb = ipu6_isys_buffer_to_vb2_buffer(ib); -+ -+ if (atomic_read(&ib->str2mmio_flag)) { -+ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); -+ /* -+ * Operation on buffer is ended with error and will be reported -+ * to the userspace when it is de-queued -+ */ -+ atomic_set(&ib->str2mmio_flag, 0); -+ } else { -+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE); -+ } -+} -+ -+void ipu6_isys_queue_buf_ready(struct ipu6_isys_stream *stream, -+ struct ipu6_fw_isys_resp_info_abi *info) -+{ -+ struct ipu6_isys_queue *aq = stream->output_pins[info->pin_id].aq; -+ struct ipu6_isys *isys = stream->isys; -+ struct device *dev = &isys->adev->auxdev.dev; -+ struct ipu6_isys_buffer *ib; -+ struct vb2_buffer *vb; -+ unsigned long flags; -+ bool first = true; -+ struct vb2_v4l2_buffer *buf; -+ -+ spin_lock_irqsave(&aq->lock, flags); -+ if (list_empty(&aq->active)) { -+ spin_unlock_irqrestore(&aq->lock, flags); -+ dev_err(dev, "active queue empty\n"); -+ return; -+ } -+ -+ list_for_each_entry_reverse(ib, &aq->active, head) { -+ dma_addr_t addr; -+ -+ vb = ipu6_isys_buffer_to_vb2_buffer(ib); -+ addr = vb2_dma_contig_plane_dma_addr(vb, 0); -+ -+ if (info->pin.addr != addr) { -+ if (first) -+ dev_err(dev, "Unexpected buffer address %pad\n", -+ &addr); -+ first = false; -+ continue; -+ } -+ -+ if (info->error_info.error == -+ IPU6_FW_ISYS_ERROR_HW_REPORTED_STR2MMIO) { -+ /* -+ * Check for error message: -+ * 'IPU6_FW_ISYS_ERROR_HW_REPORTED_STR2MMIO' -+ */ -+ atomic_set(&ib->str2mmio_flag, 1); -+ } -+ dev_dbg(dev, "buffer: found buffer %pad\n", &addr); -+ -+ buf = to_vb2_v4l2_buffer(vb); -+ buf->field = V4L2_FIELD_NONE; -+ -+ list_del(&ib->head); -+ spin_unlock_irqrestore(&aq->lock, flags); -+ -+ ipu6_isys_buf_calc_sequence_time(ib, info); -+ -+ ipu6_isys_queue_buf_done(ib); -+ -+ return; -+ } -+ -+ dev_err(dev, "Failed to find a matching video buffer"); -+ -+ spin_unlock_irqrestore(&aq->lock, flags); -+} -+ -+static const struct vb2_ops ipu6_isys_queue_ops = { -+ .queue_setup = queue_setup, -+ .wait_prepare = vb2_ops_wait_prepare, -+ .wait_finish = vb2_ops_wait_finish, -+ .buf_prepare = ipu6_isys_buf_prepare, -+ .start_streaming = start_streaming, -+ .stop_streaming = stop_streaming, -+ .buf_queue = buf_queue, -+}; -+ -+int ipu6_isys_queue_init(struct ipu6_isys_queue *aq) -+{ -+ struct ipu6_isys *isys = ipu6_isys_queue_to_video(aq)->isys; -+ struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); -+ int ret; -+ -+ /* no support for userptr */ -+ if (!aq->vbq.io_modes) -+ aq->vbq.io_modes = VB2_MMAP | VB2_DMABUF; -+ -+ aq->vbq.drv_priv = aq; -+ aq->vbq.ops = &ipu6_isys_queue_ops; -+ aq->vbq.lock = &av->mutex; -+ aq->vbq.mem_ops = &vb2_dma_contig_memops; -+ aq->vbq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; -+ aq->vbq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; -+ -+ ret = vb2_queue_init(&aq->vbq); -+ if (ret) -+ return ret; -+ -+ aq->dev = &isys->adev->auxdev.dev; -+ aq->vbq.dev = &isys->adev->auxdev.dev; -+ spin_lock_init(&aq->lock); -+ INIT_LIST_HEAD(&aq->active); -+ INIT_LIST_HEAD(&aq->incoming); -+ -+ return 0; -+} -+ -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.h b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.h -new file mode 100644 -index 000000000000..9fb454577bb5 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.h -@@ -0,0 +1,76 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_ISYS_QUEUE_H -+#define IPU6_ISYS_QUEUE_H -+ -+#include <linux/container_of.h> -+#include <linux/atomic.h> -+#include <linux/device.h> -+#include <linux/list.h> -+#include <linux/spinlock_types.h> -+ -+#include <media/videobuf2-v4l2.h> -+ -+#include "ipu6-fw-isys.h" -+#include "ipu6-isys-video.h" -+ -+struct ipu6_isys_queue { -+ struct vb2_queue vbq; -+ struct list_head node; -+ struct device *dev; -+ /* -+ * @lock: serialise access to queued and pre_streamon_queued -+ */ -+ spinlock_t lock; -+ struct list_head active; -+ struct list_head incoming; -+ unsigned int fw_output; -+}; -+ -+struct ipu6_isys_buffer { -+ struct list_head head; -+ atomic_t str2mmio_flag; -+}; -+ -+struct ipu6_isys_video_buffer { -+ struct vb2_v4l2_buffer vb_v4l2; -+ struct ipu6_isys_buffer ib; -+}; -+ -+#define IPU6_ISYS_BUFFER_LIST_FL_INCOMING BIT(0) -+#define IPU6_ISYS_BUFFER_LIST_FL_ACTIVE BIT(1) -+#define IPU6_ISYS_BUFFER_LIST_FL_SET_STATE BIT(2) -+ -+struct ipu6_isys_buffer_list { -+ struct list_head head; -+ unsigned int nbufs; -+}; -+ -+#define vb2_queue_to_isys_queue(__vb2) \ -+ container_of(__vb2, struct ipu6_isys_queue, vbq) -+ -+#define ipu6_isys_to_isys_video_buffer(__ib) \ -+ container_of(__ib, struct ipu6_isys_video_buffer, ib) -+ -+#define vb2_buffer_to_ipu6_isys_video_buffer(__vvb) \ -+ container_of(__vvb, struct ipu6_isys_video_buffer, vb_v4l2) -+ -+#define ipu6_isys_buffer_to_vb2_buffer(__ib) \ -+ (&ipu6_isys_to_isys_video_buffer(__ib)->vb_v4l2.vb2_buf) -+ -+void ipu6_isys_buffer_list_queue(struct ipu6_isys_buffer_list *bl, -+ unsigned long op_flags, -+ enum vb2_buffer_state state); -+void -+ipu6_isys_buf_to_fw_frame_buf(struct ipu6_fw_isys_frame_buff_set_abi *set, -+ struct ipu6_isys_stream *stream, -+ struct ipu6_isys_buffer_list *bl); -+void -+ipu6_isys_buf_calc_sequence_time(struct ipu6_isys_buffer *ib, -+ struct ipu6_fw_isys_resp_info_abi *info); -+void ipu6_isys_queue_buf_done(struct ipu6_isys_buffer *ib); -+void ipu6_isys_queue_buf_ready(struct ipu6_isys_stream *stream, -+ struct ipu6_fw_isys_resp_info_abi *info); -+int ipu6_isys_queue_init(struct ipu6_isys_queue *aq); -+#endif /* IPU6_ISYS_QUEUE_H */ -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -new file mode 100644 -index 000000000000..847eac26bcd6 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -@@ -0,0 +1,1253 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2013 - 2023 Intel Corporation -+ */ -+ -+#include <linux/align.h> -+#include <linux/bits.h> -+#include <linux/bug.h> -+#include <linux/completion.h> -+#include <linux/container_of.h> -+#include <linux/device.h> -+#include <linux/list.h> -+#include <linux/math64.h> -+#include <linux/minmax.h> -+#include <linux/module.h> -+#include <linux/mutex.h> -+#include <linux/pm_runtime.h> -+#include <linux/spinlock.h> -+#include <linux/string.h> -+ -+#include <media/media-entity.h> -+#include <media/v4l2-ctrls.h> -+#include <media/v4l2-dev.h> -+#include <media/v4l2-fh.h> -+#include <media/v4l2-ioctl.h> -+#include <media/v4l2-subdev.h> -+#include <media/videobuf2-v4l2.h> -+ -+#include "ipu6.h" -+#include "ipu6-bus.h" -+#include "ipu6-cpd.h" -+#include "ipu6-fw-isys.h" -+#include "ipu6-isys.h" -+#include "ipu6-isys-csi2.h" -+#include "ipu6-isys-queue.h" -+#include "ipu6-isys-video.h" -+#include "ipu6-platform-regs.h" -+ -+const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = { -+ {V4L2_PIX_FMT_SBGGR12, 16, 12, MEDIA_BUS_FMT_SBGGR12_1X12, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW16}, -+ {V4L2_PIX_FMT_SGBRG12, 16, 12, MEDIA_BUS_FMT_SGBRG12_1X12, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW16}, -+ {V4L2_PIX_FMT_SGRBG12, 16, 12, MEDIA_BUS_FMT_SGRBG12_1X12, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW16}, -+ {V4L2_PIX_FMT_SRGGB12, 16, 12, MEDIA_BUS_FMT_SRGGB12_1X12, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW16}, -+ {V4L2_PIX_FMT_SBGGR10, 16, 10, MEDIA_BUS_FMT_SBGGR10_1X10, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW16}, -+ {V4L2_PIX_FMT_SGBRG10, 16, 10, MEDIA_BUS_FMT_SGBRG10_1X10, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW16}, -+ {V4L2_PIX_FMT_SGRBG10, 16, 10, MEDIA_BUS_FMT_SGRBG10_1X10, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW16}, -+ {V4L2_PIX_FMT_SRGGB10, 16, 10, MEDIA_BUS_FMT_SRGGB10_1X10, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW16}, -+ {V4L2_PIX_FMT_SBGGR8, 8, 8, MEDIA_BUS_FMT_SBGGR8_1X8, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW8}, -+ {V4L2_PIX_FMT_SGBRG8, 8, 8, MEDIA_BUS_FMT_SGBRG8_1X8, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW8}, -+ {V4L2_PIX_FMT_SGRBG8, 8, 8, MEDIA_BUS_FMT_SGRBG8_1X8, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW8}, -+ {V4L2_PIX_FMT_SRGGB8, 8, 8, MEDIA_BUS_FMT_SRGGB8_1X8, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW8}, -+ {V4L2_PIX_FMT_SBGGR12P, 12, 12, MEDIA_BUS_FMT_SBGGR12_1X12, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW12}, -+ {V4L2_PIX_FMT_SGBRG12P, 12, 12, MEDIA_BUS_FMT_SGBRG12_1X12, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW12}, -+ {V4L2_PIX_FMT_SGRBG12P, 12, 12, MEDIA_BUS_FMT_SGRBG12_1X12, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW12}, -+ {V4L2_PIX_FMT_SRGGB12P, 12, 12, MEDIA_BUS_FMT_SRGGB12_1X12, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW12}, -+ {V4L2_PIX_FMT_SBGGR10P, 10, 10, MEDIA_BUS_FMT_SBGGR10_1X10, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW10}, -+ {V4L2_PIX_FMT_SGBRG10P, 10, 10, MEDIA_BUS_FMT_SGBRG10_1X10, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW10}, -+ {V4L2_PIX_FMT_SGRBG10P, 10, 10, MEDIA_BUS_FMT_SGRBG10_1X10, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW10}, -+ {V4L2_PIX_FMT_SRGGB10P, 10, 10, MEDIA_BUS_FMT_SRGGB10_1X10, -+ IPU6_FW_ISYS_FRAME_FORMAT_RAW10}, -+ {V4L2_PIX_FMT_UYVY, 16, 16, MEDIA_BUS_FMT_UYVY8_1X16, -+ IPU6_FW_ISYS_FRAME_FORMAT_UYVY}, -+ {V4L2_PIX_FMT_YUYV, 16, 16, MEDIA_BUS_FMT_YUYV8_1X16, -+ IPU6_FW_ISYS_FRAME_FORMAT_YUYV}, -+ {V4L2_PIX_FMT_RGB565, 16, 16, MEDIA_BUS_FMT_RGB565_1X16, -+ IPU6_FW_ISYS_FRAME_FORMAT_RGB565}, -+ {V4L2_PIX_FMT_BGR24, 24, 24, MEDIA_BUS_FMT_RGB888_1X24, -+ IPU6_FW_ISYS_FRAME_FORMAT_RGBA888}, -+}; -+ -+static int video_open(struct file *file) -+{ -+ struct ipu6_isys_video *av = video_drvdata(file); -+ struct ipu6_isys *isys = av->isys; -+ struct ipu6_bus_device *adev = isys->adev; -+ -+ mutex_lock(&isys->mutex); -+ if (isys->need_reset) { -+ mutex_unlock(&isys->mutex); -+ dev_warn(&adev->auxdev.dev, "isys power cycle required\n"); -+ return -EIO; -+ } -+ mutex_unlock(&isys->mutex); -+ -+ return v4l2_fh_open(file); -+} -+ -+static int video_release(struct file *file) -+{ -+ return vb2_fop_release(file); -+} -+ -+static const struct ipu6_isys_pixelformat * -+ipu6_isys_get_pixelformat(u32 pixelformat) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { -+ const struct ipu6_isys_pixelformat *pfmt = &ipu6_isys_pfmts[i]; -+ -+ if (pfmt->pixelformat == pixelformat) -+ return pfmt; -+ } -+ -+ return &ipu6_isys_pfmts[0]; -+} -+ -+int ipu6_isys_vidioc_querycap(struct file *file, void *fh, -+ struct v4l2_capability *cap) -+{ -+ struct ipu6_isys_video *av = video_drvdata(file); -+ -+ strscpy(cap->driver, IPU6_ISYS_NAME, sizeof(cap->driver)); -+ strscpy(cap->card, av->isys->media_dev.model, sizeof(cap->card)); -+ -+ return 0; -+} -+ -+int ipu6_isys_vidioc_enum_fmt(struct file *file, void *fh, -+ struct v4l2_fmtdesc *f) -+{ -+ unsigned int i, found = 0; -+ -+ if (f->index >= ARRAY_SIZE(ipu6_isys_pfmts)) -+ return -EINVAL; -+ -+ if (!f->mbus_code) { -+ f->flags = 0; -+ f->pixelformat = ipu6_isys_pfmts[f->index].pixelformat; -+ return 0; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { -+ if (f->mbus_code != ipu6_isys_pfmts[i].code) -+ continue; -+ -+ if (f->index == found) { -+ f->flags = 0; -+ f->pixelformat = ipu6_isys_pfmts[i].pixelformat; -+ return 0; -+ } -+ found++; -+ } -+ -+ return -EINVAL; -+} -+ -+static int ipu6_isys_vidioc_enum_framesizes(struct file *file, void *fh, -+ struct v4l2_frmsizeenum *fsize) -+{ -+ if (fsize->index > 0) -+ return -EINVAL; -+ -+ fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; -+ fsize->stepwise.min_width = IPU6_ISYS_MIN_WIDTH; -+ fsize->stepwise.max_width = IPU6_ISYS_MAX_WIDTH; -+ fsize->stepwise.min_height = IPU6_ISYS_MIN_HEIGHT; -+ fsize->stepwise.max_height = IPU6_ISYS_MAX_HEIGHT; -+ fsize->stepwise.step_width = 2; -+ fsize->stepwise.step_height = 2; -+ -+ return 0; -+} -+ -+static int vidioc_g_fmt_vid_cap_mplane(struct file *file, void *fh, -+ struct v4l2_format *fmt) -+{ -+ struct ipu6_isys_video *av = video_drvdata(file); -+ -+ fmt->fmt.pix_mp = av->mpix; -+ -+ return 0; -+} -+ -+static const struct ipu6_isys_pixelformat * -+ipu6_isys_video_try_fmt_vid_mplane(struct ipu6_isys_video *av, -+ struct v4l2_pix_format_mplane *mpix) -+{ -+ const struct ipu6_isys_pixelformat *pfmt = -+ ipu6_isys_get_pixelformat(mpix->pixelformat); -+ -+ mpix->pixelformat = pfmt->pixelformat; -+ mpix->num_planes = 1; -+ -+ mpix->width = clamp(mpix->width, IPU6_ISYS_MIN_WIDTH, -+ IPU6_ISYS_MAX_WIDTH); -+ mpix->height = clamp(mpix->height, IPU6_ISYS_MIN_HEIGHT, -+ IPU6_ISYS_MAX_HEIGHT); -+ -+ if (pfmt->bpp != pfmt->bpp_packed) -+ mpix->plane_fmt[0].bytesperline = -+ mpix->width * DIV_ROUND_UP(pfmt->bpp, BITS_PER_BYTE); -+ else -+ mpix->plane_fmt[0].bytesperline = -+ DIV_ROUND_UP((unsigned int)mpix->width * pfmt->bpp, -+ BITS_PER_BYTE); -+ -+ mpix->plane_fmt[0].bytesperline = ALIGN(mpix->plane_fmt[0].bytesperline, -+ av->isys->line_align); -+ -+ /* -+ * (height + 1) * bytesperline due to a hardware issue: the DMA unit -+ * is a power of two, and a line should be transferred as few units -+ * as possible. The result is that up to line length more data than -+ * the image size may be transferred to memory after the image. -+ * Another limitation is the GDA allocation unit size. For low -+ * resolution it gives a bigger number. Use larger one to avoid -+ * memory corruption. -+ */ -+ mpix->plane_fmt[0].sizeimage = -+ max(mpix->plane_fmt[0].sizeimage, -+ mpix->plane_fmt[0].bytesperline * mpix->height + -+ max(mpix->plane_fmt[0].bytesperline, -+ av->isys->pdata->ipdata->isys_dma_overshoot)); -+ -+ memset(mpix->plane_fmt[0].reserved, 0, -+ sizeof(mpix->plane_fmt[0].reserved)); -+ -+ mpix->field = V4L2_FIELD_NONE; -+ -+ mpix->colorspace = V4L2_COLORSPACE_RAW; -+ mpix->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; -+ mpix->quantization = V4L2_QUANTIZATION_DEFAULT; -+ mpix->xfer_func = V4L2_XFER_FUNC_DEFAULT; -+ -+ return pfmt; -+} -+ -+static int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *fh, -+ struct v4l2_format *f) -+{ -+ struct ipu6_isys_video *av = video_drvdata(file); -+ -+ if (av->aq.vbq.streaming) -+ return -EBUSY; -+ -+ av->pfmt = ipu6_isys_video_try_fmt_vid_mplane(av, &f->fmt.pix_mp); -+ av->mpix = f->fmt.pix_mp; -+ -+ return 0; -+} -+ -+static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *fh, -+ struct v4l2_format *f) -+{ -+ struct ipu6_isys_video *av = video_drvdata(file); -+ -+ ipu6_isys_video_try_fmt_vid_mplane(av, &f->fmt.pix_mp); -+ -+ return 0; -+} -+ -+static int link_validate(struct media_link *link) -+{ -+ struct ipu6_isys_video *av = -+ container_of(link->sink, struct ipu6_isys_video, pad); -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ struct v4l2_subdev_state *s_state; -+ struct v4l2_subdev *s_sd; -+ struct v4l2_mbus_framefmt *s_fmt; -+ struct media_pad *s_pad; -+ u32 s_stream; -+ int ret = -EPIPE; -+ -+ if (!link->source->entity) -+ return ret; -+ -+ s_sd = media_entity_to_v4l2_subdev(link->source->entity); -+ s_state = v4l2_subdev_get_unlocked_active_state(s_sd); -+ if (!s_state) -+ return ret; -+ -+ dev_dbg(dev, "validating link \"%s\":%u -> \"%s\"\n", -+ link->source->entity->name, link->source->index, -+ link->sink->entity->name); -+ -+ s_pad = media_pad_remote_pad_first(&av->pad); -+ s_stream = ipu6_isys_get_src_stream_by_src_pad(s_sd, s_pad->index); -+ -+ v4l2_subdev_lock_state(s_state); -+ -+ s_fmt = v4l2_subdev_state_get_stream_format(s_state, s_pad->index, -+ s_stream); -+ if (!s_fmt) { -+ dev_err(dev, "failed to get source pad format\n"); -+ goto unlock; -+ } -+ -+ if (s_fmt->width != av->mpix.width || -+ s_fmt->height != av->mpix.height || s_fmt->code != av->pfmt->code) { -+ dev_err(dev, "format mismatch %dx%d,%x != %dx%d,%x\n", -+ s_fmt->width, s_fmt->height, s_fmt->code, -+ av->mpix.width, av->mpix.height, av->pfmt->code); -+ goto unlock; -+ } -+ -+ v4l2_subdev_unlock_state(s_state); -+ -+ return 0; -+unlock: -+ v4l2_subdev_unlock_state(s_state); -+ -+ return ret; -+} -+ -+static void get_stream_opened(struct ipu6_isys_video *av) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&av->isys->streams_lock, flags); -+ av->isys->stream_opened++; -+ spin_unlock_irqrestore(&av->isys->streams_lock, flags); -+} -+ -+static void put_stream_opened(struct ipu6_isys_video *av) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&av->isys->streams_lock, flags); -+ av->isys->stream_opened--; -+ spin_unlock_irqrestore(&av->isys->streams_lock, flags); -+} -+ -+static int ipu6_isys_fw_pin_cfg(struct ipu6_isys_video *av, -+ struct ipu6_fw_isys_stream_cfg_data_abi *cfg) -+{ -+ struct media_pad *src_pad = media_pad_remote_pad_first(&av->pad); -+ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(src_pad->entity); -+ struct ipu6_fw_isys_input_pin_info_abi *input_pin; -+ struct ipu6_fw_isys_output_pin_info_abi *output_pin; -+ struct ipu6_isys_stream *stream = av->stream; -+ struct ipu6_isys_queue *aq = &av->aq; -+ struct v4l2_mbus_framefmt fmt; -+ struct v4l2_rect v4l2_crop; -+ struct ipu6_isys *isys = av->isys; -+ struct device *dev = &isys->adev->auxdev.dev; -+ int input_pins = cfg->nof_input_pins++; -+ int output_pins; -+ u32 src_stream; -+ int ret; -+ -+ src_stream = ipu6_isys_get_src_stream_by_src_pad(sd, src_pad->index); -+ ret = ipu6_isys_get_stream_pad_fmt(sd, src_pad->index, src_stream, -+ &fmt); -+ if (ret < 0) { -+ dev_err(dev, "can't get stream format (%d)\n", ret); -+ return ret; -+ } -+ -+ ret = ipu6_isys_get_stream_pad_crop(sd, src_pad->index, src_stream, -+ &v4l2_crop); -+ if (ret < 0) { -+ dev_err(dev, "can't get stream crop (%d)\n", ret); -+ return ret; -+ } -+ -+ input_pin = &cfg->input_pins[input_pins]; -+ input_pin->input_res.width = fmt.width; -+ input_pin->input_res.height = fmt.height; -+ input_pin->dt = av->dt; -+ input_pin->bits_per_pix = av->pfmt->bpp_packed; -+ input_pin->mapped_dt = 0x40; /* invalid mipi data type */ -+ input_pin->mipi_decompression = 0; -+ input_pin->capture_mode = IPU6_FW_ISYS_CAPTURE_MODE_REGULAR; -+ input_pin->mipi_store_mode = av->pfmt->bpp == av->pfmt->bpp_packed ? -+ IPU6_FW_ISYS_MIPI_STORE_MODE_DISCARD_LONG_HEADER : -+ IPU6_FW_ISYS_MIPI_STORE_MODE_NORMAL; -+ input_pin->crop_first_and_last_lines = v4l2_crop.top & 1; -+ -+ output_pins = cfg->nof_output_pins++; -+ aq->fw_output = output_pins; -+ stream->output_pins[output_pins].pin_ready = ipu6_isys_queue_buf_ready; -+ stream->output_pins[output_pins].aq = aq; -+ -+ output_pin = &cfg->output_pins[output_pins]; -+ output_pin->input_pin_id = input_pins; -+ output_pin->output_res.width = av->mpix.width; -+ output_pin->output_res.height = av->mpix.height; -+ -+ output_pin->stride = av->mpix.plane_fmt[0].bytesperline; -+ if (av->pfmt->bpp != av->pfmt->bpp_packed) -+ output_pin->pt = IPU6_FW_ISYS_PIN_TYPE_RAW_SOC; -+ else -+ output_pin->pt = IPU6_FW_ISYS_PIN_TYPE_MIPI; -+ output_pin->ft = av->pfmt->css_pixelformat; -+ output_pin->send_irq = 1; -+ memset(output_pin->ts_offsets, 0, sizeof(output_pin->ts_offsets)); -+ output_pin->s2m_pixel_soc_pixel_remapping = -+ S2M_PIXEL_SOC_PIXEL_REMAPPING_FLAG_NO_REMAPPING; -+ output_pin->csi_be_soc_pixel_remapping = -+ CSI_BE_SOC_PIXEL_REMAPPING_FLAG_NO_REMAPPING; -+ -+ output_pin->snoopable = true; -+ output_pin->error_handling_enable = false; -+ output_pin->sensor_type = isys->sensor_type++; -+ if (isys->sensor_type > isys->pdata->ipdata->sensor_type_end) -+ isys->sensor_type = isys->pdata->ipdata->sensor_type_start; -+ -+ return 0; -+} -+ -+static int start_stream_firmware(struct ipu6_isys_video *av, -+ struct ipu6_isys_buffer_list *bl) -+{ -+ struct ipu6_fw_isys_stream_cfg_data_abi *stream_cfg; -+ struct ipu6_fw_isys_frame_buff_set_abi *buf = NULL; -+ struct ipu6_isys_stream *stream = av->stream; -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ struct isys_fw_msgs *msg = NULL; -+ struct ipu6_isys_queue *aq; -+ int ret, retout, tout; -+ u16 send_type; -+ -+ msg = ipu6_get_fw_msg_buf(stream); -+ if (!msg) -+ return -ENOMEM; -+ -+ stream_cfg = &msg->fw_msg.stream; -+ stream_cfg->src = stream->stream_source; -+ stream_cfg->vc = stream->vc; -+ stream_cfg->isl_use = 0; -+ stream_cfg->sensor_type = IPU6_FW_ISYS_SENSOR_MODE_NORMAL; -+ -+ list_for_each_entry(aq, &stream->queues, node) { -+ struct ipu6_isys_video *__av = ipu6_isys_queue_to_video(aq); -+ -+ ret = ipu6_isys_fw_pin_cfg(__av, stream_cfg); -+ if (ret < 0) { -+ ipu6_put_fw_msg_buf(av->isys, (u64)stream_cfg); -+ return ret; -+ } -+ } -+ -+ ipu6_fw_isys_dump_stream_cfg(dev, stream_cfg); -+ -+ stream->nr_output_pins = stream_cfg->nof_output_pins; -+ -+ reinit_completion(&stream->stream_open_completion); -+ -+ ret = ipu6_fw_isys_complex_cmd(av->isys, stream->stream_handle, -+ stream_cfg, msg->dma_addr, -+ sizeof(*stream_cfg), -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_OPEN); -+ if (ret < 0) { -+ dev_err(dev, "can't open stream (%d)\n", ret); -+ ipu6_put_fw_msg_buf(av->isys, (u64)stream_cfg); -+ return ret; -+ } -+ -+ get_stream_opened(av); -+ -+ tout = wait_for_completion_timeout(&stream->stream_open_completion, -+ IPU6_FW_CALL_TIMEOUT_JIFFIES); -+ -+ ipu6_put_fw_msg_buf(av->isys, (u64)stream_cfg); -+ -+ if (!tout) { -+ dev_err(dev, "stream open time out\n"); -+ ret = -ETIMEDOUT; -+ goto out_put_stream_opened; -+ } -+ if (stream->error) { -+ dev_err(dev, "stream open error: %d\n", stream->error); -+ ret = -EIO; -+ goto out_put_stream_opened; -+ } -+ dev_dbg(dev, "start stream: open complete\n"); -+ -+ if (bl) { -+ msg = ipu6_get_fw_msg_buf(stream); -+ if (!msg) { -+ ret = -ENOMEM; -+ goto out_put_stream_opened; -+ } -+ buf = &msg->fw_msg.frame; -+ ipu6_isys_buf_to_fw_frame_buf(buf, stream, bl); -+ ipu6_isys_buffer_list_queue(bl, -+ IPU6_ISYS_BUFFER_LIST_FL_ACTIVE, 0); -+ } -+ -+ reinit_completion(&stream->stream_start_completion); -+ -+ if (bl) { -+ send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_START_AND_CAPTURE; -+ ipu6_fw_isys_dump_frame_buff_set(dev, buf, -+ stream_cfg->nof_output_pins); -+ ret = ipu6_fw_isys_complex_cmd(av->isys, stream->stream_handle, -+ buf, msg->dma_addr, -+ sizeof(*buf), send_type); -+ } else { -+ send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_START; -+ ret = ipu6_fw_isys_simple_cmd(av->isys, stream->stream_handle, -+ send_type); -+ } -+ -+ if (ret < 0) { -+ dev_err(dev, "can't start streaming (%d)\n", ret); -+ goto out_stream_close; -+ } -+ -+ tout = wait_for_completion_timeout(&stream->stream_start_completion, -+ IPU6_FW_CALL_TIMEOUT_JIFFIES); -+ if (!tout) { -+ dev_err(dev, "stream start time out\n"); -+ ret = -ETIMEDOUT; -+ goto out_stream_close; -+ } -+ if (stream->error) { -+ dev_err(dev, "stream start error: %d\n", stream->error); -+ ret = -EIO; -+ goto out_stream_close; -+ } -+ dev_dbg(dev, "start stream: complete\n"); -+ -+ return 0; -+ -+out_stream_close: -+ reinit_completion(&stream->stream_close_completion); -+ -+ retout = ipu6_fw_isys_simple_cmd(av->isys, -+ stream->stream_handle, -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_CLOSE); -+ if (retout < 0) { -+ dev_dbg(dev, "can't close stream (%d)\n", retout); -+ goto out_put_stream_opened; -+ } -+ -+ tout = wait_for_completion_timeout(&stream->stream_close_completion, -+ IPU6_FW_CALL_TIMEOUT_JIFFIES); -+ if (!tout) -+ dev_err(dev, "stream close time out\n"); -+ else if (stream->error) -+ dev_err(dev, "stream close error: %d\n", stream->error); -+ else -+ dev_dbg(dev, "stream close complete\n"); -+ -+out_put_stream_opened: -+ put_stream_opened(av); -+ -+ return ret; -+} -+ -+static void stop_streaming_firmware(struct ipu6_isys_video *av) -+{ -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ struct ipu6_isys_stream *stream = av->stream; -+ int ret, tout; -+ -+ reinit_completion(&stream->stream_stop_completion); -+ -+ ret = ipu6_fw_isys_simple_cmd(av->isys, stream->stream_handle, -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_FLUSH); -+ -+ if (ret < 0) { -+ dev_err(dev, "can't stop stream (%d)\n", ret); -+ return; -+ } -+ -+ tout = wait_for_completion_timeout(&stream->stream_stop_completion, -+ IPU6_FW_CALL_TIMEOUT_JIFFIES); -+ if (!tout) -+ dev_warn(dev, "stream stop time out\n"); -+ else if (stream->error) -+ dev_warn(dev, "stream stop error: %d\n", stream->error); -+ else -+ dev_dbg(dev, "stop stream: complete\n"); -+} -+ -+static void close_streaming_firmware(struct ipu6_isys_video *av) -+{ -+ struct ipu6_isys_stream *stream = av->stream; -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ int ret, tout; -+ -+ reinit_completion(&stream->stream_close_completion); -+ -+ ret = ipu6_fw_isys_simple_cmd(av->isys, stream->stream_handle, -+ IPU6_FW_ISYS_SEND_TYPE_STREAM_CLOSE); -+ if (ret < 0) { -+ dev_err(dev, "can't close stream (%d)\n", ret); -+ return; -+ } -+ -+ tout = wait_for_completion_timeout(&stream->stream_close_completion, -+ IPU6_FW_CALL_TIMEOUT_JIFFIES); -+ if (!tout) -+ dev_warn(dev, "stream close time out\n"); -+ else if (stream->error) -+ dev_warn(dev, "stream close error: %d\n", stream->error); -+ else -+ dev_dbg(dev, "close stream: complete\n"); -+ -+ put_stream_opened(av); -+} -+ -+int ipu6_isys_video_prepare_stream(struct ipu6_isys_video *av, -+ struct media_entity *source_entity, -+ int nr_queues) -+{ -+ struct ipu6_isys_stream *stream = av->stream; -+ struct ipu6_isys_csi2 *csi2; -+ -+ if (WARN_ON(stream->nr_streaming)) -+ return -EINVAL; -+ -+ stream->nr_queues = nr_queues; -+ atomic_set(&stream->sequence, 0); -+ -+ stream->seq_index = 0; -+ memset(stream->seq, 0, sizeof(stream->seq)); -+ -+ if (WARN_ON(!list_empty(&stream->queues))) -+ return -EINVAL; -+ -+ stream->stream_source = stream->asd->source; -+ csi2 = ipu6_isys_subdev_to_csi2(stream->asd); -+ csi2->receiver_errors = 0; -+ stream->source_entity = source_entity; -+ -+ dev_dbg(&av->isys->adev->auxdev.dev, -+ "prepare stream: external entity %s\n", -+ stream->source_entity->name); -+ -+ return 0; -+} -+ -+void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video *av, -+ bool state) -+{ -+ struct ipu6_isys *isys = av->isys; -+ struct ipu6_isys_csi2 *csi2 = NULL; -+ struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark; -+ struct device *dev = &isys->adev->auxdev.dev; -+ struct v4l2_mbus_framefmt format; -+ struct v4l2_subdev *esd; -+ struct v4l2_control hb = { .id = V4L2_CID_HBLANK, .value = 0 }; -+ unsigned int bpp, lanes; -+ s64 link_freq = 0; -+ u64 pixel_rate = 0; -+ int ret; -+ -+ if (!state) -+ return; -+ -+ esd = media_entity_to_v4l2_subdev(av->stream->source_entity); -+ -+ av->watermark.width = av->mpix.width; -+ av->watermark.height = av->mpix.height; -+ av->watermark.sram_gran_shift = isys->pdata->ipdata->sram_gran_shift; -+ av->watermark.sram_gran_size = isys->pdata->ipdata->sram_gran_size; -+ -+ ret = v4l2_g_ctrl(esd->ctrl_handler, &hb); -+ if (!ret && hb.value >= 0) -+ av->watermark.hblank = hb.value; -+ else -+ av->watermark.hblank = 0; -+ -+ csi2 = ipu6_isys_subdev_to_csi2(av->stream->asd); -+ link_freq = ipu6_isys_csi2_get_link_freq(csi2); -+ if (link_freq > 0) { -+ lanes = csi2->nlanes; -+ ret = ipu6_isys_get_stream_pad_fmt(&csi2->asd.sd, 0, -+ av->source_stream, &format); -+ if (!ret) { -+ bpp = ipu6_isys_mbus_code_to_bpp(format.code); -+ pixel_rate = mul_u64_u32_div(link_freq, lanes * 2, bpp); -+ } -+ } -+ -+ av->watermark.pixel_rate = pixel_rate; -+ -+ if (!pixel_rate) { -+ mutex_lock(&iwake_watermark->mutex); -+ iwake_watermark->force_iwake_disable = true; -+ mutex_unlock(&iwake_watermark->mutex); -+ dev_warn(dev, "unexpected pixel_rate from %s, disable iwake.\n", -+ av->stream->source_entity->name); -+ } -+} -+ -+static void calculate_stream_datarate(struct ipu6_isys_video *av) -+{ -+ struct video_stream_watermark *watermark = &av->watermark; -+ u32 bpp = av->pfmt->bpp; -+ u32 pages_per_line, pb_bytes_per_line, pixels_per_line, bytes_per_line; -+ u64 line_time_ns, stream_data_rate; -+ u16 shift, size; -+ -+ shift = watermark->sram_gran_shift; -+ size = watermark->sram_gran_size; -+ -+ pixels_per_line = watermark->width + watermark->hblank; -+ line_time_ns = div_u64(pixels_per_line * NSEC_PER_SEC, -+ watermark->pixel_rate); -+ bytes_per_line = watermark->width * bpp / 8; -+ pages_per_line = DIV_ROUND_UP(bytes_per_line, size); -+ pb_bytes_per_line = pages_per_line << shift; -+ stream_data_rate = div64_u64(pb_bytes_per_line * 1000, line_time_ns); -+ -+ watermark->stream_data_rate = stream_data_rate; -+} -+ -+void ipu6_isys_update_stream_watermark(struct ipu6_isys_video *av, bool state) -+{ -+ struct isys_iwake_watermark *iwake_watermark = -+ &av->isys->iwake_watermark; -+ -+ if (!av->watermark.pixel_rate) -+ return; -+ -+ if (state) { -+ calculate_stream_datarate(av); -+ mutex_lock(&iwake_watermark->mutex); -+ list_add(&av->watermark.stream_node, -+ &iwake_watermark->video_list); -+ mutex_unlock(&iwake_watermark->mutex); -+ } else { -+ av->watermark.stream_data_rate = 0; -+ mutex_lock(&iwake_watermark->mutex); -+ list_del(&av->watermark.stream_node); -+ mutex_unlock(&iwake_watermark->mutex); -+ } -+ -+ update_watermark_setting(av->isys); -+} -+ -+void ipu6_isys_put_stream(struct ipu6_isys_stream *stream) -+{ -+ struct device *dev = &stream->isys->adev->auxdev.dev; -+ unsigned int i; -+ unsigned long flags; -+ -+ if (!stream) { -+ dev_err(dev, "no available stream\n"); -+ return; -+ } -+ -+ spin_lock_irqsave(&stream->isys->streams_lock, flags); -+ for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) { -+ if (&stream->isys->streams[i] == stream) { -+ if (stream->isys->streams_ref_count[i] > 0) -+ stream->isys->streams_ref_count[i]--; -+ else -+ dev_warn(dev, "invalid stream %d\n", i); -+ -+ break; -+ } -+ } -+ spin_unlock_irqrestore(&stream->isys->streams_lock, flags); -+} -+ -+static struct ipu6_isys_stream * -+ipu6_isys_get_stream(struct ipu6_isys_video *av, struct ipu6_isys_subdev *asd) -+{ -+ struct ipu6_isys_stream *stream = NULL; -+ struct ipu6_isys *isys = av->isys; -+ unsigned long flags; -+ unsigned int i; -+ u8 vc = av->vc; -+ -+ if (!isys) -+ return NULL; -+ -+ spin_lock_irqsave(&isys->streams_lock, flags); -+ for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) { -+ if (isys->streams_ref_count[i] && isys->streams[i].vc == vc && -+ isys->streams[i].asd == asd) { -+ isys->streams_ref_count[i]++; -+ stream = &isys->streams[i]; -+ break; -+ } -+ } -+ -+ if (!stream) { -+ for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) { -+ if (!isys->streams_ref_count[i]) { -+ isys->streams_ref_count[i]++; -+ stream = &isys->streams[i]; -+ stream->vc = vc; -+ stream->asd = asd; -+ break; -+ } -+ } -+ } -+ spin_unlock_irqrestore(&isys->streams_lock, flags); -+ -+ return stream; -+} -+ -+struct ipu6_isys_stream * -+ipu6_isys_query_stream_by_handle(struct ipu6_isys *isys, u8 stream_handle) -+{ -+ unsigned long flags; -+ struct ipu6_isys_stream *stream = NULL; -+ -+ if (!isys) -+ return NULL; -+ -+ if (stream_handle >= IPU6_ISYS_MAX_STREAMS) { -+ dev_err(&isys->adev->auxdev.dev, -+ "stream_handle %d is invalid\n", stream_handle); -+ return NULL; -+ } -+ -+ spin_lock_irqsave(&isys->streams_lock, flags); -+ if (isys->streams_ref_count[stream_handle] > 0) { -+ isys->streams_ref_count[stream_handle]++; -+ stream = &isys->streams[stream_handle]; -+ } -+ spin_unlock_irqrestore(&isys->streams_lock, flags); -+ -+ return stream; -+} -+ -+struct ipu6_isys_stream * -+ipu6_isys_query_stream_by_source(struct ipu6_isys *isys, int source, u8 vc) -+{ -+ struct ipu6_isys_stream *stream = NULL; -+ unsigned long flags; -+ unsigned int i; -+ -+ if (!isys) -+ return NULL; -+ -+ if (source < 0) { -+ dev_err(&stream->isys->adev->auxdev.dev, -+ "query stream with invalid port number\n"); -+ return NULL; -+ } -+ -+ spin_lock_irqsave(&isys->streams_lock, flags); -+ for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) { -+ if (!isys->streams_ref_count[i]) -+ continue; -+ -+ if (isys->streams[i].stream_source == source && -+ isys->streams[i].vc == vc) { -+ stream = &isys->streams[i]; -+ isys->streams_ref_count[i]++; -+ break; -+ } -+ } -+ spin_unlock_irqrestore(&isys->streams_lock, flags); -+ -+ return stream; -+} -+ -+static u64 get_stream_mask_by_pipeline(struct ipu6_isys_video *av) -+{ -+ struct media_pipeline *pipeline = -+ media_entity_pipeline(&av->vdev.entity); -+ struct media_entity *entity; -+ unsigned int i; -+ u64 stream_mask = 0; -+ -+ for (i = 0; i < NR_OF_VIDEO_DEVICE; i++) { -+ entity = &av->isys->av[i].vdev.entity; -+ if (pipeline == media_entity_pipeline(entity)) -+ stream_mask |= BIT_ULL(av->isys->av[i].source_stream); -+ } -+ -+ return stream_mask; -+} -+ -+int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, -+ struct ipu6_isys_buffer_list *bl) -+{ -+ struct v4l2_subdev_krouting *routing; -+ struct ipu6_isys_stream *stream = av->stream; -+ struct v4l2_subdev_state *subdev_state; -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ struct v4l2_subdev *sd = NULL; -+ struct v4l2_subdev *ssd = NULL; -+ struct media_pad *r_pad; -+ struct media_pad *s_pad = NULL; -+ u32 sink_pad, sink_stream; -+ u64 r_stream; -+ u64 stream_mask = 0; -+ int ret = 0; -+ -+ dev_dbg(dev, "set stream: %d\n", state); -+ -+ if (WARN(!stream->source_entity, "No source entity for stream\n")) -+ return -ENODEV; -+ -+ ssd = media_entity_to_v4l2_subdev(stream->source_entity); -+ sd = &stream->asd->sd; -+ r_pad = media_pad_remote_pad_first(&av->pad); -+ r_stream = ipu6_isys_get_src_stream_by_src_pad(sd, r_pad->index); -+ -+ subdev_state = v4l2_subdev_lock_and_get_active_state(sd); -+ routing = &subdev_state->routing; -+ ret = v4l2_subdev_routing_find_opposite_end(routing, r_pad->index, -+ r_stream, &sink_pad, -+ &sink_stream); -+ v4l2_subdev_unlock_state(subdev_state); -+ if (ret) -+ return ret; -+ -+ s_pad = media_pad_remote_pad_first(&stream->asd->pad[sink_pad]); -+ -+ stream_mask = get_stream_mask_by_pipeline(av); -+ if (!state) { -+ stop_streaming_firmware(av); -+ -+ /* stop external sub-device now. */ -+ dev_dbg(dev, "disable streams 0x%llx of %s\n", stream_mask, -+ ssd->name); -+ ret = v4l2_subdev_disable_streams(ssd, s_pad->index, -+ stream_mask); -+ if (ret) { -+ dev_err(dev, "disable streams of %s failed with %d\n", -+ ssd->name, ret); -+ return ret; -+ } -+ -+ /* stop sub-device which connects with video */ -+ dev_dbg(dev, "stream off entity %s pad:%d\n", sd->name, -+ r_pad->index); -+ ret = v4l2_subdev_call(sd, video, s_stream, state); -+ if (ret) { -+ dev_err(dev, "stream off %s failed with %d\n", sd->name, -+ ret); -+ return ret; -+ } -+ close_streaming_firmware(av); -+ } else { -+ ret = start_stream_firmware(av, bl); -+ if (ret) { -+ dev_err(dev, "start stream of firmware failed\n"); -+ goto out_clear_stream_watermark; -+ } -+ -+ /* start sub-device which connects with video */ -+ dev_dbg(dev, "stream on %s pad %d\n", sd->name, r_pad->index); -+ ret = v4l2_subdev_call(sd, video, s_stream, state); -+ if (ret) { -+ dev_err(dev, "stream on %s failed with %d\n", sd->name, -+ ret); -+ goto out_media_entity_stop_streaming_firmware; -+ } -+ -+ /* start external sub-device now. */ -+ dev_dbg(dev, "enable streams 0x%llx of %s\n", stream_mask, -+ ssd->name); -+ ret = v4l2_subdev_enable_streams(ssd, s_pad->index, -+ stream_mask); -+ if (ret) { -+ dev_err(dev, -+ "enable streams 0x%llx of %s failed with %d\n", -+ stream_mask, stream->source_entity->name, ret); -+ goto out_media_entity_stop_streaming; -+ } -+ } -+ -+ av->streaming = state; -+ -+ return 0; -+ -+out_media_entity_stop_streaming: -+ v4l2_subdev_disable_streams(sd, r_pad->index, BIT(r_stream)); -+ -+out_media_entity_stop_streaming_firmware: -+ stop_streaming_firmware(av); -+ -+out_clear_stream_watermark: -+ ipu6_isys_update_stream_watermark(av, 0); -+ -+ return ret; -+} -+ -+static const struct v4l2_ioctl_ops ioctl_ops_mplane = { -+ .vidioc_querycap = ipu6_isys_vidioc_querycap, -+ .vidioc_enum_fmt_vid_cap = ipu6_isys_vidioc_enum_fmt, -+ .vidioc_enum_framesizes = ipu6_isys_vidioc_enum_framesizes, -+ .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap_mplane, -+ .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap_mplane, -+ .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap_mplane, -+ .vidioc_reqbufs = vb2_ioctl_reqbufs, -+ .vidioc_create_bufs = vb2_ioctl_create_bufs, -+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, -+ .vidioc_querybuf = vb2_ioctl_querybuf, -+ .vidioc_qbuf = vb2_ioctl_qbuf, -+ .vidioc_dqbuf = vb2_ioctl_dqbuf, -+ .vidioc_streamon = vb2_ioctl_streamon, -+ .vidioc_streamoff = vb2_ioctl_streamoff, -+ .vidioc_expbuf = vb2_ioctl_expbuf, -+}; -+ -+static const struct media_entity_operations entity_ops = { -+ .link_validate = link_validate, -+}; -+ -+static const struct v4l2_file_operations isys_fops = { -+ .owner = THIS_MODULE, -+ .poll = vb2_fop_poll, -+ .unlocked_ioctl = video_ioctl2, -+ .mmap = vb2_fop_mmap, -+ .open = video_open, -+ .release = video_release, -+}; -+ -+int ipu6_isys_fw_open(struct ipu6_isys *isys) -+{ -+ struct ipu6_bus_device *adev = isys->adev; -+ const struct ipu6_isys_internal_pdata *ipdata = isys->pdata->ipdata; -+ int ret; -+ -+ ret = pm_runtime_resume_and_get(&adev->auxdev.dev); -+ if (ret < 0) -+ return ret; -+ -+ mutex_lock(&isys->mutex); -+ -+ if (isys->ref_count++) -+ goto unlock; -+ -+ ipu6_configure_spc(adev->isp, &ipdata->hw_variant, -+ IPU6_CPD_PKG_DIR_ISYS_SERVER_IDX, isys->pdata->base, -+ adev->pkg_dir, adev->pkg_dir_dma_addr); -+ -+ /* -+ * Buffers could have been left to wrong queue at last closure. -+ * Move them now back to empty buffer queue. -+ */ -+ ipu6_cleanup_fw_msg_bufs(isys); -+ -+ if (isys->fwcom) { -+ /* -+ * Something went wrong in previous shutdown. As we are now -+ * restarting isys we can safely delete old context. -+ */ -+ dev_warn(&adev->auxdev.dev, "clearing old context\n"); -+ ipu6_fw_isys_cleanup(isys); -+ } -+ -+ ret = ipu6_fw_isys_init(isys, ipdata->num_parallel_streams); -+ if (ret < 0) -+ goto out; -+ -+unlock: -+ mutex_unlock(&isys->mutex); -+ -+ return 0; -+ -+out: -+ isys->ref_count--; -+ mutex_unlock(&isys->mutex); -+ pm_runtime_put(&adev->auxdev.dev); -+ -+ return ret; -+} -+ -+void ipu6_isys_fw_close(struct ipu6_isys *isys) -+{ -+ mutex_lock(&isys->mutex); -+ -+ isys->ref_count--; -+ if (!isys->ref_count) { -+ ipu6_fw_isys_close(isys); -+ if (isys->fwcom) { -+ isys->need_reset = true; -+ dev_warn(&isys->adev->auxdev.dev, -+ "failed to close fw isys\n"); -+ } -+ } -+ -+ mutex_unlock(&isys->mutex); -+ -+ if (isys->need_reset) -+ pm_runtime_put_sync(&isys->adev->auxdev.dev); -+ else -+ pm_runtime_put(&isys->adev->auxdev.dev); -+} -+ -+int ipu6_isys_setup_video(struct ipu6_isys_video *av, -+ struct media_entity **source_entity, int *nr_queues) -+{ -+ struct device *dev = &av->isys->adev->auxdev.dev; -+ struct v4l2_mbus_frame_desc_entry entry; -+ struct v4l2_subdev_route *route = NULL; -+ struct v4l2_subdev_route *r; -+ struct v4l2_subdev_state *state; -+ struct ipu6_isys_subdev *asd; -+ struct v4l2_subdev *remote_sd; -+ struct media_pipeline *pipeline; -+ struct media_pad *source_pad, *remote_pad; -+ int ret = -EINVAL; -+ -+ remote_pad = media_pad_remote_pad_first(&av->pad); -+ if (!remote_pad) { -+ dev_dbg(dev, "failed to get remote pad\n"); -+ return -ENODEV; -+ } -+ -+ remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity); -+ asd = to_ipu6_isys_subdev(remote_sd); -+ source_pad = media_pad_remote_pad_first(&remote_pad->entity->pads[0]); -+ if (!source_pad) { -+ dev_dbg(dev, "No external source entity\n"); -+ return -ENODEV; -+ } -+ -+ *source_entity = source_pad->entity; -+ -+ /* Find the root */ -+ state = v4l2_subdev_lock_and_get_active_state(remote_sd); -+ for_each_active_route(&state->routing, r) { -+ if (r->source_pad != remote_pad->index) -+ continue; -+ -+ route = r; -+ break; -+ } -+ -+ if (!route) { -+ v4l2_subdev_unlock_state(state); -+ dev_dbg(dev, "Failed to find route\n"); -+ return -ENODEV; -+ } -+ v4l2_subdev_unlock_state(state); -+ av->source_stream = route->sink_stream; -+ -+ ret = ipu6_isys_csi2_get_remote_desc(av->source_stream, -+ to_ipu6_isys_csi2(asd), -+ *source_entity, &entry, -+ nr_queues); -+ if (ret == -ENOIOCTLCMD) { -+ av->vc = 0; -+ av->dt = ipu6_isys_mbus_code_to_mipi(av->pfmt->code); -+ *nr_queues = 1; -+ } else if (!ret) { -+ dev_dbg(dev, "Framedesc: stream %u, len %u, vc %u, dt %#x\n", -+ entry.stream, entry.length, entry.bus.csi2.vc, -+ entry.bus.csi2.dt); -+ -+ av->vc = entry.bus.csi2.vc; -+ av->dt = entry.bus.csi2.dt; -+ } else { -+ dev_err(dev, "failed to get remote frame desc\n"); -+ return ret; -+ } -+ -+ pipeline = media_entity_pipeline(&av->vdev.entity); -+ if (!pipeline) -+ ret = video_device_pipeline_alloc_start(&av->vdev); -+ else -+ ret = video_device_pipeline_start(&av->vdev, pipeline); -+ if (ret < 0) { -+ dev_dbg(dev, "media pipeline start failed\n"); -+ return ret; -+ } -+ -+ av->stream = ipu6_isys_get_stream(av, asd); -+ if (!av->stream) { -+ video_device_pipeline_stop(&av->vdev); -+ dev_err(dev, "no available stream for firmware\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Do everything that's needed to initialise things related to video -+ * buffer queue, video node, and the related media entity. The caller -+ * is expected to assign isys field and set the name of the video -+ * device. -+ */ -+int ipu6_isys_video_init(struct ipu6_isys_video *av) -+{ -+ struct v4l2_format format = { -+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, -+ .fmt.pix_mp = { -+ .width = 1920, -+ .height = 1080, -+ }, -+ }; -+ int ret; -+ -+ mutex_init(&av->mutex); -+ av->vdev.device_caps = V4L2_CAP_STREAMING | V4L2_CAP_IO_MC | -+ V4L2_CAP_VIDEO_CAPTURE_MPLANE; -+ av->vdev.vfl_dir = VFL_DIR_RX; -+ -+ ret = ipu6_isys_queue_init(&av->aq); -+ if (ret) -+ goto out_free_watermark; -+ -+ av->pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; -+ ret = media_entity_pads_init(&av->vdev.entity, 1, &av->pad); -+ if (ret) -+ goto out_vb2_queue_release; -+ -+ av->vdev.entity.ops = &entity_ops; -+ av->vdev.release = video_device_release_empty; -+ av->vdev.fops = &isys_fops; -+ av->vdev.v4l2_dev = &av->isys->v4l2_dev; -+ if (!av->vdev.ioctl_ops) -+ av->vdev.ioctl_ops = &ioctl_ops_mplane; -+ av->vdev.queue = &av->aq.vbq; -+ av->vdev.lock = &av->mutex; -+ -+ ipu6_isys_video_try_fmt_vid_mplane(av, &format.fmt.pix_mp); -+ av->mpix = format.fmt.pix_mp; -+ -+ set_bit(V4L2_FL_USES_V4L2_FH, &av->vdev.flags); -+ video_set_drvdata(&av->vdev, av); -+ -+ ret = video_register_device(&av->vdev, VFL_TYPE_VIDEO, -1); -+ if (ret) -+ goto out_media_entity_cleanup; -+ -+ return ret; -+ -+out_media_entity_cleanup: -+ vb2_video_unregister_device(&av->vdev); -+ media_entity_cleanup(&av->vdev.entity); -+ -+out_vb2_queue_release: -+ vb2_queue_release(&av->aq.vbq); -+ -+out_free_watermark: -+ mutex_destroy(&av->mutex); -+ -+ return ret; -+} -+ -+void ipu6_isys_video_cleanup(struct ipu6_isys_video *av) -+{ -+ vb2_video_unregister_device(&av->vdev); -+ media_entity_cleanup(&av->vdev.entity); -+ mutex_destroy(&av->mutex); -+} -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h -new file mode 100644 -index 000000000000..21cd33c7e277 ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h -@@ -0,0 +1,136 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* Copyright (C) 2013 - 2023 Intel Corporation */ -+ -+#ifndef IPU6_ISYS_VIDEO_H -+#define IPU6_ISYS_VIDEO_H -+ -+#include <linux/atomic.h> -+#include <linux/completion.h> -+#include <linux/container_of.h> -+#include <linux/list.h> -+#include <linux/mutex.h> -+ -+#include <media/media-entity.h> -+#include <media/v4l2-dev.h> -+ -+#include "ipu6-isys-queue.h" -+ -+#define IPU6_ISYS_OUTPUT_PINS 11 -+#define IPU6_ISYS_MAX_PARALLEL_SOF 2 -+#define NR_OF_VIDEO_DEVICE 31 -+ -+struct file; -+struct ipu6_isys; -+struct ipu6_isys_subdev; -+ -+struct ipu6_isys_pixelformat { -+ u32 pixelformat; -+ u32 bpp; -+ u32 bpp_packed; -+ u32 code; -+ u32 css_pixelformat; -+}; -+ -+struct sequence_info { -+ unsigned int sequence; -+ u64 timestamp; -+}; -+ -+struct output_pin_data { -+ void (*pin_ready)(struct ipu6_isys_stream *stream, -+ struct ipu6_fw_isys_resp_info_abi *info); -+ struct ipu6_isys_queue *aq; -+}; -+ -+/* -+ * Align with firmware stream. Each stream represents a CSI virtual channel. -+ * May map to multiple video devices -+ */ -+struct ipu6_isys_stream { -+ struct mutex mutex; -+ struct media_entity *source_entity; -+ atomic_t sequence; -+ unsigned int seq_index; -+ struct sequence_info seq[IPU6_ISYS_MAX_PARALLEL_SOF]; -+ int stream_source; -+ int stream_handle; -+ unsigned int nr_output_pins; -+ struct ipu6_isys_subdev *asd; -+ -+ int nr_queues; /* Number of capture queues */ -+ int nr_streaming; -+ int streaming; /* Has streaming been really started? */ -+ struct list_head queues; -+ struct completion stream_open_completion; -+ struct completion stream_close_completion; -+ struct completion stream_start_completion; -+ struct completion stream_stop_completion; -+ struct ipu6_isys *isys; -+ -+ struct output_pin_data output_pins[IPU6_ISYS_OUTPUT_PINS]; -+ int error; -+ u8 vc; -+}; -+ -+struct video_stream_watermark { -+ u32 width; -+ u32 height; -+ u32 hblank; -+ u32 frame_rate; -+ u64 pixel_rate; -+ u64 stream_data_rate; -+ u16 sram_gran_shift; -+ u16 sram_gran_size; -+ struct list_head stream_node; -+}; -+ -+struct ipu6_isys_video { -+ struct ipu6_isys_queue aq; -+ /* Serialise access to other fields in the struct. */ -+ struct mutex mutex; -+ struct media_pad pad; -+ struct video_device vdev; -+ struct v4l2_pix_format_mplane mpix; -+ const struct ipu6_isys_pixelformat *pfmt; -+ struct ipu6_isys *isys; -+ struct ipu6_isys_stream *stream; -+ unsigned int streaming; -+ struct video_stream_watermark watermark; -+ u32 source_stream; -+ u8 vc; -+ u8 dt; -+}; -+ -+#define ipu6_isys_queue_to_video(__aq) \ -+ container_of(__aq, struct ipu6_isys_video, aq) -+ -+extern const struct ipu6_isys_pixelformat ipu6_isys_pfmts[]; -+extern const struct ipu6_isys_pixelformat ipu6_isys_pfmts_packed[]; -+ -+int ipu6_isys_vidioc_querycap(struct file *file, void *fh, -+ struct v4l2_capability *cap); -+ -+int ipu6_isys_vidioc_enum_fmt(struct file *file, void *fh, -+ struct v4l2_fmtdesc *f); -+int ipu6_isys_video_prepare_stream(struct ipu6_isys_video *av, -+ struct media_entity *source_entity, -+ int nr_queues); -+int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, -+ struct ipu6_isys_buffer_list *bl); -+int ipu6_isys_fw_open(struct ipu6_isys *isys); -+void ipu6_isys_fw_close(struct ipu6_isys *isys); -+int ipu6_isys_setup_video(struct ipu6_isys_video *av, -+ struct media_entity **source_entity, int *nr_queues); -+int ipu6_isys_video_init(struct ipu6_isys_video *av); -+void ipu6_isys_video_cleanup(struct ipu6_isys_video *av); -+void ipu6_isys_put_stream(struct ipu6_isys_stream *stream); -+struct ipu6_isys_stream * -+ipu6_isys_query_stream_by_handle(struct ipu6_isys *isys, u8 stream_handle); -+struct ipu6_isys_stream * -+ipu6_isys_query_stream_by_source(struct ipu6_isys *isys, int source, u8 vc); -+ -+void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video *av, -+ bool state); -+void ipu6_isys_update_stream_watermark(struct ipu6_isys_video *av, bool state); -+ -+#endif /* IPU6_ISYS_VIDEO_H */ --- -2.43.2 - - -From cc79447bab87ce8c498b0e7a5f849c7d4f6262c0 Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:26 +0800 -Subject: [PATCH 19/33] media: add Kconfig and Makefile for IPU6 - -Add IPU6 support in Kconfig and Makefile, with this patch you can -build the Intel IPU6 and input system modules by select the -CONFIG_VIDEO_INTEL_IPU6 in config. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> -Signed-off-by: Andreas Helbech Kleist <andreaskleist@gmail.com> ---- - drivers/media/pci/intel/Kconfig | 1 + - drivers/media/pci/intel/Makefile | 1 + - drivers/media/pci/intel/ipu6/Kconfig | 17 +++++++++++++++++ - drivers/media/pci/intel/ipu6/Makefile | 23 +++++++++++++++++++++++ - 4 files changed, 42 insertions(+) - create mode 100644 drivers/media/pci/intel/ipu6/Kconfig - create mode 100644 drivers/media/pci/intel/ipu6/Makefile - -diff --git a/drivers/media/pci/intel/Kconfig b/drivers/media/pci/intel/Kconfig -index ee4684159d3d..04cb3d253486 100644 ---- a/drivers/media/pci/intel/Kconfig -+++ b/drivers/media/pci/intel/Kconfig -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0-only - - source "drivers/media/pci/intel/ipu3/Kconfig" -+source "drivers/media/pci/intel/ipu6/Kconfig" - source "drivers/media/pci/intel/ivsc/Kconfig" - - config IPU_BRIDGE -diff --git a/drivers/media/pci/intel/Makefile b/drivers/media/pci/intel/Makefile -index f199a97e1d78..3a2cc6567159 100644 ---- a/drivers/media/pci/intel/Makefile -+++ b/drivers/media/pci/intel/Makefile -@@ -5,3 +5,4 @@ - obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o - obj-y += ipu3/ - obj-y += ivsc/ -+obj-$(CONFIG_VIDEO_INTEL_IPU6) += ipu6/ -diff --git a/drivers/media/pci/intel/ipu6/Kconfig b/drivers/media/pci/intel/ipu6/Kconfig -new file mode 100644 -index 000000000000..5cb4f3c2d59f ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/Kconfig -@@ -0,0 +1,17 @@ -+config VIDEO_INTEL_IPU6 -+ tristate "Intel IPU6 driver" -+ depends on ACPI || COMPILE_TEST -+ depends on MEDIA_SUPPORT -+ depends on MEDIA_PCI_SUPPORT -+ depends on X86 && X86_64 -+ select IOMMU_IOVA -+ select VIDEO_V4L2_SUBDEV_API -+ select VIDEOBUF2_DMA_CONTIG -+ select V4L2_FWNODE -+ select IPU_BRIDGE -+ help -+ This is the 6th Gen Intel Image Processing Unit, found in Intel SoCs -+ and used for capturing images and video from camera sensors. -+ -+ To compile this driver, say Y here! It contains 2 modules - -+ intel_ipu6 and intel_ipu6_isys. -diff --git a/drivers/media/pci/intel/ipu6/Makefile b/drivers/media/pci/intel/ipu6/Makefile -new file mode 100644 -index 000000000000..a821b0a1567f ---- /dev/null -+++ b/drivers/media/pci/intel/ipu6/Makefile -@@ -0,0 +1,23 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+ -+intel-ipu6-y := ipu6.o \ -+ ipu6-bus.o \ -+ ipu6-dma.o \ -+ ipu6-mmu.o \ -+ ipu6-buttress.o \ -+ ipu6-cpd.o \ -+ ipu6-fw-com.o -+ -+obj-$(CONFIG_VIDEO_INTEL_IPU6) += intel-ipu6.o -+ -+intel-ipu6-isys-y := ipu6-isys.o \ -+ ipu6-isys-csi2.o \ -+ ipu6-fw-isys.o \ -+ ipu6-isys-video.o \ -+ ipu6-isys-queue.o \ -+ ipu6-isys-subdev.o \ -+ ipu6-isys-mcd-phy.o \ -+ ipu6-isys-jsl-phy.o \ -+ ipu6-isys-dwc-phy.o -+ -+obj-$(CONFIG_VIDEO_INTEL_IPU6) += intel-ipu6-isys.o --- -2.43.2 - - -From edc6bed6991727e64f1eb60c0392403c39b96ba4 Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:27 +0800 -Subject: [PATCH 20/33] MAINTAINERS: add maintainers for Intel IPU6 input - system driver - -Update MAINTAINERS file for Intel IPU6 input system driver. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - MAINTAINERS | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/MAINTAINERS b/MAINTAINERS -index 1aabf1c15bb3..5346d472cb0f 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -10899,6 +10899,16 @@ F: Documentation/admin-guide/media/ipu3_rcb.svg - F: Documentation/userspace-api/media/v4l/metafmt-intel-ipu3.rst - F: drivers/staging/media/ipu3/ - -+INTEL IPU6 INPUT SYSTEM DRIVER -+M: Sakari Ailus <sakari.ailus@linux.intel.com> -+M: Bingbu Cao <bingbu.cao@intel.com> -+R: Tianshu Qiu <tian.shu.qiu@intel.com> -+L: linux-media@vger.kernel.org -+S: Maintained -+T: git git://linuxtv.org/media_tree.git -+F: Documentation/admin-guide/media/ipu6-isys.rst -+F: drivers/media/pci/intel/ipu6/ -+ - INTEL ISHTP ECLITE DRIVER - M: Sumesh K Naduvalath <sumesh.k.naduvalath@intel.com> - L: platform-driver-x86@vger.kernel.org --- -2.43.2 - - -From a12041e5f7fb32b93669f19b579bc1940a026bbe Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:28 +0800 -Subject: [PATCH 21/33] Documentation: add Intel IPU6 ISYS driver admin-guide - doc - -This document mainly describe the functionality of IPU6 and -IPU6 isys driver, and gives an example that how user can do -imaging capture with tools. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - Documentation/admin-guide/media/ipu6-isys.rst | 158 ++++++++++++++++ - .../admin-guide/media/ipu6_isys_graph.svg | 174 ++++++++++++++++++ - .../admin-guide/media/v4l-drivers.rst | 1 + - 3 files changed, 333 insertions(+) - create mode 100644 Documentation/admin-guide/media/ipu6-isys.rst - create mode 100644 Documentation/admin-guide/media/ipu6_isys_graph.svg - -diff --git a/Documentation/admin-guide/media/ipu6-isys.rst b/Documentation/admin-guide/media/ipu6-isys.rst -new file mode 100644 -index 000000000000..5e78ab88c649 ---- /dev/null -+++ b/Documentation/admin-guide/media/ipu6-isys.rst -@@ -0,0 +1,158 @@ -+.. SPDX-License-Identifier: GPL-2.0 -+ -+.. include:: <isonum.txt> -+ -+======================================================== -+Intel Image Processing Unit 6 (IPU6) Input System driver -+======================================================== -+ -+Copyright |copy| 2023 Intel Corporation -+ -+Introduction -+============ -+ -+This file documents the Intel IPU6 (6th generation Image Processing Unit) -+Input System (MIPI CSI2 receiver) drivers located under -+drivers/media/pci/intel/ipu6. -+ -+The Intel IPU6 can be found in certain Intel Chipsets but not in all SKUs: -+ -+* TigerLake -+* JasperLake -+* AlderLake -+* RaptorLake -+* MeteorLake -+ -+Intel IPU6 is made up of two components - Input System (ISYS) and Processing -+System (PSYS). -+ -+The Input System mainly works as MIPI CSI2 receiver which receives and -+processes the imaging data from the sensors and outputs the frames to memory. -+ -+There are 2 driver modules - intel_ipu6 and intel_ipu6_isys. intel_ipu6 is an -+IPU6 common driver which does PCI configuration, firmware loading and parsing, -+firmware authentication, DMA mapping and IPU-MMU (internal Memory mapping Unit) -+configuration. intel_ipu6_isys implements V4L2, Media Controller and V4L2 -+sub-device interfaces. The IPU6 ISYS driver supports camera sensors connected -+to the IPU6 ISYS through V4L2 sub-device sensor drivers. -+ -+.. Note:: See Documentation/driver-api/media/drivers/ipu6.rst for more -+ information about the IPU6 hardware. -+ -+ -+Input system driver -+=================== -+ -+The input System driver mainly configures CSI2 DPHY, constructs the firmware -+stream configuration, sends commands to firmware, gets response from hardware -+and firmware and then returns buffers to user. -+The ISYS is represented as several V4L2 sub-devices - 'Intel IPU6 CSI2 $port', -+which provide V4L2 subdev interfaces to the user space, there are also several -+video nodes for each CSI-2 stream capture - 'Intel IPU6 ISYS capture $num' which -+provide interface to user to set formats, queue buffers and streaming. -+ -+.. kernel-figure:: ipu6_isys_graph.svg -+ :alt: ipu6 isys media graph with multiple streams support -+ -+ ipu6 isys media graph with multiple streams support -+ -+Capturing frames by IPU6 ISYS -+----------------------------- -+ -+IPU6 ISYS is used to capture frames from the camera sensors connected to the -+CSI2 ports. The supported input formats of ISYS are listed in table below: -+ -+.. tabularcolumns:: |p{0.8cm}|p{4.0cm}|p{4.0cm}| -+ -+.. flat-table:: -+ :header-rows: 1 -+ -+ * - IPU6 ISYS supported input formats -+ -+ * - RGB565, RGB888 -+ -+ * - UYVY8, YUYV8 -+ -+ * - RAW8, RAW10, RAW12 -+ -+.. _ipu6_isys_capture_examples: -+ -+Examples -+~~~~~~~~ -+Here is an example of IPU6 ISYS raw capture on Dell XPS 9315 laptop. On this -+machine, ov01a10 sensor is connected to IPU ISYS CSI2 port 2, which can -+generate images at sBGGR10 with resolution 1280x800. -+ -+Using the media controller APIs, we can configure ov01a10 sensor by -+media-ctl [#f1]_ and yavta [#f2]_ to transmit frames to IPU6 ISYS. -+ -+.. code-block:: none -+ -+ # Example 1 capture frame from ov01a10 camera sensor -+ # This example assumes /dev/media0 as the IPU ISYS media device -+ export MDEV=/dev/media0 -+ -+ # Establish the link for the media devices using media-ctl -+ media-ctl -d $MDEV -l "\"ov01a10 3-0036\":0 -> \"Intel IPU6 CSI2 2\":0[1]" -+ -+ # Set the format for the media devices -+ media-ctl -d $MDEV -V "ov01a10:0 [fmt:SBGGR10/1280x800]" -+ media-ctl -d $MDEV -V "Intel IPU6 CSI2 2:0 [fmt:SBGGR10/1280x800]" -+ media-ctl -d $MDEV -V "Intel IPU6 CSI2 2:1 [fmt:SBGGR10/1280x800]" -+ -+Once the media pipeline is configured, desired sensor specific settings -+(such as exposure and gain settings) can be set, using the yavta tool. -+ -+e.g -+ -+.. code-block:: none -+ -+ # and that ov01a10 sensor is connected to i2c bus 3 with address 0x36 -+ export SDEV=$(media-ctl -d $MDEV -e "ov01a10 3-0036") -+ -+ yavta -w 0x009e0903 400 $SDEV -+ yavta -w 0x009e0913 1000 $SDEV -+ yavta -w 0x009e0911 2000 $SDEV -+ -+Once the desired sensor settings are set, frame captures can be done as below. -+ -+e.g -+ -+.. code-block:: none -+ -+ yavta --data-prefix -u -c10 -n5 -I -s 1280x800 --file=/tmp/frame-#.bin \ -+ -f SBGGR10 $(media-ctl -d $MDEV -e "Intel IPU6 ISYS Capture 0") -+ -+With the above command, 10 frames are captured at 1280x800 resolution with -+sBGGR10 format. The captured frames are available as /tmp/frame-#.bin files. -+ -+Here is another example of IPU6 ISYS RAW and metadata capture from camera -+sensor ov2740 on Lenovo X1 Yoga laptop. -+ -+.. code-block:: none -+ -+ media-ctl -l "\"ov2740 14-0036\":0 -> \"Intel IPU6 CSI2 1\":0[1]" -+ media-ctl -l "\"Intel IPU6 CSI2 1\":1 -> \"Intel IPU6 ISYS Capture 0\":0[5]" -+ media-ctl -l "\"Intel IPU6 CSI2 1\":2 -> \"Intel IPU6 ISYS Capture 1\":0[5]" -+ -+ # set routing -+ media-ctl -v -R "\"Intel IPU6 CSI2 1\" [0/0->1/0[1],0/1->2/1[1]]" -+ -+ media-ctl -v "\"Intel IPU6 CSI2 1\":0/0 [fmt:SGRBG10/1932x1092]" -+ media-ctl -v "\"Intel IPU6 CSI2 1\":0/1 [fmt:GENERIC_8/97x1]" -+ media-ctl -v "\"Intel IPU6 CSI2 1\":1/0 [fmt:SGRBG10/1932x1092]" -+ media-ctl -v "\"Intel IPU6 CSI2 1\":2/1 [fmt:GENERIC_8/97x1]" -+ -+ CAPTURE_DEV=$(media-ctl -e "Intel IPU6 ISYS Capture 0") -+ ./yavta --data-prefix -c100 -n5 -I -s1932x1092 --file=/tmp/frame-#.bin \ -+ -f SGRBG10 ${CAPTURE_DEV} -+ -+ CAPTURE_META=$(media-ctl -e "Intel IPU6 ISYS Capture 1") -+ ./yavta --data-prefix -c100 -n5 -I -s97x1 -B meta-capture \ -+ --file=/tmp/meta-#.bin -f GENERIC_8 ${CAPTURE_META} -+ -+References -+========== -+ -+.. [#f1] https://git.ideasonboard.org/?p=media-ctl.git;a=summary -+.. [#f2] https://git.ideasonboard.org/yavta.git -diff --git a/Documentation/admin-guide/media/ipu6_isys_graph.svg b/Documentation/admin-guide/media/ipu6_isys_graph.svg -new file mode 100644 -index 000000000000..707747c75280 ---- /dev/null -+++ b/Documentation/admin-guide/media/ipu6_isys_graph.svg -@@ -0,0 +1,174 @@ -+<?xml version="1.0" encoding="UTF-8" standalone="no"?> -+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" -+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -+<!-- Generated by graphviz version 2.38.0 (20140413.2041) -+ --> -+<!-- Title: board Pages: 1 --> -+<svg width="559pt" height="810pt" -+ viewBox="0.00 0.00 559.00 809.50" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 805.5)"> -+<title>board</title> -+<polygon fill="white" stroke="none" points="-4,4 -4,-805.5 555,-805.5 555,4 -4,4"/> -+<!-- n00000001 --> -+<g id="node1" class="node"><title>n00000001</title> -+<polygon fill="#66cd00" stroke="black" points="551,-192.5 387,-192.5 387,-154.5 551,-154.5 551,-192.5"/> -+<text text-anchor="middle" x="469" y="-177.3" font-family="Times,serif" font-size="14.00">Intel IPU6 ISYS Capture 0</text> -+<text text-anchor="middle" x="469" y="-162.3" font-family="Times,serif" font-size="14.00">/dev/video0</text> -+</g> -+<!-- n00000002 --> -+<g id="node2" class="node"><title>n00000002</title> -+<polygon fill="#66cd00" stroke="black" points="551,-395.5 387,-395.5 387,-357.5 551,-357.5 551,-395.5"/> -+<text text-anchor="middle" x="469" y="-380.3" font-family="Times,serif" font-size="14.00">Intel IPU6 ISYS Capture 1</text> -+<text text-anchor="middle" x="469" y="-365.3" font-family="Times,serif" font-size="14.00">/dev/video1</text> -+</g> -+<!-- n00000003 --> -+<g id="node3" class="node"><title>n00000003</title> -+<polygon fill="#66cd00" stroke="black" points="551,-598.5 387,-598.5 387,-560.5 551,-560.5 551,-598.5"/> -+<text text-anchor="middle" x="469" y="-583.3" font-family="Times,serif" font-size="14.00">Intel IPU6 ISYS Capture 2</text> -+<text text-anchor="middle" x="469" y="-568.3" font-family="Times,serif" font-size="14.00">/dev/video2</text> -+</g> -+<!-- n00000004 --> -+<g id="node4" class="node"><title>n00000004</title> -+<polygon fill="#66cd00" stroke="black" points="551,-801.5 387,-801.5 387,-763.5 551,-763.5 551,-801.5"/> -+<text text-anchor="middle" x="469" y="-786.3" font-family="Times,serif" font-size="14.00">Intel IPU6 ISYS Capture 3</text> -+<text text-anchor="middle" x="469" y="-771.3" font-family="Times,serif" font-size="14.00">/dev/video3</text> -+</g> -+<!-- n0000007d --> -+<g id="node5" class="node"><title>n0000007d</title> -+<path fill="#ffb90f" stroke="black" d="M201,-0.5C201,-0.5 339,-0.5 339,-0.5 345,-0.5 351,-6.5 351,-12.5 351,-12.5 351,-172.5 351,-172.5 351,-178.5 345,-184.5 339,-184.5 339,-184.5 201,-184.5 201,-184.5 195,-184.5 189,-178.5 189,-172.5 189,-172.5 189,-12.5 189,-12.5 189,-6.5 195,-0.5 201,-0.5"/> -+<text text-anchor="middle" x="200.5" y="-88.8" font-family="Times,serif" font-size="14.00">0</text> -+<polyline fill="none" stroke="black" points="212,-0.5 212,-184.5 "/> -+<text text-anchor="middle" x="270" y="-96.3" font-family="Times,serif" font-size="14.00">Intel IPU6 CSI2 0</text> -+<text text-anchor="middle" x="270" y="-81.3" font-family="Times,serif" font-size="14.00">/dev/v4l-subdev0</text> -+<polyline fill="none" stroke="black" points="328,-0.5 328,-184.5 "/> -+<text text-anchor="middle" x="339.5" y="-169.3" font-family="Times,serif" font-size="14.00">1</text> -+<polyline fill="none" stroke="black" points="328,-161.5 351,-161.5 "/> -+<text text-anchor="middle" x="339.5" y="-146.3" font-family="Times,serif" font-size="14.00">2</text> -+<polyline fill="none" stroke="black" points="328,-138.5 351,-138.5 "/> -+<text text-anchor="middle" x="339.5" y="-123.3" font-family="Times,serif" font-size="14.00">3</text> -+<polyline fill="none" stroke="black" points="328,-115.5 351,-115.5 "/> -+<text text-anchor="middle" x="339.5" y="-100.3" font-family="Times,serif" font-size="14.00">4</text> -+<polyline fill="none" stroke="black" points="328,-92.5 351,-92.5 "/> -+<text text-anchor="middle" x="339.5" y="-77.3" font-family="Times,serif" font-size="14.00">5</text> -+<polyline fill="none" stroke="black" points="328,-69.5 351,-69.5 "/> -+<text text-anchor="middle" x="339.5" y="-54.3" font-family="Times,serif" font-size="14.00">6</text> -+<polyline fill="none" stroke="black" points="328,-46.5 351,-46.5 "/> -+<text text-anchor="middle" x="339.5" y="-31.3" font-family="Times,serif" font-size="14.00">7</text> -+<polyline fill="none" stroke="black" points="328,-23.5 351,-23.5 "/> -+<text text-anchor="middle" x="339.5" y="-8.3" font-family="Times,serif" font-size="14.00">8</text> -+</g> -+<!-- n0000007d->n00000001 --> -+<g id="edge1" class="edge"><title>n0000007d:port1->n00000001</title> -+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M351,-173.5C359.322,-173.5 367.976,-173.5 376.644,-173.5"/> -+<polygon fill="black" stroke="black" points="376.807,-177 386.807,-173.5 376.807,-170 376.807,-177"/> -+</g> -+<!-- n00000087 --> -+<g id="node6" class="node"><title>n00000087</title> -+<path fill="#ffb90f" stroke="black" d="M201,-203.5C201,-203.5 339,-203.5 339,-203.5 345,-203.5 351,-209.5 351,-215.5 351,-215.5 351,-375.5 351,-375.5 351,-381.5 345,-387.5 339,-387.5 339,-387.5 201,-387.5 201,-387.5 195,-387.5 189,-381.5 189,-375.5 189,-375.5 189,-215.5 189,-215.5 189,-209.5 195,-203.5 201,-203.5"/> -+<text text-anchor="middle" x="200.5" y="-291.8" font-family="Times,serif" font-size="14.00">0</text> -+<polyline fill="none" stroke="black" points="212,-203.5 212,-387.5 "/> -+<text text-anchor="middle" x="270" y="-299.3" font-family="Times,serif" font-size="14.00">Intel IPU6 CSI2 1</text> -+<text text-anchor="middle" x="270" y="-284.3" font-family="Times,serif" font-size="14.00">/dev/v4l-subdev1</text> -+<polyline fill="none" stroke="black" points="328,-203.5 328,-387.5 "/> -+<text text-anchor="middle" x="339.5" y="-372.3" font-family="Times,serif" font-size="14.00">1</text> -+<polyline fill="none" stroke="black" points="328,-364.5 351,-364.5 "/> -+<text text-anchor="middle" x="339.5" y="-349.3" font-family="Times,serif" font-size="14.00">2</text> -+<polyline fill="none" stroke="black" points="328,-341.5 351,-341.5 "/> -+<text text-anchor="middle" x="339.5" y="-326.3" font-family="Times,serif" font-size="14.00">3</text> -+<polyline fill="none" stroke="black" points="328,-318.5 351,-318.5 "/> -+<text text-anchor="middle" x="339.5" y="-303.3" font-family="Times,serif" font-size="14.00">4</text> -+<polyline fill="none" stroke="black" points="328,-295.5 351,-295.5 "/> -+<text text-anchor="middle" x="339.5" y="-280.3" font-family="Times,serif" font-size="14.00">5</text> -+<polyline fill="none" stroke="black" points="328,-272.5 351,-272.5 "/> -+<text text-anchor="middle" x="339.5" y="-257.3" font-family="Times,serif" font-size="14.00">6</text> -+<polyline fill="none" stroke="black" points="328,-249.5 351,-249.5 "/> -+<text text-anchor="middle" x="339.5" y="-234.3" font-family="Times,serif" font-size="14.00">7</text> -+<polyline fill="none" stroke="black" points="328,-226.5 351,-226.5 "/> -+<text text-anchor="middle" x="339.5" y="-211.3" font-family="Times,serif" font-size="14.00">8</text> -+</g> -+<!-- n00000087->n00000002 --> -+<g id="edge2" class="edge"><title>n00000087:port1->n00000002</title> -+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M351,-376.5C359.322,-376.5 367.976,-376.5 376.644,-376.5"/> -+<polygon fill="black" stroke="black" points="376.807,-380 386.807,-376.5 376.807,-373 376.807,-380"/> -+</g> -+<!-- n00000091 --> -+<g id="node7" class="node"><title>n00000091</title> -+<path fill="#ffb90f" stroke="black" d="M201,-406.5C201,-406.5 339,-406.5 339,-406.5 345,-406.5 351,-412.5 351,-418.5 351,-418.5 351,-578.5 351,-578.5 351,-584.5 345,-590.5 339,-590.5 339,-590.5 201,-590.5 201,-590.5 195,-590.5 189,-584.5 189,-578.5 189,-578.5 189,-418.5 189,-418.5 189,-412.5 195,-406.5 201,-406.5"/> -+<text text-anchor="middle" x="200.5" y="-494.8" font-family="Times,serif" font-size="14.00">0</text> -+<polyline fill="none" stroke="black" points="212,-406.5 212,-590.5 "/> -+<text text-anchor="middle" x="270" y="-502.3" font-family="Times,serif" font-size="14.00">Intel IPU6 CSI2 2</text> -+<text text-anchor="middle" x="270" y="-487.3" font-family="Times,serif" font-size="14.00">/dev/v4l-subdev2</text> -+<polyline fill="none" stroke="black" points="328,-406.5 328,-590.5 "/> -+<text text-anchor="middle" x="339.5" y="-575.3" font-family="Times,serif" font-size="14.00">1</text> -+<polyline fill="none" stroke="black" points="328,-567.5 351,-567.5 "/> -+<text text-anchor="middle" x="339.5" y="-552.3" font-family="Times,serif" font-size="14.00">2</text> -+<polyline fill="none" stroke="black" points="328,-544.5 351,-544.5 "/> -+<text text-anchor="middle" x="339.5" y="-529.3" font-family="Times,serif" font-size="14.00">3</text> -+<polyline fill="none" stroke="black" points="328,-521.5 351,-521.5 "/> -+<text text-anchor="middle" x="339.5" y="-506.3" font-family="Times,serif" font-size="14.00">4</text> -+<polyline fill="none" stroke="black" points="328,-498.5 351,-498.5 "/> -+<text text-anchor="middle" x="339.5" y="-483.3" font-family="Times,serif" font-size="14.00">5</text> -+<polyline fill="none" stroke="black" points="328,-475.5 351,-475.5 "/> -+<text text-anchor="middle" x="339.5" y="-460.3" font-family="Times,serif" font-size="14.00">6</text> -+<polyline fill="none" stroke="black" points="328,-452.5 351,-452.5 "/> -+<text text-anchor="middle" x="339.5" y="-437.3" font-family="Times,serif" font-size="14.00">7</text> -+<polyline fill="none" stroke="black" points="328,-429.5 351,-429.5 "/> -+<text text-anchor="middle" x="339.5" y="-414.3" font-family="Times,serif" font-size="14.00">8</text> -+</g> -+<!-- n00000091->n00000003 --> -+<g id="edge3" class="edge"><title>n00000091:port1->n00000003</title> -+<path fill="none" stroke="black" d="M351,-579.5C359.322,-579.5 367.976,-579.5 376.644,-579.5"/> -+<polygon fill="black" stroke="black" points="376.807,-583 386.807,-579.5 376.807,-576 376.807,-583"/> -+</g> -+<!-- n0000009b --> -+<g id="node8" class="node"><title>n0000009b</title> -+<path fill="#ffb90f" stroke="black" d="M201,-609.5C201,-609.5 339,-609.5 339,-609.5 345,-609.5 351,-615.5 351,-621.5 351,-621.5 351,-781.5 351,-781.5 351,-787.5 345,-793.5 339,-793.5 339,-793.5 201,-793.5 201,-793.5 195,-793.5 189,-787.5 189,-781.5 189,-781.5 189,-621.5 189,-621.5 189,-615.5 195,-609.5 201,-609.5"/> -+<text text-anchor="middle" x="200.5" y="-697.8" font-family="Times,serif" font-size="14.00">0</text> -+<polyline fill="none" stroke="black" points="212,-609.5 212,-793.5 "/> -+<text text-anchor="middle" x="270" y="-705.3" font-family="Times,serif" font-size="14.00">Intel IPU6 CSI2 3</text> -+<text text-anchor="middle" x="270" y="-690.3" font-family="Times,serif" font-size="14.00">/dev/v4l-subdev3</text> -+<polyline fill="none" stroke="black" points="328,-609.5 328,-793.5 "/> -+<text text-anchor="middle" x="339.5" y="-778.3" font-family="Times,serif" font-size="14.00">1</text> -+<polyline fill="none" stroke="black" points="328,-770.5 351,-770.5 "/> -+<text text-anchor="middle" x="339.5" y="-755.3" font-family="Times,serif" font-size="14.00">2</text> -+<polyline fill="none" stroke="black" points="328,-747.5 351,-747.5 "/> -+<text text-anchor="middle" x="339.5" y="-732.3" font-family="Times,serif" font-size="14.00">3</text> -+<polyline fill="none" stroke="black" points="328,-724.5 351,-724.5 "/> -+<text text-anchor="middle" x="339.5" y="-709.3" font-family="Times,serif" font-size="14.00">4</text> -+<polyline fill="none" stroke="black" points="328,-701.5 351,-701.5 "/> -+<text text-anchor="middle" x="339.5" y="-686.3" font-family="Times,serif" font-size="14.00">5</text> -+<polyline fill="none" stroke="black" points="328,-678.5 351,-678.5 "/> -+<text text-anchor="middle" x="339.5" y="-663.3" font-family="Times,serif" font-size="14.00">6</text> -+<polyline fill="none" stroke="black" points="328,-655.5 351,-655.5 "/> -+<text text-anchor="middle" x="339.5" y="-640.3" font-family="Times,serif" font-size="14.00">7</text> -+<polyline fill="none" stroke="black" points="328,-632.5 351,-632.5 "/> -+<text text-anchor="middle" x="339.5" y="-617.3" font-family="Times,serif" font-size="14.00">8</text> -+</g> -+<!-- n0000009b->n00000004 --> -+<g id="edge4" class="edge"><title>n0000009b:port1->n00000004</title> -+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M351,-782.5C359.322,-782.5 367.976,-782.5 376.644,-782.5"/> -+<polygon fill="black" stroke="black" points="376.807,-786 386.807,-782.5 376.807,-779 376.807,-786"/> -+</g> -+<!-- n00000865 --> -+<g id="node9" class="node"><title>n00000865</title> -+<path fill="cornflowerblue" stroke="black" d="M12,-479.5C12,-479.5 141,-479.5 141,-479.5 147,-479.5 153,-485.5 153,-491.5 153,-491.5 153,-505.5 153,-505.5 153,-511.5 147,-517.5 141,-517.5 141,-517.5 12,-517.5 12,-517.5 6,-517.5 0,-511.5 0,-505.5 0,-505.5 0,-491.5 0,-491.5 0,-485.5 6,-479.5 12,-479.5"/> -+<text text-anchor="middle" x="10" y="-494.8" font-family="Times,serif" font-size="14.00"> </text> -+<polyline fill="none" stroke="black" points="20,-479.5 20,-517.5 "/> -+<text text-anchor="middle" x="75" y="-502.3" font-family="Times,serif" font-size="14.00">ov01a10 3-0036</text> -+<text text-anchor="middle" x="75" y="-487.3" font-family="Times,serif" font-size="14.00">/dev/v4l-subdev4</text> -+<polyline fill="none" stroke="black" points="130,-479.5 130,-517.5 "/> -+<text text-anchor="middle" x="141.5" y="-494.8" font-family="Times,serif" font-size="14.00">0</text> -+</g> -+<!-- n00000865->n00000091 --> -+<g id="edge5" class="edge"><title>n00000865:port0->n00000091:port0</title> -+<path fill="none" stroke="black" d="M153,-498.5C165,-498.5 170.25,-498.5 178.875,-498.5"/> -+<polygon fill="black" stroke="black" points="179,-502 189,-498.5 179,-495 179,-502"/> -+</g> -+<!-- n00000866 --> -+<!-- n00000866->n0000007d --> -+<!-- n00000867 --> -+<!-- n00000867->n00000087 --> -+<!-- n00000868 --> -+<!-- n00000868->n0000009b --> -+</g> -+</svg> -diff --git a/Documentation/admin-guide/media/v4l-drivers.rst b/Documentation/admin-guide/media/v4l-drivers.rst -index f4bb2605f07e..4120eded9a13 100644 ---- a/Documentation/admin-guide/media/v4l-drivers.rst -+++ b/Documentation/admin-guide/media/v4l-drivers.rst -@@ -16,6 +16,7 @@ Video4Linux (V4L) driver-specific documentation - imx - imx7 - ipu3 -+ ipu6-isys - ivtv - mgb4 - omap3isp --- -2.43.2 - - -From 3e80683ecc9ffe38fdf6e6232089794b6019816b Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:29 +0800 -Subject: [PATCH 22/33] Documentation: add documentation of Intel IPU6 driver - and hardware overview - -Add a documentation for an overview of IPU6 hardware and describe the main -the components of IPU6 driver. - -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - .../driver-api/media/drivers/index.rst | 1 + - .../driver-api/media/drivers/ipu6.rst | 205 ++++++++++++++++++ - 2 files changed, 206 insertions(+) - create mode 100644 Documentation/driver-api/media/drivers/ipu6.rst - -diff --git a/Documentation/driver-api/media/drivers/index.rst b/Documentation/driver-api/media/drivers/index.rst -index c4123a16b5f9..7f6f3dcd5c90 100644 ---- a/Documentation/driver-api/media/drivers/index.rst -+++ b/Documentation/driver-api/media/drivers/index.rst -@@ -26,6 +26,7 @@ Video4Linux (V4L) drivers - vimc-devel - zoran - ccs/ccs -+ ipu6 - - - Digital TV drivers -diff --git a/Documentation/driver-api/media/drivers/ipu6.rst b/Documentation/driver-api/media/drivers/ipu6.rst -new file mode 100644 -index 000000000000..b6357155c13b ---- /dev/null -+++ b/Documentation/driver-api/media/drivers/ipu6.rst -@@ -0,0 +1,205 @@ -+.. SPDX-License-Identifier: GPL-2.0 -+ -+================== -+Intel IPU6 Driver -+================== -+ -+Author: Bingbu Cao <bingbu.cao@intel.com> -+ -+Overview -+========= -+ -+Intel IPU6 is the sixth generation of Intel Image Processing Unit used in some -+Intel Chipsets such as Tiger Lake, Jasper Lake, Alder Lake, Raptor Lake and -+Meteor Lake. IPU6 consists of two major systems: Input System (IS) and -+Processing System (PS). IPU6 are visible on the PCI bus as a single device, -+it can be found by ``lspci``: -+ -+``0000:00:05.0 Multimedia controller: Intel Corporation Device xxxx (rev xx)`` -+ -+IPU6 has a 16 MB BAR in PCI configuration Space for MMIO registers which is -+visible for driver. -+ -+Buttress -+========= -+ -+The IPU6 is connecting to the system fabric with ``Buttress`` which is enabling -+host driver to control the IPU6, it also allows IPU6 access the system memory to -+store and load frame pixel streams and any other metadata. -+ -+``Buttress`` mainly manages several system functionalities - power management, -+interrupt handling, firmware authentication and global timer sync. -+ -+IS and PS Power flow -+--------------------------- -+ -+IPU6 driver initialize the IS and PS power up or down request by setting the -+Buttress frequency control register for IS and PS - -+``IPU6_BUTTRESS_REG_IS_FREQ_CTL`` and ``IPU6_BUTTRESS_REG_PS_FREQ_CTL`` in -+function: -+ -+.. c:function:: int ipu6_buttress_power(..., bool on) -+ -+Buttress forwards the request to Punit, after Punit execute the power up flow, -+buttress indicates driver that IS or PS is powered up by updating the power -+status registers. -+ -+.. Note:: IS power up needs take place prior to PS power up, IS power down needs -+ take place after PS power down due to hardware limitation. -+ -+ -+Interrupt -+------------ -+ -+IPU6 interrupt can be generated as MSI or INTA, interrupt will be triggered -+when IS, PS, Buttress event or error happen, driver can get the interrupt -+cause by reading the interrupt status register ``BUTTRESS_REG_ISR_STATUS``, -+driver firstly clear the irq status and then call specific IS or PS irq handler. -+ -+.. c:function:: irqreturn_t ipu6_buttress_isr(int irq, ...) -+ -+Security and firmware authentication -+------------------------------------- -+To address the IPU6 firmware security concerns, the IPU6 firmware needs to -+undergo an authentication process before it is allowed to executed on the IPU6 -+internal processors. Driver will work with Converged Security Engine (CSE) to -+complete authentication process. CSE is responsible of authenticating the -+IPU6 firmware, the authenticated firmware binary is copied into an isolated -+memory region. Firmware authentication process is implemented by CSE following -+an IPC handshake with driver. There are some Buttress registers used by CSE and -+driver to communicate with each other as IPC messages. -+ -+.. c:function:: int ipu6_buttress_authenticate(...) -+ -+Global timer sync -+------------------ -+IPU driver initiates a Hammock Harbor synchronization flow each time it starts -+camera operation. IPU will synchronizes an internal counter in the Buttress -+with a copy of SoC time, this counter keeps the updated time until camera -+operation is stopped. Driver can use this time counter to calibrate the -+timestamp based on the timestamp in response event from firmware. -+ -+.. c:function:: int ipu6_buttress_start_tsc_sync(...) -+ -+ -+DMA and MMU -+============ -+ -+IPU6 has its own scalar processor where the firmware run at, it has -+an internal 32-bits virtual address space. IPU6 has MMU address translation -+hardware to allow that scalar process access the internal memory and external -+system memory through IPU6 virtual address. The address translation is -+based on two levels of page lookup tables stored in system memory which are -+maintained by IPU6 driver. IPU6 driver sets the level-1 page table base address -+to MMU register and allow MMU to lookup the page table. -+ -+IPU6 driver exports its own DMA operations. Driver will update the page table -+entries for each DMA operation and invalidate the MMU TLB after each unmap and -+free. -+ -+.. code-block:: none -+ -+ const struct dma_map_ops ipu6_dma_ops = { -+ .alloc = ipu6_dma_alloc, -+ .free = ipu6_dma_free, -+ .mmap = ipu6_dma_mmap, -+ .map_sg = ipu6_dma_map_sg, -+ .unmap_sg = ipu6_dma_unmap_sg, -+ ... -+ }; -+ -+.. Note:: IPU6 MMU works behind IOMMU, so for each IPU6 DMA ops, driver will -+ call generic PCI DMA ops to ask IOMMU to do the additional mapping -+ if VT-d enabled. -+ -+ -+Firmware file format -+===================== -+ -+IPU6 release the firmware in Code Partition Directory (CPD) file format. The -+CPD firmware contains a CPD header, several CPD entries and CPD components. -+CPD component includes 3 entries - manifest, metadata and module data. Manifest -+and metadata are defined by CSE and used by CSE for authentication. Module data -+is defined by IPU6 which holds the binary data of firmware called package -+directory. IPU6 driver (``ipu6-cpd.c``) parses and validates the CPD firmware -+file and get the package directory binary data of IPU6 firmware, copy it to -+specific DMA buffer and sets its base address to Buttress ``FW_SOURCE_BASE`` -+register, CSE will do authentication for this firmware binary. -+ -+ -+Syscom interface -+================ -+ -+IPU6 driver communicates with firmware via syscom ABI. Syscom is an -+inter-processor communication mechanism between IPU scalar processor and CPU. -+There are a number of resources shared between firmware and software. -+A system memory region where the message queues reside, firmware can access the -+memory region via IPU MMU. Syscom queues are FIFO fixed depth queues with -+configurable elements ``token`` (message). There is also a common IPU MMIO -+registers where the queue read and write indices reside. Software and firmware -+work as producer and consumer of tokens in queue, and update the write and read -+indices separately when sending or receiving each message. -+ -+IPU6 driver must prepare and configure the number of input and output queues, -+configure the count of tokens per queue and the size of per token before -+initiate and start the communication with firmware, firmware and software must -+use same configurations. IPU6 Buttress has a number of firmware boot parameter -+registers which can be used to store the address of configuration and initiate -+the Syscom state, then driver can request firmware to start and run via setting -+the scalar processor control status register. -+ -+ -+Input System -+============== -+ -+IPU6 input system consists of MIPI D-PHY and several CSI receiver controllers, -+it can capture image pixel data from camera sensors or other MIPI CSI output -+devices. -+ -+D-PHYs and CSI-2 ports lane mapping -+----------------------------------- -+ -+IPU6 integrates different D-PHY IPs on different SoCs, on Tiger Lake and Alder -+Lake, IPU6 integrates MCD10 D-PHY, IPU6SE on Jasper Lake integrates JSL D-PHY -+and IPU6EP on Meteor Lake integrates a Synopsys DWC D-PHY. There is an adaption -+layer between D-PHY and CSI receiver controller which includes port -+configuration, PHY wrapper or private test interfaces for D-PHY. There are 3 -+D-PHY drivers ``ipu6-isys-mcd-phy.c``, ``ipu6-isys-jsl-phy.c`` and -+``ipu6-isys-dwc-phy.c`` program the above 3 D-PHYs in IPU6. -+ -+Different IPU6 version has different D-PHY lanes mappings, On Tiger Lake, there -+are 12 data lanes and 8 clock lanes, IPU6 support maximum 8 CSI-2 ports, see -+the ppi mmapping in ``ipu6-isys-mcd-phy.c`` for more information. On Jasper Lake -+and Alder Lake, D-PHY has 8 data lanes and 4 clock lanes, IPU6 support maximum 4 -+CSI-2 ports. For Meteor Lake, D-PHY has 12 data lanes and 6 clock lanes, IPU6 -+support maximum 6 CSI-2 ports. -+ -+.. Note:: Each adjacent CSI ports work as a pair and share the data lanes. -+ For example, for CSI port 0 and 1, CSI port 0 support maximum 4 -+ data lanes, CSI port 1 support maximum 2 data lanes, CSI port 0 -+ with 2 data lanes can work together with CSI port 1 with 2 data lanes. -+ If trying to use CSI port 0 with 4 lanes, CSI port 1 will not be -+ available as the 4 data lanes are shared by CSI port 0 and 1. Same -+ scenario is also applied for CSI port 2/3, 4/5 and 7/8. -+ -+IS firmware ABIs -+---------------- -+ -+IPU6 firmware define a series of ABIs to software. In general, software firstly -+prepare the stream configuration ``struct ipu6_fw_isys_stream_cfg_data_abi`` -+and send the configuration to firmware via sending ``STREAM_OPEN`` command. -+Stream configuration includes input pins and output pins, input pin -+``struct ipu6_fw_isys_input_pin_info_abi`` defines the resolution and data type -+of input source, output pin ``struct ipu6_fw_isys_output_pin_info_abi`` -+defines the output resolution, stride and frame format, etc. Once driver get the -+interrupt from firmware that indicates stream open successfully, driver will -+send the ``STREAM_START`` and ``STREAM_CAPTURE`` command to request firmware to -+start capturing image frames. ``STREAM_CAPTURE`` command queues the buffers to -+firmware with ``struct ipu6_fw_isys_frame_buff_set``, software then wait the -+interrupt and response from firmware, ``PIN_DATA_READY`` means data ready -+on specific output pin and then software return the buffers to user. -+ -+.. Note:: See :ref:`Examples<ipu6_isys_capture_examples>` about how to do -+ capture by IPU6 IS driver. -+ -+ --- -2.43.2 - - -From d883f3386e7185d9404cb25e32df986656a4e82a Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:30 +0800 -Subject: [PATCH 23/33] media: ipu6/isys: support line-based metadata capture - support - -Some camera sensor can output the embedded data in specific -data type. This patch add the support for embedded data capture -in IPU6 IS driver. - -It's based on Sakari's line-based metadata capture support change: -<URL:https://git.linuxtv.org/sailus/media_tree.git/log/?h=metadata> - -Signed-off-by: Hongju Wang <hongju.wang@intel.com> -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 5 + - .../media/pci/intel/ipu6/ipu6-isys-queue.c | 44 ++-- - .../media/pci/intel/ipu6/ipu6-isys-subdev.c | 5 + - .../media/pci/intel/ipu6/ipu6-isys-video.c | 201 +++++++++++++++--- - .../media/pci/intel/ipu6/ipu6-isys-video.h | 7 +- - 5 files changed, 216 insertions(+), 46 deletions(-) - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c -index ac9fa3e0d7ab..a6430d531129 100644 ---- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c -@@ -42,6 +42,11 @@ static const u32 csi2_supported_codes[] = { - MEDIA_BUS_FMT_SGBRG8_1X8, - MEDIA_BUS_FMT_SGRBG8_1X8, - MEDIA_BUS_FMT_SRGGB8_1X8, -+ MEDIA_BUS_FMT_META_8, -+ MEDIA_BUS_FMT_META_10, -+ MEDIA_BUS_FMT_META_12, -+ MEDIA_BUS_FMT_META_16, -+ MEDIA_BUS_FMT_META_24, - 0 - }; - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c -index 735d2d642d87..15fa7ed22b2f 100644 ---- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c -@@ -35,11 +35,14 @@ static int queue_setup(struct vb2_queue *q, unsigned int *num_buffers, - /* num_planes == 0: we're being called through VIDIOC_REQBUFS */ - if (!*num_planes) { - use_fmt = true; -- *num_planes = av->mpix.num_planes; -+ if (av->vfmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) -+ *num_planes = av->vfmt.fmt.pix_mp.num_planes; -+ else if (av->vfmt.type == V4L2_BUF_TYPE_META_CAPTURE) -+ *num_planes = 1; - } - - for (i = 0; i < *num_planes; i++) { -- size = av->mpix.plane_fmt[i].sizeimage; -+ size = ipu6_get_data_size(&av->vfmt, i); - if (use_fmt) { - sizes[i] = size; - } else if (sizes[i] < size) { -@@ -59,16 +62,17 @@ static int ipu6_isys_buf_prepare(struct vb2_buffer *vb) - struct ipu6_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue); - struct ipu6_isys_video *av = ipu6_isys_queue_to_video(aq); - struct device *dev = &av->isys->adev->auxdev.dev; -+ u32 bytesperline = ipu6_get_bytes_per_line(&av->vfmt); -+ u32 height = ipu6_get_frame_height(&av->vfmt); -+ u32 size = ipu6_get_data_size(&av->vfmt, 0); - - dev_dbg(dev, "buffer: %s: configured size %u, buffer size %lu\n", -- av->vdev.name, av->mpix.plane_fmt[0].sizeimage, -- vb2_plane_size(vb, 0)); -+ av->vdev.name, size, vb2_plane_size(vb, 0)); - -- if (av->mpix.plane_fmt[0].sizeimage > vb2_plane_size(vb, 0)) -+ if (size > vb2_plane_size(vb, 0)) - return -EINVAL; - -- vb2_set_plane_payload(vb, 0, av->mpix.plane_fmt[0].bytesperline * -- av->mpix.height); -+ vb2_set_plane_payload(vb, 0, bytesperline * height); - vb->planes[0].data_offset = 0; - - return 0; -@@ -437,18 +441,22 @@ static int ipu6_isys_link_fmt_validate(struct ipu6_isys_queue *aq) - return ret; - } - -- if (format.width != av->mpix.width || -- format.height != av->mpix.height) { -- dev_dbg(dev, "wrong width or height %ux%u (%ux%u expected)\n", -- av->mpix.width, av->mpix.height, -- format.width, format.height); -+ if (format.width != ipu6_get_frame_width(&av->vfmt) || -+ format.height != ipu6_get_frame_height(&av->vfmt)) { -+ dev_err(dev, "wrong width or height %ux%u (%ux%u expected)\n", -+ ipu6_get_frame_width(&av->vfmt), -+ ipu6_get_frame_height(&av->vfmt), format.width, -+ format.height); - return -EINVAL; - } - -- if (format.field != av->mpix.field) { -- dev_dbg(dev, "wrong field value 0x%8.8x (0x%8.8x expected)\n", -- av->mpix.field, format.field); -- return -EINVAL; -+ if (av->vfmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { -+ if (format.field != av->vfmt.fmt.pix_mp.field) { -+ dev_dbg(dev, -+ "wrong field value 0x%8.8x (%8.8x expected)\n", -+ av->vfmt.fmt.pix_mp.field, format.field); -+ return -EINVAL; -+ } - } - - if (format.code != av->pfmt->code) { -@@ -531,8 +539,8 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) - int nr_queues, ret; - - dev_dbg(dev, "stream: %s: width %u, height %u, css pixelformat %u\n", -- av->vdev.name, av->mpix.width, av->mpix.height, -- av->pfmt->css_pixelformat); -+ av->vdev.name, ipu6_get_frame_width(&av->vfmt), -+ ipu6_get_frame_height(&av->vfmt), av->pfmt->css_pixelformat); - - ret = ipu6_isys_setup_video(av, &source_entity, &nr_queues); - if (ret < 0) { -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c -index 510c5ca34f9f..3c9263ac02a3 100644 ---- a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c -@@ -20,25 +20,30 @@ unsigned int ipu6_isys_mbus_code_to_bpp(u32 code) - { - switch (code) { - case MEDIA_BUS_FMT_RGB888_1X24: -+ case MEDIA_BUS_FMT_META_24: - return 24; - case MEDIA_BUS_FMT_RGB565_1X16: - case MEDIA_BUS_FMT_UYVY8_1X16: - case MEDIA_BUS_FMT_YUYV8_1X16: -+ case MEDIA_BUS_FMT_META_16: - return 16; - case MEDIA_BUS_FMT_SBGGR12_1X12: - case MEDIA_BUS_FMT_SGBRG12_1X12: - case MEDIA_BUS_FMT_SGRBG12_1X12: - case MEDIA_BUS_FMT_SRGGB12_1X12: -+ case MEDIA_BUS_FMT_META_12: - return 12; - case MEDIA_BUS_FMT_SBGGR10_1X10: - case MEDIA_BUS_FMT_SGBRG10_1X10: - case MEDIA_BUS_FMT_SGRBG10_1X10: - case MEDIA_BUS_FMT_SRGGB10_1X10: -+ case MEDIA_BUS_FMT_META_10: - return 10; - case MEDIA_BUS_FMT_SBGGR8_1X8: - case MEDIA_BUS_FMT_SGBRG8_1X8: - case MEDIA_BUS_FMT_SGRBG8_1X8: - case MEDIA_BUS_FMT_SRGGB8_1X8: -+ case MEDIA_BUS_FMT_META_8: - return 8; - default: - WARN_ON(1); -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -index 847eac26bcd6..1a023bf1e1a6 100644 ---- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -@@ -85,6 +85,11 @@ const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = { - IPU6_FW_ISYS_FRAME_FORMAT_RGB565}, - {V4L2_PIX_FMT_BGR24, 24, 24, MEDIA_BUS_FMT_RGB888_1X24, - IPU6_FW_ISYS_FRAME_FORMAT_RGBA888}, -+ {V4L2_META_FMT_GENERIC_8, 8, 8, MEDIA_BUS_FMT_META_8, 0}, -+ {V4L2_META_FMT_GENERIC_CSI2_10, 10, 10, MEDIA_BUS_FMT_META_10, 0}, -+ {V4L2_META_FMT_GENERIC_CSI2_12, 12, 12, MEDIA_BUS_FMT_META_12, 0}, -+ {V4L2_META_FMT_GENERIC_CSI2_16, 16, 16, MEDIA_BUS_FMT_META_16, 0}, -+ {V4L2_META_FMT_GENERIC_CSI2_24, 24, 24, MEDIA_BUS_FMT_META_24, 0}, - }; - - static int video_open(struct file *file) -@@ -181,12 +186,12 @@ static int ipu6_isys_vidioc_enum_framesizes(struct file *file, void *fh, - return 0; - } - --static int vidioc_g_fmt_vid_cap_mplane(struct file *file, void *fh, -- struct v4l2_format *fmt) -+static int vidioc_get_format(struct file *file, void *fh, -+ struct v4l2_format *fmt) - { - struct ipu6_isys_video *av = video_drvdata(file); - -- fmt->fmt.pix_mp = av->mpix; -+ *fmt = av->vfmt; - - return 0; - } -@@ -245,30 +250,114 @@ ipu6_isys_video_try_fmt_vid_mplane(struct ipu6_isys_video *av, - return pfmt; - } - --static int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *fh, -- struct v4l2_format *f) -+static const struct ipu6_isys_pixelformat * -+ipu6_isys_video_try_fmt_meta(struct ipu6_isys_video *av, -+ struct v4l2_meta_format *meta) -+{ -+ const struct ipu6_isys_pixelformat *pfmt = -+ ipu6_isys_get_pixelformat(meta->dataformat); -+ -+ memset(&av->vfmt, 0, sizeof(av->vfmt)); -+ av->vfmt.type = V4L2_BUF_TYPE_META_CAPTURE; -+ av->pfmt = pfmt; -+ -+ meta->dataformat = pfmt->pixelformat; -+ meta->width = clamp(meta->width, IPU6_ISYS_MIN_WIDTH, -+ IPU6_ISYS_MAX_WIDTH); -+ meta->height = clamp(meta->height, IPU6_ISYS_MIN_HEIGHT, -+ IPU6_ISYS_MAX_HEIGHT); -+ -+ if (pfmt->bpp != pfmt->bpp_packed) -+ meta->bytesperline = meta->width * -+ DIV_ROUND_UP(pfmt->bpp, BITS_PER_BYTE); -+ else -+ meta->bytesperline = -+ DIV_ROUND_UP(meta->width * pfmt->bpp, BITS_PER_BYTE); -+ -+ meta->bytesperline = ALIGN(meta->bytesperline, av->isys->line_align); -+ meta->buffersize = -+ max(max(meta->buffersize, meta->bytesperline * meta->height + -+ max(meta->bytesperline, -+ av->isys->pdata->ipdata->isys_dma_overshoot)), 1U); -+ -+ return pfmt; -+} -+ -+static const struct ipu6_isys_pixelformat * -+ipu6_isys_video_try_fmt(struct ipu6_isys_video *av, struct v4l2_format *f) -+{ -+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) -+ return ipu6_isys_video_try_fmt_vid_mplane(av, &f->fmt.pix_mp); -+ else if (f->type == V4L2_BUF_TYPE_META_CAPTURE) -+ return ipu6_isys_video_try_fmt_meta(av, &f->fmt.meta); -+ else -+ return &ipu6_isys_pfmts[0]; -+} -+ -+static int vidioc_set_format(struct file *file, void *fh, -+ struct v4l2_format *f) - { - struct ipu6_isys_video *av = video_drvdata(file); - - if (av->aq.vbq.streaming) - return -EBUSY; - -- av->pfmt = ipu6_isys_video_try_fmt_vid_mplane(av, &f->fmt.pix_mp); -- av->mpix = f->fmt.pix_mp; -+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && -+ f->type != V4L2_BUF_TYPE_META_CAPTURE) -+ return -EINVAL; -+ -+ av->pfmt = ipu6_isys_video_try_fmt(av, f); -+ av->vfmt = *f; - - return 0; - } - --static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *fh, -- struct v4l2_format *f) -+static int vidioc_try_format(struct file *file, void *fh, -+ struct v4l2_format *f) - { - struct ipu6_isys_video *av = video_drvdata(file); - -- ipu6_isys_video_try_fmt_vid_mplane(av, &f->fmt.pix_mp); -+ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && -+ f->type != V4L2_BUF_TYPE_META_CAPTURE) -+ return -EINVAL; -+ -+ ipu6_isys_video_try_fmt(av, f); - - return 0; - } - -+static int vidioc_request_qbufs(struct file *file, void *priv, -+ struct v4l2_requestbuffers *p) -+{ -+ struct ipu6_isys_video *av = video_drvdata(file); -+ int ret; -+ -+ av->aq.vbq.is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(p->type); -+ av->aq.vbq.is_output = V4L2_TYPE_IS_OUTPUT(p->type); -+ -+ ret = vb2_queue_change_type(&av->aq.vbq, p->type); -+ if (ret) -+ return ret; -+ -+ return vb2_ioctl_reqbufs(file, priv, p); -+} -+ -+static int vidioc_create_bufs(struct file *file, void *priv, -+ struct v4l2_create_buffers *p) -+{ -+ struct ipu6_isys_video *av = video_drvdata(file); -+ int ret; -+ -+ av->aq.vbq.is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(p->format.type); -+ av->aq.vbq.is_output = V4L2_TYPE_IS_OUTPUT(p->format.type); -+ -+ ret = vb2_queue_change_type(&av->aq.vbq, p->format.type); -+ if (ret) -+ return ret; -+ -+ return vb2_ioctl_create_bufs(file, priv, p); -+} -+ - static int link_validate(struct media_link *link) - { - struct ipu6_isys_video *av = -@@ -279,6 +368,8 @@ static int link_validate(struct media_link *link) - struct v4l2_mbus_framefmt *s_fmt; - struct media_pad *s_pad; - u32 s_stream; -+ u32 height; -+ u32 width; - int ret = -EPIPE; - - if (!link->source->entity) -@@ -305,11 +396,13 @@ static int link_validate(struct media_link *link) - goto unlock; - } - -- if (s_fmt->width != av->mpix.width || -- s_fmt->height != av->mpix.height || s_fmt->code != av->pfmt->code) { -+ height = ipu6_get_frame_height(&av->vfmt); -+ width = ipu6_get_frame_width(&av->vfmt); -+ if (s_fmt->width != width || s_fmt->height != height || -+ s_fmt->code != av->pfmt->code) { - dev_err(dev, "format mismatch %dx%d,%x != %dx%d,%x\n", -- s_fmt->width, s_fmt->height, s_fmt->code, -- av->mpix.width, av->mpix.height, av->pfmt->code); -+ s_fmt->width, s_fmt->height, s_fmt->code, width, height, -+ av->pfmt->code); - goto unlock; - } - -@@ -393,10 +486,10 @@ static int ipu6_isys_fw_pin_cfg(struct ipu6_isys_video *av, - - output_pin = &cfg->output_pins[output_pins]; - output_pin->input_pin_id = input_pins; -- output_pin->output_res.width = av->mpix.width; -- output_pin->output_res.height = av->mpix.height; -+ output_pin->output_res.width = ipu6_get_frame_width(&av->vfmt); -+ output_pin->output_res.height = ipu6_get_frame_height(&av->vfmt); - -- output_pin->stride = av->mpix.plane_fmt[0].bytesperline; -+ output_pin->stride = ipu6_get_bytes_per_line(&av->vfmt); - if (av->pfmt->bpp != av->pfmt->bpp_packed) - output_pin->pt = IPU6_FW_ISYS_PIN_TYPE_RAW_SOC; - else -@@ -663,8 +756,8 @@ void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video *av, - - esd = media_entity_to_v4l2_subdev(av->stream->source_entity); - -- av->watermark.width = av->mpix.width; -- av->watermark.height = av->mpix.height; -+ av->watermark.width = ipu6_get_frame_width(&av->vfmt); -+ av->watermark.height = ipu6_get_frame_height(&av->vfmt); - av->watermark.sram_gran_shift = isys->pdata->ipdata->sram_gran_shift; - av->watermark.sram_gran_size = isys->pdata->ipdata->sram_gran_size; - -@@ -992,11 +1085,15 @@ static const struct v4l2_ioctl_ops ioctl_ops_mplane = { - .vidioc_querycap = ipu6_isys_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = ipu6_isys_vidioc_enum_fmt, - .vidioc_enum_framesizes = ipu6_isys_vidioc_enum_framesizes, -- .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap_mplane, -- .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap_mplane, -- .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap_mplane, -- .vidioc_reqbufs = vb2_ioctl_reqbufs, -- .vidioc_create_bufs = vb2_ioctl_create_bufs, -+ .vidioc_g_fmt_vid_cap_mplane = vidioc_get_format, -+ .vidioc_s_fmt_vid_cap_mplane = vidioc_set_format, -+ .vidioc_try_fmt_vid_cap_mplane = vidioc_try_format, -+ .vidioc_enum_fmt_meta_cap = ipu6_isys_vidioc_enum_fmt, -+ .vidioc_g_fmt_meta_cap = vidioc_get_format, -+ .vidioc_s_fmt_meta_cap = vidioc_set_format, -+ .vidioc_try_fmt_meta_cap = vidioc_try_format, -+ .vidioc_reqbufs = vidioc_request_qbufs, -+ .vidioc_create_bufs = vidioc_create_bufs, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, -@@ -1199,7 +1296,8 @@ int ipu6_isys_video_init(struct ipu6_isys_video *av) - - mutex_init(&av->mutex); - av->vdev.device_caps = V4L2_CAP_STREAMING | V4L2_CAP_IO_MC | -- V4L2_CAP_VIDEO_CAPTURE_MPLANE; -+ V4L2_CAP_VIDEO_CAPTURE_MPLANE | -+ V4L2_CAP_META_CAPTURE; - av->vdev.vfl_dir = VFL_DIR_RX; - - ret = ipu6_isys_queue_init(&av->aq); -@@ -1220,8 +1318,8 @@ int ipu6_isys_video_init(struct ipu6_isys_video *av) - av->vdev.queue = &av->aq.vbq; - av->vdev.lock = &av->mutex; - -- ipu6_isys_video_try_fmt_vid_mplane(av, &format.fmt.pix_mp); -- av->mpix = format.fmt.pix_mp; -+ ipu6_isys_video_try_fmt(av, &format); -+ av->vfmt = format; - - set_bit(V4L2_FL_USES_V4L2_FH, &av->vdev.flags); - video_set_drvdata(&av->vdev, av); -@@ -1251,3 +1349,52 @@ void ipu6_isys_video_cleanup(struct ipu6_isys_video *av) - media_entity_cleanup(&av->vdev.entity); - mutex_destroy(&av->mutex); - } -+ -+u32 ipu6_get_data_size(struct v4l2_format *vfmt, int plane) -+{ -+ if (vfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) -+ return vfmt->fmt.pix_mp.plane_fmt[plane].sizeimage; -+ else if (vfmt->type == V4L2_BUF_TYPE_META_CAPTURE) -+ return vfmt->fmt.meta.buffersize; -+ -+ WARN_ON_ONCE(1); -+ -+ return 0; -+} -+ -+u32 ipu6_get_bytes_per_line(struct v4l2_format *vfmt) -+{ -+ if (vfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) -+ return vfmt->fmt.pix_mp.plane_fmt[0].bytesperline; -+ else if (vfmt->type == V4L2_BUF_TYPE_META_CAPTURE) -+ return vfmt->fmt.meta.bytesperline; -+ -+ WARN_ON_ONCE(1); -+ -+ return 0; -+} -+ -+u32 ipu6_get_frame_width(struct v4l2_format *vfmt) -+{ -+ if (vfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) -+ return vfmt->fmt.pix_mp.width; -+ else if (vfmt->type == V4L2_BUF_TYPE_META_CAPTURE) -+ return vfmt->fmt.meta.width; -+ -+ WARN_ON_ONCE(1); -+ -+ return 0; -+} -+ -+u32 ipu6_get_frame_height(struct v4l2_format *vfmt) -+{ -+ if (vfmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) -+ return vfmt->fmt.pix_mp.height; -+ else if (vfmt->type == V4L2_BUF_TYPE_META_CAPTURE) -+ return vfmt->fmt.meta.height; -+ -+ WARN_ON_ONCE(1); -+ -+ return 0; -+} -+ -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h -index 21cd33c7e277..2634ec0fd68b 100644 ---- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.h -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.h -@@ -90,7 +90,7 @@ struct ipu6_isys_video { - struct mutex mutex; - struct media_pad pad; - struct video_device vdev; -- struct v4l2_pix_format_mplane mpix; -+ struct v4l2_format vfmt; - const struct ipu6_isys_pixelformat *pfmt; - struct ipu6_isys *isys; - struct ipu6_isys_stream *stream; -@@ -133,4 +133,9 @@ void ipu6_isys_configure_stream_watermark(struct ipu6_isys_video *av, - bool state); - void ipu6_isys_update_stream_watermark(struct ipu6_isys_video *av, bool state); - -+u32 ipu6_get_data_size(struct v4l2_format *vfmt, int plane); -+u32 ipu6_get_bytes_per_line(struct v4l2_format *vfmt); -+u32 ipu6_get_frame_width(struct v4l2_format *vfmt); -+u32 ipu6_get_frame_height(struct v4l2_format *vfmt); -+ - #endif /* IPU6_ISYS_VIDEO_H */ --- -2.43.2 - - -From 9a6fb311b81433ebbd8e0769bed19958a6a5a5f6 Mon Sep 17 00:00:00 2001 -From: Bingbu Cao <bingbu.cao@intel.com> -Date: Thu, 11 Jan 2024 14:55:31 +0800 -Subject: [PATCH 24/33] media: ipu6/isys: support new v4l2 subdev state APIs - -Add support for the upcoming v4l2-subdev API changes in kernel 6.8. -This patch is based on Sakari's branch: -<URL:https://git.linuxtv.org/sailus/media_tree.git/log/?h=metadata> - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Bingbu Cao <bingbu.cao@intel.com> ---- - drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 8 +++----- - .../media/pci/intel/ipu6/ipu6-isys-subdev.c | 19 +++++++++++-------- - .../media/pci/intel/ipu6/ipu6-isys-subdev.h | 2 -- - .../media/pci/intel/ipu6/ipu6-isys-video.c | 3 +-- - 4 files changed, 15 insertions(+), 17 deletions(-) - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c -index a6430d531129..6f258cf92fc1 100644 ---- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c -@@ -403,12 +403,11 @@ static int ipu6_isys_csi2_set_sel(struct v4l2_subdev *sd, - if (!sink_ffmt) - return -EINVAL; - -- src_ffmt = v4l2_subdev_state_get_stream_format(state, sel->pad, -- sel->stream); -+ src_ffmt = v4l2_subdev_state_get_format(state, sel->pad, sel->stream); - if (!src_ffmt) - return -EINVAL; - -- crop = v4l2_subdev_state_get_stream_crop(state, sel->pad, sel->stream); -+ crop = v4l2_subdev_state_get_crop(state, sel->pad, sel->stream); - if (!crop) - return -EINVAL; - -@@ -453,7 +452,7 @@ static int ipu6_isys_csi2_get_sel(struct v4l2_subdev *sd, - if (!sink_ffmt) - return -EINVAL; - -- crop = v4l2_subdev_state_get_stream_crop(state, sel->pad, sel->stream); -+ crop = v4l2_subdev_state_get_crop(state, sel->pad, sel->stream); - if (!crop) - return -EINVAL; - -@@ -480,7 +479,6 @@ static const struct v4l2_subdev_video_ops csi2_sd_video_ops = { - }; - - static const struct v4l2_subdev_pad_ops csi2_sd_pad_ops = { -- .init_cfg = ipu6_isys_subdev_init_cfg, - .get_fmt = v4l2_subdev_get_fmt, - .set_fmt = ipu6_isys_subdev_set_fmt, - .get_selection = ipu6_isys_csi2_get_sel, -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c -index 3c9263ac02a3..aeccd6f93986 100644 ---- a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c -@@ -156,8 +156,7 @@ int ipu6_isys_subdev_set_fmt(struct v4l2_subdev *sd, - format->format.field = V4L2_FIELD_NONE; - - /* Store the format and propagate it to the source pad. */ -- fmt = v4l2_subdev_state_get_stream_format(state, format->pad, -- format->stream); -+ fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream); - if (!fmt) - return -EINVAL; - -@@ -182,8 +181,7 @@ int ipu6_isys_subdev_set_fmt(struct v4l2_subdev *sd, - if (ret) - return -EINVAL; - -- crop = v4l2_subdev_state_get_stream_crop(state, other_pad, -- other_stream); -+ crop = v4l2_subdev_state_get_crop(state, other_pad, other_stream); - /* reset crop */ - crop->left = 0; - crop->top = 0; -@@ -241,7 +239,7 @@ int ipu6_isys_get_stream_pad_fmt(struct v4l2_subdev *sd, u32 pad, u32 stream, - return -EINVAL; - - state = v4l2_subdev_lock_and_get_active_state(sd); -- fmt = v4l2_subdev_state_get_stream_format(state, pad, stream); -+ fmt = v4l2_subdev_state_get_format(state, pad, stream); - if (fmt) - *format = *fmt; - v4l2_subdev_unlock_state(state); -@@ -259,7 +257,7 @@ int ipu6_isys_get_stream_pad_crop(struct v4l2_subdev *sd, u32 pad, u32 stream, - return -EINVAL; - - state = v4l2_subdev_lock_and_get_active_state(sd); -- rect = v4l2_subdev_state_get_stream_crop(state, pad, stream); -+ rect = v4l2_subdev_state_get_crop(state, pad, stream); - if (rect) - *crop = *rect; - v4l2_subdev_unlock_state(state); -@@ -291,8 +289,8 @@ u32 ipu6_isys_get_src_stream_by_src_pad(struct v4l2_subdev *sd, u32 pad) - return source_stream; - } - --int ipu6_isys_subdev_init_cfg(struct v4l2_subdev *sd, -- struct v4l2_subdev_state *state) -+static int ipu6_isys_subdev_init_state(struct v4l2_subdev *sd, -+ struct v4l2_subdev_state *state) - { - struct v4l2_subdev_route route = { - .sink_pad = 0, -@@ -317,6 +315,10 @@ int ipu6_isys_subdev_set_routing(struct v4l2_subdev *sd, - return subdev_set_routing(sd, state, routing); - } - -+static const struct v4l2_subdev_internal_ops ipu6_isys_subdev_internal_ops = { -+ .init_state = ipu6_isys_subdev_init_state, -+}; -+ - int ipu6_isys_subdev_init(struct ipu6_isys_subdev *asd, - const struct v4l2_subdev_ops *ops, - unsigned int nr_ctrls, -@@ -334,6 +336,7 @@ int ipu6_isys_subdev_init(struct ipu6_isys_subdev *asd, - V4L2_SUBDEV_FL_STREAMS; - asd->sd.owner = THIS_MODULE; - asd->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; -+ asd->sd.internal_ops = &ipu6_isys_subdev_internal_ops; - - asd->pad = devm_kcalloc(&asd->isys->adev->auxdev.dev, num_pads, - sizeof(*asd->pad), GFP_KERNEL); -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h -index adea2a55761d..f4e32b094b5b 100644 ---- a/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.h -@@ -46,8 +46,6 @@ int ipu6_isys_get_stream_pad_fmt(struct v4l2_subdev *sd, u32 pad, u32 stream, - struct v4l2_mbus_framefmt *format); - int ipu6_isys_get_stream_pad_crop(struct v4l2_subdev *sd, u32 pad, u32 stream, - struct v4l2_rect *crop); --int ipu6_isys_subdev_init_cfg(struct v4l2_subdev *sd, -- struct v4l2_subdev_state *state); - int ipu6_isys_subdev_set_routing(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - enum v4l2_subdev_format_whence which, -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -index 1a023bf1e1a6..62d4043fc2a1 100644 ---- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -@@ -389,8 +389,7 @@ static int link_validate(struct media_link *link) - - v4l2_subdev_lock_state(s_state); - -- s_fmt = v4l2_subdev_state_get_stream_format(s_state, s_pad->index, -- s_stream); -+ s_fmt = v4l2_subdev_state_get_format(s_state, s_pad->index, s_stream); - if (!s_fmt) { - dev_err(dev, "failed to get source pad format\n"); - goto unlock; --- -2.43.2 - - -From 53ca77877d2cc7ecc39bb0ef26a1871a1c26afd1 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Mon, 15 Jan 2024 15:57:06 +0100 -Subject: [PATCH 25/33] media: intel/ipu6: Disable packed bayer v4l2-buffer - formats on TGL - -Using CSI2 packing to store 10bpp bayer data in the v4l2-buffers does not -work on Tiger Lake when testing with an ov01a1s sensor. - -Disable packed bayer formats on Tiger Lake for now. - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - .../media/pci/intel/ipu6/ipu6-isys-video.c | 65 ++++++++++++------- - 1 file changed, 43 insertions(+), 22 deletions(-) - -diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -index 62d4043fc2a1..c971ffe0b948 100644 ---- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -@@ -61,6 +61,17 @@ const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = { - IPU6_FW_ISYS_FRAME_FORMAT_RAW8}, - {V4L2_PIX_FMT_SRGGB8, 8, 8, MEDIA_BUS_FMT_SRGGB8_1X8, - IPU6_FW_ISYS_FRAME_FORMAT_RAW8}, -+ {V4L2_PIX_FMT_UYVY, 16, 16, MEDIA_BUS_FMT_UYVY8_1X16, -+ IPU6_FW_ISYS_FRAME_FORMAT_UYVY}, -+ {V4L2_PIX_FMT_YUYV, 16, 16, MEDIA_BUS_FMT_YUYV8_1X16, -+ IPU6_FW_ISYS_FRAME_FORMAT_YUYV}, -+ {V4L2_PIX_FMT_RGB565, 16, 16, MEDIA_BUS_FMT_RGB565_1X16, -+ IPU6_FW_ISYS_FRAME_FORMAT_RGB565}, -+ {V4L2_PIX_FMT_BGR24, 24, 24, MEDIA_BUS_FMT_RGB888_1X24, -+ IPU6_FW_ISYS_FRAME_FORMAT_RGBA888}, -+}; -+ -+const struct ipu6_isys_pixelformat ipu6_isys_pfmts_packed[] = { - {V4L2_PIX_FMT_SBGGR12P, 12, 12, MEDIA_BUS_FMT_SBGGR12_1X12, - IPU6_FW_ISYS_FRAME_FORMAT_RAW12}, - {V4L2_PIX_FMT_SGBRG12P, 12, 12, MEDIA_BUS_FMT_SGBRG12_1X12, -@@ -77,19 +88,6 @@ const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = { - IPU6_FW_ISYS_FRAME_FORMAT_RAW10}, - {V4L2_PIX_FMT_SRGGB10P, 10, 10, MEDIA_BUS_FMT_SRGGB10_1X10, - IPU6_FW_ISYS_FRAME_FORMAT_RAW10}, -- {V4L2_PIX_FMT_UYVY, 16, 16, MEDIA_BUS_FMT_UYVY8_1X16, -- IPU6_FW_ISYS_FRAME_FORMAT_UYVY}, -- {V4L2_PIX_FMT_YUYV, 16, 16, MEDIA_BUS_FMT_YUYV8_1X16, -- IPU6_FW_ISYS_FRAME_FORMAT_YUYV}, -- {V4L2_PIX_FMT_RGB565, 16, 16, MEDIA_BUS_FMT_RGB565_1X16, -- IPU6_FW_ISYS_FRAME_FORMAT_RGB565}, -- {V4L2_PIX_FMT_BGR24, 24, 24, MEDIA_BUS_FMT_RGB888_1X24, -- IPU6_FW_ISYS_FRAME_FORMAT_RGBA888}, -- {V4L2_META_FMT_GENERIC_8, 8, 8, MEDIA_BUS_FMT_META_8, 0}, -- {V4L2_META_FMT_GENERIC_CSI2_10, 10, 10, MEDIA_BUS_FMT_META_10, 0}, -- {V4L2_META_FMT_GENERIC_CSI2_12, 12, 12, MEDIA_BUS_FMT_META_12, 0}, -- {V4L2_META_FMT_GENERIC_CSI2_16, 16, 16, MEDIA_BUS_FMT_META_16, 0}, -- {V4L2_META_FMT_GENERIC_CSI2_24, 24, 24, MEDIA_BUS_FMT_META_24, 0}, - }; - - static int video_open(struct file *file) -@@ -114,14 +112,27 @@ static int video_release(struct file *file) - return vb2_fop_release(file); - } - -+static const struct ipu6_isys_pixelformat * -+ipu6_isys_get_pixelformat_by_idx(unsigned int idx) -+{ -+ if (idx < ARRAY_SIZE(ipu6_isys_pfmts)) -+ return &ipu6_isys_pfmts[idx]; -+ -+ idx -= ARRAY_SIZE(ipu6_isys_pfmts); -+ -+ if (idx < ARRAY_SIZE(ipu6_isys_pfmts_packed)) -+ return &ipu6_isys_pfmts_packed[idx]; -+ -+ return NULL; -+} -+ - static const struct ipu6_isys_pixelformat * - ipu6_isys_get_pixelformat(u32 pixelformat) - { -+ const struct ipu6_isys_pixelformat *pfmt; - unsigned int i; - -- for (i = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { -- const struct ipu6_isys_pixelformat *pfmt = &ipu6_isys_pfmts[i]; -- -+ for (i = 0; (pfmt = ipu6_isys_get_pixelformat_by_idx(i)); i++) { - if (pfmt->pixelformat == pixelformat) - return pfmt; - } -@@ -143,24 +154,34 @@ int ipu6_isys_vidioc_querycap(struct file *file, void *fh, - int ipu6_isys_vidioc_enum_fmt(struct file *file, void *fh, - struct v4l2_fmtdesc *f) - { -- unsigned int i, found = 0; -+ struct ipu6_isys_video *av = video_drvdata(file); -+ const struct ipu6_isys_pixelformat *fmt; -+ unsigned int i, nfmts, found = 0; -+ -+ nfmts = ARRAY_SIZE(ipu6_isys_pfmts); -+ /* Disable packed formats on TGL for now, TGL has 8 CSI ports */ -+ if (av->isys->pdata->ipdata->csi2.nports != 8) -+ nfmts += ARRAY_SIZE(ipu6_isys_pfmts_packed); - -- if (f->index >= ARRAY_SIZE(ipu6_isys_pfmts)) -+ if (f->index >= nfmts) - return -EINVAL; - - if (!f->mbus_code) { -+ fmt = ipu6_isys_get_pixelformat_by_idx(f->index); - f->flags = 0; -- f->pixelformat = ipu6_isys_pfmts[f->index].pixelformat; -+ f->pixelformat = fmt->pixelformat; - return 0; - } - -- for (i = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { -- if (f->mbus_code != ipu6_isys_pfmts[i].code) -+ for (i = 0; i < nfmts; i++) { -+ fmt = ipu6_isys_get_pixelformat_by_idx(i); -+ -+ if (f->mbus_code != fmt->code) - continue; - - if (f->index == found) { - f->flags = 0; -- f->pixelformat = ipu6_isys_pfmts[i].pixelformat; -+ f->pixelformat = fmt->pixelformat; - return 0; - } - found++; --- -2.43.2 - - -From ed407043f03e9af2b09ab8ad449c2716ce7fde01 Mon Sep 17 00:00:00 2001 +From b5a82464677815dcbe6a06b0ee92ed065b1ec275 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Mon, 6 Nov 2023 12:13:42 +0100 -Subject: [PATCH 26/33] media: Add ov01a1s driver +Subject: [PATCH 1/3] media: Add ov01a1s driver Add ov01a1s driver from: https://github.com/intel/ipu6-drivers/ @@ -16257,10 +15,10 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> create mode 100644 drivers/media/i2c/ov01a1s.c diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig -index 4c3435921f19..08f934740980 100644 +index c6d3ee472d81..59e0d304bef2 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig -@@ -313,6 +313,15 @@ config VIDEO_OV01A10 +@@ -315,6 +315,15 @@ config VIDEO_OV01A10 To compile this driver as a module, choose M here: the module will be called ov01a10. @@ -17486,70 +1244,12 @@ index 000000000000..0dcce8b492b4 +MODULE_DESCRIPTION("OmniVision OV01A1S sensor driver"); +MODULE_LICENSE("GPL v2"); -- -2.43.2 - - -From 9f58ae728245ad7ac604737ab16781d7ccb2006e Mon Sep 17 00:00:00 2001 -From: Florian Klink <flokli@flokli.de> -Date: Sun, 17 Mar 2024 14:24:05 +0200 -Subject: [PATCH 27/33] ov01a1s.c: support Linux 6.8.0 - -Used https://github.com/intel/ipu6-drivers/pull/213 as an inspiration. ---- - drivers/media/i2c/ov01a1s.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/drivers/media/i2c/ov01a1s.c b/drivers/media/i2c/ov01a1s.c -index 0dcce8b492b4..923b12b2a948 100644 ---- a/drivers/media/i2c/ov01a1s.c -+++ b/drivers/media/i2c/ov01a1s.c -@@ -832,8 +832,10 @@ static int ov01a1s_set_format(struct v4l2_subdev *sd, - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) - *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; --#else -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) - *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; -+#else -+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format; - #endif - } else { - ov01a1s->cur_mode = mode; -@@ -871,9 +873,11 @@ static int ov01a1s_get_format(struct v4l2_subdev *sd, - #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) - fmt->format = *v4l2_subdev_get_try_format(&ov01a1s->sd, cfg, - fmt->pad); --#else -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) - fmt->format = *v4l2_subdev_get_try_format(&ov01a1s->sd, - sd_state, fmt->pad); -+#else -+ fmt->format = *v4l2_subdev_state_get_format(sd_state, fmt->pad); - #endif - else - ov01a1s_update_pad_format(ov01a1s->cur_mode, &fmt->format); -@@ -929,9 +933,12 @@ static int ov01a1s_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) - #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) - ov01a1s_update_pad_format(&supported_modes[0], - v4l2_subdev_get_try_format(sd, fh->pad, 0)); --#else -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) - ov01a1s_update_pad_format(&supported_modes[0], - v4l2_subdev_get_try_format(sd, fh->state, 0)); -+#else -+ ov01a1s_update_pad_format(&supported_modes[0], -+ v4l2_subdev_state_get_format(fh->state, 0)); - #endif - mutex_unlock(&ov01a1s->mutex); - --- -2.43.2 - +2.45.2 -From 80bee1ca899ebfa4126d1e69ea821a2c30aba00c Mon Sep 17 00:00:00 2001 +From 5cdf8b2b159a7cfef03b67b7fd51da967345090c Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Mon, 6 Nov 2023 12:33:56 +0100 -Subject: [PATCH 28/33] media: ov01a1s: Remove non upstream iVSC support +Subject: [PATCH 2/3] media: ov01a1s: Remove non upstream iVSC support Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- @@ -17557,7 +1257,7 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> 1 file changed, 71 deletions(-) diff --git a/drivers/media/i2c/ov01a1s.c b/drivers/media/i2c/ov01a1s.c -index 923b12b2a948..22b406bdeae9 100644 +index 0dcce8b492b4..c97c1a661022 100644 --- a/drivers/media/i2c/ov01a1s.c +++ b/drivers/media/i2c/ov01a1s.c @@ -17,9 +17,6 @@ @@ -17683,7 +1383,7 @@ index 923b12b2a948..22b406bdeae9 100644 return ret; } -@@ -1051,18 +992,6 @@ static int ov01a1s_parse_power(struct ov01a1s *ov01a1s) +@@ -1044,18 +985,6 @@ static int ov01a1s_parse_power(struct ov01a1s *ov01a1s) { int ret = 0; @@ -17703,375 +1403,61 @@ index 923b12b2a948..22b406bdeae9 100644 ret = ov01a1s_parse_gpio(ov01a1s); #elif IS_ENABLED(CONFIG_POWER_CTRL_LOGIC) -- -2.43.2 - - -From e624515c64d782b452a4676c1e117815267559ae Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Tue, 23 Jan 2024 14:58:35 +0100 -Subject: [PATCH 29/33] media: hi556: Return -EPROBE_DEFER if no endpoint is - found - -With ipu bridge, endpoints may only be created when ipu bridge has -initialised. This may happen after the sensor driver has first probed. - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/media/i2c/hi556.c | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - -diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c -index 38c77d515786..96bae9914d52 100644 ---- a/drivers/media/i2c/hi556.c -+++ b/drivers/media/i2c/hi556.c -@@ -1206,8 +1206,13 @@ static int hi556_check_hwcfg(struct device *dev) - int ret = 0; - unsigned int i, j; - -- if (!fwnode) -- return -ENXIO; -+ /* -+ * Sometimes the fwnode graph is initialized by the bridge driver, -+ * wait for this. -+ */ -+ ep = fwnode_graph_get_next_endpoint(fwnode, NULL); -+ if (!ep) -+ return -EPROBE_DEFER; - - ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk); - if (ret) { -@@ -1220,10 +1225,6 @@ static int hi556_check_hwcfg(struct device *dev) - return -EINVAL; - } - -- ep = fwnode_graph_get_next_endpoint(fwnode, NULL); -- if (!ep) -- return -ENXIO; -- - ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); - fwnode_handle_put(ep); - if (ret) --- -2.43.2 - - -From b127d1003050fb894ea764b600d5f399af413b68 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Tue, 23 Jan 2024 14:48:26 +0100 -Subject: [PATCH 30/33] media: hi556: Add support for reset GPIO - -On some ACPI platforms, such as Chromebooks the ACPI methods to -change the power-state (_PS0 and _PS3) fully take care of powering -on/off the sensor. - -On other ACPI platforms, such as e.g. various HP models with IPU6 + -hi556 sensor, the sensor driver must control the reset GPIO itself. - -Add support for having the driver control an optional reset GPIO. - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/media/i2c/hi556.c | 45 ++++++++++++++++++++++++++++++++++++++- - 1 file changed, 44 insertions(+), 1 deletion(-) - -diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c -index 96bae9914d52..f5a39b83598b 100644 ---- a/drivers/media/i2c/hi556.c -+++ b/drivers/media/i2c/hi556.c -@@ -4,6 +4,7 @@ - #include <asm/unaligned.h> - #include <linux/acpi.h> - #include <linux/delay.h> -+#include <linux/gpio/consumer.h> - #include <linux/i2c.h> - #include <linux/module.h> - #include <linux/pm_runtime.h> -@@ -633,6 +634,9 @@ struct hi556 { - struct v4l2_ctrl *hblank; - struct v4l2_ctrl *exposure; - -+ /* GPIOs, clocks, etc. */ -+ struct gpio_desc *reset_gpio; -+ - /* Current mode */ - const struct hi556_mode *cur_mode; - -@@ -1276,6 +1280,25 @@ static void hi556_remove(struct i2c_client *client) - mutex_destroy(&hi556->mutex); - } - -+static int hi556_suspend(struct device *dev) -+{ -+ struct v4l2_subdev *sd = dev_get_drvdata(dev); -+ struct hi556 *hi556 = to_hi556(sd); -+ -+ gpiod_set_value_cansleep(hi556->reset_gpio, 1); -+ return 0; -+} -+ -+static int hi556_resume(struct device *dev) -+{ -+ struct v4l2_subdev *sd = dev_get_drvdata(dev); -+ struct hi556 *hi556 = to_hi556(sd); -+ -+ gpiod_set_value_cansleep(hi556->reset_gpio, 0); -+ usleep_range(5000, 5500); -+ return 0; -+} -+ - static int hi556_probe(struct i2c_client *client) - { - struct hi556 *hi556; -@@ -1295,12 +1318,24 @@ static int hi556_probe(struct i2c_client *client) - - v4l2_i2c_subdev_init(&hi556->sd, client, &hi556_subdev_ops); - -+ hi556->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", -+ GPIOD_OUT_HIGH); -+ if (IS_ERR(hi556->reset_gpio)) -+ return dev_err_probe(&client->dev, PTR_ERR(hi556->reset_gpio), -+ "failed to get reset GPIO\n"); -+ - full_power = acpi_dev_state_d0(&client->dev); - if (full_power) { -+ /* Ensure non ACPI managed resources are enabled */ -+ ret = hi556_resume(&client->dev); -+ if (ret) -+ return dev_err_probe(&client->dev, ret, -+ "failed to power on sensor\n"); -+ - ret = hi556_identify_module(hi556); - if (ret) { - dev_err(&client->dev, "failed to find sensor: %d", ret); -- return ret; -+ goto probe_error_power_off; - } - } - -@@ -1345,9 +1380,16 @@ static int hi556_probe(struct i2c_client *client) - v4l2_ctrl_handler_free(hi556->sd.ctrl_handler); - mutex_destroy(&hi556->mutex); - -+probe_error_power_off: -+ if (full_power) -+ hi556_suspend(&client->dev); -+ - return ret; - } - -+static DEFINE_RUNTIME_DEV_PM_OPS(hi556_pm_ops, hi556_suspend, hi556_resume, -+ NULL); -+ - #ifdef CONFIG_ACPI - static const struct acpi_device_id hi556_acpi_ids[] = { - {"INT3537"}, -@@ -1361,6 +1403,7 @@ static struct i2c_driver hi556_i2c_driver = { - .driver = { - .name = "hi556", - .acpi_match_table = ACPI_PTR(hi556_acpi_ids), -+ .pm = pm_sleep_ptr(&hi556_pm_ops), - }, - .probe = hi556_probe, - .remove = hi556_remove, --- -2.43.2 - - -From ee651202ba2ca38da067b5379edd7b4f339cf7a8 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Tue, 23 Jan 2024 14:54:22 +0100 -Subject: [PATCH 31/33] media: hi556: Add support for external clock - -On some ACPI platforms, such as Chromebooks the ACPI methods to -change the power-state (_PS0 and _PS3) fully take care of powering -on/off the sensor. - -On other ACPI platforms, such as e.g. various HP models with IPU6 + -hi556 sensor, the sensor driver must control the sensor's clock itself. - -Add support for having the driver control an optional clock. - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/media/i2c/hi556.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c -index f5a39b83598b..b783e0f56687 100644 ---- a/drivers/media/i2c/hi556.c -+++ b/drivers/media/i2c/hi556.c -@@ -3,6 +3,7 @@ - - #include <asm/unaligned.h> - #include <linux/acpi.h> -+#include <linux/clk.h> - #include <linux/delay.h> - #include <linux/gpio/consumer.h> - #include <linux/i2c.h> -@@ -636,6 +637,7 @@ struct hi556 { - - /* GPIOs, clocks, etc. */ - struct gpio_desc *reset_gpio; -+ struct clk *clk; - - /* Current mode */ - const struct hi556_mode *cur_mode; -@@ -1286,6 +1288,7 @@ static int hi556_suspend(struct device *dev) - struct hi556 *hi556 = to_hi556(sd); - - gpiod_set_value_cansleep(hi556->reset_gpio, 1); -+ clk_disable_unprepare(hi556->clk); - return 0; - } - -@@ -1293,6 +1296,11 @@ static int hi556_resume(struct device *dev) - { - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct hi556 *hi556 = to_hi556(sd); -+ int ret; -+ -+ ret = clk_prepare_enable(hi556->clk); -+ if (ret) -+ return ret; - - gpiod_set_value_cansleep(hi556->reset_gpio, 0); - usleep_range(5000, 5500); -@@ -1324,6 +1332,11 @@ static int hi556_probe(struct i2c_client *client) - return dev_err_probe(&client->dev, PTR_ERR(hi556->reset_gpio), - "failed to get reset GPIO\n"); - -+ hi556->clk = devm_clk_get_optional(&client->dev, "clk"); -+ if (IS_ERR(hi556->clk)) -+ return dev_err_probe(&client->dev, PTR_ERR(hi556->clk), -+ "failed to get clock\n"); -+ - full_power = acpi_dev_state_d0(&client->dev); - if (full_power) { - /* Ensure non ACPI managed resources are enabled */ --- -2.43.2 - - -From 16be71996d451b8137ba63070e760448814c11a1 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Wed, 24 Jan 2024 18:45:02 +0100 -Subject: [PATCH 32/33] media: hi556: Add support for avdd regulator - -On some ACPI platforms, such as Chromebooks the ACPI methods to -change the power-state (_PS0 and _PS3) fully take care of powering -on/off the sensor. - -On other ACPI platforms, such as e.g. various HP models with IPU6 + -hi556 sensor, the sensor driver must control the avdd regulator itself. - -Add support for having the driver control the sensor's avdd regulator. -Note this relies on the regulator-core providing a dummy regulator -(which it does by default) on platforms where Linux is not aware of -the avdd regulator. - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/media/i2c/hi556.c | 24 ++++++++++++++++++++++++ - 1 file changed, 24 insertions(+) - -diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c -index b783e0f56687..5641c249d4b1 100644 ---- a/drivers/media/i2c/hi556.c -+++ b/drivers/media/i2c/hi556.c -@@ -9,6 +9,7 @@ - #include <linux/i2c.h> - #include <linux/module.h> - #include <linux/pm_runtime.h> -+#include <linux/regulator/consumer.h> - #include <media/v4l2-ctrls.h> - #include <media/v4l2-device.h> - #include <media/v4l2-fwnode.h> -@@ -638,6 +639,7 @@ struct hi556 { - /* GPIOs, clocks, etc. */ - struct gpio_desc *reset_gpio; - struct clk *clk; -+ struct regulator *avdd; - - /* Current mode */ - const struct hi556_mode *cur_mode; -@@ -1286,8 +1288,17 @@ static int hi556_suspend(struct device *dev) - { - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct hi556 *hi556 = to_hi556(sd); -+ int ret; - - gpiod_set_value_cansleep(hi556->reset_gpio, 1); -+ -+ ret = regulator_disable(hi556->avdd); -+ if (ret) { -+ dev_err(dev, "failed to disable avdd: %d\n", ret); -+ gpiod_set_value_cansleep(hi556->reset_gpio, 0); -+ return ret; -+ } -+ - clk_disable_unprepare(hi556->clk); - return 0; - } -@@ -1302,6 +1313,13 @@ static int hi556_resume(struct device *dev) - if (ret) - return ret; - -+ ret = regulator_enable(hi556->avdd); -+ if (ret) { -+ dev_err(dev, "failed to enable avdd: %d\n", ret); -+ clk_disable_unprepare(hi556->clk); -+ return ret; -+ } -+ - gpiod_set_value_cansleep(hi556->reset_gpio, 0); - usleep_range(5000, 5500); - return 0; -@@ -1337,6 +1355,12 @@ static int hi556_probe(struct i2c_client *client) - return dev_err_probe(&client->dev, PTR_ERR(hi556->clk), - "failed to get clock\n"); - -+ /* The regulator core will provide a "dummy" regulator if necessary */ -+ hi556->avdd = devm_regulator_get(&client->dev, "avdd"); -+ if (IS_ERR(hi556->avdd)) -+ return dev_err_probe(&client->dev, PTR_ERR(hi556->avdd), -+ "failed to get avdd regulator\n"); -+ - full_power = acpi_dev_state_d0(&client->dev); - if (full_power) { - /* Ensure non ACPI managed resources are enabled */ --- -2.43.2 - +2.45.2 -From 6bd6e73829cf264120f629c88c552c4eb59c7eee Mon Sep 17 00:00:00 2001 +From 5ccd06ac4351f3eb8146c1109446fc80aeaa873f Mon Sep 17 00:00:00 2001 From: Florian Klink <flokli@flokli.de> -Date: Sun, 17 Mar 2024 17:07:53 +0200 -Subject: [PATCH 33/33] media: intel/ipu6: fix firmware paths +Date: Sun, 17 Mar 2024 14:24:05 +0200 +Subject: [PATCH 3/3] ov01a1s.c: support Linux 6.8.0 -linux-firmware ships them in intel/ipu, not intel/. +Used https://github.com/intel/ipu6-drivers/pull/213 as an inspiration. --- - drivers/media/pci/intel/ipu6/ipu6.h | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) + drivers/media/i2c/ov01a1s.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) -diff --git a/drivers/media/pci/intel/ipu6/ipu6.h b/drivers/media/pci/intel/ipu6/ipu6.h -index 04e7e7e61ca5..da8a95a9edf8 100644 ---- a/drivers/media/pci/intel/ipu6/ipu6.h -+++ b/drivers/media/pci/intel/ipu6/ipu6.h -@@ -24,10 +24,10 @@ struct ipu6_bus_device; - #define IPU6_NAME "intel-ipu6" - #define IPU6_MEDIA_DEV_MODEL_NAME "ipu6" - --#define IPU6SE_FIRMWARE_NAME "intel/ipu6se_fw.bin" --#define IPU6EP_FIRMWARE_NAME "intel/ipu6ep_fw.bin" --#define IPU6_FIRMWARE_NAME "intel/ipu6_fw.bin" --#define IPU6EPMTL_FIRMWARE_NAME "intel/ipu6epmtl_fw.bin" -+#define IPU6SE_FIRMWARE_NAME "intel/ipu/ipu6se_fw.bin" -+#define IPU6EP_FIRMWARE_NAME "intel/ipu/ipu6ep_fw.bin" -+#define IPU6_FIRMWARE_NAME "intel/ipu/ipu6_fw.bin" -+#define IPU6EPMTL_FIRMWARE_NAME "intel/ipu/ipu6epmtl_fw.bin" +diff --git a/drivers/media/i2c/ov01a1s.c b/drivers/media/i2c/ov01a1s.c +index c97c1a661022..22b406bdeae9 100644 +--- a/drivers/media/i2c/ov01a1s.c ++++ b/drivers/media/i2c/ov01a1s.c +@@ -773,8 +773,10 @@ static int ov01a1s_set_format(struct v4l2_subdev *sd, + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; +-#else ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) + *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; ++#else ++ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format; + #endif + } else { + ov01a1s->cur_mode = mode; +@@ -812,9 +814,11 @@ static int ov01a1s_get_format(struct v4l2_subdev *sd, + #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + fmt->format = *v4l2_subdev_get_try_format(&ov01a1s->sd, cfg, + fmt->pad); +-#else ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) + fmt->format = *v4l2_subdev_get_try_format(&ov01a1s->sd, + sd_state, fmt->pad); ++#else ++ fmt->format = *v4l2_subdev_state_get_format(sd_state, fmt->pad); + #endif + else + ov01a1s_update_pad_format(ov01a1s->cur_mode, &fmt->format); +@@ -870,9 +874,12 @@ static int ov01a1s_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) + #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + ov01a1s_update_pad_format(&supported_modes[0], + v4l2_subdev_get_try_format(sd, fh->pad, 0)); +-#else ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) + ov01a1s_update_pad_format(&supported_modes[0], + v4l2_subdev_get_try_format(sd, fh->state, 0)); ++#else ++ ov01a1s_update_pad_format(&supported_modes[0], ++ v4l2_subdev_state_get_format(fh->state, 0)); + #endif + mutex_unlock(&ov01a1s->mutex); - enum ipu6_version { - IPU6_VER_INVALID = 0, -- -2.43.2 +2.45.2 diff --git a/users/flokli/ipu6-softisp/libcamera/0016-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch b/users/flokli/ipu6-softisp/libcamera/0001-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch index 724b67033ff4..5340901edb94 100644 --- a/users/flokli/ipu6-softisp/libcamera/0016-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch +++ b/users/flokli/ipu6-softisp/libcamera/0001-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch @@ -1,7 +1,7 @@ -From e9580d30a1a79fce1ebd72ae74ceb4a3d1cf8fbb Mon Sep 17 00:00:00 2001 +From 0e94883c2f4f6164d40d4ea355449ba0864dc4f9 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Tue, 19 Dec 2023 11:16:26 +0100 -Subject: [PATCH 16/21] libcamera: Add support for IGIG_GBGR_IGIG_GRGB bayer +Subject: [PATCH 1/3] libcamera: Add support for IGIG_GBGR_IGIG_GRGB bayer order DNU The ov01a1s sensor has the following bayer pattern (4x4 tile repeating): @@ -23,15 +23,15 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> include/linux/media-bus-format.h | 4 +++- include/linux/videodev2.h | 3 +++ src/libcamera/bayer_format.cpp | 5 +++++ - src/libcamera/camera_sensor.cpp | 3 +++ src/libcamera/formats.cpp | 20 ++++++++++++++++++++ src/libcamera/formats.yaml | 5 +++++ + src/libcamera/sensor/camera_sensor.cpp | 3 +++ src/libcamera/v4l2_pixelformat.cpp | 4 ++++ - src/libcamera/v4l2_subdevice.cpp | 1 + - 10 files changed, 48 insertions(+), 2 deletions(-) + src/libcamera/v4l2_subdevice.cpp | 7 +++++++ + 10 files changed, 54 insertions(+), 2 deletions(-) diff --git a/include/libcamera/internal/bayer_format.h b/include/libcamera/internal/bayer_format.h -index 78ba3969..e77106c3 100644 +index 5c14bb5f..49b7f417 100644 --- a/include/libcamera/internal/bayer_format.h +++ b/include/libcamera/internal/bayer_format.h @@ -27,7 +27,8 @@ public: @@ -45,10 +45,10 @@ index 78ba3969..e77106c3 100644 enum class Packing : uint16_t { diff --git a/include/linux/drm_fourcc.h b/include/linux/drm_fourcc.h -index 1496e097..750ae8c9 100644 +index b4e1a092..070696bc 100644 --- a/include/linux/drm_fourcc.h +++ b/include/linux/drm_fourcc.h -@@ -405,6 +405,8 @@ extern "C" { +@@ -447,6 +447,8 @@ extern "C" { #define DRM_FORMAT_SGRBG10 fourcc_code('B', 'A', '1', '0') #define DRM_FORMAT_SGBRG10 fourcc_code('G', 'B', '1', '0') #define DRM_FORMAT_SBGGR10 fourcc_code('B', 'G', '1', '0') @@ -58,19 +58,19 @@ index 1496e097..750ae8c9 100644 /* 12-bit Bayer formats */ #define DRM_FORMAT_SRGGB12 fourcc_code('R', 'G', '1', '2') diff --git a/include/linux/media-bus-format.h b/include/linux/media-bus-format.h -index 0dfc11ee..c5fbda0e 100644 +index f05f747e..1b4a65db 100644 --- a/include/linux/media-bus-format.h +++ b/include/linux/media-bus-format.h -@@ -112,7 +112,7 @@ +@@ -121,7 +121,7 @@ #define MEDIA_BUS_FMT_YUV16_1X48 0x202a #define MEDIA_BUS_FMT_UYYVYY16_0_5X48 0x202b -/* Bayer - next is 0x3021 */ -+/* Bayer - next is 0x3022 */ ++/* Bayer - next is 0x3022 */ #define MEDIA_BUS_FMT_SBGGR8_1X8 0x3001 #define MEDIA_BUS_FMT_SGBRG8_1X8 0x3013 #define MEDIA_BUS_FMT_SGRBG8_1X8 0x3002 -@@ -145,6 +145,8 @@ +@@ -154,6 +154,8 @@ #define MEDIA_BUS_FMT_SGBRG16_1X16 0x301e #define MEDIA_BUS_FMT_SGRBG16_1X16 0x301f #define MEDIA_BUS_FMT_SRGGB16_1X16 0x3020 @@ -80,10 +80,10 @@ index 0dfc11ee..c5fbda0e 100644 /* JPEG compressed formats - next is 0x4002 */ #define MEDIA_BUS_FMT_JPEG_1X8 0x4001 diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h -index bfb315d6..13c6c9d3 100644 +index 0b5482a0..a51d6755 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h -@@ -678,6 +678,9 @@ struct v4l2_pix_format { +@@ -704,6 +704,9 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_SGBRG16 v4l2_fourcc('G', 'B', '1', '6') /* 16 GBGB.. RGRG.. */ #define V4L2_PIX_FMT_SGRBG16 v4l2_fourcc('G', 'R', '1', '6') /* 16 GRGR.. BGBG.. */ #define V4L2_PIX_FMT_SRGGB16 v4l2_fourcc('R', 'G', '1', '6') /* 16 RGRG.. GBGB.. */ @@ -94,10 +94,10 @@ index bfb315d6..13c6c9d3 100644 /* HSV formats */ #define V4L2_PIX_FMT_HSV24 v4l2_fourcc('H', 'S', 'V', '3') diff --git a/src/libcamera/bayer_format.cpp b/src/libcamera/bayer_format.cpp -index 3bf15fb4..ae227540 100644 +index 014f716d..325887a2 100644 --- a/src/libcamera/bayer_format.cpp +++ b/src/libcamera/bayer_format.cpp -@@ -108,6 +108,8 @@ const std::map<BayerFormat, Formats, BayerFormatComparator> bayerToFormat{ +@@ -112,6 +112,8 @@ const std::map<BayerFormat, Formats, BayerFormatComparator> bayerToFormat{ { formats::SGRBG10, V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10) } }, { { BayerFormat::RGGB, 10, BayerFormat::Packing::None }, { formats::SRGGB10, V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10) } }, @@ -106,7 +106,7 @@ index 3bf15fb4..ae227540 100644 { { BayerFormat::BGGR, 10, BayerFormat::Packing::CSI2 }, { formats::SBGGR10_CSI2P, V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P) } }, { { BayerFormat::GBRG, 10, BayerFormat::Packing::CSI2 }, -@@ -116,6 +118,8 @@ const std::map<BayerFormat, Formats, BayerFormatComparator> bayerToFormat{ +@@ -120,6 +122,8 @@ const std::map<BayerFormat, Formats, BayerFormatComparator> bayerToFormat{ { formats::SGRBG10_CSI2P, V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10P) } }, { { BayerFormat::RGGB, 10, BayerFormat::Packing::CSI2 }, { formats::SRGGB10_CSI2P, V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P) } }, @@ -115,7 +115,7 @@ index 3bf15fb4..ae227540 100644 { { BayerFormat::BGGR, 10, BayerFormat::Packing::IPU3 }, { formats::SBGGR10_IPU3, V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SBGGR10) } }, { { BayerFormat::GBRG, 10, BayerFormat::Packing::IPU3 }, -@@ -193,6 +197,7 @@ const std::unordered_map<unsigned int, BayerFormat> mbusCodeToBayer{ +@@ -211,6 +215,7 @@ const std::unordered_map<unsigned int, BayerFormat> mbusCodeToBayer{ { MEDIA_BUS_FMT_SGBRG10_1X10, { BayerFormat::GBRG, 10, BayerFormat::Packing::None } }, { MEDIA_BUS_FMT_SGRBG10_1X10, { BayerFormat::GRBG, 10, BayerFormat::Packing::None } }, { MEDIA_BUS_FMT_SRGGB10_1X10, { BayerFormat::RGGB, 10, BayerFormat::Packing::None } }, @@ -123,25 +123,11 @@ index 3bf15fb4..ae227540 100644 { MEDIA_BUS_FMT_SBGGR12_1X12, { BayerFormat::BGGR, 12, BayerFormat::Packing::None } }, { MEDIA_BUS_FMT_SGBRG12_1X12, { BayerFormat::GBRG, 12, BayerFormat::Packing::None } }, { MEDIA_BUS_FMT_SGRBG12_1X12, { BayerFormat::GRBG, 12, BayerFormat::Packing::None } }, -diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp -index 0ef78d9c..f19f72ea 100644 ---- a/src/libcamera/camera_sensor.cpp -+++ b/src/libcamera/camera_sensor.cpp -@@ -510,6 +510,9 @@ int CameraSensor::initProperties() - case BayerFormat::MONO: - cfa = properties::draft::MONO; - break; -+ case BayerFormat::IGIG_GBGR_IGIG_GRGB: -+ cfa = properties::draft::RGB; -+ break; - } - - properties_.set(properties::draft::ColorFilterArrangement, cfa); diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp -index 447e6238..aef7d598 100644 +index cf41f2c2..13ac3253 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp -@@ -599,6 +599,16 @@ const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{ +@@ -639,6 +639,16 @@ const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{ .pixelsPerGroup = 2, .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, } }, @@ -158,7 +144,7 @@ index 447e6238..aef7d598 100644 { formats::SBGGR10_CSI2P, { .name = "SBGGR10_CSI2P", .format = formats::SBGGR10_CSI2P, -@@ -639,6 +649,16 @@ const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{ +@@ -679,6 +689,16 @@ const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{ .pixelsPerGroup = 4, .planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }}, } }, @@ -176,10 +162,10 @@ index 447e6238..aef7d598 100644 .name = "SBGGR12", .format = formats::SBGGR12, diff --git a/src/libcamera/formats.yaml b/src/libcamera/formats.yaml -index 539ac0b3..0786a900 100644 +index fe027a7c..394f980c 100644 --- a/src/libcamera/formats.yaml +++ b/src/libcamera/formats.yaml -@@ -100,6 +100,8 @@ formats: +@@ -107,6 +107,8 @@ formats: fourcc: DRM_FORMAT_SGBRG10 - SBGGR10: fourcc: DRM_FORMAT_SBGGR10 @@ -188,7 +174,7 @@ index 539ac0b3..0786a900 100644 - SRGGB12: fourcc: DRM_FORMAT_SRGGB12 -@@ -144,6 +146,9 @@ formats: +@@ -151,6 +153,9 @@ formats: - SBGGR10_CSI2P: fourcc: DRM_FORMAT_SBGGR10 mod: MIPI_FORMAT_MOD_CSI2_PACKED @@ -198,11 +184,25 @@ index 539ac0b3..0786a900 100644 - SRGGB12_CSI2P: fourcc: DRM_FORMAT_SRGGB12 +diff --git a/src/libcamera/sensor/camera_sensor.cpp b/src/libcamera/sensor/camera_sensor.cpp +index c6d7f801..77c396b9 100644 +--- a/src/libcamera/sensor/camera_sensor.cpp ++++ b/src/libcamera/sensor/camera_sensor.cpp +@@ -526,6 +526,9 @@ int CameraSensor::initProperties() + case BayerFormat::MONO: + cfa = properties::draft::MONO; + break; ++ case BayerFormat::IGIG_GBGR_IGIG_GRGB: ++ cfa = properties::draft::RGB; ++ break; + } + + properties_.set(properties::draft::ColorFilterArrangement, cfa); diff --git a/src/libcamera/v4l2_pixelformat.cpp b/src/libcamera/v4l2_pixelformat.cpp -index 5551c62e..53078d99 100644 +index 70568335..a2fbd644 100644 --- a/src/libcamera/v4l2_pixelformat.cpp +++ b/src/libcamera/v4l2_pixelformat.cpp -@@ -153,6 +153,8 @@ const std::map<V4L2PixelFormat, V4L2PixelFormat::Info> vpf2pf{ +@@ -159,6 +159,8 @@ const std::map<V4L2PixelFormat, V4L2PixelFormat::Info> vpf2pf{ { formats::SGRBG10, "10-bit Bayer GRGR/BGBG" } }, { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10), { formats::SRGGB10, "10-bit Bayer RGRG/GBGB" } }, @@ -211,7 +211,7 @@ index 5551c62e..53078d99 100644 { V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P), { formats::SBGGR10_CSI2P, "10-bit Bayer BGBG/GRGR Packed" } }, { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10P), -@@ -161,6 +163,8 @@ const std::map<V4L2PixelFormat, V4L2PixelFormat::Info> vpf2pf{ +@@ -167,6 +169,8 @@ const std::map<V4L2PixelFormat, V4L2PixelFormat::Info> vpf2pf{ { formats::SGRBG10_CSI2P, "10-bit Bayer GRGR/BGBG Packed" } }, { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P), { formats::SRGGB10_CSI2P, "10-bit Bayer RGRG/GBGB Packed" } }, @@ -221,17 +221,23 @@ index 5551c62e..53078d99 100644 { formats::SBGGR12, "12-bit Bayer BGBG/GRGR" } }, { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12), diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp -index 15e8206a..4ad37aaf 100644 +index 6da77775..0ba8c0de 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp -@@ -128,6 +128,7 @@ const std::map<uint32_t, V4L2SubdeviceFormatInfo> formatInfoMap = { - { MEDIA_BUS_FMT_SGBRG10_1X10, { 10, "SGBRG10_1X10", PixelFormatInfo::ColourEncodingRAW } }, - { MEDIA_BUS_FMT_SGRBG10_1X10, { 10, "SGRBG10_1X10", PixelFormatInfo::ColourEncodingRAW } }, - { MEDIA_BUS_FMT_SRGGB10_1X10, { 10, "SRGGB10_1X10", PixelFormatInfo::ColourEncodingRAW } }, -+ { MEDIA_BUS_FMT_SIGIG_GBGR_IGIG_GRGB10_1X10, { 10, "SIGIG_GBGR_IGIG_GRGB10_1X10", PixelFormatInfo::ColourEncodingRAW } }, - { MEDIA_BUS_FMT_SBGGR12_1X12, { 12, "SBGGR12_1X12", PixelFormatInfo::ColourEncodingRAW } }, - { MEDIA_BUS_FMT_SGBRG12_1X12, { 12, "SGBRG12_1X12", PixelFormatInfo::ColourEncodingRAW } }, - { MEDIA_BUS_FMT_SGRBG12_1X12, { 12, "SGRBG12_1X12", PixelFormatInfo::ColourEncodingRAW } }, +@@ -595,6 +595,13 @@ const std::map<uint32_t, MediaBusFormatInfo> mediaBusFormatInfo{ + .bitsPerPixel = 10, + .colourEncoding = PixelFormatInfo::ColourEncodingRAW, + } }, ++ { MEDIA_BUS_FMT_SIGIG_GBGR_IGIG_GRGB10_1X10, { ++ .name = "SIGIG_GBGR_IGIG_GRGB10_1X10", ++ .code = MEDIA_BUS_FMT_SIGIG_GBGR_IGIG_GRGB10_1X10, ++ .type = MediaBusFormatInfo::Type::Image, ++ .bitsPerPixel = 10, ++ .colourEncoding = PixelFormatInfo::ColourEncodingRAW, ++ } }, + { MEDIA_BUS_FMT_SBGGR12_1X12, { + .name = "SBGGR12_1X12", + .code = MEDIA_BUS_FMT_SBGGR12_1X12, -- -2.43.2 +2.45.2 diff --git a/users/flokli/ipu6-softisp/libcamera/0001-libcamera-pipeline-simple-fix-size-adjustment-in-val.patch b/users/flokli/ipu6-softisp/libcamera/0001-libcamera-pipeline-simple-fix-size-adjustment-in-val.patch deleted file mode 100644 index b640ddaa24cd..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0001-libcamera-pipeline-simple-fix-size-adjustment-in-val.patch +++ /dev/null @@ -1,82 +0,0 @@ -From d86746fc1739f678e4bafe43f5047cba9b6b053e Mon Sep 17 00:00:00 2001 -From: Andrey Konovalov <andrey.konovalov@linaro.org> -Date: Mon, 11 Mar 2024 15:15:05 +0100 -Subject: [PATCH 01/21] libcamera: pipeline: simple: fix size adjustment in - validate() - -SimpleCameraConfiguration::validate() adjusts the configuration of its -streams (if the size is not in the outputSizes) to the captureSize. But -the captureSize itself can be not in the outputSizes, and then the -adjusted configuration won't be valid resulting in camera configuration -failure. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - src/libcamera/pipeline/simple/simple.cpp | 37 ++++++++++++++++++++++-- - 1 file changed, 35 insertions(+), 2 deletions(-) - -diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp -index 911051b2..a84f6760 100644 ---- a/src/libcamera/pipeline/simple/simple.cpp -+++ b/src/libcamera/pipeline/simple/simple.cpp -@@ -881,6 +881,30 @@ SimpleCameraConfiguration::SimpleCameraConfiguration(Camera *camera, - { - } - -+namespace { -+ -+static Size adjustSize(const Size &requestedSize, const SizeRange &supportedSizes) -+{ -+ ASSERT(supportedSizes.min <= supportedSizes.max); -+ -+ if (supportedSizes.min == supportedSizes.max) -+ return supportedSizes.max; -+ -+ unsigned int hStep = supportedSizes.hStep; -+ unsigned int vStep = supportedSizes.vStep; -+ -+ if (hStep == 0) -+ hStep = supportedSizes.max.width - supportedSizes.min.width; -+ if (vStep == 0) -+ vStep = supportedSizes.max.height - supportedSizes.min.height; -+ -+ Size adjusted = requestedSize.boundedTo(supportedSizes.max).expandedTo(supportedSizes.min); -+ -+ return adjusted.shrunkBy(supportedSizes.min).alignedDownTo(hStep, vStep).grownBy(supportedSizes.min); -+} -+ -+} /* namespace */ -+ - CameraConfiguration::Status SimpleCameraConfiguration::validate() - { - const CameraSensor *sensor = data_->sensor_.get(); -@@ -997,10 +1021,19 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() - } - - if (!pipeConfig_->outputSizes.contains(cfg.size)) { -+ Size adjustedSize = pipeConfig_->captureSize; -+ /* -+ * The converter (when present) may not be able to output -+ * a size identical to its input size. The capture size is thus -+ * not guaranteed to be a valid output size. In such cases, use -+ * the smaller valid output size closest to the requested. -+ */ -+ if (!pipeConfig_->outputSizes.contains(adjustedSize)) -+ adjustedSize = adjustSize(cfg.size, pipeConfig_->outputSizes); - LOG(SimplePipeline, Debug) - << "Adjusting size from " << cfg.size -- << " to " << pipeConfig_->captureSize; -- cfg.size = pipeConfig_->captureSize; -+ << " to " << adjustedSize; -+ cfg.size = adjustedSize; - status = Adjusted; - } - --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0002-libcamera-internal-Move-dma_heaps.-h-cpp-to-common-d.patch b/users/flokli/ipu6-softisp/libcamera/0002-libcamera-internal-Move-dma_heaps.-h-cpp-to-common-d.patch deleted file mode 100644 index 450a0a21f19a..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0002-libcamera-internal-Move-dma_heaps.-h-cpp-to-common-d.patch +++ /dev/null @@ -1,350 +0,0 @@ -From 96e50c6a43352a9cb81d558fea27e580f2b26585 Mon Sep 17 00:00:00 2001 -From: Andrey Konovalov <andrey.konovalov@linaro.org> -Date: Mon, 11 Mar 2024 15:15:06 +0100 -Subject: [PATCH 02/21] libcamera: internal: Move dma_heaps.[h, cpp] to common - directories - -DmaHeap class is useful outside the RPi pipeline handler too. - -Move dma_heaps.h and dma_heaps.cpp to common directories. Update -the build files and RPi vc4 pipeline handler accordingly. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> -Reviewed-by: Naushir Patuck <naush@raspberrypi.com> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> ---- - .../libcamera/internal}/dma_heaps.h | 4 - - include/libcamera/internal/meson.build | 1 + - src/libcamera/dma_heaps.cpp | 127 ++++++++++++++++++ - src/libcamera/meson.build | 1 + - src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp | 90 ------------- - src/libcamera/pipeline/rpi/vc4/meson.build | 1 - - src/libcamera/pipeline/rpi/vc4/vc4.cpp | 5 +- - 7 files changed, 131 insertions(+), 98 deletions(-) - rename {src/libcamera/pipeline/rpi/vc4 => include/libcamera/internal}/dma_heaps.h (92%) - create mode 100644 src/libcamera/dma_heaps.cpp - delete mode 100644 src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp - -diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h b/include/libcamera/internal/dma_heaps.h -similarity index 92% -rename from src/libcamera/pipeline/rpi/vc4/dma_heaps.h -rename to include/libcamera/internal/dma_heaps.h -index 0a4a8d86..cff8f140 100644 ---- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h -+++ b/include/libcamera/internal/dma_heaps.h -@@ -13,8 +13,6 @@ - - namespace libcamera { - --namespace RPi { -- - class DmaHeap - { - public: -@@ -27,6 +25,4 @@ private: - UniqueFD dmaHeapHandle_; - }; - --} /* namespace RPi */ -- - } /* namespace libcamera */ -diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build -index 7f1f3440..33eb0fb3 100644 ---- a/include/libcamera/internal/meson.build -+++ b/include/libcamera/internal/meson.build -@@ -25,6 +25,7 @@ libcamera_internal_headers = files([ - 'device_enumerator.h', - 'device_enumerator_sysfs.h', - 'device_enumerator_udev.h', -+ 'dma_heaps.h', - 'formats.h', - 'framebuffer.h', - 'ipa_manager.h', -diff --git a/src/libcamera/dma_heaps.cpp b/src/libcamera/dma_heaps.cpp -new file mode 100644 -index 00000000..38ef175a ---- /dev/null -+++ b/src/libcamera/dma_heaps.cpp -@@ -0,0 +1,127 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2020, Raspberry Pi Ltd -+ * -+ * dma_heaps.h - Helper class for dma-heap allocations. -+ */ -+ -+#include "libcamera/internal/dma_heaps.h" -+ -+#include <array> -+#include <fcntl.h> -+#include <sys/ioctl.h> -+#include <unistd.h> -+ -+#include <linux/dma-buf.h> -+#include <linux/dma-heap.h> -+ -+#include <libcamera/base/log.h> -+ -+/** -+ * \file dma_heaps.cpp -+ * \brief CMA dma-heap allocator -+ */ -+ -+/* -+ * /dev/dma_heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma -+ * to only have to worry about importing. -+ * -+ * Annoyingly, should the cma heap size be specified on the kernel command line -+ * instead of DT, the heap gets named "reserved" instead. -+ */ -+static constexpr std::array<const char *, 2> heapNames = { -+ "/dev/dma_heap/linux,cma", -+ "/dev/dma_heap/reserved" -+}; -+ -+namespace libcamera { -+ -+LOG_DEFINE_CATEGORY(DmaHeap) -+ -+/** -+ * \class DmaHeap -+ * \brief Helper class for CMA dma-heap allocations -+ */ -+ -+/** -+ * \brief Construct a DmaHeap that owns a CMA dma-heap file descriptor -+ * -+ * Goes through the internal list of possible names of the CMA dma-heap devices -+ * until a CMA dma-heap device is successfully opened. If it fails to open any -+ * dma-heap device, an invalid DmaHeap object is constructed. A valid DmaHeap -+ * object owns a wrapped dma-heap file descriptor. -+ * -+ * Please check the new DmaHeap object with \ref DmaHeap::isValid before using it. -+ */ -+DmaHeap::DmaHeap() -+{ -+ for (const char *name : heapNames) { -+ int ret = ::open(name, O_RDWR | O_CLOEXEC, 0); -+ if (ret < 0) { -+ ret = errno; -+ LOG(DmaHeap, Debug) -+ << "Failed to open " << name << ": " -+ << strerror(ret); -+ continue; -+ } -+ -+ dmaHeapHandle_ = UniqueFD(ret); -+ break; -+ } -+ -+ if (!dmaHeapHandle_.isValid()) -+ LOG(DmaHeap, Error) << "Could not open any dmaHeap device"; -+} -+ -+/** -+ * \brief Destroy the DmaHeap instance -+ * -+ * Destroying a DmaHeap instance which owns a wrapped dma-heap file descriptor -+ * closes the descriptor automatically. -+ */ -+DmaHeap::~DmaHeap() = default; -+ -+/** -+ * \fn DmaHeap::isValid() -+ * \brief Check if the DmaHeap instance is valid -+ * \return True if the DmaHeap is valid, false otherwise -+ */ -+ -+/** -+ * \brief Allocate a dma-buf from the DmaHeap -+ * \param [in] name The name to set for the allocated buffer -+ * \param [in] size The size of the buffer to allocate -+ * \return The \ref UniqueFD of the allocated buffer -+ * -+ * Allocates a dma-buf with read/write access. -+ * If the allocation fails returns invalid UniqueFD. -+ */ -+UniqueFD DmaHeap::alloc(const char *name, std::size_t size) -+{ -+ int ret; -+ -+ if (!name) -+ return {}; -+ -+ struct dma_heap_allocation_data alloc = {}; -+ -+ alloc.len = size; -+ alloc.fd_flags = O_CLOEXEC | O_RDWR; -+ -+ ret = ::ioctl(dmaHeapHandle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc); -+ if (ret < 0) { -+ LOG(DmaHeap, Error) << "dmaHeap allocation failure for " << name; -+ return {}; -+ } -+ -+ UniqueFD allocFd(alloc.fd); -+ ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name); -+ if (ret < 0) { -+ LOG(DmaHeap, Error) << "dmaHeap naming failure for " << name; -+ return {}; -+ } -+ -+ return allocFd; -+} -+ -+} /* namespace libcamera */ -diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build -index 45f63e93..3c5e43df 100644 ---- a/src/libcamera/meson.build -+++ b/src/libcamera/meson.build -@@ -17,6 +17,7 @@ libcamera_sources = files([ - 'delayed_controls.cpp', - 'device_enumerator.cpp', - 'device_enumerator_sysfs.cpp', -+ 'dma_heaps.cpp', - 'fence.cpp', - 'formats.cpp', - 'framebuffer.cpp', -diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp b/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp -deleted file mode 100644 -index 317b1fc1..00000000 ---- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp -+++ /dev/null -@@ -1,90 +0,0 @@ --/* SPDX-License-Identifier: LGPL-2.1-or-later */ --/* -- * Copyright (C) 2020, Raspberry Pi Ltd -- * -- * dma_heaps.h - Helper class for dma-heap allocations. -- */ -- --#include "dma_heaps.h" -- --#include <array> --#include <fcntl.h> --#include <linux/dma-buf.h> --#include <linux/dma-heap.h> --#include <sys/ioctl.h> --#include <unistd.h> -- --#include <libcamera/base/log.h> -- --/* -- * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma -- * to only have to worry about importing. -- * -- * Annoyingly, should the cma heap size be specified on the kernel command line -- * instead of DT, the heap gets named "reserved" instead. -- */ --static constexpr std::array<const char *, 2> heapNames = { -- "/dev/dma_heap/linux,cma", -- "/dev/dma_heap/reserved" --}; -- --namespace libcamera { -- --LOG_DECLARE_CATEGORY(RPI) -- --namespace RPi { -- --DmaHeap::DmaHeap() --{ -- for (const char *name : heapNames) { -- int ret = ::open(name, O_RDWR | O_CLOEXEC, 0); -- if (ret < 0) { -- ret = errno; -- LOG(RPI, Debug) << "Failed to open " << name << ": " -- << strerror(ret); -- continue; -- } -- -- dmaHeapHandle_ = UniqueFD(ret); -- break; -- } -- -- if (!dmaHeapHandle_.isValid()) -- LOG(RPI, Error) << "Could not open any dmaHeap device"; --} -- --DmaHeap::~DmaHeap() = default; -- --UniqueFD DmaHeap::alloc(const char *name, std::size_t size) --{ -- int ret; -- -- if (!name) -- return {}; -- -- struct dma_heap_allocation_data alloc = {}; -- -- alloc.len = size; -- alloc.fd_flags = O_CLOEXEC | O_RDWR; -- -- ret = ::ioctl(dmaHeapHandle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc); -- if (ret < 0) { -- LOG(RPI, Error) << "dmaHeap allocation failure for " -- << name; -- return {}; -- } -- -- UniqueFD allocFd(alloc.fd); -- ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name); -- if (ret < 0) { -- LOG(RPI, Error) << "dmaHeap naming failure for " -- << name; -- return {}; -- } -- -- return allocFd; --} -- --} /* namespace RPi */ -- --} /* namespace libcamera */ -diff --git a/src/libcamera/pipeline/rpi/vc4/meson.build b/src/libcamera/pipeline/rpi/vc4/meson.build -index cdb049c5..386e2296 100644 ---- a/src/libcamera/pipeline/rpi/vc4/meson.build -+++ b/src/libcamera/pipeline/rpi/vc4/meson.build -@@ -1,7 +1,6 @@ - # SPDX-License-Identifier: CC0-1.0 - - libcamera_sources += files([ -- 'dma_heaps.cpp', - 'vc4.cpp', - ]) - -diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp -index 26102ea7..3a42e75e 100644 ---- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp -+++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp -@@ -12,12 +12,11 @@ - #include <libcamera/formats.h> - - #include "libcamera/internal/device_enumerator.h" -+#include "libcamera/internal/dma_heaps.h" - - #include "../common/pipeline_base.h" - #include "../common/rpi_stream.h" - --#include "dma_heaps.h" -- - using namespace std::chrono_literals; - - namespace libcamera { -@@ -87,7 +86,7 @@ public: - RPi::Device<Isp, 4> isp_; - - /* DMAHEAP allocation helper. */ -- RPi::DmaHeap dmaHeap_; -+ DmaHeap dmaHeap_; - SharedFD lsTable_; - - struct Config { --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0020-ov01a1s-HACK.patch b/users/flokli/ipu6-softisp/libcamera/0002-ov01a1s-HACK.patch index 343f04c8502b..61316d10427f 100644 --- a/users/flokli/ipu6-softisp/libcamera/0020-ov01a1s-HACK.patch +++ b/users/flokli/ipu6-softisp/libcamera/0002-ov01a1s-HACK.patch @@ -1,30 +1,30 @@ -From 2bde6e420571c6dc0ff25246620b4c987987f6be Mon Sep 17 00:00:00 2001 +From 5895f4ed8163780446665b99b8d5dc31d6f2b791 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Tue, 19 Dec 2023 15:45:51 +0100 -Subject: [PATCH 20/21] ov01a1s HACK +Subject: [PATCH 2/3] ov01a1s HACK Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- - src/libcamera/camera_sensor.cpp | 6 ++++++ - src/libcamera/software_isp/debayer_cpu.cpp | 8 ++++++++ + src/libcamera/sensor/camera_sensor.cpp | 6 ++++++ + src/libcamera/software_isp/debayer_cpu.cpp | 7 +++++++ src/libcamera/software_isp/swstats_cpu.cpp | 4 ++++ - 3 files changed, 18 insertions(+) + 3 files changed, 17 insertions(+) -diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp -index f19f72ea..7ad4b9ef 100644 ---- a/src/libcamera/camera_sensor.cpp -+++ b/src/libcamera/camera_sensor.cpp -@@ -34,6 +34,9 @@ +diff --git a/src/libcamera/sensor/camera_sensor.cpp b/src/libcamera/sensor/camera_sensor.cpp +index 77c396b9..628b12f4 100644 +--- a/src/libcamera/sensor/camera_sensor.cpp ++++ b/src/libcamera/sensor/camera_sensor.cpp +@@ -33,6 +33,9 @@ + */ namespace libcamera { - ++ +// HACK HACK +bool is_ov01a1s = false; -+ + LOG_DEFINE_CATEGORY(CameraSensor) - /** -@@ -426,6 +429,9 @@ int CameraSensor::initProperties() +@@ -442,6 +445,9 @@ int CameraSensor::initProperties() model_ = subdev_->model(); properties_.set(properties::Model, utils::toAscii(model_)); @@ -35,7 +35,7 @@ index f19f72ea..7ad4b9ef 100644 int ret = generateId(); if (ret) diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp -index 3be3cdfe..d6599805 100644 +index 8254bbe9..10ea29b1 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp @@ -23,6 +23,7 @@ @@ -46,7 +46,7 @@ index 3be3cdfe..d6599805 100644 /** * \class DebayerCpu * \brief Class for debayering on the CPU -@@ -262,6 +263,9 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf +@@ -275,6 +276,9 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat); @@ -56,7 +56,7 @@ index 3be3cdfe..d6599805 100644 if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) && bayerFormat.packing == BayerFormat::Packing::None && isStandardBayerOrder(bayerFormat.order)) { -@@ -330,7 +334,11 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF +@@ -343,6 +347,9 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat); @@ -64,12 +64,10 @@ index 3be3cdfe..d6599805 100644 + bayerFormat.order = BayerFormat::IGIG_GBGR_IGIG_GRGB; + xShift_ = 0; -+ swapRedBlueGains_ = false; - switch (outputFormat) { diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp -index be310f56..cda1894a 100644 +index 815c4d4f..0b310f80 100644 --- a/src/libcamera/software_isp/swstats_cpu.cpp +++ b/src/libcamera/software_isp/swstats_cpu.cpp @@ -19,6 +19,7 @@ @@ -80,7 +78,7 @@ index be310f56..cda1894a 100644 /** * \class SwStatsCpu * \brief Class for gathering statistics on the CPU -@@ -271,6 +272,9 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) +@@ -367,6 +368,9 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputCfg.pixelFormat); @@ -91,5 +89,5 @@ index be310f56..cda1894a 100644 setupStandardBayerOrder(bayerFormat.order) == 0) { switch (bayerFormat.bitDepth) { -- -2.43.2 +2.45.2 diff --git a/users/flokli/ipu6-softisp/libcamera/0021-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch b/users/flokli/ipu6-softisp/libcamera/0003-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch index a3af38c93c79..f250617bd3ad 100644 --- a/users/flokli/ipu6-softisp/libcamera/0021-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch +++ b/users/flokli/ipu6-softisp/libcamera/0003-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch @@ -1,7 +1,7 @@ -From a21bb26dcfcc00425f031421b87576f9c81e4824 Mon Sep 17 00:00:00 2001 +From 06add438e4fc53faca6e016bd582df0e7ac5a271 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Wed, 24 Jan 2024 20:44:29 +0100 -Subject: [PATCH 21/21] libcamera: debayer_cpu: Make the minimum size 1280x720 +Subject: [PATCH 3/3] libcamera: debayer_cpu: Make the minimum size 1280x720 pipewire + firefox default to what looks like 640x480 if we export the entire supported cropping range. Hardcode 720p as minsize for now. @@ -12,31 +12,31 @@ Signed-off-by: Hans de Goede <hdegoede@redhat.com> 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp -index d6599805..5a06b191 100644 +index 10ea29b1..a354138b 100644 --- a/src/libcamera/software_isp/debayer_cpu.cpp +++ b/src/libcamera/software_isp/debayer_cpu.cpp -@@ -790,10 +790,17 @@ SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize) +@@ -805,10 +805,17 @@ SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize) return {}; } -- return SizeRange(Size(pattern_size.width, pattern_size.height), -- Size((inputSize.width - 2 * pattern_size.width) & ~(pattern_size.width - 1), -- (inputSize.height - 2 * border_height) & ~(pattern_size.height - 1)), -- pattern_size.width, pattern_size.height); +- return SizeRange(Size(patternSize.width, patternSize.height), +- Size((inputSize.width - 2 * patternSize.width) & ~(patternSize.width - 1), +- (inputSize.height - 2 * borderHeight) & ~(patternSize.height - 1)), +- patternSize.width, patternSize.height); + /* + * pipewire + firefox default to what looks like 640x480 + * if we export the entire supported cropping range. + * Hardcode 720p as minsize for now. Minsize should be -+ * Size(pattern_size.width, pattern_size.height) ++ * Size(patternSize.width, patternSize.height) + */ -+ unsigned int w = (inputSize.width - 2 * pattern_size.width) & ~(pattern_size.width - 1); -+ unsigned int h = (inputSize.height - 2 * pattern_size.height) & ~(pattern_size.height - 1); ++ unsigned int w = (inputSize.width - 2 * patternSize.width) & ~(patternSize.width - 1); ++ unsigned int h = (inputSize.height - 2 * patternSize.height) & ~(patternSize.height - 1); + return SizeRange(Size(std::min(w, 1280u), std::min(h, 720u)), + Size(w, h), -+ pattern_size.width, pattern_size.height); ++ patternSize.width, patternSize.height); } } /* namespace libcamera */ -- -2.43.2 +2.45.2 diff --git a/users/flokli/ipu6-softisp/libcamera/0003-libcamera-dma_heaps-extend-DmaHeap-class-to-support-.patch b/users/flokli/ipu6-softisp/libcamera/0003-libcamera-dma_heaps-extend-DmaHeap-class-to-support-.patch deleted file mode 100644 index 6e5ef9445a4b..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0003-libcamera-dma_heaps-extend-DmaHeap-class-to-support-.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 5df9bc3b2a3d86bcc8504896cc87d7fcb5aea3a4 Mon Sep 17 00:00:00 2001 -From: Andrey Konovalov <andrey.konovalov@linaro.org> -Date: Mon, 11 Mar 2024 15:15:07 +0100 -Subject: [PATCH 03/21] libcamera: dma_heaps: extend DmaHeap class to support - system heap - -Add an argument to the constructor to specify dma heaps type(s) -to use. Can be DmaHeapFlag::Cma and/or DmaHeapFlag::System. -By default DmaHeapFlag::Cma is used. If both DmaHeapFlag::Cma and -DmaHeapFlag::System are set, CMA heap is tried first. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - include/libcamera/internal/dma_heaps.h | 12 ++++- - src/libcamera/dma_heaps.cpp | 67 ++++++++++++++++++++------ - 2 files changed, 63 insertions(+), 16 deletions(-) - -diff --git a/include/libcamera/internal/dma_heaps.h b/include/libcamera/internal/dma_heaps.h -index cff8f140..80bf29e7 100644 ---- a/include/libcamera/internal/dma_heaps.h -+++ b/include/libcamera/internal/dma_heaps.h -@@ -9,6 +9,7 @@ - - #include <stddef.h> - -+#include <libcamera/base/flags.h> - #include <libcamera/base/unique_fd.h> - - namespace libcamera { -@@ -16,7 +17,14 @@ namespace libcamera { - class DmaHeap - { - public: -- DmaHeap(); -+ enum class DmaHeapFlag { -+ Cma = 1 << 0, -+ System = 1 << 1, -+ }; -+ -+ using DmaHeapFlags = Flags<DmaHeapFlag>; -+ -+ DmaHeap(DmaHeapFlags flags = DmaHeapFlag::Cma); - ~DmaHeap(); - bool isValid() const { return dmaHeapHandle_.isValid(); } - UniqueFD alloc(const char *name, std::size_t size); -@@ -25,4 +33,6 @@ private: - UniqueFD dmaHeapHandle_; - }; - -+LIBCAMERA_FLAGS_ENABLE_OPERATORS(DmaHeap::DmaHeapFlag) -+ - } /* namespace libcamera */ -diff --git a/src/libcamera/dma_heaps.cpp b/src/libcamera/dma_heaps.cpp -index 38ef175a..d0e33ce6 100644 ---- a/src/libcamera/dma_heaps.cpp -+++ b/src/libcamera/dma_heaps.cpp -@@ -19,9 +19,11 @@ - - /** - * \file dma_heaps.cpp -- * \brief CMA dma-heap allocator -+ * \brief dma-heap allocator - */ - -+namespace libcamera { -+ - /* - * /dev/dma_heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma - * to only have to worry about importing. -@@ -29,42 +31,77 @@ - * Annoyingly, should the cma heap size be specified on the kernel command line - * instead of DT, the heap gets named "reserved" instead. - */ --static constexpr std::array<const char *, 2> heapNames = { -- "/dev/dma_heap/linux,cma", -- "/dev/dma_heap/reserved" -+ -+/** -+ * \struct DmaHeapInfo -+ * \brief Tells what type of dma-heap the dma-heap represented by the device node name is -+ * \var DmaHeapInfo::flag -+ * \brief The type of the dma-heap -+ * \var DmaHeapInfo::name -+ * \brief The dma-heap's device node name -+ */ -+struct DmaHeapInfo { -+ DmaHeap::DmaHeapFlag flag; -+ const char *name; - }; - --namespace libcamera { -+static constexpr std::array<DmaHeapInfo, 3> heapInfos = { -+ { /* CMA heap names first */ -+ { DmaHeap::DmaHeapFlag::Cma, "/dev/dma_heap/linux,cma" }, -+ { DmaHeap::DmaHeapFlag::Cma, "/dev/dma_heap/reserved" }, -+ { DmaHeap::DmaHeapFlag::System, "/dev/dma_heap/system" } } -+}; - - LOG_DEFINE_CATEGORY(DmaHeap) - - /** - * \class DmaHeap -- * \brief Helper class for CMA dma-heap allocations -+ * \brief Helper class for dma-heap allocations - */ - - /** -- * \brief Construct a DmaHeap that owns a CMA dma-heap file descriptor -+ * \enum DmaHeap::DmaHeapFlag -+ * \brief Type of the dma-heap -+ * \var DmaHeap::Cma -+ * \brief Allocate from a CMA dma-heap -+ * \var DmaHeap::System -+ * \brief Allocate from the system dma-heap -+ */ -+ -+/** -+ * \typedef DmaHeap::DmaHeapFlags -+ * \brief A bitwise combination of DmaHeap::DmaHeapFlag values -+ */ -+ -+/** -+ * \brief Construct a DmaHeap that owns a CMA or system dma-heap file descriptor -+ * \param [in] flags The type(s) of the dma-heap(s) to allocate from - * -- * Goes through the internal list of possible names of the CMA dma-heap devices -- * until a CMA dma-heap device is successfully opened. If it fails to open any -- * dma-heap device, an invalid DmaHeap object is constructed. A valid DmaHeap -- * object owns a wrapped dma-heap file descriptor. -+ * By default \a flags are set to DmaHeap::DmaHeapFlag::Cma. The constructor goes -+ * through the internal list of possible names of the CMA and system dma-heap devices -+ * until the dma-heap device of the requested type is successfully opened. If more -+ * than one dma-heap type is specified in flags the CMA heap is tried first. If it -+ * fails to open any dma-heap device an invalid DmaHeap object is constructed. -+ * A valid DmaHeap object owns a wrapped dma-heap file descriptor. - * - * Please check the new DmaHeap object with \ref DmaHeap::isValid before using it. - */ --DmaHeap::DmaHeap() -+DmaHeap::DmaHeap(DmaHeapFlags flags) - { -- for (const char *name : heapNames) { -- int ret = ::open(name, O_RDWR | O_CLOEXEC, 0); -+ for (const auto &info : heapInfos) { -+ if (!(flags & info.flag)) -+ continue; -+ -+ int ret = ::open(info.name, O_RDWR | O_CLOEXEC, 0); - if (ret < 0) { - ret = errno; - LOG(DmaHeap, Debug) -- << "Failed to open " << name << ": " -+ << "Failed to open " << info.name << ": " - << strerror(ret); - continue; - } - -+ LOG(DmaHeap, Debug) << "Using " << info.name; - dmaHeapHandle_ = UniqueFD(ret); - break; - } --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0004-libcamera-internal-Move-SharedMemObject-class-to-a-c.patch b/users/flokli/ipu6-softisp/libcamera/0004-libcamera-internal-Move-SharedMemObject-class-to-a-c.patch deleted file mode 100644 index 48f10aa47a99..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0004-libcamera-internal-Move-SharedMemObject-class-to-a-c.patch +++ /dev/null @@ -1,69 +0,0 @@ -From a6777760a2121f02808baecea504ac0e242f860b Mon Sep 17 00:00:00 2001 -From: Andrey Konovalov <andrey.konovalov@linaro.org> -Date: Mon, 11 Mar 2024 15:15:08 +0100 -Subject: [PATCH 04/21] libcamera: internal: Move SharedMemObject class to a - common directory - -Move SharedMemObject class out of RPi namespace and put it into -include/libcamera/internal so that everyone could use it. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> ---- - include/libcamera/internal/meson.build | 1 + - .../libcamera/internal}/shared_mem_object.h | 6 +----- - 2 files changed, 2 insertions(+), 5 deletions(-) - rename {src/libcamera/pipeline/rpi/common => include/libcamera/internal}/shared_mem_object.h (97%) - -diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build -index 33eb0fb3..5807dfd9 100644 ---- a/include/libcamera/internal/meson.build -+++ b/include/libcamera/internal/meson.build -@@ -39,6 +39,7 @@ libcamera_internal_headers = files([ - 'process.h', - 'pub_key.h', - 'request.h', -+ 'shared_mem_object.h', - 'source_paths.h', - 'sysfs.h', - 'v4l2_device.h', -diff --git a/src/libcamera/pipeline/rpi/common/shared_mem_object.h b/include/libcamera/internal/shared_mem_object.h -similarity index 97% -rename from src/libcamera/pipeline/rpi/common/shared_mem_object.h -rename to include/libcamera/internal/shared_mem_object.h -index aa56c220..98636b44 100644 ---- a/src/libcamera/pipeline/rpi/common/shared_mem_object.h -+++ b/include/libcamera/internal/shared_mem_object.h -@@ -6,8 +6,8 @@ - */ - #pragma once - --#include <cstddef> - #include <fcntl.h> -+#include <stddef.h> - #include <string> - #include <sys/mman.h> - #include <sys/stat.h> -@@ -19,8 +19,6 @@ - - namespace libcamera { - --namespace RPi { -- - template<class T> - class SharedMemObject - { -@@ -123,6 +121,4 @@ private: - T *obj_; - }; - --} /* namespace RPi */ -- - } /* namespace libcamera */ --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0005-libcamera-shared_mem_object-reorganize-the-code-and-.patch b/users/flokli/ipu6-softisp/libcamera/0005-libcamera-shared_mem_object-reorganize-the-code-and-.patch deleted file mode 100644 index d2143febf740..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0005-libcamera-shared_mem_object-reorganize-the-code-and-.patch +++ /dev/null @@ -1,403 +0,0 @@ -From f94af21adc1889706127d07c5425f44c9cec9a95 Mon Sep 17 00:00:00 2001 -From: Andrei Konovalov <andrey.konovalov.ynk@gmail.com> -Date: Mon, 11 Mar 2024 15:15:09 +0100 -Subject: [PATCH 05/21] libcamera: shared_mem_object: reorganize the code and - document the SharedMemObject class - -Split the parts which doesn't otherwise depend on the type T or -arguments Args out of the SharedMemObject class into a new -SharedMem class. - -Doxygen documentation by Dennis Bonke and Andrei Konovalov. - -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Co-developed-by: Dennis Bonke <admin@dennisbonke.com> -Signed-off-by: Dennis Bonke <admin@dennisbonke.com> -Signed-off-by: Andrei Konovalov <andrey.konovalov.ynk@gmail.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> ---- - .../libcamera/internal/shared_mem_object.h | 101 ++++++---- - src/libcamera/meson.build | 1 + - src/libcamera/shared_mem_object.cpp | 190 ++++++++++++++++++ - 3 files changed, 253 insertions(+), 39 deletions(-) - create mode 100644 src/libcamera/shared_mem_object.cpp - -diff --git a/include/libcamera/internal/shared_mem_object.h b/include/libcamera/internal/shared_mem_object.h -index 98636b44..43b07c9d 100644 ---- a/include/libcamera/internal/shared_mem_object.h -+++ b/include/libcamera/internal/shared_mem_object.h -@@ -6,12 +6,9 @@ - */ - #pragma once - --#include <fcntl.h> - #include <stddef.h> - #include <string> - #include <sys/mman.h> --#include <sys/stat.h> --#include <unistd.h> - #include <utility> - - #include <libcamera/base/class.h> -@@ -19,58 +16,92 @@ - - namespace libcamera { - -+class SharedMem -+{ -+public: -+ SharedMem() -+ : mem_(nullptr) -+ { -+ } -+ -+ SharedMem(const std::string &name, std::size_t size); -+ -+ SharedMem(SharedMem &&rhs) -+ { -+ this->name_ = std::move(rhs.name_); -+ this->fd_ = std::move(rhs.fd_); -+ this->mem_ = rhs.mem_; -+ rhs.mem_ = nullptr; -+ } -+ -+ virtual ~SharedMem() -+ { -+ if (mem_) -+ munmap(mem_, size_); -+ } -+ -+ /* Make SharedMem non-copyable for now. */ -+ LIBCAMERA_DISABLE_COPY(SharedMem) -+ -+ SharedMem &operator=(SharedMem &&rhs) -+ { -+ this->name_ = std::move(rhs.name_); -+ this->fd_ = std::move(rhs.fd_); -+ this->mem_ = rhs.mem_; -+ rhs.mem_ = nullptr; -+ return *this; -+ } -+ -+ const SharedFD &fd() const -+ { -+ return fd_; -+ } -+ -+ void *mem() const -+ { -+ return mem_; -+ } -+ -+private: -+ std::string name_; -+ SharedFD fd_; -+ size_t size_; -+protected: -+ void *mem_; -+}; -+ - template<class T> --class SharedMemObject -+class SharedMemObject : public SharedMem - { - public: - static constexpr std::size_t SIZE = sizeof(T); - - SharedMemObject() -- : obj_(nullptr) -+ : SharedMem(), obj_(nullptr) - { - } - - template<class... Args> - SharedMemObject(const std::string &name, Args &&...args) -- : name_(name), obj_(nullptr) -+ : SharedMem(name, SIZE), obj_(nullptr) - { -- void *mem; -- int ret; -- -- ret = memfd_create(name_.c_str(), MFD_CLOEXEC); -- if (ret < 0) -- return; -- -- fd_ = SharedFD(std::move(ret)); -- if (!fd_.isValid()) -- return; -- -- ret = ftruncate(fd_.get(), SIZE); -- if (ret < 0) -+ if (mem_ == nullptr) - return; - -- mem = mmap(nullptr, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, -- fd_.get(), 0); -- if (mem == MAP_FAILED) -- return; -- -- obj_ = new (mem) T(std::forward<Args>(args)...); -+ obj_ = new (mem_) T(std::forward<Args>(args)...); - } - - SharedMemObject(SharedMemObject<T> &&rhs) -+ : SharedMem(std::move(rhs)) - { -- this->name_ = std::move(rhs.name_); -- this->fd_ = std::move(rhs.fd_); - this->obj_ = rhs.obj_; - rhs.obj_ = nullptr; - } - - ~SharedMemObject() - { -- if (obj_) { -+ if (obj_) - obj_->~T(); -- munmap(obj_, SIZE); -- } - } - - /* Make SharedMemObject non-copyable for now. */ -@@ -78,8 +109,7 @@ public: - - SharedMemObject<T> &operator=(SharedMemObject<T> &&rhs) - { -- this->name_ = std::move(rhs.name_); -- this->fd_ = std::move(rhs.fd_); -+ SharedMem::operator=(std::move(rhs)); - this->obj_ = rhs.obj_; - rhs.obj_ = nullptr; - return *this; -@@ -105,19 +135,12 @@ public: - return *obj_; - } - -- const SharedFD &fd() const -- { -- return fd_; -- } -- - explicit operator bool() const - { - return !!obj_; - } - - private: -- std::string name_; -- SharedFD fd_; - T *obj_; - }; - -diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build -index 3c5e43df..94a95ae3 100644 ---- a/src/libcamera/meson.build -+++ b/src/libcamera/meson.build -@@ -41,6 +41,7 @@ libcamera_sources = files([ - 'process.cpp', - 'pub_key.cpp', - 'request.cpp', -+ 'shared_mem_object.cpp', - 'source_paths.cpp', - 'stream.cpp', - 'sysfs.cpp', -diff --git a/src/libcamera/shared_mem_object.cpp b/src/libcamera/shared_mem_object.cpp -new file mode 100644 -index 00000000..44fe74c2 ---- /dev/null -+++ b/src/libcamera/shared_mem_object.cpp -@@ -0,0 +1,190 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Raspberry Pi Ltd -+ * -+ * shared_mem_object.cpp - Helper class for shared memory allocations -+ */ -+ -+#include "libcamera/internal/shared_mem_object.h" -+ -+#include <sys/types.h> -+#include <unistd.h> -+ -+/** -+ * \file shared_mem_object.cpp -+ * \brief Helper class for shared memory allocations -+ */ -+ -+namespace libcamera { -+ -+/** -+ * \class SharedMem -+ * \brief Helper class for allocating shared memory -+ * -+ * Memory is allocated and exposed as a SharedFD for use across IPC boundaries. -+ * -+ * SharedMem allocates the shared memory of the given size and maps it. -+ * To check that the shared memory was allocated and mapped successfully, one -+ * needs to verify that the pointer to the shared memory returned by SharedMem::mem() -+ * is not nullptr. -+ * -+ * To access the shared memory from another process the SharedFD should be passed -+ * to that process, and then the shared memory should be mapped into that process -+ * address space by calling mmap(). -+ * -+ * A single memfd is created for every SharedMem. If there is a need to allocate -+ * a large number of objects in shared memory, these objects should be grouped -+ * together and use the shared memory allocated by a single SharedMem object if -+ * possible. This will help to minimize the number of created memfd's. -+ */ -+ -+/** -+ * \fn SharedMem::SharedMem(const std::string &name, std::size_t size) -+ * \brief Constructor for the SharedMem -+ * \param[in] name Name of the SharedMem -+ * \param[in] size Size of the shared memory to allocate and map -+ */ -+ -+/** -+ * \fn SharedMem::SharedMem(SharedMem &&rhs) -+ * \brief Move constructor for SharedMem -+ * \param[in] rhs The object to move -+ */ -+ -+/** -+ * \fn SharedMem::~SharedMem() -+ * \brief SharedMem destructor -+ * -+ * Unmaps the allocated shared memory. Decrements the shared memory descriptor use -+ * count. -+ */ -+ -+/** -+ * \fn SharedMem &SharedMem::operator=(SharedMem &&rhs) -+ * \brief Move constructor for SharedMem -+ * \param[in] rhs The object to move -+ */ -+ -+/** -+ * \fn const SharedFD &SharedMem::fd() const -+ * \brief Gets the file descriptor for the underlying shared memory -+ * \return The file descriptor -+ */ -+ -+/** -+ * \fn void *SharedMem::mem() const -+ * \brief Gets the pointer to the underlying shared memory -+ * \return The pointer to the shared memory -+ */ -+ -+SharedMem::SharedMem(const std::string &name, std::size_t size) -+ : name_(name), size_(size), mem_(nullptr) -+{ -+ int fd = memfd_create(name_.c_str(), MFD_CLOEXEC); -+ if (fd < 0) -+ return; -+ -+ fd_ = SharedFD(std::move(fd)); -+ if (!fd_.isValid()) -+ return; -+ -+ if (ftruncate(fd_.get(), size_) < 0) -+ return; -+ -+ mem_ = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, -+ fd_.get(), 0); -+ if (mem_ == MAP_FAILED) -+ mem_ = nullptr; -+} -+ -+/** -+ * \var SharedMem::mem_ -+ * \brief Pointer to the shared memory allocated -+ */ -+ -+/** -+ * \class SharedMemObject -+ * \brief Helper class for allocating objects in shared memory -+ * -+ * Memory is allocated and exposed as a SharedFD for use across IPC boundaries. -+ * -+ * Given the type of the object to be created in shared memory and the arguments -+ * to pass to this object's constructor, SharedMemObject allocates the shared memory -+ * of the size of the object and constructs the object in this memory. To ensure -+ * that the SharedMemObject was created successfully, one needs to verify that the -+ * overloaded bool() operator returns true. The object created in the shared memory -+ * can be accessed using the SharedMemObject::operator*() indirection operator. Its -+ * members can be accessed with the SharedMemObject::operator->() member of pointer -+ * operator. -+ * -+ * To access the object from another process the SharedFD should be passed to that -+ * process, and the shared memory should be mapped by calling mmap(). -+ * -+ * A single memfd is created for every SharedMemObject. If there is a need to allocate -+ * a large number of objects in shared memory, these objects should be grouped into a -+ * single large object to keep the number of created memfd's reasonably small. -+ */ -+ -+/** -+ * \var SharedMemObject::SIZE -+ * \brief The size of the object that is going to be stored here -+ */ -+ -+/** -+ * \fn SharedMemObject< T >::SharedMemObject(const std::string &name, Args &&...args) -+ * \brief Constructor for the SharedMemObject -+ * \param[in] name Name of the SharedMemObject -+ * \param[in] args Args to pass to the constructor of the object in shared memory -+ */ -+ -+/** -+ * \fn SharedMemObject::SharedMemObject(SharedMemObject<T> &&rhs) -+ * \brief Move constructor for SharedMemObject -+ * \param[in] rhs The object to move -+ */ -+ -+/** -+ * \fn SharedMemObject::~SharedMemObject() -+ * \brief SharedMemObject destructor -+ * -+ * Destroys the object created in the shared memory and then unmaps the shared memory. -+ * Decrements the shared memory descriptor use count. -+ */ -+ -+/** -+ * \fn SharedMemObject::operator=(SharedMemObject<T> &&rhs) -+ * \brief Operator= for SharedMemObject -+ * \param[in] rhs The SharedMemObject object to take the data from -+ */ -+ -+/** -+ * \fn SharedMemObject::operator->() -+ * \brief Operator-> for SharedMemObject -+ * \return The pointer to the object -+ */ -+ -+/** -+ * \fn const T *SharedMemObject::operator->() const -+ * \brief Operator-> for SharedMemObject -+ * \return The pointer to the const object -+ */ -+ -+/** -+ * \fn SharedMemObject::operator*() -+ * \brief Operator* for SharedMemObject -+ * \return The reference to the object -+ */ -+ -+/** -+ * \fn const T &SharedMemObject::operator*() const -+ * \brief Operator* for SharedMemObject -+ * \return Const reference to the object -+ */ -+ -+/** -+ * \fn SharedMemObject::operator bool() -+ * \brief Operator bool() for SharedMemObject -+ * \return True if the object was created OK in the shared memory, false otherwise -+ */ -+ -+} // namespace libcamera --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0006-libcamera-software_isp-Add-SwStatsCpu-class.patch b/users/flokli/ipu6-softisp/libcamera/0006-libcamera-software_isp-Add-SwStatsCpu-class.patch deleted file mode 100644 index 9f80b69f168c..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0006-libcamera-software_isp-Add-SwStatsCpu-class.patch +++ /dev/null @@ -1,523 +0,0 @@ -From 4259b01930333c6666a185d923e6e68ec915a4fd Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Mon, 11 Mar 2024 15:15:10 +0100 -Subject: [PATCH 06/21] libcamera: software_isp: Add SwStatsCpu class - -Add a CPU based SwStats implementation for SoftwareISP / SoftIPA use. - -This implementation offers a configure function + functions to gather -statistics on a line by line basis. This allows CPU based software -debayering to call into interlace debayering and statistics gathering -on a line by line bases while the input data is still hot in the cache. - -This implementation also allows specifying a window over which to gather -statistics instead of processing the whole frame. - -Doxygen documentation by Dennis Bonke. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> -Co-developed-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Co-developed-by: Pavel Machek <pavel@ucw.cz> -Signed-off-by: Pavel Machek <pavel@ucw.cz> -Co-developed-by: Dennis Bonke <admin@dennisbonke.com> -Signed-off-by: Dennis Bonke <admin@dennisbonke.com> -Co-developed-by: Marttico <g.martti@gmail.com> -Signed-off-by: Marttico <g.martti@gmail.com> -Co-developed-by: Toon Langendam <t.langendam@gmail.com> -Signed-off-by: Toon Langendam <t.langendam@gmail.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - include/libcamera/internal/meson.build | 1 + - .../internal/software_isp/meson.build | 5 + - .../internal/software_isp/swisp_stats.h | 38 ++++ - src/libcamera/meson.build | 1 + - src/libcamera/software_isp/meson.build | 12 + - src/libcamera/software_isp/swstats_cpu.cpp | 208 ++++++++++++++++++ - src/libcamera/software_isp/swstats_cpu.h | 159 +++++++++++++ - 7 files changed, 424 insertions(+) - create mode 100644 include/libcamera/internal/software_isp/meson.build - create mode 100644 include/libcamera/internal/software_isp/swisp_stats.h - create mode 100644 src/libcamera/software_isp/meson.build - create mode 100644 src/libcamera/software_isp/swstats_cpu.cpp - create mode 100644 src/libcamera/software_isp/swstats_cpu.h - -diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build -index 5807dfd9..160fdc37 100644 ---- a/include/libcamera/internal/meson.build -+++ b/include/libcamera/internal/meson.build -@@ -50,3 +50,4 @@ libcamera_internal_headers = files([ - ]) - - subdir('converter') -+subdir('software_isp') -diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build -new file mode 100644 -index 00000000..66c9c3fb ---- /dev/null -+++ b/include/libcamera/internal/software_isp/meson.build -@@ -0,0 +1,5 @@ -+# SPDX-License-Identifier: CC0-1.0 -+ -+libcamera_internal_headers += files([ -+ 'swisp_stats.h', -+]) -diff --git a/include/libcamera/internal/software_isp/swisp_stats.h b/include/libcamera/internal/software_isp/swisp_stats.h -new file mode 100644 -index 00000000..afe42c9a ---- /dev/null -+++ b/include/libcamera/internal/software_isp/swisp_stats.h -@@ -0,0 +1,38 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Linaro Ltd -+ * -+ * swisp_stats.h - Statistics data format used by the software ISP and software IPA -+ */ -+ -+#pragma once -+ -+namespace libcamera { -+ -+/** -+ * \brief Struct that holds the statistics for the Software ISP. -+ */ -+struct SwIspStats { -+ /** -+ * \brief Holds the sum of all sampled red pixels. -+ */ -+ unsigned long sumR_; -+ /** -+ * \brief Holds the sum of all sampled green pixels. -+ */ -+ unsigned long sumG_; -+ /** -+ * \brief Holds the sum of all sampled blue pixels. -+ */ -+ unsigned long sumB_; -+ /** -+ * \brief Number of bins in the yHistogram. -+ */ -+ static constexpr unsigned int kYHistogramSize = 16; -+ /** -+ * \brief A histogram of luminance values. -+ */ -+ std::array<unsigned int, kYHistogramSize> yHistogram; -+}; -+ -+} /* namespace libcamera */ -diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build -index 94a95ae3..91e4cc60 100644 ---- a/src/libcamera/meson.build -+++ b/src/libcamera/meson.build -@@ -71,6 +71,7 @@ subdir('converter') - subdir('ipa') - subdir('pipeline') - subdir('proxy') -+subdir('software_isp') - - null_dep = dependency('', required : false) - -diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build -new file mode 100644 -index 00000000..fcfff74a ---- /dev/null -+++ b/src/libcamera/software_isp/meson.build -@@ -0,0 +1,12 @@ -+# SPDX-License-Identifier: CC0-1.0 -+ -+softisp_enabled = pipelines.contains('simple') -+summary({'SoftISP support' : softisp_enabled}, section : 'Configuration') -+ -+if not (softisp_enabled) -+ subdir_done() -+endif -+ -+libcamera_sources += files([ -+ 'swstats_cpu.cpp', -+]) -diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp -new file mode 100644 -index 00000000..448d0e4c ---- /dev/null -+++ b/src/libcamera/software_isp/swstats_cpu.cpp -@@ -0,0 +1,208 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Linaro Ltd -+ * Copyright (C) 2023, Red Hat Inc. -+ * -+ * Authors: -+ * Hans de Goede <hdegoede@redhat.com> -+ * -+ * swstats_cpu.cpp - CPU based software statistics implementation -+ */ -+ -+#include "swstats_cpu.h" -+ -+#include <libcamera/base/log.h> -+ -+#include <libcamera/stream.h> -+ -+#include "libcamera/internal/bayer_format.h" -+ -+namespace libcamera { -+ -+/** -+ * \class SwStatsCpu -+ * \brief Class for gathering statistics on the CPU -+ * -+ * CPU based software ISP statistics implementation. -+ * -+ * This class offers a configure function + functions to gather statistics -+ * on a line by line basis. This allows CPU based software debayering to -+ * interlace debayering and statistics gathering on a line by line basis -+ * while the input data is still hot in the cache. -+ * -+ * It is also possible to specify a window over which to gather -+ * statistics instead of processing the whole frame. -+ */ -+ -+LOG_DEFINE_CATEGORY(SwStatsCpu) -+ -+SwStatsCpu::SwStatsCpu() -+{ -+ sharedStats_ = SharedMemObject<SwIspStats>("softIsp_stats"); -+ if (!sharedStats_.fd().isValid()) -+ LOG(SwStatsCpu, Error) -+ << "Failed to create shared memory for statistics"; -+} -+ -+static const unsigned int kRedYMul = 77; /* 0.299 * 256 */ -+static const unsigned int kGreenYMul = 150; /* 0.587 * 256 */ -+static const unsigned int kBlueYMul = 29; /* 0.114 * 256 */ -+ -+#define SWSTATS_START_LINE_STATS(pixel_t) \ -+ pixel_t r, g, g2, b; \ -+ unsigned int yVal; \ -+ \ -+ unsigned int sumR = 0; \ -+ unsigned int sumG = 0; \ -+ unsigned int sumB = 0; -+ -+#define SWSTATS_ACCUMULATE_LINE_STATS(div) \ -+ sumR += r; \ -+ sumG += g; \ -+ sumB += b; \ -+ \ -+ yVal = r * kRedYMul; \ -+ yVal += g * kGreenYMul; \ -+ yVal += b * kBlueYMul; \ -+ stats_.yHistogram[yVal * SwIspStats::kYHistogramSize / (256 * 256 * (div))]++; -+ -+#define SWSTATS_FINISH_LINE_STATS() \ -+ stats_.sumR_ += sumR; \ -+ stats_.sumG_ += sumG; \ -+ stats_.sumB_ += sumB; -+ -+void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[]) -+{ -+ const uint8_t *src0 = src[1] + window_.x * 5 / 4; -+ const uint8_t *src1 = src[2] + window_.x * 5 / 4; -+ const int widthInBytes = window_.width * 5 / 4; -+ -+ if (swapLines_) -+ std::swap(src0, src1); -+ -+ SWSTATS_START_LINE_STATS(uint8_t) -+ -+ /* x += 5 sample every other 2x2 block */ -+ for (int x = 0; x < widthInBytes; x += 5) { -+ /* BGGR */ -+ b = src0[x]; -+ g = src0[x + 1]; -+ g2 = src1[x]; -+ r = src1[x + 1]; -+ g = (g + g2) / 2; -+ /* Data is already 8 bits, divide by 1 */ -+ SWSTATS_ACCUMULATE_LINE_STATS(1) -+ } -+ -+ SWSTATS_FINISH_LINE_STATS() -+} -+ -+void SwStatsCpu::statsGBRG10PLine0(const uint8_t *src[]) -+{ -+ const uint8_t *src0 = src[1] + window_.x * 5 / 4; -+ const uint8_t *src1 = src[2] + window_.x * 5 / 4; -+ const int widthInBytes = window_.width * 5 / 4; -+ -+ if (swapLines_) -+ std::swap(src0, src1); -+ -+ SWSTATS_START_LINE_STATS(uint8_t) -+ -+ /* x += 5 sample every other 2x2 block */ -+ for (int x = 0; x < widthInBytes; x += 5) { -+ /* GBRG */ -+ g = src0[x]; -+ b = src0[x + 1]; -+ r = src1[x]; -+ g2 = src1[x + 1]; -+ g = (g + g2) / 2; -+ /* Data is already 8 bits, divide by 1 */ -+ SWSTATS_ACCUMULATE_LINE_STATS(1) -+ } -+ -+ SWSTATS_FINISH_LINE_STATS() -+} -+ -+/** -+ * \brief Reset state to start statistics gathering for a new frame. -+ * -+ * This may only be called after a successful setWindow() call. -+ */ -+void SwStatsCpu::startFrame(void) -+{ -+ stats_.sumR_ = 0; -+ stats_.sumB_ = 0; -+ stats_.sumG_ = 0; -+ stats_.yHistogram.fill(0); -+} -+ -+/** -+ * \brief Finish statistics calculation for the current frame. -+ * -+ * This may only be called after a successful setWindow() call. -+ */ -+void SwStatsCpu::finishFrame(void) -+{ -+ *sharedStats_ = stats_; -+ statsReady.emit(0); -+} -+ -+/** -+ * \brief Configure the statistics object for the passed in input format. -+ * \param[in] inputCfg The input format -+ * -+ * \return 0 on success, a negative errno value on failure -+ */ -+int SwStatsCpu::configure(const StreamConfiguration &inputCfg) -+{ -+ BayerFormat bayerFormat = -+ BayerFormat::fromPixelFormat(inputCfg.pixelFormat); -+ -+ if (bayerFormat.bitDepth == 10 && -+ bayerFormat.packing == BayerFormat::Packing::CSI2) { -+ patternSize_.height = 2; -+ patternSize_.width = 4; /* 5 bytes per *4* pixels */ -+ /* Skip every 3th and 4th line, sample every other 2x2 block */ -+ ySkipMask_ = 0x02; -+ xShift_ = 0; -+ -+ switch (bayerFormat.order) { -+ case BayerFormat::BGGR: -+ case BayerFormat::GRBG: -+ stats0_ = &SwStatsCpu::statsBGGR10PLine0; -+ swapLines_ = bayerFormat.order == BayerFormat::GRBG; -+ return 0; -+ case BayerFormat::GBRG: -+ case BayerFormat::RGGB: -+ stats0_ = &SwStatsCpu::statsGBRG10PLine0; -+ swapLines_ = bayerFormat.order == BayerFormat::RGGB; -+ return 0; -+ default: -+ break; -+ } -+ } -+ -+ LOG(SwStatsCpu, Info) -+ << "Unsupported input format " << inputCfg.pixelFormat.toString(); -+ return -EINVAL; -+} -+ -+/** -+ * \brief Specify window coordinates over which to gather statistics. -+ * \param[in] window The window object. -+ */ -+void SwStatsCpu::setWindow(Rectangle window) -+{ -+ window_ = window; -+ -+ window_.x &= ~(patternSize_.width - 1); -+ window_.x += xShift_; -+ window_.y &= ~(patternSize_.height - 1); -+ -+ /* width_ - xShift_ to make sure the window fits */ -+ window_.width -= xShift_; -+ window_.width &= ~(patternSize_.width - 1); -+ window_.height &= ~(patternSize_.height - 1); -+} -+ -+} /* namespace libcamera */ -diff --git a/src/libcamera/software_isp/swstats_cpu.h b/src/libcamera/software_isp/swstats_cpu.h -new file mode 100644 -index 00000000..0ac9ae71 ---- /dev/null -+++ b/src/libcamera/software_isp/swstats_cpu.h -@@ -0,0 +1,159 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Linaro Ltd -+ * Copyright (C) 2023, Red Hat Inc. -+ * -+ * Authors: -+ * Hans de Goede <hdegoede@redhat.com> -+ * -+ * swstats_cpu.h - CPU based software statistics implementation -+ */ -+ -+#pragma once -+ -+#include <stdint.h> -+ -+#include <libcamera/base/signal.h> -+ -+#include <libcamera/geometry.h> -+ -+#include "libcamera/internal/shared_mem_object.h" -+#include "libcamera/internal/software_isp/swisp_stats.h" -+ -+namespace libcamera { -+ -+class PixelFormat; -+struct StreamConfiguration; -+ -+class SwStatsCpu -+{ -+public: -+ SwStatsCpu(); -+ ~SwStatsCpu() = default; -+ -+ /** -+ * \brief Gets whether the statistics object is valid. -+ * -+ * \return true if it's valid, false otherwise -+ */ -+ bool isValid() const { return sharedStats_.fd().isValid(); } -+ -+ /** -+ * \brief Get the file descriptor for the statistics. -+ * -+ * \return the file descriptor -+ */ -+ const SharedFD &getStatsFD() { return sharedStats_.fd(); } -+ -+ /** -+ * \brief Get the pattern size. -+ * -+ * For some input-formats, e.g. Bayer data, processing is done multiple lines -+ * and/or columns at a time. Get width and height at which the (bayer) pattern -+ * repeats. Window values are rounded down to a multiple of this and the height -+ * also indicates if processLine2() should be called or not. -+ * This may only be called after a successful configure() call. -+ * -+ * \return the pattern size -+ */ -+ const Size &patternSize() { return patternSize_; } -+ -+ int configure(const StreamConfiguration &inputCfg); -+ void setWindow(Rectangle window); -+ void startFrame(); -+ void finishFrame(); -+ -+ /** -+ * \brief Process line 0. -+ * \param[in] y The y coordinate. -+ * \param[in] src The input data. -+ * -+ * This function processes line 0 for input formats with patternSize height == 1. -+ * It'll process line 0 and 1 for input formats with patternSize height >= 2. -+ * This function may only be called after a successful setWindow() call. -+ */ -+ void processLine0(unsigned int y, const uint8_t *src[]) -+ { -+ if ((y & ySkipMask_) || y < (unsigned int)window_.y || -+ y >= (window_.y + window_.height)) -+ return; -+ -+ (this->*stats0_)(src); -+ } -+ -+ /** -+ * \brief Process line 2 and 3. -+ * \param[in] y The y coordinate. -+ * \param[in] src The input data. -+ * -+ * This function processes line 2 and 3 for input formats with patternSize height == 4. -+ * This function may only be called after a successful setWindow() call. -+ */ -+ void processLine2(unsigned int y, const uint8_t *src[]) -+ { -+ if ((y & ySkipMask_) || y < (unsigned int)window_.y || -+ y >= (window_.y + window_.height)) -+ return; -+ -+ (this->*stats2_)(src); -+ } -+ -+ /** -+ * \brief Signals that the statistics are ready. -+ * -+ * The int parameter isn't actually used. -+ */ -+ Signal<int> statsReady; -+ -+private: -+ /** -+ * \brief Called when there is data to get statistics from. -+ * \param[in] src The input data -+ * -+ * These functions take an array of (patternSize_.height + 1) src -+ * pointers each pointing to a line in the source image. The middle -+ * element of the array will point to the actual line being processed. -+ * Earlier element(s) will point to the previous line(s) and later -+ * element(s) to the next line(s). -+ * -+ * See the documentation of DebayerCpu::debayerFn for more details. -+ */ -+ using statsProcessFn = void (SwStatsCpu::*)(const uint8_t *src[]); -+ -+ void statsBGGR10PLine0(const uint8_t *src[]); -+ void statsGBRG10PLine0(const uint8_t *src[]); -+ -+ /* Variables set by configure(), used every line */ -+ statsProcessFn stats0_; -+ statsProcessFn stats2_; -+ bool swapLines_; -+ -+ /** -+ * \brief Skip lines where this bitmask is set in y. -+ */ -+ unsigned int ySkipMask_; -+ -+ /** -+ * \brief Statistics window, set by setWindow(), used ever line. -+ */ -+ Rectangle window_; -+ -+ /** -+ * \brief The size of the bayer pattern. -+ * -+ * Valid sizes are: 2x2, 4x2 or 4x4. -+ */ -+ Size patternSize_; -+ -+ /** -+ * \brief The offset of x, applied to window_.x for bayer variants. -+ * -+ * This can either be 0 or 1. -+ */ -+ unsigned int xShift_; -+ -+ SharedMemObject<SwIspStats> sharedStats_; -+ SwIspStats stats_; -+}; -+ -+} /* namespace libcamera */ --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0007-libcamera-software_isp-Add-Debayer-base-class.patch b/users/flokli/ipu6-softisp/libcamera/0007-libcamera-software_isp-Add-Debayer-base-class.patch deleted file mode 100644 index 7c7170989666..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0007-libcamera-software_isp-Add-Debayer-base-class.patch +++ /dev/null @@ -1,255 +0,0 @@ -From 25e6893e46bd2174f6913eea79817988d9280706 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Mon, 11 Mar 2024 15:15:11 +0100 -Subject: [PATCH 07/21] libcamera: software_isp: Add Debayer base class - -Add a base class for debayer implementations. This is intended to be -suitable for both GPU (or otherwise) accelerated debayer implementations -as well as CPU based debayering. - -Doxygen documentation by Dennis Bonke. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> -Co-developed-by: Dennis Bonke <admin@dennisbonke.com> -Signed-off-by: Dennis Bonke <admin@dennisbonke.com> -Co-developed-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - .../internal/software_isp/debayer_params.h | 48 ++++++++ - .../internal/software_isp/meson.build | 1 + - src/libcamera/software_isp/debayer.cpp | 29 +++++ - src/libcamera/software_isp/debayer.h | 104 ++++++++++++++++++ - src/libcamera/software_isp/meson.build | 1 + - 5 files changed, 183 insertions(+) - create mode 100644 include/libcamera/internal/software_isp/debayer_params.h - create mode 100644 src/libcamera/software_isp/debayer.cpp - create mode 100644 src/libcamera/software_isp/debayer.h - -diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h -new file mode 100644 -index 00000000..98965fa1 ---- /dev/null -+++ b/include/libcamera/internal/software_isp/debayer_params.h -@@ -0,0 +1,48 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Red Hat Inc. -+ * -+ * Authors: -+ * Hans de Goede <hdegoede@redhat.com> -+ * -+ * debayer_params.h - DebayerParams header -+ */ -+ -+#pragma once -+ -+namespace libcamera { -+ -+/** -+ * \brief Struct to hold the debayer parameters. -+ */ -+struct DebayerParams { -+ /** -+ * \brief const value for 1.0 gain -+ */ -+ static constexpr unsigned int kGain10 = 256; -+ -+ /** -+ * \brief Red Gain -+ * -+ * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc. -+ */ -+ unsigned int gainR; -+ /** -+ * \brief Green Gain -+ * -+ * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc. -+ */ -+ unsigned int gainG; -+ /** -+ * \brief Blue Gain -+ * -+ * 128 = 0.5, 256 = 1.0, 512 = 2.0, etc. -+ */ -+ unsigned int gainB; -+ /** -+ * \brief Gamma correction, 1.0 is no correction -+ */ -+ float gamma; -+}; -+ -+} /* namespace libcamera */ -diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build -index 66c9c3fb..a620e16d 100644 ---- a/include/libcamera/internal/software_isp/meson.build -+++ b/include/libcamera/internal/software_isp/meson.build -@@ -1,5 +1,6 @@ - # SPDX-License-Identifier: CC0-1.0 - - libcamera_internal_headers += files([ -+ 'debayer_params.h', - 'swisp_stats.h', - ]) -diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp -new file mode 100644 -index 00000000..64f0b5a0 ---- /dev/null -+++ b/src/libcamera/software_isp/debayer.cpp -@@ -0,0 +1,29 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Linaro Ltd -+ * Copyright (C) 2023, Red Hat Inc. -+ * -+ * Authors: -+ * Hans de Goede <hdegoede@redhat.com> -+ * -+ * debayer.cpp - debayer base class -+ */ -+ -+#include "debayer.h" -+ -+namespace libcamera { -+ -+/** -+ * \class Debayer -+ * \brief Base debayering class -+ * -+ * Base class that provides functions for setting up the debayering process. -+ */ -+ -+LOG_DEFINE_CATEGORY(Debayer) -+ -+Debayer::~Debayer() -+{ -+} -+ -+} /* namespace libcamera */ -diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h -new file mode 100644 -index 00000000..8880ff99 ---- /dev/null -+++ b/src/libcamera/software_isp/debayer.h -@@ -0,0 +1,104 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Linaro Ltd -+ * Copyright (C) 2023, Red Hat Inc. -+ * -+ * Authors: -+ * Hans de Goede <hdegoede@redhat.com> -+ * -+ * debayer.h - debayering base class -+ */ -+ -+#pragma once -+ -+#include <stdint.h> -+ -+#include <libcamera/base/log.h> -+#include <libcamera/base/signal.h> -+ -+#include <libcamera/geometry.h> -+#include <libcamera/stream.h> -+ -+#include "libcamera/internal/software_isp/debayer_params.h" -+ -+namespace libcamera { -+ -+class FrameBuffer; -+ -+LOG_DECLARE_CATEGORY(Debayer) -+ -+class Debayer -+{ -+public: -+ virtual ~Debayer() = 0; -+ -+ /** -+ * \brief Configure the debayer object according to the passed in parameters. -+ * \param[in] inputCfg The input configuration. -+ * \param[in] outputCfgs The output configurations. -+ * -+ * \return 0 on success, a negative errno on failure. -+ */ -+ virtual int configure(const StreamConfiguration &inputCfg, -+ const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs) = 0; -+ -+ /** -+ * \brief Get the width and height at which the bayer pattern repeats. -+ * \param[in] inputFormat The input format. -+ * -+ * Valid sizes are: 2x2, 4x2 or 4x4. -+ * -+ * \return pattern size or an empty size for unsupported inputFormats. -+ */ -+ virtual Size patternSize(PixelFormat inputFormat) = 0; -+ -+ /** -+ * \brief Get the supported output formats. -+ * \param[in] inputFormat The input format. -+ * -+ * \return all supported output formats or an empty vector if there are none. -+ */ -+ virtual std::vector<PixelFormat> formats(PixelFormat inputFormat) = 0; -+ -+ /** -+ * \brief Get the stride and the frame size. -+ * \param[in] outputFormat The output format. -+ * \param[in] size The output size. -+ * -+ * \return a tuple of the stride and the frame size, or a tuple with 0,0 if there is no valid output config. -+ */ -+ virtual std::tuple<unsigned int, unsigned int> -+ strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) = 0; -+ -+ /** -+ * \brief Process the bayer data into the requested format. -+ * \param[in] input The input buffer. -+ * \param[in] output The output buffer. -+ * \param[in] params The parameters to be used in debayering. -+ * -+ * \note DebayerParams is passed by value deliberately so that a copy is passed -+ * when this is run in another thread by invokeMethod(). -+ */ -+ virtual void process(FrameBuffer *input, FrameBuffer *output, DebayerParams params) = 0; -+ -+ /** -+ * \brief Get the supported output sizes for the given input format and size. -+ * \param[in] inputFormat The input format. -+ * \param[in] inputSize The input size. -+ * -+ * \return The valid size ranges or an empty range if there are none. -+ */ -+ virtual SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) = 0; -+ -+ /** -+ * \brief Signals when the input buffer is ready. -+ */ -+ Signal<FrameBuffer *> inputBufferReady; -+ -+ /** -+ * \brief Signals when the output buffer is ready. -+ */ -+ Signal<FrameBuffer *> outputBufferReady; -+}; -+ -+} /* namespace libcamera */ -diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build -index fcfff74a..62095f61 100644 ---- a/src/libcamera/software_isp/meson.build -+++ b/src/libcamera/software_isp/meson.build -@@ -8,5 +8,6 @@ if not (softisp_enabled) - endif - - libcamera_sources += files([ -+ 'debayer.cpp', - 'swstats_cpu.cpp', - ]) --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0008-libcamera-software_isp-Add-DebayerCpu-class.patch b/users/flokli/ipu6-softisp/libcamera/0008-libcamera-software_isp-Add-DebayerCpu-class.patch deleted file mode 100644 index f549769f2fde..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0008-libcamera-software_isp-Add-DebayerCpu-class.patch +++ /dev/null @@ -1,825 +0,0 @@ -From 5f57a52ea1054cac73344d83ff605cba0df0d279 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Mon, 11 Mar 2024 15:15:12 +0100 -Subject: [PATCH 08/21] libcamera: software_isp: Add DebayerCpu class - -Add CPU based debayering implementation. This initial implementation -only supports debayering packed 10 bits per pixel bayer data in -the 4 standard bayer orders. - -Doxygen documentation by Dennis Bonke. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Co-developed-by: Dennis Bonke <admin@dennisbonke.com> -Signed-off-by: Dennis Bonke <admin@dennisbonke.com> -Co-developed-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Co-developed-by: Pavel Machek <pavel@ucw.cz> -Signed-off-by: Pavel Machek <pavel@ucw.cz> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> ---- - src/libcamera/software_isp/debayer_cpu.cpp | 626 +++++++++++++++++++++ - src/libcamera/software_isp/debayer_cpu.h | 143 +++++ - src/libcamera/software_isp/meson.build | 1 + - 3 files changed, 770 insertions(+) - create mode 100644 src/libcamera/software_isp/debayer_cpu.cpp - create mode 100644 src/libcamera/software_isp/debayer_cpu.h - -diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp -new file mode 100644 -index 00000000..f932362c ---- /dev/null -+++ b/src/libcamera/software_isp/debayer_cpu.cpp -@@ -0,0 +1,626 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Linaro Ltd -+ * Copyright (C) 2023, Red Hat Inc. -+ * -+ * Authors: -+ * Hans de Goede <hdegoede@redhat.com> -+ * -+ * debayer_cpu.cpp - CPU based debayering class -+ */ -+ -+#include "debayer_cpu.h" -+ -+#include <math.h> -+#include <stdlib.h> -+#include <time.h> -+ -+#include <libcamera/formats.h> -+ -+#include "libcamera/internal/bayer_format.h" -+#include "libcamera/internal/framebuffer.h" -+#include "libcamera/internal/mapped_framebuffer.h" -+ -+namespace libcamera { -+ -+/** -+ * \class DebayerCpu -+ * \brief Class for debayering on the CPU -+ * -+ * Implementation for CPU based debayering -+ */ -+ -+/** -+ * \brief Constructs a DebayerCpu object. -+ * \param[in] stats Pointer to the stats object to use. -+ */ -+DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats) -+ : stats_(std::move(stats)), gamma_correction_(1.0) -+{ -+#ifdef __x86_64__ -+ enableInputMemcpy_ = false; -+#else -+ enableInputMemcpy_ = true; -+#endif -+ /* Initialize gamma to 1.0 curve */ -+ for (unsigned int i = 0; i < kGammaLookupSize; i++) -+ gamma_[i] = i / (kGammaLookupSize / kRGBLookupSize); -+ -+ for (unsigned int i = 0; i < kMaxLineBuffers; i++) -+ lineBuffers_[i] = nullptr; -+} -+ -+DebayerCpu::~DebayerCpu() -+{ -+ for (unsigned int i = 0; i < kMaxLineBuffers; i++) -+ free(lineBuffers_[i]); -+} -+ -+// RGR -+// GBG -+// RGR -+#define BGGR_BGR888(p, n, div) \ -+ *dst++ = blue_[curr[x] / (div)]; \ -+ *dst++ = green_[(prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div))]; \ -+ *dst++ = red_[(prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))]; \ -+ x++; -+ -+// GBG -+// RGR -+// GBG -+#define GRBG_BGR888(p, n, div) \ -+ *dst++ = blue_[(prev[x] + next[x]) / (2 * (div))]; \ -+ *dst++ = green_[curr[x] / (div)]; \ -+ *dst++ = red_[(curr[x - p] + curr[x + n]) / (2 * (div))]; \ -+ x++; -+ -+// GRG -+// BGB -+// GRG -+#define GBRG_BGR888(p, n, div) \ -+ *dst++ = blue_[(curr[x - p] + curr[x + n]) / (2 * (div))]; \ -+ *dst++ = green_[curr[x] / (div)]; \ -+ *dst++ = red_[(prev[x] + next[x]) / (2 * (div))]; \ -+ x++; -+ -+// BGB -+// GRG -+// BGB -+#define RGGB_BGR888(p, n, div) \ -+ *dst++ = blue_[(prev[x - p] + prev[x + n] + next[x - p] + next[x + n]) / (4 * (div))]; \ -+ *dst++ = green_[(prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div))]; \ -+ *dst++ = red_[curr[x] / (div)]; \ -+ x++; -+ -+void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) -+{ -+ const int width_in_bytes = window_.width * 5 / 4; -+ const uint8_t *prev = (const uint8_t *)src[0]; -+ const uint8_t *curr = (const uint8_t *)src[1]; -+ const uint8_t *next = (const uint8_t *)src[2]; -+ -+ /* -+ * For the first pixel getting a pixel from the previous column uses -+ * x - 2 to skip the 5th byte with least-significant bits for 4 pixels. -+ * Same for last pixel (uses x + 2) and looking at the next column. -+ */ -+ for (int x = 0; x < width_in_bytes;) { -+ /* First pixel */ -+ BGGR_BGR888(2, 1, 1) -+ /* Second pixel BGGR -> GBRG */ -+ GBRG_BGR888(1, 1, 1) -+ /* Same thing for third and fourth pixels */ -+ BGGR_BGR888(1, 1, 1) -+ GBRG_BGR888(1, 2, 1) -+ /* Skip 5th src byte with 4 x 2 least-significant-bits */ -+ x++; -+ } -+} -+ -+void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) -+{ -+ const int width_in_bytes = window_.width * 5 / 4; -+ const uint8_t *prev = (const uint8_t *)src[0]; -+ const uint8_t *curr = (const uint8_t *)src[1]; -+ const uint8_t *next = (const uint8_t *)src[2]; -+ -+ for (int x = 0; x < width_in_bytes;) { -+ /* First pixel */ -+ GRBG_BGR888(2, 1, 1) -+ /* Second pixel GRBG -> RGGB */ -+ RGGB_BGR888(1, 1, 1) -+ /* Same thing for third and fourth pixels */ -+ GRBG_BGR888(1, 1, 1) -+ RGGB_BGR888(1, 2, 1) -+ /* Skip 5th src byte with 4 x 2 least-significant-bits */ -+ x++; -+ } -+} -+ -+void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]) -+{ -+ const int width_in_bytes = window_.width * 5 / 4; -+ const uint8_t *prev = (const uint8_t *)src[0]; -+ const uint8_t *curr = (const uint8_t *)src[1]; -+ const uint8_t *next = (const uint8_t *)src[2]; -+ -+ for (int x = 0; x < width_in_bytes;) { -+ /* Even pixel */ -+ GBRG_BGR888(2, 1, 1) -+ /* Odd pixel GBGR -> BGGR */ -+ BGGR_BGR888(1, 1, 1) -+ /* Same thing for next 2 pixels */ -+ GBRG_BGR888(1, 1, 1) -+ BGGR_BGR888(1, 2, 1) -+ /* Skip 5th src byte with 4 x 2 least-significant-bits */ -+ x++; -+ } -+} -+ -+void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]) -+{ -+ const int width_in_bytes = window_.width * 5 / 4; -+ const uint8_t *prev = (const uint8_t *)src[0]; -+ const uint8_t *curr = (const uint8_t *)src[1]; -+ const uint8_t *next = (const uint8_t *)src[2]; -+ -+ for (int x = 0; x < width_in_bytes;) { -+ /* Even pixel */ -+ RGGB_BGR888(2, 1, 1) -+ /* Odd pixel RGGB -> GRBG */ -+ GRBG_BGR888(1, 1, 1) -+ /* Same thing for next 2 pixels */ -+ RGGB_BGR888(1, 1, 1) -+ GRBG_BGR888(1, 2, 1) -+ /* Skip 5th src byte with 4 x 2 least-significant-bits */ -+ x++; -+ } -+} -+ -+static bool isStandardBayerOrder(BayerFormat::Order order) -+{ -+ return order == BayerFormat::BGGR || order == BayerFormat::GBRG || -+ order == BayerFormat::GRBG || order == BayerFormat::RGGB; -+} -+ -+/* -+ * Setup the Debayer object according to the passed in parameters. -+ * Return 0 on success, a negative errno value on failure -+ * (unsupported parameters). -+ */ -+int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config) -+{ -+ BayerFormat bayerFormat = -+ BayerFormat::fromPixelFormat(inputFormat); -+ -+ if (bayerFormat.bitDepth == 10 && -+ bayerFormat.packing == BayerFormat::Packing::CSI2 && -+ isStandardBayerOrder(bayerFormat.order)) { -+ config.bpp = 10; -+ config.patternSize.width = 4; /* 5 bytes per *4* pixels */ -+ config.patternSize.height = 2; -+ config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 }); -+ return 0; -+ } -+ -+ LOG(Debayer, Info) -+ << "Unsupported input format " << inputFormat.toString(); -+ return -EINVAL; -+} -+ -+int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config) -+{ -+ if (outputFormat == formats::RGB888) { -+ config.bpp = 24; -+ return 0; -+ } -+ -+ LOG(Debayer, Info) -+ << "Unsupported output format " << outputFormat.toString(); -+ return -EINVAL; -+} -+ -+/* TODO: this ignores outputFormat since there is only 1 supported outputFormat for now */ -+int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat) -+{ -+ BayerFormat bayerFormat = -+ BayerFormat::fromPixelFormat(inputFormat); -+ -+ if (bayerFormat.bitDepth == 10 && -+ bayerFormat.packing == BayerFormat::Packing::CSI2) { -+ switch (bayerFormat.order) { -+ case BayerFormat::BGGR: -+ debayer0_ = &DebayerCpu::debayer10P_BGBG_BGR888; -+ debayer1_ = &DebayerCpu::debayer10P_GRGR_BGR888; -+ return 0; -+ case BayerFormat::GBRG: -+ debayer0_ = &DebayerCpu::debayer10P_GBGB_BGR888; -+ debayer1_ = &DebayerCpu::debayer10P_RGRG_BGR888; -+ return 0; -+ case BayerFormat::GRBG: -+ debayer0_ = &DebayerCpu::debayer10P_GRGR_BGR888; -+ debayer1_ = &DebayerCpu::debayer10P_BGBG_BGR888; -+ return 0; -+ case BayerFormat::RGGB: -+ debayer0_ = &DebayerCpu::debayer10P_RGRG_BGR888; -+ debayer1_ = &DebayerCpu::debayer10P_GBGB_BGR888; -+ return 0; -+ default: -+ break; -+ } -+ } -+ -+ LOG(Debayer, Error) << "Unsupported input output format combination"; -+ return -EINVAL; -+} -+ -+int DebayerCpu::configure(const StreamConfiguration &inputCfg, -+ const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs) -+{ -+ if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) -+ return -EINVAL; -+ -+ if (stats_->configure(inputCfg) != 0) -+ return -EINVAL; -+ -+ const Size &stats_pattern_size = stats_->patternSize(); -+ if (inputConfig_.patternSize.width != stats_pattern_size.width || -+ inputConfig_.patternSize.height != stats_pattern_size.height) { -+ LOG(Debayer, Error) -+ << "mismatching stats and debayer pattern sizes for " -+ << inputCfg.pixelFormat.toString(); -+ return -EINVAL; -+ } -+ -+ inputConfig_.stride = inputCfg.stride; -+ -+ if (outputCfgs.size() != 1) { -+ LOG(Debayer, Error) -+ << "Unsupported number of output streams: " -+ << outputCfgs.size(); -+ return -EINVAL; -+ } -+ -+ const StreamConfiguration &outputCfg = outputCfgs[0]; -+ SizeRange outSizeRange = sizes(inputCfg.pixelFormat, inputCfg.size); -+ std::tie(outputConfig_.stride, outputConfig_.frameSize) = -+ strideAndFrameSize(outputCfg.pixelFormat, outputCfg.size); -+ -+ if (!outSizeRange.contains(outputCfg.size) || outputConfig_.stride != outputCfg.stride) { -+ LOG(Debayer, Error) -+ << "Invalid output size/stride: " -+ << "\n " << outputCfg.size << " (" << outSizeRange << ")" -+ << "\n " << outputCfg.stride << " (" << outputConfig_.stride << ")"; -+ return -EINVAL; -+ } -+ -+ if (setDebayerFunctions(inputCfg.pixelFormat, outputCfg.pixelFormat) != 0) -+ return -EINVAL; -+ -+ window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) & -+ ~(inputConfig_.patternSize.width - 1); -+ window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) & -+ ~(inputConfig_.patternSize.height - 1); -+ window_.width = outputCfg.size.width; -+ window_.height = outputCfg.size.height; -+ -+ /* Don't pass x,y since process() already adjusts src before passing it */ -+ stats_->setWindow(Rectangle(window_.size())); -+ -+ /* pad with patternSize.Width on both left and right side */ -+ lineBufferPadding_ = inputConfig_.patternSize.width * inputConfig_.bpp / 8; -+ lineBufferLength_ = window_.width * inputConfig_.bpp / 8 + -+ 2 * lineBufferPadding_; -+ for (unsigned int i = 0; -+ i < (inputConfig_.patternSize.height + 1) && enableInputMemcpy_; -+ i++) { -+ free(lineBuffers_[i]); -+ lineBuffers_[i] = (uint8_t *)malloc(lineBufferLength_); -+ if (!lineBuffers_[i]) -+ return -ENOMEM; -+ } -+ -+ measuredFrames_ = 0; -+ frameProcessTime_ = 0; -+ -+ return 0; -+} -+ -+/* -+ * Get width and height at which the bayer-pattern repeats. -+ * Return pattern-size or an empty Size for an unsupported inputFormat. -+ */ -+Size DebayerCpu::patternSize(PixelFormat inputFormat) -+{ -+ DebayerCpu::DebayerInputConfig config; -+ -+ if (getInputConfig(inputFormat, config) != 0) -+ return {}; -+ -+ return config.patternSize; -+} -+ -+std::vector<PixelFormat> DebayerCpu::formats(PixelFormat inputFormat) -+{ -+ DebayerCpu::DebayerInputConfig config; -+ -+ if (getInputConfig(inputFormat, config) != 0) -+ return std::vector<PixelFormat>(); -+ -+ return config.outputFormats; -+} -+ -+std::tuple<unsigned int, unsigned int> -+DebayerCpu::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) -+{ -+ DebayerCpu::DebayerOutputConfig config; -+ -+ if (getOutputConfig(outputFormat, config) != 0) -+ return std::make_tuple(0, 0); -+ -+ /* round up to multiple of 8 for 64 bits alignment */ -+ unsigned int stride = (size.width * config.bpp / 8 + 7) & ~7; -+ -+ return std::make_tuple(stride, stride * size.height); -+} -+ -+void DebayerCpu::setupInputMemcpy(const uint8_t *linePointers[]) -+{ -+ const unsigned int patternHeight = inputConfig_.patternSize.height; -+ -+ if (!enableInputMemcpy_) -+ return; -+ -+ for (unsigned int i = 0; i < patternHeight; i++) { -+ memcpy(lineBuffers_[i], linePointers[i + 1] - lineBufferPadding_, -+ lineBufferLength_); -+ linePointers[i + 1] = lineBuffers_[i] + lineBufferPadding_; -+ } -+ -+ /* Point lineBufferIndex_ to first unused lineBuffer */ -+ lineBufferIndex_ = patternHeight; -+} -+ -+void DebayerCpu::shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src) -+{ -+ const unsigned int patternHeight = inputConfig_.patternSize.height; -+ -+ for (unsigned int i = 0; i < patternHeight; i++) -+ linePointers[i] = linePointers[i + 1]; -+ -+ linePointers[patternHeight] = src + -+ (patternHeight / 2) * (int)inputConfig_.stride; -+} -+ -+void DebayerCpu::memcpyNextLine(const uint8_t *linePointers[]) -+{ -+ const unsigned int patternHeight = inputConfig_.patternSize.height; -+ -+ if (!enableInputMemcpy_) -+ return; -+ -+ memcpy(lineBuffers_[lineBufferIndex_], linePointers[patternHeight] - lineBufferPadding_, -+ lineBufferLength_); -+ linePointers[patternHeight] = lineBuffers_[lineBufferIndex_] + lineBufferPadding_; -+ -+ lineBufferIndex_ = (lineBufferIndex_ + 1) % (patternHeight + 1); -+} -+ -+void DebayerCpu::process2(const uint8_t *src, uint8_t *dst) -+{ -+ unsigned int y_end = window_.y + window_.height; -+ /* Holds [0] previous- [1] current- [2] next-line */ -+ const uint8_t *linePointers[3]; -+ -+ /* Adjust src to top left corner of the window */ -+ src += window_.y * inputConfig_.stride + window_.x * inputConfig_.bpp / 8; -+ -+ /* [x] becomes [x - 1] after initial shiftLinePointers() call */ -+ if (window_.y) { -+ linePointers[1] = src - inputConfig_.stride; /* previous-line */ -+ linePointers[2] = src; -+ } else { -+ /* window_.y == 0, use the next line as prev line */ -+ linePointers[1] = src + inputConfig_.stride; -+ linePointers[2] = src; -+ /* Last 2 lines also need special handling */ -+ y_end -= 2; -+ } -+ -+ setupInputMemcpy(linePointers); -+ -+ for (unsigned int y = window_.y; y < y_end; y += 2) { -+ shiftLinePointers(linePointers, src); -+ memcpyNextLine(linePointers); -+ stats_->processLine0(y, linePointers); -+ (this->*debayer0_)(dst, linePointers); -+ src += inputConfig_.stride; -+ dst += outputConfig_.stride; -+ -+ shiftLinePointers(linePointers, src); -+ memcpyNextLine(linePointers); -+ (this->*debayer1_)(dst, linePointers); -+ src += inputConfig_.stride; -+ dst += outputConfig_.stride; -+ } -+ -+ if (window_.y == 0) { -+ shiftLinePointers(linePointers, src); -+ memcpyNextLine(linePointers); -+ stats_->processLine0(y_end, linePointers); -+ (this->*debayer0_)(dst, linePointers); -+ src += inputConfig_.stride; -+ dst += outputConfig_.stride; -+ -+ shiftLinePointers(linePointers, src); -+ /* next line may point outside of src, use prev. */ -+ linePointers[2] = linePointers[0]; -+ (this->*debayer1_)(dst, linePointers); -+ src += inputConfig_.stride; -+ dst += outputConfig_.stride; -+ } -+} -+ -+void DebayerCpu::process4(const uint8_t *src, uint8_t *dst) -+{ -+ const unsigned int y_end = window_.y + window_.height; -+ /* -+ * This holds pointers to [0] 2-lines-up [1] 1-line-up [2] current-line -+ * [3] 1-line-down [4] 2-lines-down. -+ */ -+ const uint8_t *linePointers[5]; -+ -+ /* Adjust src to top left corner of the window */ -+ src += window_.y * inputConfig_.stride + window_.x * inputConfig_.bpp / 8; -+ -+ /* [x] becomes [x - 1] after initial shiftLinePointers() call */ -+ linePointers[1] = src - 2 * inputConfig_.stride; -+ linePointers[2] = src - inputConfig_.stride; -+ linePointers[3] = src; -+ linePointers[4] = src + inputConfig_.stride; -+ -+ setupInputMemcpy(linePointers); -+ -+ for (unsigned int y = window_.y; y < y_end; y += 4) { -+ shiftLinePointers(linePointers, src); -+ memcpyNextLine(linePointers); -+ stats_->processLine0(y, linePointers); -+ (this->*debayer0_)(dst, linePointers); -+ src += inputConfig_.stride; -+ dst += outputConfig_.stride; -+ -+ shiftLinePointers(linePointers, src); -+ memcpyNextLine(linePointers); -+ (this->*debayer1_)(dst, linePointers); -+ src += inputConfig_.stride; -+ dst += outputConfig_.stride; -+ -+ shiftLinePointers(linePointers, src); -+ memcpyNextLine(linePointers); -+ stats_->processLine2(y, linePointers); -+ (this->*debayer2_)(dst, linePointers); -+ src += inputConfig_.stride; -+ dst += outputConfig_.stride; -+ -+ shiftLinePointers(linePointers, src); -+ memcpyNextLine(linePointers); -+ (this->*debayer3_)(dst, linePointers); -+ src += inputConfig_.stride; -+ dst += outputConfig_.stride; -+ } -+} -+ -+static inline int64_t timeDiff(timespec &after, timespec &before) -+{ -+ return (after.tv_sec - before.tv_sec) * 1000000000LL + -+ (int64_t)after.tv_nsec - (int64_t)before.tv_nsec; -+} -+ -+void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams params) -+{ -+ timespec frameStartTime; -+ -+ if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure) { -+ frameStartTime = {}; -+ clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime); -+ } -+ -+ /* Apply DebayerParams */ -+ if (params.gamma != gamma_correction_) { -+ for (unsigned int i = 0; i < kGammaLookupSize; i++) -+ gamma_[i] = UINT8_MAX * powf(i / (kGammaLookupSize - 1.0), params.gamma); -+ -+ gamma_correction_ = params.gamma; -+ } -+ -+ for (unsigned int i = 0; i < kRGBLookupSize; i++) { -+ constexpr unsigned int div = -+ kRGBLookupSize * DebayerParams::kGain10 / kGammaLookupSize; -+ unsigned int idx; -+ -+ /* Apply gamma after gain! */ -+ idx = std::min({ i * params.gainR / div, (kGammaLookupSize - 1) }); -+ red_[i] = gamma_[idx]; -+ -+ idx = std::min({ i * params.gainG / div, (kGammaLookupSize - 1) }); -+ green_[i] = gamma_[idx]; -+ -+ idx = std::min({ i * params.gainB / div, (kGammaLookupSize - 1) }); -+ blue_[i] = gamma_[idx]; -+ } -+ -+ /* Copy metadata from the input buffer */ -+ FrameMetadata &metadata = output->_d()->metadata(); -+ metadata.status = input->metadata().status; -+ metadata.sequence = input->metadata().sequence; -+ metadata.timestamp = input->metadata().timestamp; -+ -+ MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); -+ MappedFrameBuffer out(output, MappedFrameBuffer::MapFlag::Write); -+ if (!in.isValid() || !out.isValid()) { -+ LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; -+ metadata.status = FrameMetadata::FrameError; -+ return; -+ } -+ -+ stats_->startFrame(); -+ -+ if (inputConfig_.patternSize.height == 2) -+ process2(in.planes()[0].data(), out.planes()[0].data()); -+ else -+ process4(in.planes()[0].data(), out.planes()[0].data()); -+ -+ metadata.planes()[0].bytesused = out.planes()[0].size(); -+ -+ /* Measure before emitting signals */ -+ if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure && -+ ++measuredFrames_ > DebayerCpu::kFramesToSkip) { -+ timespec frameEndTime = {}; -+ clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime); -+ frameProcessTime_ += timeDiff(frameEndTime, frameStartTime); -+ if (measuredFrames_ == DebayerCpu::kLastFrameToMeasure) { -+ const unsigned int measuredFrames = DebayerCpu::kLastFrameToMeasure - -+ DebayerCpu::kFramesToSkip; -+ LOG(Debayer, Info) -+ << "Processed " << measuredFrames -+ << " frames in " << frameProcessTime_ / 1000 << "us, " -+ << frameProcessTime_ / (1000 * measuredFrames) -+ << " us/frame"; -+ } -+ } -+ -+ stats_->finishFrame(); -+ outputBufferReady.emit(output); -+ inputBufferReady.emit(input); -+} -+ -+SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize) -+{ -+ Size pattern_size = patternSize(inputFormat); -+ unsigned int border_height = pattern_size.height; -+ -+ if (pattern_size.isNull()) -+ return {}; -+ -+ /* No need for top/bottom border with a pattern height of 2 */ -+ if (pattern_size.height == 2) -+ border_height = 0; -+ -+ /* -+ * For debayer interpolation a border is kept around the entire image -+ * and the minimum output size is pattern-height x pattern-width. -+ */ -+ if (inputSize.width < (3 * pattern_size.width) || -+ inputSize.height < (2 * border_height + pattern_size.height)) { -+ LOG(Debayer, Warning) -+ << "Input format size too small: " << inputSize.toString(); -+ return {}; -+ } -+ -+ return SizeRange(Size(pattern_size.width, pattern_size.height), -+ Size((inputSize.width - 2 * pattern_size.width) & ~(pattern_size.width - 1), -+ (inputSize.height - 2 * border_height) & ~(pattern_size.height - 1)), -+ pattern_size.width, pattern_size.height); -+} -+ -+} /* namespace libcamera */ -diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h -new file mode 100644 -index 00000000..8a51ed85 ---- /dev/null -+++ b/src/libcamera/software_isp/debayer_cpu.h -@@ -0,0 +1,143 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Linaro Ltd -+ * Copyright (C) 2023, Red Hat Inc. -+ * -+ * Authors: -+ * Hans de Goede <hdegoede@redhat.com> -+ * -+ * debayer_cpu.h - CPU based debayering header -+ */ -+ -+#pragma once -+ -+#include <memory> -+#include <stdint.h> -+#include <vector> -+ -+#include <libcamera/base/object.h> -+ -+#include "debayer.h" -+#include "swstats_cpu.h" -+ -+namespace libcamera { -+ -+class DebayerCpu : public Debayer, public Object -+{ -+public: -+ DebayerCpu(std::unique_ptr<SwStatsCpu> stats); -+ ~DebayerCpu(); -+ -+ int configure(const StreamConfiguration &inputCfg, -+ const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs); -+ Size patternSize(PixelFormat inputFormat); -+ std::vector<PixelFormat> formats(PixelFormat input); -+ std::tuple<unsigned int, unsigned int> -+ strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); -+ void process(FrameBuffer *input, FrameBuffer *output, DebayerParams params); -+ SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); -+ -+ /** -+ * \brief Get the file descriptor for the statistics. -+ * -+ * \return the file descriptor pointing to the statistics. -+ */ -+ const SharedFD &getStatsFD() { return stats_->getStatsFD(); } -+ -+ /** -+ * \brief Get the output frame size. -+ * -+ * \return The output frame size. -+ */ -+ unsigned int frameSize() { return outputConfig_.frameSize; } -+ -+private: -+ /** -+ * \brief Called to debayer 1 line of Bayer input data to output format -+ * \param[out] dst Pointer to the start of the output line to write -+ * \param[in] src The input data -+ * -+ * Input data is an array of (patternSize_.height + 1) src -+ * pointers each pointing to a line in the Bayer source. The middle -+ * element of the array will point to the actual line being processed. -+ * Earlier element(s) will point to the previous line(s) and later -+ * element(s) to the next line(s). -+ * -+ * These functions take an array of src pointers, rather than -+ * a single src pointer + a stride for the source, so that when the src -+ * is slow uncached memory it can be copied to faster memory before -+ * debayering. Debayering a standard 2x2 Bayer pattern requires access -+ * to the previous and next src lines for interpolating the missing -+ * colors. To allow copying the src lines only once 3 temporary buffers -+ * each holding a single line are used, re-using the oldest buffer for -+ * the next line and the pointers are swizzled so that: -+ * src[0] = previous-line, src[1] = currrent-line, src[2] = next-line. -+ * This way the 3 pointers passed to the debayer functions form -+ * a sliding window over the src avoiding the need to copy each -+ * line more than once. -+ * -+ * Similarly for bayer patterns which repeat every 4 lines, 5 src -+ * pointers are passed holding: src[0] = 2-lines-up, src[1] = 1-line-up -+ * src[2] = current-line, src[3] = 1-line-down, src[4] = 2-lines-down. -+ */ -+ using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]); -+ -+ /* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */ -+ void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); -+ void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); -+ void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]); -+ void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]); -+ -+ struct DebayerInputConfig { -+ Size patternSize; -+ unsigned int bpp; /* Memory used per pixel, not precision */ -+ unsigned int stride; -+ std::vector<PixelFormat> outputFormats; -+ }; -+ -+ struct DebayerOutputConfig { -+ unsigned int bpp; /* Memory used per pixel, not precision */ -+ unsigned int stride; -+ unsigned int frameSize; -+ }; -+ -+ int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); -+ int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); -+ int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat); -+ void setupInputMemcpy(const uint8_t *linePointers[]); -+ void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src); -+ void memcpyNextLine(const uint8_t *linePointers[]); -+ void process2(const uint8_t *src, uint8_t *dst); -+ void process4(const uint8_t *src, uint8_t *dst); -+ -+ static constexpr unsigned int kGammaLookupSize = 1024; -+ static constexpr unsigned int kRGBLookupSize = 256; -+ /* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */ -+ static constexpr unsigned int kMaxLineBuffers = 5; -+ -+ std::array<uint8_t, kGammaLookupSize> gamma_; -+ std::array<uint8_t, kRGBLookupSize> red_; -+ std::array<uint8_t, kRGBLookupSize> green_; -+ std::array<uint8_t, kRGBLookupSize> blue_; -+ debayerFn debayer0_; -+ debayerFn debayer1_; -+ debayerFn debayer2_; -+ debayerFn debayer3_; -+ Rectangle window_; -+ DebayerInputConfig inputConfig_; -+ DebayerOutputConfig outputConfig_; -+ std::unique_ptr<SwStatsCpu> stats_; -+ uint8_t *lineBuffers_[kMaxLineBuffers]; -+ unsigned int lineBufferLength_; -+ unsigned int lineBufferPadding_; -+ unsigned int lineBufferIndex_; -+ bool enableInputMemcpy_; -+ float gamma_correction_; -+ unsigned int measuredFrames_; -+ int64_t frameProcessTime_; -+ /* Skip 30 frames for things to stabilize then measure 30 frames */ -+ static constexpr unsigned int kFramesToSkip = 30; -+ static constexpr unsigned int kLastFrameToMeasure = 60; -+}; -+ -+} /* namespace libcamera */ -diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build -index 62095f61..71b46539 100644 ---- a/src/libcamera/software_isp/meson.build -+++ b/src/libcamera/software_isp/meson.build -@@ -9,5 +9,6 @@ endif - - libcamera_sources += files([ - 'debayer.cpp', -+ 'debayer_cpu.cpp', - 'swstats_cpu.cpp', - ]) --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0009-libcamera-ipa-add-Soft-IPA.patch b/users/flokli/ipu6-softisp/libcamera/0009-libcamera-ipa-add-Soft-IPA.patch deleted file mode 100644 index 40f9403ba984..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0009-libcamera-ipa-add-Soft-IPA.patch +++ /dev/null @@ -1,506 +0,0 @@ -From 5261c801d8425fa82bcbd3da0199d06153eb5bd7 Mon Sep 17 00:00:00 2001 -From: Andrey Konovalov <andrey.konovalov@linaro.org> -Date: Mon, 11 Mar 2024 15:15:13 +0100 -Subject: [PATCH 09/21] libcamera: ipa: add Soft IPA - -Define the Soft IPA main and event interfaces, add the Soft IPA -implementation. - -The current src/ipa/meson.build assumes the IPA name to match the -pipeline name. For this reason "-Dipas=simple" is used for the -Soft IPA module. - -Auto exposure/gain and AWB implementation by Dennis, Toon and Martti. - -Auto exposure/gain targets a Mean Sample Value of 2.5 following -the MSV calculation algorithm from: -https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Co-developed-by: Dennis Bonke <admin@dennisbonke.com> -Signed-off-by: Dennis Bonke <admin@dennisbonke.com> -Co-developed-by: Marttico <g.martti@gmail.com> -Signed-off-by: Marttico <g.martti@gmail.com> -Co-developed-by: Toon Langendam <t.langendam@gmail.com> -Signed-off-by: Toon Langendam <t.langendam@gmail.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - Documentation/Doxyfile.in | 1 + - include/libcamera/ipa/meson.build | 1 + - include/libcamera/ipa/soft.mojom | 28 +++ - meson_options.txt | 2 +- - src/ipa/simple/data/meson.build | 9 + - src/ipa/simple/data/soft.conf | 3 + - src/ipa/simple/meson.build | 25 +++ - src/ipa/simple/soft_simple.cpp | 326 ++++++++++++++++++++++++++++++ - 8 files changed, 394 insertions(+), 1 deletion(-) - create mode 100644 include/libcamera/ipa/soft.mojom - create mode 100644 src/ipa/simple/data/meson.build - create mode 100644 src/ipa/simple/data/soft.conf - create mode 100644 src/ipa/simple/meson.build - create mode 100644 src/ipa/simple/soft_simple.cpp - -diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in -index a86ea6c1..2be8d47b 100644 ---- a/Documentation/Doxyfile.in -+++ b/Documentation/Doxyfile.in -@@ -44,6 +44,7 @@ EXCLUDE = @TOP_SRCDIR@/include/libcamera/base/span.h \ - @TOP_SRCDIR@/src/libcamera/pipeline/ \ - @TOP_SRCDIR@/src/libcamera/tracepoints.cpp \ - @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \ -+ @TOP_BUILDDIR@/include/libcamera/ipa/soft_ipa_interface.h \ - @TOP_BUILDDIR@/src/libcamera/proxy/ - - EXCLUDE_PATTERNS = @TOP_BUILDDIR@/include/libcamera/ipa/*_serializer.h \ -diff --git a/include/libcamera/ipa/meson.build b/include/libcamera/ipa/meson.build -index f3b4881c..3352d08f 100644 ---- a/include/libcamera/ipa/meson.build -+++ b/include/libcamera/ipa/meson.build -@@ -65,6 +65,7 @@ pipeline_ipa_mojom_mapping = { - 'ipu3': 'ipu3.mojom', - 'rkisp1': 'rkisp1.mojom', - 'rpi/vc4': 'raspberrypi.mojom', -+ 'simple': 'soft.mojom', - 'vimc': 'vimc.mojom', - } - -diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom -new file mode 100644 -index 00000000..c249bd75 ---- /dev/null -+++ b/include/libcamera/ipa/soft.mojom -@@ -0,0 +1,28 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+ -+/* -+ * \todo Document the interface and remove the related EXCLUDE_PATTERNS entry. -+ */ -+ -+module ipa.soft; -+ -+import "include/libcamera/ipa/core.mojom"; -+ -+interface IPASoftInterface { -+ init(libcamera.IPASettings settings, -+ libcamera.SharedFD fdStats, -+ libcamera.SharedFD fdParams, -+ libcamera.ControlInfoMap sensorCtrlInfoMap) -+ => (int32 ret); -+ start() => (int32 ret); -+ stop(); -+ configure(libcamera.ControlInfoMap sensorCtrlInfoMap) -+ => (int32 ret); -+ -+ [async] processStats(libcamera.ControlList sensorControls); -+}; -+ -+interface IPASoftEventInterface { -+ setSensorControls(libcamera.ControlList sensorControls); -+ setIspParams(int32 dummy); -+}; -diff --git a/meson_options.txt b/meson_options.txt -index 5fdc7be8..94372e47 100644 ---- a/meson_options.txt -+++ b/meson_options.txt -@@ -27,7 +27,7 @@ option('gstreamer', - - option('ipas', - type : 'array', -- choices : ['ipu3', 'rkisp1', 'rpi/vc4', 'vimc'], -+ choices : ['ipu3', 'rkisp1', 'rpi/vc4', 'simple', 'vimc'], - description : 'Select which IPA modules to build') - - option('lc-compliance', -diff --git a/src/ipa/simple/data/meson.build b/src/ipa/simple/data/meson.build -new file mode 100644 -index 00000000..33548cc6 ---- /dev/null -+++ b/src/ipa/simple/data/meson.build -@@ -0,0 +1,9 @@ -+# SPDX-License-Identifier: CC0-1.0 -+ -+conf_files = files([ -+ 'soft.conf', -+]) -+ -+install_data(conf_files, -+ install_dir : ipa_data_dir / 'soft', -+ install_tag : 'runtime') -diff --git a/src/ipa/simple/data/soft.conf b/src/ipa/simple/data/soft.conf -new file mode 100644 -index 00000000..0c70e7c0 ---- /dev/null -+++ b/src/ipa/simple/data/soft.conf -@@ -0,0 +1,3 @@ -+# SPDX-License-Identifier: LGPL-2.1-or-later -+# -+# Dummy configuration file for the soft IPA. -diff --git a/src/ipa/simple/meson.build b/src/ipa/simple/meson.build -new file mode 100644 -index 00000000..3e863db7 ---- /dev/null -+++ b/src/ipa/simple/meson.build -@@ -0,0 +1,25 @@ -+# SPDX-License-Identifier: CC0-1.0 -+ -+ipa_name = 'ipa_soft_simple' -+ -+mod = shared_module(ipa_name, -+ ['soft_simple.cpp', libcamera_generated_ipa_headers], -+ name_prefix : '', -+ include_directories : [ipa_includes, libipa_includes], -+ dependencies : libcamera_private, -+ link_with : libipa, -+ install : true, -+ install_dir : ipa_install_dir) -+ -+if ipa_sign_module -+ custom_target(ipa_name + '.so.sign', -+ input : mod, -+ output : ipa_name + '.so.sign', -+ command : [ipa_sign, ipa_priv_key, '@INPUT@', '@OUTPUT@'], -+ install : false, -+ build_by_default : true) -+endif -+ -+subdir('data') -+ -+ipa_names += ipa_name -diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp -new file mode 100644 -index 00000000..312df4ba ---- /dev/null -+++ b/src/ipa/simple/soft_simple.cpp -@@ -0,0 +1,326 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Linaro Ltd -+ * -+ * soft_simple.cpp - Simple Software Image Processing Algorithm module -+ */ -+ -+#include <sys/mman.h> -+ -+#include <libcamera/base/file.h> -+#include <libcamera/base/log.h> -+#include <libcamera/base/shared_fd.h> -+ -+#include <libcamera/control_ids.h> -+#include <libcamera/controls.h> -+ -+#include <libcamera/ipa/ipa_interface.h> -+#include <libcamera/ipa/ipa_module_info.h> -+#include <libcamera/ipa/soft_ipa_interface.h> -+ -+#include "libcamera/internal/camera_sensor.h" -+#include "libcamera/internal/software_isp/debayer_params.h" -+#include "libcamera/internal/software_isp/swisp_stats.h" -+ -+namespace libcamera { -+ -+LOG_DEFINE_CATEGORY(IPASoft) -+ -+namespace ipa::soft { -+ -+class IPASoftSimple : public ipa::soft::IPASoftInterface -+{ -+public: -+ IPASoftSimple() -+ : params_(static_cast<DebayerParams *>(MAP_FAILED)), -+ stats_(static_cast<SwIspStats *>(MAP_FAILED)), ignore_updates_(0) -+ { -+ } -+ -+ ~IPASoftSimple() -+ { -+ if (stats_ != MAP_FAILED) -+ munmap(stats_, sizeof(SwIspStats)); -+ if (params_ != MAP_FAILED) -+ munmap(params_, sizeof(DebayerParams)); -+ } -+ -+ int init(const IPASettings &settings, -+ const SharedFD &fdStats, -+ const SharedFD &fdParams, -+ const ControlInfoMap &sensorInfoMap) override; -+ int configure(const ControlInfoMap &sensorInfoMap) override; -+ -+ int start() override; -+ void stop() override; -+ -+ void processStats(const ControlList &sensorControls) override; -+ -+private: -+ void updateExposure(double exposureMSV); -+ -+ SharedFD fdStats_; -+ SharedFD fdParams_; -+ DebayerParams *params_; -+ SwIspStats *stats_; -+ -+ int32_t exposure_min_, exposure_max_; -+ int32_t again_min_, again_max_; -+ int32_t again_, exposure_; -+ unsigned int ignore_updates_; -+}; -+ -+int IPASoftSimple::init([[maybe_unused]] const IPASettings &settings, -+ const SharedFD &fdStats, -+ const SharedFD &fdParams, -+ const ControlInfoMap &sensorInfoMap) -+{ -+ fdStats_ = fdStats; -+ if (!fdStats_.isValid()) { -+ LOG(IPASoft, Error) << "Invalid Statistics handle"; -+ return -ENODEV; -+ } -+ -+ fdParams_ = fdParams; -+ if (!fdParams_.isValid()) { -+ LOG(IPASoft, Error) << "Invalid Parameters handle"; -+ return -ENODEV; -+ } -+ -+ params_ = static_cast<DebayerParams *>(mmap(nullptr, sizeof(DebayerParams), -+ PROT_WRITE, MAP_SHARED, -+ fdParams_.get(), 0)); -+ if (params_ == MAP_FAILED) { -+ LOG(IPASoft, Error) << "Unable to map Parameters"; -+ return -errno; -+ } -+ -+ stats_ = static_cast<SwIspStats *>(mmap(nullptr, sizeof(SwIspStats), -+ PROT_READ, MAP_SHARED, -+ fdStats_.get(), 0)); -+ if (stats_ == MAP_FAILED) { -+ LOG(IPASoft, Error) << "Unable to map Statistics"; -+ return -errno; -+ } -+ -+ if (sensorInfoMap.find(V4L2_CID_EXPOSURE) == sensorInfoMap.end()) { -+ LOG(IPASoft, Error) << "Don't have exposure control"; -+ return -EINVAL; -+ } -+ -+ if (sensorInfoMap.find(V4L2_CID_ANALOGUE_GAIN) == sensorInfoMap.end()) { -+ LOG(IPASoft, Error) << "Don't have gain control"; -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+int IPASoftSimple::configure(const ControlInfoMap &sensorInfoMap) -+{ -+ const ControlInfo &exposure_info = sensorInfoMap.find(V4L2_CID_EXPOSURE)->second; -+ const ControlInfo &gain_info = sensorInfoMap.find(V4L2_CID_ANALOGUE_GAIN)->second; -+ -+ exposure_min_ = exposure_info.min().get<int32_t>(); -+ exposure_max_ = exposure_info.max().get<int32_t>(); -+ if (!exposure_min_) { -+ LOG(IPASoft, Warning) << "Minimum exposure is zero, that can't be linear"; -+ exposure_min_ = 1; -+ } -+ -+ again_min_ = gain_info.min().get<int32_t>(); -+ again_max_ = gain_info.max().get<int32_t>(); -+ /* -+ * The camera sensor gain (g) is usually not equal to the value written -+ * into the gain register (x). But the way how the AGC algorithm changes -+ * the gain value to make the total exposure closer to the optimum assumes -+ * that g(x) is not too far from linear function. If the minimal gain is 0, -+ * the g(x) is likely to be far from the linear, like g(x) = a / (b * x + c). -+ * To avoid unexpected changes to the gain by the AGC algorithm (abrupt near -+ * one edge, and very small near the other) we limit the range of the gain -+ * values used. -+ */ -+ if (!again_min_) { -+ LOG(IPASoft, Warning) << "Minimum gain is zero, that can't be linear"; -+ again_min_ = std::min(100, again_min_ / 2 + again_max_ / 2); -+ } -+ -+ LOG(IPASoft, Info) << "Exposure " << exposure_min_ << "-" << exposure_max_ -+ << ", gain " << again_min_ << "-" << again_max_; -+ -+ return 0; -+} -+ -+int IPASoftSimple::start() -+{ -+ return 0; -+} -+ -+void IPASoftSimple::stop() -+{ -+} -+ -+/* -+ * The number of bins to use for the optimal exposure calculations. -+ */ -+static constexpr unsigned int kExposureBinsCount = 5; -+/* -+ * The exposure is optimal when the mean sample value of the histogram is -+ * in the middle of the range. -+ */ -+static constexpr float kExposureOptimal = kExposureBinsCount / 2.0; -+/* -+ * The below value implements the hysteresis for the exposure adjustment. -+ * It is small enough to have the exposure close to the optimal, and is big -+ * enough to prevent the exposure from wobbling around the optimal value. -+ */ -+static constexpr float kExposureSatisfactory = 0.2; -+ -+void IPASoftSimple::processStats(const ControlList &sensorControls) -+{ -+ /* -+ * Calculate red and blue gains for AWB. -+ * Clamp max gain at 4.0, this also avoids 0 division. -+ */ -+ if (stats_->sumR_ <= stats_->sumG_ / 4) -+ params_->gainR = 1024; -+ else -+ params_->gainR = 256 * stats_->sumG_ / stats_->sumR_; -+ -+ if (stats_->sumB_ <= stats_->sumG_ / 4) -+ params_->gainB = 1024; -+ else -+ params_->gainB = 256 * stats_->sumG_ / stats_->sumB_; -+ -+ /* Green gain and gamma values are fixed */ -+ params_->gainG = 256; -+ params_->gamma = 0.5; -+ -+ setIspParams.emit(0); -+ -+ /* -+ * AE / AGC, use 2 frames delay to make sure that the exposure and -+ * the gain set have applied to the camera sensor. -+ */ -+ if (ignore_updates_ > 0) { -+ --ignore_updates_; -+ return; -+ } -+ -+ /* -+ * Calculate Mean Sample Value (MSV) according to formula from: -+ * https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf -+ */ -+ constexpr unsigned int yHistValsPerBin = -+ SwIspStats::kYHistogramSize / kExposureBinsCount; -+ constexpr unsigned int yHistValsPerBinMod = -+ SwIspStats::kYHistogramSize / -+ (SwIspStats::kYHistogramSize % kExposureBinsCount + 1); -+ int ExposureBins[kExposureBinsCount] = {}; -+ unsigned int denom = 0; -+ unsigned int num = 0; -+ -+ for (unsigned int i = 0; i < SwIspStats::kYHistogramSize; i++) { -+ unsigned int idx = (i - (i / yHistValsPerBinMod)) / yHistValsPerBin; -+ ExposureBins[idx] += stats_->yHistogram[i]; -+ } -+ -+ for (unsigned int i = 0; i < kExposureBinsCount; i++) { -+ LOG(IPASoft, Debug) << i << ": " << ExposureBins[i]; -+ denom += ExposureBins[i]; -+ num += ExposureBins[i] * (i + 1); -+ } -+ -+ float exposureMSV = (float)num / denom; -+ -+ /* sanity check */ -+ if (!sensorControls.contains(V4L2_CID_EXPOSURE) || -+ !sensorControls.contains(V4L2_CID_ANALOGUE_GAIN)) { -+ LOG(IPASoft, Error) << "Control(s) missing"; -+ return; -+ } -+ -+ ControlList ctrls(sensorControls); -+ -+ exposure_ = ctrls.get(V4L2_CID_EXPOSURE).get<int32_t>(); -+ again_ = ctrls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); -+ -+ updateExposure(exposureMSV); -+ -+ ctrls.set(V4L2_CID_EXPOSURE, exposure_); -+ ctrls.set(V4L2_CID_ANALOGUE_GAIN, again_); -+ -+ ignore_updates_ = 2; -+ -+ setSensorControls.emit(ctrls); -+ -+ LOG(IPASoft, Debug) << "exposureMSV " << exposureMSV -+ << " exp " << exposure_ << " again " << again_ -+ << " gain R/B " << params_->gainR << "/" << params_->gainB; -+} -+ -+void IPASoftSimple::updateExposure(double exposureMSV) -+{ -+ /* DENOMINATOR of 10 gives ~10% increment/decrement; DENOMINATOR of 5 - about ~20% */ -+ static constexpr uint8_t kExpDenominator = 10; -+ static constexpr uint8_t kExpNumeratorUp = kExpDenominator + 1; -+ static constexpr uint8_t kExpNumeratorDown = kExpDenominator - 1; -+ -+ int next; -+ -+ if (exposureMSV < kExposureOptimal - kExposureSatisfactory) { -+ next = exposure_ * kExpNumeratorUp / kExpDenominator; -+ if (next - exposure_ < 1) -+ exposure_ += 1; -+ else -+ exposure_ = next; -+ if (exposure_ >= exposure_max_) { -+ next = again_ * kExpNumeratorUp / kExpDenominator; -+ if (next - again_ < 1) -+ again_ += 1; -+ else -+ again_ = next; -+ } -+ } -+ -+ if (exposureMSV > kExposureOptimal + kExposureSatisfactory) { -+ if (exposure_ == exposure_max_ && again_ != again_min_) { -+ next = again_ * kExpNumeratorDown / kExpDenominator; -+ if (again_ - next < 1) -+ again_ -= 1; -+ else -+ again_ = next; -+ } else { -+ next = exposure_ * kExpNumeratorDown / kExpDenominator; -+ if (exposure_ - next < 1) -+ exposure_ -= 1; -+ else -+ exposure_ = next; -+ } -+ } -+ -+ exposure_ = std::clamp(exposure_, exposure_min_, exposure_max_); -+ again_ = std::clamp(again_, again_min_, again_max_); -+} -+ -+} /* namespace ipa::soft */ -+ -+/* -+ * External IPA module interface -+ */ -+extern "C" { -+const struct IPAModuleInfo ipaModuleInfo = { -+ IPA_MODULE_API_VERSION, -+ 0, -+ "SimplePipelineHandler", -+ "simple", -+}; -+ -+IPAInterface *ipaCreate() -+{ -+ return new ipa::soft::IPASoftSimple(); -+} -+ -+} /* extern "C" */ -+ -+} /* namespace libcamera */ --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0010-libcamera-introduce-SoftwareIsp.patch b/users/flokli/ipu6-softisp/libcamera/0010-libcamera-introduce-SoftwareIsp.patch deleted file mode 100644 index 9f2d66c2f8b6..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0010-libcamera-introduce-SoftwareIsp.patch +++ /dev/null @@ -1,507 +0,0 @@ -From ad41ea12fe4b8ca0ace20781c775a63ed0d66f4c Mon Sep 17 00:00:00 2001 -From: Andrey Konovalov <andrey.konovalov@linaro.org> -Date: Mon, 11 Mar 2024 15:15:14 +0100 -Subject: [PATCH 10/21] libcamera: introduce SoftwareIsp - -Doxygen documentation by Dennis Bonke. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Co-developed-by: Dennis Bonke <admin@dennisbonke.com> -Signed-off-by: Dennis Bonke <admin@dennisbonke.com> -Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - .../internal/software_isp/meson.build | 1 + - .../internal/software_isp/software_isp.h | 98 +++++ - src/libcamera/software_isp/meson.build | 1 + - src/libcamera/software_isp/software_isp.cpp | 349 ++++++++++++++++++ - 4 files changed, 449 insertions(+) - create mode 100644 include/libcamera/internal/software_isp/software_isp.h - create mode 100644 src/libcamera/software_isp/software_isp.cpp - -diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build -index a620e16d..508ddddc 100644 ---- a/include/libcamera/internal/software_isp/meson.build -+++ b/include/libcamera/internal/software_isp/meson.build -@@ -2,5 +2,6 @@ - - libcamera_internal_headers += files([ - 'debayer_params.h', -+ 'software_isp.h', - 'swisp_stats.h', - ]) -diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h -new file mode 100644 -index 00000000..8d25e979 ---- /dev/null -+++ b/include/libcamera/internal/software_isp/software_isp.h -@@ -0,0 +1,98 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Linaro Ltd -+ * -+ * software_isp.h - Simple software ISP implementation -+ */ -+ -+#pragma once -+ -+#include <functional> -+#include <initializer_list> -+#include <map> -+#include <memory> -+#include <string> -+#include <tuple> -+#include <vector> -+ -+#include <libcamera/base/class.h> -+#include <libcamera/base/log.h> -+#include <libcamera/base/signal.h> -+#include <libcamera/base/thread.h> -+ -+#include <libcamera/geometry.h> -+#include <libcamera/pixel_format.h> -+ -+#include <libcamera/ipa/soft_ipa_interface.h> -+#include <libcamera/ipa/soft_ipa_proxy.h> -+ -+#include "libcamera/internal/dma_heaps.h" -+#include "libcamera/internal/pipeline_handler.h" -+#include "libcamera/internal/shared_mem_object.h" -+#include "libcamera/internal/software_isp/debayer_params.h" -+ -+namespace libcamera { -+ -+class DebayerCpu; -+class FrameBuffer; -+class PixelFormat; -+struct StreamConfiguration; -+ -+LOG_DECLARE_CATEGORY(SoftwareIsp) -+ -+class SoftwareIsp -+{ -+public: -+ SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls); -+ ~SoftwareIsp(); -+ -+ int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; } -+ -+ bool isValid() const; -+ -+ std::vector<PixelFormat> formats(PixelFormat input); -+ -+ SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); -+ -+ std::tuple<unsigned int, unsigned int> -+ strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); -+ -+ int configure(const StreamConfiguration &inputCfg, -+ const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs, -+ const ControlInfoMap &sensorControls); -+ -+ int exportBuffers(unsigned int output, unsigned int count, -+ std::vector<std::unique_ptr<FrameBuffer>> *buffers); -+ -+ void processStats(const ControlList &sensorControls); -+ -+ int start(); -+ void stop(); -+ -+ int queueBuffers(FrameBuffer *input, -+ const std::map<unsigned int, FrameBuffer *> &outputs); -+ -+ void process(FrameBuffer *input, FrameBuffer *output); -+ -+ Signal<FrameBuffer *> inputBufferReady; -+ Signal<FrameBuffer *> outputBufferReady; -+ Signal<int> ispStatsReady; -+ Signal<const ControlList &> setSensorControls; -+ -+private: -+ void saveIspParams(int dummy); -+ void setSensorCtrls(const ControlList &sensorControls); -+ void statsReady(int dummy); -+ void inputReady(FrameBuffer *input); -+ void outputReady(FrameBuffer *output); -+ -+ std::unique_ptr<DebayerCpu> debayer_; -+ Thread ispWorkerThread_; -+ SharedMemObject<DebayerParams> sharedParams_; -+ DebayerParams debayerParams_; -+ DmaHeap dmaHeap_; -+ -+ std::unique_ptr<ipa::soft::IPAProxySoft> ipa_; -+}; -+ -+} /* namespace libcamera */ -diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build -index 71b46539..e9266e54 100644 ---- a/src/libcamera/software_isp/meson.build -+++ b/src/libcamera/software_isp/meson.build -@@ -10,5 +10,6 @@ endif - libcamera_sources += files([ - 'debayer.cpp', - 'debayer_cpu.cpp', -+ 'software_isp.cpp', - 'swstats_cpu.cpp', - ]) -diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp -new file mode 100644 -index 00000000..388b4496 ---- /dev/null -+++ b/src/libcamera/software_isp/software_isp.cpp -@@ -0,0 +1,349 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2023, Linaro Ltd -+ * -+ * software_isp.cpp - Simple software ISP implementation -+ */ -+ -+#include "libcamera/internal/software_isp/software_isp.h" -+ -+#include <sys/mman.h> -+#include <sys/types.h> -+#include <unistd.h> -+ -+#include <libcamera/formats.h> -+#include <libcamera/stream.h> -+ -+#include "libcamera/internal/bayer_format.h" -+#include "libcamera/internal/framebuffer.h" -+#include "libcamera/internal/ipa_manager.h" -+#include "libcamera/internal/mapped_framebuffer.h" -+ -+#include "debayer_cpu.h" -+ -+/** -+ * \file software_isp.cpp -+ * \brief Simple software ISP implementation -+ */ -+ -+namespace libcamera { -+ -+LOG_DEFINE_CATEGORY(SoftwareIsp) -+ -+/** -+ * \class SoftwareIsp -+ * \brief Class for the Software ISP -+ */ -+ -+/** -+ * \var SoftwareIsp::inputBufferReady -+ * \brief A signal emitted when the input frame buffer completes -+ */ -+ -+/** -+ * \var SoftwareIsp::outputBufferReady -+ * \brief A signal emitted when the output frame buffer completes -+ */ -+ -+/** -+ * \var SoftwareIsp::ispStatsReady -+ * \brief A signal emitted when the statistics for IPA are ready -+ * -+ * The int parameter isn't actually used. -+ */ -+ -+/** -+ * \var SoftwareIsp::setSensorControls -+ * \brief A signal emitted when the values to write to the sensor controls are ready -+ */ -+ -+/** -+ * \brief Constructs SoftwareIsp object -+ * \param[in] pipe The pipeline handler in use -+ * \param[in] sensorControls ControlInfoMap describing the controls supported by the sensor -+ */ -+SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls) -+ : debayer_(nullptr), -+ debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10, DebayerParams::kGain10, 0.5f }, -+ dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System) -+{ -+ if (!dmaHeap_.isValid()) { -+ LOG(SoftwareIsp, Error) << "Failed to create DmaHeap object"; -+ return; -+ } -+ -+ sharedParams_ = SharedMemObject<DebayerParams>("softIsp_params"); -+ if (!sharedParams_) { -+ LOG(SoftwareIsp, Error) << "Failed to create shared memory for parameters"; -+ return; -+ } -+ -+ auto stats = std::make_unique<SwStatsCpu>(); -+ if (!stats->isValid()) { -+ LOG(SoftwareIsp, Error) << "Failed to create SwStatsCpu object"; -+ return; -+ } -+ stats->statsReady.connect(this, &SoftwareIsp::statsReady); -+ -+ debayer_ = std::make_unique<DebayerCpu>(std::move(stats)); -+ debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady); -+ debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady); -+ -+ ipa_ = IPAManager::createIPA<ipa::soft::IPAProxySoft>(pipe, 0, 0); -+ if (!ipa_) { -+ LOG(SoftwareIsp, Error) -+ << "Creating IPA for software ISP failed"; -+ debayer_.reset(); -+ return; -+ } -+ -+ int ret = ipa_->init(IPASettings{ "No cfg file", "No sensor model" }, -+ debayer_->getStatsFD(), -+ sharedParams_.fd(), -+ sensorControls); -+ if (ret) { -+ LOG(SoftwareIsp, Error) << "IPA init failed"; -+ debayer_.reset(); -+ return; -+ } -+ -+ ipa_->setIspParams.connect(this, &SoftwareIsp::saveIspParams); -+ ipa_->setSensorControls.connect(this, &SoftwareIsp::setSensorCtrls); -+ -+ debayer_->moveToThread(&ispWorkerThread_); -+} -+ -+SoftwareIsp::~SoftwareIsp() -+{ -+ /* make sure to destroy the DebayerCpu before the ispWorkerThread_ is gone */ -+ debayer_.reset(); -+} -+ -+/** -+ * \fn int SoftwareIsp::loadConfiguration([[maybe_unused]] const std::string &filename) -+ * \brief Load a configuration from a file -+ * \param[in] filename The file to load the configuration data from -+ * -+ * Currently is a stub doing nothing and always returning "success". -+ * -+ * \return 0 on success -+ */ -+ -+/** -+ * \brief Process the statistics gathered -+ * \param[in] sensorControls The sensor controls -+ * -+ * Requests the IPA to calculate new parameters for ISP and new control -+ * values for the sensor. -+ */ -+void SoftwareIsp::processStats(const ControlList &sensorControls) -+{ -+ ASSERT(ipa_); -+ ipa_->processStats(sensorControls); -+} -+ -+/** -+ * \brief Check the validity of Software Isp object -+ * \return True if Software Isp is valid, false otherwise -+ */ -+bool SoftwareIsp::isValid() const -+{ -+ return !!debayer_; -+} -+ -+/** -+ * \brief Get the output formats supported for the given input format -+ * \param[in] inputFormat The input format -+ * \return All the supported output formats or an empty vector if there are none -+ */ -+std::vector<PixelFormat> SoftwareIsp::formats(PixelFormat inputFormat) -+{ -+ ASSERT(debayer_ != nullptr); -+ -+ return debayer_->formats(inputFormat); -+} -+ -+/** -+ * \brief Get the supported output sizes for the given input format and size -+ * \param[in] inputFormat The input format -+ * \param[in] inputSize The input frame size -+ * \return The valid size range or an empty range if there are none -+ */ -+SizeRange SoftwareIsp::sizes(PixelFormat inputFormat, const Size &inputSize) -+{ -+ ASSERT(debayer_ != nullptr); -+ -+ return debayer_->sizes(inputFormat, inputSize); -+} -+ -+/** -+ * Get the output stride and the frame size in bytes for the given output format and size -+ * \param[in] outputFormat The output format -+ * \param[in] size The output size (width and height in pixels) -+ * \return A tuple of the stride and the frame size in bytes, or a tuple of 0,0 -+ * if there is no valid output config -+ */ -+std::tuple<unsigned int, unsigned int> -+SoftwareIsp::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) -+{ -+ ASSERT(debayer_ != nullptr); -+ -+ return debayer_->strideAndFrameSize(outputFormat, size); -+} -+ -+/** -+ * \brief Configure the SoftwareIsp object according to the passed in parameters -+ * \param[in] inputCfg The input configuration -+ * \param[in] outputCfgs The output configurations -+ * \param[in] sensorControls ControlInfoMap of the controls supported by the sensor -+ * \return 0 on success, a negative errno on failure -+ */ -+int SoftwareIsp::configure(const StreamConfiguration &inputCfg, -+ const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs, -+ const ControlInfoMap &sensorControls) -+{ -+ ASSERT(ipa_ != nullptr && debayer_ != nullptr); -+ -+ int ret = ipa_->configure(sensorControls); -+ if (ret < 0) -+ return ret; -+ -+ return debayer_->configure(inputCfg, outputCfgs); -+} -+ -+/** -+ * \brief Export the buffers from the Software ISP -+ * \param[in] output Output stream index exporting the buffers -+ * \param[in] count Number of buffers to allocate -+ * \param[out] buffers Vector to store the allocated buffers -+ * \return The number of allocated buffers on success or a negative error code -+ * otherwise -+ */ -+int SoftwareIsp::exportBuffers(unsigned int output, unsigned int count, -+ std::vector<std::unique_ptr<FrameBuffer>> *buffers) -+{ -+ ASSERT(debayer_ != nullptr); -+ -+ /* single output for now */ -+ if (output >= 1) -+ return -EINVAL; -+ -+ for (unsigned int i = 0; i < count; i++) { -+ const std::string name = "frame-" + std::to_string(i); -+ const size_t frameSize = debayer_->frameSize(); -+ -+ FrameBuffer::Plane outPlane; -+ outPlane.fd = SharedFD(dmaHeap_.alloc(name.c_str(), frameSize)); -+ if (!outPlane.fd.isValid()) { -+ LOG(SoftwareIsp, Error) -+ << "failed to allocate a dma_buf"; -+ return -ENOMEM; -+ } -+ outPlane.offset = 0; -+ outPlane.length = frameSize; -+ -+ std::vector<FrameBuffer::Plane> planes{ outPlane }; -+ buffers->emplace_back(std::make_unique<FrameBuffer>(std::move(planes))); -+ } -+ -+ return count; -+} -+ -+/** -+ * \brief Queue buffers to Software ISP -+ * \param[in] input The input framebuffer -+ * \param[in] outputs The container holding the output stream indexes and -+ * their respective frame buffer outputs -+ * \return 0 on success, a negative errno on failure -+ */ -+int SoftwareIsp::queueBuffers(FrameBuffer *input, -+ const std::map<unsigned int, FrameBuffer *> &outputs) -+{ -+ unsigned int mask = 0; -+ -+ /* -+ * Validate the outputs as a sanity check: at least one output is -+ * required, all outputs must reference a valid stream and no two -+ * outputs can reference the same stream. -+ */ -+ if (outputs.empty()) -+ return -EINVAL; -+ -+ for (auto [index, buffer] : outputs) { -+ if (!buffer) -+ return -EINVAL; -+ if (index >= 1) /* only single stream atm */ -+ return -EINVAL; -+ if (mask & (1 << index)) -+ return -EINVAL; -+ -+ mask |= 1 << index; -+ } -+ -+ process(input, outputs.at(0)); -+ -+ return 0; -+} -+ -+/** -+ * \brief Starts the Software ISP streaming operation -+ * \return 0 on success, any other value indicates an error -+ */ -+int SoftwareIsp::start() -+{ -+ int ret = ipa_->start(); -+ if (ret) -+ return ret; -+ -+ ispWorkerThread_.start(); -+ return 0; -+} -+ -+/** -+ * \brief Stops the Software ISP streaming operation -+ */ -+void SoftwareIsp::stop() -+{ -+ ispWorkerThread_.exit(); -+ ispWorkerThread_.wait(); -+ -+ ipa_->stop(); -+} -+ -+/** -+ * \brief Passes the input framebuffer to the ISP worker to process -+ * \param[in] input The input framebuffer -+ * \param[out] output The framebuffer to write the processed frame to -+ */ -+void SoftwareIsp::process(FrameBuffer *input, FrameBuffer *output) -+{ -+ debayer_->invokeMethod(&DebayerCpu::process, -+ ConnectionTypeQueued, input, output, debayerParams_); -+} -+ -+void SoftwareIsp::saveIspParams([[maybe_unused]] int dummy) -+{ -+ debayerParams_ = *sharedParams_; -+} -+ -+void SoftwareIsp::setSensorCtrls(const ControlList &sensorControls) -+{ -+ setSensorControls.emit(sensorControls); -+} -+ -+void SoftwareIsp::statsReady(int dummy) -+{ -+ ispStatsReady.emit(dummy); -+} -+ -+void SoftwareIsp::inputReady(FrameBuffer *input) -+{ -+ inputBufferReady.emit(input); -+} -+ -+void SoftwareIsp::outputReady(FrameBuffer *output) -+{ -+ outputBufferReady.emit(output); -+} -+ -+} /* namespace libcamera */ --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0011-libcamera-pipeline-simple-rename-converterBuffers_-a.patch b/users/flokli/ipu6-softisp/libcamera/0011-libcamera-pipeline-simple-rename-converterBuffers_-a.patch deleted file mode 100644 index 5c2237a8eb01..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0011-libcamera-pipeline-simple-rename-converterBuffers_-a.patch +++ /dev/null @@ -1,240 +0,0 @@ -From 050440eed6ab90686df217f5ff7dea0b241e3898 Mon Sep 17 00:00:00 2001 -From: Andrey Konovalov <andrey.konovalov@linaro.org> -Date: Mon, 11 Mar 2024 15:15:15 +0100 -Subject: [PATCH 11/21] libcamera: pipeline: simple: rename converterBuffers_ - and related vars - -The converterBuffers_ and the converterQueue_ are not that specific -to the Converter, and could be used by another entity doing the format -conversion. - -Rename converterBuffers_, converterQueue_, and useConverter_ to -conversionBuffers_, conversionQueue_ and useConversion_ to -disassociate them from the Converter. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - src/libcamera/pipeline/simple/simple.cpp | 63 ++++++++++++------------ - 1 file changed, 32 insertions(+), 31 deletions(-) - -diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp -index a84f6760..78854ef8 100644 ---- a/src/libcamera/pipeline/simple/simple.cpp -+++ b/src/libcamera/pipeline/simple/simple.cpp -@@ -269,17 +269,18 @@ public: - std::vector<Configuration> configs_; - std::map<PixelFormat, std::vector<const Configuration *>> formats_; - -+ std::vector<std::unique_ptr<FrameBuffer>> conversionBuffers_; -+ std::queue<std::map<unsigned int, FrameBuffer *>> conversionQueue_; -+ bool useConversion_; -+ - std::unique_ptr<Converter> converter_; -- std::vector<std::unique_ptr<FrameBuffer>> converterBuffers_; -- bool useConverter_; -- std::queue<std::map<unsigned int, FrameBuffer *>> converterQueue_; - - private: - void tryPipeline(unsigned int code, const Size &size); - static std::vector<const MediaPad *> routedSourcePads(MediaPad *sink); - -- void converterInputDone(FrameBuffer *buffer); -- void converterOutputDone(FrameBuffer *buffer); -+ void conversionInputDone(FrameBuffer *buffer); -+ void conversionOutputDone(FrameBuffer *buffer); - }; - - class SimpleCameraConfiguration : public CameraConfiguration -@@ -503,8 +504,8 @@ int SimpleCameraData::init() - << "Failed to create converter, disabling format conversion"; - converter_.reset(); - } else { -- converter_->inputBufferReady.connect(this, &SimpleCameraData::converterInputDone); -- converter_->outputBufferReady.connect(this, &SimpleCameraData::converterOutputDone); -+ converter_->inputBufferReady.connect(this, &SimpleCameraData::conversionInputDone); -+ converter_->outputBufferReady.connect(this, &SimpleCameraData::conversionOutputDone); - } - } - -@@ -740,7 +741,7 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) - * point converting an erroneous buffer. - */ - if (buffer->metadata().status != FrameMetadata::FrameSuccess) { -- if (!useConverter_) { -+ if (!useConversion_) { - /* No conversion, just complete the request. */ - Request *request = buffer->request(); - pipe->completeBuffer(request, buffer); -@@ -756,16 +757,16 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) - if (buffer->metadata().status != FrameMetadata::FrameCancelled) - video_->queueBuffer(buffer); - -- if (converterQueue_.empty()) -+ if (conversionQueue_.empty()) - return; - - Request *request = nullptr; -- for (auto &item : converterQueue_.front()) { -+ for (auto &item : conversionQueue_.front()) { - FrameBuffer *outputBuffer = item.second; - request = outputBuffer->request(); - pipe->completeBuffer(request, outputBuffer); - } -- converterQueue_.pop(); -+ conversionQueue_.pop(); - - if (request) - pipe->completeRequest(request); -@@ -782,9 +783,9 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) - */ - Request *request = buffer->request(); - -- if (useConverter_ && !converterQueue_.empty()) { -+ if (useConversion_ && !conversionQueue_.empty()) { - const std::map<unsigned int, FrameBuffer *> &outputs = -- converterQueue_.front(); -+ conversionQueue_.front(); - if (!outputs.empty()) { - FrameBuffer *outputBuffer = outputs.begin()->second; - if (outputBuffer) -@@ -801,14 +802,14 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) - * conversion is needed. If there's no queued request, just requeue the - * captured buffer for capture. - */ -- if (useConverter_) { -- if (converterQueue_.empty()) { -+ if (useConversion_) { -+ if (conversionQueue_.empty()) { - video_->queueBuffer(buffer); - return; - } - -- converter_->queueBuffers(buffer, converterQueue_.front()); -- converterQueue_.pop(); -+ converter_->queueBuffers(buffer, conversionQueue_.front()); -+ conversionQueue_.pop(); - return; - } - -@@ -817,13 +818,13 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) - pipe->completeRequest(request); - } - --void SimpleCameraData::converterInputDone(FrameBuffer *buffer) -+void SimpleCameraData::conversionInputDone(FrameBuffer *buffer) - { - /* Queue the input buffer back for capture. */ - video_->queueBuffer(buffer); - } - --void SimpleCameraData::converterOutputDone(FrameBuffer *buffer) -+void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer) - { - SimplePipelineHandler *pipe = SimpleCameraData::pipe(); - -@@ -1189,14 +1190,14 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) - - /* Configure the converter if needed. */ - std::vector<std::reference_wrapper<StreamConfiguration>> outputCfgs; -- data->useConverter_ = config->needConversion(); -+ data->useConversion_ = config->needConversion(); - - for (unsigned int i = 0; i < config->size(); ++i) { - StreamConfiguration &cfg = config->at(i); - - cfg.setStream(&data->streams_[i]); - -- if (data->useConverter_) -+ if (data->useConversion_) - outputCfgs.push_back(cfg); - } - -@@ -1222,7 +1223,7 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, - * Export buffers on the converter or capture video node, depending on - * whether the converter is used or not. - */ -- if (data->useConverter_) -+ if (data->useConversion_) - return data->converter_->exportBuffers(data->streamIndex(stream), - count, buffers); - else -@@ -1243,13 +1244,13 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL - return -EBUSY; - } - -- if (data->useConverter_) { -+ if (data->useConversion_) { - /* - * When using the converter allocate a fixed number of internal - * buffers. - */ - ret = video->allocateBuffers(kNumInternalBuffers, -- &data->converterBuffers_); -+ &data->conversionBuffers_); - } else { - /* Otherwise, prepare for using buffers from the only stream. */ - Stream *stream = &data->streams_[0]; -@@ -1268,7 +1269,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL - return ret; - } - -- if (data->useConverter_) { -+ if (data->useConversion_) { - ret = data->converter_->start(); - if (ret < 0) { - stop(camera); -@@ -1276,7 +1277,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL - } - - /* Queue all internal buffers for capture. */ -- for (std::unique_ptr<FrameBuffer> &buffer : data->converterBuffers_) -+ for (std::unique_ptr<FrameBuffer> &buffer : data->conversionBuffers_) - video->queueBuffer(buffer.get()); - } - -@@ -1288,7 +1289,7 @@ void SimplePipelineHandler::stopDevice(Camera *camera) - SimpleCameraData *data = cameraData(camera); - V4L2VideoDevice *video = data->video_; - -- if (data->useConverter_) -+ if (data->useConversion_) - data->converter_->stop(); - - video->streamOff(); -@@ -1296,7 +1297,7 @@ void SimplePipelineHandler::stopDevice(Camera *camera) - - video->bufferReady.disconnect(data, &SimpleCameraData::bufferReady); - -- data->converterBuffers_.clear(); -+ data->conversionBuffers_.clear(); - - releasePipeline(data); - } -@@ -1314,7 +1315,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) - * queue, it will be handed to the converter in the capture - * completion handler. - */ -- if (data->useConverter_) { -+ if (data->useConversion_) { - buffers.emplace(data->streamIndex(stream), buffer); - } else { - ret = data->video_->queueBuffer(buffer); -@@ -1323,8 +1324,8 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) - } - } - -- if (data->useConverter_) -- data->converterQueue_.push(std::move(buffers)); -+ if (data->useConversion_) -+ data->conversionQueue_.push(std::move(buffers)); - - return 0; - } --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch b/users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch deleted file mode 100644 index 378a43604f9a..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch +++ /dev/null @@ -1,302 +0,0 @@ -From d64b0fca22ef25b8a14d7fc97dfab64eb1c4f21a Mon Sep 17 00:00:00 2001 -From: Andrey Konovalov <andrey.konovalov@linaro.org> -Date: Mon, 11 Mar 2024 15:15:16 +0100 -Subject: [PATCH 12/21] libcamera: pipeline: simple: enable use of Soft ISP and - Soft IPA - -To enable the Simple Soft ISP and Soft IPA for simple pipeline handler -configure the build with: - -Dpipelines=simple -Dipas=simple - -Also using the Soft ISP for the particular hardware platform must -be enabled in the supportedDevices[] table. - -If the pipeline uses Converter, Soft ISP and Soft IPA aren't -available. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - src/libcamera/pipeline/simple/simple.cpp | 137 ++++++++++++++++++----- - 1 file changed, 109 insertions(+), 28 deletions(-) - -diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp -index 78854ef8..c3ebb7b7 100644 ---- a/src/libcamera/pipeline/simple/simple.cpp -+++ b/src/libcamera/pipeline/simple/simple.cpp -@@ -34,6 +34,7 @@ - #include "libcamera/internal/device_enumerator.h" - #include "libcamera/internal/media_device.h" - #include "libcamera/internal/pipeline_handler.h" -+#include "libcamera/internal/software_isp/software_isp.h" - #include "libcamera/internal/v4l2_subdevice.h" - #include "libcamera/internal/v4l2_videodevice.h" - -@@ -185,17 +186,22 @@ struct SimplePipelineInfo { - * and the number of streams it supports. - */ - std::vector<std::pair<const char *, unsigned int>> converters; -+ /* -+ * Using Software ISP is to be enabled per driver. -+ * The Software ISP can't be used together with the converters. -+ */ -+ bool swIspEnabled; - }; - - namespace { - - static const SimplePipelineInfo supportedDevices[] = { -- { "dcmipp", {} }, -- { "imx7-csi", { { "pxp", 1 } } }, -- { "j721e-csi2rx", {} }, -- { "mxc-isi", {} }, -- { "qcom-camss", {} }, -- { "sun6i-csi", {} }, -+ { "dcmipp", {}, false }, -+ { "imx7-csi", { { "pxp", 1 } }, false }, -+ { "j721e-csi2rx", {}, false }, -+ { "mxc-isi", {}, false }, -+ { "qcom-camss", {}, true }, -+ { "sun6i-csi", {}, false }, - }; - - } /* namespace */ -@@ -274,6 +280,7 @@ public: - bool useConversion_; - - std::unique_ptr<Converter> converter_; -+ std::unique_ptr<SoftwareIsp> swIsp_; - - private: - void tryPipeline(unsigned int code, const Size &size); -@@ -281,6 +288,9 @@ private: - - void conversionInputDone(FrameBuffer *buffer); - void conversionOutputDone(FrameBuffer *buffer); -+ -+ void ispStatsReady(int dummy); -+ void setSensorControls(const ControlList &sensorControls); - }; - - class SimpleCameraConfiguration : public CameraConfiguration -@@ -332,6 +342,7 @@ public: - V4L2VideoDevice *video(const MediaEntity *entity); - V4L2Subdevice *subdev(const MediaEntity *entity); - MediaDevice *converter() { return converter_; } -+ bool swIspEnabled() { return swIspEnabled_; } - - protected: - int queueRequestDevice(Camera *camera, Request *request) override; -@@ -360,6 +371,7 @@ private: - std::map<const MediaEntity *, EntityData> entities_; - - MediaDevice *converter_; -+ bool swIspEnabled_; - }; - - /* ----------------------------------------------------------------------------- -@@ -509,6 +521,29 @@ int SimpleCameraData::init() - } - } - -+ /* -+ * Instantiate Soft ISP if this is enabled for the given driver and no converter is used. -+ */ -+ if (!converter_ && pipe->swIspEnabled()) { -+ swIsp_ = std::make_unique<SoftwareIsp>(pipe, sensor_->controls()); -+ if (!swIsp_->isValid()) { -+ LOG(SimplePipeline, Warning) -+ << "Failed to create software ISP, disabling software debayering"; -+ swIsp_.reset(); -+ } else { -+ /* -+ * \todo explain why SimpleCameraData::conversionInputDone() can't be directly -+ * connected to inputBufferReady signal. -+ */ -+ swIsp_->inputBufferReady.connect(pipe, [this](FrameBuffer *buffer) { -+ this->conversionInputDone(buffer); -+ }); -+ swIsp_->outputBufferReady.connect(this, &SimpleCameraData::conversionOutputDone); -+ swIsp_->ispStatsReady.connect(this, &SimpleCameraData::ispStatsReady); -+ swIsp_->setSensorControls.connect(this, &SimpleCameraData::setSensorControls); -+ } -+ } -+ - video_ = pipe->video(entities_.back().entity); - ASSERT(video_); - -@@ -599,12 +634,21 @@ void SimpleCameraData::tryPipeline(unsigned int code, const Size &size) - config.captureFormat = pixelFormat; - config.captureSize = format.size; - -- if (!converter_) { -+ -+ if (converter_) { -+ config.outputFormats = converter_->formats(pixelFormat); -+ config.outputSizes = converter_->sizes(format.size); -+ } else if (swIsp_) { -+ config.outputFormats = swIsp_->formats(pixelFormat); -+ config.outputSizes = swIsp_->sizes(pixelFormat, format.size); -+ if (config.outputFormats.empty()) { -+ /* Do not use swIsp for unsupported pixelFormat's: */ -+ config.outputFormats = { pixelFormat }; -+ config.outputSizes = config.captureSize; -+ } -+ } else { - config.outputFormats = { pixelFormat }; - config.outputSizes = config.captureSize; -- } else { -- config.outputFormats = converter_->formats(pixelFormat); -- config.outputSizes = converter_->sizes(format.size); - } - - configs_.push_back(config); -@@ -750,9 +794,9 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) - } - - /* -- * The converter is in use. Requeue the internal buffer for -- * capture (unless the stream is being stopped), and complete -- * the request with all the user-facing buffers. -+ * The converter or Software ISP is in use. Requeue the internal -+ * buffer for capture (unless the stream is being stopped), and -+ * complete the request with all the user-facing buffers. - */ - if (buffer->metadata().status != FrameMetadata::FrameCancelled) - video_->queueBuffer(buffer); -@@ -798,9 +842,9 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) - buffer->metadata().timestamp); - - /* -- * Queue the captured and the request buffer to the converter if format -- * conversion is needed. If there's no queued request, just requeue the -- * captured buffer for capture. -+ * Queue the captured and the request buffer to the converter or Software -+ * ISP if format conversion is needed. If there's no queued request, just -+ * requeue the captured buffer for capture. - */ - if (useConversion_) { - if (conversionQueue_.empty()) { -@@ -808,7 +852,11 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer) - return; - } - -- converter_->queueBuffers(buffer, conversionQueue_.front()); -+ if (converter_) -+ converter_->queueBuffers(buffer, conversionQueue_.front()); -+ else -+ swIsp_->queueBuffers(buffer, conversionQueue_.front()); -+ - conversionQueue_.pop(); - return; - } -@@ -834,6 +882,18 @@ void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer) - pipe->completeRequest(request); - } - -+void SimpleCameraData::ispStatsReady([[maybe_unused]] int dummy) -+{ -+ swIsp_->processStats(sensor_->getControls({ V4L2_CID_ANALOGUE_GAIN, -+ V4L2_CID_EXPOSURE })); -+} -+ -+void SimpleCameraData::setSensorControls(const ControlList &sensorControls) -+{ -+ ControlList ctrls(sensorControls); -+ sensor_->setControls(&ctrls); -+} -+ - /* Retrieve all source pads connected to a sink pad through active routes. */ - std::vector<const MediaPad *> SimpleCameraData::routedSourcePads(MediaPad *sink) - { -@@ -1046,8 +1106,10 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() - /* Set the stride, frameSize and bufferCount. */ - if (needConversion_) { - std::tie(cfg.stride, cfg.frameSize) = -- data_->converter_->strideAndFrameSize(cfg.pixelFormat, -- cfg.size); -+ (data_->converter_) ? data_->converter_->strideAndFrameSize(cfg.pixelFormat, -+ cfg.size) -+ : data_->swIsp_->strideAndFrameSize(cfg.pixelFormat, -+ cfg.size); - if (cfg.stride == 0) - return Invalid; - } else { -@@ -1210,7 +1272,9 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) - inputCfg.stride = captureFormat.planes[0].bpl; - inputCfg.bufferCount = kNumInternalBuffers; - -- return data->converter_->configure(inputCfg, outputCfgs); -+ return (data->converter_) ? data->converter_->configure(inputCfg, outputCfgs) -+ : data->swIsp_->configure(inputCfg, outputCfgs, -+ data->sensor_->controls()); - } - - int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, -@@ -1224,8 +1288,10 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, - * whether the converter is used or not. - */ - if (data->useConversion_) -- return data->converter_->exportBuffers(data->streamIndex(stream), -- count, buffers); -+ return (data->converter_) ? data->converter_->exportBuffers(data->streamIndex(stream), -+ count, buffers) -+ : data->swIsp_->exportBuffers(data->streamIndex(stream), -+ count, buffers); - else - return data->video_->exportBuffers(count, buffers); - } -@@ -1270,10 +1336,18 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL - } - - if (data->useConversion_) { -- ret = data->converter_->start(); -- if (ret < 0) { -- stop(camera); -- return ret; -+ if (data->converter_) { -+ ret = data->converter_->start(); -+ if (ret < 0) { -+ stop(camera); -+ return ret; -+ } -+ } else if (data->swIsp_) { -+ ret = data->swIsp_->start(); -+ if (ret < 0) { -+ stop(camera); -+ return ret; -+ } - } - - /* Queue all internal buffers for capture. */ -@@ -1289,8 +1363,13 @@ void SimplePipelineHandler::stopDevice(Camera *camera) - SimpleCameraData *data = cameraData(camera); - V4L2VideoDevice *video = data->video_; - -- if (data->useConversion_) -- data->converter_->stop(); -+ if (data->useConversion_) { -+ if (data->converter_) -+ data->converter_->stop(); -+ else if (data->swIsp_) { -+ data->swIsp_->stop(); -+ } -+ } - - video->streamOff(); - video->releaseBuffers(); -@@ -1452,6 +1531,8 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) - } - } - -+ swIspEnabled_ = info->swIspEnabled; -+ - /* Locate the sensors. */ - std::vector<MediaEntity *> sensors = locateSensors(); - if (sensors.empty()) { --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0013-libcamera-swstats_cpu-Add-support-for-8-10-and-12-bp.patch b/users/flokli/ipu6-softisp/libcamera/0013-libcamera-swstats_cpu-Add-support-for-8-10-and-12-bp.patch deleted file mode 100644 index 1a57d690ff91..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0013-libcamera-swstats_cpu-Add-support-for-8-10-and-12-bp.patch +++ /dev/null @@ -1,203 +0,0 @@ -From aabc53453d542495d9da25411f57308c01f2bc28 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Mon, 11 Mar 2024 15:15:17 +0100 -Subject: [PATCH 13/21] libcamera: swstats_cpu: Add support for 8, 10 and 12 - bpp unpacked bayer input - -Add support for 8, 10 and 12 bpp unpacked bayer input for all 4 standard -bayer orders. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> -Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - src/libcamera/software_isp/swstats_cpu.cpp | 128 +++++++++++++++++++++ - src/libcamera/software_isp/swstats_cpu.h | 9 ++ - 2 files changed, 137 insertions(+) - -diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp -index 448d0e4c..be310f56 100644 ---- a/src/libcamera/software_isp/swstats_cpu.cpp -+++ b/src/libcamera/software_isp/swstats_cpu.cpp -@@ -71,6 +71,83 @@ static const unsigned int kBlueYMul = 29; /* 0.114 * 256 */ - stats_.sumG_ += sumG; \ - stats_.sumB_ += sumB; - -+void SwStatsCpu::statsBGGR8Line0(const uint8_t *src[]) -+{ -+ const uint8_t *src0 = src[1] + window_.x; -+ const uint8_t *src1 = src[2] + window_.x; -+ -+ SWSTATS_START_LINE_STATS(uint8_t) -+ -+ if (swapLines_) -+ std::swap(src0, src1); -+ -+ /* x += 4 sample every other 2x2 block */ -+ for (int x = 0; x < (int)window_.width; x += 4) { -+ b = src0[x]; -+ g = src0[x + 1]; -+ g2 = src1[x]; -+ r = src1[x + 1]; -+ -+ g = (g + g2) / 2; -+ -+ SWSTATS_ACCUMULATE_LINE_STATS(1) -+ } -+ -+ SWSTATS_FINISH_LINE_STATS() -+} -+ -+void SwStatsCpu::statsBGGR10Line0(const uint8_t *src[]) -+{ -+ const uint16_t *src0 = (const uint16_t *)src[1] + window_.x; -+ const uint16_t *src1 = (const uint16_t *)src[2] + window_.x; -+ -+ SWSTATS_START_LINE_STATS(uint16_t) -+ -+ if (swapLines_) -+ std::swap(src0, src1); -+ -+ /* x += 4 sample every other 2x2 block */ -+ for (int x = 0; x < (int)window_.width; x += 4) { -+ b = src0[x]; -+ g = src0[x + 1]; -+ g2 = src1[x]; -+ r = src1[x + 1]; -+ -+ g = (g + g2) / 2; -+ -+ /* divide Y by 4 for 10 -> 8 bpp value */ -+ SWSTATS_ACCUMULATE_LINE_STATS(4) -+ } -+ -+ SWSTATS_FINISH_LINE_STATS() -+} -+ -+void SwStatsCpu::statsBGGR12Line0(const uint8_t *src[]) -+{ -+ const uint16_t *src0 = (const uint16_t *)src[1] + window_.x; -+ const uint16_t *src1 = (const uint16_t *)src[2] + window_.x; -+ -+ SWSTATS_START_LINE_STATS(uint16_t) -+ -+ if (swapLines_) -+ std::swap(src0, src1); -+ -+ /* x += 4 sample every other 2x2 block */ -+ for (int x = 0; x < (int)window_.width; x += 4) { -+ b = src0[x]; -+ g = src0[x + 1]; -+ g2 = src1[x]; -+ r = src1[x + 1]; -+ -+ g = (g + g2) / 2; -+ -+ /* divide Y by 16 for 12 -> 8 bpp value */ -+ SWSTATS_ACCUMULATE_LINE_STATS(16) -+ } -+ -+ SWSTATS_FINISH_LINE_STATS() -+} -+ - void SwStatsCpu::statsBGGR10PLine0(const uint8_t *src[]) - { - const uint8_t *src0 = src[1] + window_.x * 5 / 4; -@@ -147,6 +224,42 @@ void SwStatsCpu::finishFrame(void) - statsReady.emit(0); - } - -+/** -+ * \brief Setup SwStatsCpu object for standard Bayer orders -+ * \param[in] order The Bayer order -+ * -+ * Check if order is a standard Bayer order and setup xShift_ and swapLines_ -+ * so that a single BGGR stats function can be used for all 4 standard orders. -+ */ -+int SwStatsCpu::setupStandardBayerOrder(BayerFormat::Order order) -+{ -+ switch (order) { -+ case BayerFormat::BGGR: -+ xShift_ = 0; -+ swapLines_ = false; -+ break; -+ case BayerFormat::GBRG: -+ xShift_ = 1; /* BGGR -> GBRG */ -+ swapLines_ = false; -+ break; -+ case BayerFormat::GRBG: -+ xShift_ = 0; -+ swapLines_ = true; /* BGGR -> GRBG */ -+ break; -+ case BayerFormat::RGGB: -+ xShift_ = 1; /* BGGR -> GBRG */ -+ swapLines_ = true; /* GBRG -> RGGB */ -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ patternSize_.height = 2; -+ patternSize_.width = 2; -+ ySkipMask_ = 0x02; /* Skip every 3th and 4th line */ -+ return 0; -+} -+ - /** - * \brief Configure the statistics object for the passed in input format. - * \param[in] inputCfg The input format -@@ -158,6 +271,21 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) - BayerFormat bayerFormat = - BayerFormat::fromPixelFormat(inputCfg.pixelFormat); - -+ if (bayerFormat.packing == BayerFormat::Packing::None && -+ setupStandardBayerOrder(bayerFormat.order) == 0) { -+ switch (bayerFormat.bitDepth) { -+ case 8: -+ stats0_ = &SwStatsCpu::statsBGGR8Line0; -+ return 0; -+ case 10: -+ stats0_ = &SwStatsCpu::statsBGGR10Line0; -+ return 0; -+ case 12: -+ stats0_ = &SwStatsCpu::statsBGGR12Line0; -+ return 0; -+ } -+ } -+ - if (bayerFormat.bitDepth == 10 && - bayerFormat.packing == BayerFormat::Packing::CSI2) { - patternSize_.height = 2; -diff --git a/src/libcamera/software_isp/swstats_cpu.h b/src/libcamera/software_isp/swstats_cpu.h -index 0ac9ae71..bbbcf69b 100644 ---- a/src/libcamera/software_isp/swstats_cpu.h -+++ b/src/libcamera/software_isp/swstats_cpu.h -@@ -17,6 +17,7 @@ - - #include <libcamera/geometry.h> - -+#include "libcamera/internal/bayer_format.h" - #include "libcamera/internal/shared_mem_object.h" - #include "libcamera/internal/software_isp/swisp_stats.h" - -@@ -120,6 +121,14 @@ private: - */ - using statsProcessFn = void (SwStatsCpu::*)(const uint8_t *src[]); - -+ int setupStandardBayerOrder(BayerFormat::Order order); -+ /* Bayer 8 bpp unpacked */ -+ void statsBGGR8Line0(const uint8_t *src[]); -+ /* Bayer 10 bpp unpacked */ -+ void statsBGGR10Line0(const uint8_t *src[]); -+ /* Bayer 12 bpp unpacked */ -+ void statsBGGR12Line0(const uint8_t *src[]); -+ /* Bayer 10 bpp packed */ - void statsBGGR10PLine0(const uint8_t *src[]); - void statsGBRG10PLine0(const uint8_t *src[]); - --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0014-libcamera-debayer_cpu-Add-support-for-8-10-and-12-bp.patch b/users/flokli/ipu6-softisp/libcamera/0014-libcamera-debayer_cpu-Add-support-for-8-10-and-12-bp.patch deleted file mode 100644 index c7edf498280e..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0014-libcamera-debayer_cpu-Add-support-for-8-10-and-12-bp.patch +++ /dev/null @@ -1,234 +0,0 @@ -From 5f3647bd4f12dd62256a425c49fd18a0f5990930 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Mon, 11 Mar 2024 15:15:18 +0100 -Subject: [PATCH 14/21] libcamera: debayer_cpu: Add support for 8, 10 and 12 - bpp unpacked bayer input - -Add support for 8, 10 and 12 bpp unpacked bayer input for all 4 standard -bayer orders. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> -Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - src/libcamera/software_isp/debayer_cpu.cpp | 128 +++++++++++++++++++++ - src/libcamera/software_isp/debayer_cpu.h | 13 +++ - 2 files changed, 141 insertions(+) - -diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp -index f932362c..eb1c2718 100644 ---- a/src/libcamera/software_isp/debayer_cpu.cpp -+++ b/src/libcamera/software_isp/debayer_cpu.cpp -@@ -56,6 +56,11 @@ DebayerCpu::~DebayerCpu() - free(lineBuffers_[i]); - } - -+#define DECLARE_SRC_POINTERS(pixel_t) \ -+ const pixel_t *prev = (const pixel_t *)src[0] + xShift_; \ -+ const pixel_t *curr = (const pixel_t *)src[1] + xShift_; \ -+ const pixel_t *next = (const pixel_t *)src[2] + xShift_; -+ - // RGR - // GBG - // RGR -@@ -92,6 +97,70 @@ DebayerCpu::~DebayerCpu() - *dst++ = red_[curr[x] / (div)]; \ - x++; - -+void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) -+{ -+ DECLARE_SRC_POINTERS(uint8_t) -+ -+ for (int x = 0; x < (int)window_.width;) { -+ BGGR_BGR888(1, 1, 1) -+ GBRG_BGR888(1, 1, 1) -+ } -+} -+ -+void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) -+{ -+ DECLARE_SRC_POINTERS(uint8_t) -+ -+ for (int x = 0; x < (int)window_.width;) { -+ GRBG_BGR888(1, 1, 1) -+ RGGB_BGR888(1, 1, 1) -+ } -+} -+ -+void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) -+{ -+ DECLARE_SRC_POINTERS(uint16_t) -+ -+ for (int x = 0; x < (int)window_.width;) { -+ /* divide values by 4 for 10 -> 8 bpp value */ -+ BGGR_BGR888(1, 1, 4) -+ GBRG_BGR888(1, 1, 4) -+ } -+} -+ -+void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) -+{ -+ DECLARE_SRC_POINTERS(uint16_t) -+ -+ for (int x = 0; x < (int)window_.width;) { -+ /* divide values by 4 for 10 -> 8 bpp value */ -+ GRBG_BGR888(1, 1, 4) -+ RGGB_BGR888(1, 1, 4) -+ } -+} -+ -+void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) -+{ -+ DECLARE_SRC_POINTERS(uint16_t) -+ -+ for (int x = 0; x < (int)window_.width;) { -+ /* divide values by 16 for 12 -> 8 bpp value */ -+ BGGR_BGR888(1, 1, 16) -+ GBRG_BGR888(1, 1, 16) -+ } -+} -+ -+void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]) -+{ -+ DECLARE_SRC_POINTERS(uint16_t) -+ -+ for (int x = 0; x < (int)window_.width;) { -+ /* divide values by 16 for 12 -> 8 bpp value */ -+ GRBG_BGR888(1, 1, 16) -+ RGGB_BGR888(1, 1, 16) -+ } -+} -+ - void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]) - { - const int width_in_bytes = window_.width * 5 / 4; -@@ -193,6 +262,16 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf - BayerFormat bayerFormat = - BayerFormat::fromPixelFormat(inputFormat); - -+ if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) && -+ bayerFormat.packing == BayerFormat::Packing::None && -+ isStandardBayerOrder(bayerFormat.order)) { -+ config.bpp = (bayerFormat.bitDepth + 7) & ~7; -+ config.patternSize.width = 2; -+ config.patternSize.height = 2; -+ config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 }); -+ return 0; -+ } -+ - if (bayerFormat.bitDepth == 10 && - bayerFormat.packing == BayerFormat::Packing::CSI2 && - isStandardBayerOrder(bayerFormat.order)) { -@@ -220,12 +299,61 @@ int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &c - return -EINVAL; - } - -+/* -+ * Check for standard Bayer orders and set xShift_ and swap debayer0/1, so that -+ * a single pair of BGGR debayer functions can be used for all 4 standard orders. -+ */ -+int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order) -+{ -+ switch (order) { -+ case BayerFormat::BGGR: -+ break; -+ case BayerFormat::GBRG: -+ xShift_ = 1; /* BGGR -> GBRG */ -+ break; -+ case BayerFormat::GRBG: -+ std::swap(debayer0_, debayer1_); /* BGGR -> GRBG */ -+ break; -+ case BayerFormat::RGGB: -+ xShift_ = 1; /* BGGR -> GBRG */ -+ std::swap(debayer0_, debayer1_); /* GBRG -> RGGB */ -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ - /* TODO: this ignores outputFormat since there is only 1 supported outputFormat for now */ - int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat) - { - BayerFormat bayerFormat = - BayerFormat::fromPixelFormat(inputFormat); - -+ xShift_ = 0; -+ -+ if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) && -+ bayerFormat.packing == BayerFormat::Packing::None && -+ isStandardBayerOrder(bayerFormat.order)) { -+ switch (bayerFormat.bitDepth) { -+ case 8: -+ debayer0_ = &DebayerCpu::debayer8_BGBG_BGR888; -+ debayer1_ = &DebayerCpu::debayer8_GRGR_BGR888; -+ break; -+ case 10: -+ debayer0_ = &DebayerCpu::debayer10_BGBG_BGR888; -+ debayer1_ = &DebayerCpu::debayer10_GRGR_BGR888; -+ break; -+ case 12: -+ debayer0_ = &DebayerCpu::debayer12_BGBG_BGR888; -+ debayer1_ = &DebayerCpu::debayer12_GRGR_BGR888; -+ break; -+ } -+ setupStandardBayerOrder(bayerFormat.order); -+ return 0; -+ } -+ - if (bayerFormat.bitDepth == 10 && - bayerFormat.packing == BayerFormat::Packing::CSI2) { - switch (bayerFormat.order) { -diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h -index 8a51ed85..fd1fa180 100644 ---- a/src/libcamera/software_isp/debayer_cpu.h -+++ b/src/libcamera/software_isp/debayer_cpu.h -@@ -17,6 +17,8 @@ - - #include <libcamera/base/object.h> - -+#include "libcamera/internal/bayer_format.h" -+ - #include "debayer.h" - #include "swstats_cpu.h" - -@@ -82,6 +84,15 @@ private: - */ - using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]); - -+ /* 8-bit raw bayer format */ -+ void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); -+ void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); -+ /* unpacked 10-bit raw bayer format */ -+ void debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); -+ void debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); -+ /* unpacked 12-bit raw bayer format */ -+ void debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); -+ void debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); - /* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */ - void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]); - void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]); -@@ -103,6 +114,7 @@ private: - - int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); - int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config); -+ int setupStandardBayerOrder(BayerFormat::Order order); - int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat); - void setupInputMemcpy(const uint8_t *linePointers[]); - void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src); -@@ -131,6 +143,7 @@ private: - unsigned int lineBufferLength_; - unsigned int lineBufferPadding_; - unsigned int lineBufferIndex_; -+ unsigned int xShift_; /* Offset of 0/1 applied to window_.x */ - bool enableInputMemcpy_; - float gamma_correction_; - unsigned int measuredFrames_; --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0015-libcamera-debayer_cpu-Add-BGR888-output-support.patch b/users/flokli/ipu6-softisp/libcamera/0015-libcamera-debayer_cpu-Add-BGR888-output-support.patch deleted file mode 100644 index 0abca2ea82d9..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0015-libcamera-debayer_cpu-Add-BGR888-output-support.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 186db51d54bcbd4d5096bea1e4396966c2dad001 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Mon, 11 Mar 2024 15:15:19 +0100 -Subject: [PATCH 15/21] libcamera: debayer_cpu: Add BGR888 output support - -BGR888 is RGB888 with the red and blue pixels swapped, adjust -the debayering to swap the red and blue pixels in the bayer pattern -to add support for writing formats::BGR888. - -Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s -Tested-by: Pavel Machek <pavel@ucw.cz> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> -Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com> ---- - src/libcamera/software_isp/debayer_cpu.cpp | 42 +++++++++++++++++++--- - src/libcamera/software_isp/debayer_cpu.h | 1 + - 2 files changed, 38 insertions(+), 5 deletions(-) - -diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp -index eb1c2718..a1692693 100644 ---- a/src/libcamera/software_isp/debayer_cpu.cpp -+++ b/src/libcamera/software_isp/debayer_cpu.cpp -@@ -268,7 +268,7 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf - config.bpp = (bayerFormat.bitDepth + 7) & ~7; - config.patternSize.width = 2; - config.patternSize.height = 2; -- config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 }); -+ config.outputFormats = std::vector<PixelFormat>({ formats::RGB888, formats::BGR888 }); - return 0; - } - -@@ -278,7 +278,7 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf - config.bpp = 10; - config.patternSize.width = 4; /* 5 bytes per *4* pixels */ - config.patternSize.height = 2; -- config.outputFormats = std::vector<PixelFormat>({ formats::RGB888 }); -+ config.outputFormats = std::vector<PixelFormat>({ formats::RGB888, formats::BGR888 }); - return 0; - } - -@@ -289,7 +289,7 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf - - int DebayerCpu::getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config) - { -- if (outputFormat == formats::RGB888) { -+ if (outputFormat == formats::RGB888 || outputFormat == formats::BGR888) { - config.bpp = 24; - return 0; - } -@@ -325,13 +325,41 @@ int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order) - return 0; - } - --/* TODO: this ignores outputFormat since there is only 1 supported outputFormat for now */ --int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] PixelFormat outputFormat) -+int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat) - { - BayerFormat bayerFormat = - BayerFormat::fromPixelFormat(inputFormat); - - xShift_ = 0; -+ swapRedBlueGains_ = false; -+ -+ switch (outputFormat) { -+ case formats::RGB888: -+ break; -+ case formats::BGR888: -+ /* Swap R and B in bayer order to generate BGR888 instead of RGB888 */ -+ swapRedBlueGains_ = true; -+ -+ switch (bayerFormat.order) { -+ case BayerFormat::BGGR: -+ bayerFormat.order = BayerFormat::RGGB; -+ break; -+ case BayerFormat::GBRG: -+ bayerFormat.order = BayerFormat::GRBG; -+ break; -+ case BayerFormat::GRBG: -+ bayerFormat.order = BayerFormat::GBRG; -+ break; -+ case BayerFormat::RGGB: -+ bayerFormat.order = BayerFormat::BGGR; -+ break; -+ default: -+ goto invalid_fmt; -+ } -+ break; -+ default: -+ goto invalid_fmt; -+ } - - if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) && - bayerFormat.packing == BayerFormat::Packing::None && -@@ -378,6 +406,7 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, [[maybe_unused]] Pi - } - } - -+invalid_fmt: - LOG(Debayer, Error) << "Unsupported input output format combination"; - return -EINVAL; - } -@@ -661,6 +690,9 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams - gamma_correction_ = params.gamma; - } - -+ if (swapRedBlueGains_) -+ std::swap(params.gainR, params.gainB); -+ - for (unsigned int i = 0; i < kRGBLookupSize; i++) { - constexpr unsigned int div = - kRGBLookupSize * DebayerParams::kGain10 / kGammaLookupSize; -diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h -index fd1fa180..5f44fc65 100644 ---- a/src/libcamera/software_isp/debayer_cpu.h -+++ b/src/libcamera/software_isp/debayer_cpu.h -@@ -145,6 +145,7 @@ private: - unsigned int lineBufferIndex_; - unsigned int xShift_; /* Offset of 0/1 applied to window_.x */ - bool enableInputMemcpy_; -+ bool swapRedBlueGains_; - float gamma_correction_; - unsigned int measuredFrames_; - int64_t frameProcessTime_; --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0017-libcamera-Add-Software-ISP-benchmarking-documentatio.patch b/users/flokli/ipu6-softisp/libcamera/0017-libcamera-Add-Software-ISP-benchmarking-documentatio.patch deleted file mode 100644 index 2343e9c46fe8..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0017-libcamera-Add-Software-ISP-benchmarking-documentatio.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 6c509a3d144d46a11454d32d128d16e16602b50f Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Mon, 11 Mar 2024 15:15:20 +0100 -Subject: [PATCH 17/21] libcamera: Add "Software ISP benchmarking" - documentation - -Add a "Software ISP benchmarking" documentation section which describes -the performance/power consumption measurements used during -the Software ISP's development. - -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> -Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com> ---- - Documentation/index.rst | 1 + - Documentation/meson.build | 1 + - Documentation/software-isp-benchmarking.rst | 82 +++++++++++++++++++++ - 3 files changed, 84 insertions(+) - create mode 100644 Documentation/software-isp-benchmarking.rst - -diff --git a/Documentation/index.rst b/Documentation/index.rst -index 63fac72d..5442ae75 100644 ---- a/Documentation/index.rst -+++ b/Documentation/index.rst -@@ -24,3 +24,4 @@ - Lens driver requirements <lens_driver_requirements> - Python Bindings <python-bindings> - Camera Sensor Model <camera-sensor-model> -+ SoftwareISP Benchmarking <software-isp-benchmarking> -diff --git a/Documentation/meson.build b/Documentation/meson.build -index 7a58fec8..3872e0a8 100644 ---- a/Documentation/meson.build -+++ b/Documentation/meson.build -@@ -80,6 +80,7 @@ if sphinx.found() - 'lens_driver_requirements.rst', - 'python-bindings.rst', - 'sensor_driver_requirements.rst', -+ 'software-isp-benchmarking.rst', - '../README.rst', - ] - -diff --git a/Documentation/software-isp-benchmarking.rst b/Documentation/software-isp-benchmarking.rst -new file mode 100644 -index 00000000..b2803953 ---- /dev/null -+++ b/Documentation/software-isp-benchmarking.rst -@@ -0,0 +1,82 @@ -+.. SPDX-License-Identifier: CC-BY-SA-4.0 -+ -+.. _software-isp-benchmarking: -+ -+Software ISP benchmarking -+========================= -+ -+The Software ISP is particularly sensitive to performance regressions -+therefore it is a good idea to always benchmark the Software ISP -+before and after making changes to it and ensure that there are -+no performance regressions. -+ -+DebayerCpu class builtin benchmark -+---------------------------------- -+ -+The DebayerCpu class has a builtin benchmark. This benchmark -+measures the time spent on processing (collecting statistics -+and debayering) only, it does not measure the time spent on -+capturing or outputting the frames. -+ -+The builtin benchmark always runs. So this can be used by simply -+running "cam" or "qcam" with a pipeline using the Software ISP. -+ -+When it runs it will skip measuring the first 30 frames to -+allow the caches and the CPU temperature (turbo-ing) to warm-up -+and then it measures 30 fps and shows the total and per frame -+processing time using an info level log message: -+ -+.. code-block:: text -+ -+ INFO Debayer debayer_cpu.cpp:907 Processed 30 frames in 244317us, 8143 us/frame -+ -+To get stable measurements it is advised to disable any other processes which -+may cause significant CPU usage (e.g. disable wifi, bluetooth and browsers). -+When possible it is also advisable to disable CPU turbo-ing and -+frequency-scaling. -+ -+For example when benchmarking on a Lenovo ThinkPad X1 Yoga Gen 8, with -+the charger plugged in, the CPU can be fixed to run at 2 GHz using: -+ -+.. code-block:: shell -+ -+ sudo x86_energy_perf_policy --turbo-enable 0 -+ sudo cpupower frequency-set -d 2GHz -u 2GHz -+ -+with these settings the builtin bench reports a processing time of ~7.8ms/frame -+on this laptop for FHD SGRBG10 (unpacked) bayer data. -+ -+Measuring power consumption -+--------------------------- -+ -+Since the Software ISP is often used on mobile devices it is also -+important to measure power consumption and ensure that that does -+not regress. -+ -+For example to measure power consumption on a Lenovo ThinkPad X1 Yoga Gen 8 -+it needs to be running on battery and it should be configured with its -+platform-profile (/sys/firmware/acpi/platform_profile) set to balanced and -+with its default turbo and frequency-scaling behavior to match real world usage. -+ -+Then start qcam to capture a FHD picture at 30 fps and position the qcam window -+so that it is fully visible. After this run the following command to monitor -+the power consumption: -+ -+.. code-block:: shell -+ -+ watch -n 10 cat /sys/class/power_supply/BAT0/power_now /sys/class/hwmon/hwmon6/fan?_input -+ -+Note this not only measures the power consumption in µW it also monitors -+the speed of this laptop's 2 fans. This is important because depending on -+the ambient temperature the 2 fans may spin up while testing and this -+will cause an additional power consumption of approx. 0.5 W messing up -+the measurement. -+ -+After starting qcam + the watch command let the laptop sit without using -+it for 2 minutes for the readings to stabilize. Then check that the fans -+have not turned on and manually take a couple of consecutive power readings -+and avarage these. -+ -+On the example Lenovo ThinkPad X1 Yoga Gen 8 laptop this results in -+a measured power consumption of approx. 13 W while running qcam versus -+approx. 4-5 W while setting idle with its OLED panel on. --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0018-libcamera-software_isp-Apply-black-level-compensatio.patch b/users/flokli/ipu6-softisp/libcamera/0018-libcamera-software_isp-Apply-black-level-compensatio.patch deleted file mode 100644 index c746b74dba67..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0018-libcamera-software_isp-Apply-black-level-compensatio.patch +++ /dev/null @@ -1,396 +0,0 @@ -From bb608d177135d74e3c98b8a61fb459ebe254bca5 Mon Sep 17 00:00:00 2001 -From: Milan Zamazal <mzamazal@redhat.com> -Date: Mon, 11 Mar 2024 15:15:21 +0100 -Subject: [PATCH 18/21] libcamera: software_isp: Apply black level compensation - -Black may not be represented as 0 pixel value for given hardware, it may be -higher. If this is not compensated then various problems may occur such as low -contrast or suboptimal exposure. - -The black pixel value can be either retrieved from a tuning file for the given -hardware, or automatically on fly. The former is the right and correct method, -while the latter can be used when a tuning file is not available for the given -hardware. Since there is currently no support for tuning files in software ISP, -the automatic, hardware independent way, is always used. Support for tuning -files should be added in future but it will require more work than this patch. - -The patch looks at the image histogram and assumes that black starts when pixel -values start occurring on the left. A certain amount of the darkest pixels is -ignored; it doesn't matter whether they represent various kinds of noise or are -real, they are better to omit in any case to make the image looking better. It -also doesn't matter whether the darkest pixels occur around the supposed black -level or are spread between 0 and the black level, the difference is not -important. - -An arbitrary threshold of 2% darkest pixels is applied; there is no magic about -that value. - -The patch assumes that the black values for different colors are the same and -doesn't attempt any other non-primitive enhancements. It cannot completely -replace tuning files and simplicity, while providing visible benefit, is its -goal. Anything more sophisticated is left for future patches. - -A possible cheap enhancement, if needed, could be setting exposure + gain to -minimum values temporarily, before setting the black level. In theory, the -black level should be fixed but it may not be reached in all images. For this -reason, the patch updates black level only if the observed value is lower than -the current one; it should be never increased. - -The purpose of the patch is to compensate for hardware properties. General -image contrast enhancements are out of scope of this patch. - -Stats are still gathered as an uncorrected histogram, to avoid any confusion and -to represent the raw image data. Exposure must be determined after the black -level correction -- it has no influence on the sub-black area and must be -correct after applying the black level correction. The granularity of the -histogram is increased from 16 to 64 to provide a better precision (there is no -theory behind either of those numbers). - -Reviewed-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Milan Zamazal <mzamazal@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - .../internal/software_isp/debayer_params.h | 4 + - .../internal/software_isp/swisp_stats.h | 10 ++- - src/ipa/simple/black_level.cpp | 86 +++++++++++++++++++ - src/ipa/simple/black_level.h | 28 ++++++ - src/ipa/simple/meson.build | 7 +- - src/ipa/simple/soft_simple.cpp | 28 ++++-- - src/libcamera/software_isp/debayer_cpu.cpp | 13 ++- - src/libcamera/software_isp/debayer_cpu.h | 1 + - src/libcamera/software_isp/software_isp.cpp | 2 +- - 9 files changed, 162 insertions(+), 17 deletions(-) - create mode 100644 src/ipa/simple/black_level.cpp - create mode 100644 src/ipa/simple/black_level.h - -diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h -index 98965fa1..5e38e08b 100644 ---- a/include/libcamera/internal/software_isp/debayer_params.h -+++ b/include/libcamera/internal/software_isp/debayer_params.h -@@ -43,6 +43,10 @@ struct DebayerParams { - * \brief Gamma correction, 1.0 is no correction - */ - float gamma; -+ /** -+ * \brief Level of the black point, 0..255, 0 is no correction. -+ */ -+ unsigned int blackLevel; - }; - - } /* namespace libcamera */ -diff --git a/include/libcamera/internal/software_isp/swisp_stats.h b/include/libcamera/internal/software_isp/swisp_stats.h -index afe42c9a..25cd5abd 100644 ---- a/include/libcamera/internal/software_isp/swisp_stats.h -+++ b/include/libcamera/internal/software_isp/swisp_stats.h -@@ -7,6 +7,8 @@ - - #pragma once - -+#include <array> -+ - namespace libcamera { - - /** -@@ -28,11 +30,15 @@ struct SwIspStats { - /** - * \brief Number of bins in the yHistogram. - */ -- static constexpr unsigned int kYHistogramSize = 16; -+ static constexpr unsigned int kYHistogramSize = 64; -+ /** -+ * \brief Type of the histogram. -+ */ -+ using histogram = std::array<unsigned int, kYHistogramSize>; - /** - * \brief A histogram of luminance values. - */ -- std::array<unsigned int, kYHistogramSize> yHistogram; -+ histogram yHistogram; - }; - - } /* namespace libcamera */ -diff --git a/src/ipa/simple/black_level.cpp b/src/ipa/simple/black_level.cpp -new file mode 100644 -index 00000000..8d52201b ---- /dev/null -+++ b/src/ipa/simple/black_level.cpp -@@ -0,0 +1,86 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2024, Red Hat Inc. -+ * -+ * black_level.cpp - black level handling -+ */ -+ -+#include "black_level.h" -+ -+#include <numeric> -+ -+#include <libcamera/base/log.h> -+ -+namespace libcamera { -+ -+LOG_DEFINE_CATEGORY(IPASoftBL) -+ -+/** -+ * \class BlackLevel -+ * \brief Object providing black point level for software ISP -+ * -+ * Black level can be provided in hardware tuning files or, if no tuning file is -+ * available for the given hardware, guessed automatically, with less accuracy. -+ * As tuning files are not yet implemented for software ISP, BlackLevel -+ * currently provides only guessed black levels. -+ * -+ * This class serves for tracking black level as a property of the underlying -+ * hardware, not as means of enhancing a particular scene or image. -+ * -+ * The class is supposed to be instantiated for the given camera stream. -+ * The black level can be retrieved using BlackLevel::get() method. It is -+ * initially 0 and may change when updated using BlackLevel::update() method. -+ */ -+ -+BlackLevel::BlackLevel() -+ : blackLevel_(255), blackLevelSet_(false) -+{ -+} -+ -+/** -+ * \brief Return the current black level -+ * -+ * \return The black level, in the range from 0 (minimum) to 255 (maximum). -+ * If the black level couldn't be determined yet, return 0. -+ */ -+unsigned int BlackLevel::get() const -+{ -+ return blackLevelSet_ ? blackLevel_ : 0; -+} -+ -+/** -+ * \brief Update black level from the provided histogram -+ * \param[in] yHistogram The histogram to be used for updating black level -+ * -+ * The black level is property of the given hardware, not image. It is updated -+ * only if it has not been yet set or if it is lower than the lowest value seen -+ * so far. -+ */ -+void BlackLevel::update(SwIspStats::histogram &yHistogram) -+{ -+ // The constant is selected to be "good enough", not overly conservative or -+ // aggressive. There is no magic about the given value. -+ constexpr float ignoredPercentage_ = 0.02; -+ const unsigned int total = -+ std::accumulate(begin(yHistogram), end(yHistogram), 0); -+ const unsigned int pixelThreshold = ignoredPercentage_ * total; -+ const unsigned int currentBlackIdx = -+ blackLevel_ / (256 / SwIspStats::kYHistogramSize); -+ -+ for (unsigned int i = 0, seen = 0; -+ i < currentBlackIdx && i < SwIspStats::kYHistogramSize; -+ i++) { -+ seen += yHistogram[i]; -+ if (seen >= pixelThreshold) { -+ blackLevel_ = i * (256 / SwIspStats::kYHistogramSize); -+ blackLevelSet_ = true; -+ LOG(IPASoftBL, Debug) -+ << "Auto-set black level: " -+ << i << "/" << SwIspStats::kYHistogramSize -+ << " (" << 100 * (seen - yHistogram[i]) / total << "% below, " -+ << 100 * seen / total << "% at or below)"; -+ break; -+ } -+ }; -+} -+} // namespace libcamera -diff --git a/src/ipa/simple/black_level.h b/src/ipa/simple/black_level.h -new file mode 100644 -index 00000000..b3785db0 ---- /dev/null -+++ b/src/ipa/simple/black_level.h -@@ -0,0 +1,28 @@ -+/* SPDX-License-Identifier: LGPL-2.1-or-later */ -+/* -+ * Copyright (C) 2024, Red Hat Inc. -+ * -+ * black_level.h - black level handling -+ */ -+ -+#pragma once -+ -+#include <array> -+ -+#include "libcamera/internal/software_isp/swisp_stats.h" -+ -+namespace libcamera { -+ -+class BlackLevel -+{ -+public: -+ BlackLevel(); -+ unsigned int get() const; -+ void update(std::array<unsigned int, SwIspStats::kYHistogramSize> &yHistogram); -+ -+private: -+ unsigned int blackLevel_; -+ bool blackLevelSet_; -+}; -+ -+} // namespace libcamera -diff --git a/src/ipa/simple/meson.build b/src/ipa/simple/meson.build -index 3e863db7..44b5f1d7 100644 ---- a/src/ipa/simple/meson.build -+++ b/src/ipa/simple/meson.build -@@ -2,8 +2,13 @@ - - ipa_name = 'ipa_soft_simple' - -+soft_simple_sources = files([ -+ 'soft_simple.cpp', -+ 'black_level.cpp', -+]) -+ - mod = shared_module(ipa_name, -- ['soft_simple.cpp', libcamera_generated_ipa_headers], -+ [soft_simple_sources, libcamera_generated_ipa_headers], - name_prefix : '', - include_directories : [ipa_includes, libipa_includes], - dependencies : libcamera_private, -diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp -index 312df4ba..ac027568 100644 ---- a/src/ipa/simple/soft_simple.cpp -+++ b/src/ipa/simple/soft_simple.cpp -@@ -22,6 +22,8 @@ - #include "libcamera/internal/software_isp/debayer_params.h" - #include "libcamera/internal/software_isp/swisp_stats.h" - -+#include "black_level.h" -+ - namespace libcamera { - - LOG_DEFINE_CATEGORY(IPASoft) -@@ -33,7 +35,8 @@ class IPASoftSimple : public ipa::soft::IPASoftInterface - public: - IPASoftSimple() - : params_(static_cast<DebayerParams *>(MAP_FAILED)), -- stats_(static_cast<SwIspStats *>(MAP_FAILED)), ignore_updates_(0) -+ stats_(static_cast<SwIspStats *>(MAP_FAILED)), -+ blackLevel_(BlackLevel()), ignore_updates_(0) - { - } - -@@ -63,6 +66,7 @@ private: - SharedFD fdParams_; - DebayerParams *params_; - SwIspStats *stats_; -+ BlackLevel blackLevel_; - - int32_t exposure_min_, exposure_max_; - int32_t again_min_, again_max_; -@@ -196,6 +200,10 @@ void IPASoftSimple::processStats(const ControlList &sensorControls) - params_->gainG = 256; - params_->gamma = 0.5; - -+ if (ignore_updates_ > 0) -+ blackLevel_.update(stats_->yHistogram); -+ params_->blackLevel = blackLevel_.get(); -+ - setIspParams.emit(0); - - /* -@@ -211,18 +219,19 @@ void IPASoftSimple::processStats(const ControlList &sensorControls) - * Calculate Mean Sample Value (MSV) according to formula from: - * https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf - */ -- constexpr unsigned int yHistValsPerBin = -- SwIspStats::kYHistogramSize / kExposureBinsCount; -- constexpr unsigned int yHistValsPerBinMod = -- SwIspStats::kYHistogramSize / -- (SwIspStats::kYHistogramSize % kExposureBinsCount + 1); -+ const unsigned int blackLevelHistIdx = -+ params_->blackLevel / (256 / SwIspStats::kYHistogramSize); -+ const unsigned int histogramSize = SwIspStats::kYHistogramSize - blackLevelHistIdx; -+ const unsigned int yHistValsPerBin = histogramSize / kExposureBinsCount; -+ const unsigned int yHistValsPerBinMod = -+ histogramSize / (histogramSize % kExposureBinsCount + 1); - int ExposureBins[kExposureBinsCount] = {}; - unsigned int denom = 0; - unsigned int num = 0; - -- for (unsigned int i = 0; i < SwIspStats::kYHistogramSize; i++) { -+ for (unsigned int i = 0; i < histogramSize; i++) { - unsigned int idx = (i - (i / yHistValsPerBinMod)) / yHistValsPerBin; -- ExposureBins[idx] += stats_->yHistogram[i]; -+ ExposureBins[idx] += stats_->yHistogram[blackLevelHistIdx + i]; - } - - for (unsigned int i = 0; i < kExposureBinsCount; i++) { -@@ -256,7 +265,8 @@ void IPASoftSimple::processStats(const ControlList &sensorControls) - - LOG(IPASoft, Debug) << "exposureMSV " << exposureMSV - << " exp " << exposure_ << " again " << again_ -- << " gain R/B " << params_->gainR << "/" << params_->gainB; -+ << " gain R/B " << params_->gainR << "/" << params_->gainB -+ << " black level " << params_->blackLevel; - } - - void IPASoftSimple::updateExposure(double exposureMSV) -diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp -index a1692693..3be3cdfe 100644 ---- a/src/libcamera/software_isp/debayer_cpu.cpp -+++ b/src/libcamera/software_isp/debayer_cpu.cpp -@@ -35,7 +35,7 @@ namespace libcamera { - * \param[in] stats Pointer to the stats object to use. - */ - DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats) -- : stats_(std::move(stats)), gamma_correction_(1.0) -+ : stats_(std::move(stats)), gamma_correction_(1.0), blackLevel_(0) - { - #ifdef __x86_64__ - enableInputMemcpy_ = false; -@@ -683,11 +683,16 @@ void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams - } - - /* Apply DebayerParams */ -- if (params.gamma != gamma_correction_) { -- for (unsigned int i = 0; i < kGammaLookupSize; i++) -- gamma_[i] = UINT8_MAX * powf(i / (kGammaLookupSize - 1.0), params.gamma); -+ if (params.gamma != gamma_correction_ || params.blackLevel != blackLevel_) { -+ const unsigned int blackIndex = -+ params.blackLevel * kGammaLookupSize / 256; -+ std::fill(gamma_.begin(), gamma_.begin() + blackIndex, 0); -+ const float divisor = kGammaLookupSize - blackIndex - 1.0; -+ for (unsigned int i = blackIndex; i < kGammaLookupSize; i++) -+ gamma_[i] = UINT8_MAX * powf((i - blackIndex) / divisor, params.gamma); - - gamma_correction_ = params.gamma; -+ blackLevel_ = params.blackLevel; - } - - if (swapRedBlueGains_) -diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h -index 5f44fc65..ea02f909 100644 ---- a/src/libcamera/software_isp/debayer_cpu.h -+++ b/src/libcamera/software_isp/debayer_cpu.h -@@ -147,6 +147,7 @@ private: - bool enableInputMemcpy_; - bool swapRedBlueGains_; - float gamma_correction_; -+ unsigned int blackLevel_; - unsigned int measuredFrames_; - int64_t frameProcessTime_; - /* Skip 30 frames for things to stabilize then measure 30 frames */ -diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp -index 388b4496..9b49be41 100644 ---- a/src/libcamera/software_isp/software_isp.cpp -+++ b/src/libcamera/software_isp/software_isp.cpp -@@ -64,7 +64,7 @@ LOG_DEFINE_CATEGORY(SoftwareIsp) - */ - SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls) - : debayer_(nullptr), -- debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10, DebayerParams::kGain10, 0.5f }, -+ debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10, DebayerParams::kGain10, 0.5f, 0 }, - dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System) - { - if (!dmaHeap_.isValid()) { --- -2.43.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch b/users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch deleted file mode 100644 index 5b562c603c52..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0019-libcamera-Soft-IPA-use-CameraSensorHelper-for-analog.patch +++ /dev/null @@ -1,239 +0,0 @@ -From b0c07674abecb05dc0af93a4b749971f057bc3c6 Mon Sep 17 00:00:00 2001 -From: Andrei Konovalov <andrey.konovalov.ynk@gmail.com> -Date: Mon, 11 Mar 2024 15:15:22 +0100 -Subject: [PATCH 19/21] libcamera: Soft IPA: use CameraSensorHelper for - analogue gain - -Use CameraSensorHelper to convert the analogue gain code read from the -camera sensor into real analogue gain value. In the future this makes -it possible to use faster AE/AGC algorithm. For now the same AE/AGC -algorithm is used, but even then the CameraSensorHelper lets us use the -full range of analogue gain values. - -If there is no CameraSensorHelper for the camera sensor in use, a -warning log message is printed, and the AE/AGC works exactly as before -this change. - -Signed-off-by: Andrei Konovalov <andrey.konovalov.ynk@gmail.com> -Reviewed-by: Hans de Goede <hdegoede@redhat.com> -Signed-off-by: Hans de Goede <hdegoede@redhat.com> -Reviewed-by: Milan Zamazal <mzamazal@redhat.com> ---- - .../internal/software_isp/software_isp.h | 3 +- - src/ipa/simple/soft_simple.cpp | 77 ++++++++++++------- - src/libcamera/pipeline/simple/simple.cpp | 2 +- - src/libcamera/software_isp/software_isp.cpp | 8 +- - 4 files changed, 57 insertions(+), 33 deletions(-) - -diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h -index 8d25e979..2a6db7ba 100644 ---- a/include/libcamera/internal/software_isp/software_isp.h -+++ b/include/libcamera/internal/software_isp/software_isp.h -@@ -26,6 +26,7 @@ - #include <libcamera/ipa/soft_ipa_interface.h> - #include <libcamera/ipa/soft_ipa_proxy.h> - -+#include "libcamera/internal/camera_sensor.h" - #include "libcamera/internal/dma_heaps.h" - #include "libcamera/internal/pipeline_handler.h" - #include "libcamera/internal/shared_mem_object.h" -@@ -43,7 +44,7 @@ LOG_DECLARE_CATEGORY(SoftwareIsp) - class SoftwareIsp - { - public: -- SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls); -+ SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor); - ~SoftwareIsp(); - - int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; } -diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp -index ac027568..e4d64762 100644 ---- a/src/ipa/simple/soft_simple.cpp -+++ b/src/ipa/simple/soft_simple.cpp -@@ -22,6 +22,8 @@ - #include "libcamera/internal/software_isp/debayer_params.h" - #include "libcamera/internal/software_isp/swisp_stats.h" - -+#include "libipa/camera_sensor_helper.h" -+ - #include "black_level.h" - - namespace libcamera { -@@ -67,18 +69,27 @@ private: - DebayerParams *params_; - SwIspStats *stats_; - BlackLevel blackLevel_; -+ std::unique_ptr<CameraSensorHelper> camHelper_; - - int32_t exposure_min_, exposure_max_; -- int32_t again_min_, again_max_; -- int32_t again_, exposure_; -+ int32_t exposure_; -+ double again_min_, again_max_, againMinStep_; -+ double again_; - unsigned int ignore_updates_; - }; - --int IPASoftSimple::init([[maybe_unused]] const IPASettings &settings, -+int IPASoftSimple::init(const IPASettings &settings, - const SharedFD &fdStats, - const SharedFD &fdParams, - const ControlInfoMap &sensorInfoMap) - { -+ camHelper_ = CameraSensorHelperFactoryBase::create(settings.sensorModel); -+ if (camHelper_ == nullptr) { -+ LOG(IPASoft, Warning) -+ << "Failed to create camera sensor helper for " -+ << settings.sensorModel; -+ } -+ - fdStats_ = fdStats; - if (!fdStats_.isValid()) { - LOG(IPASoft, Error) << "Invalid Statistics handle"; -@@ -132,25 +143,35 @@ int IPASoftSimple::configure(const ControlInfoMap &sensorInfoMap) - exposure_min_ = 1; - } - -- again_min_ = gain_info.min().get<int32_t>(); -- again_max_ = gain_info.max().get<int32_t>(); -- /* -- * The camera sensor gain (g) is usually not equal to the value written -- * into the gain register (x). But the way how the AGC algorithm changes -- * the gain value to make the total exposure closer to the optimum assumes -- * that g(x) is not too far from linear function. If the minimal gain is 0, -- * the g(x) is likely to be far from the linear, like g(x) = a / (b * x + c). -- * To avoid unexpected changes to the gain by the AGC algorithm (abrupt near -- * one edge, and very small near the other) we limit the range of the gain -- * values used. -- */ -- if (!again_min_) { -- LOG(IPASoft, Warning) << "Minimum gain is zero, that can't be linear"; -- again_min_ = std::min(100, again_min_ / 2 + again_max_ / 2); -+ int32_t again_min = gain_info.min().get<int32_t>(); -+ int32_t again_max = gain_info.max().get<int32_t>(); -+ -+ if (camHelper_) { -+ again_min_ = camHelper_->gain(again_min); -+ again_max_ = camHelper_->gain(again_max); -+ againMinStep_ = (again_max_ - again_min_) / 100.0; -+ } else { -+ /* -+ * The camera sensor gain (g) is usually not equal to the value written -+ * into the gain register (x). But the way how the AGC algorithm changes -+ * the gain value to make the total exposure closer to the optimum assumes -+ * that g(x) is not too far from linear function. If the minimal gain is 0, -+ * the g(x) is likely to be far from the linear, like g(x) = a / (b * x + c). -+ * To avoid unexpected changes to the gain by the AGC algorithm (abrupt near -+ * one edge, and very small near the other) we limit the range of the gain -+ * values used. -+ */ -+ again_max_ = again_max; -+ if (!again_min) { -+ LOG(IPASoft, Warning) << "Minimum gain is zero, that can't be linear"; -+ again_min_ = std::min(100, again_min / 2 + again_max / 2); -+ } -+ againMinStep_ = 1.0; - } - - LOG(IPASoft, Info) << "Exposure " << exposure_min_ << "-" << exposure_max_ -- << ", gain " << again_min_ << "-" << again_max_; -+ << ", gain " << again_min_ << "-" << again_max_ -+ << " (" << againMinStep_ << ")"; - - return 0; - } -@@ -252,12 +273,14 @@ void IPASoftSimple::processStats(const ControlList &sensorControls) - ControlList ctrls(sensorControls); - - exposure_ = ctrls.get(V4L2_CID_EXPOSURE).get<int32_t>(); -- again_ = ctrls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); -+ int32_t again = ctrls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>(); -+ again_ = camHelper_ ? camHelper_->gain(again) : again; - - updateExposure(exposureMSV); - - ctrls.set(V4L2_CID_EXPOSURE, exposure_); -- ctrls.set(V4L2_CID_ANALOGUE_GAIN, again_); -+ ctrls.set(V4L2_CID_ANALOGUE_GAIN, -+ static_cast<int32_t>(camHelper_ ? camHelper_->gainCode(again_) : again_)); - - ignore_updates_ = 2; - -@@ -276,7 +299,7 @@ void IPASoftSimple::updateExposure(double exposureMSV) - static constexpr uint8_t kExpNumeratorUp = kExpDenominator + 1; - static constexpr uint8_t kExpNumeratorDown = kExpDenominator - 1; - -- int next; -+ double next; - - if (exposureMSV < kExposureOptimal - kExposureSatisfactory) { - next = exposure_ * kExpNumeratorUp / kExpDenominator; -@@ -286,18 +309,18 @@ void IPASoftSimple::updateExposure(double exposureMSV) - exposure_ = next; - if (exposure_ >= exposure_max_) { - next = again_ * kExpNumeratorUp / kExpDenominator; -- if (next - again_ < 1) -- again_ += 1; -+ if (next - again_ < againMinStep_) -+ again_ += againMinStep_; - else - again_ = next; - } - } - - if (exposureMSV > kExposureOptimal + kExposureSatisfactory) { -- if (exposure_ == exposure_max_ && again_ != again_min_) { -+ if (exposure_ == exposure_max_ && again_ > again_min_) { - next = again_ * kExpNumeratorDown / kExpDenominator; -- if (again_ - next < 1) -- again_ -= 1; -+ if (again_ - next < againMinStep_) -+ again_ -= againMinStep_; - else - again_ = next; - } else { -diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp -index c3ebb7b7..7e932a14 100644 ---- a/src/libcamera/pipeline/simple/simple.cpp -+++ b/src/libcamera/pipeline/simple/simple.cpp -@@ -525,7 +525,7 @@ int SimpleCameraData::init() - * Instantiate Soft ISP if this is enabled for the given driver and no converter is used. - */ - if (!converter_ && pipe->swIspEnabled()) { -- swIsp_ = std::make_unique<SoftwareIsp>(pipe, sensor_->controls()); -+ swIsp_ = std::make_unique<SoftwareIsp>(pipe, sensor_.get()); - if (!swIsp_->isValid()) { - LOG(SimplePipeline, Warning) - << "Failed to create software ISP, disabling software debayering"; -diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp -index 9b49be41..ea4d96e4 100644 ---- a/src/libcamera/software_isp/software_isp.cpp -+++ b/src/libcamera/software_isp/software_isp.cpp -@@ -60,9 +60,9 @@ LOG_DEFINE_CATEGORY(SoftwareIsp) - /** - * \brief Constructs SoftwareIsp object - * \param[in] pipe The pipeline handler in use -- * \param[in] sensorControls ControlInfoMap describing the controls supported by the sensor -+ * \param[in] sensor Pointer to the CameraSensor instance owned by the pipeline handler - */ --SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorControls) -+SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor) - : debayer_(nullptr), - debayerParams_{ DebayerParams::kGain10, DebayerParams::kGain10, DebayerParams::kGain10, 0.5f, 0 }, - dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System) -@@ -97,10 +97,10 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const ControlInfoMap &sensorCont - return; - } - -- int ret = ipa_->init(IPASettings{ "No cfg file", "No sensor model" }, -+ int ret = ipa_->init(IPASettings{ "No cfg file", sensor->model() }, - debayer_->getStatsFD(), - sharedParams_.fd(), -- sensorControls); -+ sensor->controls()); - if (ret) { - LOG(SoftwareIsp, Error) << "IPA init failed"; - debayer_.reset(); --- -2.43.2 - diff --git a/users/flokli/keyboards/corneish_zen/0001-miryoku_behaviors-add-quick-tap-ms-require-prior-idl.patch b/users/flokli/keyboards/corneish_zen/0001-miryoku_behaviors-add-quick-tap-ms-require-prior-idl.patch new file mode 100644 index 000000000000..fc86c0627ddc --- /dev/null +++ b/users/flokli/keyboards/corneish_zen/0001-miryoku_behaviors-add-quick-tap-ms-require-prior-idl.patch @@ -0,0 +1,25 @@ +From 9ed3e8ee2aad704fcfef2490617e2fd22902b2c4 Mon Sep 17 00:00:00 2001 +From: Florian Klink <flokli@flokli.de> +Date: Sun, 27 Oct 2024 12:01:13 +0100 +Subject: [PATCH] miryoku_behaviors: add quick-tap-ms, require-prior-idle-ms + +--- + miryoku/miryoku_behaviors.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/miryoku/miryoku_behaviors.dtsi b/miryoku/miryoku_behaviors.dtsi +index 473df49..73211da 100644 +--- a/miryoku/miryoku_behaviors.dtsi ++++ b/miryoku/miryoku_behaviors.dtsi +@@ -14,6 +14,8 @@ + compatible = "zmk,behavior-hold-tap"; + #binding-cells = <2>; + tapping-term-ms = <U_TAPPING_TERM>; ++ quick-tap-ms = <200>; ++ require-prior-idle-ms = <125>; + flavor = "tap-preferred"; + bindings = <&mo>, <&kp>; + }; +-- +2.46.1 + diff --git a/users/flokli/keyboards/corneish_zen/0001-miryoku_layer_alternatives.h-expose-alt-gr-on-G-and-.patch b/users/flokli/keyboards/corneish_zen/0001-miryoku_layer_alternatives.h-expose-alt-gr-on-G-and-.patch new file mode 100644 index 000000000000..540ecb162e2d --- /dev/null +++ b/users/flokli/keyboards/corneish_zen/0001-miryoku_layer_alternatives.h-expose-alt-gr-on-G-and-.patch @@ -0,0 +1,25 @@ +From a852a9738cc7510f6d3b80d1befb3c88ef8f08f7 Mon Sep 17 00:00:00 2001 +From: Florian Klink <flokli@flokli.de> +Date: Sun, 27 Oct 2024 11:14:30 +0100 +Subject: [PATCH] miryoku_layer_alternatives.h: expose alt-gr on G and M + +--- + miryoku/miryoku_babel/miryoku_layer_alternatives.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/miryoku/miryoku_babel/miryoku_layer_alternatives.h b/miryoku/miryoku_babel/miryoku_layer_alternatives.h +index 8044fdd..07ed9b6 100644 +--- a/miryoku/miryoku_babel/miryoku_layer_alternatives.h ++++ b/miryoku/miryoku_babel/miryoku_layer_alternatives.h +@@ -86,7 +86,7 @@ U_NP, U_NP, U_LT(U_MEDIA, ESC),U_LT(U_NAV, SPACE),U_LT + + #define MIRYOKU_ALTERNATIVES_BASE_COLEMAKDH \ + &kp Q, &kp W, &kp F, &kp P, &kp B, &kp J, &kp L, &kp U, &kp Y, &kp SQT, \ +-U_MT(LGUI, A), U_MT(LALT, R), U_MT(LCTRL, S), U_MT(LSHFT, T), &kp G, &kp M, U_MT(LSHFT, N), U_MT(LCTRL, E), U_MT(LALT, I), U_MT(LGUI, O), \ ++U_MT(LGUI, A), U_MT(LALT, R), U_MT(LCTRL, S), U_MT(LSHFT, T), U_MT(RALT, G), U_MT(RALT, M), U_MT(LSHFT, N), U_MT(LCTRL, E), U_MT(LALT, I), U_MT(LGUI, O), \ + U_LT(U_BUTTON, Z), U_MT(RALT, X), &kp C, &kp D, &kp V, &kp K, &kp H, &kp COMMA, U_MT(RALT, DOT), U_LT(U_BUTTON, SLASH),\ + U_NP, U_NP, U_LT(U_MEDIA, ESC),U_LT(U_NAV, SPACE),U_LT(U_MOUSE, TAB),U_LT(U_SYM, RET), U_LT(U_NUM, BSPC), U_LT(U_FUN, DEL), U_NP, U_NP + +-- +2.46.1 + diff --git a/users/flokli/keyboards/corneish_zen/default.nix b/users/flokli/keyboards/corneish_zen/default.nix new file mode 100644 index 000000000000..f570fc0bc003 --- /dev/null +++ b/users/flokli/keyboards/corneish_zen/default.nix @@ -0,0 +1,62 @@ +{ pkgs, lib, ... }: +let + zmk-nix = pkgs.fetchFromGitHub { + owner = "lilyinstarlight"; + repo = "zmk-nix"; + rev = "d72e94ab94b2bceb60a29a2a8c2e1d304a4e922e"; + hash = "sha256-3WXPPBJ2u8rMxejPhUahSiqOBr1BOfTgDa7oQDPtw54="; + }; + + builders = pkgs.callPackage (import (zmk-nix + "/nix/builders.nix")) { }; + + miryoku_zmk = pkgs.fetchFromGitHub { + owner = "manna-harbour"; + repo = "miryoku_zmk"; + rev = "e6683e9f8b6c199b339208b1b501e88a7308ed48"; + hash = "sha256-GjTbAoyhr557Tn4JaWsA3Po5KxMsQXrpKc9H+PU3T8A="; + }; + + miryoku_zmk_patched = pkgs.runCommand "miryoku_zmk_patched" { } '' + mkdir -p $out + cp -r ${miryoku_zmk}/. $out/ + cd $out + chmod -R +w $out + patch -p1 < ${./0001-miryoku_layer_alternatives.h-expose-alt-gr-on-G-and-.patch} + patch -p1 < ${./0001-miryoku_behaviors-add-quick-tap-ms-require-prior-idl.patch} + ''; + +in + +rec { + config = pkgs.runCommand "config" { } '' + mkdir -p $out/config + cp -r ${miryoku_zmk_patched}/miryoku $out/ + cp ${./west.yml} $out/config/west.yml + cp ${miryoku_zmk_patched}/config/corneish_zen.keymap $out/config/ + ''; + + # helpful for debugging the resulting keymap + config-flat = pkgs.runCommand "config-flat" + { + nativeBuildInputs = [ pkgs.python3.pkgs.pcpp ]; + } '' + mkdir -p $out/config + cp ${./west.yml} $out/config/west.yml + pcpp --passthru-unfound-includes -o $out/config/corneish_zen.keymap ${miryoku_zmk_patched}/config/corneish_zen.keymap + ''; + + firmware = builders.buildSplitKeyboard { + name = "corneish_zen_v1"; + board = "corneish_zen_v1_%PART%"; + zephyrDepsHash = "sha256-D5CAlrO/E6DPbtUJyh/ec8ACpo1XM1jx2gLS2TpklBQ="; + src = config; + }; + + flash-left = pkgs.writeShellScript "flash.sh" '' + cp ${firmware}/zmk_left.uf2 /run/media/$USER/CORNEISHZEN/ + ''; + + flash-right = pkgs.writeShellScript "flash.sh" '' + cp ${firmware}/zmk_right.uf2 /run/media/$USER/CORNEISHZEN/ + ''; +} diff --git a/users/flokli/keyboards/corneish_zen/west.yml b/users/flokli/keyboards/corneish_zen/west.yml new file mode 100644 index 000000000000..b48d4a66e986 --- /dev/null +++ b/users/flokli/keyboards/corneish_zen/west.yml @@ -0,0 +1,34 @@ +manifest: + remotes: + - name: zmkfirmware + url-base: https://github.com/zmkfirmware + projects: + - name: zephyr + remote: zmkfirmware + revision: f8e4d15791602c67405c0fd2651167a895939565 # v3.5.0+zmk-fixes + import: + name-blocklist: + - ci-tools + - hal_altera + - hal_cypress + - hal_infineon + - hal_microchip + - hal_nxp + - hal_openisa + - hal_silabs + - hal_xtensa + - hal_st + - hal_ti + - loramac-node + - mcuboot + - mcumgr + - net-tools + - openthread + - edtt + - trusted-firmware-m + - name: zmk + remote: zmkfirmware + revision: 7f1ee320ab638245bbdae9b1cda5d5c50e2cb16e # main + import: app/west.yml + self: + path: config diff --git a/users/flokli/keyboards/dilemma/default.nix b/users/flokli/keyboards/dilemma/default.nix index 265f8e56dbf0..5c962b77689f 100644 --- a/users/flokli/keyboards/dilemma/default.nix +++ b/users/flokli/keyboards/dilemma/default.nix @@ -1,16 +1,18 @@ { depot, pkgs, ... }: rec { + qmk_firmware_src = pkgs.fetchFromGitHub { + owner = "qmk"; + repo = "qmk_firmware"; + rev = "0.26.6"; + hash = "sha256-mzkX1YF7MLrBpDhQV/0IlEyjcgaCkq8EaRDoBT97o8I="; + fetchSubmodules = true; + }; + firmware = pkgs.stdenv.mkDerivation { name = "keychron-bastardkb-dilemma-firmware"; - src = pkgs.fetchFromGitHub { - owner = "qmk"; - repo = "qmk_firmware"; - rev = "728aa576b0cd65c6fb7cf77132fdcd06fcedb643"; # develop branch - hash = "sha256-YmdX8nEsB1R8d265HAmvwejPjEHJdoTnm4QNigzrcyw="; - fetchSubmodules = true; - }; + src = qmk_firmware_src; patches = [ ./enable-taps.patch ]; @@ -38,7 +40,7 @@ rec { }; flash = pkgs.writeShellScript "flash.sh" '' - ${pkgs.qmk}/bin/qmk flash ${firmware}/bastardkb_dilemma_3x5_3_flokli.uf2 + QMK_HOME=${qmk_firmware_src} ${pkgs.qmk}/bin/qmk flash ${firmware}/bastardkb_dilemma_3x5_3_flokli.uf2 ''; meta.ci.targets = [ "firmware" ]; diff --git a/users/flokli/keyboards/dilemma/keymap.c b/users/flokli/keyboards/dilemma/keymap.c index 2c21ef6c9ef3..695c4227f0d2 100644 --- a/users/flokli/keyboards/dilemma/keymap.c +++ b/users/flokli/keyboards/dilemma/keymap.c @@ -173,10 +173,10 @@ enum dilemma_keymap_layers { L00, L01, L02, L03, L04, R05, R06, R07, R08, R09, \ L10, L11, L12, L13, L14, R15, R16, R17, R18, R19, \ ...) \ - L00, L01, L02, L03, L04, \ - R05, R06, R07, R08, R09, \ - LGUI_T(L10), LALT_T(L11), LCTL_T(L12), LSFT_T(L13), L14, \ - R15, RSFT_T(R16), RCTL_T(R17), RALT_T(R18), RGUI_T(R19), \ + L00, L01, L02, L03, L04, \ + R05, R06, R07, R08, R09, \ + LGUI_T(L10), LALT_T(L11), LCTL_T(L12), LSFT_T(L13), RALT_T(L14), \ + RALT_T(R15), RSFT_T(R16), RCTL_T(R17), LALT_T(R18), RGUI_T(R19), \ __VA_ARGS__ #define HOME_ROW_MOD_GACS(...) _HOME_ROW_MOD_GACS(__VA_ARGS__) diff --git a/users/flokli/keyboards/k6_pro/default.nix b/users/flokli/keyboards/k6_pro/default.nix index 708bec7313b6..49945b88aeec 100644 --- a/users/flokli/keyboards/k6_pro/default.nix +++ b/users/flokli/keyboards/k6_pro/default.nix @@ -1,16 +1,18 @@ { depot, pkgs, ... }: rec { + qmk_firmware_src = pkgs.fetchFromGitHub { + owner = "Keychron"; # the Keychron fork of qmk/qmk_firmware + repo = "qmk_firmware"; + rev = "e0a48783e7cde92d1edfc53a8fff511c45e869d4"; # bluetooth_playground branch + hash = "sha256-Pk9kXktmej9JyvSt7UMEW2FDrBg7k1lOssh6HjrP5ro="; + fetchSubmodules = true; + }; + firmware = pkgs.stdenv.mkDerivation { name = "keychron-k6_pro-firmware"; - src = pkgs.fetchFromGitHub { - owner = "Keychron"; # the Keychron fork of qmk/qmk_firmware - repo = "qmk_firmware"; - rev = "e0a48783e7cde92d1edfc53a8fff511c45e869d4"; # bluetooth_playground branch - hash = "sha256-Pk9kXktmej9JyvSt7UMEW2FDrBg7k1lOssh6HjrP5ro="; - fetchSubmodules = true; - }; + src = qmk_firmware_src; nativeBuildInputs = [ pkgs.qmk @@ -32,7 +34,7 @@ rec { }; flash = pkgs.writeShellScript "flash.sh" '' - ${pkgs.qmk}/bin/qmk flash ${firmware}/keychron_k6_pro_ansi_rgb_flokli.bin + QMK_HOME=${qmk_firmware_src} ${pkgs.qmk}/bin/qmk flash ${firmware}/keychron_k6_pro_ansi_rgb_flokli.bin ''; meta.ci.targets = [ "firmware" ]; diff --git a/users/flokli/nixos/default.nix b/users/flokli/nixos/default.nix index 9ed223a90896..cce4801f45bd 100644 --- a/users/flokli/nixos/default.nix +++ b/users/flokli/nixos/default.nix @@ -23,6 +23,7 @@ depot.nix.readTree.drvTargets rec { deps = (depot.nix.lazy-deps { deploy-archeology-ec2.attr = "users.flokli.nixos.deploy-archeology-ec2"; + aws.attr = "third_party.nixpkgs.awscli"; }); shell = pkgs.mkShell { diff --git a/users/flokli/presentations/2023-09-09-nixcon-tvix/default.nix b/users/flokli/presentations/2023-09-09-nixcon-tvix/default.nix index 1ec0a0bd0ed7..b50309b6c2f6 100644 --- a/users/flokli/presentations/2023-09-09-nixcon-tvix/default.nix +++ b/users/flokli/presentations/2023-09-09-nixcon-tvix/default.nix @@ -18,9 +18,6 @@ stdenv.mkDerivation { fontDirectories = with pkgs; [ jetbrains-mono fira fira-code fira-mono lato ]; }; - PUPPETEER_EXECUTABLE_PATH = "${pkgs.chromium}/bin/chromium"; - PUPPETEER_SKIP_CHROMIUM_DOWNLOAD = "1"; - nativeBuildInputs = [ pkgs.reveal-md pkgs.graphviz ]; buildPhase = '' @@ -31,7 +28,10 @@ stdenv.mkDerivation { mkdir -p $out reveal-md --static $out presentation.md - reveal-md --print $out/slides.pdf presentation.md cp tvixbolt.webm $out + + CHROME_CONFIG_HOME=/build/.config reveal-md presentation.md --print $out/slides.pdf --puppeteer-chromium-executable="${pkgs.chromium}/bin/chromium" + # Above command doesn't fail on error, ensure file has been created + [[ -f "$out/slides.pdf" ]] || exit 1 ''; } diff --git a/users/flokli/presentations/2023-09-13-asg-tvix-store/default.nix b/users/flokli/presentations/2023-09-13-asg-tvix-store/default.nix index 840f21de8103..e1709a06786d 100644 --- a/users/flokli/presentations/2023-09-13-asg-tvix-store/default.nix +++ b/users/flokli/presentations/2023-09-13-asg-tvix-store/default.nix @@ -28,5 +28,9 @@ stdenv.mkDerivation { mkdir -p $out cp tvix-store-graph-blob-directory.svg $out/ reveal-md --static $out presentation.md + + CHROME_CONFIG_HOME=/build/.config reveal-md presentation.md --print $out/slides.pdf --puppeteer-chromium-executable="${pkgs.chromium}/bin/chromium" + # Above command doesn't fail on error, ensure file has been created + [[ -f "$out/slides.pdf" ]] || exit 1 ''; } diff --git a/users/flokli/presentations/2024-10-25-nixcon-tvix/.gitignore b/users/flokli/presentations/2024-10-25-nixcon-tvix/.gitignore new file mode 100644 index 000000000000..397b4a7624e3 --- /dev/null +++ b/users/flokli/presentations/2024-10-25-nixcon-tvix/.gitignore @@ -0,0 +1 @@ +*.log diff --git a/users/flokli/presentations/2024-10-25-nixcon-tvix/default.nix b/users/flokli/presentations/2024-10-25-nixcon-tvix/default.nix new file mode 100644 index 000000000000..763104cfd5ca --- /dev/null +++ b/users/flokli/presentations/2024-10-25-nixcon-tvix/default.nix @@ -0,0 +1,35 @@ +{ depot, pkgs, ... }: + +let + inherit (pkgs) + fontconfig qrencode runCommand stdenv; + mkQr = url: runCommand "qrcode.png" { } '' + ${qrencode}/bin/qrencode -o $out -t SVG -s 5 \ + --background=fafafa \ + --foreground=000000 \ + ${url} + ''; +in +stdenv.mkDerivation { + name = "2024-nixcon-tvix"; + src = ./.; + + FONTCONFIG_FILE = pkgs.makeFontsConf { + fontDirectories = with pkgs; [ jetbrains-mono fira fira-code fira-mono lato ]; + }; + + nativeBuildInputs = [ pkgs.reveal-md pkgs.graphviz ]; + + buildPhase = '' + cp ${depot.tvix.logo}/logo.png tvix-logo.png + cp ${mkQr "https://flokli.de"} qrcode-flokli.svg + cp ${mkQr "https://tvix.dev"} qrcode-tvix.svg + + mkdir -p $out + reveal-md --static $out presentation.md + + CHROME_CONFIG_HOME=/build/.config reveal-md presentation.md --print $out/slides.pdf --puppeteer-chromium-executable="${pkgs.chromium}/bin/chromium" + # Above command doesn't fail on error, ensure file has been created + [[ -f "$out/slides.pdf" ]] || exit 1 + ''; +} diff --git a/users/flokli/presentations/2024-10-25-nixcon-tvix/nar-bridge.png b/users/flokli/presentations/2024-10-25-nixcon-tvix/nar-bridge.png new file mode 100644 index 000000000000..1cf449a999cc --- /dev/null +++ b/users/flokli/presentations/2024-10-25-nixcon-tvix/nar-bridge.png Binary files differdiff --git a/users/flokli/presentations/2024-10-25-nixcon-tvix/nix-compat.png b/users/flokli/presentations/2024-10-25-nixcon-tvix/nix-compat.png new file mode 100644 index 000000000000..958ce1bf8dcf --- /dev/null +++ b/users/flokli/presentations/2024-10-25-nixcon-tvix/nix-compat.png Binary files differdiff --git a/users/flokli/presentations/2024-10-25-nixcon-tvix/presentation.md b/users/flokli/presentations/2024-10-25-nixcon-tvix/presentation.md new file mode 100644 index 000000000000..ca636e0a86b2 --- /dev/null +++ b/users/flokli/presentations/2024-10-25-nixcon-tvix/presentation.md @@ -0,0 +1,261 @@ +--- +author: +- Florian Klink +date: 2024-10-25 +title: "Tvix: Status update" +theme: solarized +revealOptions: + transition: 'fade' +--- + +# Tvix: Status update + +![Tvix Logo](tvix-logo.png) + +2023-10-25 + +Florian Klink (flokli) + +--- + +## Whoami + +- flokli<!-- .element: class="fragment" --> +- nixpkgs contributor since 2018, maintaining systemd, nsncd and more<!-- .element: class="fragment" --> +- Freelance Nix/DevOps consultant<!-- .element: class="fragment" --> + +--- + +## What is Tvix? + +--- + +![tvix solves this](./tvix_solves_this.jpg) +<!-- .element: class="r-stretch" --> + +--- + +## What is Tvix? + +- A Rust re-implementation of the components of the Nix package manager<!-- .element: class="fragment" --> +- Uses different underlying approaches while retaining Nix compatibility "on the surface"<!-- .element: class="fragment" --> +- modular architecture, allowing to recombine aspects to solve your usecase<!-- .element: class="fragment" --> +- No "end-user CLI" for now, focus on getting the foundational architecture right and 100% correctness with Nix<!-- .element: class="fragment" --> + +--- + +## Topics +- Component overview<!-- .element: class="fragment" --> +- Recent developments<!-- .element: class="fragment" --> +- Next steps<!-- .element: class="fragment" --> + +Note: Component overview, to understand a bit better how it's different / updates since the last talk / outlook on roadmap + +--- + +## Structure + + - <!-- .element: class="fragment" --> + **tvix-castore**, the granular data storage/syncing engine. + - <!-- .element: class="fragment" --> + **tvix-store**, the "Nix store implementation" on top of tvix-castore + - <!-- .element: class="fragment" --> + **nix-compat**, a library providing access to data formats, protocols and concepts + - <!-- .element: class="fragment" --> + **tvix-eval**, a bytecode interpreter evaluator and core Nix *language* concepts and builtins + - <!-- .element: class="fragment" --> + **tvix-build**, a generic builder interface + - <!-- .element: class="fragment" --> + **tvix-glue**, combines tvix-eval with tvix-[ca]store and tvix-build + + +Note: one big cargo workspace / go into detail later! / nix-compat: concepts like output path calculation, doesn't depend on tvix crates +tvix-eval: language concepts being Scopes, Thunks, Nix values, "core builtins" + +---- + +![tvix-castore](./tvix-castore.png) +<!-- .element: class="r-stretch" --> + +Note: Nix does do content addressing on a store path level, we're on a per-file/chunk in file. That model allows granular syncing and reuse of parts, which will speedup substitution/copying. Because everything is ca, it'll also allow decentralization and local p2p substitution. Think about everyone in the same room serving chunks. verified streaming. + +---- + +![tvix-store](./tvix-store.png) +<!-- .element: class="r-stretch" --> + +Note: track all metadata about store paths (think about the sqlite db), and link to castore instead of storing NAR. NarCalculation: this computation, is super nice to cache, as this info +never needs to expire, and is reconstructable in a pure CA manner. + +---- + +![tvix-store](./nix-compat.png) +<!-- .element: class="r-stretch" --> + +Note: kept as a somewhat separate library, Tvix "first consumer". But use from your code, it doesn't depend on Tvix bits. Regularly factoring out Nix concepts into this library + +---- + +![tvix-eval](./tvix-eval.png) +<!-- .element: class="r-stretch" --> + +Note: only includes basic builtins, like string manipulation, math, …. Other crates can bring their own builtins + +---- + +![tvix-build](./tvix-build.png) +<!-- .element: class="r-stretch" --> + +Note: Not aware of Nix, store paths etc. just flexible enough to express everything in there. Use it for your own build system! + +---- + +![tvix-glue](./tvix-glue.png) +<!-- .element: class="r-stretch" --> + +Note: connects the evaluator to store and builders + +---- + +![nar-bridge](./nar-bridge.png) +<!-- .element: class="r-stretch" --> + +Note: Example on how to use this: Nix HTTP binary cache lens into tvix-[ca]store, allows Nix to download from and push into. It renders NARs on-the-fly + +--- + +## Updates +Rough overview. Check blog posts and `git log` for details! + +---- + +## Updates (#1) + + - <!-- .element: class="fragment" --> + Fixes on error catchability and context behaviour + - <!-- .element: class="fragment" --> + More compact Nix Value types (memory-wise) + - <!-- .element: class="fragment" --> + `tvix-cli` REPL global scope manipulation (assign variables and use them in next command) + - <!-- .element: class="fragment" --> + `firefox.outPath` and `pkgsCross.aarch64-multiplatform.firefox.outPath` correct and added to CI 🎉 + +Notes: catchability/context to align behaviour with nix / … / assign variables and use them in the next REPL command + +---- + +## Updates (#2) + + - <!-- .element: class="fragment" --> + OpenTelemetry integration, trace propagation throughout the entire stack + - <!-- .element: class="fragment" --> + more backends in tvix-[ca]store (`object_store`/`local fs`/`redb`/`bigtable`/…) + - <!-- .element: class="fragment" --> + nar-bridge RIIR, was deployed as a fetch-through cache for cache.nixos.org at Bornhack + - <!-- .element: class="fragment" --> + store composition/combinators + - <!-- .element: class="fragment" --> + wiring up of builds (without reference propagation yet, but reference scanning) + +Notes: o11y already proven super helpful for debugging where time is spent / first version of composition / builds waiting on reference propagation + +---- + +## Other Updates + + - <!-- .element: class="fragment" --> + A lot of the tooling for `cache.nixos.org` usage / closure analysis making use of and contributing to `nix-compat` (`@edef`) 🎉 + - <!-- .element: class="fragment" --> + "Replit using `tvix-[ca]store` and reporting 10x storage reduction" (`@cbrewster`) 🎉 + - <!-- .element: class="fragment" --> + "Devenv is switching to Tvix" (Talk on Saturday 12:55, `@domenkozar`) 🎉 + +--- + +## Next steps (in no specific order): + + - <!-- .element: class="fragment" --> + Test suite classification system, to decouple test cases from test runner and share with other Nix impls + - <!-- .element: class="fragment" --> + (Continuous) Docs deployment, website restructuring + - <!-- .element: class="fragment" --> + Interactions with the evaluator (LSP, DAP) + - <!-- .element: class="fragment" --> + Persistent deployment of nar-bridge, as fetch-through cache for `cache.nixos.org` + - <!-- .element: class="fragment" --> + Blob / Chunking protocol improvements (use local chunks where possible, allow readahead) + +Note: Allows filtering, reusing test cases in Nixcpp and Lix. + Mention some behavorial changes found. + Mention fetchTree + Make it easier for new contributors to get started + LSP / Debug adapter protocol / tvix-eval jobs + / … / is gonna improve performance for IO into store paths + +---- + +## Next steps (in no specific order) (cont.): + + - <!-- .element: class="fragment" --> + "Build/Fetch realization goal engine" (tradeoff network bandwidth and CPU time) + - <!-- .element: class="fragment" --> + More per-store metrics and instance names + - <!-- .element: class="fragment" --> + More backends (p2p discovery, ipfs, …) + +Note: needed for builds / to get better insights into cache hit ratios etc. + +--- + +## Contributing + +- <!-- .element: class="fragment" --> + Join the IRC channel (`#tvix-dev` on `hackint`), bridged to Matrix and XMPP +- <!-- .element: class="fragment" --> + Check our issue tracker (b.tvl.fyi), as well as `tvix/docs/src/TODO.md` (but ask!) +- <!-- .element: class="fragment" --> + Try to use it and tell us how you broke it! +- <!-- .element: class="fragment" --> + Sponsoring + +Note: make sure to ask in the channel to ensure noone is already working on this + +--- + +# Thanks to... + +- <!-- .element: class="fragment" --> + all Tvix contributors +- <!-- .element: class="fragment" --> + Nix community members for their input on the architecture +- <!-- .element: class="fragment" --> + Sponsors + +Note: some drive-by, some sticking around longer / NLNET / Clan + +---- + +# Questions? + +<style> +.container{ + display: flex; +} +.col{ + flex: 1; +} +</style> + +<div class="container"> + +<div class="col"> +Florian Klink / <a href="https://flokli.de">flokli.de</a><br /> +<img src="qrcode-flokli.svg" /> +</div> + +<div class="col"> +Tvix / <a href="https://tvix.dev">tvix.dev</a><br /> +<img src="qrcode-tvix.svg" /> +</div> + +</div> diff --git a/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-build.png b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-build.png new file mode 100644 index 000000000000..5d11e73f7f12 --- /dev/null +++ b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-build.png Binary files differdiff --git a/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-castore.png b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-castore.png new file mode 100644 index 000000000000..c1f42e1112b6 --- /dev/null +++ b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-castore.png Binary files differdiff --git a/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-eval.png b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-eval.png new file mode 100644 index 000000000000..e7c034e6795d --- /dev/null +++ b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-eval.png Binary files differdiff --git a/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-glue.png b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-glue.png new file mode 100644 index 000000000000..00427aa143c7 --- /dev/null +++ b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-glue.png Binary files differdiff --git a/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-store.png b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-store.png new file mode 100644 index 000000000000..c35723afc9ab --- /dev/null +++ b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix-store.png Binary files differdiff --git a/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix_solves_this.jpg b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix_solves_this.jpg new file mode 100644 index 000000000000..d5494b1ec507 --- /dev/null +++ b/users/flokli/presentations/2024-10-25-nixcon-tvix/tvix_solves_this.jpg Binary files differdiff --git a/users/kranzes/OWNERS b/users/kranzes/OWNERS new file mode 100644 index 000000000000..7c5803bf4150 --- /dev/null +++ b/users/kranzes/OWNERS @@ -0,0 +1 @@ +kranzes diff --git a/users/kranzes/wasm-hello-world/Cargo.lock b/users/kranzes/wasm-hello-world/Cargo.lock new file mode 100644 index 000000000000..7a9956d8e2d1 --- /dev/null +++ b/users/kranzes/wasm-hello-world/Cargo.lock @@ -0,0 +1,124 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "proc-macro2" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "wasm_hello_world" +version = "0.1.0" +dependencies = [ + "wasm-bindgen", +] diff --git a/users/kranzes/wasm-hello-world/Cargo.nix b/users/kranzes/wasm-hello-world/Cargo.nix new file mode 100644 index 000000000000..d590411e11eb --- /dev/null +++ b/users/kranzes/wasm-hello-world/Cargo.nix @@ -0,0 +1,1082 @@ +# This file was @generated by crate2nix 0.14.1 with the command: +# "generate" "--all-features" +# See https://github.com/kolloch/crate2nix for more info. + +{ nixpkgs ? <nixpkgs> +, pkgs ? import nixpkgs { config = { }; } +, lib ? pkgs.lib +, stdenv ? pkgs.stdenv +, buildRustCrateForPkgs ? pkgs: pkgs.buildRustCrate + # This is used as the `crateOverrides` argument for `buildRustCrate`. +, defaultCrateOverrides ? pkgs.defaultCrateOverrides + # The features to enable for the root_crate or the workspace_members. +, rootFeatures ? [ "default" ] + # If true, throw errors instead of issueing deprecation warnings. +, strictDeprecation ? false + # Elements to add to the `-C target-feature=` argument passed to `rustc` + # (separated by `,`, prefixed with `+`). + # Used for conditional compilation based on CPU feature detection. +, targetFeatures ? [ ] + # Whether to perform release builds: longer compile times, faster binaries. +, release ? true + # Additional crate2nix configuration if it exists. +, crateConfig ? if builtins.pathExists ./crate-config.nix + then pkgs.callPackage ./crate-config.nix { } + else { } +}: + +rec { + # + # "public" attributes that we attempt to keep stable with new versions of crate2nix. + # + + rootCrate = rec { + packageId = "wasm_hello_world"; + + # Use this attribute to refer to the derivation building your root crate package. + # You can override the features with rootCrate.build.override { features = [ "default" "feature1" ... ]; }. + build = internal.buildRustCrateWithFeatures { + inherit packageId; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + # Refer your crate build derivation by name here. + # You can override the features with + # workspaceMembers."${crateName}".build.override { features = [ "default" "feature1" ... ]; }. + workspaceMembers = { + "wasm_hello_world" = rec { + packageId = "wasm_hello_world"; + build = internal.buildRustCrateWithFeatures { + packageId = "wasm_hello_world"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + }; + + # A derivation that joins the outputs of all workspace members together. + allWorkspaceMembers = pkgs.symlinkJoin { + name = "all-workspace-members"; + paths = + let members = builtins.attrValues workspaceMembers; + in builtins.map (m: m.build) members; + }; + + # + # "internal" ("private") attributes that may change in every new version of crate2nix. + # + + internal = rec { + # Build and dependency information for crates. + # Many of the fields are passed one-to-one to buildRustCrate. + # + # Noteworthy: + # * `dependencies`/`buildDependencies`: similar to the corresponding fields for buildRustCrate. + # but with additional information which is used during dependency/feature resolution. + # * `resolvedDependencies`: the selected default features reported by cargo - only included for debugging. + # * `devDependencies` as of now not used by `buildRustCrate` but used to + # inject test dependencies into the build + + crates = { + "bumpalo" = rec { + crateName = "bumpalo"; + version = "3.16.0"; + edition = "2021"; + sha256 = "0b015qb4knwanbdlp1x48pkb4pm57b8gidbhhhxr900q2wb6fabr"; + authors = [ + "Nick Fitzgerald <fitzgen@gmail.com>" + ]; + features = { + "allocator-api2" = [ "dep:allocator-api2" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "cfg-if" = rec { + crateName = "cfg-if"; + version = "1.0.0"; + edition = "2018"; + sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + }; + }; + "log" = rec { + crateName = "log"; + version = "0.4.21"; + edition = "2021"; + sha256 = "074hldq1q8rlzq2s2qa8f25hj4s3gpw71w64vdwzjd01a4g8rvch"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "kv_serde" = [ "kv_std" "value-bag/serde" "serde" ]; + "kv_std" = [ "std" "kv" "value-bag/error" ]; + "kv_sval" = [ "kv" "value-bag/sval" "sval" "sval_ref" ]; + "kv_unstable" = [ "kv" "value-bag" ]; + "kv_unstable_serde" = [ "kv_serde" "kv_unstable_std" ]; + "kv_unstable_std" = [ "kv_std" "kv_unstable" ]; + "kv_unstable_sval" = [ "kv_sval" "kv_unstable" ]; + "serde" = [ "dep:serde" ]; + "sval" = [ "dep:sval" ]; + "sval_ref" = [ "dep:sval_ref" ]; + "value-bag" = [ "dep:value-bag" ]; + }; + }; + "once_cell" = rec { + crateName = "once_cell"; + version = "1.19.0"; + edition = "2021"; + sha256 = "14kvw7px5z96dk4dwdm1r9cqhhy2cyj1l5n5b29mynbb8yr15nrz"; + authors = [ + "Aleksey Kladov <aleksey.kladov@gmail.com>" + ]; + features = { + "alloc" = [ "race" ]; + "atomic-polyfill" = [ "critical-section" ]; + "critical-section" = [ "dep:critical-section" "portable-atomic" ]; + "default" = [ "std" ]; + "parking_lot" = [ "dep:parking_lot_core" ]; + "portable-atomic" = [ "dep:portable-atomic" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "race" "std" ]; + }; + "proc-macro2" = rec { + crateName = "proc-macro2"; + version = "1.0.85"; + edition = "2021"; + sha256 = "08zwg5l5f3czp62g4cvzgjwnk176lsrwq6kdi4x0arm9bbhlq912"; + libName = "proc_macro2"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "unicode-ident"; + packageId = "unicode-ident"; + } + ]; + features = { + "default" = [ "proc-macro" ]; + }; + resolvedDefaultFeatures = [ "default" "proc-macro" ]; + }; + "quote" = rec { + crateName = "quote"; + version = "1.0.36"; + edition = "2018"; + sha256 = "19xcmh445bg6simirnnd4fvkmp6v2qiwxh5f6rw4a70h76pnm9qg"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "proc-macro" ]; + "proc-macro" = [ "proc-macro2/proc-macro" ]; + }; + resolvedDefaultFeatures = [ "default" "proc-macro" ]; + }; + "syn" = rec { + crateName = "syn"; + version = "2.0.66"; + edition = "2021"; + sha256 = "1xfgrprsbz8j31kabvfinb4fyhajlk2q7lxa18fb006yl90kyby4"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + { + name = "quote"; + packageId = "quote"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "unicode-ident"; + packageId = "unicode-ident"; + } + ]; + features = { + "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; + "printing" = [ "dep:quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; + "test" = [ "syn-test-suite/all-features" ]; + }; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "full" "parsing" "printing" "proc-macro" "visit" ]; + }; + "unicode-ident" = rec { + crateName = "unicode-ident"; + version = "1.0.12"; + edition = "2018"; + sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + + }; + "wasm-bindgen" = rec { + crateName = "wasm-bindgen"; + version = "0.2.93"; + edition = "2021"; + sha256 = "1dfr7pka5kwvky2fx82m9d060p842hc5fyyw8igryikcdb0xybm8"; + libName = "wasm_bindgen"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "wasm-bindgen-macro"; + packageId = "wasm-bindgen-macro"; + } + ]; + features = { + "default" = [ "spans" "std" ]; + "enable-interning" = [ "std" ]; + "serde" = [ "dep:serde" ]; + "serde-serialize" = [ "serde" "serde_json" "std" ]; + "serde_json" = [ "dep:serde_json" ]; + "spans" = [ "wasm-bindgen-macro/spans" ]; + "strict-macro" = [ "wasm-bindgen-macro/strict-macro" ]; + "xxx_debug_only_print_generated_code" = [ "wasm-bindgen-macro/xxx_debug_only_print_generated_code" ]; + }; + resolvedDefaultFeatures = [ "default" "spans" "std" ]; + }; + "wasm-bindgen-backend" = rec { + crateName = "wasm-bindgen-backend"; + version = "0.2.93"; + edition = "2021"; + sha256 = "0yypblaf94rdgqs5xw97499xfwgs1096yx026d6h88v563d9dqwx"; + libName = "wasm_bindgen_backend"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "bumpalo"; + packageId = "bumpalo"; + } + { + name = "log"; + packageId = "log"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn"; + features = [ "full" ]; + } + { + name = "wasm-bindgen-shared"; + packageId = "wasm-bindgen-shared"; + } + ]; + features = { + "extra-traits" = [ "syn/extra-traits" ]; + }; + resolvedDefaultFeatures = [ "spans" ]; + }; + "wasm-bindgen-macro" = rec { + crateName = "wasm-bindgen-macro"; + version = "0.2.93"; + edition = "2021"; + sha256 = "1kycd1xfx4d9xzqknvzbiqhwb5fzvjqrrn88x692q1vblj8lqp2q"; + procMacro = true; + libName = "wasm_bindgen_macro"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "quote"; + packageId = "quote"; + } + { + name = "wasm-bindgen-macro-support"; + packageId = "wasm-bindgen-macro-support"; + } + ]; + features = { + "spans" = [ "wasm-bindgen-macro-support/spans" ]; + "strict-macro" = [ "wasm-bindgen-macro-support/strict-macro" ]; + }; + resolvedDefaultFeatures = [ "spans" ]; + }; + "wasm-bindgen-macro-support" = rec { + crateName = "wasm-bindgen-macro-support"; + version = "0.2.93"; + edition = "2021"; + sha256 = "0dp8w6jmw44srym6l752nkr3hkplyw38a2fxz5f3j1ch9p3l1hxg"; + libName = "wasm_bindgen_macro_support"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn"; + features = [ "visit" "full" ]; + } + { + name = "wasm-bindgen-backend"; + packageId = "wasm-bindgen-backend"; + } + { + name = "wasm-bindgen-shared"; + packageId = "wasm-bindgen-shared"; + } + ]; + features = { + "extra-traits" = [ "syn/extra-traits" ]; + "spans" = [ "wasm-bindgen-backend/spans" ]; + }; + resolvedDefaultFeatures = [ "spans" ]; + }; + "wasm-bindgen-shared" = rec { + crateName = "wasm-bindgen-shared"; + version = "0.2.93"; + edition = "2021"; + links = "wasm_bindgen"; + sha256 = "1104bny0hv40jfap3hp8jhs0q4ya244qcrvql39i38xlghq0lan6"; + libName = "wasm_bindgen_shared"; + authors = [ + "The wasm-bindgen Developers" + ]; + + }; + "wasm_hello_world" = rec { + crateName = "wasm_hello_world"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./.; }; + type = [ "cdylib" ]; + dependencies = [ + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + ]; + + }; + }; + + # + # crate2nix/default.nix (excerpt start) + # + + /* Target (platform) data for conditional dependencies. + This corresponds roughly to what buildRustCrate is setting. + */ + makeDefaultTarget = platform: { + unix = platform.isUnix; + windows = platform.isWindows; + fuchsia = true; + test = false; + + inherit (platform.rust.platform) + arch + os + vendor; + family = platform.rust.platform.target-family; + env = "gnu"; + endian = + if platform.parsed.cpu.significantByte.name == "littleEndian" + then "little" else "big"; + pointer_width = toString platform.parsed.cpu.bits; + debug_assertions = false; + }; + + /* Filters common temp files and build files. */ + # TODO(pkolloch): Substitute with gitignore filter + sourceFilter = name: type: + let + baseName = builtins.baseNameOf (builtins.toString name); + in + ! ( + # Filter out git + baseName == ".gitignore" + || (type == "directory" && baseName == ".git") + + # Filter out build results + || ( + type == "directory" && ( + baseName == "target" + || baseName == "_site" + || baseName == ".sass-cache" + || baseName == ".jekyll-metadata" + || baseName == "build-artifacts" + ) + ) + + # Filter out nix-build result symlinks + || ( + type == "symlink" && lib.hasPrefix "result" baseName + ) + + # Filter out IDE config + || ( + type == "directory" && ( + baseName == ".idea" || baseName == ".vscode" + ) + ) || lib.hasSuffix ".iml" baseName + + # Filter out nix build files + || baseName == "Cargo.nix" + + # Filter out editor backup / swap files. + || lib.hasSuffix "~" baseName + || builtins.match "^\\.sw[a-z]$$" baseName != null + || builtins.match "^\\..*\\.sw[a-z]$$" baseName != null + || lib.hasSuffix ".tmp" baseName + || lib.hasSuffix ".bak" baseName + || baseName == "tests.nix" + ); + + /* Returns a crate which depends on successful test execution + of crate given as the second argument. + + testCrateFlags: list of flags to pass to the test exectuable + testInputs: list of packages that should be available during test execution + */ + crateWithTest = { crate, testCrate, testCrateFlags, testInputs, testPreRun, testPostRun }: + assert builtins.typeOf testCrateFlags == "list"; + assert builtins.typeOf testInputs == "list"; + assert builtins.typeOf testPreRun == "string"; + assert builtins.typeOf testPostRun == "string"; + let + # override the `crate` so that it will build and execute tests instead of + # building the actual lib and bin targets We just have to pass `--test` + # to rustc and it will do the right thing. We execute the tests and copy + # their log and the test executables to $out for later inspection. + test = + let + drv = testCrate.override + ( + _: { + buildTests = true; + release = false; + } + ); + # If the user hasn't set any pre/post commands, we don't want to + # insert empty lines. This means that any existing users of crate2nix + # don't get a spurious rebuild unless they set these explicitly. + testCommand = pkgs.lib.concatStringsSep "\n" + (pkgs.lib.filter (s: s != "") [ + testPreRun + "$f $testCrateFlags 2>&1 | tee -a $out" + testPostRun + ]); + in + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; + + inherit (crate) src; + + inherit testCrateFlags; + + buildInputs = testInputs; + + buildPhase = '' + set -e + export RUST_BACKTRACE=1 + + # build outputs + testRoot=target/debug + mkdir -p $testRoot + + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . + + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; + in + pkgs.runCommand "${crate.name}-linked" + { + inherit (crate) outputs crateName; + passthru = (crate.passthru or { }) // { + inherit test; + }; + } + (lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) '' + echo tested by ${test} + '' + '' + ${lib.concatMapStringsSep "\n" (output: "ln -s ${crate.${output}} ${"$"}${output}") crate.outputs} + ''); + + /* A restricted overridable version of builtRustCratesWithFeatures. */ + buildRustCrateWithFeatures = + { packageId + , features ? rootFeatures + , crateOverrides ? defaultCrateOverrides + , buildRustCrateForPkgsFunc ? null + , runTests ? false + , testCrateFlags ? [ ] + , testInputs ? [ ] + # Any command to run immediatelly before a test is executed. + , testPreRun ? "" + # Any command run immediatelly after a test is executed. + , testPostRun ? "" + }: + lib.makeOverridable + ( + { features + , crateOverrides + , runTests + , testCrateFlags + , testInputs + , testPreRun + , testPostRun + }: + let + buildRustCrateForPkgsFuncOverriden = + if buildRustCrateForPkgsFunc != null + then buildRustCrateForPkgsFunc + else + ( + if crateOverrides == pkgs.defaultCrateOverrides + then buildRustCrateForPkgs + else + pkgs: (buildRustCrateForPkgs pkgs).override { + defaultCrateOverrides = crateOverrides; + } + ); + builtRustCrates = builtRustCratesWithFeatures { + inherit packageId features; + buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; + runTests = false; + }; + builtTestRustCrates = builtRustCratesWithFeatures { + inherit packageId features; + buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; + runTests = true; + }; + drv = builtRustCrates.crates.${packageId}; + testDrv = builtTestRustCrates.crates.${packageId}; + derivation = + if runTests then + crateWithTest + { + crate = drv; + testCrate = testDrv; + inherit testCrateFlags testInputs testPreRun testPostRun; + } + else drv; + in + derivation + ) + { inherit features crateOverrides runTests testCrateFlags testInputs testPreRun testPostRun; }; + + /* Returns an attr set with packageId mapped to the result of buildRustCrateForPkgsFunc + for the corresponding crate. + */ + builtRustCratesWithFeatures = + { packageId + , features + , crateConfigs ? crates + , buildRustCrateForPkgsFunc + , runTests + , makeTarget ? makeDefaultTarget + } @ args: + assert (builtins.isAttrs crateConfigs); + assert (builtins.isString packageId); + assert (builtins.isList features); + assert (builtins.isAttrs (makeTarget stdenv.hostPlatform)); + assert (builtins.isBool runTests); + let + rootPackageId = packageId; + mergedFeatures = mergePackageFeatures + ( + args // { + inherit rootPackageId; + target = makeTarget stdenv.hostPlatform // { test = runTests; }; + } + ); + # Memoize built packages so that reappearing packages are only built once. + builtByPackageIdByPkgs = mkBuiltByPackageIdByPkgs pkgs; + mkBuiltByPackageIdByPkgs = pkgs: + let + self = { + crates = lib.mapAttrs (packageId: value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs; + target = makeTarget stdenv.hostPlatform; + build = mkBuiltByPackageIdByPkgs pkgs.buildPackages; + }; + in + self; + buildByPackageIdForPkgsImpl = self: pkgs: packageId: + let + features = mergedFeatures."${packageId}" or [ ]; + crateConfig' = crateConfigs."${packageId}"; + crateConfig = + builtins.removeAttrs crateConfig' [ "resolvedDefaultFeatures" "devDependencies" ]; + devDependencies = + lib.optionals + (runTests && packageId == rootPackageId) + (crateConfig'.devDependencies or [ ]); + dependencies = + dependencyDerivations { + inherit features; + inherit (self) target; + buildByPackageId = depPackageId: + # proc_macro crates must be compiled for the build architecture + if crateConfigs.${depPackageId}.procMacro or false + then self.build.crates.${depPackageId} + else self.crates.${depPackageId}; + dependencies = + (crateConfig.dependencies or [ ]) + ++ devDependencies; + }; + buildDependencies = + dependencyDerivations { + inherit features; + inherit (self.build) target; + buildByPackageId = depPackageId: + self.build.crates.${depPackageId}; + dependencies = crateConfig.buildDependencies or [ ]; + }; + dependenciesWithRenames = + let + buildDeps = filterEnabledDependencies { + inherit features; + inherit (self) target; + dependencies = crateConfig.dependencies or [ ] ++ devDependencies; + }; + hostDeps = filterEnabledDependencies { + inherit features; + inherit (self.build) target; + dependencies = crateConfig.buildDependencies or [ ]; + }; + in + lib.filter (d: d ? "rename") (hostDeps ++ buildDeps); + # Crate renames have the form: + # + # { + # crate_name = [ + # { version = "1.2.3"; rename = "crate_name01"; } + # ]; + # # ... + # } + crateRenames = + let + grouped = + lib.groupBy + (dependency: dependency.name) + dependenciesWithRenames; + versionAndRename = dep: + let + package = crateConfigs."${dep.packageId}"; + in + { inherit (dep) rename; inherit (package) version; }; + in + lib.mapAttrs (name: builtins.map versionAndRename) grouped; + in + buildRustCrateForPkgsFunc pkgs + ( + crateConfig // { + src = crateConfig.src or ( + pkgs.fetchurl rec { + name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz"; + # https://www.pietroalbini.org/blog/downloading-crates-io/ + # Not rate-limited, CDN URL. + url = "https://static.crates.io/crates/${crateConfig.crateName}/${crateConfig.crateName}-${crateConfig.version}.crate"; + sha256 = + assert (lib.assertMsg (crateConfig ? sha256) "Missing sha256 for ${name}"); + crateConfig.sha256; + } + ); + extraRustcOpts = lib.lists.optional (targetFeatures != [ ]) "-C target-feature=${lib.concatMapStringsSep "," (x: "+${x}") targetFeatures}"; + inherit features dependencies buildDependencies crateRenames release; + } + ); + in + builtByPackageIdByPkgs; + + /* Returns the actual derivations for the given dependencies. */ + dependencyDerivations = + { buildByPackageId + , features + , dependencies + , target + }: + assert (builtins.isList features); + assert (builtins.isList dependencies); + assert (builtins.isAttrs target); + let + enabledDependencies = filterEnabledDependencies { + inherit dependencies features target; + }; + depDerivation = dependency: buildByPackageId dependency.packageId; + in + map depDerivation enabledDependencies; + + /* Returns a sanitized version of val with all values substituted that cannot + be serialized as JSON. + */ + sanitizeForJson = val: + if builtins.isAttrs val + then lib.mapAttrs (n: sanitizeForJson) val + else if builtins.isList val + then builtins.map sanitizeForJson val + else if builtins.isFunction val + then "function" + else val; + + /* Returns various tools to debug a crate. */ + debugCrate = { packageId, target ? makeDefaultTarget stdenv.hostPlatform }: + assert (builtins.isString packageId); + let + debug = rec { + # The built tree as passed to buildRustCrate. + buildTree = buildRustCrateWithFeatures { + buildRustCrateForPkgsFunc = _: lib.id; + inherit packageId; + }; + sanitizedBuildTree = sanitizeForJson buildTree; + dependencyTree = sanitizeForJson + ( + buildRustCrateWithFeatures { + buildRustCrateForPkgsFunc = _: crate: { + "01_crateName" = crate.crateName or false; + "02_features" = crate.features or [ ]; + "03_dependencies" = crate.dependencies or [ ]; + }; + inherit packageId; + } + ); + mergedPackageFeatures = mergePackageFeatures { + features = rootFeatures; + inherit packageId target; + }; + diffedDefaultPackageFeatures = diffDefaultPackageFeatures { + inherit packageId target; + }; + }; + in + { internal = debug; }; + + /* Returns differences between cargo default features and crate2nix default + features. + + This is useful for verifying the feature resolution in crate2nix. + */ + diffDefaultPackageFeatures = + { crateConfigs ? crates + , packageId + , target + }: + assert (builtins.isAttrs crateConfigs); + let + prefixValues = prefix: lib.mapAttrs (n: v: { "${prefix}" = v; }); + mergedFeatures = + prefixValues + "crate2nix" + (mergePackageFeatures { inherit crateConfigs packageId target; features = [ "default" ]; }); + configs = prefixValues "cargo" crateConfigs; + combined = lib.foldAttrs (a: b: a // b) { } [ mergedFeatures configs ]; + onlyInCargo = + builtins.attrNames + (lib.filterAttrs (n: v: !(v ? "crate2nix") && (v ? "cargo")) combined); + onlyInCrate2Nix = + builtins.attrNames + (lib.filterAttrs (n: v: (v ? "crate2nix") && !(v ? "cargo")) combined); + differentFeatures = lib.filterAttrs + ( + n: v: + (v ? "crate2nix") + && (v ? "cargo") + && (v.crate2nix.features or [ ]) != (v."cargo".resolved_default_features or [ ]) + ) + combined; + in + builtins.toJSON { + inherit onlyInCargo onlyInCrate2Nix differentFeatures; + }; + + /* Returns an attrset mapping packageId to the list of enabled features. + + If multiple paths to a dependency enable different features, the + corresponding feature sets are merged. Features in rust are additive. + */ + mergePackageFeatures = + { crateConfigs ? crates + , packageId + , rootPackageId ? packageId + , features ? rootFeatures + , dependencyPath ? [ crates.${packageId}.crateName ] + , featuresByPackageId ? { } + , target + # Adds devDependencies to the crate with rootPackageId. + , runTests ? false + , ... + } @ args: + assert (builtins.isAttrs crateConfigs); + assert (builtins.isString packageId); + assert (builtins.isString rootPackageId); + assert (builtins.isList features); + assert (builtins.isList dependencyPath); + assert (builtins.isAttrs featuresByPackageId); + assert (builtins.isAttrs target); + assert (builtins.isBool runTests); + let + crateConfig = crateConfigs."${packageId}" or (builtins.throw "Package not found: ${packageId}"); + expandedFeatures = expandFeatures (crateConfig.features or { }) features; + enabledFeatures = enableFeatures (crateConfig.dependencies or [ ]) expandedFeatures; + depWithResolvedFeatures = dependency: + let + inherit (dependency) packageId; + features = dependencyFeatures enabledFeatures dependency; + in + { inherit packageId features; }; + resolveDependencies = cache: path: dependencies: + assert (builtins.isAttrs cache); + assert (builtins.isList dependencies); + let + enabledDependencies = filterEnabledDependencies { + inherit dependencies target; + features = enabledFeatures; + }; + directDependencies = map depWithResolvedFeatures enabledDependencies; + foldOverCache = op: lib.foldl op cache directDependencies; + in + foldOverCache + ( + cache: { packageId, features }: + let + cacheFeatures = cache.${packageId} or [ ]; + combinedFeatures = sortedUnique (cacheFeatures ++ features); + in + if cache ? ${packageId} && cache.${packageId} == combinedFeatures + then cache + else + mergePackageFeatures { + features = combinedFeatures; + featuresByPackageId = cache; + inherit crateConfigs packageId target runTests rootPackageId; + } + ); + cacheWithSelf = + let + cacheFeatures = featuresByPackageId.${packageId} or [ ]; + combinedFeatures = sortedUnique (cacheFeatures ++ enabledFeatures); + in + featuresByPackageId // { + "${packageId}" = combinedFeatures; + }; + cacheWithDependencies = + resolveDependencies cacheWithSelf "dep" + ( + crateConfig.dependencies or [ ] + ++ lib.optionals + (runTests && packageId == rootPackageId) + (crateConfig.devDependencies or [ ]) + ); + cacheWithAll = + resolveDependencies + cacheWithDependencies "build" + (crateConfig.buildDependencies or [ ]); + in + cacheWithAll; + + /* Returns the enabled dependencies given the enabled features. */ + filterEnabledDependencies = { dependencies, features, target }: + assert (builtins.isList dependencies); + assert (builtins.isList features); + assert (builtins.isAttrs target); + + lib.filter + ( + dep: + let + targetFunc = dep.target or (features: true); + in + targetFunc { inherit features target; } + && ( + !(dep.optional or false) + || builtins.any (doesFeatureEnableDependency dep) features + ) + ) + dependencies; + + /* Returns whether the given feature should enable the given dependency. */ + doesFeatureEnableDependency = dependency: feature: + let + name = dependency.rename or dependency.name; + prefix = "${name}/"; + len = builtins.stringLength prefix; + startsWithPrefix = builtins.substring 0 len feature == prefix; + in + feature == name || feature == "dep:" + name || startsWithPrefix; + + /* Returns the expanded features for the given inputFeatures by applying the + rules in featureMap. + + featureMap is an attribute set which maps feature names to lists of further + feature names to enable in case this feature is selected. + */ + expandFeatures = featureMap: inputFeatures: + assert (builtins.isAttrs featureMap); + assert (builtins.isList inputFeatures); + let + expandFeaturesNoCycle = oldSeen: inputFeatures: + if inputFeatures != [ ] + then + let + # The feature we're currently expanding. + feature = builtins.head inputFeatures; + # All the features we've seen/expanded so far, including the one + # we're currently processing. + seen = oldSeen // { ${feature} = 1; }; + # Expand the feature but be careful to not re-introduce a feature + # that we've already seen: this can easily cause a cycle, see issue + # #209. + enables = builtins.filter (f: !(seen ? "${f}")) (featureMap."${feature}" or [ ]); + in + [ feature ] ++ (expandFeaturesNoCycle seen (builtins.tail inputFeatures ++ enables)) + # No more features left, nothing to expand to. + else [ ]; + outFeatures = expandFeaturesNoCycle { } inputFeatures; + in + sortedUnique outFeatures; + + /* This function adds optional dependencies as features if they are enabled + indirectly by dependency features. This function mimics Cargo's behavior + described in a note at: + https://doc.rust-lang.org/nightly/cargo/reference/features.html#dependency-features + */ + enableFeatures = dependencies: features: + assert (builtins.isList features); + assert (builtins.isList dependencies); + let + additionalFeatures = lib.concatMap + ( + dependency: + assert (builtins.isAttrs dependency); + let + enabled = builtins.any (doesFeatureEnableDependency dependency) features; + in + if (dependency.optional or false) && enabled + then [ (dependency.rename or dependency.name) ] + else [ ] + ) + dependencies; + in + sortedUnique (features ++ additionalFeatures); + + /* + Returns the actual features for the given dependency. + + features: The features of the crate that refers this dependency. + */ + dependencyFeatures = features: dependency: + assert (builtins.isList features); + assert (builtins.isAttrs dependency); + let + defaultOrNil = + if dependency.usesDefaultFeatures or true + then [ "default" ] + else [ ]; + explicitFeatures = dependency.features or [ ]; + additionalDependencyFeatures = + let + name = dependency.rename or dependency.name; + stripPrefixMatch = prefix: s: + if lib.hasPrefix prefix s + then lib.removePrefix prefix s + else null; + extractFeature = feature: lib.findFirst + (f: f != null) + null + (map (prefix: stripPrefixMatch prefix feature) [ + (name + "/") + (name + "?/") + ]); + dependencyFeatures = lib.filter (f: f != null) (map extractFeature features); + in + dependencyFeatures; + in + defaultOrNil ++ explicitFeatures ++ additionalDependencyFeatures; + + /* Sorts and removes duplicates from a list of strings. */ + sortedUnique = features: + assert (builtins.isList features); + assert (builtins.all builtins.isString features); + let + outFeaturesSet = lib.foldl (set: feature: set // { "${feature}" = 1; }) { } features; + outFeaturesUnique = builtins.attrNames outFeaturesSet; + in + builtins.sort (a: b: a < b) outFeaturesUnique; + + deprecationWarning = message: value: + if strictDeprecation + then builtins.throw "strictDeprecation enabled, aborting: ${message}" + else builtins.trace message value; + + # + # crate2nix/default.nix (excerpt end) + # + }; +} + diff --git a/users/kranzes/wasm-hello-world/Cargo.toml b/users/kranzes/wasm-hello-world/Cargo.toml new file mode 100644 index 000000000000..e08caa7ecf24 --- /dev/null +++ b/users/kranzes/wasm-hello-world/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "wasm_hello_world" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +wasm-bindgen = "0.2.92" diff --git a/users/kranzes/wasm-hello-world/default.nix b/users/kranzes/wasm-hello-world/default.nix new file mode 100644 index 000000000000..0970f955deff --- /dev/null +++ b/users/kranzes/wasm-hello-world/default.nix @@ -0,0 +1,15 @@ +{ pkgs, lib, ... }: + +(pkgs.pkgsCross.wasm32-unknown-none.callPackage ./Cargo.nix { }).rootCrate.build.overrideAttrs (oldAttrs: { + installPhase = '' + ${lib.getExe pkgs.wasm-bindgen-cli} \ + --target web \ + --out-dir $out \ + --out-name ${oldAttrs.crateName} \ + --no-typescript \ + target/lib/${oldAttrs.crateName}-${oldAttrs.metadata}.wasm + + mv src/*.html $out + ''; +}) + diff --git a/users/kranzes/wasm-hello-world/src/index.html b/users/kranzes/wasm-hello-world/src/index.html new file mode 100644 index 000000000000..d6366c8ee8b1 --- /dev/null +++ b/users/kranzes/wasm-hello-world/src/index.html @@ -0,0 +1,19 @@ +<html> + <head> + <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/> + </head> + <body> + <script type="module"> + import init, { hello_world } from './wasm_hello_world.js'; + + async function run() { + await init(); + + hello_world(); + } + + run(); + </script> + </body> +</html> + diff --git a/users/kranzes/wasm-hello-world/src/lib.rs b/users/kranzes/wasm-hello-world/src/lib.rs new file mode 100644 index 000000000000..c184214822e7 --- /dev/null +++ b/users/kranzes/wasm-hello-world/src/lib.rs @@ -0,0 +1,11 @@ +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +extern "C" { + fn alert(s: &str); +} + +#[wasm_bindgen] +pub fn hello_world() { + alert("Hello World!"); +} diff --git a/users/picnoir/tvix-daemon/Cargo.lock b/users/picnoir/tvix-daemon/Cargo.lock index 683203f5ca1e..8756e8a753da 100644 --- a/users/picnoir/tvix-daemon/Cargo.lock +++ b/users/picnoir/tvix-daemon/Cargo.lock @@ -4,72 +4,73 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -78,9 +79,9 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", @@ -89,9 +90,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -100,15 +101,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", @@ -130,7 +131,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "tokio", "tower", "tower-layer", @@ -140,9 +141,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", @@ -153,7 +154,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", "tracing", @@ -161,17 +162,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] @@ -188,9 +189,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -203,9 +204,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "regex-automata", @@ -214,15 +215,18 @@ dependencies = [ [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.0.90" +version = "1.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "58e804ac3194a48bb129643eb1d62fcc20d18c6b8c181704489353d13120bcd1" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -232,9 +236,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.3" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -242,9 +246,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -254,9 +258,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.3" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", @@ -266,15 +270,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "const-oid" @@ -284,9 +288,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -303,16 +307,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -331,15 +334,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", @@ -357,9 +360,9 @@ dependencies = [ [[package]] name = "document-features" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" dependencies = [ "litrs", ] @@ -400,16 +403,10 @@ dependencies = [ ] [[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] name = "fiat-crypto" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "fnv" @@ -428,24 +425,24 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -454,21 +451,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-macro", @@ -490,9 +487,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -501,9 +498,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -512,31 +509,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] -name = "h2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" - -[[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -561,9 +533,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", @@ -571,12 +543,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http", "http-body", "pin-project-lite", @@ -584,9 +556,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -596,14 +568,13 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2", "http", "http-body", "httparse", @@ -616,9 +587,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", "futures-util", @@ -626,37 +597,43 @@ dependencies = [ "http-body", "hyper", "pin-project-lite", - "socket2", "tokio", + "tower-service", ] [[package]] -name = "indexmap" -version = "2.2.5" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" -dependencies = [ - "equivalent", - "hashbrown", -] +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" + +[[package]] +name = "libmimalloc-sys" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] [[package]] name = "litrs" @@ -666,9 +643,9 @@ checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -676,9 +653,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "matchit" @@ -688,9 +665,18 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mimalloc" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +dependencies = [ + "libmimalloc-sys", +] [[package]] name = "mime" @@ -706,22 +692,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -739,13 +726,16 @@ dependencies = [ name = "nix-compat" version = "0.1.0" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "bstr", + "bytes", "data-encoding", "ed25519", "ed25519-dalek", "enum-primitive-derive", "glob", + "mimalloc", + "nix-compat-derive", "nom", "num-traits", "pin-project-lite", @@ -754,6 +744,16 @@ dependencies = [ "sha2", "thiserror", "tokio", + "tracing", +] + +[[package]] +name = "nix-compat-derive" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -778,37 +778,27 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] name = "object" -version = "0.32.2" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "overload" @@ -818,9 +808,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -828,15 +818,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets", ] [[package]] @@ -847,18 +837,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", @@ -867,9 +857,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -888,25 +878,19 @@ dependencies = [ ] [[package]] -name = "platforms" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" - -[[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -922,45 +906,45 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scopeguard" @@ -970,24 +954,24 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -996,11 +980,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -1048,10 +1033,16 @@ dependencies = [ ] [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -1076,18 +1067,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -1102,21 +1093,21 @@ dependencies = [ [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.52" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -1130,19 +1121,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + +[[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -1161,21 +1158,20 @@ dependencies = [ [[package]] name = "tokio" -version = "1.36.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1198,9 +1194,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", @@ -1209,9 +1205,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -1233,28 +1229,27 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "tower" -version = "0.4.13" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper 0.1.2", "tokio", "tower-layer", "tower-service", @@ -1263,15 +1258,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -1352,15 +1347,15 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" @@ -1370,9 +1365,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -1404,138 +1399,79 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] -name = "windows_i686_gnu" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/users/picnoir/tvix-daemon/Cargo.nix b/users/picnoir/tvix-daemon/Cargo.nix index 2382027f9b13..0a2a18c9c843 100644 --- a/users/picnoir/tvix-daemon/Cargo.nix +++ b/users/picnoir/tvix-daemon/Cargo.nix @@ -1,4 +1,4 @@ -# This file was @generated by crate2nix 0.13.0 with the command: +# This file was @generated by crate2nix 0.14.1 with the command: # "generate" "--all-features" # See https://github.com/kolloch/crate2nix for more info. @@ -13,6 +13,8 @@ , rootFeatures ? [ "default" ] # If true, throw errors instead of issueing deprecation warnings. , strictDeprecation ? false + # Elements to add to the `-C target-feature=` argument passed to `rustc` + # (separated by `,`, prefixed with `+`). # Used for conditional compilation based on CPU feature detection. , targetFeatures ? [ ] # Whether to perform release builds: longer compile times, faster binaries. @@ -83,9 +85,10 @@ rec { crates = { "addr2line" = rec { crateName = "addr2line"; - version = "0.21.0"; + version = "0.24.2"; edition = "2018"; - sha256 = "1jx0k3iwyqr8klqbzk6kjvr496yd94aspis10vwsj5wy7gib4c4a"; + crateBin = [ ]; + sha256 = "1hd1i57zxgz08j6h5qrhsnm2fi0bcqvsh389fw400xm3arz2ggnz"; dependencies = [ { name = "gimli"; @@ -95,28 +98,29 @@ rec { } ]; features = { + "all" = [ "bin" ]; "alloc" = [ "dep:alloc" ]; + "bin" = [ "loader" "rustc-demangle" "cpp_demangle" "fallible-iterator" "smallvec" "dep:clap" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; "cpp_demangle" = [ "dep:cpp_demangle" ]; - "default" = [ "rustc-demangle" "cpp_demangle" "std-object" "fallible-iterator" "smallvec" "memmap2" ]; + "default" = [ "rustc-demangle" "cpp_demangle" "loader" "fallible-iterator" "smallvec" ]; "fallible-iterator" = [ "dep:fallible-iterator" ]; - "memmap2" = [ "dep:memmap2" ]; - "object" = [ "dep:object" ]; + "loader" = [ "std" "dep:object" "dep:memmap2" "dep:typed-arena" ]; "rustc-demangle" = [ "dep:rustc-demangle" ]; "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "gimli/rustc-dep-of-std" ]; "smallvec" = [ "dep:smallvec" ]; "std" = [ "gimli/std" ]; - "std-object" = [ "std" "object" "object/std" "object/compression" "gimli/endian-reader" ]; }; }; - "adler" = rec { - crateName = "adler"; - version = "1.0.2"; - edition = "2015"; - sha256 = "1zim79cvzd5yrkzl3nyfx0avijwgk9fqv3yrscdy1cc79ih02qpj"; + "adler2" = rec { + crateName = "adler2"; + version = "2.0.0"; + edition = "2021"; + sha256 = "09r6drylvgy8vv8k20lnbvwq8gp09h7smfn6h1rxsy15pgh629si"; authors = [ "Jonas Schievink <jonasschievink@gmail.com>" + "oyvindln <oyvindln@users.noreply.github.com>" ]; features = { "compiler_builtins" = [ "dep:compiler_builtins" ]; @@ -127,9 +131,9 @@ rec { }; "anstream" = rec { crateName = "anstream"; - version = "0.6.13"; + version = "0.6.15"; edition = "2021"; - sha256 = "1yv2idkyf9mp9xwc684v0ywqiy86lwc9gvllwdishl7y6czx0syr"; + sha256 = "09nm4qj34kiwgzczdvj14x7hgsb235g4sqsay3xsz7zqn4d5rqb4"; dependencies = [ { name = "anstyle"; @@ -155,6 +159,10 @@ rec { packageId = "colorchoice"; } { + name = "is_terminal_polyfill"; + packageId = "is_terminal_polyfill"; + } + { name = "utf8parse"; packageId = "utf8parse"; } @@ -168,9 +176,9 @@ rec { }; "anstyle" = rec { crateName = "anstyle"; - version = "1.0.6"; + version = "1.0.8"; edition = "2021"; - sha256 = "1g1ngvxrz9d6xsymxzzzg581jzyz1sn8d0jpjcwxks07cff2c0c9"; + sha256 = "1cfmkza63xpn1kkz844mgjwm9miaiz4jkyczmwxzivcsypk1vv0v"; features = { "default" = [ "std" ]; }; @@ -178,9 +186,10 @@ rec { }; "anstyle-parse" = rec { crateName = "anstyle-parse"; - version = "0.2.3"; + version = "0.2.5"; edition = "2021"; - sha256 = "134jhzrz89labrdwxxnjxqjdg06qvaflj1wkfnmyapwyldfwcnn7"; + sha256 = "1jy12rvgbldflnb2x7mcww9dcffw1mx22nyv6p3n7d62h0gdwizb"; + libName = "anstyle_parse"; dependencies = [ { name = "utf8parse"; @@ -197,13 +206,14 @@ rec { }; "anstyle-query" = rec { crateName = "anstyle-query"; - version = "1.0.2"; + version = "1.1.1"; edition = "2021"; - sha256 = "0j3na4b1nma39g4x7cwvj009awxckjf3z2vkwhldgka44hqj72g2"; + sha256 = "0aj22iy4pzk6mz745sfrm1ym14r0y892jhcrbs8nkj7nqx9gqdkd"; + libName = "anstyle_query"; dependencies = [ { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; + packageId = "windows-sys"; target = { target, features }: (target."windows" or false); features = [ "Win32_System_Console" "Win32_Foundation" ]; } @@ -212,9 +222,10 @@ rec { }; "anstyle-wincon" = rec { crateName = "anstyle-wincon"; - version = "3.0.2"; + version = "3.0.4"; edition = "2021"; - sha256 = "19v0fv400bmp4niqpzxnhg83vz12mmqv7l2l8vi80qcdxj0lpm8w"; + sha256 = "1y2pkvsrdxbcwircahb4wimans2pzmwwxad7ikdhj5lpdqdlxxsv"; + libName = "anstyle_wincon"; dependencies = [ { name = "anstyle"; @@ -222,7 +233,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; + packageId = "windows-sys"; target = { target, features }: (target."windows" or false); features = [ "Win32_System_Console" "Win32_Foundation" ]; } @@ -231,9 +242,10 @@ rec { }; "async-stream" = rec { crateName = "async-stream"; - version = "0.3.5"; - edition = "2018"; - sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + version = "0.3.6"; + edition = "2021"; + sha256 = "0xl4zqncrdmw2g6241wgr11dxdg4h7byy6bz3l6si03qyfk72nhb"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -255,10 +267,11 @@ rec { }; "async-stream-impl" = rec { crateName = "async-stream-impl"; - version = "0.3.5"; - edition = "2018"; - sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; + version = "0.3.6"; + edition = "2021"; + sha256 = "0kaplfb5axsvf1gfs2gk6c4zx6zcsns0yf3ssk7iwni7bphlvhn7"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -281,10 +294,11 @@ rec { }; "async-trait" = rec { crateName = "async-trait"; - version = "0.1.77"; + version = "0.1.83"; edition = "2021"; - sha256 = "1adf1jh2yg39rkpmqjqyr9xyd6849p0d95425i6imgbhx0syx069"; + sha256 = "1p8q8gm4fv2fdka8hwy2w3f8df7p5inixqi7rlmbnky3wmysw73j"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -300,16 +314,17 @@ rec { { name = "syn"; packageId = "syn"; - features = [ "full" "visit-mut" ]; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "proc-macro" "visit-mut" ]; } ]; }; "autocfg" = rec { crateName = "autocfg"; - version = "1.1.0"; + version = "1.4.0"; edition = "2015"; - sha256 = "1ylp3cb47ylzabimazvbz9ms6ap784zhb6syaz6c1jqpmcmq0s6l"; + sha256 = "09lz3by90d2hphbq56znag9v87gfpd9gb8nr82hll8z6x2nhprdc"; authors = [ "Josh Stone <cuviper@gmail.com>" ]; @@ -317,9 +332,9 @@ rec { }; "axum" = rec { crateName = "axum"; - version = "0.7.4"; + version = "0.7.7"; edition = "2021"; - sha256 = "17kv7v8m981cqmfbv5m538fzxhw51l9bajv06kfddi7njarb8dhj"; + sha256 = "1bkhgnj7rk1aih1c1ylqkmn72mjbgi8lql1paim35j3s613kjkjh"; dependencies = [ { name = "async-trait"; @@ -360,7 +375,7 @@ rec { name = "hyper-util"; packageId = "hyper-util"; optional = true; - features = [ "tokio" "server" "server-auto" ]; + features = [ "tokio" "server" "service" ]; } { name = "itoa"; @@ -387,6 +402,10 @@ rec { packageId = "pin-project-lite"; } { + name = "rustversion"; + packageId = "rustversion"; + } + { name = "serde"; packageId = "serde"; } @@ -408,7 +427,7 @@ rec { } { name = "sync_wrapper"; - packageId = "sync_wrapper"; + packageId = "sync_wrapper 1.0.1"; } { name = "tokio"; @@ -438,18 +457,8 @@ rec { usesDefaultFeatures = false; } ]; - buildDependencies = [ - { - name = "rustversion"; - packageId = "rustversion"; - } - ]; devDependencies = [ { - name = "rustversion"; - packageId = "rustversion"; - } - { name = "serde"; packageId = "serde"; features = [ "derive" ]; @@ -479,8 +488,8 @@ rec { "__private_docs" = [ "tower/full" "dep:tower-http" ]; "default" = [ "form" "http1" "json" "matched-path" "original-uri" "query" "tokio" "tower-log" "tracing" ]; "form" = [ "dep:serde_urlencoded" ]; - "http1" = [ "dep:hyper" "hyper?/http1" ]; - "http2" = [ "dep:hyper" "hyper?/http2" ]; + "http1" = [ "dep:hyper" "hyper?/http1" "hyper-util?/http1" ]; + "http2" = [ "dep:hyper" "hyper?/http2" "hyper-util?/http2" ]; "json" = [ "dep:serde_json" "dep:serde_path_to_error" ]; "macros" = [ "dep:axum-macros" ]; "multipart" = [ "dep:multer" ]; @@ -494,9 +503,10 @@ rec { }; "axum-core" = rec { crateName = "axum-core"; - version = "0.4.3"; + version = "0.4.5"; edition = "2021"; - sha256 = "1qx28wg4j6qdcdrisqwyaavlzc0zvbsrcwa99zf9456lfbyn6p51"; + sha256 = "16b1496c4gm387q20hkv5ic3k5bd6xmnvk50kwsy6ymr8rhvvwh9"; + libName = "axum_core"; dependencies = [ { name = "async-trait"; @@ -533,8 +543,12 @@ rec { packageId = "pin-project-lite"; } { + name = "rustversion"; + packageId = "rustversion"; + } + { name = "sync_wrapper"; - packageId = "sync_wrapper"; + packageId = "sync_wrapper 1.0.1"; } { name = "tower-layer"; @@ -551,12 +565,6 @@ rec { usesDefaultFeatures = false; } ]; - buildDependencies = [ - { - name = "rustversion"; - packageId = "rustversion"; - } - ]; devDependencies = [ { name = "futures-util"; @@ -573,9 +581,9 @@ rec { }; "backtrace" = rec { crateName = "backtrace"; - version = "0.3.69"; - edition = "2018"; - sha256 = "0dsq23dhw4pfndkx2nsa1ml2g31idm7ss7ljxp8d57avygivg290"; + version = "0.3.74"; + edition = "2021"; + sha256 = "06pfif7nwx66qf2zaanc2fcq7m64i91ki9imw9xd3bnz5hrwp0ld"; authors = [ "The Rust Project Developers" ]; @@ -607,28 +615,23 @@ rec { packageId = "object"; usesDefaultFeatures = false; target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); - features = [ "read_core" "elf" "macho" "pe" "unaligned" "archive" ]; + features = [ "read_core" "elf" "macho" "pe" "xcoff" "unaligned" "archive" ]; } { name = "rustc-demangle"; packageId = "rustc-demangle"; } - ]; - buildDependencies = [ { - name = "cc"; - packageId = "cc"; + name = "windows-targets"; + packageId = "windows-targets"; + target = { target, features }: (target."windows" or false); } ]; features = { "cpp_demangle" = [ "dep:cpp_demangle" ]; "default" = [ "std" ]; - "rustc-serialize" = [ "dep:rustc-serialize" ]; "serde" = [ "dep:serde" ]; - "serialize-rustc" = [ "rustc-serialize" ]; "serialize-serde" = [ "serde" ]; - "verify-winapi" = [ "winapi/dbghelp" "winapi/handleapi" "winapi/libloaderapi" "winapi/memoryapi" "winapi/minwindef" "winapi/processthreadsapi" "winapi/synchapi" "winapi/tlhelp32" "winapi/winbase" "winapi/winnt" ]; - "winapi" = [ "dep:winapi" ]; }; resolvedDefaultFeatures = [ "default" "std" ]; }; @@ -660,11 +663,11 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "bitflags 2.4.2" = rec { + "bitflags 2.6.0" = rec { crateName = "bitflags"; - version = "2.4.2"; + version = "2.6.0"; edition = "2021"; - sha256 = "1pqd142hyqlzr7p9djxq2ff0jx07a2sb2xp9lhw69cbf80s0jmzd"; + sha256 = "1pkidwzn3hnxlsl8zizh0bncgbjnw7c41cx7bby26ncbzmiznj5h"; authors = [ "The Rust Project Developers" ]; @@ -682,6 +685,7 @@ rec { version = "0.10.4"; edition = "2018"; sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -695,9 +699,9 @@ rec { }; "bstr" = rec { crateName = "bstr"; - version = "1.9.1"; + version = "1.10.0"; edition = "2021"; - sha256 = "01ipr5rncw3kf4dyc1p2g00njn1df2b0xpviwhb8830iv77wbvq5"; + sha256 = "036wwrchd5gq3q4k6w1j2bfl2bk2ff8c0dsa9y7w7aw7nf7knwj0"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -732,9 +736,9 @@ rec { }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.7.2"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "1wzs7l57iwqmrszdpr2mmqf1b1hgvpxafc30imxhnry0zfl9m3a2"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -747,16 +751,20 @@ rec { }; "cc" = rec { crateName = "cc"; - version = "1.0.90"; + version = "1.1.29"; edition = "2018"; - sha256 = "1xg1bqnq50dpf6g1hl90caxgz4afnf74pxa426gh7wxch9561mlc"; + sha256 = "1ldw40qx2lwk9021f64cdf6d286c5zbb2gk456qqp94l66n09s2q"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; + dependencies = [ + { + name = "shlex"; + packageId = "shlex"; + } + ]; features = { - "jobserver" = [ "dep:jobserver" ]; - "libc" = [ "dep:libc" ]; - "parallel" = [ "libc" "jobserver" ]; + "parallel" = [ "dep:libc" "dep:jobserver" ]; }; }; "cfg-if" = rec { @@ -764,6 +772,7 @@ rec { version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -775,10 +784,10 @@ rec { }; "clap" = rec { crateName = "clap"; - version = "4.5.3"; + version = "4.5.20"; edition = "2021"; crateBin = [ ]; - sha256 = "04w8fx68hzjzk45ir4b9jzwk4m7bki0k5afwns9zqgh61v82d5ll"; + sha256 = "1s37v23gcxkjy4800qgnkxkpliz68vslpr5sgn1xar56hmnkfzxr"; dependencies = [ { name = "clap_builder"; @@ -806,6 +815,7 @@ rec { "suggestions" = [ "clap_builder/suggestions" ]; "unicode" = [ "clap_builder/unicode" ]; "unstable-doc" = [ "clap_builder/unstable-doc" "derive" ]; + "unstable-ext" = [ "clap_builder/unstable-ext" ]; "unstable-styles" = [ "clap_builder/unstable-styles" ]; "unstable-v5" = [ "clap_builder/unstable-v5" "clap_derive?/unstable-v5" "deprecated" ]; "usage" = [ "clap_builder/usage" ]; @@ -815,9 +825,9 @@ rec { }; "clap_builder" = rec { crateName = "clap_builder"; - version = "4.5.2"; + version = "4.5.20"; edition = "2021"; - sha256 = "1d7p4hph4fyhaphkf0v5zv0kq4lz25a9jq2f901yrq3afqp9w4mf"; + sha256 = "0m6w10l2f65h3ch0d53lql6p26xxrh20ffipra9ysjsfsjmq1g0r"; dependencies = [ { name = "anstream"; @@ -845,7 +855,7 @@ rec { "std" = [ "anstyle/std" ]; "suggestions" = [ "dep:strsim" "error-context" ]; "unicode" = [ "dep:unicode-width" "dep:unicase" ]; - "unstable-doc" = [ "cargo" "wrap_help" "env" "unicode" "string" ]; + "unstable-doc" = [ "cargo" "wrap_help" "env" "unicode" "string" "unstable-ext" ]; "unstable-styles" = [ "color" ]; "unstable-v5" = [ "deprecated" ]; "wrap_help" = [ "help" "dep:terminal_size" ]; @@ -854,9 +864,9 @@ rec { }; "clap_derive" = rec { crateName = "clap_derive"; - version = "4.5.3"; + version = "4.5.18"; edition = "2021"; - sha256 = "0byp6k5kyvi9jcbnjjbyw7ak7avn87f2s4ya154f3xc01h29l8wh"; + sha256 = "1ardb26bvcpg72q9myr7yir3a8c83gx7vxk1cccabsd9n73s1ija"; procMacro = true; dependencies = [ { @@ -885,16 +895,16 @@ rec { }; "clap_lex" = rec { crateName = "clap_lex"; - version = "0.7.0"; + version = "0.7.2"; edition = "2021"; - sha256 = "1kh1sckgq71kay2rrr149pl9gbsrvyccsq6xm5xpnq0cxnyqzk4q"; + sha256 = "15zcrc2fa6ycdzaihxghf48180bnvzsivhf0fmah24bnnaf76qhl"; }; "colorchoice" = rec { crateName = "colorchoice"; - version = "1.0.0"; + version = "1.0.2"; edition = "2021"; - sha256 = "1ix7w85kwvyybwi2jdkl3yva2r2bvdcc3ka2grjfzfgrapqimgxc"; + sha256 = "1h18ph538y8yjmbpaf8li98l0ifms2xmh3rax9666c5qfjfi3zfk"; }; "const-oid" = rec { @@ -902,6 +912,7 @@ rec { version = "0.9.6"; edition = "2021"; sha256 = "1y0jnqaq7p2wvspnx7qj76m7hjcqpz73qzvr9l2p9n2s51vr6if2"; + libName = "const_oid"; authors = [ "RustCrypto Developers" ]; @@ -911,9 +922,9 @@ rec { }; "cpufeatures" = rec { crateName = "cpufeatures"; - version = "0.2.12"; + version = "0.2.14"; edition = "2018"; - sha256 = "012m7rrak4girqlii3jnqwrr73gv1i980q4wra5yyyhvzwk5xzjk"; + sha256 = "1q3qd9qkw94vs7n5i0y3zz2cqgzcxvdgyb54ryngwmjhfbgrg1k0"; authors = [ "RustCrypto Developers" ]; @@ -921,7 +932,7 @@ rec { { name = "libc"; packageId = "libc"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-linux-android"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-linux-android"); } { name = "libc"; @@ -946,6 +957,7 @@ rec { version = "0.1.6"; edition = "2018"; sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; authors = [ "RustCrypto Developers" ]; @@ -968,9 +980,10 @@ rec { }; "curve25519-dalek" = rec { crateName = "curve25519-dalek"; - version = "4.1.2"; + version = "4.1.3"; edition = "2021"; - sha256 = "0j7kqchcgycs4a11gvlda93h9w2jr05nn4hjpfyh2kn94a4pnrqa"; + sha256 = "1gmjb9dsknrr8lypmhkyjd67p1arb8mbfamlwxm7vph38my8pywp"; + libName = "curve25519_dalek"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -1016,10 +1029,6 @@ rec { ]; buildDependencies = [ { - name = "platforms"; - packageId = "platforms"; - } - { name = "rustc_version"; packageId = "rustc_version"; } @@ -1043,6 +1052,7 @@ rec { edition = "2021"; sha256 = "1cry71xxrr0mcy5my3fb502cwfxy6822k4pm19cwrilrg7hq4s7l"; procMacro = true; + libName = "curve25519_dalek_derive"; dependencies = [ { name = "proc-macro2"; @@ -1062,9 +1072,10 @@ rec { }; "data-encoding" = rec { crateName = "data-encoding"; - version = "2.5.0"; + version = "2.6.0"; edition = "2018"; - sha256 = "1rcbnwfmfxhlshzbn3r7srm3azqha3mn33yxyqxkzz2wpqcjm5ky"; + sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -1076,9 +1087,9 @@ rec { }; "der" = rec { crateName = "der"; - version = "0.7.8"; + version = "0.7.9"; edition = "2021"; - sha256 = "070bwiyr80800h31c5zd96ckkgagfjgnrrdmz3dzg2lccsd3dypz"; + sha256 = "1h4vzjfa1lczxdf8avfj9qlwh1qianqlxdy1g5rn762qnvkzhnzm"; authors = [ "RustCrypto Developers" ]; @@ -1145,13 +1156,14 @@ rec { }; "document-features" = rec { crateName = "document-features"; - version = "0.2.8"; + version = "0.2.10"; edition = "2018"; - sha256 = "15cvgxqngxslgllz15m8aban6wqfgsi6nlhr0g25yfsnd6nq4lpg"; + sha256 = "182h528pjyv4ppil2pd2nir46qrb393x5kvm4y51yhnjmgm6jsfb"; procMacro = true; + libName = "document_features"; libPath = "lib.rs"; authors = [ - "Slint Developers <info@slint-ui.com>" + "Slint Developers <info@slint.dev>" ]; dependencies = [ { @@ -1200,6 +1212,7 @@ rec { version = "2.1.1"; edition = "2021"; sha256 = "0w88cafwglg9hjizldbmlza0ns3hls81zk1bcih3m5m3h67algaa"; + libName = "ed25519_dalek"; authors = [ "isis lovecruft <isis@patternsinthevoid.net>" "Tony Arcieri <bascule@gmail.com>" @@ -1278,6 +1291,7 @@ rec { edition = "2018"; sha256 = "0k6wcf58h5kh64yq5nfq71va53kaya0kzxwsjwbgwm2n2zd9axxs"; procMacro = true; + libName = "enum_primitive_derive"; authors = [ "Doug Goldstein <cardoe@cardoe.com>" ]; @@ -1298,18 +1312,12 @@ rec { ]; }; - "equivalent" = rec { - crateName = "equivalent"; - version = "1.0.1"; - edition = "2015"; - sha256 = "1malmx5f4lkfvqasz319lq6gb3ddg19yzf9s8cykfsgzdmyq0hsl"; - - }; "fiat-crypto" = rec { crateName = "fiat-crypto"; - version = "0.2.6"; + version = "0.2.9"; edition = "2018"; - sha256 = "10hkkkjynhibvchznkxx81gwxqarn9i5sgz40d6xxb8xzhsz8xhn"; + sha256 = "07c1vknddv3ak7w89n85ik0g34nzzpms6yb845vrjnv9m4csbpi8"; + libName = "fiat_crypto"; authors = [ "Fiat Crypto library authors <jgross@mit.edu>" ]; @@ -1355,9 +1363,10 @@ rec { }; "futures-channel" = rec { crateName = "futures-channel"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "0y6b7xxqdjm9hlcjpakcg41qfl7lihf6gavk8fyqijsxhvbzgj7a"; + sha256 = "040vpqpqlbk099razq8lyn74m0f161zd0rp36hciqrwcg2zibzrd"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -1376,9 +1385,10 @@ rec { }; "futures-core" = rec { crateName = "futures-core"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "07aslayrn3lbggj54kci0ishmd1pr367fp7iks7adia1p05miinz"; + sha256 = "0gk6yrxgi5ihfanm2y431jadrll00n5ifhnpx090c2f2q1cr1wh5"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -1388,10 +1398,11 @@ rec { }; "futures-macro" = rec { crateName = "futures-macro"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1b49qh9d402y8nka4q6wvvj0c88qq91wbr192mdn5h54nzs0qxc7"; + sha256 = "0l1n7kqzwwmgiznn0ywdc5i24z72zvh9q1dwps54mimppi7f6bhn"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -1411,9 +1422,10 @@ rec { }; "futures-sink" = rec { crateName = "futures-sink"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "1dag8xyyaya8n8mh8smx7x6w2dpmafg2din145v973a3hw7f1f4z"; + sha256 = "1xyly6naq6aqm52d5rh236snm08kw8zadydwqz8bip70s6vzlxg5"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1422,9 +1434,10 @@ rec { }; "futures-task" = rec { crateName = "futures-task"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "013h1724454hj8qczp8vvs10qfiqrxr937qsrv6rhii68ahlzn1q"; + sha256 = "124rv4n90f5xwfsm9qw6y99755y021cmi5dhzh253s920z77s3zr"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1433,9 +1446,10 @@ rec { }; "futures-util" = rec { crateName = "futures-util"; - version = "0.3.30"; + version = "0.3.31"; edition = "2018"; - sha256 = "0j0xqhcir1zf2dcbpd421kgw6wvsk0rpxflylcysn1rlp3g02r1x"; + sha256 = "10aa1ar8bgkgbr4wzxlidkqkcxf77gffyj8j7768h831pcaq784z"; + libName = "futures_util"; dependencies = [ { name = "futures-core"; @@ -1521,9 +1535,9 @@ rec { }; "getrandom" = rec { crateName = "getrandom"; - version = "0.2.12"; + version = "0.2.15"; edition = "2018"; - sha256 = "1d8jb9bv38nkwlqqdjcav6gxckgwc9g30pm3qq506rvncpm9400r"; + sha256 = "1mzlnrb3dgyd1fb84gvw10pyr8wdqdl4ry4sr64i1s8an66pqmn4"; authors = [ "The Rand Project Developers" ]; @@ -1557,9 +1571,9 @@ rec { }; "gimli" = rec { crateName = "gimli"; - version = "0.28.1"; + version = "0.31.1"; edition = "2018"; - sha256 = "0lv23wc8rxvmjia3mcxc6hj9vkqnv1bqq0h8nzjcgf71mrxx6wa2"; + sha256 = "0gvqc0ramx8szv76jhfd4dms0zyamvlg4whhiz11j34hh3dqxqh7"; features = { "default" = [ "read-all" "write" ]; "endian-reader" = [ "read" "dep:stable_deref_trait" ]; @@ -1582,102 +1596,6 @@ rec { ]; }; - "h2" = rec { - crateName = "h2"; - version = "0.4.2"; - edition = "2018"; - sha256 = "0hqr2l7kl9zqjcjdv69v9jx6v65mlbsavsyff8mr6lgqkbjk1l1i"; - authors = [ - "Carl Lerche <me@carllerche.com>" - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "fnv"; - packageId = "fnv"; - } - { - name = "futures-core"; - packageId = "futures-core"; - usesDefaultFeatures = false; - } - { - name = "futures-sink"; - packageId = "futures-sink"; - usesDefaultFeatures = false; - } - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - } - { - name = "http"; - packageId = "http"; - } - { - name = "indexmap"; - packageId = "indexmap"; - features = [ "std" ]; - } - { - name = "slab"; - packageId = "slab"; - } - { - name = "tokio"; - packageId = "tokio"; - features = [ "io-util" ]; - } - { - name = "tokio-util"; - packageId = "tokio-util"; - features = [ "codec" "io" ]; - } - { - name = "tracing"; - packageId = "tracing"; - usesDefaultFeatures = false; - features = [ "std" ]; - } - ]; - devDependencies = [ - { - name = "tokio"; - packageId = "tokio"; - features = [ "rt-multi-thread" "macros" "sync" "net" ]; - } - ]; - features = { }; - }; - "hashbrown" = rec { - crateName = "hashbrown"; - version = "0.14.3"; - edition = "2021"; - sha256 = "012nywlg0lj9kwanh69my5x67vjlfmzfi9a0rq4qvis2j8fil3r9"; - authors = [ - "Amanieu d'Antras <amanieu@gmail.com>" - ]; - features = { - "ahash" = [ "dep:ahash" ]; - "alloc" = [ "dep:alloc" ]; - "allocator-api2" = [ "dep:allocator-api2" ]; - "compiler_builtins" = [ "dep:compiler_builtins" ]; - "core" = [ "dep:core" ]; - "default" = [ "ahash" "inline-more" "allocator-api2" ]; - "equivalent" = [ "dep:equivalent" ]; - "nightly" = [ "allocator-api2?/nightly" "bumpalo/allocator_api" ]; - "rayon" = [ "dep:rayon" ]; - "rkyv" = [ "dep:rkyv" ]; - "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" ]; - "serde" = [ "dep:serde" ]; - }; - resolvedDefaultFeatures = [ "raw" ]; - }; "heck" = rec { crateName = "heck"; version = "0.5.0"; @@ -1690,6 +1608,7 @@ rec { version = "0.3.9"; edition = "2021"; sha256 = "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -1732,9 +1651,10 @@ rec { }; "http-body" = rec { crateName = "http-body"; - version = "1.0.0"; + version = "1.0.1"; edition = "2018"; - sha256 = "0hyn8n3iadrbwq8y0p1rl1275s4nm49bllw5wji29g4aa3dqbb0w"; + sha256 = "111ir5k2b9ihz5nr9cz7cwm7fnydca7dx4hc7vr16scfzghxrzhy"; + libName = "http_body"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -1754,9 +1674,10 @@ rec { }; "http-body-util" = rec { crateName = "http-body-util"; - version = "0.1.1"; + version = "0.1.2"; edition = "2018"; - sha256 = "07agldas2qgcfc05ckiarlmf9vzragbda823nqhrqrc6mjrghx84"; + sha256 = "0kslwazg4400qnc2azkrgqqci0fppv12waicnsy5d8hncvbjjd3r"; + libName = "http_body_util"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -1768,8 +1689,9 @@ rec { packageId = "bytes"; } { - name = "futures-core"; - packageId = "futures-core"; + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; } { name = "http"; @@ -1788,9 +1710,9 @@ rec { }; "httparse" = rec { crateName = "httparse"; - version = "1.8.0"; + version = "1.9.5"; edition = "2018"; - sha256 = "010rrfahm1jss3p022fqf3j3jmm72vhn4iqhykahb9ynpaag75yq"; + sha256 = "0ip9v8m9lvgvq1lznl31wvn0ch1v254na7lhid9p29yx9rbx6wbx"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -1811,9 +1733,9 @@ rec { }; "hyper" = rec { crateName = "hyper"; - version = "1.2.0"; + version = "1.4.1"; edition = "2021"; - sha256 = "0fi6k7hz5fmdph0a5r8hw50d7h2n9zxkizmafcmb65f67bblhr8q"; + sha256 = "01ds8i3q6hw5kw56mavy544m11gkr87zi999siigdl3n1qpd5psh"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -1834,11 +1756,6 @@ rec { usesDefaultFeatures = false; } { - name = "h2"; - packageId = "h2"; - optional = true; - } - { name = "http"; packageId = "http"; } @@ -1888,7 +1805,7 @@ rec { name = "futures-util"; packageId = "futures-util"; usesDefaultFeatures = false; - features = [ "sink" ]; + features = [ "alloc" "sink" ]; } { name = "tokio"; @@ -1898,20 +1815,21 @@ rec { ]; features = { "client" = [ "dep:want" "dep:pin-project-lite" "dep:smallvec" ]; - "ffi" = [ "dep:libc" "dep:http-body-util" ]; + "ffi" = [ "dep:libc" "dep:http-body-util" "futures-util?/alloc" ]; "full" = [ "client" "http1" "http2" "server" ]; "http1" = [ "dep:futures-channel" "dep:futures-util" "dep:httparse" "dep:itoa" ]; "http2" = [ "dep:futures-channel" "dep:futures-util" "dep:h2" ]; "server" = [ "dep:httpdate" "dep:pin-project-lite" "dep:smallvec" ]; "tracing" = [ "dep:tracing" ]; }; - resolvedDefaultFeatures = [ "default" "http1" "http2" "server" ]; + resolvedDefaultFeatures = [ "default" "http1" "server" ]; }; "hyper-util" = rec { crateName = "hyper-util"; - version = "0.1.3"; + version = "0.1.9"; edition = "2021"; - sha256 = "1akngan7j0n2n0wd25c6952mvqbkj9gp1lcwzyxjc0d37l8yyf6a"; + sha256 = "12yhradh0bpwa9jjyyq6shrrcx9fxbdkrq06xj7ccfhqkyq6waa1"; + libName = "hyper_util"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -1942,16 +1860,15 @@ rec { packageId = "pin-project-lite"; } { - name = "socket2"; - packageId = "socket2"; + name = "tokio"; + packageId = "tokio"; optional = true; - features = [ "all" ]; + usesDefaultFeatures = false; } { - name = "tokio"; - packageId = "tokio"; + name = "tower-service"; + packageId = "tower-service"; optional = true; - features = [ "net" "rt" "time" ]; } ]; devDependencies = [ @@ -1967,56 +1884,36 @@ rec { { name = "tokio"; packageId = "tokio"; - features = [ "macros" "test-util" ]; + features = [ "macros" "test-util" "signal" ]; } ]; features = { - "client" = [ "hyper/client" "dep:tracing" "dep:futures-channel" "dep:tower" "dep:tower-service" ]; - "client-legacy" = [ "client" ]; - "full" = [ "client" "client-legacy" "server" "server-auto" "service" "http1" "http2" "tokio" ]; + "client" = [ "hyper/client" "dep:tracing" "dep:futures-channel" "dep:tower-service" ]; + "client-legacy" = [ "client" "dep:socket2" "tokio/sync" ]; + "full" = [ "client" "client-legacy" "server" "server-auto" "server-graceful" "service" "http1" "http2" "tokio" ]; "http1" = [ "hyper/http1" ]; "http2" = [ "hyper/http2" ]; "server" = [ "hyper/server" ]; "server-auto" = [ "server" "http1" "http2" ]; - "service" = [ "dep:tower" "dep:tower-service" ]; - "tokio" = [ "dep:tokio" "dep:socket2" ]; + "server-graceful" = [ "server" "tokio/sync" "futures-util/alloc" ]; + "service" = [ "dep:tower-service" ]; + "tokio" = [ "dep:tokio" "tokio/net" "tokio/rt" "tokio/time" ]; }; - resolvedDefaultFeatures = [ "default" "http1" "http2" "server" "server-auto" "tokio" ]; + resolvedDefaultFeatures = [ "default" "http1" "server" "service" "tokio" ]; }; - "indexmap" = rec { - crateName = "indexmap"; - version = "2.2.5"; + "is_terminal_polyfill" = rec { + crateName = "is_terminal_polyfill"; + version = "1.70.1"; edition = "2021"; - sha256 = "1x4x9zdqvlkfks3y84dsynh1p8na3nn48nn454s26rqla6fr42vv"; - dependencies = [ - { - name = "equivalent"; - packageId = "equivalent"; - usesDefaultFeatures = false; - } - { - name = "hashbrown"; - packageId = "hashbrown"; - usesDefaultFeatures = false; - features = [ "raw" ]; - } - ]; - features = { - "arbitrary" = [ "dep:arbitrary" ]; - "borsh" = [ "dep:borsh" ]; - "default" = [ "std" ]; - "quickcheck" = [ "dep:quickcheck" ]; - "rayon" = [ "dep:rayon" ]; - "rustc-rayon" = [ "dep:rustc-rayon" ]; - "serde" = [ "dep:serde" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; + sha256 = "1kwfgglh91z33kl0w5i338mfpa3zs0hidq5j4ny4rmjwrikchhvr"; + features = { }; + resolvedDefaultFeatures = [ "default" ]; }; "itoa" = rec { crateName = "itoa"; - version = "1.0.10"; + version = "1.0.11"; edition = "2018"; - sha256 = "0k7xjfki7mnv6yzjrbnbnjllg86acmbnk4izz2jmm1hx2wd6v95i"; + sha256 = "0nv9cqjwzr3q58qz84dcz63ggc54yhf1yqar1m858m1kfd4g3wa9"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -2026,9 +1923,9 @@ rec { }; "lazy_static" = rec { crateName = "lazy_static"; - version = "1.4.0"; + version = "1.5.0"; edition = "2015"; - sha256 = "0in6ikhw8mgl33wjv6q6xfrb5b9jr16q8ygjy803fay4zcisvaz2"; + sha256 = "1zk6dqqni0193xg6iijh7i3i44sryglwgvx20spdvwk3r6sbrlmv"; authors = [ "Marvin Löbel <loebel.marvin@gmail.com>" ]; @@ -2039,9 +1936,9 @@ rec { }; "libc" = rec { crateName = "libc"; - version = "0.2.153"; + version = "0.2.159"; edition = "2015"; - sha256 = "1gg7m1ils5dms5miq9fyllrcp0jxnbpgkx71chd2i0lafa8qy6cw"; + sha256 = "1i9xpia0hn1y8dws7all8rqng6h3lc8ymlgslnljcvm376jrf7an"; authors = [ "The Rust Project Developers" ]; @@ -2053,6 +1950,33 @@ rec { }; resolvedDefaultFeatures = [ "default" "extra_traits" "std" ]; }; + "libmimalloc-sys" = rec { + crateName = "libmimalloc-sys"; + version = "0.1.39"; + edition = "2018"; + links = "mimalloc"; + sha256 = "0i3b0dzz7cp0ik7ys66q92r16va78gwlbrnxhj5fnkdxsc8niai3"; + libName = "libmimalloc_sys"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cty" = [ "dep:cty" ]; + "extended" = [ "cty" ]; + }; + }; "litrs" = rec { crateName = "litrs"; version = "0.4.1"; @@ -2070,9 +1994,9 @@ rec { }; "lock_api" = rec { crateName = "lock_api"; - version = "0.4.11"; - edition = "2018"; - sha256 = "0iggx0h4jx63xm35861106af3jkxq06fpqhpkhgw0axi2n38y5iw"; + version = "0.4.12"; + edition = "2021"; + sha256 = "05qvxa6g27yyva25a5ghsg85apdxkvr77yhkyhapj6r8vnf8pbq7"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -2098,9 +2022,9 @@ rec { }; "log" = rec { crateName = "log"; - version = "0.4.21"; + version = "0.4.22"; edition = "2021"; - sha256 = "074hldq1q8rlzq2s2qa8f25hj4s3gpw71w64vdwzjd01a4g8rvch"; + sha256 = "093vs0wkm1rgyykk7fjbqp2lwizbixac1w52gv109p5r4jh0p9x7"; authors = [ "The Rust Project Developers" ]; @@ -2132,9 +2056,9 @@ rec { }; "memchr" = rec { crateName = "memchr"; - version = "2.7.1"; + version = "2.7.4"; edition = "2021"; - sha256 = "0jf1kicqa4vs9lyzj4v4y1p90q0dh87hvhsdd5xvhnp527sw8gaj"; + sha256 = "18z32bhxrax0fnjikv475z7ii718hq457qwmaryixfxsl2qrmjkq"; authors = [ "Andrew Gallant <jamslam@gmail.com>" "bluss" @@ -2150,6 +2074,34 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; + "mimalloc" = rec { + crateName = "mimalloc"; + version = "0.1.43"; + edition = "2018"; + sha256 = "0csnyrxc16i592gm5ffham07jyj2w98qsh9jyy1rv59lmr8474b8"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + "Vincent Rouillé <vincent@speedy37.fr>" + "Thom Chiovoloni <chiovolonit@gmail.com>" + ]; + dependencies = [ + { + name = "libmimalloc-sys"; + packageId = "libmimalloc-sys"; + usesDefaultFeatures = false; + } + ]; + features = { + "debug" = [ "libmimalloc-sys/debug" ]; + "debug_in_debug" = [ "libmimalloc-sys/debug_in_debug" ]; + "extended" = [ "libmimalloc-sys/extended" ]; + "local_dynamic_tls" = [ "libmimalloc-sys/local_dynamic_tls" ]; + "no_thp" = [ "libmimalloc-sys/no_thp" ]; + "override" = [ "libmimalloc-sys/override" ]; + "secure" = [ "libmimalloc-sys/secure" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; "mime" = rec { crateName = "mime"; version = "0.3.17"; @@ -2165,6 +2117,7 @@ rec { version = "0.2.1"; edition = "2018"; sha256 = "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8"; + libName = "minimal_lexical"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2175,17 +2128,17 @@ rec { }; "miniz_oxide" = rec { crateName = "miniz_oxide"; - version = "0.7.2"; - edition = "2018"; - sha256 = "19qlxb21s6kabgqq61mk7kd1qk2invyygj076jz6i1gj2lz1z0cx"; + version = "0.8.0"; + edition = "2021"; + sha256 = "1wadxkg6a6z4lr7kskapj5d8pxlx7cp1ifw4daqnkzqjxych5n72"; authors = [ "Frommi <daniil.liferenko@gmail.com>" "oyvindln <oyvindln@users.noreply.github.com>" ]; dependencies = [ { - name = "adler"; - packageId = "adler"; + name = "adler2"; + packageId = "adler2"; usesDefaultFeatures = false; } ]; @@ -2194,16 +2147,16 @@ rec { "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; "default" = [ "with-alloc" ]; - "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler/rustc-dep-of-std" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler2/rustc-dep-of-std" ]; "simd" = [ "simd-adler32" ]; "simd-adler32" = [ "dep:simd-adler32" ]; }; }; "mio" = rec { crateName = "mio"; - version = "0.8.11"; - edition = "2018"; - sha256 = "034byyl0ardml5yliy1hmvx8arkmn9rv479pid794sm07ia519m4"; + version = "1.0.2"; + edition = "2021"; + sha256 = "1v1cnnn44awxbcfm4zlavwgkvbyg7gp5zzjm8mqf1apkrwflvq40"; authors = [ "Carl Lerche <me@carllerche.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -2211,6 +2164,12 @@ rec { ]; dependencies = [ { + name = "hermit-abi"; + packageId = "hermit-abi"; + rename = "libc"; + target = { target, features }: ("hermit" == target."os" or null); + } + { name = "libc"; packageId = "libc"; target = { target, features }: ("wasi" == target."os" or null); @@ -2227,9 +2186,9 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys"; target = { target, features }: (target."windows" or false); - features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; + features = [ "Wdk_Foundation" "Wdk_Storage_FileSystem" "Wdk_System_IO" "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; } ]; features = { @@ -2286,16 +2245,12 @@ rec { version = "0.1.0"; edition = "2021"; crateBin = [ ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat; } - else ../../../tvix/nix-compat; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat; }; + libName = "nix_compat"; dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "bstr"; @@ -2303,6 +2258,11 @@ rec { features = [ "alloc" "unicode" "serde" ]; } { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { name = "data-encoding"; packageId = "data-encoding"; } @@ -2323,6 +2283,15 @@ rec { packageId = "glob"; } { + name = "mimalloc"; + packageId = "mimalloc"; + } + { + name = "nix-compat-derive"; + packageId = "nix-compat-derive"; + optional = true; + } + { name = "nom"; packageId = "nom"; } @@ -2358,20 +2327,57 @@ rec { optional = true; features = [ "io-util" "macros" ]; } + { + name = "tracing"; + packageId = "tracing"; + } ]; devDependencies = [ { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "serde_json"; packageId = "serde_json"; } ]; features = { "async" = [ "tokio" ]; + "bytes" = [ "dep:bytes" ]; + "default" = [ "async" "wire" "nix-compat-derive" ]; + "nix-compat-derive" = [ "dep:nix-compat-derive" ]; "pin-project-lite" = [ "dep:pin-project-lite" ]; "tokio" = [ "dep:tokio" ]; - "wire" = [ "tokio" "pin-project-lite" ]; + "wire" = [ "tokio" "pin-project-lite" "bytes" ]; }; - resolvedDefaultFeatures = [ "pin-project-lite" "tokio" "wire" ]; + resolvedDefaultFeatures = [ "async" "bytes" "default" "nix-compat-derive" "pin-project-lite" "tokio" "wire" ]; + }; + "nix-compat-derive" = rec { + crateName = "nix-compat-derive"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat-derive; }; + procMacro = true; + libName = "nix_compat_derive"; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + features = [ "proc-macro" ]; + } + { + name = "quote"; + packageId = "quote"; + features = [ "proc-macro" ]; + } + { + name = "syn"; + packageId = "syn"; + features = [ "full" "extra-traits" ]; + } + ]; + }; "nom" = rec { crateName = "nom"; @@ -2404,6 +2410,7 @@ rec { version = "0.46.0"; edition = "2018"; sha256 = "115sywxh53p190lyw97alm14nc004qj5jm5lvdj608z84rbida3p"; + libName = "nu_ansi_term"; authors = [ "ogham@bsago.me" "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>" @@ -2429,9 +2436,10 @@ rec { }; "num-traits" = rec { crateName = "num-traits"; - version = "0.2.18"; - edition = "2018"; - sha256 = "0yjib8p2p9kzmaz48xwhs69w5dh1wipph9jgnillzd2x33jz03fs"; + version = "0.2.19"; + edition = "2021"; + sha256 = "0h984rhdkkqd4ny9cif7y2azl3xdfb7768hb9irhpsch4q3gq787"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -2447,33 +2455,11 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "num_cpus" = rec { - crateName = "num_cpus"; - version = "1.16.0"; - edition = "2015"; - sha256 = "0hra6ihpnh06dvfvz9ipscys0xfqa9ca9hzp384d5m02ssvgqqa1"; - authors = [ - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "hermit-abi"; - packageId = "hermit-abi"; - target = { target, features }: ("hermit" == target."os" or null); - } - { - name = "libc"; - packageId = "libc"; - target = { target, features }: (!(target."windows" or false)); - } - ]; - - }; "object" = rec { crateName = "object"; - version = "0.32.2"; + version = "0.36.5"; edition = "2018"; - sha256 = "0hc4cjwyngiy6k51hlzrlsxgv5z25vv7c2cp0ky1lckfic0259m6"; + sha256 = "0gk8lhbs229c68lapq6w6qmnm4jkj48hrcw5ilfyswy514nhmpxf"; dependencies = [ { name = "memchr"; @@ -2482,13 +2468,15 @@ rec { } ]; features = { - "all" = [ "read" "write" "std" "compression" "wasm" ]; + "all" = [ "read" "write" "build" "std" "compression" "wasm" ]; "alloc" = [ "dep:alloc" ]; + "build" = [ "build_core" "write_std" "elf" ]; + "build_core" = [ "read_core" "write_core" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "compression" = [ "dep:flate2" "dep:ruzstd" "std" ]; "core" = [ "dep:core" ]; "default" = [ "read" "compression" ]; - "doc" = [ "read_core" "write_std" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; + "doc" = [ "read_core" "write_std" "build_core" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; "pe" = [ "coff" ]; "read" = [ "read_core" "archive" "coff" "elf" "macho" "pe" "xcoff" "unaligned" ]; "rustc-dep-of-std" = [ "core" "compiler_builtins" "alloc" "memchr/rustc-dep-of-std" ]; @@ -2499,13 +2487,13 @@ rec { "write_core" = [ "dep:crc32fast" "dep:indexmap" "dep:hashbrown" ]; "write_std" = [ "write_core" "std" "indexmap?/std" "crc32fast?/std" ]; }; - resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" ]; + resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" "xcoff" ]; }; "once_cell" = rec { crateName = "once_cell"; - version = "1.19.0"; + version = "1.20.2"; edition = "2021"; - sha256 = "14kvw7px5z96dk4dwdm1r9cqhhy2cyj1l5n5b29mynbb8yr15nrz"; + sha256 = "0xb7rw1aqr7pa4z3b00y7786gyf8awx2gca3md73afy76dzgwq8j"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" ]; @@ -2532,9 +2520,9 @@ rec { }; "parking_lot" = rec { crateName = "parking_lot"; - version = "0.12.1"; - edition = "2018"; - sha256 = "13r2xk7mnxfc5g0g6dkdxqdqad99j7s7z8zhzz4npw5r0g0v4hip"; + version = "0.12.3"; + edition = "2021"; + sha256 = "09ws9g6245iiq8z975h8ycf818a66q3c6zv4b5h8skpm7hc1igzi"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -2559,9 +2547,9 @@ rec { }; "parking_lot_core" = rec { crateName = "parking_lot_core"; - version = "0.9.9"; - edition = "2018"; - sha256 = "13h0imw1aq86wj28gxkblhkzx6z1gk8q18n0v76qmmj6cliajhjc"; + version = "0.9.10"; + edition = "2021"; + sha256 = "1y3cf9ld9ijf7i4igwzffcn0xl16dxyn4c5bwgjck1dkgabiyh0y"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; @@ -2586,7 +2574,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets 0.48.5"; + packageId = "windows-targets"; target = { target, features }: (target."windows" or false); } ]; @@ -2602,6 +2590,7 @@ rec { version = "2.3.1"; edition = "2018"; sha256 = "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -2613,9 +2602,10 @@ rec { }; "pin-project" = rec { crateName = "pin-project"; - version = "1.1.5"; + version = "1.1.6"; edition = "2021"; - sha256 = "1cxl146x0q7lawp0m1826wsgj8mmmfs6ja8q7m6f7ff5j6vl7gxn"; + sha256 = "1v4924b870bss0x5ahww9a164d4dbny90vzkmljfbqfxc6hj7wds"; + libName = "pin_project"; dependencies = [ { name = "pin-project-internal"; @@ -2626,10 +2616,11 @@ rec { }; "pin-project-internal" = rec { crateName = "pin-project-internal"; - version = "1.1.5"; + version = "1.1.6"; edition = "2021"; - sha256 = "0r9r4ivwiyqf45sv6b30l1dx282lxaax2f6gl84jwa3q590s8f1g"; + sha256 = "1y2pjavbcq40njylbnw3929i8nnrcdzrhgalzgqk57ya2n2jsl54"; procMacro = true; + libName = "pin_project_internal"; dependencies = [ { name = "proc-macro2"; @@ -2642,16 +2633,18 @@ rec { { name = "syn"; packageId = "syn"; - features = [ "full" "visit-mut" ]; + usesDefaultFeatures = false; + features = [ "parsing" "printing" "clone-impls" "proc-macro" "full" "visit-mut" ]; } ]; }; "pin-project-lite" = rec { crateName = "pin-project-lite"; - version = "0.2.13"; + version = "0.2.14"; edition = "2018"; - sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + sha256 = "00nx3f04agwjlsmd3mc5rx5haibj2v8q9b52b0kwn63wcv4nz9mx"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -2659,6 +2652,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -2698,26 +2692,12 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "std" ]; }; - "platforms" = rec { - crateName = "platforms"; - version = "3.3.0"; - edition = "2018"; - sha256 = "0k7q6pigmnvgpfasvssb12m2pv3pc94zrhrfg9by3h3wmhyfqvb2"; - authors = [ - "Tony Arcieri <bascule@gmail.com>" - "Sergey \"Shnatsel\" Davidoff <shnatsel@gmail.com>" - ]; - features = { - "default" = [ "std" ]; - "serde" = [ "dep:serde" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "proc-macro2" = rec { crateName = "proc-macro2"; - version = "1.0.79"; + version = "1.0.87"; edition = "2021"; - sha256 = "0bn004ybzdqid81cqppr5c9jrvqsxv50x60sxc41cwpmk0igydg8"; + sha256 = "16mifsq1nqzk81qm82aszib44jsd23gpqic5z4kbmzpnvjhdmr5k"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -2735,9 +2715,9 @@ rec { }; "quote" = rec { crateName = "quote"; - version = "1.0.35"; + version = "1.0.37"; edition = "2018"; - sha256 = "1vv8r2ncaz4pqdr78x7f138ka595sp2ncr1sa2plm4zxbsmwj7i9"; + sha256 = "1brklraw2g34bxy9y4q1nbrccn7bv36ylihv12c9vlcii55x7fdm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -2780,9 +2760,9 @@ rec { }; "redox_syscall" = rec { crateName = "redox_syscall"; - version = "0.4.1"; - edition = "2018"; - sha256 = "1aiifyz5dnybfvkk4cdab9p2kmphag1yad6iknc7aszlxxldf8j7"; + version = "0.5.7"; + edition = "2021"; + sha256 = "07vpgfr6a04k0x19zqr1xdlqm6fncik3zydbdi3f5g3l5k7zwvcv"; libName = "syscall"; authors = [ "Jeremy Soller <jackpot51@gmail.com>" @@ -2790,19 +2770,22 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 1.3.2"; + packageId = "bitflags 2.6.0"; } ]; features = { "core" = [ "dep:core" ]; + "default" = [ "userspace" ]; "rustc-dep-of-std" = [ "core" "bitflags/rustc-dep-of-std" ]; }; + resolvedDefaultFeatures = [ "default" "userspace" ]; }; "regex-automata" = rec { crateName = "regex-automata"; - version = "0.4.6"; + version = "0.4.8"; edition = "2021"; - sha256 = "1spaq7y4im7s56d1gxa2hi4hzf6dwswb1bv8xyavzya7k25kpf46"; + sha256 = "18wd530ndrmygi6xnz3sp345qi0hy2kdbsa89182nwbl6br5i1rn"; + libName = "regex_automata"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -2840,9 +2823,10 @@ rec { }; "rustc-demangle" = rec { crateName = "rustc-demangle"; - version = "0.1.23"; + version = "0.1.24"; edition = "2015"; - sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + sha256 = "07zysaafgrkzy2rjgwqdj2a8qdpsm6zv6f5pgpk9x0lm40z9b6vi"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -2854,13 +2838,9 @@ rec { }; "rustc_version" = rec { crateName = "rustc_version"; - version = "0.4.0"; + version = "0.4.1"; edition = "2018"; - sha256 = "0rpk9rcdk405xhbmgclsh4pai0svn49x35aggl4nhbkd4a2zb85z"; - authors = [ - "Dirkjan Ochtman <dirkjan@ochtman.nl>" - "Marvin Löbel <loebel.marvin@gmail.com>" - ]; + sha256 = "14lvdsmr5si5qbqzrajgb6vfn69k0sfygrvfvr2mps26xwi3mjyg"; dependencies = [ { name = "semver"; @@ -2871,9 +2851,9 @@ rec { }; "rustversion" = rec { crateName = "rustversion"; - version = "1.0.14"; + version = "1.0.17"; edition = "2018"; - sha256 = "1x1pz1yynk5xzzrazk2svmidj69jhz89dz5vrc28sixl20x1iz3z"; + sha256 = "1mm3fckyvb0l2209in1n2k05sws5d9mpkszbnwhq3pkq8apjhpcm"; procMacro = true; build = "build/build.rs"; authors = [ @@ -2883,9 +2863,9 @@ rec { }; "ryu" = rec { crateName = "ryu"; - version = "1.0.17"; + version = "1.0.18"; edition = "2018"; - sha256 = "188vrsh3zlnl5xl7lw0rp2sc0knpx8yaqpwvr648b6h12v4rfrp8"; + sha256 = "17xx2s8j1lln7iackzd9p0sv546vjq71i779gphjq923vjh5pjzk"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -2907,9 +2887,9 @@ rec { }; "semver" = rec { crateName = "semver"; - version = "1.0.22"; + version = "1.0.23"; edition = "2018"; - sha256 = "1jir6q2ps4s5v52bqxpvwj35p0m0ahl5pf62ppwksbv5kvk3zm4j"; + sha256 = "12wqpxfflclbq4dv8sa6gchdh92ahhwn4ci1ls22wlby3h57wsb1"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -2921,9 +2901,9 @@ rec { }; "serde" = rec { crateName = "serde"; - version = "1.0.197"; + version = "1.0.210"; edition = "2018"; - sha256 = "1qjcxqd3p4yh5cmmax9q4ics1zy34j5ij32cvjj5dc5rw5rwic9z"; + sha256 = "0flc0z8wgax1k4j5bf2zyq48bgzyv425jkd5w0i6wbh7f8j5kqy8"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -2955,9 +2935,9 @@ rec { }; "serde_derive" = rec { crateName = "serde_derive"; - version = "1.0.197"; + version = "1.0.210"; edition = "2015"; - sha256 = "02v1x0sdv8qy06lpr6by4ar1n3jz3hmab15cgimpzhgd895v7c3y"; + sha256 = "07yzy4wafk79ps0hmbqmsqh5xjna4pm4q57wc847bb8gl3nh4f94"; procMacro = true; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" @@ -2988,9 +2968,9 @@ rec { }; "serde_json" = rec { crateName = "serde_json"; - version = "1.0.114"; + version = "1.0.128"; edition = "2021"; - sha256 = "1q4saigxwkf8bw4y5kp6k33dnavlvvwa2q4zmag59vrjsqdrpw65"; + sha256 = "1n43nia50ybpcfmh3gcw4lcc627qsg9nyakzwgkk9pm10xklbxbg"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -3001,6 +2981,11 @@ rec { packageId = "itoa"; } { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + { name = "ryu"; packageId = "ryu"; } @@ -3022,7 +3007,7 @@ rec { "default" = [ "std" ]; "indexmap" = [ "dep:indexmap" ]; "preserve_order" = [ "indexmap" "std" ]; - "std" = [ "serde/std" ]; + "std" = [ "memchr/std" "serde/std" ]; }; resolvedDefaultFeatures = [ "default" "raw_value" "std" ]; }; @@ -3119,6 +3104,7 @@ rec { version = "0.1.7"; edition = "2018"; sha256 = "1xipjr4nqsgw34k7a2cgj9zaasl2ds6jwn89886kww93d32a637l"; + libName = "sharded_slab"; authors = [ "Eliza Weisman <eliza@buoyant.io>" ]; @@ -3132,11 +3118,30 @@ rec { "loom" = [ "dep:loom" ]; }; }; + "shlex" = rec { + crateName = "shlex"; + version = "1.3.0"; + edition = "2015"; + sha256 = "0r1y6bv26c1scpxvhg2cabimrmwgbp4p3wy6syj9n0c4s3q2znhg"; + authors = [ + "comex <comexk@gmail.com>" + "Fenhl <fenhl@fenhl.net>" + "Adrian Taylor <adetaylor@chromium.org>" + "Alex Touchet <alextouchet@outlook.com>" + "Daniel Parks <dp+git@oxidized.org>" + "Garrett Berg <googberg@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; "signal-hook-registry" = rec { crateName = "signal-hook-registry"; - version = "1.4.1"; + version = "1.4.2"; edition = "2015"; - sha256 = "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq"; + sha256 = "1cb5akgq8ajnd5spyn587srvs4n26ryq0p78nswffwhv46sf1sd9"; + libName = "signal_hook_registry"; authors = [ "Michal 'vorner' Vaner <vorner@vorner.cz>" "Masaki Hara <ackie.h.gmai@gmail.com>" @@ -3195,9 +3200,9 @@ rec { }; "smallvec" = rec { crateName = "smallvec"; - version = "1.13.1"; + version = "1.13.2"; edition = "2018"; - sha256 = "1mzk9j117pn3k1gabys0b7nz8cdjsx5xc6q7fwnm8r0an62d7v76"; + sha256 = "0rsw5samawl3wsw6glrsb127rx6sh89a8wyikicw6dkdcjd1lpiw"; authors = [ "The Servo Project Developers" ]; @@ -3211,9 +3216,9 @@ rec { }; "socket2" = rec { crateName = "socket2"; - version = "0.5.6"; + version = "0.5.7"; edition = "2021"; - sha256 = "0w98g7dh9m74vpxln401hl4knpjzrx7jhng7cbh46x9vm70dkzq5"; + sha256 = "070r941wbq76xpy039an4pyiy3rfj7mp7pvibf1rcri9njq5wc6f"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -3226,7 +3231,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; + packageId = "windows-sys"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_System_IO" "Win32_System_Threading" "Win32_System_WindowsProgramming" ]; } @@ -3268,9 +3273,9 @@ rec { }; "strsim" = rec { crateName = "strsim"; - version = "0.11.0"; + version = "0.11.1"; edition = "2015"; - sha256 = "00gsdp2x1gkkxsbjxgrjyil2hsbdg49bwv8q2y1f406dwk4p7q2y"; + sha256 = "0kzvqlw8hxqb7y598w1s0hxlnmi84sg5vsipp3yg5na5d1rvba3x"; authors = [ "Danny Guo <danny@dannyguo.com>" "maxbachmann <oss@maxbachmann.de>" @@ -3279,9 +3284,9 @@ rec { }; "subtle" = rec { crateName = "subtle"; - version = "2.5.0"; + version = "2.6.1"; edition = "2018"; - sha256 = "1g2yjs7gffgmdvkkq0wrrh0pxds3q0dv6dhkw9cdpbib656xdkc1"; + sha256 = "14ijxaymghbl1p0wql9cib5zlwiina7kall6w7g89csprkgbvhhk"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -3292,9 +3297,9 @@ rec { }; "syn" = rec { crateName = "syn"; - version = "2.0.52"; + version = "2.0.79"; edition = "2021"; - sha256 = "01saay6pi9x19f6lin3mw3xawdyyagpzzy39ghz2rw6i6rdx36dn"; + sha256 = "147mk4sgigmvsb9l8qzj199ygf0fgb0bphwdsghn8205pz82q4w9"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3317,14 +3322,13 @@ rec { ]; features = { "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; - "printing" = [ "quote" ]; - "proc-macro" = [ "proc-macro2/proc-macro" "quote/proc-macro" ]; - "quote" = [ "dep:quote" ]; + "printing" = [ "dep:quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; "test" = [ "syn-test-suite/all-features" ]; }; - resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit-mut" ]; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit-mut" ]; }; - "sync_wrapper" = rec { + "sync_wrapper 0.1.2" = rec { crateName = "sync_wrapper"; version = "0.1.2"; edition = "2018"; @@ -3337,11 +3341,24 @@ rec { "futures-core" = [ "dep:futures-core" ]; }; }; + "sync_wrapper 1.0.1" = rec { + crateName = "sync_wrapper"; + version = "1.0.1"; + edition = "2018"; + sha256 = "150k6lwvr4nl237ngsz8fj5j78k712m4bggrfyjsidllraz5l1m7"; + authors = [ + "Actyx AG <developer@actyx.io>" + ]; + features = { + "futures" = [ "futures-core" ]; + "futures-core" = [ "dep:futures-core" ]; + }; + }; "thiserror" = rec { crateName = "thiserror"; - version = "1.0.58"; + version = "1.0.64"; edition = "2021"; - sha256 = "15rjgd1abi2mzjgzfhrvmsxf9h65n95h6sp8f4s52q4i00wqhih3"; + sha256 = "114s8lmssxl0c2480s671am88vzlasbaikxbvfv8pyqrq6mzh2nm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3355,10 +3372,11 @@ rec { }; "thiserror-impl" = rec { crateName = "thiserror-impl"; - version = "1.0.58"; + version = "1.0.64"; edition = "2021"; - sha256 = "1xylyqcb8rv5yh2yf97hg4n4kg27qccc0ijafr1zqklrhahkn7y6"; + sha256 = "1hvzmjx9iamln854l74qyhs0jl2pg3hhqzpqm9p8gszmf9v4x408"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3400,9 +3418,9 @@ rec { }; "tokio" = rec { crateName = "tokio"; - version = "1.36.0"; + version = "1.40.0"; edition = "2021"; - sha256 = "0c89p36zbd4abr1z3l5mipp43x7z4c9b4vp4s6r8y0gs2mjmya31"; + sha256 = "166rllhfkyqp0fs7sxn6crv74iizi4wzd3cvxkcpmlk52qip1c72"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3430,11 +3448,6 @@ rec { usesDefaultFeatures = false; } { - name = "num_cpus"; - packageId = "num_cpus"; - optional = true; - } - { name = "parking_lot"; packageId = "parking_lot"; optional = true; @@ -3463,7 +3476,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys"; optional = true; target = { target, features }: (target."windows" or false); } @@ -3481,7 +3494,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Security_Authorization" ]; } @@ -3494,10 +3507,9 @@ rec { "macros" = [ "tokio-macros" ]; "mio" = [ "dep:mio" ]; "net" = [ "libc" "mio/os-poll" "mio/os-ext" "mio/net" "socket2" "windows-sys/Win32_Foundation" "windows-sys/Win32_Security" "windows-sys/Win32_Storage_FileSystem" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_System_SystemServices" ]; - "num_cpus" = [ "dep:num_cpus" ]; "parking_lot" = [ "dep:parking_lot" ]; "process" = [ "bytes" "libc" "mio/os-poll" "mio/os-ext" "mio/net" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Threading" "windows-sys/Win32_System_WindowsProgramming" ]; - "rt-multi-thread" = [ "num_cpus" "rt" ]; + "rt-multi-thread" = [ "rt" ]; "signal" = [ "libc" "mio/os-poll" "mio/net" "mio/os-ext" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Console" ]; "signal-hook-registry" = [ "dep:signal-hook-registry" ]; "socket2" = [ "dep:socket2" ]; @@ -3506,13 +3518,14 @@ rec { "tracing" = [ "dep:tracing" ]; "windows-sys" = [ "dep:windows-sys" ]; }; - resolvedDefaultFeatures = [ "bytes" "default" "fs" "full" "io-std" "io-util" "libc" "macros" "mio" "net" "num_cpus" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "test-util" "time" "tokio-macros" "windows-sys" ]; + resolvedDefaultFeatures = [ "bytes" "default" "fs" "full" "io-std" "io-util" "libc" "macros" "mio" "net" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "test-util" "time" "tokio-macros" "windows-sys" ]; }; "tokio-listener" = rec { crateName = "tokio-listener"; version = "0.3.2"; edition = "2021"; sha256 = "00vkr1cywd2agn8jbkzwwf7y4ps3cfjm8l9ab697px2cgc97wdln"; + libName = "tokio_listener"; dependencies = [ { name = "axum"; @@ -3594,10 +3607,11 @@ rec { }; "tokio-macros" = rec { crateName = "tokio-macros"; - version = "2.2.0"; + version = "2.4.0"; edition = "2021"; - sha256 = "0fwjy4vdx1h9pi4g2nml72wi0fr27b5m954p13ji9anyy8l1x2jv"; + sha256 = "0lnpg14h1v3fh2jvnc8cz7cjf0m7z1xgkwfpcyy632g829imjgb9"; procMacro = true; + libName = "tokio_macros"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3620,9 +3634,10 @@ rec { }; "tokio-stream" = rec { crateName = "tokio-stream"; - version = "0.1.14"; + version = "0.1.16"; edition = "2021"; - sha256 = "0hi8hcwavh5sdi1ivc9qc4yvyr32f153c212dpd7sb366y6rhz1r"; + sha256 = "1wc65gprcsyzqlr0k091glswy96kph90i32gffi4ksyh03hnqkjg"; + libName = "tokio_stream"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3666,6 +3681,7 @@ rec { version = "0.4.4"; edition = "2021"; sha256 = "1xzri2m3dg8nzdyznm77nymvil9cyh1gfdfrbnska51iqfmvls14"; + libName = "tokio_test"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3703,9 +3719,10 @@ rec { }; "tokio-util" = rec { crateName = "tokio-util"; - version = "0.7.10"; + version = "0.7.12"; edition = "2021"; - sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + sha256 = "0spc0g4irbnf2flgag22gfii87avqzibwfm0si0d1g0k9ijw7rv1"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3731,13 +3748,6 @@ rec { packageId = "tokio"; features = [ "sync" ]; } - { - name = "tracing"; - packageId = "tracing"; - optional = true; - usesDefaultFeatures = false; - features = [ "std" ]; - } ]; devDependencies = [ { @@ -3748,7 +3758,6 @@ rec { ]; features = { "__docs_rs" = [ "futures-util" ]; - "codec" = [ "tracing" ]; "compat" = [ "futures-io" ]; "full" = [ "codec" "compat" "io-util" "time" "net" "rt" ]; "futures-io" = [ "dep:futures-io" ]; @@ -3761,13 +3770,13 @@ rec { "time" = [ "tokio/time" "slab" ]; "tracing" = [ "dep:tracing" ]; }; - resolvedDefaultFeatures = [ "codec" "default" "io" "net" "tracing" ]; + resolvedDefaultFeatures = [ "codec" "default" "net" ]; }; "tower" = rec { crateName = "tower"; - version = "0.4.13"; + version = "0.5.1"; edition = "2018"; - sha256 = "073wncyqav4sak1p755hf6vl66njgfc1z1g1di9rxx3cvvh9pymq"; + sha256 = "0kvbp97bhb4sk24vhihcz74ngn0i4ygxqikmxndgng3w926r6wr8"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -3785,13 +3794,13 @@ rec { features = [ "alloc" ]; } { - name = "pin-project"; - packageId = "pin-project"; + name = "pin-project-lite"; + packageId = "pin-project-lite"; optional = true; } { - name = "pin-project-lite"; - packageId = "pin-project-lite"; + name = "sync_wrapper"; + packageId = "sync_wrapper 0.1.2"; optional = true; } { @@ -3826,12 +3835,17 @@ rec { packageId = "tokio"; features = [ "macros" "sync" "test-util" "rt-multi-thread" ]; } + { + name = "tracing"; + packageId = "tracing"; + usesDefaultFeatures = false; + features = [ "std" ]; + } ]; features = { "__common" = [ "futures-core" "pin-project-lite" ]; - "balance" = [ "discover" "load" "ready-cache" "make" "rand" "slab" ]; + "balance" = [ "discover" "load" "ready-cache" "make" "slab" "util" ]; "buffer" = [ "__common" "tokio/sync" "tokio/rt" "tokio-util" "tracing" ]; - "default" = [ "log" ]; "discover" = [ "__common" ]; "filter" = [ "__common" "futures-util" ]; "full" = [ "balance" "buffer" "discover" "filter" "hedge" "limit" "load" "load-shed" "make" "ready-cache" "reconnect" "retry" "spawn-ready" "steer" "timeout" "util" ]; @@ -3845,28 +3859,28 @@ rec { "load-shed" = [ "__common" ]; "log" = [ "tracing/log" ]; "make" = [ "futures-util" "pin-project-lite" "tokio/io-std" ]; - "pin-project" = [ "dep:pin-project" ]; "pin-project-lite" = [ "dep:pin-project-lite" ]; - "rand" = [ "dep:rand" ]; "ready-cache" = [ "futures-core" "futures-util" "indexmap" "tokio/sync" "tracing" "pin-project-lite" ]; "reconnect" = [ "make" "tokio/io-std" "tracing" ]; - "retry" = [ "__common" "tokio/time" ]; + "retry" = [ "__common" "tokio/time" "util" ]; "slab" = [ "dep:slab" ]; "spawn-ready" = [ "__common" "futures-util" "tokio/sync" "tokio/rt" "util" "tracing" ]; + "sync_wrapper" = [ "dep:sync_wrapper" ]; "timeout" = [ "pin-project-lite" "tokio/time" ]; "tokio" = [ "dep:tokio" ]; "tokio-stream" = [ "dep:tokio-stream" ]; "tokio-util" = [ "dep:tokio-util" ]; "tracing" = [ "dep:tracing" ]; - "util" = [ "__common" "futures-util" "pin-project" ]; + "util" = [ "__common" "futures-util" "pin-project-lite" "sync_wrapper" ]; }; - resolvedDefaultFeatures = [ "__common" "futures-core" "futures-util" "log" "make" "pin-project" "pin-project-lite" "tokio" "tracing" "util" ]; + resolvedDefaultFeatures = [ "__common" "futures-core" "futures-util" "log" "make" "pin-project-lite" "sync_wrapper" "tokio" "tracing" "util" ]; }; "tower-layer" = rec { crateName = "tower-layer"; - version = "0.3.2"; + version = "0.3.3"; edition = "2018"; - sha256 = "1l7i17k9vlssrdg4s3b0ia5jjkmmxsvv8s9y9ih0jfi8ssz8s362"; + sha256 = "03kq92fdzxin51w8iqix06dcfgydyvx7yr6izjq0p626v9n2l70j"; + libName = "tower_layer"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -3874,9 +3888,10 @@ rec { }; "tower-service" = rec { crateName = "tower-service"; - version = "0.3.2"; + version = "0.3.3"; edition = "2018"; - sha256 = "0lmfzmmvid2yp2l36mbavhmqgsvzqf7r2wiwz73ml4xmwaf1rg5n"; + sha256 = "1hzfkvkci33ra94xjx64vv3pp0sq346w06fpkcdwjcid7zhvdycd"; + libName = "tower_service"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -3935,6 +3950,7 @@ rec { edition = "2018"; sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; procMacro = true; + libName = "tracing_attributes"; authors = [ "Tokio Contributors <team@tokio.rs>" "Eliza Weisman <eliza@buoyant.io>" @@ -3963,6 +3979,7 @@ rec { version = "0.1.32"; edition = "2018"; sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3993,6 +4010,7 @@ rec { version = "0.2.0"; edition = "2018"; sha256 = "1hs77z026k730ij1a9dhahzrl0s073gfa2hm5p0fbl0b80gmz1gf"; + libName = "tracing_log"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -4024,6 +4042,7 @@ rec { version = "0.3.18"; edition = "2018"; sha256 = "12vs1bwk4kig1l2qqjbbn2nm5amwiqmkcmnznylzmnfvjy6083xd"; + libName = "tracing_subscriber"; authors = [ "Eliza Weisman <eliza@buoyant.io>" "David Barsky <me@davidbarsky.com>" @@ -4110,12 +4129,7 @@ rec { requiredFeatures = [ ]; } ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./.; } - else ./.; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./.; }; dependencies = [ { name = "clap"; @@ -4170,9 +4184,10 @@ rec { }; "unicode-ident" = rec { crateName = "unicode-ident"; - version = "1.0.12"; + version = "1.0.13"; edition = "2018"; - sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + sha256 = "1zm1xylzsdfvm2a5ib9li3g5pp7qnkv4amhspydvgbmd9k6mc6z9"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -4180,9 +4195,9 @@ rec { }; "utf8parse" = rec { crateName = "utf8parse"; - version = "0.2.1"; + version = "0.2.2"; edition = "2018"; - sha256 = "02ip1a0az0qmc2786vxk2nqwsgcwf17d3a38fkf0q7hrmwh9c6vi"; + sha256 = "088807qwjq46azicqwbhlmzwrbkz7l4hpw43sdkdyyk524vdxaq6"; authors = [ "Joe Wilm <joe@jwilm.com>" "Christian Duerr <contact@christianduerr.com>" @@ -4205,9 +4220,9 @@ rec { }; "version_check" = rec { crateName = "version_check"; - version = "0.9.4"; + version = "0.9.5"; edition = "2015"; - sha256 = "0gs8grwdlgh0xq660d7wr80x14vxbizmd8dbp29p2pdncx8lp1s9"; + sha256 = "0nhhi4i5x89gm911azqbn7avs9mdacw2i3vcz3cnmz3mv4rqz4hb"; authors = [ "Sergio Benitez <sb@sergio.bz>" ]; @@ -4242,12 +4257,12 @@ rec { { name = "winapi-i686-pc-windows-gnu"; packageId = "winapi-i686-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "i686-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnu"); } { name = "winapi-x86_64-pc-windows-gnu"; packageId = "winapi-x86_64-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnu"); } ]; features = { @@ -4260,6 +4275,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -4270,316 +4286,25 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; }; - "windows-sys 0.48.0" = rec { - crateName = "windows-sys"; - version = "0.48.0"; - edition = "2018"; - sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; - authors = [ - "Microsoft" - ]; - dependencies = [ - { - name = "windows-targets"; - packageId = "windows-targets 0.48.5"; - } - ]; - features = { - "Wdk_System" = [ "Wdk" ]; - "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; - "Win32_Data" = [ "Win32" ]; - "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; - "Win32_Data_RightsManagement" = [ "Win32_Data" ]; - "Win32_Data_Xml" = [ "Win32_Data" ]; - "Win32_Data_Xml_MsXml" = [ "Win32_Data_Xml" ]; - "Win32_Data_Xml_XmlLite" = [ "Win32_Data_Xml" ]; - "Win32_Devices" = [ "Win32" ]; - "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; - "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; - "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; - "Win32_Devices_Communication" = [ "Win32_Devices" ]; - "Win32_Devices_DeviceAccess" = [ "Win32_Devices" ]; - "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; - "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; - "Win32_Devices_Display" = [ "Win32_Devices" ]; - "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; - "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; - "Win32_Devices_Fax" = [ "Win32_Devices" ]; - "Win32_Devices_FunctionDiscovery" = [ "Win32_Devices" ]; - "Win32_Devices_Geolocation" = [ "Win32_Devices" ]; - "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; - "Win32_Devices_ImageAcquisition" = [ "Win32_Devices" ]; - "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; - "Win32_Devices_Properties" = [ "Win32_Devices" ]; - "Win32_Devices_Pwm" = [ "Win32_Devices" ]; - "Win32_Devices_Sensors" = [ "Win32_Devices" ]; - "Win32_Devices_SerialCommunication" = [ "Win32_Devices" ]; - "Win32_Devices_Tapi" = [ "Win32_Devices" ]; - "Win32_Devices_Usb" = [ "Win32_Devices" ]; - "Win32_Devices_WebServicesOnDevices" = [ "Win32_Devices" ]; - "Win32_Foundation" = [ "Win32" ]; - "Win32_Gaming" = [ "Win32" ]; - "Win32_Globalization" = [ "Win32" ]; - "Win32_Graphics" = [ "Win32" ]; - "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; - "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; - "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; - "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; - "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; - "Win32_Graphics_Printing_PrintTicket" = [ "Win32_Graphics_Printing" ]; - "Win32_Management" = [ "Win32" ]; - "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; - "Win32_Media" = [ "Win32" ]; - "Win32_Media_Audio" = [ "Win32_Media" ]; - "Win32_Media_Audio_Apo" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_DirectMusic" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_Endpoints" = [ "Win32_Media_Audio" ]; - "Win32_Media_Audio_XAudio2" = [ "Win32_Media_Audio" ]; - "Win32_Media_DeviceManager" = [ "Win32_Media" ]; - "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; - "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; - "Win32_Media_LibrarySharingServices" = [ "Win32_Media" ]; - "Win32_Media_MediaPlayer" = [ "Win32_Media" ]; - "Win32_Media_Multimedia" = [ "Win32_Media" ]; - "Win32_Media_Speech" = [ "Win32_Media" ]; - "Win32_Media_Streaming" = [ "Win32_Media" ]; - "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; - "Win32_NetworkManagement" = [ "Win32" ]; - "Win32_NetworkManagement_Dhcp" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_MobileBroadband" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_NetworkPolicyServer" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_Snmp" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsConnectNow" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; - "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; - "Win32_Networking" = [ "Win32" ]; - "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; - "Win32_Networking_BackgroundIntelligentTransferService" = [ "Win32_Networking" ]; - "Win32_Networking_Clustering" = [ "Win32_Networking" ]; - "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; - "Win32_Networking_Ldap" = [ "Win32_Networking" ]; - "Win32_Networking_NetworkListManager" = [ "Win32_Networking" ]; - "Win32_Networking_RemoteDifferentialCompression" = [ "Win32_Networking" ]; - "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; - "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; - "Win32_Networking_WinInet" = [ "Win32_Networking" ]; - "Win32_Networking_WinSock" = [ "Win32_Networking" ]; - "Win32_Networking_WindowsWebServices" = [ "Win32_Networking" ]; - "Win32_Security" = [ "Win32" ]; - "Win32_Security_AppLocker" = [ "Win32_Security" ]; - "Win32_Security_Authentication" = [ "Win32_Security" ]; - "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; - "Win32_Security_Authentication_Identity_Provider" = [ "Win32_Security_Authentication_Identity" ]; - "Win32_Security_Authorization" = [ "Win32_Security" ]; - "Win32_Security_Authorization_UI" = [ "Win32_Security_Authorization" ]; - "Win32_Security_ConfigurationSnapin" = [ "Win32_Security" ]; - "Win32_Security_Credentials" = [ "Win32_Security" ]; - "Win32_Security_Cryptography" = [ "Win32_Security" ]; - "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_Cryptography_Certificates" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_Cryptography_Sip" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_Cryptography_UI" = [ "Win32_Security_Cryptography" ]; - "Win32_Security_DiagnosticDataQuery" = [ "Win32_Security" ]; - "Win32_Security_DirectoryServices" = [ "Win32_Security" ]; - "Win32_Security_EnterpriseData" = [ "Win32_Security" ]; - "Win32_Security_ExtensibleAuthenticationProtocol" = [ "Win32_Security" ]; - "Win32_Security_Isolation" = [ "Win32_Security" ]; - "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; - "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; - "Win32_Security_Tpm" = [ "Win32_Security" ]; - "Win32_Security_WinTrust" = [ "Win32_Security" ]; - "Win32_Security_WinWlx" = [ "Win32_Security" ]; - "Win32_Storage" = [ "Win32" ]; - "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; - "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; - "Win32_Storage_Compression" = [ "Win32_Storage" ]; - "Win32_Storage_DataDeduplication" = [ "Win32_Storage" ]; - "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; - "Win32_Storage_EnhancedStorage" = [ "Win32_Storage" ]; - "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; - "Win32_Storage_FileServerResourceManager" = [ "Win32_Storage" ]; - "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; - "Win32_Storage_Imapi" = [ "Win32_Storage" ]; - "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; - "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; - "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; - "Win32_Storage_Jet" = [ "Win32_Storage" ]; - "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; - "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; - "Win32_Storage_Packaging" = [ "Win32_Storage" ]; - "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; - "Win32_Storage_Packaging_Opc" = [ "Win32_Storage_Packaging" ]; - "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; - "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; - "Win32_Storage_Vhd" = [ "Win32_Storage" ]; - "Win32_Storage_VirtualDiskService" = [ "Win32_Storage" ]; - "Win32_Storage_Vss" = [ "Win32_Storage" ]; - "Win32_Storage_Xps" = [ "Win32_Storage" ]; - "Win32_Storage_Xps_Printing" = [ "Win32_Storage_Xps" ]; - "Win32_System" = [ "Win32" ]; - "Win32_System_AddressBook" = [ "Win32_System" ]; - "Win32_System_Antimalware" = [ "Win32_System" ]; - "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; - "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; - "Win32_System_AssessmentTool" = [ "Win32_System" ]; - "Win32_System_ClrHosting" = [ "Win32_System" ]; - "Win32_System_Com" = [ "Win32_System" ]; - "Win32_System_Com_CallObj" = [ "Win32_System_Com" ]; - "Win32_System_Com_ChannelCredentials" = [ "Win32_System_Com" ]; - "Win32_System_Com_Events" = [ "Win32_System_Com" ]; - "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; - "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; - "Win32_System_Com_UI" = [ "Win32_System_Com" ]; - "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; - "Win32_System_ComponentServices" = [ "Win32_System" ]; - "Win32_System_Console" = [ "Win32_System" ]; - "Win32_System_Contacts" = [ "Win32_System" ]; - "Win32_System_CorrelationVector" = [ "Win32_System" ]; - "Win32_System_DataExchange" = [ "Win32_System" ]; - "Win32_System_DeploymentServices" = [ "Win32_System" ]; - "Win32_System_DesktopSharing" = [ "Win32_System" ]; - "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; - "Win32_System_Diagnostics" = [ "Win32_System" ]; - "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_ClrProfiling" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_Debug_ActiveScript" = [ "Win32_System_Diagnostics_Debug" ]; - "Win32_System_Diagnostics_Debug_Extensions" = [ "Win32_System_Diagnostics_Debug" ]; - "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; - "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; - "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; - "Win32_System_Environment" = [ "Win32_System" ]; - "Win32_System_ErrorReporting" = [ "Win32_System" ]; - "Win32_System_EventCollector" = [ "Win32_System" ]; - "Win32_System_EventLog" = [ "Win32_System" ]; - "Win32_System_EventNotificationService" = [ "Win32_System" ]; - "Win32_System_GroupPolicy" = [ "Win32_System" ]; - "Win32_System_HostCompute" = [ "Win32_System" ]; - "Win32_System_HostComputeNetwork" = [ "Win32_System" ]; - "Win32_System_HostComputeSystem" = [ "Win32_System" ]; - "Win32_System_Hypervisor" = [ "Win32_System" ]; - "Win32_System_IO" = [ "Win32_System" ]; - "Win32_System_Iis" = [ "Win32_System" ]; - "Win32_System_Ioctl" = [ "Win32_System" ]; - "Win32_System_JobObjects" = [ "Win32_System" ]; - "Win32_System_Js" = [ "Win32_System" ]; - "Win32_System_Kernel" = [ "Win32_System" ]; - "Win32_System_LibraryLoader" = [ "Win32_System" ]; - "Win32_System_Mailslots" = [ "Win32_System" ]; - "Win32_System_Mapi" = [ "Win32_System" ]; - "Win32_System_Memory" = [ "Win32_System" ]; - "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; - "Win32_System_MessageQueuing" = [ "Win32_System" ]; - "Win32_System_MixedReality" = [ "Win32_System" ]; - "Win32_System_Mmc" = [ "Win32_System" ]; - "Win32_System_Ole" = [ "Win32_System" ]; - "Win32_System_ParentalControls" = [ "Win32_System" ]; - "Win32_System_PasswordManagement" = [ "Win32_System" ]; - "Win32_System_Performance" = [ "Win32_System" ]; - "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; - "Win32_System_Pipes" = [ "Win32_System" ]; - "Win32_System_Power" = [ "Win32_System" ]; - "Win32_System_ProcessStatus" = [ "Win32_System" ]; - "Win32_System_RealTimeCommunications" = [ "Win32_System" ]; - "Win32_System_Recovery" = [ "Win32_System" ]; - "Win32_System_Registry" = [ "Win32_System" ]; - "Win32_System_RemoteAssistance" = [ "Win32_System" ]; - "Win32_System_RemoteDesktop" = [ "Win32_System" ]; - "Win32_System_RemoteManagement" = [ "Win32_System" ]; - "Win32_System_RestartManager" = [ "Win32_System" ]; - "Win32_System_Restore" = [ "Win32_System" ]; - "Win32_System_Rpc" = [ "Win32_System" ]; - "Win32_System_Search" = [ "Win32_System" ]; - "Win32_System_Search_Common" = [ "Win32_System_Search" ]; - "Win32_System_SecurityCenter" = [ "Win32_System" ]; - "Win32_System_ServerBackup" = [ "Win32_System" ]; - "Win32_System_Services" = [ "Win32_System" ]; - "Win32_System_SettingsManagementInfrastructure" = [ "Win32_System" ]; - "Win32_System_SetupAndMigration" = [ "Win32_System" ]; - "Win32_System_Shutdown" = [ "Win32_System" ]; - "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; - "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; - "Win32_System_SystemInformation" = [ "Win32_System" ]; - "Win32_System_SystemServices" = [ "Win32_System" ]; - "Win32_System_TaskScheduler" = [ "Win32_System" ]; - "Win32_System_Threading" = [ "Win32_System" ]; - "Win32_System_Time" = [ "Win32_System" ]; - "Win32_System_TpmBaseServices" = [ "Win32_System" ]; - "Win32_System_UpdateAgent" = [ "Win32_System" ]; - "Win32_System_UpdateAssessment" = [ "Win32_System" ]; - "Win32_System_UserAccessLogging" = [ "Win32_System" ]; - "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; - "Win32_System_WindowsProgramming" = [ "Win32_System" ]; - "Win32_System_WindowsSync" = [ "Win32_System" ]; - "Win32_System_Wmi" = [ "Win32_System" ]; - "Win32_UI" = [ "Win32" ]; - "Win32_UI_Accessibility" = [ "Win32_UI" ]; - "Win32_UI_Animation" = [ "Win32_UI" ]; - "Win32_UI_ColorSystem" = [ "Win32_UI" ]; - "Win32_UI_Controls" = [ "Win32_UI" ]; - "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; - "Win32_UI_Controls_RichEdit" = [ "Win32_UI_Controls" ]; - "Win32_UI_HiDpi" = [ "Win32_UI" ]; - "Win32_UI_Input" = [ "Win32_UI" ]; - "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Ink" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Radial" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; - "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; - "Win32_UI_InteractionContext" = [ "Win32_UI" ]; - "Win32_UI_LegacyWindowsEnvironmentFeatures" = [ "Win32_UI" ]; - "Win32_UI_Magnification" = [ "Win32_UI" ]; - "Win32_UI_Notifications" = [ "Win32_UI" ]; - "Win32_UI_Ribbon" = [ "Win32_UI" ]; - "Win32_UI_Shell" = [ "Win32_UI" ]; - "Win32_UI_Shell_Common" = [ "Win32_UI_Shell" ]; - "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; - "Win32_UI_TabletPC" = [ "Win32_UI" ]; - "Win32_UI_TextServices" = [ "Win32_UI" ]; - "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; - "Win32_UI_Wpf" = [ "Win32_UI" ]; - "Win32_Web" = [ "Win32" ]; - "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; - }; - resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Console" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "default" ]; - }; - "windows-sys 0.52.0" = rec { + "windows-sys" = rec { crateName = "windows-sys"; version = "0.52.0"; edition = "2021"; sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + libName = "windows_sys"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets 0.52.4"; + packageId = "windows-targets"; } ]; features = { @@ -4813,237 +4538,136 @@ rec { "Win32_Web" = [ "Win32" ]; "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; }; - resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_System" "Win32_System_Console" "Win32_System_IO" "Win32_System_Threading" "Win32_System_WindowsProgramming" "default" ]; + resolvedDefaultFeatures = [ "Wdk" "Wdk_Foundation" "Wdk_Storage" "Wdk_Storage_FileSystem" "Wdk_System" "Wdk_System_IO" "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Console" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "default" ]; }; - "windows-targets 0.48.5" = rec { + "windows-targets" = rec { crateName = "windows-targets"; - version = "0.48.5"; - edition = "2018"; - sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0wwrx625nwlfp7k93r2rra568gad1mwd888h1jwnl0vfg5r4ywlv"; + libName = "windows_targets"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows_aarch64_gnullvm"; - packageId = "windows_aarch64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + packageId = "windows_aarch64_gnullvm"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); } { name = "windows_aarch64_msvc"; - packageId = "windows_aarch64_msvc 0.48.5"; + packageId = "windows_aarch64_msvc"; target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_i686_gnu"; - packageId = "windows_i686_gnu 0.48.5"; - target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!(target."windows_raw_dylib" or false))); - } - { - name = "windows_i686_msvc"; - packageId = "windows_i686_msvc 0.48.5"; - target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); - } - { - name = "windows_x86_64_gnu"; - packageId = "windows_x86_64_gnu 0.48.5"; - target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); - } - { - name = "windows_x86_64_gnullvm"; - packageId = "windows_x86_64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); - } - { - name = "windows_x86_64_msvc"; - packageId = "windows_x86_64_msvc 0.48.5"; - target = { target, features }: (("x86_64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); - } - ]; - - }; - "windows-targets 0.52.4" = rec { - crateName = "windows-targets"; - version = "0.52.4"; - edition = "2021"; - sha256 = "06sdd7fin3dj9cmlg6n1dw0n1l10jhn9b8ckz1cqf0drb9z7plvx"; - authors = [ - "Microsoft" - ]; - dependencies = [ - { - name = "windows_aarch64_gnullvm"; - packageId = "windows_aarch64_gnullvm 0.52.4"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + packageId = "windows_i686_gnu"; + target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); } { - name = "windows_aarch64_msvc"; - packageId = "windows_aarch64_msvc 0.52.4"; - target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); - } - { - name = "windows_i686_gnu"; - packageId = "windows_i686_gnu 0.52.4"; - target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + name = "windows_i686_gnullvm"; + packageId = "windows_i686_gnullvm"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnullvm"); } { name = "windows_i686_msvc"; - packageId = "windows_i686_msvc 0.52.4"; + packageId = "windows_i686_msvc"; target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnu"; - packageId = "windows_x86_64_gnu 0.52.4"; + packageId = "windows_x86_64_gnu"; target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnullvm"; - packageId = "windows_x86_64_gnullvm 0.52.4"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); + packageId = "windows_x86_64_gnullvm"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); } { name = "windows_x86_64_msvc"; - packageId = "windows_x86_64_msvc 0.52.4"; - target = { target, features }: (("x86_64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); + packageId = "windows_x86_64_msvc"; + target = { target, features }: ((("x86_64" == target."arch" or null) || ("arm64ec" == target."arch" or null)) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } ]; }; - "windows_aarch64_gnullvm 0.48.5" = rec { + "windows_aarch64_gnullvm" = rec { crateName = "windows_aarch64_gnullvm"; - version = "0.48.5"; - edition = "2018"; - sha256 = "1n05v7qblg1ci3i567inc7xrkmywczxrs1z3lj3rkkxw18py6f1b"; - authors = [ - "Microsoft" - ]; - - }; - "windows_aarch64_gnullvm 0.52.4" = rec { - crateName = "windows_aarch64_gnullvm"; - version = "0.52.4"; + version = "0.52.6"; edition = "2021"; - sha256 = "1jfam5qfngg8v1syxklnvy8la94b5igm7klkrk8z5ik5qgs6rx5w"; + sha256 = "1lrcq38cr2arvmz19v32qaggvj8bh1640mdm9c2fr877h0hn591j"; authors = [ "Microsoft" ]; }; - "windows_aarch64_msvc 0.48.5" = rec { + "windows_aarch64_msvc" = rec { crateName = "windows_aarch64_msvc"; - version = "0.48.5"; - edition = "2018"; - sha256 = "1g5l4ry968p73g6bg6jgyvy9lb8fyhcs54067yzxpcpkf44k2dfw"; - authors = [ - "Microsoft" - ]; - - }; - "windows_aarch64_msvc 0.52.4" = rec { - crateName = "windows_aarch64_msvc"; - version = "0.52.4"; + version = "0.52.6"; edition = "2021"; - sha256 = "0xdn6db0rk8idn7dxsyflixq2dbj9x60kzdzal5rkxmwsffjb7ys"; + sha256 = "0sfl0nysnz32yyfh773hpi49b1q700ah6y7sacmjbqjjn5xjmv09"; authors = [ "Microsoft" ]; }; - "windows_i686_gnu 0.48.5" = rec { + "windows_i686_gnu" = rec { crateName = "windows_i686_gnu"; - version = "0.48.5"; - edition = "2018"; - sha256 = "0gklnglwd9ilqx7ac3cn8hbhkraqisd0n83jxzf9837nvvkiand7"; - authors = [ - "Microsoft" - ]; - - }; - "windows_i686_gnu 0.52.4" = rec { - crateName = "windows_i686_gnu"; - version = "0.52.4"; + version = "0.52.6"; edition = "2021"; - sha256 = "1lq1g35sbj55ms86by4c080jcqrlfjy9bw5r4mgrkq4riwkdhx5l"; + sha256 = "02zspglbykh1jh9pi7gn8g1f97jh1rrccni9ivmrfbl0mgamm6wf"; authors = [ "Microsoft" ]; }; - "windows_i686_msvc 0.48.5" = rec { - crateName = "windows_i686_msvc"; - version = "0.48.5"; - edition = "2018"; - sha256 = "01m4rik437dl9rdf0ndnm2syh10hizvq0dajdkv2fjqcywrw4mcg"; + "windows_i686_gnullvm" = rec { + crateName = "windows_i686_gnullvm"; + version = "0.52.6"; + edition = "2021"; + sha256 = "0rpdx1537mw6slcpqa0rm3qixmsb79nbhqy5fsm3q2q9ik9m5vhf"; authors = [ "Microsoft" ]; }; - "windows_i686_msvc 0.52.4" = rec { + "windows_i686_msvc" = rec { crateName = "windows_i686_msvc"; - version = "0.52.4"; + version = "0.52.6"; edition = "2021"; - sha256 = "00lfzw88dkf3fdcf2hpfhp74i9pwbp7rwnj1nhy79vavksifj58m"; + sha256 = "0rkcqmp4zzmfvrrrx01260q3xkpzi6fzi2x2pgdcdry50ny4h294"; authors = [ "Microsoft" ]; }; - "windows_x86_64_gnu 0.48.5" = rec { + "windows_x86_64_gnu" = rec { crateName = "windows_x86_64_gnu"; - version = "0.48.5"; - edition = "2018"; - sha256 = "13kiqqcvz2vnyxzydjh73hwgigsdr2z1xpzx313kxll34nyhmm2k"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_gnu 0.52.4" = rec { - crateName = "windows_x86_64_gnu"; - version = "0.52.4"; + version = "0.52.6"; edition = "2021"; - sha256 = "00qs6x33bf9lai2q68faxl56cszbv7mf7zqlslmc1778j0ahkvjy"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_gnullvm 0.48.5" = rec { - crateName = "windows_x86_64_gnullvm"; - version = "0.48.5"; - edition = "2018"; - sha256 = "1k24810wfbgz8k48c2yknqjmiigmql6kk3knmddkv8k8g1v54yqb"; + sha256 = "0y0sifqcb56a56mvn7xjgs8g43p33mfqkd8wj1yhrgxzma05qyhl"; authors = [ "Microsoft" ]; }; - "windows_x86_64_gnullvm 0.52.4" = rec { + "windows_x86_64_gnullvm" = rec { crateName = "windows_x86_64_gnullvm"; - version = "0.52.4"; + version = "0.52.6"; edition = "2021"; - sha256 = "0xr13xxakp14hs4v4hg2ynjcv7wrzr3hg7zk5agglj8v8pr7kjkp"; - authors = [ - "Microsoft" - ]; - - }; - "windows_x86_64_msvc 0.48.5" = rec { - crateName = "windows_x86_64_msvc"; - version = "0.48.5"; - edition = "2018"; - sha256 = "0f4mdp895kkjh9zv8dxvn4pc10xr7839lf5pa9l0193i2pkgr57d"; + sha256 = "03gda7zjx1qh8k9nnlgb7m3w3s1xkysg55hkd1wjch8pqhyv5m94"; authors = [ "Microsoft" ]; }; - "windows_x86_64_msvc 0.52.4" = rec { + "windows_x86_64_msvc" = rec { crateName = "windows_x86_64_msvc"; - version = "0.52.4"; + version = "0.52.6"; edition = "2021"; - sha256 = "1n0yc7xiv9iki1j3xl8nxlwwkr7dzsnwwvycvgxxv81d5bjm5drj"; + sha256 = "1v7rb5cibyzx8vak29pdrk8nx9hycsjs4w0jgms08qk49jl6v7sq"; authors = [ "Microsoft" ]; @@ -5051,9 +4675,9 @@ rec { }; "zeroize" = rec { crateName = "zeroize"; - version = "1.7.0"; + version = "1.8.1"; edition = "2021"; - sha256 = "0bfvby7k9pdp6623p98yz2irqnamcyzpn7zh20nqmdn68b0lwnsj"; + sha256 = "1pjdrmjwmszpxfd7r860jx54cyk94qk59x13sc307cvr5256glyf"; authors = [ "The RustCrypto Project Developers" ]; @@ -5081,14 +4705,11 @@ rec { fuchsia = true; test = false; - /* We are choosing an arbitrary rust version to grab `lib` from, - which is unfortunate, but `lib` has been version-agnostic the - whole time so this is good enough for now. - */ - os = pkgs.rust.lib.toTargetOs platform; - arch = pkgs.rust.lib.toTargetArch platform; - family = pkgs.rust.lib.toTargetFamily platform; - vendor = pkgs.rust.lib.toTargetVendor platform; + inherit (platform.rust.platform) + arch + os + vendor; + family = platform.rust.platform.target-family; env = "gnu"; endian = if platform.parsed.cpu.significantByte.name == "littleEndian" @@ -5178,51 +4799,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; - export RUST_BACKTRACE=1 + inherit (crate) src; - # recreate a file hierarchy as when running tests with cargo + inherit testCrateFlags; - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # TODO(raitobezarius): I believe there could be more edge cases if `crate.sourceRoot` - # do exist but it's very hard to reason about them, so let's wait until the first bug report. - mkdir -p source/ - cd source/ + buildInputs = testInputs; - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + buildPhase = '' + set -e + export RUST_BACKTRACE=1 - # build outputs - testRoot=target/debug - mkdir -p $testRoot + # build outputs + testRoot=target/debug + mkdir -p $testRoot - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { @@ -5331,7 +4942,7 @@ rec { let self = { crates = lib.mapAttrs (packageId: value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs; - target = makeTarget pkgs.stdenv.hostPlatform; + target = makeTarget stdenv.hostPlatform; build = mkBuiltByPackageIdByPkgs pkgs.buildPackages; }; in @@ -5406,8 +5017,6 @@ rec { buildRustCrateForPkgsFunc pkgs ( crateConfig // { - # https://github.com/NixOS/nixpkgs/issues/218712 - dontStrip = stdenv.hostPlatform.isDarwin; src = crateConfig.src or ( pkgs.fetchurl rec { name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz"; diff --git a/users/picnoir/tvix-daemon/default.nix b/users/picnoir/tvix-daemon/default.nix index 78b9aa9a1d1c..d970ac3608f3 100644 --- a/users/picnoir/tvix-daemon/default.nix +++ b/users/picnoir/tvix-daemon/default.nix @@ -36,8 +36,18 @@ in buildPhase = "cargo clippy --tests --all-features --benches --examples | tee $out"; }; + crate2nix-check = + let + crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; + in + crate2nix-check.command.overrideAttrs { + meta.ci.extraSteps = { + inherit crate2nix-check; + }; + }; meta.ci.targets = [ "tvix-daemon" "shell" + "crate2nix-check" ]; } diff --git a/users/picnoir/tvix-daemon/src/main.rs b/users/picnoir/tvix-daemon/src/main.rs index 102067fcf7d4..dc49b209e009 100644 --- a/users/picnoir/tvix-daemon/src/main.rs +++ b/users/picnoir/tvix-daemon/src/main.rs @@ -4,7 +4,7 @@ use tokio_listener::{self, SystemOptions, UserOptions}; use tracing::{debug, error, info, instrument, Level}; use nix_compat::worker_protocol::{self, server_handshake_client, ClientSettings, Trust}; -use nix_compat::{wire, ProtocolVersion}; +use nix_compat::ProtocolVersion; #[derive(Parser, Debug)] struct Cli { @@ -78,7 +78,9 @@ where // TODO: implement logging. For now, we'll just send // STDERR_LAST, which is good enough to get Nix respond to // us. - wire::write_u64(&mut client_connection.conn, worker_protocol::STDERR_LAST) + client_connection + .conn + .write_u64_le(worker_protocol::STDERR_LAST) .await .unwrap(); loop { @@ -109,6 +111,6 @@ where let settings = worker_protocol::read_client_settings(&mut conn.conn, conn.version).await?; // The client expects us to send some logs when we're processing // the settings. Sending STDERR_LAST signal we're done processing. - wire::write_u64(&mut conn.conn, worker_protocol::STDERR_LAST).await?; + conn.conn.write_u64_le(worker_protocol::STDERR_LAST).await?; Ok(settings) } diff --git a/users/sterni/machines/ingeborg/http/code.sterni.lv.nix b/users/sterni/machines/ingeborg/http/code.sterni.lv.nix index fd4975ed1d59..24ce218d48d6 100644 --- a/users/sterni/machines/ingeborg/http/code.sterni.lv.nix +++ b/users/sterni/machines/ingeborg/http/code.sterni.lv.nix @@ -167,10 +167,22 @@ in { imports = [ ./nginx.nix - ./fcgiwrap.nix ]; config = { + services.fcgiwrap.instances.cgit = { + process = { + user = "http"; + group = "http"; + }; + # Default value doesn't work as documented + # https://github.com/NixOS/nixpkgs/pull/318599/files#r1673885083 + socket = { + user = "http"; + group = "http"; + }; + }; + services.nginx.virtualHosts."${virtualHost}" = { enableACME = true; forceSSL = true; @@ -185,7 +197,7 @@ in fastcgi_param QUERY_STRING $args; fastcgi_param HTTP_HOST $server_name; fastcgi_param CGIT_CONFIG ${cgitConfig}; - fastcgi_pass unix:${toString config.services.fcgiwrap.socketAddress}; + fastcgi_pass unix:${toString config.services.fcgiwrap.instances.cgit.socket.address}; } ''; }; diff --git a/users/sterni/machines/ingeborg/http/fcgiwrap.nix b/users/sterni/machines/ingeborg/http/fcgiwrap.nix deleted file mode 100644 index 19696d85d413..000000000000 --- a/users/sterni/machines/ingeborg/http/fcgiwrap.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ ... }: - -{ - imports = [ - ./nginx.nix - ]; - - config.services.fcgiwrap = { - enable = true; - socketType = "unix"; - socketAddress = "/run/fcgiwrap.sock"; - user = "http"; - group = "http"; - }; -} diff --git a/users/sterni/modules/backup-minecraft-fabric.nix b/users/sterni/modules/backup-minecraft-fabric.nix index a80a7f51a9ef..5dad2b8825c2 100644 --- a/users/sterni/modules/backup-minecraft-fabric.nix +++ b/users/sterni/modules/backup-minecraft-fabric.nix @@ -10,7 +10,8 @@ let inherit (depot.nix) getBins; bins = getBins pkgs.borgbackup [ "borg" ] - // getBins pkgs.mcrcon [ "mcrcon" ]; + // getBins pkgs.mcrcon [ "mcrcon" ] + // getBins pkgs.systemd [ "systemd-creds" ]; unvaried = ls: builtins.all (l: l == builtins.head ls) ls; @@ -29,7 +30,7 @@ let export MCRCON_HOST="localhost" export MCRCON_PORT="${toString instanceCfg.serverProperties."rcon.port"}" # Unfortunately, mcrcon can't read the password from a file - export MCRCON_PASS="$(cat "''${CREDENTIALS_DIRECTORY}/${instanceName}-rcon-password")" + export MCRCON_PASS="$(${bins.systemd-creds} cat "${instanceName}-rcon-password")" ${bins.mcrcon} save-all unset MCRCON_PASS diff --git a/users/sterni/modules/minecraft-fabric.nix b/users/sterni/modules/minecraft-fabric.nix index 6cc32cd20587..8f44c8a536af 100644 --- a/users/sterni/modules/minecraft-fabric.nix +++ b/users/sterni/modules/minecraft-fabric.nix @@ -273,7 +273,7 @@ let export MCRCON_HOST=localhost export MCRCON_PORT=${lib.escapeShellArg instanceCfg.serverProperties."rcon.port"} # Unfortunately, mcrcon can't read the password from a file - export MCRCON_PASS="$(cat "''${CREDENTIALS_DIRECTORY}/rcon-password")" + export MCRCON_PASS="$(cat "''${RCON_PASSWORD}")" # Send stop request "${bins.mcrcon}" 'say Server is stopping' save-all stop @@ -314,7 +314,7 @@ let # Create config and set password from credentials (echo hopefully doesn't leak) copyFromStore "${serverPropertiesFile name instanceCfg}" server.properties - echo "rcon.password=$(cat "$CREDENTIALS_DIRECTORY/rcon-password")" >> server.properties + echo "rcon.password=$(cat "$RCON_PASSWORD")" >> server.properties # Build patched jar "${bins.java}" -jar "${fabricInstallerJar}" \ @@ -509,8 +509,13 @@ in after = [ "network.target" ]; inherit (instanceCfg) enable; + environment = { + # Workaround for https://github.com/systemd/systemd/issues/34805 + "RCON_PASSWORD" = "%d/rcon-password"; + }; + serviceConfig = { - Type = "simple"; + Type = "exec"; User = instanceCfg.user; Group = instanceCfg.group; ExecStart = startScript name instanceCfg; diff --git a/users/tazjin/chase-geese/default.nix b/users/tazjin/chase-geese/default.nix index 3549f758687d..595ca92896a5 100644 --- a/users/tazjin/chase-geese/default.nix +++ b/users/tazjin/chase-geese/default.nix @@ -9,5 +9,5 @@ pkgs.writeShellScriptBin "chase-geese" '' echo "Mounting the cloud ..." mkdir -p ~/cloud - ${depot.third_party.geesefs}/bin/geesefs tazjins-files ~/cloud + ${pkgs.geesefs}/bin/geesefs tazjins-files ~/cloud '' diff --git a/users/tazjin/cursed/default.nix b/users/tazjin/cursed/default.nix new file mode 100644 index 000000000000..336a746db79d --- /dev/null +++ b/users/tazjin/cursed/default.nix @@ -0,0 +1,9 @@ +{ depot, ... }: + +let + inherit (depot.web) bubblegum; +in +(bubblegum.writeCGI + { + name = "cursed"; + } ./responder.nix) // { meta.ci.skip = true; } diff --git a/users/tazjin/cursed/responder.nix b/users/tazjin/cursed/responder.nix new file mode 100644 index 000000000000..9aa6a2d55807 --- /dev/null +++ b/users/tazjin/cursed/responder.nix @@ -0,0 +1,76 @@ +{ depot, ... }: + +let + inherit (depot.users.sterni.nix.html) + __findFile + esc + withDoctype + ; + + # CGI envvars: https://www.instanet.com/cgi/env.html + method = builtins.getEnv "REQUEST_METHOD"; + path = builtins.getEnv "PATH_INFO"; + + rawQuery = builtins.getEnv "QUERY_STRING"; + query = with builtins; let + pairs = (filter (s: isString s && s != "") (split "&" rawQuery)); + tuples = filter (l: length l > 0) (map (p: filter (s: isString s) (split "=" p)) pairs); + mkAttr = t: { + name = elemAt t 0; + value = elemAt t 1; + }; + in + listToAttrs (map mkAttr tuples); + + default = let { + hasQuery = if builtins.length (builtins.attrNames query) > 0 then "?" else ""; + body = (withDoctype (<html> { lang = "en"; } [ + (<head> { } [ + (<title> { } "some cursed nix") + ]) + (<body> { } [ + (<p> { } "hello volgasprint") + (<p> { } [ method " " path hasQuery rawQuery ]) + (<p> { } (builtins.toJSON query)) + ]) + ])); + }; + + greeter = withDoctype (<html> { lang = "en"; } [ + (<head> { } [ + (<title> { } "hello there") + ]) + (<body> { } [ + (<p> { } "hello ${query.name or "unknown"}") + ]) + ]); + + weather = let { + town = query.town or "Kazan"; + w = builtins.fetchurl "https://wttr.in/${town}?"; + rendered = with depot.third_party.nixpkgs; runCommand "weather-${town}" { } '' + cat ${w} | ${ansi2html}/bin/ansi2html > $out + ''; + + body = builtins.readFile "${rendered}"; + }; + + routes = { + "/other" = (withDoctype (<html> { lang = "en"; } [ + (<head> { } [ + (<title> { } "other endpoint") + ]) + (<body> { } [ + (<p> { } "this is another route") + ]) + ])); + "/greeter" = greeter; + "/weather" = weather; + }."${path}" or default; + +in +depot.web.bubblegum.respond "OK" +{ + "Content-Type" = "text/html"; +} + routes diff --git a/users/tazjin/dotfiles/.skip-subtree b/users/tazjin/dotfiles/.skip-subtree new file mode 100644 index 000000000000..954981f436ee --- /dev/null +++ b/users/tazjin/dotfiles/.skip-subtree @@ -0,0 +1 @@ +Stuff below here is managed manually, without readTree. diff --git a/users/tazjin/dotfiles/default.nix b/users/tazjin/dotfiles/default.nix index 9b783a9c857c..6291a10303e7 100644 --- a/users/tazjin/dotfiles/default.nix +++ b/users/tazjin/dotfiles/default.nix @@ -1,3 +1,23 @@ -_: { +{ depot, pkgs, ... }@args: + +rec { dunstrc = ./dunstrc; + niri = ./niri.config.kdl; + fuzzel = ./fuzzel.ini; + waybar = { + config = import ./waybar/config.nix args; + style = pkgs.runCommandNoCC "waybar-style.css" + { + CHICAGO95 = depot.third_party.chicago95; + } '' + cat ${./waybar/style.css} | ${pkgs.envsubst}/bin/envsubst > $out + ''; + }; + + # Helper derivation for iterating on waybar config. + waybarTest = pkgs.runCommandNoCC "waybar-conf" { } '' + mkdir -p $out + cat ${pkgs.writeText "waybar-conf.json" (builtins.toJSON(builtins.attrValues waybar.config))} > $out/config + cp ${waybar.style} $out/style.css + ''; } diff --git a/users/tazjin/dotfiles/dunstrc b/users/tazjin/dotfiles/dunstrc index 2aa1141b6ec2..d984ff94ecaa 100644 --- a/users/tazjin/dotfiles/dunstrc +++ b/users/tazjin/dotfiles/dunstrc @@ -1,54 +1,15 @@ [global] -font = Iosevka Term 11 -origin = top-left -markup = yes -plain_text = no -format = "<b>%s</b>\n%b" -sort = no -indicate_hidden = yes -alignment = center -bounce_freq = 0 -show_age_threshold = -1 -word_wrap = yes -ignore_newline = no -stack_duplicates = yes -hide_duplicate_count = yes -geometry = "300x50-15+49" -shrink = no -transparency = 5 -idle_threshold = 0 -monitor = 0 +origin = bottom-right +offset = 5x5 # takes into account menu bar! +corner_radius = 5 +frame_width = 1 +frame_color = "#000000" +foreground = "#000000" +background = "#ffffe1" +font = Arial 12 follow = keyboard -sticky_history = yes -history_length = 15 -show_indicators = no -line_height = 3 -separator_height = 2 -padding = 6 -horizontal_padding = 6 -separator_color = frame -startup_notification = false -dmenu = /usr/bin/dmenu -p dunst: -browser = /usr/bin/firefox -new-tab -icon_position = off -max_icon_size = 80 -frame_width = 3 -frame_color = "#8EC07C" - -[urgency_low] -frame_color = "#3B7C87" -foreground = "#3B7C87" -background = "#191311" -timeout = 4 - -[urgency_normal] -frame_color = "#5B8234" -foreground = "#5B8234" -background = "#191311" -timeout = 6 - -[urgency_critical] -frame_color = "#B7472A" -foreground = "#B7472A" -background = "#191311" -timeout = 8 +vertical_alignment = top +format = "<b>%s</b>\n<i>from %a</i>\n\n%b" +icon_theme = "Chicago95-tux" +enable_recursive_icon_lookup = true +icon_position = left diff --git a/users/tazjin/dotfiles/fuzzel.ini b/users/tazjin/dotfiles/fuzzel.ini new file mode 100644 index 000000000000..92d46c0b6d88 --- /dev/null +++ b/users/tazjin/dotfiles/fuzzel.ini @@ -0,0 +1,17 @@ +[main] +font=Arial + +[colors] +background=c0c0c0ff +text=000000ff +input=000000ff +prompt=000000ff +match=808080ff +selection=000080ff +selection-match=ffffffff +selection-text=ffffffff +border=080808ff + +[border] +width=2 +radius=5 diff --git a/users/tazjin/dotfiles/niri.config.kdl b/users/tazjin/dotfiles/niri.config.kdl new file mode 100644 index 000000000000..8873404f7ec4 --- /dev/null +++ b/users/tazjin/dotfiles/niri.config.kdl @@ -0,0 +1,137 @@ +// https://github.com/YaLTeR/niri/wiki/Configuration:-Overview + +input { + keyboard { + xkb { + layout "us,ru" + variant "hyper" + options "grp:win_space_toggle,compose:ralt,caps:hyper" + } + } + + touchpad { + tap + } + + trackball { + left-handed + } +} + +layout { + gaps 12 + center-focused-column "never" + + preset-column-widths { + proportion 0.33333 + proportion 0.5 + proportion 0.66667 + } + + default-column-width {} + + focus-ring { + off + } + + border { + off + } +} + +spawn-at-startup "xwayland-satellite" +spawn-at-startup "xrandr --output eDP-1 --primary" +spawn-at-startup "wpaperd" "-d" +spawn-at-startup "systemctl --user start xss-lock" + +environment { + QT_QPA_PLATFORM "wayland" + DISPLAY ":0" + EDITOR "emacsclient" +} + +hotkey-overlay { + skip-at-startup +} + +screenshot-path "~/screenshots/screenshot-%Y-%m-%d_%H-%M-%S.png" + +animations { + slowdown 0.3 +} + +binds { + Mod+Shift+Slash { show-hotkey-overlay; } + + Mod+T { spawn "emacsclient" "--no-wait" "--create-frame" "--eval" "(vterm)"; } + Mod+Shift+T { spawn "alacritty"; } // fallback terminal + Mod+D { spawn "xfce4-appfinder" "--disable-server"; } + Super+Alt+L { spawn "swaylock" "-fFkl" "-c" "#008080"; } + Super+B { spawn "emacsclient" "-e" "(niri-go-anywhere-external)"; } + + // Volume control + XF86AudioRaiseVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1+"; } + XF86AudioLowerVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1-"; } + XF86AudioMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; } + XF86AudioMicMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; } + + // Brightness control + XF86MonBrightnessUp allow-when-locked=true { spawn "light" "-A" "5"; } + Shift+XF86MonBrightnessUp allow-when-locked=true { spawn "light" "-A" "1"; } + XF86MonBrightnessDown allow-when-locked=true { spawn "light" "-U" "5"; } + Shift+XF86MonBrightnessDown allow-when-locked=true { spawn "light" "-U" "1"; } + + Mod+Q { close-window; } + + Mod+Left { focus-column-or-monitor-left; } + Mod+Right { focus-column-or-monitor-right; } + Mod+Down { focus-column-or-monitor-right; } + Mod+Up { focus-column-or-monitor-left; } + Mod+J { focus-column-or-monitor-left; } + Mod+K { focus-column-or-monitor-right; } + Mod+L { focus-window-up; } + Mod+Semicolon { focus-window-down; } + + Mod+Ctrl+Left { move-column-left-or-to-monitor-left; } + Mod+Ctrl+Right { move-column-right-or-to-monitor-right; } + Mod+Ctrl+J { move-column-left-or-to-monitor-left; } + Mod+Ctrl+K { move-column-right-or-to-monitor-right; } + + Mod+Home { focus-column-first; } + Mod+End { focus-column-last; } + + Mod+Ctrl+Home { move-column-to-first; } + Mod+Ctrl+End { move-column-to-last; } + + // Scroll (or move windows) between columns when holding the modifier down. + Mod+WheelScrollDown cooldown-ms=150 { focus-column-or-monitor-right; } + Mod+WheelScrollUp cooldown-ms=150 { focus-column-or-monitor-left; } + Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-right-or-to-monitor-right; } + Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-left-or-to-monitor-left; } + + Mod+Comma { consume-window-into-column; } + Mod+Period { expel-window-from-column; } + + // There are also commands that consume or expel a single window to the side. + // Mod+BracketLeft { consume-or-expel-window-left; } + // Mod+BracketRight { consume-or-expel-window-right; } + + Mod+R { switch-preset-column-width; } + Mod+Shift+R { reset-window-height; } + Mod+F { maximize-column; } + Mod+Shift+F { fullscreen-window; } + Mod+C { center-column; } + + Mod+Minus { set-column-width "-10%"; } + Mod+Equal { set-column-width "+10%"; } + + // Finer height adjustments when in column with other windows. + Mod+Shift+Minus { set-window-height "-2%"; } + Mod+Shift+Equal { set-window-height "+2%"; } + + Print { screenshot; } + Ctrl+Print { screenshot-screen; } + Alt+Print { screenshot-window; } + + Mod+Shift+E { quit; } +} diff --git a/users/tazjin/dotfiles/waybar/config.nix b/users/tazjin/dotfiles/waybar/config.nix new file mode 100644 index 000000000000..ba5281f02e07 --- /dev/null +++ b/users/tazjin/dotfiles/waybar/config.nix @@ -0,0 +1,64 @@ +{ depot, pkgs, ... }: + +let + launcher = "${pkgs.xfce4-appfinder}/bin/xfce4-appfinder --disable-server"; +in +{ + mainBar = { + layer = "top"; + position = "bottom"; + modules-left = [ "custom/start" "wlr/taskbar" ]; + + "custom/start" = { + format = " Start"; + on-click = "xfce4-appfinder --disable-server"; + }; + + modules-right = [ "tray" "backlight" "battery" "pulseaudio" "clock" ]; + + pulseaudio = { + on-click = "pavucontrol"; + format = " "; #styling only + states = { + low = 1; + medium = 40; + high = 75; + }; + }; + + battery = { + format = " "; # styling only + interval = 10; + states = { + full = 100; + good = 85; + medium = 60; + low = 40; + warning = 20; + critical = 10; + }; + }; + + backlight = { + format = "{percent}%"; # styling only + on-scroll-up = "light -A 1"; + on-scroll-down = "light -U 1"; + }; + + clock.format-alt = "{:%a, %d. %b %H:%M}"; + + tray = { + icon-size = 20; + spacing = 10; + }; + + "wlr/taskbar" = { + format = "{icon} {title}"; + on-click = "activate"; + rewrite = { + # Truncate any format over 16 characters. + "^(.{16}).+$" = "$1…"; + }; + }; + }; +} diff --git a/users/tazjin/dotfiles/waybar/style.css b/users/tazjin/dotfiles/waybar/style.css new file mode 100644 index 000000000000..52f5759cc796 --- /dev/null +++ b/users/tazjin/dotfiles/waybar/style.css @@ -0,0 +1,254 @@ +* { + /* `otf-font-awesome` is required to be installed for icons */ + font-family: FontAwesome, MS Sans Serif; + font-size: 14px; +} + +window#waybar { + background-color: #c0c0c0; + border-top: 0.1875em solid #dfdfdf; + color: #000000; + transition-property: background-color; + transition-duration: .5s; +} + +window#waybar.hidden { + opacity: 0.2; +} + +window#waybar.termite { + background-color: #3F3F3F; +} + +window#waybar.chromium { + background-color: #000000; + border: none; +} + +button { + /* Use box-shadow instead of border so the text isn't offset */ + box-shadow: inset 0 -0.1875em transparent; + /* Avoid rounded borders under each button name */ + border: none; + border-radius: 0; +} + +/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ +button:hover { + background: inherit; + box-shadow: inset 0 -0.1875em #ffffff; +} + +#mode { + background-color: #64727D; + box-shadow: inset 0 -0.1875em #ffffff; +} + +#clock, +#battery, +#cpu, +#memory, +#disk, +#temperature, +#backlight, +#network, +#pulseaudio, +#wireplumber, +#custom-media, +#tray, +#mode, +#idle_inhibitor, +#scratchpad, +#power-profiles-daemon, +#mpd { + padding: 0 0.3125em; + padding-top: 0em; + padding-bottom: 0em; + /* color: #ffffff; */ +} + +#window, +#workspaces { + margin: 0 0.25em; +} + +/* faithful-ish recreation of the old Windows start button ... */ +#custom-start { + /* general positioning to keep the spacing approximately correct */ + color: @button_text_color; + font-weight: bold; + margin: 0.2em; + margin-top: 0.35em; + padding: 0.2em; + padding-left: 1.25em; + + /* raised button look, as per the Chicago95 GTK button style */ + border: 0.1em solid; + border-radius: 0em; + color: @button_text_color; + outline-color: @outline_color; + border-top-color: @border_bright; + border-right-color: @border_dark; + border-left-color: @border_bright; + border-bottom-color: @border_dark; + background-color: @button_bg_color; + box-shadow: inset -0.1em -0.1em @border_shade, inset 0.1em 0.1em @border_light; + + /* the actual image! */ + background-image: url("${CHICAGO95}/share/icons/Chicago95/categories/scalable/xfdesktop-menu.svg"); + background-position: 0.15em center; + background-repeat: no-repeat; + background-size: 1.4em; +} + +.modules-right { + margin: 0.2em; + margin-top: 0.35em; +} + +#clock { + border-top: 0.1em solid gray; + border-left: 0.1em solid gray; + border-right: 0.1em solid white; + border-bottom: 0.1em solid white; +} + +/* base setup for classes that have a Chicago95 icon as the display */ +#battery, #pulseaudio, #backlight { + background-position: center; + background-repeat: no-repeat; + background-size: 24px; + min-width: 24px; + color: transparent; /* because the tooltips are still desirable */ +} + +#backlight { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/32/xfpm-brightness-lcd.png"); + font-size: 0px; +} + +/* battery levels matching Chicago95 icons */ + +#battery.charging.critical { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-000-charging.png"); +} + +#battery.charging.warning { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-020-charging.png"); +} + +#battery.charging.low { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-040-charging.png"); +} + +#battery.charging.medium { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-060-charging.png"); +} + +#battery.charging.good { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-080-charging.png"); +} + +#battery.charging.full { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-100-charging.png"); +} + +#battery.critical { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-000.png"); +} + +#battery.warning { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-020.png"); +} + +#battery.low { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-040.png"); +} + +#battery.medium { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-060.png"); +} + +#battery.good { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-080.png"); +} + +#battery.full { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/48/battery-100.png"); +} + +/* volume levels matching Chicago95 icons */ + +#pulseaudio.muted { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/32/audio-volume-muted.png"); +} + +#pulseaudio.low { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/32/audio-volume-low.png"); +} + +#pulseaudio.medium { + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/32/audio-volume-medium.png"); +} + +#pulseaudio { /* default, if no lower volume state is set */ + background-image: url("${CHICAGO95}/share/icons/Chicago95/status/32/audio-volume-high.png"); +} + +@keyframes blink { + to { + background-color: #ffffff; + color: #000000; + } +} + +label:focus { + background-color: #000000; +} + +#tray > .passive { + -gtk-icon-effect: dim; +} + +#tray > .needs-attention { + -gtk-icon-effect: highlight; + background-color: #e35f5f; +} + +#idle_inhibitor { + background-color: #2d3436; +} + +#idle_inhibitor.activated { + background-color: #ecf0f1; + color: #2d3436; +} + +#taskbar { + color: @button_text_color; + margin: 0.2em; + margin-top: 0.35em; +} + +#taskbar button { + padding: 0.2em; + margin-right: 0.3em; + border: 0.1em solid; + border-radius: 0em; + color: @button_text_color; + outline-color: @outline_color; + border-top-color: @border_bright; + border-right-color: @border_dark; + border-left-color: @border_bright; + border-bottom-color: @border_dark; + background-color: @button_bg_color; + box-shadow: inset -0.1em -0.1em @border_shade, inset 0.1em 0.1em @border_light; +} + +#taskbar button.active { + border-top-color: @border_dark; + border-right-color: @border_bright; + border-left-color: @border_dark; + border-bottom-color: @border_bright; + box-shadow: inset 1px 1px @border_shade; +} diff --git a/users/tazjin/eaglemode/default.nix b/users/tazjin/eaglemode/default.nix new file mode 100644 index 000000000000..9f59695a40b8 --- /dev/null +++ b/users/tazjin/eaglemode/default.nix @@ -0,0 +1,16 @@ +# Derivation for my fully configured Eagle Mode. +{ depot, ... }: + +with depot.tools.eaglemode; + +withConfig { + config = etcDir { + extraPaths = [ + commands.emacsclient + plugins.example + plugins.yatracker + plugins.qoi + plugins.avif + ]; + }; +} diff --git a/users/tazjin/emacs/config/init.el b/users/tazjin/emacs/config/init.el index ced3bf2ff83b..89aefdca4750 100644 --- a/users/tazjin/emacs/config/init.el +++ b/users/tazjin/emacs/config/init.el @@ -29,6 +29,10 @@ (use-package browse-kill-ring) +(use-package company + :config + (global-company-mode)) + (use-package consult :bind ("C-c r g" . consult-ripgrep) @@ -68,11 +72,20 @@ (prescient-persist-mode) (setq completion-styles '(basic prescient))) +(use-package vertico-prescient + :config + (vertico-prescient-mode)) + +(use-package company-prescient + :config + (company-prescient-mode)) + (use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode)) (use-package rainbow-mode) (use-package s) (use-package string-edit-at-point) -(use-package term-switcher) +(use-package term-switcher + :bind (:map global-map ("C-c v" . #'ts/switch-to-terminal))) (use-package undo-tree :config (global-undo-tree-mode) @@ -126,12 +139,9 @@ (use-package f) -(use-package go-mode - :bind (:map go-mode-map ("C-c C-r" . recompile)) - :hook ((go-mode . (lambda () - (setq tab-width 2) - (setq-local compile-command - (concat "go build " buffer-file-name)))))) +(use-package go-ts-mode + :custom + (go-ts-mode-indent-offset 4)) (use-package haskell-mode) @@ -152,6 +162,7 @@ (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))) (use-package markdown-toc) +(use-package niri) (use-package nix-mode :hook ((nix-mode . (lambda () @@ -169,7 +180,7 @@ (setq common-lisp-hyperspec-root "file:///home/tazjin/docs/lisp/")) (use-package telega - :bind (:map global-map ("s-c" . (lambda (p) (interactive "P") + :bind (:map global-map ("C-x c" . (lambda (p) (interactive "P") (if p (call-interactively #'telega-chat-with) (telega)))) :map telega-chat-button-map ("a" . ignore)) @@ -241,8 +252,7 @@ ;; Load all other Emacs configuration. These configurations are ;; added to `load-path' by Nix. -(mapc 'require '(desktop - mail-setup +(mapc 'require '(mail-setup look-and-feel functions settings diff --git a/users/tazjin/emacs/config/settings.el b/users/tazjin/emacs/config/settings.el index 6c66ca608d6e..afe181b70bdf 100644 --- a/users/tazjin/emacs/config/settings.el +++ b/users/tazjin/emacs/config/settings.el @@ -19,6 +19,9 @@ ediff-split-window-function 'split-window-horizontally initial-major-mode 'emacs-lisp-mode) +(setq-default tab-width 4) +(setq-default fill-column 80) + (add-to-list 'safe-local-variable-values '(lexical-binding . t)) (add-to-list 'safe-local-variable-values '(whitespace-line-column . 80)) diff --git a/users/tazjin/emacs/default.nix b/users/tazjin/emacs/default.nix index 46843432f189..b07ca2927f44 100644 --- a/users/tazjin/emacs/default.nix +++ b/users/tazjin/emacs/default.nix @@ -3,14 +3,14 @@ { depot, lib, pkgs, ... }: pkgs.makeOverridable - ({ emacs ? pkgs.emacs29 }: + ({ emacs ? pkgs.emacs29-pgtk }: let emacsPackages = (pkgs.emacsPackagesFor emacs); emacsWithPackages = emacsPackages.emacsWithPackages; # If switching telega versions, use this variable because it will # keep the version check, binary path and so on in sync. - currentTelega = epkgs: epkgs.melpaPackages.telega; + currentTelega = epkgs: epkgs.telega; # $PATH for binaries that need to be available to Emacs emacsBinPath = lib.makeBinPath [ @@ -41,6 +41,7 @@ pkgs.makeOverridable tree-sitter-rust tree-sitter-sql tree-sitter-toml + tree-sitter-typescript tree-sitter-yaml ]); @@ -52,13 +53,14 @@ pkgs.makeOverridable browse-kill-ring cargo clojure-mode + company + company-prescient consult deft direnv elixir-mode elm-mode erlang - depotExwm go-mode google-c-style gruber-darker-theme @@ -92,6 +94,7 @@ pkgs.makeOverridable undo-tree uuidgen vertico + vertico-prescient vterm web-mode websocket @@ -101,17 +104,13 @@ pkgs.makeOverridable zetteldeft zoxide - # experimental (not otherwise embedded in config yet) - orderless - corfu - eat - # Wonky stuff (currentTelega epkgs) customTreesitGrammars # TODO(tazjin): how is this *supposed* to work?! # Custom depot packages (either ours, or overridden ones) tvlPackages.dottime + tvlPackages.niri tvlPackages.nix-util tvlPackages.passively tvlPackages.rcirc @@ -177,8 +176,6 @@ pkgs.makeOverridable # Expose telega/tdlib version check as a target that is built in # CI. - # - # TODO(tazjin): uncomment when telega works again inherit tdlibCheck; meta.ci.targets = [ "tdlibCheck" ]; }; diff --git a/users/tazjin/german-string/.gitignore b/users/tazjin/german-string/.gitignore new file mode 100644 index 000000000000..2f7896d1d136 --- /dev/null +++ b/users/tazjin/german-string/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/users/tazjin/german-string/Cargo.lock b/users/tazjin/german-string/Cargo.lock new file mode 100644 index 000000000000..ffd73ea32472 --- /dev/null +++ b/users/tazjin/german-string/Cargo.lock @@ -0,0 +1,399 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "german-string" +version = "0.1.0" +dependencies = [ + "proptest", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.156" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5f43f184355eefb8d17fc948dbecf6c13be3c141f20d834ae842193a448c72a" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "syn" +version = "2.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/users/tazjin/german-string/Cargo.toml b/users/tazjin/german-string/Cargo.toml new file mode 100644 index 000000000000..8eec963f071a --- /dev/null +++ b/users/tazjin/german-string/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "german-string" +version = "0.1.0" +edition = "2021" + +[dev-dependencies] +proptest = "1.5.0" diff --git a/users/tazjin/german-string/default.nix b/users/tazjin/german-string/default.nix new file mode 100644 index 000000000000..c6cbc8c3c2d0 --- /dev/null +++ b/users/tazjin/german-string/default.nix @@ -0,0 +1,5 @@ +{ depot, pkgs, ... }: + +depot.third_party.naersk.buildPackage { + src = ./.; +} diff --git a/users/tazjin/german-string/src/lib.rs b/users/tazjin/german-string/src/lib.rs new file mode 100644 index 000000000000..328eca309f38 --- /dev/null +++ b/users/tazjin/german-string/src/lib.rs @@ -0,0 +1,435 @@ +use std::alloc::Layout; +use std::cmp::Ordering; +use std::fmt::{Debug, Formatter}; + +#[derive(Clone, Copy)] +#[repr(C)] +struct GSSmall { + len: u32, + data: [u8; 12], +} + +#[derive(Clone, Copy)] +#[repr(transparent)] +struct StorageClassPtr(usize); + +impl StorageClassPtr { + fn transient(ptr: *const u8) -> Self { + debug_assert!( + (ptr as usize & 0b1) == 0, + "pointer must be at least 2-byte aligned" + ); + Self(ptr as usize) + } + + fn persistent(ptr: *const u8) -> Self { + debug_assert!( + (ptr as usize & 0b1) == 0, + "pointer must be at least 2-byte aligned" + ); + Self((ptr as usize) | 0b1) + } + + fn as_ptr(&self) -> *const u8 { + (self.0 & !0b1) as *const u8 + } + + unsafe fn as_mut_ptr(&self) -> *mut u8 { + (self.0 & !0b1) as *mut u8 + } + + fn is_transient(&self) -> bool { + (self.0 & 0b1) == 0 + } +} + +#[derive(Clone, Copy)] +#[repr(C)] +struct GSLarge { + len: u32, + prefix: [u8; 4], + data: StorageClassPtr, +} + +const _ASSERT_VARIANTS_SIZE: () = assert!( + std::mem::size_of::<GSSmall>() == std::mem::size_of::<GSLarge>(), + "German String variants must have the same size" +); + +union GSRepr { + small: GSSmall, + large: GSLarge, +} + +#[repr(transparent)] +pub struct GermanString(GSRepr); + +const _ASSERT_GSTRING_SIZE: () = assert!( + std::mem::size_of::<GermanString>() == 16, + "German String should be 16 bytes in size", +); + +impl GermanString { + /// Creates a new transient German String from the given slice, copying the + /// data in the process. + pub fn transient(bytes: &[u8]) -> GermanString { + if bytes.len() > u32::MAX as usize { + panic!("GermanString maximum length is {} bytes", u32::MAX); + } + + if bytes.len() <= 12 { + let mut s = GSSmall { + len: bytes.len() as u32, + data: [0u8; 12], + }; + s.data[..bytes.len()].copy_from_slice(bytes); + GermanString(GSRepr { small: s }) + } else { + let layout = Layout::array::<u8>(bytes.len()).unwrap(); + let mut large = GSLarge { + len: bytes.len() as u32, + prefix: [0u8; 4], + data: unsafe { + let ptr = std::alloc::alloc(layout); + if ptr.is_null() { + std::alloc::handle_alloc_error(layout); + } + std::ptr::copy_nonoverlapping(bytes.as_ptr(), ptr, bytes.len()); + StorageClassPtr::transient(ptr) + }, + }; + + large.prefix.copy_from_slice(&bytes[..4]); + + GermanString(GSRepr { large }) + } + } + + /// Creates a new transient German String from the given owned bytes. Short + /// strings will be copied into the string representation, long strings will + /// be moved out of the given vector without additional allocations. + pub fn transient_from_owned(bytes: Vec<u8>) -> GermanString { + if bytes.len() > u32::MAX as usize { + panic!("GermanString maximum length is {} bytes", u32::MAX); + } + + if bytes.len() <= 12 { + let mut s = GSSmall { + len: bytes.len() as u32, + data: [0u8; 12], + }; + + s.data[..bytes.len()].copy_from_slice(&bytes); + GermanString(GSRepr { small: s }) + } else { + let md = std::mem::ManuallyDrop::new(bytes); + let mut large = GSLarge { + len: md.len() as u32, + prefix: [0u8; 4], + data: StorageClassPtr::transient(md.as_ptr()), + }; + + large.prefix.copy_from_slice(&md[..4]); + GermanString(GSRepr { large }) + } + } + + /// Creates a persistent German String from a static data buffer. + pub fn persistent(bytes: &'static [u8]) -> GermanString { + if bytes.len() > u32::MAX as usize { + panic!("GermanString maximum length is {} bytes", u32::MAX); + } + + if bytes.len() <= 12 { + let mut s = GSSmall { + len: bytes.len() as u32, + data: [0u8; 12], + }; + + s.data[..bytes.len()].copy_from_slice(&bytes); + GermanString(GSRepr { small: s }) + } else { + let mut large = GSLarge { + len: bytes.len() as u32, + prefix: [0u8; 4], + data: StorageClassPtr::persistent(bytes.as_ptr()), + }; + + large.prefix.copy_from_slice(&bytes[..4]); + GermanString(GSRepr { large }) + } + } + + /// Creates a persistent German String by leaking the provided data. + pub fn persistent_leak(bytes: Vec<u8>) -> GermanString { + if bytes.len() > u32::MAX as usize { + panic!("GermanString maximum length is {} bytes", u32::MAX); + } + + if bytes.len() <= 12 { + let mut s = GSSmall { + len: bytes.len() as u32, + data: [0u8; 12], + }; + + s.data[..bytes.len()].copy_from_slice(&bytes); + GermanString(GSRepr { small: s }) + } else { + let md = std::mem::ManuallyDrop::new(bytes); + let mut large = GSLarge { + len: md.len() as u32, + prefix: [0u8; 4], + data: StorageClassPtr::persistent(md.as_ptr()), + }; + + large.prefix.copy_from_slice(&md[..4]); + GermanString(GSRepr { large }) + } + } + + /// Creates a persistent German String from a static data buffer. + pub fn persistent_from_str(s: &'static str) -> GermanString { + GermanString::persistent(s.as_bytes()) + } + + pub fn len(&self) -> usize { + // SAFETY: The length field is located in the same location for both + // variants, reading it from either is safe. + unsafe { self.0.small.len as usize } + } + + pub fn as_bytes(&self) -> &[u8] { + if self.len() > 12 { + unsafe { std::slice::from_raw_parts(self.0.large.data.as_ptr(), self.len()) } + } else { + unsafe { &self.0.small.data.as_ref()[..self.len()] } + } + } + + pub fn as_str(&self) -> Result<&str, std::str::Utf8Error> { + std::str::from_utf8(self.as_bytes()) + } +} + +impl Drop for GermanString { + fn drop(&mut self) { + unsafe { + if self.len() > 12 && self.0.large.data.is_transient() { + let layout = Layout::array::<u8>(self.len()).unwrap(); + std::alloc::dealloc(self.0.large.data.as_mut_ptr(), layout); + } + } + } +} + +impl PartialEq for GermanString { + fn eq(&self, other: &GermanString) -> bool { + if self.len() != other.len() { + return false; + } + + unsafe { + if self.len() <= 12 { + return self.0.small.data[..self.len()] == other.0.small.data[..other.len()]; + } + return self.0.large.data.as_ptr() == other.0.large.data.as_ptr() + || (self.0.large.prefix == other.0.large.prefix + && self.as_bytes() == other.as_bytes()); + } + } +} + +impl Eq for GermanString {} + +impl Ord for GermanString { + fn cmp(&self, other: &GermanString) -> Ordering { + match (self.len().cmp(&12), other.len().cmp(&12)) { + // two small strings + (Ordering::Less | Ordering::Equal, Ordering::Less | Ordering::Equal) => unsafe { + self.0.small.data[..self.len()].cmp(&other.0.small.data[..other.len()]) + }, + // two large strings + (Ordering::Greater, Ordering::Greater) => unsafe { + match self.0.large.prefix.cmp(&other.0.large.prefix) { + Ordering::Equal => self.as_bytes().cmp(other.as_bytes()), + ordering => ordering, + } + }, + + // LHS large, RHS small + (Ordering::Greater, _) => { + let prefix_ordering = + unsafe { self.0.large.prefix.as_slice().cmp(&other.0.small.data[..4]) }; + + if prefix_ordering != Ordering::Equal { + return prefix_ordering; + } + + self.as_bytes().cmp(other.as_bytes()) + } + + // LHS small, RHS large + (_, Ordering::Greater) => { + let prefix_ordering = + unsafe { self.0.small.data[..4].cmp(other.0.large.prefix.as_slice()) }; + + if prefix_ordering != Ordering::Equal { + return prefix_ordering; + } + + self.as_bytes().cmp(other.as_bytes()) + } + } + } +} + +impl PartialOrd for GermanString { + fn partial_cmp(&self, other: &GermanString) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Debug for GermanString { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + String::from_utf8_lossy(self.as_bytes()).fmt(f) + } +} + +impl Clone for GermanString { + fn clone(&self) -> Self { + unsafe { + if self.len() <= 12 { + return GermanString(GSRepr { + small: self.0.small.clone(), + }); + } + + if self.0.large.data.is_transient() { + return GermanString::transient(self.as_bytes()); + } + + return GermanString(GSRepr { + large: self.0.large.clone(), + }); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use proptest::prelude::*; + + impl Arbitrary for GermanString { + type Parameters = <String as Arbitrary>::Parameters; + type Strategy = BoxedStrategy<Self>; + + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { + any_with::<String>(args) + .prop_map(|s| GermanString::transient(s.as_bytes())) + .boxed() + } + } + + #[test] + fn test_empty_string() { + let empty = GermanString::transient(b""); + + assert_eq!(empty.len(), 0, "empty string should be empty"); + assert_eq!(empty.as_bytes(), b"", "empty string should contain nothing"); + assert_eq!( + empty.as_str().expect("empty string is valid UTF-8"), + "", + "empty string should contain empty string" + ); + } + + #[test] + fn test_short_string() { + let short = GermanString::transient(b"meow"); + + assert_eq!(short.len(), 4, "'meow' is four characters"); + assert_eq!( + short.as_bytes(), + b"meow", + "short string returns correct bytes" + ); + assert_eq!( + short.as_str().expect("'meow' is valid UTF-8"), + "meow", + "short string returns correct string" + ); + } + + #[test] + fn test_long_string() { + let input: &str = "This code was written at https://signal.live"; + let long = GermanString::transient(input.as_bytes()); + + assert_eq!(long.len(), 44, "long string has correct length"); + assert_eq!( + long.as_bytes(), + input.as_bytes(), + "long string returns correct bytes" + ); + + assert_eq!( + long.as_str().expect("input is valid UTF-8"), + input, + "long string returns correct string" + ); + } + + proptest! { + #[test] + fn test_roundtrip_vec(input: Vec<u8>) { + let gs = GermanString::transient_from_owned(input.clone()); + assert_eq!(input.len(), gs.len(), "length should match"); + + let out = gs.as_bytes().to_owned(); + assert_eq!(input, out, "roundtrip should yield same bytes"); + } + + #[test] + fn test_roundtrip_string(input: String) { + let gs = GermanString::transient_from_owned(input.clone().into_bytes()); + assert_eq!(input.len(), gs.len(), "length should match"); + + let out = String::from_utf8(gs.as_bytes().to_owned()) + .expect("string should be valid after roundtrip"); + + assert_eq!(input, out, "roundtrip should yield same string"); + } + + // Test [`Eq`] implementation. + #[test] + fn test_eq(lhs: Vec<u8>, rhs: Vec<u8>) { + let lhs_gs = GermanString::transient(lhs.as_slice()); + let rhs_gs = GermanString::transient(rhs.as_slice()); + + assert_eq!( + (lhs == rhs), + (lhs_gs == rhs_gs), + "Eq should match between std::String and GermanString ({:?} == {:?})", + lhs, rhs, + ); + } + + #[test] + fn test_reflexivity(x: GermanString) { + prop_assert!(x == x); + } + + #[test] + fn test_symmetry(x: GermanString, y: GermanString) { + prop_assert_eq!(x == y, y == x); + } + + #[test] + fn test_transitivity(x: GermanString, y: GermanString, z: GermanString) { + if x == y && y == z { + assert!(x == z); + } + } + } +} diff --git a/users/tazjin/home/arbat.nix b/users/tazjin/home/arbat.nix new file mode 100644 index 000000000000..83daf2012ca0 --- /dev/null +++ b/users/tazjin/home/arbat.nix @@ -0,0 +1,11 @@ +# Home manage configuration for arbat. + +{ depot, pkgs, ... }: # readTree +{ config, lib, ... }: # home-manager + +{ + imports = [ + depot.users.tazjin.home.shared + depot.users.tazjin.home.persistence + ]; +} diff --git a/users/tazjin/home/shared.nix b/users/tazjin/home/shared.nix index 38d8add4ac2f..51ff1ac94af5 100644 --- a/users/tazjin/home/shared.nix +++ b/users/tazjin/home/shared.nix @@ -5,6 +5,8 @@ let + inherit (depot.third_party) chicago95; + # URL handler to open `tg://` URLs in telega.el telega-launcher = pkgs.writeShellScriptBin "telega-launcher" '' echo "Opening ''${1} in telega.el ..." @@ -38,12 +40,6 @@ in ''; }; - services.screen-locker = { - enable = true; - inactiveInterval = 10; # minutes - lockCmd = "${depot.users.tazjin.screenLock}/bin/tazjin-screen-lock"; - }; - home.packages = [ telega-launcher ]; xdg.desktopEntries.telega-launcher = { @@ -65,13 +61,40 @@ in }; }; - services.picom = { + # put Niri (& related tools) configuration in place + xdg.configFile."niri/config.kdl".source = depot.users.tazjin.dotfiles.niri; + xdg.configFile."fuzzel/fuzzel.ini".source = depot.users.tazjin.dotfiles.fuzzel; + + programs.wpaperd = { + enable = true; + settings = { + default = { + duration = "1d"; + mode = "center"; + sorting = "random"; + }; + + any.path = ../wallpapers; + }; + }; + + programs.waybar = { enable = true; - vSync = true; - backend = "glx"; + settings = depot.users.tazjin.dotfiles.waybar.config; + style = depot.users.tazjin.dotfiles.waybar.style; + systemd.enable = true; }; + systemd.user.services.waybar.Unit.After = lib.mkForce [ "niri.service" ]; - services.syncthing.enable = true; + + services.swayidle = let cmd = "${pkgs.swaylock}/bin/swaylock -fFkl -c 008080"; in { + enable = true; + events = [ + { event = "before-sleep"; command = cmd; } + { event = "lock"; command = cmd; } + ]; + }; + systemd.user.services.swayidle.Unit.After = lib.mkForce [ "niri.service" ]; # Enable the dunst notification daemon, but force the # configuration file separately instead of going via the strange @@ -84,6 +107,18 @@ in ''; }; + gtk = { + enable = true; + theme.name = "Chicago95"; + theme.package = chicago95; + + iconTheme.name = "Chicago95-tux"; + iconTheme.package = chicago95; + + cursorTheme.name = lib.mkDefault "Chicago95_Animated_Hourglass_Cursors"; + cursorTheme.package = chicago95; + }; + systemd.user.startServices = true; # Previous default version, see https://github.com/nix-community/home-manager/blob/master/docs/release-notes/rl-2211.adoc diff --git a/users/tazjin/home/zamalek.nix b/users/tazjin/home/zamalek.nix index d24de945bb28..98da5e6b233e 100644 --- a/users/tazjin/home/zamalek.nix +++ b/users/tazjin/home/zamalek.nix @@ -8,4 +8,6 @@ depot.users.tazjin.home.shared depot.users.tazjin.home.persistence ]; + + gtk.cursorTheme.name = lib.mkForce "Chicago95_Animated_Hourglass_Cursors_HiDPI"; } diff --git a/users/tazjin/keys/default.nix b/users/tazjin/keys/default.nix index 16b232b09435..300cd49e89de 100644 --- a/users/tazjin/keys/default.nix +++ b/users/tazjin/keys/default.nix @@ -9,4 +9,5 @@ in withAll { zamalek_ed25519 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDBRXeb8EuecLHP0bW4zuebXp4KRnXgJTZfeVWXQ1n1R tazjin@zamalek"; khamovnik_yk = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPgOyR4rRM8IaVGgN2ZxGlKtd7GLYbxdRTRa3u9EhRNSkHAvRTN9sgw7mm0iPLnHChPy10anKV43vTaIm906Gm8="; khamovnik_agenix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG4YSl5+DHQR3rOoBJLQfQ840U0CrYkByMKdzu/LDxoT tazjin@khamovnik"; + arbat = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ1Eai0p7eF7XML5wokqF4GlVZM+YXEORfs/GPGwEky7 tazjin@arbat"; } diff --git a/users/tazjin/niri-reap/.gitignore b/users/tazjin/niri-reap/.gitignore new file mode 100644 index 000000000000..2f7896d1d136 --- /dev/null +++ b/users/tazjin/niri-reap/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/users/tazjin/niri-reap/Cargo.lock b/users/tazjin/niri-reap/Cargo.lock new file mode 100644 index 000000000000..e7916c5b3acd --- /dev/null +++ b/users/tazjin/niri-reap/Cargo.lock @@ -0,0 +1,104 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "niri-ipc" +version = "0.1.9" +source = "git+https://github.com/YaLTeR/niri.git#6a48728ffb1e638839b07f9ab2f06b2adb41dc61" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "niri-reap" +version = "0.1.0" +dependencies = [ + "niri-ipc", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" diff --git a/users/tazjin/niri-reap/Cargo.toml b/users/tazjin/niri-reap/Cargo.toml new file mode 100644 index 000000000000..5f6677196333 --- /dev/null +++ b/users/tazjin/niri-reap/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "niri-reap" +version = "0.1.0" +edition = "2021" + +[dependencies] +niri-ipc = { git = "https://github.com/YaLTeR/niri.git", version = "0.1.9" } diff --git a/users/tazjin/niri-reap/README.md b/users/tazjin/niri-reap/README.md new file mode 100644 index 000000000000..207a087657fa --- /dev/null +++ b/users/tazjin/niri-reap/README.md @@ -0,0 +1,20 @@ +niri-reap +========= + +Tiny, MIT-licensed companion program for [niri](https://github.com/YaLTeR/niri). + +I don't use workspaces in my workflow, but when disconnecting an external +screen, the workspaces that it was displaying are moved to the remaining screen. + +This program "reaps" all windows on workspaces except the currently active one, +and moves them all to the current workspace. + +## Usage + +If you have the full TVL monorepo, just `mg run //users/tazjin/niri-reap`. There +is no configuration, and there are no flags. + +If you don't have the TVL monorepo and just want `niri-reap`, do this: + +1. Get the code: `git clone https://code.tvl.fyi/depot.git:/users/tazjin/niri-reap.git` +2. Run the code: `cargo run` diff --git a/users/tazjin/niri-reap/default.nix b/users/tazjin/niri-reap/default.nix new file mode 100644 index 000000000000..80c82f475a2f --- /dev/null +++ b/users/tazjin/niri-reap/default.nix @@ -0,0 +1,13 @@ +{ depot, pkgs, ... }: + +pkgs.rustPlatform.buildRustPackage { + name = "niri-reap"; + src = depot.third_party.gitignoreSource ./.; + + cargoLock = { + lockFile = ./Cargo.lock; + outputHashes = { + "niri-ipc-0.1.9" = "sha256:1s294bw62mmckq9xyfzgw4p2nvkzday4k276j60m668prhlfp071"; + }; + }; +} diff --git a/users/tazjin/niri-reap/src/main.rs b/users/tazjin/niri-reap/src/main.rs new file mode 100644 index 000000000000..315a5015d413 --- /dev/null +++ b/users/tazjin/niri-reap/src/main.rs @@ -0,0 +1,93 @@ +use niri_ipc::socket::Socket; +use niri_ipc::{Action, Reply, Request, Response, Window, Workspace}; + +fn sock() -> Socket { + Socket::connect().expect("could not connect to Niri socket") +} + +fn list_workspaces() -> Vec<Workspace> { + let (reply, _) = sock() + .send(Request::Workspaces) + .expect("failed to send workspace request"); + + match reply { + Reply::Err(err) => panic!("failed to list workspaces: {}", err), + Reply::Ok(Response::Workspaces(w)) => w, + Reply::Ok(other) => panic!("unexpected reply from Niri: {:#?}", other), + } +} + +fn list_windows() -> Vec<Window> { + let (reply, _) = sock() + .send(Request::Windows) + .expect("failed to send window request"); + + match reply { + Reply::Err(err) => panic!("failed to list windows: {}", err), + Reply::Ok(Response::Windows(w)) => w, + Reply::Ok(other) => panic!("unexpected reply from Niri: {:#?}", other), + } +} + +fn reap_window(window: u64, workspace: u64) { + let (reply, _) = sock() + .send(Request::Action(Action::MoveWindowToWorkspace { + window_id: Some(window), + reference: niri_ipc::WorkspaceReferenceArg::Id(workspace), + })) + .expect("failed to send window move request"); + + reply.expect("failed to move window to workspace"); +} + +fn get_active_workspace(workspaces: &[Workspace]) -> &Workspace { + workspaces + .iter() + .filter(|w| w.is_focused) + .next() + .expect("expected an active workspace") +} + +fn move_workspace_up() { + let (result, _) = sock() + .send(Request::Action(Action::MoveWorkspaceUp {})) + .expect("failed to send workspace move command"); + + result.expect("failed to move workspace up"); +} + +fn main() { + let mut workspaces = list_workspaces(); + let mut active_workspace = get_active_workspace(&workspaces); + + // Ensure that the current workspace is the first one, to avoid issues with + // indices changing during the window moves. + while active_workspace.idx > 1 { + move_workspace_up(); + workspaces = list_workspaces(); + active_workspace = get_active_workspace(&workspaces); + } + + let orphan_workspaces = workspaces + .iter() + .filter(|w| w.output == active_workspace.output) + .filter(|w| w.idx > 1) + .map(|w| w.id) + .collect::<Vec<_>>(); + + if orphan_workspaces.is_empty() { + return; + } + + let reapable = list_windows() + .into_iter() + .filter(|w| match w.workspace_id { + Some(id) => orphan_workspaces.contains(&id), + None => true, + }) + .collect::<Vec<_>>(); + + for window in reapable.iter().rev() { + reap_window(window.id, active_workspace.id); + } +} diff --git a/users/tazjin/nixos/arbat/default.nix b/users/tazjin/nixos/arbat/default.nix new file mode 100644 index 000000000000..c87aa445c29c --- /dev/null +++ b/users/tazjin/nixos/arbat/default.nix @@ -0,0 +1,72 @@ +# arbat is my Unchartevice 6640MA, with a Zhaoxin CPU. +{ depot, lib, pkgs, ... }: + +config: +let + mod = name: depot.path.origSrc + ("/ops/modules/" + name); + usermod = name: depot.path.origSrc + ("/users/tazjin/nixos/modules/" + name); + + zdevice = device: { + inherit device; + fsType = "zfs"; + }; +in +{ + imports = [ + (usermod "chromium.nix") + (usermod "desktop.nix") + (usermod "fonts.nix") + (usermod "home-config.nix") + (usermod "laptop.nix") + (usermod "persistence.nix") + (usermod "physical.nix") + (pkgs.home-manager.src + "/nixos") + ]; + + tvl.cache.enable = true; + + boot = { + loader.systemd-boot.enable = true; + supportedFilesystems = [ "zfs" ]; + zfs.devNodes = "/dev/"; + # TODO: double-check this list + initrd.availableKernelModules = [ "ahci" "uhci_hcd" "ehci_pci" "xhci_pci" "usb_storage" "sd_mod" "rtsx_usb_sdmmc" ]; + kernelModules = [ "kvm-intel" ]; # interesting + }; + + networking = { + hostName = "arbat"; + hostId = "864f050b"; + networkmanager.enable = true; + }; + + fileSystems = { + "/" = zdevice "zpool/ephemeral/root"; + "/home" = zdevice "zpool/ephemeral/home"; + "/persist" = zdevice "zpool/persistent/data" // { neededForBoot = true; }; + "/nix" = zdevice "zpool/persistent/nix"; + "/depot" = zdevice "zpool/persistent/depot"; + + "/boot" = { + device = "/dev/disk/by-uuid/B3B5-92F7"; + fsType = "vfat"; + }; + }; + + hardware = { + enableRedistributableFirmware = true; + graphics.enable = true; + bluetooth.enable = true; + }; + + # TODO(tazjin): decide on this + services.libinput = { + enable = true; + # libinput thinks the touchpad is a mouse + mouse.naturalScrolling = false; + mouse.disableWhileTyping = true; + }; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + system.stateVersion = "24.11"; +} diff --git a/users/tazjin/nixos/default.nix b/users/tazjin/nixos/default.nix index 8f82c39ea11f..6bca09d8f129 100644 --- a/users/tazjin/nixos/default.nix +++ b/users/tazjin/nixos/default.nix @@ -2,11 +2,14 @@ let systemFor = sys: (depot.ops.nixos.nixosFor sys).system; in depot.nix.readTree.drvTargets { + arbatSystem = systemFor depot.users.tazjin.nixos.arbat; camdenSystem = systemFor depot.users.tazjin.nixos.camden; - frogSystem = systemFor depot.users.tazjin.nixos.frog; tverskoySystem = systemFor depot.users.tazjin.nixos.tverskoy; zamalekSystem = systemFor depot.users.tazjin.nixos.zamalek; koptevoRaw = depot.ops.nixos.nixosFor depot.users.tazjin.nixos.koptevo; koptevoSystem = systemFor depot.users.tazjin.nixos.koptevo; khamovnikSystem = systemFor depot.users.tazjin.nixos.khamovnik; + + # no need to build this while the machine is in storage + # frogSystem = systemFor depot.users.tazjin.nixos.frog; } diff --git a/users/tazjin/nixos/frog/default.nix b/users/tazjin/nixos/frog/default.nix index dfb6b46d5aa1..226886bfba6c 100644 --- a/users/tazjin/nixos/frog/default.nix +++ b/users/tazjin/nixos/frog/default.nix @@ -41,10 +41,9 @@ lib.fix (self: { hardware = { cpu.amd.updateMicrocode = true; enableRedistributableFirmware = true; - opengl = { + graphics = { enable = true; - driSupport = true; - driSupport32Bit = true; + enable32Bit = true; }; pulseaudio = { @@ -110,7 +109,7 @@ lib.fix (self: { corefonts dejavu_fonts jetbrains-mono - noto-fonts-cjk + noto-fonts-cjk-sans noto-fonts-emoji ]; diff --git a/users/tazjin/nixos/khamovnik/default.nix b/users/tazjin/nixos/khamovnik/default.nix index 8ea925c90dd0..dcb19be2ae9f 100644 --- a/users/tazjin/nixos/khamovnik/default.nix +++ b/users/tazjin/nixos/khamovnik/default.nix @@ -43,6 +43,8 @@ in "rtsx_pci_sdmmc" ]; kernelModules = [ "kvm-intel" ]; + + tmp.cleanOnBoot = true; }; fileSystems = { @@ -64,12 +66,13 @@ in tvl.cache.enable = true; networking.hostName = "khamovnik"; + networking.networkmanager.enable = true; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; hardware.cpu.intel.updateMicrocode = true; hardware.enableRedistributableFirmware = true; - hardware.opengl.extraPackages = with pkgs; [ + hardware.graphics.extraPackages = with pkgs; [ intel-compute-runtime intel-media-driver intel-vaapi-driver @@ -104,7 +107,6 @@ in }; # Enable sound with pipewire. - sound.enable = true; hardware.pulseaudio.enable = false; security.rtkit.enable = true; services.pipewire = { @@ -117,6 +119,13 @@ in # Try to work around Intel CPU throttling bugs services.throttled.enable = true; + # Try to get suspend to work more reliably + services.logind = { + lidSwitch = "suspend"; + lidSwitchDocked = "suspend"; + lidSwitchExternalPower = "suspend"; + }; + virtualisation.docker.enable = true; hardware.bluetooth.enable = true; @@ -129,5 +138,7 @@ in protobuf ]; + programs.adb.enable = true; + system.stateVersion = "23.05"; # Did you read the comment? } diff --git a/users/tazjin/nixos/koptevo/default.nix b/users/tazjin/nixos/koptevo/default.nix index ea8dfd4bd809..187f7b92fbb0 100644 --- a/users/tazjin/nixos/koptevo/default.nix +++ b/users/tazjin/nixos/koptevo/default.nix @@ -11,12 +11,12 @@ in imports = [ (mod "quassel.nix") (mod "www/base.nix") - (mod "www/tazj.in.nix") (usermod "airsonic.nix") (usermod "geesefs.nix") + (usermod "homepage.nix") + (usermod "miniflux.nix") (usermod "predlozhnik.nix") (usermod "tgsa.nix") - (usermod "miniflux.nix") (depot.third_party.agenix.src + "/modules/age.nix") ]; @@ -62,7 +62,7 @@ in domain = "tazj.in"; useDHCP = true; firewall.enable = true; - firewall.allowedTCPPorts = [ 22 80 443 ]; + firewall.allowedTCPPorts = [ 22 80 443 8776 9443 ]; wireless.enable = true; wireless.networks."How do I computer fast?" = { @@ -72,8 +72,22 @@ in time.timeZone = "UTC"; - security.acme.acceptTerms = true; - security.acme.defaults.email = lib.mkForce "acme@tazj.in"; + security.acme = { + acceptTerms = true; + defaults.email = lib.mkForce "acme@tazj.in"; + + # wildcard cert for usage with Yggdrasil services + certs."y.tazj.in" = { + dnsProvider = "yandexcloud"; + credentialFiles.YANDEX_CLOUD_IAM_TOKEN_FILE = "/run/agenix/lego-yandex"; + extraDomainNames = [ "*.y.tazj.in" ]; + + # folder tvl/tazjin-private/default + environmentFile = builtins.toFile "lego-yandex-env" '' + YANDEX_CLOUD_FOLDER_ID=b1gq41rsbggeum4qafnh + ''; + }; + }; programs.fish.enable = true; @@ -84,11 +98,14 @@ in openssh.authorizedKeys.keys = depot.users.tazjin.keys.all; }; + users.users.nginx.extraGroups = [ "acme" ]; + age.secrets = let secretFile = name: depot.users.tazjin.secrets."${name}.age"; in { + lego-yandex.file = secretFile "lego-yandex"; tgsa-yandex.file = secretFile "tgsa-yandex"; }; @@ -101,6 +118,7 @@ in acmeHost = "koptevo.tazj.in"; bindAddresses = [ "0.0.0.0" + "::" ]; }; @@ -169,16 +187,120 @@ in # List packages installed in system profile. To search, run: # $ nix search wget environment.systemPackages = with pkgs; [ + bat curl + emacs-nox htop jq - nmap - bat - emacs-nox nano + nmap + radicle-node wget ]; + # configure Yggdrasil network + services.yggdrasil = { + enable = true; + persistentKeys = true; + openMulticastPort = true; + + settings = { + Listen = [ "tls://[::]:9443" ]; # yggd + IfName = "ygg0"; + Peers = [ + "quic://ygg-msk-1.averyan.ru:8364" + "tls://ekb.itrus.su:7992" + "tls://s-mow-1.sergeysedoy97.ru:65534" + ]; + + MulticastInterfaces = [{ + Regex = "enp.*"; + Beacon = true; + Listen = true; + Port = 0; + }]; + + AllowedPublicKeys = [ + "573fd89392e2741ead4edd85034c91c88f1e560d991bbdbf1fccb6233db4d325" # khamovnik + "a56300c3af1ad54840f4b38b9438e3c108a0aa0fd72793dc7d6bd57325c6d691" # zamalek + "301e98e68522f55b3d9fb7a37817eb0e1aeb6478ef1ac124b9915080e9be205f" # tverskoy + "152b658f8a3e0cd6d1486c3cb984795ec7c9a02274c9f096bd2045cabf8bfa92" # A9 + "550f4920592d2831d013fd1c83ba9ad174ec352273260fd5d7c2627dbe60d097" # matepad + ]; + }; + }; + + # TODO(tazjin): move this to a module for radicle stuff + services.radicle = { + enable = true; + publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILHs6jSvMdtu9oJCt48etEs8ExjfGY5PmWQsRzFleogS"; + privateKeyFile = "/etc/secrets/radicle"; # TODO: to manage, or not to manage ... + + settings = { + web.pinned.repositories = [ + "rad:z3r5zMi9U3az3i4cPKxMcA3K7xx9L" # depot + "rad:z2mdnBK1tX6pibdBfRct3ThCgheHu" # tvix-go + ]; + + node = { + alias = "rad.tazj.in"; + seedingPolicy.default = "block"; + }; + }; + + node = { + openFirewall = true; + listenAddress = "[::]"; + }; + + httpd = { + enable = true; + listenAddress = "127.0.0.1"; + listenPort = 7235; # radl + }; + }; + + services.nginx.virtualHosts."rad.tazj.in" = { + enableACME = true; + forceSSL = true; + locations."/".proxyPass = "http://127.0.0.1:7235"; + }; + + services.nginx.virtualHosts."rad.y.tazj.in" = { + enableSSL = true; + useACMEHost = "y.tazj.in"; + locations = config.services.nginx.virtualHosts."rad.tazj.in".locations; + }; + + services.nginx.virtualHosts."src.tazj.in" = { + enableACME = true; + forceSSL = true; + root = depot.third_party.radicle-explorer.withPreferredSeeds [{ + hostname = "rad.tazj.in"; + port = 443; + scheme = "https"; + }]; + + locations."/" = { + index = "index.html"; + extraConfig = '' + try_files $uri $uri/ /index.html; + ''; + }; + }; + + services.nginx.virtualHosts."src.y.tazj.in" = { + enableSSL = true; + useACMEHost = "y.tazj.in"; + root = depot.third_party.radicle-explorer.withPreferredSeeds [{ + hostname = "rad.y.tazj.in"; + port = 443; + scheme = "https"; + }]; + + locations = config.services.nginx.virtualHosts."src.tazj.in".locations; + }; + programs.mtr.enable = true; programs.mosh.enable = true; zramSwap.enable = true; diff --git a/users/tazjin/nixos/modules/desktop.nix b/users/tazjin/nixos/modules/desktop.nix index 12a42b8faa4b..d2cdb37646f3 100644 --- a/users/tazjin/nixos/modules/desktop.nix +++ b/users/tazjin/nixos/modules/desktop.nix @@ -10,43 +10,67 @@ pulse.enable = true; }; - redshift.enable = true; blueman.enable = true; + libinput.enable = true; xserver = { - enable = true; - xkb.layout = "us"; - xkb.options = "caps:super"; - - libinput.enable = true; - - displayManager = { - # Give EXWM permission to control the session. - sessionCommands = "${pkgs.xorg.xhost}/bin/xhost +SI:localuser:$USER"; - lightdm.enable = true; - # lightdm.greeters.gtk.clock-format = "%H:%M"; # TODO(tazjin): TZ? - }; - - windowManager.session = lib.singleton { - name = "exwm"; - start = "${config.tazjin.emacs}/bin/tazjins-emacs --internal-border=0 --border-width=0"; + enable = true; # wayland doesn't work otherwise ...?! + displayManager.gdm = { + enable = true; + wayland = true; }; }; }; - # Set variables to enable EXWM-XIM and other Emacs features. - environment.sessionVariables = { - XMODIFIERS = "@im=exwm-xim"; - GTK_IM_MODULE = "xim"; - QT_IM_MODULE = "xim"; - CLUTTER_IM_MODULE = "xim"; - EDITOR = "emacsclient"; - _JAVA_AWT_WM_NONREPARENTING = "1"; - }; + services.displayManager.sessionPackages = [ pkgs.niri ]; + + programs.xwayland.enable = true; + + environment.systemPackages = with pkgs; [ + # core packages + niri + xwayland-satellite + swaylock + + # support tooling + alacritty + fuzzel + kanshi + qt5.qtwayland + swayidle + waybar + wdisplays + wl-clipboard + wl-mirror + wlr-randr + xfce.xfce4-appfinder + depot.users.tazjin.niri-reap + ]; # Do not restart the display manager automatically systemd.services.display-manager.restartIfChanged = lib.mkForce false; + # pipewire MUST start before niri, otherwise screen sharing doesn't work + systemd.user.services.pipewire.wantedBy = [ "niri.service" ]; + systemd.user.services.pipewire.before = [ "niri.service" ]; + + # enable "desktop portals", which are important somehow + xdg.portal = { + enable = true; + extraPortals = with pkgs; [ + xdg-desktop-portal-gtk + xdg-desktop-portal-gnome + ]; + config.common.default = "*"; + }; + + # swaylock needs an empty PAM configuration, otherwise it locks the user out + security.pam.services.swaylock = { }; + + # enable theming support for Qt that is compatible with Chicago95 theme + qt.enable = true; + qt.platformTheme = "qt5ct"; + # If something needs more than 10s to stop it should probably be # killed. systemd.extraConfig = '' diff --git a/users/tazjin/nixos/modules/fonts.nix b/users/tazjin/nixos/modules/fonts.nix index ee1b84e581f1..01ec118421c2 100644 --- a/users/tazjin/nixos/modules/fonts.nix +++ b/users/tazjin/nixos/modules/fonts.nix @@ -1,15 +1,17 @@ # Attempt at configuring reasonable font-rendering. -{ pkgs, ... }: +{ depot, pkgs, ... }: { fonts = { packages = with pkgs; [ corefonts dejavu_fonts + font-awesome jetbrains-mono - noto-fonts-cjk - noto-fonts-emoji + noto-fonts-cjk-sans + noto-fonts-color-emoji + noto-fonts-monochrome-emoji ]; fontconfig = { diff --git a/users/tazjin/nixos/modules/geesefs.nix b/users/tazjin/nixos/modules/geesefs.nix index c45ee528f6a2..60ee821e2fe2 100644 --- a/users/tazjin/nixos/modules/geesefs.nix +++ b/users/tazjin/nixos/modules/geesefs.nix @@ -28,7 +28,7 @@ mkdir -p $STATE_DIRECTORY/tazjins-files $STATE_DIRECTORY/cache - ${depot.third_party.geesefs}/bin/geesefs \ + ${pkgs.geesefs}/bin/geesefs \ -f -o allow_other \ --cache $STATE_DIRECTORY/cache \ --shared-config $CREDENTIALS_DIRECTORY/geesefs-tazjins-files \ diff --git a/users/tazjin/nixos/modules/home-config.nix b/users/tazjin/nixos/modules/home-config.nix index bda8f7a44014..9aa1cab46d66 100644 --- a/users/tazjin/nixos/modules/home-config.nix +++ b/users/tazjin/nixos/modules/home-config.nix @@ -6,7 +6,7 @@ users.users.tazjin = { isNormalUser = true; createHome = true; - extraGroups = [ "wheel" "networkmanager" "video" "adbusers" ]; + extraGroups = [ "wheel" "networkmanager" "video" "adbusers" "yggdrasil" ]; uid = 1000; shell = pkgs.fish; initialHashedPassword = "$2b$05$1eBPdoIgan/C/L8JFqIHBuVscQyTKw1L/4VBlzlLvLBEf6CXS3EW6"; @@ -14,6 +14,8 @@ nix.settings.trusted-users = [ "tazjin" ]; + home-manager.backupFileExtension = "backup"; home-manager.useGlobalPkgs = true; - home-manager.users.tazjin = depot.users.tazjin.home."${config.networking.hostName}"; + home-manager.users.tazjin = with depot.users.tazjin; + home."${config.networking.hostName}" or home.shared; } diff --git a/users/tazjin/nixos/modules/homepage.nix b/users/tazjin/nixos/modules/homepage.nix new file mode 100644 index 000000000000..65191d6e7087 --- /dev/null +++ b/users/tazjin/nixos/modules/homepage.nix @@ -0,0 +1,59 @@ +# serve tazjin's website & blog +{ depot, config, lib, pkgs, ... }: + +let + extraConfig = '' + location = /en/rss.xml { + return 301 https://tazj.in/feed.atom; + } + + ${depot.users.tazjin.blog.oldRedirects} + location /blog/ { + alias ${depot.users.tazjin.blog.rendered}/; + + if ($request_uri ~ ^/(.*)\.html$) { + return 302 /$1; + } + + try_files $uri $uri.html $uri/ =404; + } + + location = /predlozhnik { + return 302 https://predlozhnik.ru; + } + + # redirect for easier entry on a TV + location = /tv { + return 302 https://tazj.in/blobs/play.html; + } + + # Temporary place for serving static files. + location /blobs/ { + alias /var/lib/tazjins-blobs/; + } + ''; +in +{ + config = { + services.nginx.virtualHosts."tazj.in" = { + enableACME = true; + forceSSL = true; + root = depot.users.tazjin.homepage; + serverAliases = [ "www.tazj.in" ]; + inherit extraConfig; + }; + + services.nginx.virtualHosts."y.tazj.in" = { + enableSSL = true; + useACMEHost = "y.tazj.in"; + root = depot.users.tazjin.homepage; + inherit extraConfig; + }; + + services.nginx.virtualHosts."git.tazj.in" = { + enableACME = true; + forceSSL = true; + extraConfig = "return 301 https://code.tvl.fyi$request_uri;"; + }; + }; +} diff --git a/users/tazjin/nixos/modules/persistence.nix b/users/tazjin/nixos/modules/persistence.nix index b864d13a8d70..d3a918025a50 100644 --- a/users/tazjin/nixos/modules/persistence.nix +++ b/users/tazjin/nixos/modules/persistence.nix @@ -14,6 +14,7 @@ "/var/lib/bluetooth" "/var/lib/systemd/coredump" "/var/lib/tailscale" + "/var/lib/private/yggdrasil" "/var/log" ]; diff --git a/users/tazjin/nixos/modules/physical.nix b/users/tazjin/nixos/modules/physical.nix index bb85c6fb9827..baae1b6b5bfe 100644 --- a/users/tazjin/nixos/modules/physical.nix +++ b/users/tazjin/nixos/modules/physical.nix @@ -20,10 +20,12 @@ in environment.systemPackages = # programs from the depot (with depot; [ - users.tazjin.screenLock - users.tazjin.chase-geese config.tazjin.emacs third_party.agenix.cli + tools.when + users.tazjin.chase-geese + users.tazjin.eaglemode + users.tazjin.screenLock ]) ++ # programs from nixpkgs @@ -44,6 +46,9 @@ in gdb git gnupg + go + gopls + gotools gtk3 # for gtk-launch htop hyperfine @@ -70,6 +75,7 @@ in pulseaudio # for pactl pwgen quasselClient + radicle-node rink ripgrep rustup @@ -96,10 +102,26 @@ in # run manually patchelfed binaries environment.stub-ld.enable = false; + # Enable yggdrasil network. + services.yggdrasil = { + enable = true; + persistentKeys = true; + settings.IfName = "ygg0"; + }; + programs = { fish.enable = true; mosh.enable = true; ssh.startAgent = true; }; + + # Automatically collect garbage from the Nix store. + services.depot.automatic-gc = { + enable = true; + interval = "1 hour"; + diskThreshold = 16; # GiB + maxFreed = 50; # GiB + preserveGenerations = "14d"; + }; }; } diff --git a/users/tazjin/nixos/tverskoy/default.nix b/users/tazjin/nixos/tverskoy/default.nix index 733929219a3a..c6cd943b99b7 100644 --- a/users/tazjin/nixos/tverskoy/default.nix +++ b/users/tazjin/nixos/tverskoy/default.nix @@ -28,7 +28,7 @@ lib.fix (self: { tvl.cache.enable = true; - boot = rec { + boot = { initrd.availableKernelModules = [ "nvme" "ehci_pci" "xhci_pci" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ]; initrd.kernelModules = [ ]; @@ -38,10 +38,9 @@ lib.fix (self: { ''; # Install thinkpad modules for TLP - extraModulePackages = [ kernelPackages.acpi_call ]; + extraModulePackages = [ pkgs.linuxPackages.acpi_call ]; - kernelModules = [ "kvm-amd" "i2c_dev" ]; - kernelPackages = pkgs.zfsUnstable.latestCompatibleLinuxPackages; + kernelModules = [ "acpi_call" "kvm-amd" "i2c_dev" ]; loader.systemd-boot.enable = true; loader.efi.canTouchEfiVariables = true; }; @@ -93,9 +92,9 @@ lib.fix (self: { enableRedistributableFirmware = true; bluetooth.enable = true; - opengl = { + graphics = { enable = true; - driSupport32Bit = true; + enable32Bit = true; extraPackages = with pkgs; [ vaapiVdpau @@ -131,15 +130,6 @@ lib.fix (self: { ''; xserver.videoDrivers = [ "amdgpu" ]; - - # Automatically collect garbage from the Nix store. - depot.automatic-gc = { - enable = true; - interval = "1 hour"; - diskThreshold = 16; # GiB - maxFreed = 10; # GiB - preserveGenerations = "14d"; - }; }; systemd.user.services.lieer-tazjin = { @@ -164,12 +154,5 @@ lib.fix (self: { # android stuff for hacking on Awful.apk programs.adb.enable = true; - # systemd-oomd seems to have been enabled by default around ~ - # December 2022, and it's really into killing my X session as soon - # as I do anything stressful to the machine - systemd.services.systemd-oomd.enable = lib.mkForce false; - - environment.systemPackages = [ pkgs.vulkan-tools ]; - system.stateVersion = "20.09"; }) diff --git a/users/tazjin/nixos/zamalek/default.nix b/users/tazjin/nixos/zamalek/default.nix index a340e8a3e897..ebaf2d2cfa6d 100644 --- a/users/tazjin/nixos/zamalek/default.nix +++ b/users/tazjin/nixos/zamalek/default.nix @@ -61,10 +61,6 @@ in hostId = "ee399356"; networkmanager.enable = true; - extraHosts = '' - 10.101.240.1 wifi.silja.fi - ''; - nameservers = [ "8.8.8.8" "8.8.4.4" @@ -75,14 +71,13 @@ in cpu.intel.updateMicrocode = true; bluetooth.enable = true; enableRedistributableFirmware = true; - opengl.enable = true; + graphics.enable = true; }; - services.xserver.libinput.touchpad.clickMethod = "clickfinger"; - services.xserver.libinput.touchpad.tapping = false; + services.libinput.touchpad.clickMethod = "clickfinger"; + services.libinput.touchpad.tapping = false; services.avahi.enable = true; services.tailscale.enable = true; - powerManagement.powertop.enable = true; system.stateVersion = "21.11"; } diff --git a/users/tazjin/secrets/lego-yandex.age b/users/tazjin/secrets/lego-yandex.age new file mode 100644 index 000000000000..10524a9577c2 --- /dev/null +++ b/users/tazjin/secrets/lego-yandex.age Binary files differdiff --git a/users/tazjin/secrets/secrets.nix b/users/tazjin/secrets/secrets.nix index 12f12f721c6c..a29bd30b7766 100644 --- a/users/tazjin/secrets/secrets.nix +++ b/users/tazjin/secrets/secrets.nix @@ -13,4 +13,5 @@ in "geesefs-tazjins-files.age".publicKeys = allKeys; "miniflux.age".publicKeys = allKeys; "tgsa-yandex.age".publicKeys = allKeys; + "lego-yandex.age".publicKeys = allKeys; } diff --git a/users/tazjin/wallpapers/alphasoft.webp b/users/tazjin/wallpapers/alphasoft.webp new file mode 100644 index 000000000000..10c404eff0ab --- /dev/null +++ b/users/tazjin/wallpapers/alphasoft.webp Binary files differdiff --git a/users/tazjin/wallpapers/svema_02_big.webp b/users/tazjin/wallpapers/svema_02_big.webp new file mode 100644 index 000000000000..5b7f18715c9d --- /dev/null +++ b/users/tazjin/wallpapers/svema_02_big.webp Binary files differdiff --git a/users/tazjin/wallpapers/svema_07_big.webp b/users/tazjin/wallpapers/svema_07_big.webp new file mode 100644 index 000000000000..0706543473e5 --- /dev/null +++ b/users/tazjin/wallpapers/svema_07_big.webp Binary files differdiff --git a/users/tazjin/wallpapers/svema_09_big.webp b/users/tazjin/wallpapers/svema_09_big.webp new file mode 100644 index 000000000000..4983efef29b8 --- /dev/null +++ b/users/tazjin/wallpapers/svema_09_big.webp Binary files differdiff --git a/users/tazjin/wallpapers/svema_14_big.webp b/users/tazjin/wallpapers/svema_14_big.webp new file mode 100644 index 000000000000..c74542807c29 --- /dev/null +++ b/users/tazjin/wallpapers/svema_14_big.webp Binary files differdiff --git a/users/wpcarro/boilerplate/typescript/default.nix b/users/wpcarro/boilerplate/typescript/default.nix index 84949cae7f3c..b013cf07eb44 100644 --- a/users/wpcarro/boilerplate/typescript/default.nix +++ b/users/wpcarro/boilerplate/typescript/default.nix @@ -6,7 +6,7 @@ pkgs.stdenv.mkDerivation { buildInputs = with pkgs; [ nodejs # Exposes lscpu for parcel.js - utillinux + util-linux ]; # parcel.js needs number of CPUs PARCEL_WORKERS = "1"; diff --git a/users/wpcarro/nixos/ava/default.nix b/users/wpcarro/nixos/ava/default.nix index 25c43c003fd4..457947607e7e 100644 --- a/users/wpcarro/nixos/ava/default.nix +++ b/users/wpcarro/nixos/ava/default.nix @@ -76,10 +76,6 @@ in }; }; - # Enable sound. - sound.enable = true; - hardware.pulseaudio.enable = true; - users.mutableUsers = true; users.users.root.openssh.authorizedKeys.keys = with wpcarro.keys; [ iphone diff --git a/users/wpcarro/nixos/kyoko/default.nix b/users/wpcarro/nixos/kyoko/default.nix index 0d8907edd2f0..024276afddaf 100644 --- a/users/wpcarro/nixos/kyoko/default.nix +++ b/users/wpcarro/nixos/kyoko/default.nix @@ -79,10 +79,6 @@ in }; }; - # Enable sound. - sound.enable = true; - hardware.pulseaudio.enable = true; - users.mutableUsers = true; users.users.root.openssh.authorizedKeys.keys = with wpcarro.keys; [ iphone diff --git a/users/wpcarro/nixos/marcus/default.nix b/users/wpcarro/nixos/marcus/default.nix index a97d6d264de6..491c010ac871 100644 --- a/users/wpcarro/nixos/marcus/default.nix +++ b/users/wpcarro/nixos/marcus/default.nix @@ -50,13 +50,14 @@ in interval = "1d"; }; + libinput = { + enable = true; + touchpad.naturalScrolling = false; + touchpad.tapping = false; + }; + xserver = { enable = true; - libinput = { - enable = true; - touchpad.naturalScrolling = false; - touchpad.tapping = false; - }; xkb.layout = "us"; xkb.options = "caps:escape"; displayManager = { @@ -78,10 +79,6 @@ in }; }; - # Enable sound. - sound.enable = true; - hardware.pulseaudio.enable = true; - users.mutableUsers = true; users.users.wpcarro = { isNormalUser = true; diff --git a/users/wpcarro/nixos/tarasco/default.nix b/users/wpcarro/nixos/tarasco/default.nix index 7033caa11ab8..75f19aa6e3d6 100644 --- a/users/wpcarro/nixos/tarasco/default.nix +++ b/users/wpcarro/nixos/tarasco/default.nix @@ -72,10 +72,6 @@ in }; }; - # Enable sound. - sound.enable = true; - hardware.pulseaudio.enable = true; - users.mutableUsers = true; users.users.root.openssh.authorizedKeys.keys = with wpcarro.keys; [ ava diff --git a/users/wpcarro/website/sandbox/contentful/default.nix b/users/wpcarro/website/sandbox/contentful/default.nix index ce7e534b234b..8b3ed12c49a7 100644 --- a/users/wpcarro/website/sandbox/contentful/default.nix +++ b/users/wpcarro/website/sandbox/contentful/default.nix @@ -6,7 +6,7 @@ pkgs.stdenv.mkDerivation { buildInputs = with pkgs; [ nodejs # Exposes lscpu for parcel.js - utillinux + util-linux ]; # parcel.js needs number of CPUs PARCEL_WORKERS = "1"; diff --git a/users/yl3dy/OWNERS b/users/yl3dy/OWNERS new file mode 100644 index 000000000000..686f0179a665 --- /dev/null +++ b/users/yl3dy/OWNERS @@ -0,0 +1,3 @@ +set noparent + +yl3dy diff --git a/users/yl3dy/test.txt b/users/yl3dy/test.txt new file mode 100644 index 000000000000..57a1fac55ce4 --- /dev/null +++ b/users/yl3dy/test.txt @@ -0,0 +1 @@ +Some gpg-signed text diff --git a/views/README.md b/views/README.md index a6ebd93a7788..57fcbb476e38 100644 --- a/views/README.md +++ b/views/README.md @@ -8,9 +8,8 @@ individual content and usage information. Testing changes locally ----------------------- -Generally, when iterating on these files, it's best to locally invoke `josh- -filter` (from `//third_party//josh`) locally to inspect how the workspace would -look like: +Generally, when iterating on these files, it's best to invoke `josh-filter` +(from the `josh` package) locally to inspect how the workspace would look like: - Commit your changes. This is required, as `josh-filter` operates on your `HEAD`, not working directory state. diff --git a/web/atward/indexHtml/default.nix b/web/atward/indexHtml/default.nix index 3af808b89831..801faf57dcf2 100644 --- a/web/atward/indexHtml/default.nix +++ b/web/atward/indexHtml/default.nix @@ -35,65 +35,13 @@ depot.web.tvl.template { <kbd>cl</kbd>), atward will redirect to the appropriate `tvl.fyi` domain. - ### Configuration - - Some behaviour of atward can be configured by adding query - parameters to the search string: - - * <kbd>cs=true</kbd> - use Sourcegraph instead of cgit to view code - - - In some browsers (like Firefox) users can not edit query - parameters for search engines. As an alternative configuration can - be supplied via cookies with the same names as the configuration - parameters. - - The form below can set this configuration: - <form class="cheddar-callout cheddar-todo"> - <input type="checkbox" - id="cs-setting" - name="cs-setting" - onchange="saveSetting(this, 'cs');"> - <label for="cs-setting">Use Sourcegraph instead of cgit</label> - </form> - - <noscript> - <p class="cheddar-callout cheddar-warning"> - The form above only works with Javascript enabled. Only a few - lines of Javascript are used, and they are licensed under a - free-software license (MIT). - </p> - </noscript> - ### Source code atward's source code lives at [//web/atward](https://at.tvl.fyi/?q=%2F%2Fweb%2Fatward). ''; - extraHead = '' - <script> - /* Initialise the state of all settings. */ - function loadSettings() { - loadSetting(document.getElementById('cs-setting'), 'cs'); - } - - /* Initialise the state of a setting from a cookie. */ - function loadSetting(checkbox, name) { - if (document.cookie.split(';').some(function(cookie) { - return cookie.indexOf(`''${name}=true`) >= 0; - })) { - checkbox.checked = true; - } - } - /* Persist the state of a checkbox in a cookie */ - function saveSetting(checkbox, name) { - console.log(`setting atward parameter '''''${name}' to ''${checkbox.checked.toString()}`); - document.cookie = `''${name}=''${checkbox.checked.toString()};`; - } - - document.addEventListener('DOMContentLoaded', loadSettings); - </script> + extraHead = '' <link rel="search" type="application/opensearchdescription+xml" title="TVL Search" href="https://at.tvl.fyi/opensearch.xml"> ''; } diff --git a/web/atward/src/main.rs b/web/atward/src/main.rs index eb2603a226c6..13aeff0e27d8 100644 --- a/web/atward/src/main.rs +++ b/web/atward/src/main.rs @@ -5,7 +5,6 @@ //! browsers and attempts to send users to useful locations based on //! their search query (falling back to another search engine). use regex::Regex; -use rouille::input::cookies; use rouille::{Request, Response}; #[cfg(test)] @@ -31,43 +30,14 @@ struct Handler { struct Query { /// Query string itself. query: String, - - /// Should Sourcegraph be used instead of cgit? - cs: bool, -} - -/// Helper function for setting a parameter based on a query -/// parameter. -fn query_setting(req: &Request, config: &mut bool, param: &str) { - match req.get_param(param) { - Some(s) if s == "true" => *config = true, - Some(s) if s == "false" => *config = false, - _ => {} - } } impl Query { fn from_request(req: &Request) -> Option<Query> { - // First extract the actual search query ... - let mut query = match req.get_param("q") { - Some(query) => Query { query, cs: false }, + match req.get_param("q") { + Some(query) => Some(Query { query }), None => return None, - }; - - // ... then apply settings to it. Settings in query parameters - // take precedence over cookies. - for cookie in cookies(req) { - match cookie { - ("cs", "true") => { - query.cs = true; - } - _ => {} - } } - - query_setting(req, &mut query.cs, "cs"); - - Some(query) } } @@ -76,7 +46,6 @@ impl From<&str> for Query { fn from(query: &str) -> Query { Query { query: query.to_string(), - cs: false, } } } @@ -90,10 +59,6 @@ fn cgit_url(path: &str) -> String { } } -/// Create a URL to a path in Sourcegraph. -fn sourcegraph_path_url(path: &str) -> String { - format!("https://cs.tvl.fyi/depot/-/tree/{}", path) -} /// Definition of all supported query handlers in atward. fn handlers() -> Vec<Handler> { vec![ @@ -126,16 +91,11 @@ fn handlers() -> Vec<Handler> { // TODO(tazjin): Add support for specifying lines in a query parameter Handler { pattern: Regex::new("^//(?P<path>[a-zA-Z].*)?$").unwrap(), - target: |query, captures| { + target: |_, captures| { // Pass an empty string if the path is missing, to // redirect to the depot root. let path = captures.name("path").map(|m| m.as_str()).unwrap_or(""); - - if query.cs { - Some(sourcegraph_path_url(path)) - } else { - Some(cgit_url(path)) - } + Some(cgit_url(path)) }, }, ] diff --git a/web/atward/src/tests.rs b/web/atward/src/tests.rs index a23f96ee9a74..eb205fdf9810 100644 --- a/web/atward/src/tests.rs +++ b/web/atward/src/tests.rs @@ -44,38 +44,12 @@ fn depot_path_cgit_query() { } #[test] -fn depot_path_sourcegraph_query() { - assert_eq!( - dispatch( - &handlers(), - &Query { - query: "//web/atward/default.nix".to_string(), - cs: true, - } - ), - Some("https://cs.tvl.fyi/depot/-/tree/web/atward/default.nix".to_string()), - ); - - assert_eq!( - dispatch( - &handlers(), - &Query { - query: "/not/a/depot/path".to_string(), - cs: true, - } - ), - None - ); -} - -#[test] fn depot_root_cgit_query() { assert_eq!( dispatch( &handlers(), &Query { query: "//".to_string(), - cs: false, } ), Some("https://code.tvl.fyi/tree/".to_string()), @@ -112,7 +86,6 @@ fn request_to_query() { .expect("request should parse to a query"), Query { query: "b/42".to_string(), - cs: false, }, ); @@ -123,55 +96,6 @@ fn request_to_query() { } #[test] -fn settings_from_cookie() { - assert_eq!( - Query::from_request(&Request::fake_http( - "GET", - "/?q=b%2F42", - vec![("Cookie".to_string(), "cs=true;".to_string())], - vec![] - )) - .expect("request should parse to a query"), - Query { - query: "b/42".to_string(), - cs: true, - }, - ); -} - -#[test] -fn settings_from_query_parameter() { - assert_eq!( - Query::from_request(&Request::fake_http( - "GET", - "/?q=b%2F42&cs=true", - vec![], - vec![] - )) - .expect("request should parse to a query"), - Query { - query: "b/42".to_string(), - cs: true, - }, - ); - - // Query parameter should override cookie - assert_eq!( - Query::from_request(&Request::fake_http( - "GET", - "/?q=b%2F42&cs=false", - vec![("Cookie".to_string(), "cs=true;".to_string())], - vec![] - )) - .expect("request should parse to a query"), - Query { - query: "b/42".to_string(), - cs: false, - }, - ); -} - -#[test] fn depot_revision_query() { assert_eq!( dispatch(&handlers(), &"r/3002".into()), diff --git a/web/bubblegum/default.nix b/web/bubblegum/default.nix index ed9ab616804d..b7e1ce81ebd0 100644 --- a/web/bubblegum/default.nix +++ b/web/bubblegum/default.nix @@ -21,6 +21,7 @@ let # nixpkgs for lib and packages "third_party/nixpkgs" "third_party/overlays" + "third_party/sources" # bubblegum and its dependencies "web/bubblegum" "nix/runExecline" diff --git a/web/cgit-tvl/default.nix b/web/cgit-tvl/default.nix index d26de9a5ebe7..1be2f29b81f0 100644 --- a/web/cgit-tvl/default.nix +++ b/web/cgit-tvl/default.nix @@ -15,7 +15,7 @@ let source-filter=${depot.tools.cheddar}/bin/cheddar enable-log-filecount=1 enable-log-linecount=1 - enable-follow-links=1 + enable-follow-links=0 enable-blame=1 mimetype-file=${pkgs.mime-types}/etc/mime.types logo=https://static.tvl.fyi/${depot.web.static.drvHash}/logo-animated.svg diff --git a/web/pwcrypt/Cargo.lock b/web/pwcrypt/Cargo.lock index 7d33ab4bf182..75b2d8c9c69f 100644 --- a/web/pwcrypt/Cargo.lock +++ b/web/pwcrypt/Cargo.lock @@ -818,19 +818,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -855,9 +856,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -865,9 +866,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -878,9 +879,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" diff --git a/web/pwcrypt/Cargo.toml b/web/pwcrypt/Cargo.toml index 6c0a6e5b6d84..48c73081f1ee 100644 --- a/web/pwcrypt/Cargo.toml +++ b/web/pwcrypt/Cargo.toml @@ -8,6 +8,6 @@ argon2 = "0.5.0" getrandom = { version = "0.2.10", features = ["js"] } gloo = "0.8.0" rand_core = { version = "0.6.4", features = ["getrandom"] } -wasm-bindgen = "= 0.2.91" +wasm-bindgen = "= 0.2.93" web-sys = "0.3" yew = { version = "0.20.0", features = [ "csr" ]} diff --git a/web/tvixbolt/Cargo.lock b/web/tvixbolt/Cargo.lock index d3c5faf10c12..301847797107 100644 --- a/web/tvixbolt/Cargo.lock +++ b/web/tvixbolt/Cargo.lock @@ -3,6 +3,21 @@ version = 3 [[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] name = "aho-corasick" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -12,10 +27,40 @@ dependencies = [ ] [[package]] +name = "anymap2" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" + +[[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] [[package]] name = "bitflags" @@ -30,12 +75,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] -name = "bitmaps" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703642b98a00b3b90513279a8ede3fcfa479c126c5fb46e78f3051522f021403" - -[[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -52,9 +91,9 @@ checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" [[package]] name = "bstr" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "regex-automata", @@ -63,15 +102,21 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + +[[package]] +name = "cc" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" [[package]] name = "cfg-if" @@ -132,9 +177,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "digest" @@ -173,6 +218,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -188,12 +239,27 @@ dependencies = [ ] [[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] name = "futures-channel" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -203,6 +269,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] name = "genawaiter" version = "0.99.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -229,29 +342,59 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] name = "gloo" -version = "0.4.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23947965eee55e3e97a5cd142dd4c10631cc349b48cecca0ed230fd296f568cd" +checksum = "28999cda5ef6916ffd33fb4a7b87e1de633c47c0dc6d97905fee1cdaa142b94d" dependencies = [ - "gloo-console", - "gloo-dialogs", - "gloo-events", - "gloo-file", - "gloo-render", - "gloo-storage", - "gloo-timers", - "gloo-utils", + "gloo-console 0.2.3", + "gloo-dialogs 0.1.1", + "gloo-events 0.1.2", + "gloo-file 0.2.3", + "gloo-history 0.1.5", + "gloo-net 0.3.1", + "gloo-render 0.1.1", + "gloo-storage 0.2.2", + "gloo-timers 0.2.6", + "gloo-utils 0.1.7", + "gloo-worker 0.2.1", +] + +[[package]] +name = "gloo" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd35526c28cc55c1db77aed6296de58677dbab863b118483a27845631d870249" +dependencies = [ + "gloo-console 0.3.0", + "gloo-dialogs 0.2.0", + "gloo-events 0.2.0", + "gloo-file 0.3.0", + "gloo-history 0.2.2", + "gloo-net 0.4.0", + "gloo-render 0.2.0", + "gloo-storage 0.3.0", + "gloo-timers 0.3.0", + "gloo-utils 0.2.0", + "gloo-worker 0.4.0", ] [[package]] @@ -260,7 +403,20 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f" dependencies = [ - "gloo-utils", + "gloo-utils 0.1.7", + "js-sys", + "serde", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-console" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a17868f56b4a24f677b17c8cb69958385102fa879418052d60b50bc1727e261" +dependencies = [ + "gloo-utils 0.2.0", "js-sys", "serde", "wasm-bindgen", @@ -278,6 +434,16 @@ dependencies = [ ] [[package]] +name = "gloo-dialogs" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4748e10122b01435750ff530095b1217cf6546173459448b83913ebe7815df" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] name = "gloo-events" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -288,15 +454,112 @@ dependencies = [ ] [[package]] +name = "gloo-events" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c26fb45f7c385ba980f5fa87ac677e363949e065a083722697ef1b2cc91e41" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] name = "gloo-file" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7" dependencies = [ + "gloo-events 0.1.2", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-file" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97563d71863fb2824b2e974e754a81d19c4a7ec47b09ced8a0e6656b6d54bd1f" +dependencies = [ + "futures-channel", + "gloo-events 0.2.0", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-history" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85725d90bf0ed47063b3930ef28e863658a7905989e9929a8708aab74a1d5e7f" +dependencies = [ + "gloo-events 0.1.2", + "gloo-utils 0.1.7", + "serde", + "serde-wasm-bindgen 0.5.0", + "serde_urlencoded", + "thiserror", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-history" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "903f432be5ba34427eac5e16048ef65604a82061fe93789f2212afc73d8617d6" +dependencies = [ + "getrandom", + "gloo-events 0.2.0", + "gloo-utils 0.2.0", + "serde", + "serde-wasm-bindgen 0.6.5", + "serde_urlencoded", + "thiserror", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-net" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a66b4e3c7d9ed8d315fd6b97c8b1f74a7c6ecbbc2320e65ae7ed38b7068cc620" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils 0.1.7", + "http", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-net" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ac9e8288ae2c632fa9f8657ac70bfe38a1530f345282d7ba66a1f70b72b7dc4" +dependencies = [ "futures-channel", - "gloo-events", + "futures-core", + "futures-sink", + "gloo-utils 0.2.0", + "http", "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", ] @@ -311,12 +574,37 @@ dependencies = [ ] [[package]] +name = "gloo-render" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56008b6744713a8e8d98ac3dcb7d06543d5662358c9c805b4ce2167ad4649833" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] name = "gloo-storage" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480" dependencies = [ - "gloo-utils", + "gloo-utils 0.1.7", + "js-sys", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-storage" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a" +dependencies = [ + "gloo-utils 0.2.0", "js-sys", "serde", "serde_json", @@ -331,6 +619,16 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ "futures-channel", "futures-core", "js-sys", @@ -351,6 +649,67 @@ dependencies = [ ] [[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-worker" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13471584da78061a28306d1359dd0178d8d6fc1c7c80e5e35d27260346e0516a" +dependencies = [ + "anymap2", + "bincode", + "gloo-console 0.2.3", + "gloo-utils 0.1.7", + "js-sys", + "serde", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-worker" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76495d3dd87de51da268fa3a593da118ab43eb7f8809e17eb38d3319b424e400" +dependencies = [ + "bincode", + "futures", + "gloo-utils 0.2.0", + "gloo-worker-macros", + "js-sys", + "pinned", + "serde", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-worker-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956caa58d4857bc9941749d55e4bd3000032d8212762586fa5705632967140e7" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -358,31 +717,45 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] -name = "imbl" -version = "2.0.3" +name = "hermit-abi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978d142c8028edf52095703af2fad11d6f611af1246685725d6b850634647085" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bitmaps", - "imbl-sized-chunks", - "rand_core", - "rand_xoshiro", - "serde", - "version_check", + "bytes", + "fnv", + "itoa", ] [[package]] -name = "imbl-sized-chunks" +name = "implicit-clone" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a9aa791c7b5a71b636b7a68207fdebf171ddfc593d9c8506ec4cbc527b6a84" +dependencies = [ + "implicit-clone-derive", + "indexmap 2.2.6", +] + +[[package]] +name = "implicit-clone-derive" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6957ea0b2541c5ca561d3ef4538044af79f8a05a1eb3a3b148936aaceaa1076" +checksum = "9311685eb9a34808bbb0608ad2fcab9ae216266beca5848613e95553ac914e3b" dependencies = [ - "bitmaps", + "quote", + "syn 2.0.68", ] [[package]] @@ -396,34 +769,44 @@ dependencies = [ ] [[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + +[[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lexical-core" @@ -491,9 +874,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.152" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libredox" @@ -508,9 +891,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "md-5" @@ -524,9 +907,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -538,6 +921,21 @@ dependencies = [ ] [[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] name = "nom8" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -547,6 +945,25 @@ dependencies = [ ] [[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +dependencies = [ + "memchr", +] + +[[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -574,6 +991,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pinned" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b" +dependencies = [ + "futures", + "rustversion", + "thiserror", +] + +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2", + "syn 2.0.68", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -599,35 +1079,37 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] -name = "quote" -version = "1.0.35" +name = "prokio" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "03b55e106e5791fa5a13abd13c85d6127312e8e09098059ca2bc9b03ca4cf488" dependencies = [ - "proc-macro2", + "futures", + "gloo 0.8.1", + "num_cpus", + "once_cell", + "pin-project", + "pinned", + "tokio", + "tokio-stream", + "wasm-bindgen-futures", ] [[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - -[[package]] -name = "rand_xoshiro" -version = "0.6.0" +name = "quote" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ - "rand_core", + "proc-macro2", ] [[package]] @@ -652,9 +1134,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -664,9 +1146,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -701,46 +1183,68 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a58fa8a7ccff2aec4f39cc45bf5f985cec7125ab271cf681c279fd00192b49" dependencies = [ "countme", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "memoffset", - "rustc-hash", + "rustc-hash 1.1.0", "text-size", ] [[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "ryu" -version = "1.0.16" +name = "rustc-hash" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] -name = "scoped-tls-hkt" -version = "0.1.4" +name = "rustversion" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ddc765d3410d9f6c6ca071bf0b67f6b01e3ec4595dc3892f02677e75819dddc" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde-wasm-bindgen" -version = "0.3.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618365e8e586c22123d692b72a7d791d5ee697817b65a218cdf12a98870af0f7" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" dependencies = [ - "fnv", "js-sys", "serde", "wasm-bindgen", @@ -748,20 +1252,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.68", ] [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", "ryu", @@ -822,9 +1326,9 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" dependencies = [ "serde", ] @@ -848,9 +1352,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -883,22 +1387,43 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.68", +] + +[[package]] +name = "tokio" +version = "1.39.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +dependencies = [ + "backtrace", + "pin-project-lite", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] @@ -909,8 +1434,8 @@ checksum = "4fb9d890e4dc9298b70f740f615f2e05b9db37dce531f6b24fb77ac993f9f217" dependencies = [ "serde", "serde_spanned", - "toml_datetime", - "toml_edit", + "toml_datetime 0.5.1", + "toml_edit 0.18.1", ] [[package]] @@ -923,16 +1448,64 @@ dependencies = [ ] [[package]] +name = "toml_datetime" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db" + +[[package]] name = "toml_edit" version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" dependencies = [ - "indexmap", + "indexmap 1.9.3", "nom8", "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.5.1", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime 0.6.7", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", ] [[package]] @@ -946,25 +1519,27 @@ dependencies = [ "data-encoding", "dirs", "genawaiter", - "imbl", "itertools", "lazy_static", "lexical-core", "md-5", + "nohash-hasher", "os_str_bytes", "path-clean", "regex", "rnix", "rowan", + "rustc-hash 2.0.0", "serde", "serde_json", "sha1", "sha2", "smol_str", "tabwriter", + "thiserror", "toml", "tvix-eval-builtin-macros", - "xml-rs", + "vu128", ] [[package]] @@ -980,10 +1555,7 @@ dependencies = [ name = "tvixbolt" version = "0.1.0" dependencies = [ - "codemap", - "rnix", "serde", - "serde_urlencoded", "tvix-eval", "wasm-bindgen", "web-sys", @@ -1010,12 +1582,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] +name = "vu128" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b18da3bd753c6f4373511e5f025423986560dfe4a5e7d642cc9a0266847f9fdd" + +[[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1023,34 +1607,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.68", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -1060,9 +1645,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1070,28 +1655,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -1129,24 +1714,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "xml-rs" -version = "0.8.19" +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] [[package]] name = "yew" -version = "0.19.3" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a1ccb53e57d3f7d847338cf5758befa811cabe207df07f543c06f502f9998cd" +checksum = "5f1a03f255c70c7aa3e9c62e15292f142ede0564123543c1cc0c7a4f31660cac" dependencies = [ "console_error_panic_hook", - "gloo", - "gloo-utils", - "indexmap", + "futures", + "gloo 0.10.0", + "implicit-clone", + "indexmap 2.2.6", "js-sys", - "scoped-tls-hkt", + "prokio", + "rustversion", + "serde", "slab", + "thiserror", + "tokio", + "tracing", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1155,32 +1749,32 @@ dependencies = [ [[package]] name = "yew-macro" -version = "0.19.3" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fab79082b556d768d6e21811869c761893f0450e1d550a67892b9bce303b7bb" +checksum = "02fd8ca5166d69e59f796500a2ce432ff751edecbbb308ca59fd3fe4d0343de2" dependencies = [ "boolinator", - "lazy_static", + "once_cell", + "prettyplease", "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.68", ] [[package]] name = "yew-router" -version = "0.16.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "155804f6f3aa309f596d5c3fa14486a94e7756f1edd7634569949e401d5099f2" +checksum = "4ca1d5052c96e6762b4d6209a8aded597758d442e6c479995faf0c7b5538e0c6" dependencies = [ - "gloo", - "gloo-utils", + "gloo 0.10.0", "js-sys", "route-recognizer", "serde", - "serde-wasm-bindgen", "serde_urlencoded", - "thiserror", + "tracing", + "urlencoding", "wasm-bindgen", "web-sys", "yew", @@ -1189,11 +1783,11 @@ dependencies = [ [[package]] name = "yew-router-macro" -version = "0.16.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39049d193b52eaad4ffc80916bf08806d142c90b5edcebd527644de438a7e19a" +checksum = "42bfd190a07ca8cfde7cd4c52b3ac463803dc07323db8c34daa697e86365978c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.68", ] diff --git a/web/tvixbolt/Cargo.nix b/web/tvixbolt/Cargo.nix new file mode 100644 index 000000000000..eefa2b28b478 --- /dev/null +++ b/web/tvixbolt/Cargo.nix @@ -0,0 +1,6512 @@ +# This file was @generated by crate2nix 0.14.1 with the command: +# "generate" "--all-features" +# See https://github.com/kolloch/crate2nix for more info. + +{ nixpkgs ? <nixpkgs> +, pkgs ? import nixpkgs { config = { }; } +, lib ? pkgs.lib +, stdenv ? pkgs.stdenv +, buildRustCrateForPkgs ? pkgs: pkgs.buildRustCrate + # This is used as the `crateOverrides` argument for `buildRustCrate`. +, defaultCrateOverrides ? pkgs.defaultCrateOverrides + # The features to enable for the root_crate or the workspace_members. +, rootFeatures ? [ "default" ] + # If true, throw errors instead of issueing deprecation warnings. +, strictDeprecation ? false + # Elements to add to the `-C target-feature=` argument passed to `rustc` + # (separated by `,`, prefixed with `+`). + # Used for conditional compilation based on CPU feature detection. +, targetFeatures ? [ ] + # Whether to perform release builds: longer compile times, faster binaries. +, release ? true + # Additional crate2nix configuration if it exists. +, crateConfig ? if builtins.pathExists ./crate-config.nix + then pkgs.callPackage ./crate-config.nix { } + else { } +}: + +rec { + # + # "public" attributes that we attempt to keep stable with new versions of crate2nix. + # + + rootCrate = rec { + packageId = "tvixbolt"; + + # Use this attribute to refer to the derivation building your root crate package. + # You can override the features with rootCrate.build.override { features = [ "default" "feature1" ... ]; }. + build = internal.buildRustCrateWithFeatures { + inherit packageId; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + # Refer your crate build derivation by name here. + # You can override the features with + # workspaceMembers."${crateName}".build.override { features = [ "default" "feature1" ... ]; }. + workspaceMembers = { + "tvixbolt" = rec { + packageId = "tvixbolt"; + build = internal.buildRustCrateWithFeatures { + packageId = "tvixbolt"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + }; + + # A derivation that joins the outputs of all workspace members together. + allWorkspaceMembers = pkgs.symlinkJoin { + name = "all-workspace-members"; + paths = + let members = builtins.attrValues workspaceMembers; + in builtins.map (m: m.build) members; + }; + + # + # "internal" ("private") attributes that may change in every new version of crate2nix. + # + + internal = rec { + # Build and dependency information for crates. + # Many of the fields are passed one-to-one to buildRustCrate. + # + # Noteworthy: + # * `dependencies`/`buildDependencies`: similar to the corresponding fields for buildRustCrate. + # but with additional information which is used during dependency/feature resolution. + # * `resolvedDependencies`: the selected default features reported by cargo - only included for debugging. + # * `devDependencies` as of now not used by `buildRustCrate` but used to + # inject test dependencies into the build + + crates = { + "addr2line" = rec { + crateName = "addr2line"; + version = "0.22.0"; + edition = "2018"; + sha256 = "0y66f1sa27i9kvmlh76ynk60rxfrmkba9ja8x527h32wdb206ibf"; + dependencies = [ + { + name = "gimli"; + packageId = "gimli"; + usesDefaultFeatures = false; + features = [ "read" ]; + } + ]; + features = { + "alloc" = [ "dep:alloc" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "cpp_demangle" = [ "dep:cpp_demangle" ]; + "default" = [ "rustc-demangle" "cpp_demangle" "std-object" "fallible-iterator" "smallvec" "memmap2" ]; + "fallible-iterator" = [ "dep:fallible-iterator" ]; + "memmap2" = [ "dep:memmap2" ]; + "object" = [ "dep:object" ]; + "rustc-demangle" = [ "dep:rustc-demangle" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "gimli/rustc-dep-of-std" ]; + "smallvec" = [ "dep:smallvec" ]; + "std" = [ "gimli/std" ]; + "std-object" = [ "std" "object" "object/std" "object/compression" "gimli/endian-reader" ]; + }; + }; + "adler" = rec { + crateName = "adler"; + version = "1.0.2"; + edition = "2015"; + sha256 = "1zim79cvzd5yrkzl3nyfx0avijwgk9fqv3yrscdy1cc79ih02qpj"; + authors = [ + "Jonas Schievink <jonasschievink@gmail.com>" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "std" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + }; + }; + "aho-corasick" = rec { + crateName = "aho-corasick"; + version = "1.1.2"; + edition = "2021"; + sha256 = "1w510wnixvlgimkx1zjbvlxh6xps2vjgfqgwf5a6adlbjp5rv5mj"; + libName = "aho_corasick"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "memchr"; + packageId = "memchr"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" "perf-literal" ]; + "logging" = [ "dep:log" ]; + "perf-literal" = [ "dep:memchr" ]; + "std" = [ "memchr?/std" ]; + }; + resolvedDefaultFeatures = [ "perf-literal" "std" ]; + }; + "anymap2" = rec { + crateName = "anymap2"; + version = "0.13.0"; + edition = "2018"; + sha256 = "031kw3bp0zh2pn9fcayaw0w0gydgpgfhm08pg4yz5cml9jwv60fk"; + authors = [ + "Chris Morgan <me@chrismorgan.info>" + "Azriel Hoh <azriel91@gmail.com>" + ]; + + }; + "autocfg" = rec { + crateName = "autocfg"; + version = "1.3.0"; + edition = "2015"; + sha256 = "1c3njkfzpil03k92q0mij5y1pkhhfr4j3bf0h53bgl2vs85lsjqc"; + authors = [ + "Josh Stone <cuviper@gmail.com>" + ]; + + }; + "backtrace" = rec { + crateName = "backtrace"; + version = "0.3.73"; + edition = "2021"; + sha256 = "02iffg2pkg5nc36pgml8il7f77s138hhjw9f9l56v5zqlilk5hjw"; + authors = [ + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "addr2line"; + packageId = "addr2line"; + usesDefaultFeatures = false; + target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); + } + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "libc"; + packageId = "libc"; + usesDefaultFeatures = false; + target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); + } + { + name = "miniz_oxide"; + packageId = "miniz_oxide"; + usesDefaultFeatures = false; + target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); + } + { + name = "object"; + packageId = "object"; + usesDefaultFeatures = false; + target = { target, features }: (!((target."windows" or false) && ("msvc" == target."env" or null) && (!("uwp" == target."vendor" or null)))); + features = [ "read_core" "elf" "macho" "pe" "xcoff" "unaligned" "archive" ]; + } + { + name = "rustc-demangle"; + packageId = "rustc-demangle"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cpp_demangle" = [ "dep:cpp_demangle" ]; + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + "serialize-serde" = [ "serde" ]; + "verify-winapi" = [ "winapi/dbghelp" "winapi/handleapi" "winapi/libloaderapi" "winapi/memoryapi" "winapi/minwindef" "winapi/processthreadsapi" "winapi/synchapi" "winapi/tlhelp32" "winapi/winbase" "winapi/winnt" "winapi/winnls" "winapi/stringapiset" ]; + "winapi" = [ "dep:winapi" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "bincode" = rec { + crateName = "bincode"; + version = "1.3.3"; + edition = "2015"; + sha256 = "1bfw3mnwzx5g1465kiqllp5n4r10qrqy88kdlp3jfwnq2ya5xx5i"; + authors = [ + "Ty Overby <ty@pre-alpha.com>" + "Francesco Mazzoli <f@mazzo.li>" + "David Tolnay <dtolnay@gmail.com>" + "Zoey Riordan <zoey@dos.cafe>" + ]; + dependencies = [ + { + name = "serde"; + packageId = "serde"; + } + ]; + features = { }; + }; + "bitflags 1.3.2" = rec { + crateName = "bitflags"; + version = "1.3.2"; + edition = "2018"; + sha256 = "12ki6w8gn1ldq7yz9y680llwk5gmrhrzszaa17g1sbrw2r2qvwxy"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "bitflags 2.4.1" = rec { + crateName = "bitflags"; + version = "2.4.1"; + edition = "2021"; + sha256 = "01ryy3kd671b0ll4bhdvhsz67vwz1lz53fz504injrd7wpv64xrj"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "bytemuck" = [ "dep:bytemuck" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + "serde" = [ "dep:serde" ]; + }; + }; + "block-buffer" = rec { + crateName = "block-buffer"; + version = "0.10.4"; + edition = "2018"; + sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "generic-array"; + packageId = "generic-array"; + } + ]; + + }; + "boolinator" = rec { + crateName = "boolinator"; + version = "2.4.0"; + edition = "2015"; + sha256 = "1nccxzb1dfkjfrgzqaw1a90p26zlvv6nah5ckcpj6bn9a4zqga6g"; + authors = [ + "Daniel Keep <daniel.keep@gmail.com>" + ]; + + }; + "bstr" = rec { + crateName = "bstr"; + version = "1.10.0"; + edition = "2021"; + sha256 = "036wwrchd5gq3q4k6w1j2bfl2bk2ff8c0dsa9y7w7aw7nf7knwj0"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + { + name = "regex-automata"; + packageId = "regex-automata"; + optional = true; + usesDefaultFeatures = false; + features = [ "dfa-search" ]; + } + { + name = "serde"; + packageId = "serde"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "memchr/alloc" "serde?/alloc" ]; + "default" = [ "std" "unicode" ]; + "serde" = [ "dep:serde" ]; + "std" = [ "alloc" "memchr/std" "serde?/std" ]; + "unicode" = [ "dep:regex-automata" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "serde" "std" "unicode" ]; + }; + "bumpalo" = rec { + crateName = "bumpalo"; + version = "3.16.0"; + edition = "2021"; + sha256 = "0b015qb4knwanbdlp1x48pkb4pm57b8gidbhhhxr900q2wb6fabr"; + authors = [ + "Nick Fitzgerald <fitzgen@gmail.com>" + ]; + features = { + "allocator-api2" = [ "dep:allocator-api2" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "bytes" = rec { + crateName = "bytes"; + version = "1.7.1"; + edition = "2018"; + sha256 = "0l5sf69avjxcw41cznyzxsnymwmkpmk08q0sm7fgicvvn0ysa643"; + authors = [ + "Carl Lerche <me@carllerche.com>" + "Sean McArthur <sean@seanmonstar.com>" + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "cc" = rec { + crateName = "cc"; + version = "1.1.7"; + edition = "2018"; + sha256 = "1g2w088mkhlyji5cpsw34mzppn5jcb9h2d9sga4y677sggyw7996"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + features = { + "parallel" = [ "dep:libc" "dep:jobserver" ]; + }; + }; + "cfg-if" = rec { + crateName = "cfg-if"; + version = "1.0.0"; + edition = "2018"; + sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + }; + }; + "codemap" = rec { + crateName = "codemap"; + version = "0.1.3"; + edition = "2015"; + sha256 = "091azkslwkcijj3lp9ymb084y9a0wm4fkil7m613ja68r2snkrxr"; + authors = [ + "Kevin Mehall <km@kevinmehall.net>" + ]; + + }; + "codemap-diagnostic" = rec { + crateName = "codemap-diagnostic"; + version = "0.1.2"; + edition = "2015"; + sha256 = "08l1b84bn8r8a72rbvyi2v8a5i0j0kk0a5gr7fb6lmjvw05pf86c"; + libName = "codemap_diagnostic"; + authors = [ + "Kevin Mehall <km@kevinmehall.net>" + "The Rust Project Developers" + ]; + dependencies = [ + { + name = "codemap"; + packageId = "codemap"; + } + { + name = "termcolor"; + packageId = "termcolor"; + } + ]; + + }; + "console_error_panic_hook" = rec { + crateName = "console_error_panic_hook"; + version = "0.1.7"; + edition = "2015"; + sha256 = "1g5v8s0ndycc10mdn6igy914k645pgpcl8vjpz6nvxkhyirynsm0"; + authors = [ + "Nick Fitzgerald <fitzgen@gmail.com>" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + ]; + + }; + "countme" = rec { + crateName = "countme"; + version = "3.0.1"; + edition = "2018"; + sha256 = "0dn62hhvgmwyxslh14r4nlbvz8h50cp5mnn1qhqsw63vs7yva13p"; + authors = [ + "Aleksey Kladov <aleksey.kladov@gmail.com>" + ]; + features = { + "dashmap" = [ "dep:dashmap" ]; + "enable" = [ "dashmap" "once_cell" "rustc-hash" ]; + "once_cell" = [ "dep:once_cell" ]; + "print_at_exit" = [ "enable" ]; + "rustc-hash" = [ "dep:rustc-hash" ]; + }; + }; + "cpufeatures" = rec { + crateName = "cpufeatures"; + version = "0.2.12"; + edition = "2018"; + sha256 = "012m7rrak4girqlii3jnqwrr73gv1i980q4wra5yyyhvzwk5xzjk"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-linux-android"); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (("aarch64" == target."arch" or null) && ("linux" == target."os" or null)); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (("aarch64" == target."arch" or null) && ("apple" == target."vendor" or null)); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (("loongarch64" == target."arch" or null) && ("linux" == target."os" or null)); + } + ]; + + }; + "crypto-common" = rec { + crateName = "crypto-common"; + version = "0.1.6"; + edition = "2018"; + sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "generic-array"; + packageId = "generic-array"; + features = [ "more_lengths" ]; + } + { + name = "typenum"; + packageId = "typenum"; + } + ]; + features = { + "getrandom" = [ "rand_core/getrandom" ]; + "rand_core" = [ "dep:rand_core" ]; + }; + resolvedDefaultFeatures = [ "std" ]; + }; + "data-encoding" = rec { + crateName = "data-encoding"; + version = "2.6.0"; + edition = "2018"; + sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; + authors = [ + "Julien Cretin <git@ia0.eu>" + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "digest" = rec { + crateName = "digest"; + version = "0.10.7"; + edition = "2018"; + sha256 = "14p2n6ih29x81akj097lvz7wi9b6b9hvls0lwrv7b6xwyy0s5ncy"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "block-buffer"; + packageId = "block-buffer"; + optional = true; + } + { + name = "crypto-common"; + packageId = "crypto-common"; + } + ]; + features = { + "blobby" = [ "dep:blobby" ]; + "block-buffer" = [ "dep:block-buffer" ]; + "const-oid" = [ "dep:const-oid" ]; + "core-api" = [ "block-buffer" ]; + "default" = [ "core-api" ]; + "dev" = [ "blobby" ]; + "mac" = [ "subtle" ]; + "oid" = [ "const-oid" ]; + "rand_core" = [ "crypto-common/rand_core" ]; + "std" = [ "alloc" "crypto-common/std" ]; + "subtle" = [ "dep:subtle" ]; + }; + resolvedDefaultFeatures = [ "alloc" "block-buffer" "core-api" "default" "std" ]; + }; + "dirs" = rec { + crateName = "dirs"; + version = "4.0.0"; + edition = "2015"; + sha256 = "0n8020zl4f0frfnzvgb9agvk4a14i1kjz4daqnxkgslndwmaffna"; + authors = [ + "Simon Ochsenreither <simon@ochsenreither.de>" + ]; + dependencies = [ + { + name = "dirs-sys"; + packageId = "dirs-sys"; + } + ]; + + }; + "dirs-sys" = rec { + crateName = "dirs-sys"; + version = "0.3.7"; + edition = "2015"; + sha256 = "19md1cnkazham8a6kh22v12d8hh3raqahfk6yb043vrjr68is78v"; + libName = "dirs_sys"; + authors = [ + "Simon Ochsenreither <simon@ochsenreither.de>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "redox_users"; + packageId = "redox_users"; + usesDefaultFeatures = false; + target = { target, features }: ("redox" == target."os" or null); + } + { + name = "winapi"; + packageId = "winapi"; + target = { target, features }: (target."windows" or false); + features = [ "knownfolders" "objbase" "shlobj" "winbase" "winerror" ]; + } + ]; + + }; + "either" = rec { + crateName = "either"; + version = "1.9.0"; + edition = "2018"; + sha256 = "01qy3anr7jal5lpc20791vxrw0nl6vksb5j7x56q2fycgcyy8sm2"; + authors = [ + "bluss" + ]; + features = { + "default" = [ "use_std" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "use_std" ]; + }; + "equivalent" = rec { + crateName = "equivalent"; + version = "1.0.1"; + edition = "2015"; + sha256 = "1malmx5f4lkfvqasz319lq6gb3ddg19yzf9s8cykfsgzdmyq0hsl"; + + }; + "fnv" = rec { + crateName = "fnv"; + version = "1.0.7"; + edition = "2015"; + sha256 = "1hc2mcqha06aibcaza94vbi81j6pr9a1bbxrxjfhc91zin8yr7iz"; + libPath = "lib.rs"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "form_urlencoded" = rec { + crateName = "form_urlencoded"; + version = "1.2.1"; + edition = "2018"; + sha256 = "0milh8x7nl4f450s3ddhg57a3flcv6yq8hlkyk6fyr3mcb128dp1"; + authors = [ + "The rust-url developers" + ]; + dependencies = [ + { + name = "percent-encoding"; + packageId = "percent-encoding"; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "percent-encoding/alloc" ]; + "default" = [ "std" ]; + "std" = [ "alloc" "percent-encoding/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "futures" = rec { + crateName = "futures"; + version = "0.3.30"; + edition = "2018"; + sha256 = "1c04g14bccmprwsvx2j9m2blhwrynq7vhl151lsvcv4gi0b6jp34"; + dependencies = [ + { + name = "futures-channel"; + packageId = "futures-channel"; + usesDefaultFeatures = false; + features = [ "sink" ]; + } + { + name = "futures-core"; + packageId = "futures-core"; + usesDefaultFeatures = false; + } + { + name = "futures-io"; + packageId = "futures-io"; + usesDefaultFeatures = false; + } + { + name = "futures-sink"; + packageId = "futures-sink"; + usesDefaultFeatures = false; + } + { + name = "futures-task"; + packageId = "futures-task"; + usesDefaultFeatures = false; + } + { + name = "futures-util"; + packageId = "futures-util"; + usesDefaultFeatures = false; + features = [ "sink" ]; + } + ]; + features = { + "alloc" = [ "futures-core/alloc" "futures-task/alloc" "futures-sink/alloc" "futures-channel/alloc" "futures-util/alloc" ]; + "async-await" = [ "futures-util/async-await" "futures-util/async-await-macro" ]; + "bilock" = [ "futures-util/bilock" ]; + "compat" = [ "std" "futures-util/compat" ]; + "default" = [ "std" "async-await" "executor" ]; + "executor" = [ "std" "futures-executor/std" ]; + "futures-executor" = [ "dep:futures-executor" ]; + "io-compat" = [ "compat" "futures-util/io-compat" ]; + "std" = [ "alloc" "futures-core/std" "futures-task/std" "futures-io/std" "futures-sink/std" "futures-util/std" "futures-util/io" "futures-util/channel" ]; + "thread-pool" = [ "executor" "futures-executor/thread-pool" ]; + "unstable" = [ "futures-core/unstable" "futures-task/unstable" "futures-channel/unstable" "futures-io/unstable" "futures-util/unstable" ]; + "write-all-vectored" = [ "futures-util/write-all-vectored" ]; + }; + resolvedDefaultFeatures = [ "alloc" "async-await" "std" ]; + }; + "futures-channel" = rec { + crateName = "futures-channel"; + version = "0.3.30"; + edition = "2018"; + sha256 = "0y6b7xxqdjm9hlcjpakcg41qfl7lihf6gavk8fyqijsxhvbzgj7a"; + libName = "futures_channel"; + dependencies = [ + { + name = "futures-core"; + packageId = "futures-core"; + usesDefaultFeatures = false; + } + { + name = "futures-sink"; + packageId = "futures-sink"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "futures-core/alloc" ]; + "default" = [ "std" ]; + "futures-sink" = [ "dep:futures-sink" ]; + "sink" = [ "futures-sink" ]; + "std" = [ "alloc" "futures-core/std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "futures-sink" "sink" "std" ]; + }; + "futures-core" = rec { + crateName = "futures-core"; + version = "0.3.30"; + edition = "2018"; + sha256 = "07aslayrn3lbggj54kci0ishmd1pr367fp7iks7adia1p05miinz"; + libName = "futures_core"; + features = { + "default" = [ "std" ]; + "portable-atomic" = [ "dep:portable-atomic" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "futures-io" = rec { + crateName = "futures-io"; + version = "0.3.30"; + edition = "2018"; + sha256 = "1hgh25isvsr4ybibywhr4dpys8mjnscw4wfxxwca70cn1gi26im4"; + libName = "futures_io"; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "std" ]; + }; + "futures-macro" = rec { + crateName = "futures-macro"; + version = "0.3.30"; + edition = "2018"; + sha256 = "1b49qh9d402y8nka4q6wvvj0c88qq91wbr192mdn5h54nzs0qxc7"; + procMacro = true; + libName = "futures_macro"; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + features = [ "full" ]; + } + ]; + + }; + "futures-sink" = rec { + crateName = "futures-sink"; + version = "0.3.30"; + edition = "2018"; + sha256 = "1dag8xyyaya8n8mh8smx7x6w2dpmafg2din145v973a3hw7f1f4z"; + libName = "futures_sink"; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "futures-task" = rec { + crateName = "futures-task"; + version = "0.3.30"; + edition = "2018"; + sha256 = "013h1724454hj8qczp8vvs10qfiqrxr937qsrv6rhii68ahlzn1q"; + libName = "futures_task"; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "std" ]; + }; + "futures-util" = rec { + crateName = "futures-util"; + version = "0.3.30"; + edition = "2018"; + sha256 = "0j0xqhcir1zf2dcbpd421kgw6wvsk0rpxflylcysn1rlp3g02r1x"; + libName = "futures_util"; + dependencies = [ + { + name = "futures-channel"; + packageId = "futures-channel"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "futures-core"; + packageId = "futures-core"; + usesDefaultFeatures = false; + } + { + name = "futures-io"; + packageId = "futures-io"; + optional = true; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "futures-macro"; + packageId = "futures-macro"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "futures-sink"; + packageId = "futures-sink"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "futures-task"; + packageId = "futures-task"; + usesDefaultFeatures = false; + } + { + name = "memchr"; + packageId = "memchr"; + optional = true; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "pin-utils"; + packageId = "pin-utils"; + } + { + name = "slab"; + packageId = "slab"; + optional = true; + } + ]; + features = { + "alloc" = [ "futures-core/alloc" "futures-task/alloc" ]; + "async-await-macro" = [ "async-await" "futures-macro" ]; + "channel" = [ "std" "futures-channel" ]; + "compat" = [ "std" "futures_01" ]; + "default" = [ "std" "async-await" "async-await-macro" ]; + "futures-channel" = [ "dep:futures-channel" ]; + "futures-io" = [ "dep:futures-io" ]; + "futures-macro" = [ "dep:futures-macro" ]; + "futures-sink" = [ "dep:futures-sink" ]; + "futures_01" = [ "dep:futures_01" ]; + "io" = [ "std" "futures-io" "memchr" ]; + "io-compat" = [ "io" "compat" "tokio-io" ]; + "memchr" = [ "dep:memchr" ]; + "portable-atomic" = [ "futures-core/portable-atomic" ]; + "sink" = [ "futures-sink" ]; + "slab" = [ "dep:slab" ]; + "std" = [ "alloc" "futures-core/std" "futures-task/std" "slab" ]; + "tokio-io" = [ "dep:tokio-io" ]; + "unstable" = [ "futures-core/unstable" "futures-task/unstable" ]; + "write-all-vectored" = [ "io" ]; + }; + resolvedDefaultFeatures = [ "alloc" "async-await" "async-await-macro" "channel" "futures-channel" "futures-io" "futures-macro" "futures-sink" "io" "memchr" "sink" "slab" "std" ]; + }; + "genawaiter" = rec { + crateName = "genawaiter"; + version = "0.99.1"; + edition = "2018"; + sha256 = "1861a6vy9lc9a8lbw496m9j9jcjcn9nf7rkm6jqkkpnb3cvd0sy8"; + authors = [ + "John Simon <john@whatisaph.one>" + ]; + dependencies = [ + { + name = "genawaiter-macro"; + packageId = "genawaiter-macro"; + } + ]; + features = { + "default" = [ "proc_macro" ]; + "futures-core" = [ "dep:futures-core" ]; + "futures03" = [ "futures-core" ]; + "genawaiter-proc-macro" = [ "dep:genawaiter-proc-macro" ]; + "proc-macro-hack" = [ "dep:proc-macro-hack" ]; + "proc_macro" = [ "genawaiter-proc-macro" "proc-macro-hack" "genawaiter-macro/proc_macro" ]; + }; + }; + "genawaiter-macro" = rec { + crateName = "genawaiter-macro"; + version = "0.99.1"; + edition = "2018"; + sha256 = "1g6zmr88fk48f1ksz9ik1i2mwjsiam9s4p9aybhvs2zwzphxychb"; + libName = "genawaiter_macro"; + authors = [ + "Devin R <devin.ragotzy@gmail.com>" + ]; + features = { }; + }; + "generic-array" = rec { + crateName = "generic-array"; + version = "0.14.7"; + edition = "2015"; + sha256 = "16lyyrzrljfq424c3n8kfwkqihlimmsg5nhshbbp48np3yjrqr45"; + libName = "generic_array"; + authors = [ + "Bartłomiej Kamiński <fizyk20@gmail.com>" + "Aaron Trent <novacrazy@gmail.com>" + ]; + dependencies = [ + { + name = "typenum"; + packageId = "typenum"; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "serde" = [ "dep:serde" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + resolvedDefaultFeatures = [ "more_lengths" ]; + }; + "getrandom" = rec { + crateName = "getrandom"; + version = "0.2.15"; + edition = "2018"; + sha256 = "1mzlnrb3dgyd1fb84gvw10pyr8wdqdl4ry4sr64i1s8an66pqmn4"; + authors = [ + "The Rand Project Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "js-sys"; + packageId = "js-sys"; + optional = true; + target = { target, features }: ((("wasm32" == target."arch" or null) || ("wasm64" == target."arch" or null)) && ("unknown" == target."os" or null)); + } + { + name = "libc"; + packageId = "libc"; + usesDefaultFeatures = false; + target = { target, features }: (target."unix" or false); + } + { + name = "wasi"; + packageId = "wasi"; + usesDefaultFeatures = false; + target = { target, features }: ("wasi" == target."os" or null); + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: ((("wasm32" == target."arch" or null) || ("wasm64" == target."arch" or null)) && ("unknown" == target."os" or null)); + } + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "js" = [ "wasm-bindgen" "js-sys" ]; + "js-sys" = [ "dep:js-sys" ]; + "rustc-dep-of-std" = [ "compiler_builtins" "core" "libc/rustc-dep-of-std" "wasi/rustc-dep-of-std" ]; + "wasm-bindgen" = [ "dep:wasm-bindgen" ]; + }; + resolvedDefaultFeatures = [ "js" "js-sys" "std" "wasm-bindgen" ]; + }; + "gimli" = rec { + crateName = "gimli"; + version = "0.29.0"; + edition = "2018"; + sha256 = "1zgzprnjaawmg6zyic4f2q2hc39kdhn116qnkqpgvsasgc3x9v20"; + features = { + "default" = [ "read-all" "write" ]; + "endian-reader" = [ "read" "dep:stable_deref_trait" ]; + "fallible-iterator" = [ "dep:fallible-iterator" ]; + "read" = [ "read-core" ]; + "read-all" = [ "read" "std" "fallible-iterator" "endian-reader" ]; + "rustc-dep-of-std" = [ "dep:core" "dep:alloc" "dep:compiler_builtins" ]; + "std" = [ "fallible-iterator?/std" "stable_deref_trait?/std" ]; + "write" = [ "dep:indexmap" ]; + }; + resolvedDefaultFeatures = [ "read" "read-core" ]; + }; + "gloo 0.10.0" = rec { + crateName = "gloo"; + version = "0.10.0"; + edition = "2021"; + sha256 = "0j82hwfn6ibqla1q849vhsmxnxw6wmnjkmmffzdw2mfc51n54dfd"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "gloo-console"; + packageId = "gloo-console 0.3.0"; + optional = true; + } + { + name = "gloo-dialogs"; + packageId = "gloo-dialogs 0.2.0"; + optional = true; + } + { + name = "gloo-events"; + packageId = "gloo-events 0.2.0"; + optional = true; + } + { + name = "gloo-file"; + packageId = "gloo-file 0.3.0"; + optional = true; + } + { + name = "gloo-history"; + packageId = "gloo-history 0.2.2"; + optional = true; + } + { + name = "gloo-net"; + packageId = "gloo-net 0.4.0"; + optional = true; + } + { + name = "gloo-render"; + packageId = "gloo-render 0.2.0"; + optional = true; + } + { + name = "gloo-storage"; + packageId = "gloo-storage 0.3.0"; + optional = true; + } + { + name = "gloo-timers"; + packageId = "gloo-timers 0.3.0"; + optional = true; + } + { + name = "gloo-utils"; + packageId = "gloo-utils 0.2.0"; + optional = true; + } + { + name = "gloo-worker"; + packageId = "gloo-worker 0.4.0"; + optional = true; + } + ]; + features = { + "console" = [ "gloo-console" ]; + "default" = [ "timers" "events" "file" "dialogs" "storage" "render" "console" "utils" "history" "worker" "net" ]; + "dialogs" = [ "gloo-dialogs" ]; + "events" = [ "gloo-events" ]; + "file" = [ "gloo-file" ]; + "futures" = [ "timers" "file" "worker" "gloo-timers/futures" "gloo-file/futures" "gloo-worker/futures" ]; + "gloo-console" = [ "dep:gloo-console" ]; + "gloo-dialogs" = [ "dep:gloo-dialogs" ]; + "gloo-events" = [ "dep:gloo-events" ]; + "gloo-file" = [ "dep:gloo-file" ]; + "gloo-history" = [ "dep:gloo-history" ]; + "gloo-net" = [ "dep:gloo-net" ]; + "gloo-render" = [ "dep:gloo-render" ]; + "gloo-storage" = [ "dep:gloo-storage" ]; + "gloo-timers" = [ "dep:gloo-timers" ]; + "gloo-utils" = [ "dep:gloo-utils" ]; + "gloo-worker" = [ "dep:gloo-worker" ]; + "history" = [ "gloo-history" ]; + "net" = [ "gloo-net" ]; + "render" = [ "gloo-render" ]; + "storage" = [ "gloo-storage" ]; + "timers" = [ "gloo-timers" ]; + "utils" = [ "gloo-utils" ]; + "worker" = [ "gloo-worker" ]; + }; + resolvedDefaultFeatures = [ "console" "default" "dialogs" "events" "file" "futures" "gloo-console" "gloo-dialogs" "gloo-events" "gloo-file" "gloo-history" "gloo-net" "gloo-render" "gloo-storage" "gloo-timers" "gloo-utils" "gloo-worker" "history" "net" "render" "storage" "timers" "utils" "worker" ]; + }; + "gloo 0.8.1" = rec { + crateName = "gloo"; + version = "0.8.1"; + edition = "2018"; + sha256 = "0kdr8ahxl77fby89fvfwq13kqqyyw63pnjpv6gynz4gnbvd9r698"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "gloo-console"; + packageId = "gloo-console 0.2.3"; + optional = true; + } + { + name = "gloo-dialogs"; + packageId = "gloo-dialogs 0.1.1"; + optional = true; + } + { + name = "gloo-events"; + packageId = "gloo-events 0.1.2"; + optional = true; + } + { + name = "gloo-file"; + packageId = "gloo-file 0.2.3"; + optional = true; + } + { + name = "gloo-history"; + packageId = "gloo-history 0.1.5"; + optional = true; + } + { + name = "gloo-net"; + packageId = "gloo-net 0.3.1"; + optional = true; + } + { + name = "gloo-render"; + packageId = "gloo-render 0.1.1"; + optional = true; + } + { + name = "gloo-storage"; + packageId = "gloo-storage 0.2.2"; + optional = true; + } + { + name = "gloo-timers"; + packageId = "gloo-timers 0.2.6"; + optional = true; + } + { + name = "gloo-utils"; + packageId = "gloo-utils 0.1.7"; + optional = true; + } + { + name = "gloo-worker"; + packageId = "gloo-worker 0.2.1"; + optional = true; + } + ]; + features = { + "console" = [ "gloo-console" ]; + "default" = [ "timers" "events" "file" "dialogs" "storage" "render" "console" "utils" "history" "worker" "net" ]; + "dialogs" = [ "gloo-dialogs" ]; + "events" = [ "gloo-events" ]; + "file" = [ "gloo-file" ]; + "futures" = [ "timers" "file" "worker" "gloo-timers/futures" "gloo-file/futures" "gloo-worker/futures" ]; + "gloo-console" = [ "dep:gloo-console" ]; + "gloo-dialogs" = [ "dep:gloo-dialogs" ]; + "gloo-events" = [ "dep:gloo-events" ]; + "gloo-file" = [ "dep:gloo-file" ]; + "gloo-history" = [ "dep:gloo-history" ]; + "gloo-net" = [ "dep:gloo-net" ]; + "gloo-render" = [ "dep:gloo-render" ]; + "gloo-storage" = [ "dep:gloo-storage" ]; + "gloo-timers" = [ "dep:gloo-timers" ]; + "gloo-utils" = [ "dep:gloo-utils" ]; + "gloo-worker" = [ "dep:gloo-worker" ]; + "history" = [ "gloo-history" ]; + "net" = [ "gloo-net" ]; + "render" = [ "gloo-render" ]; + "storage" = [ "gloo-storage" ]; + "timers" = [ "gloo-timers" ]; + "utils" = [ "gloo-utils" ]; + "worker" = [ "gloo-worker" ]; + }; + resolvedDefaultFeatures = [ "console" "default" "dialogs" "events" "file" "gloo-console" "gloo-dialogs" "gloo-events" "gloo-file" "gloo-history" "gloo-net" "gloo-render" "gloo-storage" "gloo-timers" "gloo-utils" "gloo-worker" "history" "net" "render" "storage" "timers" "utils" "worker" ]; + }; + "gloo-console 0.2.3" = rec { + crateName = "gloo-console"; + version = "0.2.3"; + edition = "2018"; + sha256 = "0gqd35vn0i5y6hzfrsb2i032p1j832c08sar6dr19gny0lycxdw2"; + libName = "gloo_console"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "gloo-utils"; + packageId = "gloo-utils 0.1.7"; + features = [ "serde" ]; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "console" "Document" ]; + } + ]; + + }; + "gloo-console 0.3.0" = rec { + crateName = "gloo-console"; + version = "0.3.0"; + edition = "2021"; + sha256 = "0qg24wbvql0bsr980hbrm0pi11c3jmlwpj0pgdklz8mlas7qc5ra"; + libName = "gloo_console"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "gloo-utils"; + packageId = "gloo-utils 0.2.0"; + features = [ "serde" ]; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "console" "Document" ]; + } + ]; + + }; + "gloo-dialogs 0.1.1" = rec { + crateName = "gloo-dialogs"; + version = "0.1.1"; + edition = "2018"; + sha256 = "1rh2j0l8rbj8pbypxqy99qi2x3hq52sclijs8h47zlkjmij261k7"; + libName = "gloo_dialogs"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Window" ]; + } + ]; + + }; + "gloo-dialogs 0.2.0" = rec { + crateName = "gloo-dialogs"; + version = "0.2.0"; + edition = "2021"; + sha256 = "1pqmg2z3x4c3id25jd0p8rjwy5qjbc4k1x8gflsi9c1207hlhixz"; + libName = "gloo_dialogs"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Window" ]; + } + ]; + + }; + "gloo-events 0.1.2" = rec { + crateName = "gloo-events"; + version = "0.1.2"; + edition = "2018"; + sha256 = "1z4j14r2lim77s0jm1dpk306jyycmx2kirid33j0b0gdmgw0gcb8"; + libName = "gloo_events"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Event" "EventTarget" "AddEventListenerOptions" ]; + } + ]; + devDependencies = [ + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "HtmlElement" "Window" "Document" "Element" "MouseEvent" "ProgressEvent" ]; + } + ]; + + }; + "gloo-events 0.2.0" = rec { + crateName = "gloo-events"; + version = "0.2.0"; + edition = "2021"; + sha256 = "0h8yr4n1pvwp4rr87835w14kjdkycyn8gypmh2lmnf3wbys6zhi7"; + libName = "gloo_events"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Event" "EventTarget" "AddEventListenerOptions" ]; + } + ]; + devDependencies = [ + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "HtmlElement" "Window" "Document" "Element" "MouseEvent" "ProgressEvent" ]; + } + ]; + + }; + "gloo-file 0.2.3" = rec { + crateName = "gloo-file"; + version = "0.2.3"; + edition = "2018"; + sha256 = "1mxnd7l8gglv5yqhah6ny329hc0c98vn7h5xg0yv8f0aax75dmd8"; + libName = "gloo_file"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "gloo-events"; + packageId = "gloo-events 0.1.2"; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Blob" "File" "FileList" "FileReader" "HtmlInputElement" "BlobPropertyBag" "FilePropertyBag" "DomException" "Url" ]; + } + ]; + devDependencies = [ + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Window" "Response" ]; + } + ]; + features = { + "futures" = [ "futures-channel" ]; + "futures-channel" = [ "dep:futures-channel" ]; + "mime" = [ "dep:mime" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "gloo-file 0.3.0" = rec { + crateName = "gloo-file"; + version = "0.3.0"; + edition = "2021"; + sha256 = "07xxainnnrg6l3ccw2bvqiz4m76ih557aklp5r5q5cizhrqksmlp"; + libName = "gloo_file"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "futures-channel"; + packageId = "futures-channel"; + optional = true; + } + { + name = "gloo-events"; + packageId = "gloo-events 0.2.0"; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Blob" "File" "FileList" "FileReader" "HtmlInputElement" "BlobPropertyBag" "FilePropertyBag" "DomException" "Url" ]; + } + ]; + devDependencies = [ + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Window" "Response" ]; + } + ]; + features = { + "futures" = [ "futures-channel" ]; + "futures-channel" = [ "dep:futures-channel" ]; + "mime" = [ "dep:mime" ]; + }; + resolvedDefaultFeatures = [ "default" "futures" "futures-channel" ]; + }; + "gloo-history 0.1.5" = rec { + crateName = "gloo-history"; + version = "0.1.5"; + edition = "2018"; + sha256 = "0zsy3m5bgah8hyd95sc9b68afn1nhs7g43lkndip1m0fpy85swl5"; + libName = "gloo_history"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "gloo-events"; + packageId = "gloo-events 0.1.2"; + } + { + name = "gloo-utils"; + packageId = "gloo-utils 0.1.7"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "serde-wasm-bindgen"; + packageId = "serde-wasm-bindgen 0.5.0"; + } + { + name = "serde_urlencoded"; + packageId = "serde_urlencoded"; + optional = true; + } + { + name = "thiserror"; + packageId = "thiserror"; + optional = true; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "History" "Window" "Location" "Url" ]; + } + ]; + features = { + "default" = [ "query" ]; + "query" = [ "thiserror" "serde_urlencoded" ]; + "serde_urlencoded" = [ "dep:serde_urlencoded" ]; + "thiserror" = [ "dep:thiserror" ]; + }; + resolvedDefaultFeatures = [ "default" "query" "serde_urlencoded" "thiserror" ]; + }; + "gloo-history 0.2.2" = rec { + crateName = "gloo-history"; + version = "0.2.2"; + edition = "2021"; + sha256 = "1mhphqywgbqj4agpi4zyc4hah12nys7085jymiz44d5swlml6gwh"; + libName = "gloo_history"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "getrandom"; + packageId = "getrandom"; + target = { target, features }: ("wasm32" == target."arch" or null); + features = [ "js" ]; + } + { + name = "gloo-events"; + packageId = "gloo-events 0.2.0"; + } + { + name = "gloo-utils"; + packageId = "gloo-utils 0.2.0"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "serde-wasm-bindgen"; + packageId = "serde-wasm-bindgen 0.6.5"; + } + { + name = "serde_urlencoded"; + packageId = "serde_urlencoded"; + optional = true; + } + { + name = "thiserror"; + packageId = "thiserror"; + optional = true; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "History" "Window" "Location" "Url" ]; + } + ]; + features = { + "default" = [ "query" ]; + "query" = [ "thiserror" "serde_urlencoded" ]; + "serde_urlencoded" = [ "dep:serde_urlencoded" ]; + "thiserror" = [ "dep:thiserror" ]; + }; + resolvedDefaultFeatures = [ "default" "query" "serde_urlencoded" "thiserror" ]; + }; + "gloo-net 0.3.1" = rec { + crateName = "gloo-net"; + version = "0.3.1"; + edition = "2018"; + sha256 = "0866ih3bff7dwxdfc813pk5nwz2ayyqwi5vbzlax7n4ygly4wsx6"; + libName = "gloo_net"; + authors = [ + "Rust and WebAssembly Working Group" + "Muhammad Hamza <muhammadhamza1311@gmail.com>" + ]; + dependencies = [ + { + name = "futures-channel"; + packageId = "futures-channel"; + optional = true; + } + { + name = "futures-core"; + packageId = "futures-core"; + optional = true; + } + { + name = "futures-sink"; + packageId = "futures-sink"; + optional = true; + } + { + name = "gloo-utils"; + packageId = "gloo-utils 0.1.7"; + usesDefaultFeatures = false; + } + { + name = "http"; + packageId = "http"; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "pin-project"; + packageId = "pin-project"; + optional = true; + } + { + name = "serde"; + packageId = "serde"; + optional = true; + } + { + name = "serde_json"; + packageId = "serde_json"; + optional = true; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "wasm-bindgen-futures"; + packageId = "wasm-bindgen-futures"; + } + { + name = "web-sys"; + packageId = "web-sys"; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + ]; + features = { + "default" = [ "json" "websocket" "http" "eventsource" ]; + "eventsource" = [ "futures-channel" "futures-core" "pin-project" "web-sys/Event" "web-sys/EventTarget" "web-sys/EventSource" "web-sys/MessageEvent" ]; + "futures-channel" = [ "dep:futures-channel" ]; + "futures-core" = [ "dep:futures-core" ]; + "futures-sink" = [ "dep:futures-sink" ]; + "http" = [ "web-sys/Headers" "web-sys/UrlSearchParams" "web-sys/Url" "web-sys/Request" "web-sys/RequestInit" "web-sys/RequestMode" "web-sys/Response" "web-sys/ResponseInit" "web-sys/ResponseType" "web-sys/Window" "web-sys/RequestCache" "web-sys/RequestCredentials" "web-sys/ObserverCallback" "web-sys/RequestRedirect" "web-sys/ReferrerPolicy" "web-sys/AbortSignal" "web-sys/ReadableStream" "web-sys/Blob" "web-sys/FormData" "web-sys/WorkerGlobalScope" ]; + "json" = [ "serde" "serde_json" "gloo-utils/serde" ]; + "pin-project" = [ "dep:pin-project" ]; + "serde" = [ "dep:serde" ]; + "serde_json" = [ "dep:serde_json" ]; + "websocket" = [ "web-sys/WebSocket" "web-sys/AddEventListenerOptions" "web-sys/ErrorEvent" "web-sys/FileReader" "web-sys/MessageEvent" "web-sys/ProgressEvent" "web-sys/CloseEvent" "web-sys/CloseEventInit" "web-sys/BinaryType" "web-sys/Blob" "futures-channel" "futures-core" "futures-sink" "pin-project" ]; + }; + resolvedDefaultFeatures = [ "default" "eventsource" "futures-channel" "futures-core" "futures-sink" "http" "json" "pin-project" "serde" "serde_json" "websocket" ]; + }; + "gloo-net 0.4.0" = rec { + crateName = "gloo-net"; + version = "0.4.0"; + edition = "2021"; + sha256 = "1i3x5fvp07valrxjsa25ycq1b2p3pxqaqmw6kzx35ip2i8lfijca"; + libName = "gloo_net"; + authors = [ + "Rust and WebAssembly Working Group" + "Muhammad Hamza <muhammadhamza1311@gmail.com>" + ]; + dependencies = [ + { + name = "futures-channel"; + packageId = "futures-channel"; + optional = true; + } + { + name = "futures-core"; + packageId = "futures-core"; + optional = true; + } + { + name = "futures-sink"; + packageId = "futures-sink"; + optional = true; + } + { + name = "gloo-utils"; + packageId = "gloo-utils 0.2.0"; + usesDefaultFeatures = false; + } + { + name = "http"; + packageId = "http"; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "pin-project"; + packageId = "pin-project"; + optional = true; + } + { + name = "serde"; + packageId = "serde"; + optional = true; + } + { + name = "serde_json"; + packageId = "serde_json"; + optional = true; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "wasm-bindgen-futures"; + packageId = "wasm-bindgen-futures"; + } + { + name = "web-sys"; + packageId = "web-sys"; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + ]; + features = { + "default" = [ "json" "websocket" "http" "eventsource" ]; + "eventsource" = [ "futures-channel" "futures-core" "pin-project" "web-sys/Event" "web-sys/EventTarget" "web-sys/EventSource" "web-sys/MessageEvent" ]; + "futures-channel" = [ "dep:futures-channel" ]; + "futures-core" = [ "dep:futures-core" ]; + "futures-sink" = [ "dep:futures-sink" ]; + "http" = [ "web-sys/Headers" "web-sys/UrlSearchParams" "web-sys/Url" "web-sys/Request" "web-sys/RequestInit" "web-sys/RequestMode" "web-sys/Response" "web-sys/ResponseInit" "web-sys/ResponseType" "web-sys/Window" "web-sys/RequestCache" "web-sys/RequestCredentials" "web-sys/ObserverCallback" "web-sys/RequestRedirect" "web-sys/ReferrerPolicy" "web-sys/AbortSignal" "web-sys/ReadableStream" "web-sys/Blob" "web-sys/FormData" "web-sys/WorkerGlobalScope" ]; + "json" = [ "serde" "serde_json" "gloo-utils/serde" ]; + "pin-project" = [ "dep:pin-project" ]; + "serde" = [ "dep:serde" ]; + "serde_json" = [ "dep:serde_json" ]; + "websocket" = [ "web-sys/WebSocket" "web-sys/AddEventListenerOptions" "web-sys/ErrorEvent" "web-sys/FileReader" "web-sys/MessageEvent" "web-sys/ProgressEvent" "web-sys/CloseEvent" "web-sys/CloseEventInit" "web-sys/BinaryType" "web-sys/Blob" "futures-channel" "futures-core" "futures-sink" "pin-project" ]; + }; + resolvedDefaultFeatures = [ "default" "eventsource" "futures-channel" "futures-core" "futures-sink" "http" "json" "pin-project" "serde" "serde_json" "websocket" ]; + }; + "gloo-render 0.1.1" = rec { + crateName = "gloo-render"; + version = "0.1.1"; + edition = "2018"; + sha256 = "0r3pxj22l489ldakj6521a0f0n1r9v8xrai3k12d9kv7xxm31n9g"; + libName = "gloo_render"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Window" ]; + } + ]; + + }; + "gloo-render 0.2.0" = rec { + crateName = "gloo-render"; + version = "0.2.0"; + edition = "2021"; + sha256 = "0cwqcka7l5p29idq174c6mi5cgal0rywngdck26qwfki8ikqn02n"; + libName = "gloo_render"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Window" ]; + } + ]; + + }; + "gloo-storage 0.2.2" = rec { + crateName = "gloo-storage"; + version = "0.2.2"; + edition = "2018"; + sha256 = "1074j754a6c21sbmqws5qwaha0a13fikv17ps476zzfvyl5vcsjx"; + libName = "gloo_storage"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "gloo-utils"; + packageId = "gloo-utils 0.1.7"; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "serde"; + packageId = "serde"; + } + { + name = "serde_json"; + packageId = "serde_json"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Storage" "Window" ]; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + ]; + + }; + "gloo-storage 0.3.0" = rec { + crateName = "gloo-storage"; + version = "0.3.0"; + edition = "2021"; + sha256 = "0yi7740iza6nyg6n8sxzzhy6yg6xpbxhig7r2bwqlxcjihg07j7v"; + libName = "gloo_storage"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "gloo-utils"; + packageId = "gloo-utils 0.2.0"; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "serde"; + packageId = "serde"; + } + { + name = "serde_json"; + packageId = "serde_json"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Storage" "Window" ]; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + ]; + + }; + "gloo-timers 0.2.6" = rec { + crateName = "gloo-timers"; + version = "0.2.6"; + edition = "2018"; + sha256 = "0p2yqcxw0q9kclhwpgshq1r4ijns07nmmagll3lvrgl7pdk5m6cv"; + libName = "gloo_timers"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + ]; + features = { + "futures" = [ "futures-core" "futures-channel" ]; + "futures-channel" = [ "dep:futures-channel" ]; + "futures-core" = [ "dep:futures-core" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "gloo-timers 0.3.0" = rec { + crateName = "gloo-timers"; + version = "0.3.0"; + edition = "2021"; + sha256 = "1519157n7xppkk6pdw5w52vy1llzn5iljkqd7q1h5609jv7l7cdv"; + libName = "gloo_timers"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "futures-channel"; + packageId = "futures-channel"; + optional = true; + } + { + name = "futures-core"; + packageId = "futures-core"; + optional = true; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + ]; + features = { + "futures" = [ "futures-core" "futures-channel" ]; + "futures-channel" = [ "dep:futures-channel" ]; + "futures-core" = [ "dep:futures-core" ]; + }; + resolvedDefaultFeatures = [ "default" "futures" "futures-channel" "futures-core" ]; + }; + "gloo-utils 0.1.7" = rec { + crateName = "gloo-utils"; + version = "0.1.7"; + edition = "2018"; + sha256 = "13m59g36spynspvhx0xsaahbkdshn1v03gcjf87s7cvc443wnzq3"; + libName = "gloo_utils"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "serde"; + packageId = "serde"; + optional = true; + } + { + name = "serde_json"; + packageId = "serde_json"; + optional = true; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Document" "History" "HtmlElement" "Location" "Window" "HtmlHeadElement" "Element" ]; + } + ]; + features = { + "default" = [ "serde" ]; + "serde" = [ "dep:serde" "dep:serde_json" ]; + }; + resolvedDefaultFeatures = [ "default" "serde" ]; + }; + "gloo-utils 0.2.0" = rec { + crateName = "gloo-utils"; + version = "0.2.0"; + edition = "2021"; + sha256 = "1am31cd6889shb7158bg9zzsjcpvyzxrhfhxgia8rc8k84smam8b"; + libName = "gloo_utils"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "serde"; + packageId = "serde"; + optional = true; + } + { + name = "serde_json"; + packageId = "serde_json"; + optional = true; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Document" "History" "HtmlElement" "Location" "Window" "HtmlHeadElement" "Element" ]; + } + ]; + features = { + "default" = [ "serde" ]; + "serde" = [ "dep:serde" "dep:serde_json" ]; + }; + resolvedDefaultFeatures = [ "default" "serde" ]; + }; + "gloo-worker 0.2.1" = rec { + crateName = "gloo-worker"; + version = "0.2.1"; + edition = "2018"; + sha256 = "0sjiw13069i7bpiyb03w3kyddn3q07fmj4vd60l1l1kqva21aiqk"; + libName = "gloo_worker"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "anymap2"; + packageId = "anymap2"; + } + { + name = "bincode"; + packageId = "bincode"; + } + { + name = "gloo-console"; + packageId = "gloo-console 0.2.3"; + } + { + name = "gloo-utils"; + packageId = "gloo-utils 0.1.7"; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "wasm-bindgen-futures"; + packageId = "wasm-bindgen-futures"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Blob" "BlobPropertyBag" "DedicatedWorkerGlobalScope" "MessageEvent" "Url" "Worker" "WorkerOptions" ]; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; + "gloo-worker 0.4.0" = rec { + crateName = "gloo-worker"; + version = "0.4.0"; + edition = "2021"; + sha256 = "00744js1jcwdndzf22c8gzml7aqql4ymjfpsd2i1vrbxv0ymsjbn"; + libName = "gloo_worker"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "bincode"; + packageId = "bincode"; + } + { + name = "futures"; + packageId = "futures"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "gloo-utils"; + packageId = "gloo-utils 0.2.0"; + } + { + name = "gloo-worker-macros"; + packageId = "gloo-worker-macros"; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "pinned"; + packageId = "pinned"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "wasm-bindgen-futures"; + packageId = "wasm-bindgen-futures"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Blob" "BlobPropertyBag" "DedicatedWorkerGlobalScope" "MessageEvent" "Url" "Worker" "WorkerOptions" ]; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "default" "futures" ]; + }; + "gloo-worker-macros" = rec { + crateName = "gloo-worker-macros"; + version = "0.1.0"; + edition = "2021"; + sha256 = "1rs0f6b34mkhlmpmhqi747c34000sd5mxma92yacjyw5sicalv4m"; + procMacro = true; + libName = "gloo_worker_macros"; + authors = [ + "Rust and WebAssembly Working Group" + ]; + dependencies = [ + { + name = "proc-macro-crate"; + packageId = "proc-macro-crate"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + features = [ "full" ]; + } + ]; + + }; + "hashbrown 0.12.3" = rec { + crateName = "hashbrown"; + version = "0.12.3"; + edition = "2021"; + sha256 = "1268ka4750pyg2pbgsr43f0289l5zah4arir2k4igx5a8c6fg7la"; + authors = [ + "Amanieu d'Antras <amanieu@gmail.com>" + ]; + features = { + "ahash" = [ "dep:ahash" ]; + "ahash-compile-time-rng" = [ "ahash/compile-time-rng" ]; + "alloc" = [ "dep:alloc" ]; + "bumpalo" = [ "dep:bumpalo" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "ahash" "inline-more" ]; + "rayon" = [ "dep:rayon" ]; + "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "raw" ]; + }; + "hashbrown 0.14.5" = rec { + crateName = "hashbrown"; + version = "0.14.5"; + edition = "2021"; + sha256 = "1wa1vy1xs3mp11bn3z9dv0jricgr6a2j0zkf1g19yz3vw4il89z5"; + authors = [ + "Amanieu d'Antras <amanieu@gmail.com>" + ]; + features = { + "ahash" = [ "dep:ahash" ]; + "alloc" = [ "dep:alloc" ]; + "allocator-api2" = [ "dep:allocator-api2" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "ahash" "inline-more" "allocator-api2" ]; + "equivalent" = [ "dep:equivalent" ]; + "nightly" = [ "allocator-api2?/nightly" "bumpalo/allocator_api" ]; + "rayon" = [ "dep:rayon" ]; + "rkyv" = [ "dep:rkyv" ]; + "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "inline-more" "raw" ]; + }; + "hermit-abi" = rec { + crateName = "hermit-abi"; + version = "0.3.9"; + edition = "2021"; + sha256 = "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj"; + libName = "hermit_abi"; + authors = [ + "Stefan Lankes" + ]; + features = { + "alloc" = [ "dep:alloc" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins/rustc-dep-of-std" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "http" = rec { + crateName = "http"; + version = "0.2.12"; + edition = "2018"; + sha256 = "1w81s4bcbmcj9bjp7mllm8jlz6b31wzvirz8bgpzbqkpwmbvn730"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + "Carl Lerche <me@carllerche.com>" + "Sean McArthur <sean@seanmonstar.com>" + ]; + dependencies = [ + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "fnv"; + packageId = "fnv"; + } + { + name = "itoa"; + packageId = "itoa"; + } + ]; + + }; + "implicit-clone" = rec { + crateName = "implicit-clone"; + version = "0.4.9"; + edition = "2021"; + sha256 = "113agd9bqk7c0s2rqgarzkfp3wgbzl3q59mp6sv72nkv3iwsmagq"; + libName = "implicit_clone"; + authors = [ + "Cecile Tonglet <cecile.tonglet@cecton.com>" + ]; + dependencies = [ + { + name = "implicit-clone-derive"; + packageId = "implicit-clone-derive"; + optional = true; + } + { + name = "indexmap"; + packageId = "indexmap 2.2.6"; + optional = true; + } + ]; + features = { + "default" = [ "derive" ]; + "derive" = [ "implicit-clone-derive" ]; + "implicit-clone-derive" = [ "dep:implicit-clone-derive" ]; + "indexmap" = [ "dep:indexmap" ]; + "map" = [ "indexmap" ]; + "serde" = [ "dep:serde" "indexmap/serde" ]; + }; + resolvedDefaultFeatures = [ "default" "derive" "implicit-clone-derive" "indexmap" "map" ]; + }; + "implicit-clone-derive" = rec { + crateName = "implicit-clone-derive"; + version = "0.1.1"; + edition = "2021"; + sha256 = "0fsfj6n56mg92f3899gcdck1dqlsmgyd52k0n2xhhj53p5g6h4ck"; + procMacro = true; + libName = "implicit_clone_derive"; + authors = [ + "Cecile Tonglet <cecile.tonglet@cecton.com>" + ]; + dependencies = [ + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + features = [ "full" ]; + } + ]; + + }; + "indexmap 1.9.3" = rec { + crateName = "indexmap"; + version = "1.9.3"; + edition = "2021"; + sha256 = "16dxmy7yvk51wvnih3a3im6fp5lmx0wx76i03n06wyak6cwhw1xx"; + dependencies = [ + { + name = "hashbrown"; + packageId = "hashbrown 0.12.3"; + usesDefaultFeatures = false; + features = [ "raw" ]; + } + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "quickcheck" = [ "dep:quickcheck" ]; + "rayon" = [ "dep:rayon" ]; + "rustc-rayon" = [ "dep:rustc-rayon" ]; + "serde" = [ "dep:serde" ]; + "serde-1" = [ "serde" ]; + }; + }; + "indexmap 2.2.6" = rec { + crateName = "indexmap"; + version = "2.2.6"; + edition = "2021"; + sha256 = "09hgwi2ig0wyj5rjziia76zmhgfj95k0jb4ic3iiawm4vlavg3qn"; + dependencies = [ + { + name = "equivalent"; + packageId = "equivalent"; + usesDefaultFeatures = false; + } + { + name = "hashbrown"; + packageId = "hashbrown 0.14.5"; + usesDefaultFeatures = false; + features = [ "raw" ]; + } + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "borsh" = [ "dep:borsh" ]; + "default" = [ "std" ]; + "quickcheck" = [ "dep:quickcheck" ]; + "rayon" = [ "dep:rayon" ]; + "rustc-rayon" = [ "dep:rustc-rayon" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "itertools" = rec { + crateName = "itertools"; + version = "0.12.1"; + edition = "2018"; + sha256 = "0s95jbb3ndj1lvfxyq5wanc0fm0r6hg6q4ngb92qlfdxvci10ads"; + authors = [ + "bluss" + ]; + dependencies = [ + { + name = "either"; + packageId = "either"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "use_std" ]; + "use_std" = [ "use_alloc" "either/use_std" ]; + }; + resolvedDefaultFeatures = [ "default" "use_alloc" "use_std" ]; + }; + "itoa" = rec { + crateName = "itoa"; + version = "1.0.11"; + edition = "2018"; + sha256 = "0nv9cqjwzr3q58qz84dcz63ggc54yhf1yqar1m858m1kfd4g3wa9"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + features = { + "no-panic" = [ "dep:no-panic" ]; + }; + }; + "js-sys" = rec { + crateName = "js-sys"; + version = "0.3.69"; + edition = "2018"; + sha256 = "0v99rz97asnzapb0jsc3jjhvxpfxr7h7qd97yqyrf9i7viimbh99"; + libName = "js_sys"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + ]; + + }; + "lazy_static" = rec { + crateName = "lazy_static"; + version = "1.5.0"; + edition = "2015"; + sha256 = "1zk6dqqni0193xg6iijh7i3i44sryglwgvx20spdvwk3r6sbrlmv"; + authors = [ + "Marvin Löbel <loebel.marvin@gmail.com>" + ]; + features = { + "spin" = [ "dep:spin" ]; + "spin_no_std" = [ "spin" ]; + }; + }; + "lexical-core" = rec { + crateName = "lexical-core"; + version = "0.8.5"; + edition = "2018"; + sha256 = "0ihf0x3vrk25fq3bv9q35m0xax0wmvwkh0j0pjm2yk4ddvh5vpic"; + libName = "lexical_core"; + authors = [ + "Alex Huszagh <ahuszagh@gmail.com>" + ]; + dependencies = [ + { + name = "lexical-parse-float"; + packageId = "lexical-parse-float"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "lexical-parse-integer"; + packageId = "lexical-parse-integer"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "lexical-util"; + packageId = "lexical-util"; + usesDefaultFeatures = false; + } + { + name = "lexical-write-float"; + packageId = "lexical-write-float"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "lexical-write-integer"; + packageId = "lexical-write-integer"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "compact" = [ "lexical-write-integer/compact" "lexical-write-float/compact" "lexical-parse-integer/compact" "lexical-parse-float/compact" ]; + "default" = [ "std" "write-integers" "write-floats" "parse-integers" "parse-floats" ]; + "f128" = [ "lexical-util/f128" "lexical-parse-float/f128" "lexical-write-float/f128" ]; + "f16" = [ "lexical-util/f16" "lexical-parse-float/f16" "lexical-write-float/f16" ]; + "format" = [ "lexical-util/format" "lexical-parse-integer/format" "lexical-parse-float/format" "lexical-write-integer/format" "lexical-write-float/format" ]; + "lexical-parse-float" = [ "dep:lexical-parse-float" ]; + "lexical-parse-integer" = [ "dep:lexical-parse-integer" ]; + "lexical-write-float" = [ "dep:lexical-write-float" ]; + "lexical-write-integer" = [ "dep:lexical-write-integer" ]; + "lint" = [ "lexical-util/lint" "lexical-write-integer/lint" "lexical-write-float/lint" "lexical-parse-integer/lint" "lexical-parse-float/lint" ]; + "nightly" = [ "lexical-write-integer/nightly" "lexical-write-float/nightly" "lexical-parse-integer/nightly" "lexical-parse-float/nightly" ]; + "parse-floats" = [ "lexical-parse-float" "parse" "floats" ]; + "parse-integers" = [ "lexical-parse-integer" "parse" "integers" ]; + "power-of-two" = [ "lexical-util/power-of-two" "lexical-write-integer/power-of-two" "lexical-write-float/power-of-two" "lexical-parse-integer/power-of-two" "lexical-parse-float/power-of-two" ]; + "radix" = [ "lexical-util/radix" "lexical-write-integer/radix" "lexical-write-float/radix" "lexical-parse-integer/radix" "lexical-parse-float/radix" ]; + "safe" = [ "lexical-write-integer/safe" "lexical-write-float/safe" "lexical-parse-integer/safe" "lexical-parse-float/safe" ]; + "std" = [ "lexical-util/std" "lexical-write-integer/std" "lexical-write-float/std" "lexical-parse-integer/std" "lexical-parse-float/std" ]; + "write-floats" = [ "lexical-write-float" "write" "floats" ]; + "write-integers" = [ "lexical-write-integer" "write" "integers" ]; + }; + resolvedDefaultFeatures = [ "default" "floats" "format" "integers" "lexical-parse-float" "lexical-parse-integer" "lexical-write-float" "lexical-write-integer" "parse" "parse-floats" "parse-integers" "std" "write" "write-floats" "write-integers" ]; + }; + "lexical-parse-float" = rec { + crateName = "lexical-parse-float"; + version = "0.8.5"; + edition = "2018"; + sha256 = "0py0gp8hlzcrlvjqmqlpl2v1as65iiqxq2xsabxvhc01pmg3lfv8"; + libName = "lexical_parse_float"; + authors = [ + "Alex Huszagh <ahuszagh@gmail.com>" + ]; + dependencies = [ + { + name = "lexical-parse-integer"; + packageId = "lexical-parse-integer"; + usesDefaultFeatures = false; + } + { + name = "lexical-util"; + packageId = "lexical-util"; + usesDefaultFeatures = false; + features = [ "parse-floats" ]; + } + { + name = "static_assertions"; + packageId = "static_assertions"; + } + ]; + features = { + "compact" = [ "lexical-util/compact" "lexical-parse-integer/compact" ]; + "default" = [ "std" ]; + "f128" = [ "lexical-util/f128" ]; + "f16" = [ "lexical-util/f16" ]; + "format" = [ "lexical-util/format" "lexical-parse-integer/format" ]; + "lint" = [ "lexical-util/lint" "lexical-parse-integer/lint" ]; + "nightly" = [ "lexical-parse-integer/nightly" ]; + "power-of-two" = [ "lexical-util/power-of-two" "lexical-parse-integer/power-of-two" ]; + "radix" = [ "lexical-util/radix" "lexical-parse-integer/radix" "power-of-two" ]; + "safe" = [ "lexical-parse-integer/safe" ]; + "std" = [ "lexical-util/std" "lexical-parse-integer/std" ]; + }; + resolvedDefaultFeatures = [ "format" "std" ]; + }; + "lexical-parse-integer" = rec { + crateName = "lexical-parse-integer"; + version = "0.8.6"; + edition = "2018"; + sha256 = "1sayji3mpvb2xsjq56qcq3whfz8px9a6fxk5v7v15hyhbr4982bd"; + libName = "lexical_parse_integer"; + authors = [ + "Alex Huszagh <ahuszagh@gmail.com>" + ]; + dependencies = [ + { + name = "lexical-util"; + packageId = "lexical-util"; + usesDefaultFeatures = false; + features = [ "parse-integers" ]; + } + { + name = "static_assertions"; + packageId = "static_assertions"; + } + ]; + features = { + "compact" = [ "lexical-util/compact" ]; + "default" = [ "std" ]; + "format" = [ "lexical-util/format" ]; + "lint" = [ "lexical-util/lint" ]; + "power-of-two" = [ "lexical-util/power-of-two" ]; + "radix" = [ "lexical-util/radix" "power-of-two" ]; + "std" = [ "lexical-util/std" ]; + }; + resolvedDefaultFeatures = [ "format" "std" ]; + }; + "lexical-util" = rec { + crateName = "lexical-util"; + version = "0.8.5"; + edition = "2018"; + sha256 = "1z73qkv7yxhsbc4aiginn1dqmsj8jarkrdlyxc88g2gz2vzvjmaj"; + libName = "lexical_util"; + authors = [ + "Alex Huszagh <ahuszagh@gmail.com>" + ]; + dependencies = [ + { + name = "static_assertions"; + packageId = "static_assertions"; + } + ]; + features = { + "default" = [ "std" ]; + "f128" = [ "floats" ]; + "f16" = [ "floats" ]; + "parse-floats" = [ "parse" "floats" ]; + "parse-integers" = [ "parse" "integers" ]; + "radix" = [ "power-of-two" ]; + "write-floats" = [ "write" "floats" ]; + "write-integers" = [ "write" "integers" ]; + }; + resolvedDefaultFeatures = [ "floats" "format" "integers" "parse" "parse-floats" "parse-integers" "std" "write" "write-floats" "write-integers" ]; + }; + "lexical-write-float" = rec { + crateName = "lexical-write-float"; + version = "0.8.5"; + edition = "2018"; + sha256 = "0qk825l0csvnksh9sywb51996cjc2bylq6rxjaiha7sqqjhvmjmc"; + libName = "lexical_write_float"; + authors = [ + "Alex Huszagh <ahuszagh@gmail.com>" + ]; + dependencies = [ + { + name = "lexical-util"; + packageId = "lexical-util"; + usesDefaultFeatures = false; + features = [ "write-floats" ]; + } + { + name = "lexical-write-integer"; + packageId = "lexical-write-integer"; + usesDefaultFeatures = false; + } + { + name = "static_assertions"; + packageId = "static_assertions"; + } + ]; + features = { + "compact" = [ "lexical-util/compact" "lexical-write-integer/compact" ]; + "default" = [ "std" ]; + "f128" = [ "lexical-util/f128" ]; + "f16" = [ "lexical-util/f16" ]; + "format" = [ "lexical-util/format" ]; + "lint" = [ "lexical-util/lint" "lexical-write-integer/lint" ]; + "nightly" = [ "lexical-write-integer/nightly" ]; + "power-of-two" = [ "lexical-util/power-of-two" "lexical-write-integer/power-of-two" ]; + "radix" = [ "lexical-util/radix" "lexical-write-integer/radix" "power-of-two" ]; + "safe" = [ "lexical-write-integer/safe" ]; + "std" = [ "lexical-util/std" "lexical-write-integer/std" ]; + }; + resolvedDefaultFeatures = [ "format" "std" ]; + }; + "lexical-write-integer" = rec { + crateName = "lexical-write-integer"; + version = "0.8.5"; + edition = "2018"; + sha256 = "0ii4hmvqrg6pd4j9y1pkhkp0nw2wpivjzmljh6v6ca22yk8z7dp1"; + libName = "lexical_write_integer"; + authors = [ + "Alex Huszagh <ahuszagh@gmail.com>" + ]; + dependencies = [ + { + name = "lexical-util"; + packageId = "lexical-util"; + usesDefaultFeatures = false; + features = [ "write-integers" ]; + } + { + name = "static_assertions"; + packageId = "static_assertions"; + } + ]; + features = { + "compact" = [ "lexical-util/compact" ]; + "default" = [ "std" ]; + "format" = [ "lexical-util/format" ]; + "lint" = [ "lexical-util/lint" ]; + "power-of-two" = [ "lexical-util/power-of-two" ]; + "radix" = [ "lexical-util/radix" "power-of-two" ]; + "std" = [ "lexical-util/std" ]; + }; + resolvedDefaultFeatures = [ "format" "std" ]; + }; + "libc" = rec { + crateName = "libc"; + version = "0.2.155"; + edition = "2015"; + sha256 = "0z44c53z54znna8n322k5iwg80arxxpdzjj5260pxxzc9a58icwp"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "default" = [ "std" ]; + "rustc-dep-of-std" = [ "align" "rustc-std-workspace-core" ]; + "rustc-std-workspace-core" = [ "dep:rustc-std-workspace-core" ]; + "use_std" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "libredox" = rec { + crateName = "libredox"; + version = "0.0.1"; + edition = "2021"; + sha256 = "1s2fh4ikpp9xl0lsl01pi0n8pw1q9s3ld452vd8qh1v63v537j45"; + authors = [ + "4lDO2 <4lDO2@protonmail.com>" + ]; + dependencies = [ + { + name = "bitflags"; + packageId = "bitflags 2.4.1"; + } + { + name = "libc"; + packageId = "libc"; + } + { + name = "redox_syscall"; + packageId = "redox_syscall"; + } + ]; + features = { + "default" = [ "scheme" "call" ]; + "scheme" = [ "call" ]; + }; + resolvedDefaultFeatures = [ "call" ]; + }; + "log" = rec { + crateName = "log"; + version = "0.4.22"; + edition = "2021"; + sha256 = "093vs0wkm1rgyykk7fjbqp2lwizbixac1w52gv109p5r4jh0p9x7"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "kv_serde" = [ "kv_std" "value-bag/serde" "serde" ]; + "kv_std" = [ "std" "kv" "value-bag/error" ]; + "kv_sval" = [ "kv" "value-bag/sval" "sval" "sval_ref" ]; + "kv_unstable" = [ "kv" "value-bag" ]; + "kv_unstable_serde" = [ "kv_serde" "kv_unstable_std" ]; + "kv_unstable_std" = [ "kv_std" "kv_unstable" ]; + "kv_unstable_sval" = [ "kv_sval" "kv_unstable" ]; + "serde" = [ "dep:serde" ]; + "sval" = [ "dep:sval" ]; + "sval_ref" = [ "dep:sval_ref" ]; + "value-bag" = [ "dep:value-bag" ]; + }; + }; + "md-5" = rec { + crateName = "md-5"; + version = "0.10.6"; + edition = "2018"; + sha256 = "1kvq5rnpm4fzwmyv5nmnxygdhhb2369888a06gdc9pxyrzh7x7nq"; + libName = "md5"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "digest"; + packageId = "digest"; + } + ]; + devDependencies = [ + { + name = "digest"; + packageId = "digest"; + features = [ "dev" ]; + } + ]; + features = { + "asm" = [ "md5-asm" ]; + "default" = [ "std" ]; + "md5-asm" = [ "dep:md5-asm" ]; + "oid" = [ "digest/oid" ]; + "std" = [ "digest/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "memchr" = rec { + crateName = "memchr"; + version = "2.7.4"; + edition = "2021"; + sha256 = "18z32bhxrax0fnjikv475z7ii718hq457qwmaryixfxsl2qrmjkq"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + "bluss" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "std" ]; + "logging" = [ "dep:log" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + "std" = [ "alloc" ]; + "use_std" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "memoffset" = rec { + crateName = "memoffset"; + version = "0.9.0"; + edition = "2015"; + sha256 = "0v20ihhdzkfw1jx00a7zjpk2dcp5qjq6lz302nyqamd9c4f4nqss"; + authors = [ + "Gilad Naaman <gilad.naaman@gmail.com>" + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; + "miniz_oxide" = rec { + crateName = "miniz_oxide"; + version = "0.7.4"; + edition = "2018"; + sha256 = "024wv14aa75cvik7005s5y2nfc8zfidddbd7g55g7sjgnzfl18mq"; + authors = [ + "Frommi <daniil.liferenko@gmail.com>" + "oyvindln <oyvindln@users.noreply.github.com>" + ]; + dependencies = [ + { + name = "adler"; + packageId = "adler"; + usesDefaultFeatures = false; + } + ]; + features = { + "alloc" = [ "dep:alloc" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "with-alloc" ]; + "rustc-dep-of-std" = [ "core" "alloc" "compiler_builtins" "adler/rustc-dep-of-std" ]; + "simd" = [ "simd-adler32" ]; + "simd-adler32" = [ "dep:simd-adler32" ]; + }; + }; + "nohash-hasher" = rec { + crateName = "nohash-hasher"; + version = "0.2.0"; + edition = "2018"; + sha256 = "0lf4p6k01w4wm7zn4grnihzj8s7zd5qczjmzng7wviwxawih5x9b"; + libName = "nohash_hasher"; + authors = [ + "Parity Technologies <admin@parity.io>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "nom8" = rec { + crateName = "nom8"; + version = "0.2.0"; + edition = "2018"; + sha256 = "1y6jzabxyrl05vxnh63r66ac2fh0symg5fnynxm4ii3zkif580df"; + dependencies = [ + { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" "memchr/std" ]; + "unstable-doc" = [ "alloc" "std" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "num_cpus" = rec { + crateName = "num_cpus"; + version = "1.16.0"; + edition = "2015"; + sha256 = "0hra6ihpnh06dvfvz9ipscys0xfqa9ca9hzp384d5m02ssvgqqa1"; + authors = [ + "Sean McArthur <sean@seanmonstar.com>" + ]; + dependencies = [ + { + name = "hermit-abi"; + packageId = "hermit-abi"; + target = { target, features }: ("hermit" == target."os" or null); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (!(target."windows" or false)); + } + ]; + + }; + "object" = rec { + crateName = "object"; + version = "0.36.2"; + edition = "2018"; + sha256 = "03hpcgwcsm5cfpvcmk8x0hbkvxlpw3c2pq8afrgiifx7val3y81z"; + dependencies = [ + { + name = "memchr"; + packageId = "memchr"; + usesDefaultFeatures = false; + } + ]; + features = { + "all" = [ "read" "write" "build" "std" "compression" "wasm" ]; + "alloc" = [ "dep:alloc" ]; + "build" = [ "build_core" "write_std" "elf" ]; + "build_core" = [ "read_core" "write_core" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "compression" = [ "dep:flate2" "dep:ruzstd" "std" ]; + "core" = [ "dep:core" ]; + "default" = [ "read" "compression" ]; + "doc" = [ "read_core" "write_std" "build_core" "std" "compression" "archive" "coff" "elf" "macho" "pe" "wasm" "xcoff" ]; + "pe" = [ "coff" ]; + "read" = [ "read_core" "archive" "coff" "elf" "macho" "pe" "xcoff" "unaligned" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" "alloc" "memchr/rustc-dep-of-std" ]; + "std" = [ "memchr/std" ]; + "unstable-all" = [ "all" "unstable" ]; + "wasm" = [ "dep:wasmparser" ]; + "write" = [ "write_std" "coff" "elf" "macho" "pe" "xcoff" ]; + "write_core" = [ "dep:crc32fast" "dep:indexmap" "dep:hashbrown" ]; + "write_std" = [ "write_core" "std" "indexmap?/std" "crc32fast?/std" ]; + }; + resolvedDefaultFeatures = [ "archive" "coff" "elf" "macho" "pe" "read_core" "unaligned" "xcoff" ]; + }; + "once_cell" = rec { + crateName = "once_cell"; + version = "1.19.0"; + edition = "2021"; + sha256 = "14kvw7px5z96dk4dwdm1r9cqhhy2cyj1l5n5b29mynbb8yr15nrz"; + authors = [ + "Aleksey Kladov <aleksey.kladov@gmail.com>" + ]; + features = { + "alloc" = [ "race" ]; + "atomic-polyfill" = [ "critical-section" ]; + "critical-section" = [ "dep:critical-section" "portable-atomic" ]; + "default" = [ "std" ]; + "parking_lot" = [ "dep:parking_lot_core" ]; + "portable-atomic" = [ "dep:portable-atomic" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "race" "std" ]; + }; + "os_str_bytes" = rec { + crateName = "os_str_bytes"; + version = "6.6.1"; + edition = "2021"; + sha256 = "1885z1x4sm86v5p41ggrl49m58rbzzhd1kj72x46yy53p62msdg2"; + authors = [ + "dylni" + ]; + dependencies = [ + { + name = "memchr"; + packageId = "memchr"; + optional = true; + } + ]; + features = { + "checked_conversions" = [ "conversions" ]; + "default" = [ "memchr" "raw_os_str" ]; + "memchr" = [ "dep:memchr" ]; + "print_bytes" = [ "dep:print_bytes" ]; + "uniquote" = [ "dep:uniquote" ]; + }; + resolvedDefaultFeatures = [ "conversions" "default" "memchr" "raw_os_str" ]; + }; + "path-clean" = rec { + crateName = "path-clean"; + version = "0.1.0"; + edition = "2015"; + sha256 = "1pcgqxw0mgg3ha5hi5xkjhyjf488bw5rw1g3qlr9awbq4szh3fpc"; + libName = "path_clean"; + authors = [ + "Dan Reeves <hey@danreev.es>" + ]; + + }; + "percent-encoding" = rec { + crateName = "percent-encoding"; + version = "2.3.1"; + edition = "2018"; + sha256 = "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573"; + libName = "percent_encoding"; + authors = [ + "The rust-url developers" + ]; + features = { + "default" = [ "std" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "std" ]; + }; + "pin-project" = rec { + crateName = "pin-project"; + version = "1.1.5"; + edition = "2021"; + sha256 = "1cxl146x0q7lawp0m1826wsgj8mmmfs6ja8q7m6f7ff5j6vl7gxn"; + libName = "pin_project"; + dependencies = [ + { + name = "pin-project-internal"; + packageId = "pin-project-internal"; + } + ]; + + }; + "pin-project-internal" = rec { + crateName = "pin-project-internal"; + version = "1.1.5"; + edition = "2021"; + sha256 = "0r9r4ivwiyqf45sv6b30l1dx282lxaax2f6gl84jwa3q590s8f1g"; + procMacro = true; + libName = "pin_project_internal"; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + features = [ "full" "visit-mut" ]; + } + ]; + + }; + "pin-project-lite" = rec { + crateName = "pin-project-lite"; + version = "0.2.14"; + edition = "2018"; + sha256 = "00nx3f04agwjlsmd3mc5rx5haibj2v8q9b52b0kwn63wcv4nz9mx"; + libName = "pin_project_lite"; + + }; + "pin-utils" = rec { + crateName = "pin-utils"; + version = "0.1.0"; + edition = "2018"; + sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; + authors = [ + "Josef Brandl <mail@josefbrandl.de>" + ]; + + }; + "pinned" = rec { + crateName = "pinned"; + version = "0.1.0"; + edition = "2021"; + sha256 = "0nsrxs49dhjjz1gvg0pvac2rcidnwwd8l99y7vhwym2yv5xh4ad8"; + authors = [ + "Kaede Hoshiakwa <futursolo@icloud.com>" + ]; + dependencies = [ + { + name = "futures"; + packageId = "futures"; + usesDefaultFeatures = false; + features = [ "std" "async-await" ]; + } + { + name = "rustversion"; + packageId = "rustversion"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + ]; + + }; + "prettyplease" = rec { + crateName = "prettyplease"; + version = "0.2.20"; + edition = "2021"; + links = "prettyplease02"; + sha256 = "0pk4vm9fir1p0bl11p9fkgl9r1x9vi4avv8l7flb1wx2i1a364jz"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + usesDefaultFeatures = false; + features = [ "full" ]; + } + ]; + devDependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + usesDefaultFeatures = false; + features = [ "parsing" ]; + } + ]; + features = { + "verbatim" = [ "syn/parsing" ]; + }; + }; + "proc-macro-crate" = rec { + crateName = "proc-macro-crate"; + version = "1.3.1"; + edition = "2021"; + sha256 = "069r1k56bvgk0f58dm5swlssfcp79im230affwk6d9ck20g04k3z"; + libName = "proc_macro_crate"; + authors = [ + "Bastian Köcher <git@kchr.de>" + ]; + dependencies = [ + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "toml_edit"; + packageId = "toml_edit 0.19.15"; + } + ]; + + }; + "proc-macro-error" = rec { + crateName = "proc-macro-error"; + version = "1.0.4"; + edition = "2018"; + sha256 = "1373bhxaf0pagd8zkyd03kkx6bchzf6g0dkwrwzsnal9z47lj9fs"; + libName = "proc_macro_error"; + authors = [ + "CreepySkeleton <creepy-skeleton@yandex.ru>" + ]; + dependencies = [ + { + name = "proc-macro-error-attr"; + packageId = "proc-macro-error-attr"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 1.0.109"; + optional = true; + usesDefaultFeatures = false; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + features = { + "default" = [ "syn-error" ]; + "syn" = [ "dep:syn" ]; + "syn-error" = [ "syn" ]; + }; + resolvedDefaultFeatures = [ "default" "syn" "syn-error" ]; + }; + "proc-macro-error-attr" = rec { + crateName = "proc-macro-error-attr"; + version = "1.0.4"; + edition = "2018"; + sha256 = "0sgq6m5jfmasmwwy8x4mjygx5l7kp8s4j60bv25ckv2j1qc41gm1"; + procMacro = true; + libName = "proc_macro_error_attr"; + authors = [ + "CreepySkeleton <creepy-skeleton@yandex.ru>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + ]; + buildDependencies = [ + { + name = "version_check"; + packageId = "version_check"; + } + ]; + + }; + "proc-macro2" = rec { + crateName = "proc-macro2"; + version = "1.0.86"; + edition = "2021"; + sha256 = "0xrv22p8lqlfdf1w0pj4si8n2ws4aw0kilmziwf0vpv5ys6rwway"; + libName = "proc_macro2"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "unicode-ident"; + packageId = "unicode-ident"; + } + ]; + features = { + "default" = [ "proc-macro" ]; + }; + resolvedDefaultFeatures = [ "default" "proc-macro" ]; + }; + "prokio" = rec { + crateName = "prokio"; + version = "0.1.0"; + edition = "2021"; + sha256 = "127l9k5076xwlaf0b64hw3l14wqjss2krldb2ddgm4apdq85xd83"; + authors = [ + "Kaede Hoshikawa <futursolo@icloud.com>" + ]; + dependencies = [ + { + name = "futures"; + packageId = "futures"; + usesDefaultFeatures = false; + features = [ "std" "async-await" ]; + } + { + name = "gloo"; + packageId = "gloo 0.8.1"; + target = { target, features }: ("wasm32" == target."arch" or null); + } + { + name = "num_cpus"; + packageId = "num_cpus"; + target = { target, features }: (!("wasm32" == target."arch" or null)); + } + { + name = "once_cell"; + packageId = "once_cell"; + target = { target, features }: (!("wasm32" == target."arch" or null)); + } + { + name = "pin-project"; + packageId = "pin-project"; + } + { + name = "pinned"; + packageId = "pinned"; + } + { + name = "tokio"; + packageId = "tokio"; + target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "rt" "time" ]; + } + { + name = "tokio-stream"; + packageId = "tokio-stream"; + target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "time" ]; + } + { + name = "wasm-bindgen-futures"; + packageId = "wasm-bindgen-futures"; + target = { target, features }: ("wasm32" == target."arch" or null); + } + ]; + devDependencies = [ + { + name = "tokio"; + packageId = "tokio"; + target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "full" ]; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; + "quote" = rec { + crateName = "quote"; + version = "1.0.37"; + edition = "2018"; + sha256 = "1brklraw2g34bxy9y4q1nbrccn7bv36ylihv12c9vlcii55x7fdm"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "proc-macro" ]; + "proc-macro" = [ "proc-macro2/proc-macro" ]; + }; + resolvedDefaultFeatures = [ "default" "proc-macro" ]; + }; + "redox_syscall" = rec { + crateName = "redox_syscall"; + version = "0.4.1"; + edition = "2018"; + sha256 = "1aiifyz5dnybfvkk4cdab9p2kmphag1yad6iknc7aszlxxldf8j7"; + libName = "syscall"; + authors = [ + "Jeremy Soller <jackpot51@gmail.com>" + ]; + dependencies = [ + { + name = "bitflags"; + packageId = "bitflags 1.3.2"; + } + ]; + features = { + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "bitflags/rustc-dep-of-std" ]; + }; + }; + "redox_users" = rec { + crateName = "redox_users"; + version = "0.4.4"; + edition = "2021"; + sha256 = "1d1c7dhbb62sh8jrq9dhvqcyxqsh3wg8qknsi94iwq3r0wh7k151"; + authors = [ + "Jose Narvaez <goyox86@gmail.com>" + "Wesley Hershberger <mggmugginsmc@gmail.com>" + ]; + dependencies = [ + { + name = "getrandom"; + packageId = "getrandom"; + features = [ "std" ]; + } + { + name = "libredox"; + packageId = "libredox"; + usesDefaultFeatures = false; + features = [ "call" ]; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + ]; + features = { + "auth" = [ "rust-argon2" "zeroize" ]; + "default" = [ "auth" ]; + "rust-argon2" = [ "dep:rust-argon2" ]; + "zeroize" = [ "dep:zeroize" ]; + }; + }; + "regex" = rec { + crateName = "regex"; + version = "1.10.6"; + edition = "2021"; + sha256 = "06cnlxwzyqfbw1za1i7ks89ns4i2kr0lpg5ykx56b8v7dd6df6a2"; + authors = [ + "The Rust Project Developers" + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "aho-corasick"; + packageId = "aho-corasick"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "memchr"; + packageId = "memchr"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "regex-automata"; + packageId = "regex-automata"; + usesDefaultFeatures = false; + features = [ "alloc" "syntax" "meta" "nfa-pikevm" ]; + } + { + name = "regex-syntax"; + packageId = "regex-syntax"; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" "perf" "unicode" "regex-syntax/default" ]; + "logging" = [ "aho-corasick?/logging" "memchr?/logging" "regex-automata/logging" ]; + "perf" = [ "perf-cache" "perf-dfa" "perf-onepass" "perf-backtrack" "perf-inline" "perf-literal" ]; + "perf-backtrack" = [ "regex-automata/nfa-backtrack" ]; + "perf-dfa" = [ "regex-automata/hybrid" ]; + "perf-dfa-full" = [ "regex-automata/dfa-build" "regex-automata/dfa-search" ]; + "perf-inline" = [ "regex-automata/perf-inline" ]; + "perf-literal" = [ "dep:aho-corasick" "dep:memchr" "regex-automata/perf-literal" ]; + "perf-onepass" = [ "regex-automata/dfa-onepass" ]; + "std" = [ "aho-corasick?/std" "memchr?/std" "regex-automata/std" "regex-syntax/std" ]; + "unicode" = [ "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" "regex-automata/unicode" "regex-syntax/unicode" ]; + "unicode-age" = [ "regex-automata/unicode-age" "regex-syntax/unicode-age" ]; + "unicode-bool" = [ "regex-automata/unicode-bool" "regex-syntax/unicode-bool" ]; + "unicode-case" = [ "regex-automata/unicode-case" "regex-syntax/unicode-case" ]; + "unicode-gencat" = [ "regex-automata/unicode-gencat" "regex-syntax/unicode-gencat" ]; + "unicode-perl" = [ "regex-automata/unicode-perl" "regex-automata/unicode-word-boundary" "regex-syntax/unicode-perl" ]; + "unicode-script" = [ "regex-automata/unicode-script" "regex-syntax/unicode-script" ]; + "unicode-segment" = [ "regex-automata/unicode-segment" "regex-syntax/unicode-segment" ]; + "unstable" = [ "pattern" ]; + "use_std" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "perf" "perf-backtrack" "perf-cache" "perf-dfa" "perf-inline" "perf-literal" "perf-onepass" "std" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; + }; + "regex-automata" = rec { + crateName = "regex-automata"; + version = "0.4.7"; + edition = "2021"; + sha256 = "1pwjdi4jckpbaivpl6x4v5g4crb37zr2wac93wlfsbzgqn6gbjiq"; + libName = "regex_automata"; + authors = [ + "The Rust Project Developers" + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "aho-corasick"; + packageId = "aho-corasick"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "memchr"; + packageId = "memchr"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "regex-syntax"; + packageId = "regex-syntax"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "default" = [ "std" "syntax" "perf" "unicode" "meta" "nfa" "dfa" "hybrid" ]; + "dfa" = [ "dfa-build" "dfa-search" "dfa-onepass" ]; + "dfa-build" = [ "nfa-thompson" "dfa-search" ]; + "dfa-onepass" = [ "nfa-thompson" ]; + "hybrid" = [ "alloc" "nfa-thompson" ]; + "internal-instrument" = [ "internal-instrument-pikevm" ]; + "internal-instrument-pikevm" = [ "logging" "std" ]; + "logging" = [ "dep:log" "aho-corasick?/logging" "memchr?/logging" ]; + "meta" = [ "syntax" "nfa-pikevm" ]; + "nfa" = [ "nfa-thompson" "nfa-pikevm" "nfa-backtrack" ]; + "nfa-backtrack" = [ "nfa-thompson" ]; + "nfa-pikevm" = [ "nfa-thompson" ]; + "nfa-thompson" = [ "alloc" ]; + "perf" = [ "perf-inline" "perf-literal" ]; + "perf-literal" = [ "perf-literal-substring" "perf-literal-multisubstring" ]; + "perf-literal-multisubstring" = [ "std" "dep:aho-corasick" ]; + "perf-literal-substring" = [ "aho-corasick?/perf-literal" "dep:memchr" ]; + "std" = [ "regex-syntax?/std" "memchr?/std" "aho-corasick?/std" "alloc" ]; + "syntax" = [ "dep:regex-syntax" "alloc" ]; + "unicode" = [ "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" "unicode-word-boundary" "regex-syntax?/unicode" ]; + "unicode-age" = [ "regex-syntax?/unicode-age" ]; + "unicode-bool" = [ "regex-syntax?/unicode-bool" ]; + "unicode-case" = [ "regex-syntax?/unicode-case" ]; + "unicode-gencat" = [ "regex-syntax?/unicode-gencat" ]; + "unicode-perl" = [ "regex-syntax?/unicode-perl" ]; + "unicode-script" = [ "regex-syntax?/unicode-script" ]; + "unicode-segment" = [ "regex-syntax?/unicode-segment" ]; + }; + resolvedDefaultFeatures = [ "alloc" "dfa-onepass" "dfa-search" "hybrid" "meta" "nfa-backtrack" "nfa-pikevm" "nfa-thompson" "perf-inline" "perf-literal" "perf-literal-multisubstring" "perf-literal-substring" "std" "syntax" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" "unicode-word-boundary" ]; + }; + "regex-syntax" = rec { + crateName = "regex-syntax"; + version = "0.8.2"; + edition = "2021"; + sha256 = "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360"; + libName = "regex_syntax"; + authors = [ + "The Rust Project Developers" + "Andrew Gallant <jamslam@gmail.com>" + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "default" = [ "std" "unicode" ]; + "unicode" = [ "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; + }; + resolvedDefaultFeatures = [ "default" "std" "unicode" "unicode-age" "unicode-bool" "unicode-case" "unicode-gencat" "unicode-perl" "unicode-script" "unicode-segment" ]; + }; + "rnix" = rec { + crateName = "rnix"; + version = "0.11.0"; + edition = "2021"; + sha256 = "0pybq9gp4b7lp0066236jpqi9lgb1bzvqc9axymwrq3hxgdwwddv"; + authors = [ + "jD91mZM2 <me@krake.one>" + ]; + dependencies = [ + { + name = "rowan"; + packageId = "rowan"; + } + ]; + + }; + "route-recognizer" = rec { + crateName = "route-recognizer"; + version = "0.3.1"; + edition = "2018"; + sha256 = "0ikp3blbina00jdbifxw1c9whg6mljli24lq5pv82iar53xr9axg"; + libName = "route_recognizer"; + authors = [ + "wycats" + "rustasync" + ]; + + }; + "rowan" = rec { + crateName = "rowan"; + version = "0.15.15"; + edition = "2021"; + sha256 = "0j9b340gsyf2h7v1q9xb4mqyqp4qbyzlbk1r9zn2mzyclyl8z99j"; + authors = [ + "Aleksey Kladov <aleksey.kladov@gmail.com>" + ]; + dependencies = [ + { + name = "countme"; + packageId = "countme"; + } + { + name = "hashbrown"; + packageId = "hashbrown 0.14.5"; + usesDefaultFeatures = false; + features = [ "inline-more" ]; + } + { + name = "memoffset"; + packageId = "memoffset"; + } + { + name = "rustc-hash"; + packageId = "rustc-hash 1.1.0"; + } + { + name = "text-size"; + packageId = "text-size"; + } + ]; + features = { + "serde" = [ "dep:serde" ]; + "serde1" = [ "serde" "text-size/serde" ]; + }; + }; + "rustc-demangle" = rec { + crateName = "rustc-demangle"; + version = "0.1.24"; + edition = "2015"; + sha256 = "07zysaafgrkzy2rjgwqdj2a8qdpsm6zv6f5pgpk9x0lm40z9b6vi"; + libName = "rustc_demangle"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; + }; + }; + "rustc-hash 1.1.0" = rec { + crateName = "rustc-hash"; + version = "1.1.0"; + edition = "2015"; + sha256 = "1qkc5khrmv5pqi5l5ca9p5nl5hs742cagrndhbrlk3dhlrx3zm08"; + libName = "rustc_hash"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "rustc-hash 2.0.0" = rec { + crateName = "rustc-hash"; + version = "2.0.0"; + edition = "2021"; + sha256 = "0lni0lf846bzrf3jvci6jaf4142n1mdqxvcpczk5ch9pfgyk8c2q"; + libName = "rustc_hash"; + authors = [ + "The Rust Project Developers" + ]; + features = { + "default" = [ "std" ]; + "rand" = [ "dep:rand" "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "rustversion" = rec { + crateName = "rustversion"; + version = "1.0.17"; + edition = "2018"; + sha256 = "1mm3fckyvb0l2209in1n2k05sws5d9mpkszbnwhq3pkq8apjhpcm"; + procMacro = true; + build = "build/build.rs"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + + }; + "ryu" = rec { + crateName = "ryu"; + version = "1.0.18"; + edition = "2018"; + sha256 = "17xx2s8j1lln7iackzd9p0sv546vjq71i779gphjq923vjh5pjzk"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + features = { + "no-panic" = [ "dep:no-panic" ]; + }; + }; + "serde" = rec { + crateName = "serde"; + version = "1.0.210"; + edition = "2018"; + sha256 = "0flc0z8wgax1k4j5bf2zyq48bgzyv425jkd5w0i6wbh7f8j5kqy8"; + authors = [ + "Erick Tryzelaar <erick.tryzelaar@gmail.com>" + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "serde_derive"; + packageId = "serde_derive"; + optional = true; + } + { + name = "serde_derive"; + packageId = "serde_derive"; + target = { target, features }: false; + } + ]; + devDependencies = [ + { + name = "serde_derive"; + packageId = "serde_derive"; + } + ]; + features = { + "default" = [ "std" ]; + "derive" = [ "serde_derive" ]; + "serde_derive" = [ "dep:serde_derive" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "derive" "rc" "serde_derive" "std" ]; + }; + "serde-wasm-bindgen 0.5.0" = rec { + crateName = "serde-wasm-bindgen"; + version = "0.5.0"; + edition = "2018"; + sha256 = "03m01y4l2kqz63pb1bip52j8bqilzlhhsa7asfdanmrwhgi47cgk"; + libName = "serde_wasm_bindgen"; + authors = [ + "Ingvar Stepanyan <me@rreverser.com>" + ]; + dependencies = [ + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "serde"; + packageId = "serde"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + ]; + + }; + "serde-wasm-bindgen 0.6.5" = rec { + crateName = "serde-wasm-bindgen"; + version = "0.6.5"; + edition = "2018"; + sha256 = "0sz1l4v8059hiizf5z7r2spm6ws6sqcrs4qgqwww3p7dy1ly20l3"; + libName = "serde_wasm_bindgen"; + authors = [ + "Ingvar Stepanyan <me@rreverser.com>" + ]; + dependencies = [ + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + ]; + + }; + "serde_derive" = rec { + crateName = "serde_derive"; + version = "1.0.210"; + edition = "2015"; + sha256 = "07yzy4wafk79ps0hmbqmsqh5xjna4pm4q57wc847bb8gl3nh4f94"; + procMacro = true; + authors = [ + "Erick Tryzelaar <erick.tryzelaar@gmail.com>" + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + features = [ "proc-macro" ]; + } + { + name = "quote"; + packageId = "quote"; + usesDefaultFeatures = false; + features = [ "proc-macro" ]; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + usesDefaultFeatures = false; + features = [ "clone-impls" "derive" "parsing" "printing" "proc-macro" ]; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; + "serde_json" = rec { + crateName = "serde_json"; + version = "1.0.120"; + edition = "2021"; + sha256 = "1idpv3zxcvl76z2z47jgg1f1wjqdnhfc204asmd27qfam34j23af"; + authors = [ + "Erick Tryzelaar <erick.tryzelaar@gmail.com>" + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "itoa"; + packageId = "itoa"; + } + { + name = "ryu"; + packageId = "ryu"; + } + { + name = "serde"; + packageId = "serde"; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + ]; + features = { + "alloc" = [ "serde/alloc" ]; + "default" = [ "std" ]; + "indexmap" = [ "dep:indexmap" ]; + "preserve_order" = [ "indexmap" "std" ]; + "std" = [ "serde/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "serde_spanned" = rec { + crateName = "serde_spanned"; + version = "0.6.5"; + edition = "2021"; + sha256 = "1hgh6s3jjwyzhfk3xwb6pnnr1misq9nflwq0f026jafi37s24dpb"; + dependencies = [ + { + name = "serde"; + packageId = "serde"; + optional = true; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + } + ]; + features = { + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "serde" ]; + }; + "serde_urlencoded" = rec { + crateName = "serde_urlencoded"; + version = "0.7.1"; + edition = "2018"; + sha256 = "1zgklbdaysj3230xivihs30qi5vkhigg323a9m62k8jwf4a1qjfk"; + authors = [ + "Anthony Ramine <n.oxyde@gmail.com>" + ]; + dependencies = [ + { + name = "form_urlencoded"; + packageId = "form_urlencoded"; + } + { + name = "itoa"; + packageId = "itoa"; + } + { + name = "ryu"; + packageId = "ryu"; + } + { + name = "serde"; + packageId = "serde"; + } + ]; + + }; + "sha1" = rec { + crateName = "sha1"; + version = "0.10.6"; + edition = "2018"; + sha256 = "1fnnxlfg08xhkmwf2ahv634as30l1i3xhlhkvxflmasi5nd85gz3"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "cpufeatures"; + packageId = "cpufeatures"; + target = { target, features }: (("aarch64" == target."arch" or null) || ("x86" == target."arch" or null) || ("x86_64" == target."arch" or null)); + } + { + name = "digest"; + packageId = "digest"; + } + ]; + devDependencies = [ + { + name = "digest"; + packageId = "digest"; + features = [ "dev" ]; + } + ]; + features = { + "asm" = [ "sha1-asm" ]; + "default" = [ "std" ]; + "oid" = [ "digest/oid" ]; + "sha1-asm" = [ "dep:sha1-asm" ]; + "std" = [ "digest/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "sha2" = rec { + crateName = "sha2"; + version = "0.10.8"; + edition = "2018"; + sha256 = "1j1x78zk9il95w9iv46dh9wm73r6xrgj32y6lzzw7bxws9dbfgbr"; + authors = [ + "RustCrypto Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "cpufeatures"; + packageId = "cpufeatures"; + target = { target, features }: (("aarch64" == target."arch" or null) || ("x86_64" == target."arch" or null) || ("x86" == target."arch" or null)); + } + { + name = "digest"; + packageId = "digest"; + } + ]; + devDependencies = [ + { + name = "digest"; + packageId = "digest"; + features = [ "dev" ]; + } + ]; + features = { + "asm" = [ "sha2-asm" ]; + "asm-aarch64" = [ "asm" ]; + "default" = [ "std" ]; + "oid" = [ "digest/oid" ]; + "sha2-asm" = [ "dep:sha2-asm" ]; + "std" = [ "digest/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "slab" = rec { + crateName = "slab"; + version = "0.4.9"; + edition = "2018"; + sha256 = "0rxvsgir0qw5lkycrqgb1cxsvxzjv9bmx73bk5y42svnzfba94lg"; + authors = [ + "Carl Lerche <me@carllerche.com>" + ]; + buildDependencies = [ + { + name = "autocfg"; + packageId = "autocfg"; + } + ]; + features = { + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "smol_str" = rec { + crateName = "smol_str"; + version = "0.2.2"; + edition = "2018"; + sha256 = "1bfylqf2vnqaglw58930vpxm2rfzji5gjp15a2c0kh8aj6v8ylyx"; + authors = [ + "Aleksey Kladov <aleksey.kladov@gmail.com>" + ]; + dependencies = [ + { + name = "serde"; + packageId = "serde"; + optional = true; + usesDefaultFeatures = false; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + ]; + features = { + "arbitrary" = [ "dep:arbitrary" ]; + "default" = [ "std" ]; + "serde" = [ "dep:serde" ]; + "std" = [ "serde?/std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "static_assertions" = rec { + crateName = "static_assertions"; + version = "1.1.0"; + edition = "2015"; + sha256 = "0gsl6xmw10gvn3zs1rv99laj5ig7ylffnh71f9l34js4nr4r7sx2"; + authors = [ + "Nikolai Vazquez" + ]; + features = { }; + }; + "syn 1.0.109" = rec { + crateName = "syn"; + version = "1.0.109"; + edition = "2018"; + sha256 = "0ds2if4600bd59wsv7jjgfkayfzy3hnazs394kz6zdkmna8l3dkj"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + { + name = "quote"; + packageId = "quote"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "unicode-ident"; + packageId = "unicode-ident"; + } + ]; + features = { + "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; + "printing" = [ "quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote/proc-macro" ]; + "quote" = [ "dep:quote" ]; + "test" = [ "syn-test-suite/all-features" ]; + }; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit" "visit-mut" ]; + }; + "syn 2.0.68" = rec { + crateName = "syn"; + version = "2.0.68"; + edition = "2021"; + sha256 = "1sf1y2hajhjav38ipg63c934xrgkz4v42fz24a0ckmmri06sf7wh"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + usesDefaultFeatures = false; + } + { + name = "quote"; + packageId = "quote"; + optional = true; + usesDefaultFeatures = false; + } + { + name = "unicode-ident"; + packageId = "unicode-ident"; + } + ]; + features = { + "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; + "printing" = [ "dep:quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; + "test" = [ "syn-test-suite/all-features" ]; + }; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; + }; + "tabwriter" = rec { + crateName = "tabwriter"; + version = "1.4.0"; + edition = "2021"; + sha256 = "1xp5j7v8jsk92zcmiyh4ya9akhrchjvc595vwcvxrxk49wn2h9x3"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "unicode-width"; + packageId = "unicode-width"; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; + "termcolor" = rec { + crateName = "termcolor"; + version = "1.4.1"; + edition = "2018"; + sha256 = "0mappjh3fj3p2nmrg4y7qv94rchwi9mzmgmfflr8p2awdj7lyy86"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "winapi-util"; + packageId = "winapi-util"; + target = { target, features }: (target."windows" or false); + } + ]; + + }; + "text-size" = rec { + crateName = "text-size"; + version = "1.1.1"; + edition = "2018"; + sha256 = "0cwjbkl7w3xc8mnkhg1nwij6p5y2qkcfldgss8ddnawvhf3s32pi"; + libName = "text_size"; + authors = [ + "Aleksey Kladov <aleksey.kladov@gmail.com>" + "Christopher Durham (CAD97) <cad97@cad97.com>" + ]; + features = { + "serde" = [ "dep:serde" ]; + }; + }; + "thiserror" = rec { + crateName = "thiserror"; + version = "1.0.63"; + edition = "2021"; + sha256 = "092p83mf4p1vkjb2j6h6z96dan4raq2simhirjv12slbndq26d60"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "thiserror-impl"; + packageId = "thiserror-impl"; + } + ]; + + }; + "thiserror-impl" = rec { + crateName = "thiserror-impl"; + version = "1.0.63"; + edition = "2021"; + sha256 = "0qd21l2jjrkvnpr5da3l3b58v4wmrkn6aa0h1z5dg6kb8rc8nmd4"; + procMacro = true; + libName = "thiserror_impl"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + } + ]; + + }; + "tokio" = rec { + crateName = "tokio"; + version = "1.39.2"; + edition = "2021"; + sha256 = "1cb7yhba7nnf00cylcywk7rai5kkdb8b4jzwrc26zgbqqwdzp96s"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "backtrace"; + packageId = "backtrace"; + target = { target, features }: (target."tokio_taskdump" or false); + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + ]; + features = { + "bytes" = [ "dep:bytes" ]; + "full" = [ "fs" "io-util" "io-std" "macros" "net" "parking_lot" "process" "rt" "rt-multi-thread" "signal" "sync" "time" ]; + "io-util" = [ "bytes" ]; + "libc" = [ "dep:libc" ]; + "macros" = [ "tokio-macros" ]; + "mio" = [ "dep:mio" ]; + "net" = [ "libc" "mio/os-poll" "mio/os-ext" "mio/net" "socket2" "windows-sys/Win32_Foundation" "windows-sys/Win32_Security" "windows-sys/Win32_Storage_FileSystem" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_System_SystemServices" ]; + "parking_lot" = [ "dep:parking_lot" ]; + "process" = [ "bytes" "libc" "mio/os-poll" "mio/os-ext" "mio/net" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Threading" "windows-sys/Win32_System_WindowsProgramming" ]; + "rt-multi-thread" = [ "rt" ]; + "signal" = [ "libc" "mio/os-poll" "mio/net" "mio/os-ext" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Console" ]; + "signal-hook-registry" = [ "dep:signal-hook-registry" ]; + "socket2" = [ "dep:socket2" ]; + "test-util" = [ "rt" "sync" "time" ]; + "tokio-macros" = [ "dep:tokio-macros" ]; + "tracing" = [ "dep:tracing" ]; + "windows-sys" = [ "dep:windows-sys" ]; + }; + resolvedDefaultFeatures = [ "default" "rt" "sync" "time" ]; + }; + "tokio-stream" = rec { + crateName = "tokio-stream"; + version = "0.1.15"; + edition = "2021"; + sha256 = "1brpbsqyg8yfmfc4y0j9zxvc8xsxjc31d48kb0g6jvpc1fgchyi6"; + libName = "tokio_stream"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "futures-core"; + packageId = "futures-core"; + } + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "sync" ]; + } + ]; + devDependencies = [ + { + name = "tokio"; + packageId = "tokio"; + features = [ "full" "test-util" ]; + } + ]; + features = { + "default" = [ "time" ]; + "fs" = [ "tokio/fs" ]; + "full" = [ "time" "net" "io-util" "fs" "sync" "signal" ]; + "io-util" = [ "tokio/io-util" ]; + "net" = [ "tokio/net" ]; + "signal" = [ "tokio/signal" ]; + "sync" = [ "tokio/sync" "tokio-util" ]; + "time" = [ "tokio/time" ]; + "tokio-util" = [ "dep:tokio-util" ]; + }; + resolvedDefaultFeatures = [ "default" "time" ]; + }; + "toml" = rec { + crateName = "toml"; + version = "0.6.0"; + edition = "2021"; + sha256 = "05zjz69wjymp9yrgccg5vhvxpf855rgn23vl1yvri4nwwj8difag"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "serde"; + packageId = "serde"; + } + { + name = "serde_spanned"; + packageId = "serde_spanned"; + features = [ "serde" ]; + } + { + name = "toml_datetime"; + packageId = "toml_datetime 0.5.1"; + features = [ "serde" ]; + } + { + name = "toml_edit"; + packageId = "toml_edit 0.18.1"; + optional = true; + features = [ "serde" ]; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + ]; + features = { + "default" = [ "parse" "display" ]; + "display" = [ "dep:toml_edit" ]; + "indexmap" = [ "dep:indexmap" ]; + "parse" = [ "dep:toml_edit" ]; + "preserve_order" = [ "indexmap" ]; + }; + resolvedDefaultFeatures = [ "default" "display" "parse" ]; + }; + "toml_datetime 0.5.1" = rec { + crateName = "toml_datetime"; + version = "0.5.1"; + edition = "2021"; + sha256 = "1xcw3kyklh3s2gxp65ma26rgkl7505la4xx1r55kfgcfmikz8ls5"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + dependencies = [ + { + name = "serde"; + packageId = "serde"; + optional = true; + } + ]; + features = { + "serde" = [ "dep:serde" ]; + }; + resolvedDefaultFeatures = [ "serde" ]; + }; + "toml_datetime 0.6.7" = rec { + crateName = "toml_datetime"; + version = "0.6.7"; + edition = "2021"; + sha256 = "1nx11ng5fxp8f8bw4y0wiw9351qpv92ca2ll3l7q8hj865j9zyzq"; + authors = [ + "Alex Crichton <alex@alexcrichton.com>" + ]; + features = { + "serde" = [ "dep:serde" ]; + }; + }; + "toml_edit 0.18.1" = rec { + crateName = "toml_edit"; + version = "0.18.1"; + edition = "2021"; + sha256 = "0ax1bwzd4xclpids3b69nd1nxqi3x3qa4ymz51jbrp6hsy6rvian"; + authors = [ + "Andronik Ordian <write@reusable.software>" + "Ed Page <eopage@gmail.com>" + ]; + dependencies = [ + { + name = "indexmap"; + packageId = "indexmap 1.9.3"; + } + { + name = "nom8"; + packageId = "nom8"; + } + { + name = "serde"; + packageId = "serde"; + optional = true; + } + { + name = "serde_spanned"; + packageId = "serde_spanned"; + optional = true; + features = [ "serde" ]; + } + { + name = "toml_datetime"; + packageId = "toml_datetime 0.5.1"; + } + ]; + features = { + "easy" = [ "serde" ]; + "perf" = [ "dep:kstring" ]; + "serde" = [ "dep:serde" "toml_datetime/serde" "dep:serde_spanned" ]; + }; + resolvedDefaultFeatures = [ "default" "serde" ]; + }; + "toml_edit 0.19.15" = rec { + crateName = "toml_edit"; + version = "0.19.15"; + edition = "2021"; + sha256 = "08bl7rp5g6jwmfpad9s8jpw8wjrciadpnbaswgywpr9hv9qbfnqv"; + authors = [ + "Andronik Ordian <write@reusable.software>" + "Ed Page <eopage@gmail.com>" + ]; + dependencies = [ + { + name = "indexmap"; + packageId = "indexmap 2.2.6"; + features = [ "std" ]; + } + { + name = "toml_datetime"; + packageId = "toml_datetime 0.6.7"; + } + { + name = "winnow"; + packageId = "winnow"; + } + ]; + features = { + "perf" = [ "dep:kstring" ]; + "serde" = [ "dep:serde" "toml_datetime/serde" "dep:serde_spanned" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "tracing" = rec { + crateName = "tracing"; + version = "0.1.40"; + edition = "2018"; + sha256 = "1vv48dac9zgj9650pg2b4d0j3w6f3x9gbggf43scq5hrlysklln3"; + authors = [ + "Eliza Weisman <eliza@buoyant.io>" + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tracing-attributes"; + packageId = "tracing-attributes"; + optional = true; + } + { + name = "tracing-core"; + packageId = "tracing-core"; + usesDefaultFeatures = false; + } + ]; + features = { + "attributes" = [ "tracing-attributes" ]; + "default" = [ "std" "attributes" ]; + "log" = [ "dep:log" ]; + "log-always" = [ "log" ]; + "std" = [ "tracing-core/std" ]; + "tracing-attributes" = [ "dep:tracing-attributes" ]; + "valuable" = [ "tracing-core/valuable" ]; + }; + resolvedDefaultFeatures = [ "attributes" "default" "std" "tracing-attributes" ]; + }; + "tracing-attributes" = rec { + crateName = "tracing-attributes"; + version = "0.1.27"; + edition = "2018"; + sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; + procMacro = true; + libName = "tracing_attributes"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + "Eliza Weisman <eliza@buoyant.io>" + "David Barsky <dbarsky@amazon.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "visit-mut" "clone-impls" "extra-traits" "proc-macro" ]; + } + ]; + features = { }; + }; + "tracing-core" = rec { + crateName = "tracing-core"; + version = "0.1.32"; + edition = "2018"; + sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "once_cell"; + packageId = "once_cell"; + optional = true; + } + ]; + features = { + "default" = [ "std" "valuable/std" ]; + "once_cell" = [ "dep:once_cell" ]; + "std" = [ "once_cell" ]; + "valuable" = [ "dep:valuable" ]; + }; + resolvedDefaultFeatures = [ "once_cell" "std" ]; + }; + "tvix-eval" = rec { + crateName = "tvix-eval"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../tvix/eval; }; + libName = "tvix_eval"; + dependencies = [ + { + name = "bstr"; + packageId = "bstr"; + features = [ "serde" ]; + } + { + name = "bytes"; + packageId = "bytes"; + } + { + name = "codemap"; + packageId = "codemap"; + } + { + name = "codemap-diagnostic"; + packageId = "codemap-diagnostic"; + } + { + name = "data-encoding"; + packageId = "data-encoding"; + } + { + name = "dirs"; + packageId = "dirs"; + } + { + name = "genawaiter"; + packageId = "genawaiter"; + usesDefaultFeatures = false; + } + { + name = "itertools"; + packageId = "itertools"; + } + { + name = "lazy_static"; + packageId = "lazy_static"; + } + { + name = "lexical-core"; + packageId = "lexical-core"; + features = [ "format" "parse-floats" ]; + } + { + name = "md-5"; + packageId = "md-5"; + } + { + name = "nohash-hasher"; + packageId = "nohash-hasher"; + } + { + name = "os_str_bytes"; + packageId = "os_str_bytes"; + features = [ "conversions" ]; + } + { + name = "path-clean"; + packageId = "path-clean"; + } + { + name = "regex"; + packageId = "regex"; + } + { + name = "rnix"; + packageId = "rnix"; + } + { + name = "rowan"; + packageId = "rowan"; + } + { + name = "rustc-hash"; + packageId = "rustc-hash 2.0.0"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "rc" "derive" ]; + } + { + name = "serde_json"; + packageId = "serde_json"; + } + { + name = "sha1"; + packageId = "sha1"; + } + { + name = "sha2"; + packageId = "sha2"; + } + { + name = "smol_str"; + packageId = "smol_str"; + } + { + name = "tabwriter"; + packageId = "tabwriter"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "toml"; + packageId = "toml"; + } + { + name = "tvix-eval-builtin-macros"; + packageId = "tvix-eval-builtin-macros"; + rename = "builtin-macros"; + } + { + name = "vu128"; + packageId = "vu128"; + } + ]; + devDependencies = [ + { + name = "itertools"; + packageId = "itertools"; + } + ]; + features = { + "arbitrary" = [ "proptest" "test-strategy" ]; + "default" = [ "impure" "arbitrary" "nix_tests" ]; + "proptest" = [ "dep:proptest" ]; + "test-strategy" = [ "dep:test-strategy" ]; + }; + }; + "tvix-eval-builtin-macros" = rec { + crateName = "tvix-eval-builtin-macros"; + version = "0.0.1"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../tvix/eval/builtin-macros; }; + procMacro = true; + libName = "tvix_eval_builtin_macros"; + authors = [ + "Griffin Smith <root@gws.fyi>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 1.0.109"; + features = [ "full" "parsing" "printing" "visit" "visit-mut" "extra-traits" ]; + } + ]; + + }; + "tvixbolt" = rec { + crateName = "tvixbolt"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./.; }; + type = [ "cdylib" ]; + dependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "tvix-eval"; + packageId = "tvix-eval"; + usesDefaultFeatures = false; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "HtmlDetailsElement" ]; + } + { + name = "yew"; + packageId = "yew"; + features = [ "csr" ]; + } + { + name = "yew-router"; + packageId = "yew-router"; + } + ]; + + }; + "typenum" = rec { + crateName = "typenum"; + version = "1.17.0"; + edition = "2018"; + sha256 = "09dqxv69m9lj9zvv6xw5vxaqx15ps0vxyy5myg33i0kbqvq0pzs2"; + build = "build/main.rs"; + authors = [ + "Paho Lurie-Gregg <paho@paholg.com>" + "Andre Bogus <bogusandre@gmail.com>" + ]; + features = { + "scale-info" = [ "dep:scale-info" ]; + "scale_info" = [ "scale-info/derive" ]; + }; + }; + "unicode-ident" = rec { + crateName = "unicode-ident"; + version = "1.0.12"; + edition = "2018"; + sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + + }; + "unicode-width" = rec { + crateName = "unicode-width"; + version = "0.1.11"; + edition = "2015"; + sha256 = "11ds4ydhg8g7l06rlmh712q41qsrd0j0h00n1jm74kww3kqk65z5"; + libName = "unicode_width"; + authors = [ + "kwantam <kwantam@gmail.com>" + "Manish Goregaokar <manishsmail@gmail.com>" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "std" "core" "compiler_builtins" ]; + "std" = [ "dep:std" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; + "urlencoding" = rec { + crateName = "urlencoding"; + version = "2.1.3"; + edition = "2021"; + sha256 = "1nj99jp37k47n0hvaz5fvz7z6jd0sb4ppvfy3nphr1zbnyixpy6s"; + authors = [ + "Kornel <kornel@geekhood.net>" + "Bertram Truong <b@bertramtruong.com>" + ]; + + }; + "version_check" = rec { + crateName = "version_check"; + version = "0.9.4"; + edition = "2015"; + sha256 = "0gs8grwdlgh0xq660d7wr80x14vxbizmd8dbp29p2pdncx8lp1s9"; + authors = [ + "Sergio Benitez <sb@sergio.bz>" + ]; + + }; + "vu128" = rec { + crateName = "vu128"; + version = "1.1.0"; + edition = "2018"; + sha256 = "1pczgy26c0lsri1ddrx5wkgn0rcq4da04pqya5rl6vrwfnys73di"; + libPath = "vu128/vu128.rs"; + authors = [ + "John Millikin <john@john-millikin.com>" + ]; + + }; + "wasi" = rec { + crateName = "wasi"; + version = "0.11.0+wasi-snapshot-preview1"; + edition = "2018"; + sha256 = "08z4hxwkpdpalxjps1ai9y7ihin26y9f476i53dv98v45gkqg3cw"; + authors = [ + "The Cranelift Project Developers" + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "std" ]; + "rustc-dep-of-std" = [ "compiler_builtins" "core" "rustc-std-workspace-alloc" ]; + "rustc-std-workspace-alloc" = [ "dep:rustc-std-workspace-alloc" ]; + }; + }; + "wasm-bindgen" = rec { + crateName = "wasm-bindgen"; + version = "0.2.93"; + edition = "2021"; + sha256 = "1dfr7pka5kwvky2fx82m9d060p842hc5fyyw8igryikcdb0xybm8"; + libName = "wasm_bindgen"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "wasm-bindgen-macro"; + packageId = "wasm-bindgen-macro"; + } + ]; + features = { + "default" = [ "spans" "std" ]; + "enable-interning" = [ "std" ]; + "serde" = [ "dep:serde" ]; + "serde-serialize" = [ "serde" "serde_json" "std" ]; + "serde_json" = [ "dep:serde_json" ]; + "spans" = [ "wasm-bindgen-macro/spans" ]; + "strict-macro" = [ "wasm-bindgen-macro/strict-macro" ]; + "xxx_debug_only_print_generated_code" = [ "wasm-bindgen-macro/xxx_debug_only_print_generated_code" ]; + }; + resolvedDefaultFeatures = [ "default" "spans" "std" ]; + }; + "wasm-bindgen-backend" = rec { + crateName = "wasm-bindgen-backend"; + version = "0.2.93"; + edition = "2021"; + sha256 = "0yypblaf94rdgqs5xw97499xfwgs1096yx026d6h88v563d9dqwx"; + libName = "wasm_bindgen_backend"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "bumpalo"; + packageId = "bumpalo"; + } + { + name = "log"; + packageId = "log"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + features = [ "full" ]; + } + { + name = "wasm-bindgen-shared"; + packageId = "wasm-bindgen-shared"; + } + ]; + features = { + "extra-traits" = [ "syn/extra-traits" ]; + }; + resolvedDefaultFeatures = [ "spans" ]; + }; + "wasm-bindgen-futures" = rec { + crateName = "wasm-bindgen-futures"; + version = "0.4.42"; + edition = "2018"; + sha256 = "1h322zjvpjllcpj7dahfxjsv6inkr6y0baw7nkdwivr1c4v19g3n"; + libName = "wasm_bindgen_futures"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "cfg-if"; + packageId = "cfg-if"; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + target = { target, features }: (builtins.elem "atomics" targetFeatures); + features = [ "MessageEvent" "Worker" ]; + } + ]; + features = { + "futures-core" = [ "dep:futures-core" ]; + "futures-core-03-stream" = [ "futures-core" ]; + }; + }; + "wasm-bindgen-macro" = rec { + crateName = "wasm-bindgen-macro"; + version = "0.2.93"; + edition = "2021"; + sha256 = "1kycd1xfx4d9xzqknvzbiqhwb5fzvjqrrn88x692q1vblj8lqp2q"; + procMacro = true; + libName = "wasm_bindgen_macro"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "quote"; + packageId = "quote"; + } + { + name = "wasm-bindgen-macro-support"; + packageId = "wasm-bindgen-macro-support"; + } + ]; + features = { + "spans" = [ "wasm-bindgen-macro-support/spans" ]; + "strict-macro" = [ "wasm-bindgen-macro-support/strict-macro" ]; + }; + resolvedDefaultFeatures = [ "spans" ]; + }; + "wasm-bindgen-macro-support" = rec { + crateName = "wasm-bindgen-macro-support"; + version = "0.2.93"; + edition = "2021"; + sha256 = "0dp8w6jmw44srym6l752nkr3hkplyw38a2fxz5f3j1ch9p3l1hxg"; + libName = "wasm_bindgen_macro_support"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + features = [ "visit" "full" ]; + } + { + name = "wasm-bindgen-backend"; + packageId = "wasm-bindgen-backend"; + } + { + name = "wasm-bindgen-shared"; + packageId = "wasm-bindgen-shared"; + } + ]; + features = { + "extra-traits" = [ "syn/extra-traits" ]; + "spans" = [ "wasm-bindgen-backend/spans" ]; + }; + resolvedDefaultFeatures = [ "spans" ]; + }; + "wasm-bindgen-shared" = rec { + crateName = "wasm-bindgen-shared"; + version = "0.2.93"; + edition = "2021"; + links = "wasm_bindgen"; + sha256 = "1104bny0hv40jfap3hp8jhs0q4ya244qcrvql39i38xlghq0lan6"; + libName = "wasm_bindgen_shared"; + authors = [ + "The wasm-bindgen Developers" + ]; + + }; + "web-sys" = rec { + crateName = "web-sys"; + version = "0.3.69"; + edition = "2018"; + sha256 = "1vqkxk935xa8zcnsi4bd88sb267ly2i24xl1yiq26d1n32hskbvp"; + libName = "web_sys"; + authors = [ + "The wasm-bindgen Developers" + ]; + dependencies = [ + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + ]; + features = { + "AbortSignal" = [ "EventTarget" ]; + "AnalyserNode" = [ "AudioNode" "EventTarget" ]; + "Animation" = [ "EventTarget" ]; + "AnimationEvent" = [ "Event" ]; + "AnimationPlaybackEvent" = [ "Event" ]; + "Attr" = [ "EventTarget" "Node" ]; + "AudioBufferSourceNode" = [ "AudioNode" "AudioScheduledSourceNode" "EventTarget" ]; + "AudioContext" = [ "BaseAudioContext" "EventTarget" ]; + "AudioDestinationNode" = [ "AudioNode" "EventTarget" ]; + "AudioNode" = [ "EventTarget" ]; + "AudioProcessingEvent" = [ "Event" ]; + "AudioScheduledSourceNode" = [ "AudioNode" "EventTarget" ]; + "AudioStreamTrack" = [ "EventTarget" "MediaStreamTrack" ]; + "AudioTrackList" = [ "EventTarget" ]; + "AudioWorklet" = [ "Worklet" ]; + "AudioWorkletGlobalScope" = [ "WorkletGlobalScope" ]; + "AudioWorkletNode" = [ "AudioNode" "EventTarget" ]; + "AuthenticatorAssertionResponse" = [ "AuthenticatorResponse" ]; + "AuthenticatorAttestationResponse" = [ "AuthenticatorResponse" ]; + "BaseAudioContext" = [ "EventTarget" ]; + "BatteryManager" = [ "EventTarget" ]; + "BeforeUnloadEvent" = [ "Event" ]; + "BiquadFilterNode" = [ "AudioNode" "EventTarget" ]; + "BlobEvent" = [ "Event" ]; + "Bluetooth" = [ "EventTarget" ]; + "BluetoothAdvertisingEvent" = [ "Event" ]; + "BluetoothDevice" = [ "EventTarget" ]; + "BluetoothPermissionResult" = [ "EventTarget" "PermissionStatus" ]; + "BluetoothRemoteGattCharacteristic" = [ "EventTarget" ]; + "BluetoothRemoteGattService" = [ "EventTarget" ]; + "BroadcastChannel" = [ "EventTarget" ]; + "CanvasCaptureMediaStream" = [ "EventTarget" "MediaStream" ]; + "CanvasCaptureMediaStreamTrack" = [ "EventTarget" "MediaStreamTrack" ]; + "CdataSection" = [ "CharacterData" "EventTarget" "Node" "Text" ]; + "ChannelMergerNode" = [ "AudioNode" "EventTarget" ]; + "ChannelSplitterNode" = [ "AudioNode" "EventTarget" ]; + "CharacterData" = [ "EventTarget" "Node" ]; + "ChromeWorker" = [ "EventTarget" "Worker" ]; + "Clipboard" = [ "EventTarget" ]; + "ClipboardEvent" = [ "Event" ]; + "CloseEvent" = [ "Event" ]; + "Comment" = [ "CharacterData" "EventTarget" "Node" ]; + "CompositionEvent" = [ "Event" "UiEvent" ]; + "ConstantSourceNode" = [ "AudioNode" "AudioScheduledSourceNode" "EventTarget" ]; + "ConvolverNode" = [ "AudioNode" "EventTarget" ]; + "CssAnimation" = [ "Animation" "EventTarget" ]; + "CssConditionRule" = [ "CssGroupingRule" "CssRule" ]; + "CssCounterStyleRule" = [ "CssRule" ]; + "CssFontFaceRule" = [ "CssRule" ]; + "CssFontFeatureValuesRule" = [ "CssRule" ]; + "CssGroupingRule" = [ "CssRule" ]; + "CssImportRule" = [ "CssRule" ]; + "CssKeyframeRule" = [ "CssRule" ]; + "CssKeyframesRule" = [ "CssRule" ]; + "CssMediaRule" = [ "CssConditionRule" "CssGroupingRule" "CssRule" ]; + "CssNamespaceRule" = [ "CssRule" ]; + "CssPageRule" = [ "CssRule" ]; + "CssStyleRule" = [ "CssRule" ]; + "CssStyleSheet" = [ "StyleSheet" ]; + "CssSupportsRule" = [ "CssConditionRule" "CssGroupingRule" "CssRule" ]; + "CssTransition" = [ "Animation" "EventTarget" ]; + "CustomEvent" = [ "Event" ]; + "DedicatedWorkerGlobalScope" = [ "EventTarget" "WorkerGlobalScope" ]; + "DelayNode" = [ "AudioNode" "EventTarget" ]; + "DeviceLightEvent" = [ "Event" ]; + "DeviceMotionEvent" = [ "Event" ]; + "DeviceOrientationEvent" = [ "Event" ]; + "DeviceProximityEvent" = [ "Event" ]; + "Document" = [ "EventTarget" "Node" ]; + "DocumentFragment" = [ "EventTarget" "Node" ]; + "DocumentTimeline" = [ "AnimationTimeline" ]; + "DocumentType" = [ "EventTarget" "Node" ]; + "DomMatrix" = [ "DomMatrixReadOnly" ]; + "DomPoint" = [ "DomPointReadOnly" ]; + "DomRect" = [ "DomRectReadOnly" ]; + "DomRequest" = [ "EventTarget" ]; + "DragEvent" = [ "Event" "MouseEvent" "UiEvent" ]; + "DynamicsCompressorNode" = [ "AudioNode" "EventTarget" ]; + "Element" = [ "EventTarget" "Node" ]; + "ErrorEvent" = [ "Event" ]; + "EventSource" = [ "EventTarget" ]; + "ExtendableEvent" = [ "Event" ]; + "ExtendableMessageEvent" = [ "Event" "ExtendableEvent" ]; + "FetchEvent" = [ "Event" "ExtendableEvent" ]; + "FetchObserver" = [ "EventTarget" ]; + "File" = [ "Blob" ]; + "FileReader" = [ "EventTarget" ]; + "FileSystemDirectoryEntry" = [ "FileSystemEntry" ]; + "FileSystemDirectoryHandle" = [ "FileSystemHandle" ]; + "FileSystemFileEntry" = [ "FileSystemEntry" ]; + "FileSystemFileHandle" = [ "FileSystemHandle" ]; + "FileSystemWritableFileStream" = [ "WritableStream" ]; + "FocusEvent" = [ "Event" "UiEvent" ]; + "FontFaceSet" = [ "EventTarget" ]; + "FontFaceSetLoadEvent" = [ "Event" ]; + "GainNode" = [ "AudioNode" "EventTarget" ]; + "GamepadAxisMoveEvent" = [ "Event" "GamepadEvent" ]; + "GamepadButtonEvent" = [ "Event" "GamepadEvent" ]; + "GamepadEvent" = [ "Event" ]; + "GpuDevice" = [ "EventTarget" ]; + "GpuInternalError" = [ "GpuError" ]; + "GpuOutOfMemoryError" = [ "GpuError" ]; + "GpuPipelineError" = [ "DomException" ]; + "GpuUncapturedErrorEvent" = [ "Event" ]; + "GpuValidationError" = [ "GpuError" ]; + "HashChangeEvent" = [ "Event" ]; + "Hid" = [ "EventTarget" ]; + "HidConnectionEvent" = [ "Event" ]; + "HidDevice" = [ "EventTarget" ]; + "HidInputReportEvent" = [ "Event" ]; + "HtmlAnchorElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlAreaElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlAudioElement" = [ "Element" "EventTarget" "HtmlElement" "HtmlMediaElement" "Node" ]; + "HtmlBaseElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlBodyElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlBrElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlButtonElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlCanvasElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlDListElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlDataElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlDataListElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlDetailsElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlDialogElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlDirectoryElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlDivElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlDocument" = [ "Document" "EventTarget" "Node" ]; + "HtmlElement" = [ "Element" "EventTarget" "Node" ]; + "HtmlEmbedElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlFieldSetElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlFontElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlFormControlsCollection" = [ "HtmlCollection" ]; + "HtmlFormElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlFrameElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlFrameSetElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlHeadElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlHeadingElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlHrElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlHtmlElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlIFrameElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlImageElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlInputElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlLabelElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlLegendElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlLiElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlLinkElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlMapElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlMediaElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlMenuElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlMenuItemElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlMetaElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlMeterElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlModElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlOListElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlObjectElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlOptGroupElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlOptionElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlOptionsCollection" = [ "HtmlCollection" ]; + "HtmlOutputElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlParagraphElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlParamElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlPictureElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlPreElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlProgressElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlQuoteElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlScriptElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlSelectElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlSlotElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlSourceElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlSpanElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlStyleElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlTableCaptionElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlTableCellElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlTableColElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlTableElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlTableRowElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlTableSectionElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlTemplateElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlTextAreaElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlTimeElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlTitleElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlTrackElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlUListElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlUnknownElement" = [ "Element" "EventTarget" "HtmlElement" "Node" ]; + "HtmlVideoElement" = [ "Element" "EventTarget" "HtmlElement" "HtmlMediaElement" "Node" ]; + "IdbCursorWithValue" = [ "IdbCursor" ]; + "IdbDatabase" = [ "EventTarget" ]; + "IdbFileHandle" = [ "EventTarget" ]; + "IdbFileRequest" = [ "DomRequest" "EventTarget" ]; + "IdbLocaleAwareKeyRange" = [ "IdbKeyRange" ]; + "IdbMutableFile" = [ "EventTarget" ]; + "IdbOpenDbRequest" = [ "EventTarget" "IdbRequest" ]; + "IdbRequest" = [ "EventTarget" ]; + "IdbTransaction" = [ "EventTarget" ]; + "IdbVersionChangeEvent" = [ "Event" ]; + "IirFilterNode" = [ "AudioNode" "EventTarget" ]; + "ImageCaptureErrorEvent" = [ "Event" ]; + "ImageTrack" = [ "EventTarget" ]; + "InputEvent" = [ "Event" "UiEvent" ]; + "KeyboardEvent" = [ "Event" "UiEvent" ]; + "KeyframeEffect" = [ "AnimationEffect" ]; + "LocalMediaStream" = [ "EventTarget" "MediaStream" ]; + "MediaDevices" = [ "EventTarget" ]; + "MediaElementAudioSourceNode" = [ "AudioNode" "EventTarget" ]; + "MediaEncryptedEvent" = [ "Event" ]; + "MediaKeyError" = [ "Event" ]; + "MediaKeyMessageEvent" = [ "Event" ]; + "MediaKeySession" = [ "EventTarget" ]; + "MediaQueryList" = [ "EventTarget" ]; + "MediaQueryListEvent" = [ "Event" ]; + "MediaRecorder" = [ "EventTarget" ]; + "MediaRecorderErrorEvent" = [ "Event" ]; + "MediaSource" = [ "EventTarget" ]; + "MediaStream" = [ "EventTarget" ]; + "MediaStreamAudioDestinationNode" = [ "AudioNode" "EventTarget" ]; + "MediaStreamAudioSourceNode" = [ "AudioNode" "EventTarget" ]; + "MediaStreamEvent" = [ "Event" ]; + "MediaStreamTrack" = [ "EventTarget" ]; + "MediaStreamTrackEvent" = [ "Event" ]; + "MediaStreamTrackGenerator" = [ "EventTarget" "MediaStreamTrack" ]; + "MessageEvent" = [ "Event" ]; + "MessagePort" = [ "EventTarget" ]; + "MidiAccess" = [ "EventTarget" ]; + "MidiConnectionEvent" = [ "Event" ]; + "MidiInput" = [ "EventTarget" "MidiPort" ]; + "MidiMessageEvent" = [ "Event" ]; + "MidiOutput" = [ "EventTarget" "MidiPort" ]; + "MidiPort" = [ "EventTarget" ]; + "MouseEvent" = [ "Event" "UiEvent" ]; + "MouseScrollEvent" = [ "Event" "MouseEvent" "UiEvent" ]; + "MutationEvent" = [ "Event" ]; + "NetworkInformation" = [ "EventTarget" ]; + "Node" = [ "EventTarget" ]; + "Notification" = [ "EventTarget" ]; + "NotificationEvent" = [ "Event" "ExtendableEvent" ]; + "OfflineAudioCompletionEvent" = [ "Event" ]; + "OfflineAudioContext" = [ "BaseAudioContext" "EventTarget" ]; + "OfflineResourceList" = [ "EventTarget" ]; + "OffscreenCanvas" = [ "EventTarget" ]; + "OscillatorNode" = [ "AudioNode" "AudioScheduledSourceNode" "EventTarget" ]; + "PageTransitionEvent" = [ "Event" ]; + "PaintWorkletGlobalScope" = [ "WorkletGlobalScope" ]; + "PannerNode" = [ "AudioNode" "EventTarget" ]; + "PaymentMethodChangeEvent" = [ "Event" "PaymentRequestUpdateEvent" ]; + "PaymentRequestUpdateEvent" = [ "Event" ]; + "Performance" = [ "EventTarget" ]; + "PerformanceMark" = [ "PerformanceEntry" ]; + "PerformanceMeasure" = [ "PerformanceEntry" ]; + "PerformanceNavigationTiming" = [ "PerformanceEntry" "PerformanceResourceTiming" ]; + "PerformanceResourceTiming" = [ "PerformanceEntry" ]; + "PermissionStatus" = [ "EventTarget" ]; + "PointerEvent" = [ "Event" "MouseEvent" "UiEvent" ]; + "PopStateEvent" = [ "Event" ]; + "PopupBlockedEvent" = [ "Event" ]; + "PresentationAvailability" = [ "EventTarget" ]; + "PresentationConnection" = [ "EventTarget" ]; + "PresentationConnectionAvailableEvent" = [ "Event" ]; + "PresentationConnectionCloseEvent" = [ "Event" ]; + "PresentationConnectionList" = [ "EventTarget" ]; + "PresentationRequest" = [ "EventTarget" ]; + "ProcessingInstruction" = [ "CharacterData" "EventTarget" "Node" ]; + "ProgressEvent" = [ "Event" ]; + "PromiseRejectionEvent" = [ "Event" ]; + "PublicKeyCredential" = [ "Credential" ]; + "PushEvent" = [ "Event" "ExtendableEvent" ]; + "RadioNodeList" = [ "NodeList" ]; + "RtcDataChannel" = [ "EventTarget" ]; + "RtcDataChannelEvent" = [ "Event" ]; + "RtcPeerConnection" = [ "EventTarget" ]; + "RtcPeerConnectionIceErrorEvent" = [ "Event" ]; + "RtcPeerConnectionIceEvent" = [ "Event" ]; + "RtcTrackEvent" = [ "Event" ]; + "RtcdtmfSender" = [ "EventTarget" ]; + "RtcdtmfToneChangeEvent" = [ "Event" ]; + "Screen" = [ "EventTarget" ]; + "ScreenOrientation" = [ "EventTarget" ]; + "ScriptProcessorNode" = [ "AudioNode" "EventTarget" ]; + "ScrollAreaEvent" = [ "Event" "UiEvent" ]; + "SecurityPolicyViolationEvent" = [ "Event" ]; + "Serial" = [ "EventTarget" ]; + "SerialPort" = [ "EventTarget" ]; + "ServiceWorker" = [ "EventTarget" ]; + "ServiceWorkerContainer" = [ "EventTarget" ]; + "ServiceWorkerGlobalScope" = [ "EventTarget" "WorkerGlobalScope" ]; + "ServiceWorkerRegistration" = [ "EventTarget" ]; + "ShadowRoot" = [ "DocumentFragment" "EventTarget" "Node" ]; + "SharedWorker" = [ "EventTarget" ]; + "SharedWorkerGlobalScope" = [ "EventTarget" "WorkerGlobalScope" ]; + "SourceBuffer" = [ "EventTarget" ]; + "SourceBufferList" = [ "EventTarget" ]; + "SpeechRecognition" = [ "EventTarget" ]; + "SpeechRecognitionError" = [ "Event" ]; + "SpeechRecognitionEvent" = [ "Event" ]; + "SpeechSynthesis" = [ "EventTarget" ]; + "SpeechSynthesisErrorEvent" = [ "Event" "SpeechSynthesisEvent" ]; + "SpeechSynthesisEvent" = [ "Event" ]; + "SpeechSynthesisUtterance" = [ "EventTarget" ]; + "StereoPannerNode" = [ "AudioNode" "EventTarget" ]; + "StorageEvent" = [ "Event" ]; + "SubmitEvent" = [ "Event" ]; + "SvgAnimateElement" = [ "Element" "EventTarget" "Node" "SvgAnimationElement" "SvgElement" ]; + "SvgAnimateMotionElement" = [ "Element" "EventTarget" "Node" "SvgAnimationElement" "SvgElement" ]; + "SvgAnimateTransformElement" = [ "Element" "EventTarget" "Node" "SvgAnimationElement" "SvgElement" ]; + "SvgAnimationElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgCircleElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGeometryElement" "SvgGraphicsElement" ]; + "SvgClipPathElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgComponentTransferFunctionElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgDefsElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" ]; + "SvgDescElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgElement" = [ "Element" "EventTarget" "Node" ]; + "SvgEllipseElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGeometryElement" "SvgGraphicsElement" ]; + "SvgFilterElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgForeignObjectElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" ]; + "SvgGeometryElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" ]; + "SvgGradientElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgGraphicsElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgImageElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" ]; + "SvgLineElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGeometryElement" "SvgGraphicsElement" ]; + "SvgLinearGradientElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGradientElement" ]; + "SvgMarkerElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgMaskElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgMetadataElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgPathElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGeometryElement" "SvgGraphicsElement" ]; + "SvgPathSegArcAbs" = [ "SvgPathSeg" ]; + "SvgPathSegArcRel" = [ "SvgPathSeg" ]; + "SvgPathSegClosePath" = [ "SvgPathSeg" ]; + "SvgPathSegCurvetoCubicAbs" = [ "SvgPathSeg" ]; + "SvgPathSegCurvetoCubicRel" = [ "SvgPathSeg" ]; + "SvgPathSegCurvetoCubicSmoothAbs" = [ "SvgPathSeg" ]; + "SvgPathSegCurvetoCubicSmoothRel" = [ "SvgPathSeg" ]; + "SvgPathSegCurvetoQuadraticAbs" = [ "SvgPathSeg" ]; + "SvgPathSegCurvetoQuadraticRel" = [ "SvgPathSeg" ]; + "SvgPathSegCurvetoQuadraticSmoothAbs" = [ "SvgPathSeg" ]; + "SvgPathSegCurvetoQuadraticSmoothRel" = [ "SvgPathSeg" ]; + "SvgPathSegLinetoAbs" = [ "SvgPathSeg" ]; + "SvgPathSegLinetoHorizontalAbs" = [ "SvgPathSeg" ]; + "SvgPathSegLinetoHorizontalRel" = [ "SvgPathSeg" ]; + "SvgPathSegLinetoRel" = [ "SvgPathSeg" ]; + "SvgPathSegLinetoVerticalAbs" = [ "SvgPathSeg" ]; + "SvgPathSegLinetoVerticalRel" = [ "SvgPathSeg" ]; + "SvgPathSegMovetoAbs" = [ "SvgPathSeg" ]; + "SvgPathSegMovetoRel" = [ "SvgPathSeg" ]; + "SvgPatternElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgPolygonElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGeometryElement" "SvgGraphicsElement" ]; + "SvgPolylineElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGeometryElement" "SvgGraphicsElement" ]; + "SvgRadialGradientElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGradientElement" ]; + "SvgRectElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGeometryElement" "SvgGraphicsElement" ]; + "SvgScriptElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgSetElement" = [ "Element" "EventTarget" "Node" "SvgAnimationElement" "SvgElement" ]; + "SvgStopElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgStyleElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgSwitchElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" ]; + "SvgSymbolElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgTextContentElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" ]; + "SvgTextElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" "SvgTextContentElement" "SvgTextPositioningElement" ]; + "SvgTextPathElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" "SvgTextContentElement" ]; + "SvgTextPositioningElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" "SvgTextContentElement" ]; + "SvgTitleElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgUseElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" ]; + "SvgViewElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgaElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" ]; + "SvgfeBlendElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeColorMatrixElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeComponentTransferElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeCompositeElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeConvolveMatrixElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeDiffuseLightingElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeDisplacementMapElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeDistantLightElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeDropShadowElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeFloodElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeFuncAElement" = [ "Element" "EventTarget" "Node" "SvgComponentTransferFunctionElement" "SvgElement" ]; + "SvgfeFuncBElement" = [ "Element" "EventTarget" "Node" "SvgComponentTransferFunctionElement" "SvgElement" ]; + "SvgfeFuncGElement" = [ "Element" "EventTarget" "Node" "SvgComponentTransferFunctionElement" "SvgElement" ]; + "SvgfeFuncRElement" = [ "Element" "EventTarget" "Node" "SvgComponentTransferFunctionElement" "SvgElement" ]; + "SvgfeGaussianBlurElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeImageElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeMergeElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeMergeNodeElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeMorphologyElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeOffsetElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfePointLightElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeSpecularLightingElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeSpotLightElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeTileElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgfeTurbulenceElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvggElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" ]; + "SvgmPathElement" = [ "Element" "EventTarget" "Node" "SvgElement" ]; + "SvgsvgElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" ]; + "SvgtSpanElement" = [ "Element" "EventTarget" "Node" "SvgElement" "SvgGraphicsElement" "SvgTextContentElement" "SvgTextPositioningElement" ]; + "TaskController" = [ "AbortController" ]; + "TaskPriorityChangeEvent" = [ "Event" ]; + "TaskSignal" = [ "AbortSignal" "EventTarget" ]; + "TcpServerSocket" = [ "EventTarget" ]; + "TcpServerSocketEvent" = [ "Event" ]; + "TcpSocket" = [ "EventTarget" ]; + "TcpSocketErrorEvent" = [ "Event" ]; + "TcpSocketEvent" = [ "Event" ]; + "Text" = [ "CharacterData" "EventTarget" "Node" ]; + "TextTrack" = [ "EventTarget" ]; + "TextTrackCue" = [ "EventTarget" ]; + "TextTrackList" = [ "EventTarget" ]; + "TimeEvent" = [ "Event" ]; + "TouchEvent" = [ "Event" "UiEvent" ]; + "TrackEvent" = [ "Event" ]; + "TransitionEvent" = [ "Event" ]; + "UiEvent" = [ "Event" ]; + "Usb" = [ "EventTarget" ]; + "UsbConnectionEvent" = [ "Event" ]; + "UsbPermissionResult" = [ "EventTarget" "PermissionStatus" ]; + "UserProximityEvent" = [ "Event" ]; + "ValueEvent" = [ "Event" ]; + "VideoStreamTrack" = [ "EventTarget" "MediaStreamTrack" ]; + "VideoTrackList" = [ "EventTarget" ]; + "VrDisplay" = [ "EventTarget" ]; + "VttCue" = [ "EventTarget" "TextTrackCue" ]; + "WakeLockSentinel" = [ "EventTarget" ]; + "WaveShaperNode" = [ "AudioNode" "EventTarget" ]; + "WebGlContextEvent" = [ "Event" ]; + "WebKitCssMatrix" = [ "DomMatrix" "DomMatrixReadOnly" ]; + "WebSocket" = [ "EventTarget" ]; + "WebTransportError" = [ "DomException" ]; + "WebTransportReceiveStream" = [ "ReadableStream" ]; + "WebTransportSendStream" = [ "WritableStream" ]; + "WheelEvent" = [ "Event" "MouseEvent" "UiEvent" ]; + "Window" = [ "EventTarget" ]; + "WindowClient" = [ "Client" ]; + "Worker" = [ "EventTarget" ]; + "WorkerDebuggerGlobalScope" = [ "EventTarget" ]; + "WorkerGlobalScope" = [ "EventTarget" ]; + "XmlDocument" = [ "Document" "EventTarget" "Node" ]; + "XmlHttpRequest" = [ "EventTarget" "XmlHttpRequestEventTarget" ]; + "XmlHttpRequestEventTarget" = [ "EventTarget" ]; + "XmlHttpRequestUpload" = [ "EventTarget" "XmlHttpRequestEventTarget" ]; + "XrBoundedReferenceSpace" = [ "EventTarget" "XrReferenceSpace" "XrSpace" ]; + "XrInputSourceEvent" = [ "Event" ]; + "XrInputSourcesChangeEvent" = [ "Event" ]; + "XrJointPose" = [ "XrPose" ]; + "XrJointSpace" = [ "EventTarget" "XrSpace" ]; + "XrLayer" = [ "EventTarget" ]; + "XrPermissionStatus" = [ "EventTarget" "PermissionStatus" ]; + "XrReferenceSpace" = [ "EventTarget" "XrSpace" ]; + "XrReferenceSpaceEvent" = [ "Event" ]; + "XrSession" = [ "EventTarget" ]; + "XrSessionEvent" = [ "Event" ]; + "XrSpace" = [ "EventTarget" ]; + "XrSystem" = [ "EventTarget" ]; + "XrViewerPose" = [ "XrPose" ]; + "XrWebGlLayer" = [ "EventTarget" "XrLayer" ]; + }; + resolvedDefaultFeatures = [ "AbortSignal" "AddEventListenerOptions" "AnimationEvent" "BinaryType" "Blob" "BlobPropertyBag" "CharacterData" "CloseEvent" "CloseEventInit" "DedicatedWorkerGlobalScope" "Document" "DocumentFragment" "DomException" "DragEvent" "Element" "ErrorEvent" "Event" "EventInit" "EventSource" "EventTarget" "File" "FileList" "FilePropertyBag" "FileReader" "FocusEvent" "FormData" "Headers" "History" "HtmlBaseElement" "HtmlCollection" "HtmlDetailsElement" "HtmlElement" "HtmlHeadElement" "HtmlInputElement" "HtmlScriptElement" "HtmlTextAreaElement" "InputEvent" "InputEventInit" "KeyboardEvent" "Location" "MessageEvent" "MouseEvent" "Node" "NodeList" "ObserverCallback" "PointerEvent" "ProgressEvent" "ReadableStream" "ReferrerPolicy" "Request" "RequestCache" "RequestCredentials" "RequestInit" "RequestMode" "RequestRedirect" "Response" "ResponseInit" "ResponseType" "ShadowRoot" "Storage" "SubmitEvent" "Text" "TouchEvent" "TransitionEvent" "UiEvent" "Url" "UrlSearchParams" "WebSocket" "WheelEvent" "Window" "Worker" "WorkerGlobalScope" "WorkerOptions" "console" ]; + }; + "winapi" = rec { + crateName = "winapi"; + version = "0.3.9"; + edition = "2015"; + sha256 = "06gl025x418lchw1wxj64ycr7gha83m44cjr5sarhynd9xkrm0sw"; + authors = [ + "Peter Atashian <retep998@gmail.com>" + ]; + dependencies = [ + { + name = "winapi-i686-pc-windows-gnu"; + packageId = "winapi-i686-pc-windows-gnu"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnu"); + } + { + name = "winapi-x86_64-pc-windows-gnu"; + packageId = "winapi-x86_64-pc-windows-gnu"; + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnu"); + } + ]; + features = { + "debug" = [ "impl-debug" ]; + }; + resolvedDefaultFeatures = [ "consoleapi" "errhandlingapi" "fileapi" "knownfolders" "minwindef" "objbase" "processenv" "shlobj" "std" "sysinfoapi" "winbase" "wincon" "winerror" "winnt" ]; + }; + "winapi-i686-pc-windows-gnu" = rec { + crateName = "winapi-i686-pc-windows-gnu"; + version = "0.4.0"; + edition = "2015"; + sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; + authors = [ + "Peter Atashian <retep998@gmail.com>" + ]; + + }; + "winapi-util" = rec { + crateName = "winapi-util"; + version = "0.1.6"; + edition = "2021"; + sha256 = "15i5lm39wd44004i9d5qspry2cynkrpvwzghr6s2c3dsk28nz7pj"; + libName = "winapi_util"; + authors = [ + "Andrew Gallant <jamslam@gmail.com>" + ]; + dependencies = [ + { + name = "winapi"; + packageId = "winapi"; + target = { target, features }: (target."windows" or false); + features = [ "std" "consoleapi" "errhandlingapi" "fileapi" "minwindef" "processenv" "sysinfoapi" "winbase" "wincon" "winerror" "winnt" ]; + } + ]; + + }; + "winapi-x86_64-pc-windows-gnu" = rec { + crateName = "winapi-x86_64-pc-windows-gnu"; + version = "0.4.0"; + edition = "2015"; + sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; + authors = [ + "Peter Atashian <retep998@gmail.com>" + ]; + + }; + "winnow" = rec { + crateName = "winnow"; + version = "0.5.40"; + edition = "2021"; + sha256 = "0xk8maai7gyxda673mmw3pj1hdizy5fpi7287vaywykkk19sk4zm"; + dependencies = [ + { + name = "memchr"; + packageId = "memchr"; + optional = true; + usesDefaultFeatures = false; + } + ]; + features = { + "debug" = [ "dep:anstream" "dep:anstyle" "dep:is-terminal" "dep:terminal_size" ]; + "default" = [ "std" ]; + "simd" = [ "dep:memchr" ]; + "std" = [ "alloc" "memchr?/std" ]; + "unstable-doc" = [ "alloc" "std" "simd" "unstable-recover" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + }; + "yew" = rec { + crateName = "yew"; + version = "0.21.0"; + edition = "2021"; + sha256 = "1b0ccqqlyyhcrk0l6d8jch2xwbhl5wliabn6x6ipl367apr066jz"; + authors = [ + "Denis Kolodin <deniskolodin@gmail.com>" + "Justin Starry <justin@yew.rs>" + ]; + dependencies = [ + { + name = "console_error_panic_hook"; + packageId = "console_error_panic_hook"; + } + { + name = "futures"; + packageId = "futures"; + usesDefaultFeatures = false; + features = [ "std" ]; + } + { + name = "gloo"; + packageId = "gloo 0.10.0"; + } + { + name = "implicit-clone"; + packageId = "implicit-clone"; + features = [ "map" ]; + } + { + name = "indexmap"; + packageId = "indexmap 2.2.6"; + features = [ "std" ]; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "prokio"; + packageId = "prokio"; + } + { + name = "rustversion"; + packageId = "rustversion"; + } + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "slab"; + packageId = "slab"; + } + { + name = "thiserror"; + packageId = "thiserror"; + } + { + name = "tokio"; + packageId = "tokio"; + target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "rt" ]; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "wasm-bindgen-futures"; + packageId = "wasm-bindgen-futures"; + target = { target, features }: ("wasm32" == target."arch" or null); + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "AnimationEvent" "Document" "DragEvent" "Element" "ErrorEvent" "Event" "EventInit" "EventTarget" "FocusEvent" "HtmlElement" "HtmlInputElement" "HtmlCollection" "HtmlTextAreaElement" "InputEvent" "InputEventInit" "KeyboardEvent" "Location" "MouseEvent" "Node" "NodeList" "PointerEvent" "ProgressEvent" "ShadowRoot" "Text" "TouchEvent" "TransitionEvent" "UiEvent" "WheelEvent" "Window" "HtmlScriptElement" "SubmitEvent" ]; + } + { + name = "yew-macro"; + packageId = "yew-macro"; + } + ]; + devDependencies = [ + { + name = "gloo"; + packageId = "gloo 0.10.0"; + features = [ "futures" ]; + } + { + name = "tokio"; + packageId = "tokio"; + target = { target, features }: (!("wasm32" == target."arch" or null)); + features = [ "full" ]; + } + { + name = "wasm-bindgen-futures"; + packageId = "wasm-bindgen-futures"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "ShadowRootInit" "ShadowRootMode" "HtmlButtonElement" ]; + } + ]; + features = { + "hydration" = [ "csr" "dep:bincode" ]; + "ssr" = [ "dep:html-escape" "dep:base64ct" "dep:bincode" ]; + }; + resolvedDefaultFeatures = [ "csr" "default" ]; + }; + "yew-macro" = rec { + crateName = "yew-macro"; + version = "0.21.0"; + edition = "2021"; + sha256 = "1qix6k8f8gzxb750icxvxknm3xrg8g7a4035g6gyasbd2sjqrz82"; + procMacro = true; + libName = "yew_macro"; + authors = [ + "Justin Starry <justin@yew.rs>" + ]; + dependencies = [ + { + name = "boolinator"; + packageId = "boolinator"; + } + { + name = "once_cell"; + packageId = "once_cell"; + } + { + name = "prettyplease"; + packageId = "prettyplease"; + } + { + name = "proc-macro-error"; + packageId = "proc-macro-error"; + } + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + features = [ "full" "extra-traits" "visit-mut" ]; + } + ]; + + }; + "yew-router" = rec { + crateName = "yew-router"; + version = "0.18.0"; + edition = "2021"; + sha256 = "1ip071apn35gbycpki768ba5hxsrxnnsh2b29lmpdrln5h2xb8ac"; + libName = "yew_router"; + authors = [ + "Hamza <muhammadhamza1311@gmail.com>" + ]; + dependencies = [ + { + name = "gloo"; + packageId = "gloo 0.10.0"; + features = [ "futures" ]; + } + { + name = "js-sys"; + packageId = "js-sys"; + } + { + name = "route-recognizer"; + packageId = "route-recognizer"; + } + { + name = "serde"; + packageId = "serde"; + } + { + name = "serde_urlencoded"; + packageId = "serde_urlencoded"; + } + { + name = "tracing"; + packageId = "tracing"; + } + { + name = "urlencoding"; + packageId = "urlencoding"; + } + { + name = "wasm-bindgen"; + packageId = "wasm-bindgen"; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "Document" "HtmlBaseElement" "Window" ]; + } + { + name = "yew"; + packageId = "yew"; + usesDefaultFeatures = false; + } + { + name = "yew-router-macro"; + packageId = "yew-router-macro"; + } + ]; + devDependencies = [ + { + name = "serde"; + packageId = "serde"; + features = [ "derive" ]; + } + { + name = "web-sys"; + packageId = "web-sys"; + features = [ "HtmlHeadElement" ]; + } + { + name = "yew"; + packageId = "yew"; + features = [ "csr" ]; + } + ]; + + }; + "yew-router-macro" = rec { + crateName = "yew-router-macro"; + version = "0.18.0"; + edition = "2021"; + sha256 = "134pcmiyi5x6v8s8rnr3fg03v033qhx2piflgkgcza3wl28d3gs2"; + procMacro = true; + libName = "yew_router_macro"; + authors = [ + "Hamza <muhammadhamza1311@gmail.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.68"; + features = [ "full" "extra-traits" ]; + } + ]; + + }; + }; + + # + # crate2nix/default.nix (excerpt start) + # + + /* Target (platform) data for conditional dependencies. + This corresponds roughly to what buildRustCrate is setting. + */ + makeDefaultTarget = platform: { + unix = platform.isUnix; + windows = platform.isWindows; + fuchsia = true; + test = false; + + inherit (platform.rust.platform) + arch + os + vendor; + family = platform.rust.platform.target-family; + env = "gnu"; + endian = + if platform.parsed.cpu.significantByte.name == "littleEndian" + then "little" else "big"; + pointer_width = toString platform.parsed.cpu.bits; + debug_assertions = false; + }; + + /* Filters common temp files and build files. */ + # TODO(pkolloch): Substitute with gitignore filter + sourceFilter = name: type: + let + baseName = builtins.baseNameOf (builtins.toString name); + in + ! ( + # Filter out git + baseName == ".gitignore" + || (type == "directory" && baseName == ".git") + + # Filter out build results + || ( + type == "directory" && ( + baseName == "target" + || baseName == "_site" + || baseName == ".sass-cache" + || baseName == ".jekyll-metadata" + || baseName == "build-artifacts" + ) + ) + + # Filter out nix-build result symlinks + || ( + type == "symlink" && lib.hasPrefix "result" baseName + ) + + # Filter out IDE config + || ( + type == "directory" && ( + baseName == ".idea" || baseName == ".vscode" + ) + ) || lib.hasSuffix ".iml" baseName + + # Filter out nix build files + || baseName == "Cargo.nix" + + # Filter out editor backup / swap files. + || lib.hasSuffix "~" baseName + || builtins.match "^\\.sw[a-z]$$" baseName != null + || builtins.match "^\\..*\\.sw[a-z]$$" baseName != null + || lib.hasSuffix ".tmp" baseName + || lib.hasSuffix ".bak" baseName + || baseName == "tests.nix" + ); + + /* Returns a crate which depends on successful test execution + of crate given as the second argument. + + testCrateFlags: list of flags to pass to the test exectuable + testInputs: list of packages that should be available during test execution + */ + crateWithTest = { crate, testCrate, testCrateFlags, testInputs, testPreRun, testPostRun }: + assert builtins.typeOf testCrateFlags == "list"; + assert builtins.typeOf testInputs == "list"; + assert builtins.typeOf testPreRun == "string"; + assert builtins.typeOf testPostRun == "string"; + let + # override the `crate` so that it will build and execute tests instead of + # building the actual lib and bin targets We just have to pass `--test` + # to rustc and it will do the right thing. We execute the tests and copy + # their log and the test executables to $out for later inspection. + test = + let + drv = testCrate.override + ( + _: { + buildTests = true; + release = false; + } + ); + # If the user hasn't set any pre/post commands, we don't want to + # insert empty lines. This means that any existing users of crate2nix + # don't get a spurious rebuild unless they set these explicitly. + testCommand = pkgs.lib.concatStringsSep "\n" + (pkgs.lib.filter (s: s != "") [ + testPreRun + "$f $testCrateFlags 2>&1 | tee -a $out" + testPostRun + ]); + in + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; + + inherit (crate) src; + + inherit testCrateFlags; + + buildInputs = testInputs; + + buildPhase = '' + set -e + export RUST_BACKTRACE=1 + + # build outputs + testRoot=target/debug + mkdir -p $testRoot + + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . + + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; + in + pkgs.runCommand "${crate.name}-linked" + { + inherit (crate) outputs crateName; + passthru = (crate.passthru or { }) // { + inherit test; + }; + } + (lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) '' + echo tested by ${test} + '' + '' + ${lib.concatMapStringsSep "\n" (output: "ln -s ${crate.${output}} ${"$"}${output}") crate.outputs} + ''); + + /* A restricted overridable version of builtRustCratesWithFeatures. */ + buildRustCrateWithFeatures = + { packageId + , features ? rootFeatures + , crateOverrides ? defaultCrateOverrides + , buildRustCrateForPkgsFunc ? null + , runTests ? false + , testCrateFlags ? [ ] + , testInputs ? [ ] + # Any command to run immediatelly before a test is executed. + , testPreRun ? "" + # Any command run immediatelly after a test is executed. + , testPostRun ? "" + }: + lib.makeOverridable + ( + { features + , crateOverrides + , runTests + , testCrateFlags + , testInputs + , testPreRun + , testPostRun + }: + let + buildRustCrateForPkgsFuncOverriden = + if buildRustCrateForPkgsFunc != null + then buildRustCrateForPkgsFunc + else + ( + if crateOverrides == pkgs.defaultCrateOverrides + then buildRustCrateForPkgs + else + pkgs: (buildRustCrateForPkgs pkgs).override { + defaultCrateOverrides = crateOverrides; + } + ); + builtRustCrates = builtRustCratesWithFeatures { + inherit packageId features; + buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; + runTests = false; + }; + builtTestRustCrates = builtRustCratesWithFeatures { + inherit packageId features; + buildRustCrateForPkgsFunc = buildRustCrateForPkgsFuncOverriden; + runTests = true; + }; + drv = builtRustCrates.crates.${packageId}; + testDrv = builtTestRustCrates.crates.${packageId}; + derivation = + if runTests then + crateWithTest + { + crate = drv; + testCrate = testDrv; + inherit testCrateFlags testInputs testPreRun testPostRun; + } + else drv; + in + derivation + ) + { inherit features crateOverrides runTests testCrateFlags testInputs testPreRun testPostRun; }; + + /* Returns an attr set with packageId mapped to the result of buildRustCrateForPkgsFunc + for the corresponding crate. + */ + builtRustCratesWithFeatures = + { packageId + , features + , crateConfigs ? crates + , buildRustCrateForPkgsFunc + , runTests + , makeTarget ? makeDefaultTarget + } @ args: + assert (builtins.isAttrs crateConfigs); + assert (builtins.isString packageId); + assert (builtins.isList features); + assert (builtins.isAttrs (makeTarget stdenv.hostPlatform)); + assert (builtins.isBool runTests); + let + rootPackageId = packageId; + mergedFeatures = mergePackageFeatures + ( + args // { + inherit rootPackageId; + target = makeTarget stdenv.hostPlatform // { test = runTests; }; + } + ); + # Memoize built packages so that reappearing packages are only built once. + builtByPackageIdByPkgs = mkBuiltByPackageIdByPkgs pkgs; + mkBuiltByPackageIdByPkgs = pkgs: + let + self = { + crates = lib.mapAttrs (packageId: value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs; + target = makeTarget stdenv.hostPlatform; + build = mkBuiltByPackageIdByPkgs pkgs.buildPackages; + }; + in + self; + buildByPackageIdForPkgsImpl = self: pkgs: packageId: + let + features = mergedFeatures."${packageId}" or [ ]; + crateConfig' = crateConfigs."${packageId}"; + crateConfig = + builtins.removeAttrs crateConfig' [ "resolvedDefaultFeatures" "devDependencies" ]; + devDependencies = + lib.optionals + (runTests && packageId == rootPackageId) + (crateConfig'.devDependencies or [ ]); + dependencies = + dependencyDerivations { + inherit features; + inherit (self) target; + buildByPackageId = depPackageId: + # proc_macro crates must be compiled for the build architecture + if crateConfigs.${depPackageId}.procMacro or false + then self.build.crates.${depPackageId} + else self.crates.${depPackageId}; + dependencies = + (crateConfig.dependencies or [ ]) + ++ devDependencies; + }; + buildDependencies = + dependencyDerivations { + inherit features; + inherit (self.build) target; + buildByPackageId = depPackageId: + self.build.crates.${depPackageId}; + dependencies = crateConfig.buildDependencies or [ ]; + }; + dependenciesWithRenames = + let + buildDeps = filterEnabledDependencies { + inherit features; + inherit (self) target; + dependencies = crateConfig.dependencies or [ ] ++ devDependencies; + }; + hostDeps = filterEnabledDependencies { + inherit features; + inherit (self.build) target; + dependencies = crateConfig.buildDependencies or [ ]; + }; + in + lib.filter (d: d ? "rename") (hostDeps ++ buildDeps); + # Crate renames have the form: + # + # { + # crate_name = [ + # { version = "1.2.3"; rename = "crate_name01"; } + # ]; + # # ... + # } + crateRenames = + let + grouped = + lib.groupBy + (dependency: dependency.name) + dependenciesWithRenames; + versionAndRename = dep: + let + package = crateConfigs."${dep.packageId}"; + in + { inherit (dep) rename; inherit (package) version; }; + in + lib.mapAttrs (name: builtins.map versionAndRename) grouped; + in + buildRustCrateForPkgsFunc pkgs + ( + crateConfig // { + src = crateConfig.src or ( + pkgs.fetchurl rec { + name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz"; + # https://www.pietroalbini.org/blog/downloading-crates-io/ + # Not rate-limited, CDN URL. + url = "https://static.crates.io/crates/${crateConfig.crateName}/${crateConfig.crateName}-${crateConfig.version}.crate"; + sha256 = + assert (lib.assertMsg (crateConfig ? sha256) "Missing sha256 for ${name}"); + crateConfig.sha256; + } + ); + extraRustcOpts = lib.lists.optional (targetFeatures != [ ]) "-C target-feature=${lib.concatMapStringsSep "," (x: "+${x}") targetFeatures}"; + inherit features dependencies buildDependencies crateRenames release; + } + ); + in + builtByPackageIdByPkgs; + + /* Returns the actual derivations for the given dependencies. */ + dependencyDerivations = + { buildByPackageId + , features + , dependencies + , target + }: + assert (builtins.isList features); + assert (builtins.isList dependencies); + assert (builtins.isAttrs target); + let + enabledDependencies = filterEnabledDependencies { + inherit dependencies features target; + }; + depDerivation = dependency: buildByPackageId dependency.packageId; + in + map depDerivation enabledDependencies; + + /* Returns a sanitized version of val with all values substituted that cannot + be serialized as JSON. + */ + sanitizeForJson = val: + if builtins.isAttrs val + then lib.mapAttrs (n: sanitizeForJson) val + else if builtins.isList val + then builtins.map sanitizeForJson val + else if builtins.isFunction val + then "function" + else val; + + /* Returns various tools to debug a crate. */ + debugCrate = { packageId, target ? makeDefaultTarget stdenv.hostPlatform }: + assert (builtins.isString packageId); + let + debug = rec { + # The built tree as passed to buildRustCrate. + buildTree = buildRustCrateWithFeatures { + buildRustCrateForPkgsFunc = _: lib.id; + inherit packageId; + }; + sanitizedBuildTree = sanitizeForJson buildTree; + dependencyTree = sanitizeForJson + ( + buildRustCrateWithFeatures { + buildRustCrateForPkgsFunc = _: crate: { + "01_crateName" = crate.crateName or false; + "02_features" = crate.features or [ ]; + "03_dependencies" = crate.dependencies or [ ]; + }; + inherit packageId; + } + ); + mergedPackageFeatures = mergePackageFeatures { + features = rootFeatures; + inherit packageId target; + }; + diffedDefaultPackageFeatures = diffDefaultPackageFeatures { + inherit packageId target; + }; + }; + in + { internal = debug; }; + + /* Returns differences between cargo default features and crate2nix default + features. + + This is useful for verifying the feature resolution in crate2nix. + */ + diffDefaultPackageFeatures = + { crateConfigs ? crates + , packageId + , target + }: + assert (builtins.isAttrs crateConfigs); + let + prefixValues = prefix: lib.mapAttrs (n: v: { "${prefix}" = v; }); + mergedFeatures = + prefixValues + "crate2nix" + (mergePackageFeatures { inherit crateConfigs packageId target; features = [ "default" ]; }); + configs = prefixValues "cargo" crateConfigs; + combined = lib.foldAttrs (a: b: a // b) { } [ mergedFeatures configs ]; + onlyInCargo = + builtins.attrNames + (lib.filterAttrs (n: v: !(v ? "crate2nix") && (v ? "cargo")) combined); + onlyInCrate2Nix = + builtins.attrNames + (lib.filterAttrs (n: v: (v ? "crate2nix") && !(v ? "cargo")) combined); + differentFeatures = lib.filterAttrs + ( + n: v: + (v ? "crate2nix") + && (v ? "cargo") + && (v.crate2nix.features or [ ]) != (v."cargo".resolved_default_features or [ ]) + ) + combined; + in + builtins.toJSON { + inherit onlyInCargo onlyInCrate2Nix differentFeatures; + }; + + /* Returns an attrset mapping packageId to the list of enabled features. + + If multiple paths to a dependency enable different features, the + corresponding feature sets are merged. Features in rust are additive. + */ + mergePackageFeatures = + { crateConfigs ? crates + , packageId + , rootPackageId ? packageId + , features ? rootFeatures + , dependencyPath ? [ crates.${packageId}.crateName ] + , featuresByPackageId ? { } + , target + # Adds devDependencies to the crate with rootPackageId. + , runTests ? false + , ... + } @ args: + assert (builtins.isAttrs crateConfigs); + assert (builtins.isString packageId); + assert (builtins.isString rootPackageId); + assert (builtins.isList features); + assert (builtins.isList dependencyPath); + assert (builtins.isAttrs featuresByPackageId); + assert (builtins.isAttrs target); + assert (builtins.isBool runTests); + let + crateConfig = crateConfigs."${packageId}" or (builtins.throw "Package not found: ${packageId}"); + expandedFeatures = expandFeatures (crateConfig.features or { }) features; + enabledFeatures = enableFeatures (crateConfig.dependencies or [ ]) expandedFeatures; + depWithResolvedFeatures = dependency: + let + inherit (dependency) packageId; + features = dependencyFeatures enabledFeatures dependency; + in + { inherit packageId features; }; + resolveDependencies = cache: path: dependencies: + assert (builtins.isAttrs cache); + assert (builtins.isList dependencies); + let + enabledDependencies = filterEnabledDependencies { + inherit dependencies target; + features = enabledFeatures; + }; + directDependencies = map depWithResolvedFeatures enabledDependencies; + foldOverCache = op: lib.foldl op cache directDependencies; + in + foldOverCache + ( + cache: { packageId, features }: + let + cacheFeatures = cache.${packageId} or [ ]; + combinedFeatures = sortedUnique (cacheFeatures ++ features); + in + if cache ? ${packageId} && cache.${packageId} == combinedFeatures + then cache + else + mergePackageFeatures { + features = combinedFeatures; + featuresByPackageId = cache; + inherit crateConfigs packageId target runTests rootPackageId; + } + ); + cacheWithSelf = + let + cacheFeatures = featuresByPackageId.${packageId} or [ ]; + combinedFeatures = sortedUnique (cacheFeatures ++ enabledFeatures); + in + featuresByPackageId // { + "${packageId}" = combinedFeatures; + }; + cacheWithDependencies = + resolveDependencies cacheWithSelf "dep" + ( + crateConfig.dependencies or [ ] + ++ lib.optionals + (runTests && packageId == rootPackageId) + (crateConfig.devDependencies or [ ]) + ); + cacheWithAll = + resolveDependencies + cacheWithDependencies "build" + (crateConfig.buildDependencies or [ ]); + in + cacheWithAll; + + /* Returns the enabled dependencies given the enabled features. */ + filterEnabledDependencies = { dependencies, features, target }: + assert (builtins.isList dependencies); + assert (builtins.isList features); + assert (builtins.isAttrs target); + + lib.filter + ( + dep: + let + targetFunc = dep.target or (features: true); + in + targetFunc { inherit features target; } + && ( + !(dep.optional or false) + || builtins.any (doesFeatureEnableDependency dep) features + ) + ) + dependencies; + + /* Returns whether the given feature should enable the given dependency. */ + doesFeatureEnableDependency = dependency: feature: + let + name = dependency.rename or dependency.name; + prefix = "${name}/"; + len = builtins.stringLength prefix; + startsWithPrefix = builtins.substring 0 len feature == prefix; + in + feature == name || feature == "dep:" + name || startsWithPrefix; + + /* Returns the expanded features for the given inputFeatures by applying the + rules in featureMap. + + featureMap is an attribute set which maps feature names to lists of further + feature names to enable in case this feature is selected. + */ + expandFeatures = featureMap: inputFeatures: + assert (builtins.isAttrs featureMap); + assert (builtins.isList inputFeatures); + let + expandFeaturesNoCycle = oldSeen: inputFeatures: + if inputFeatures != [ ] + then + let + # The feature we're currently expanding. + feature = builtins.head inputFeatures; + # All the features we've seen/expanded so far, including the one + # we're currently processing. + seen = oldSeen // { ${feature} = 1; }; + # Expand the feature but be careful to not re-introduce a feature + # that we've already seen: this can easily cause a cycle, see issue + # #209. + enables = builtins.filter (f: !(seen ? "${f}")) (featureMap."${feature}" or [ ]); + in + [ feature ] ++ (expandFeaturesNoCycle seen (builtins.tail inputFeatures ++ enables)) + # No more features left, nothing to expand to. + else [ ]; + outFeatures = expandFeaturesNoCycle { } inputFeatures; + in + sortedUnique outFeatures; + + /* This function adds optional dependencies as features if they are enabled + indirectly by dependency features. This function mimics Cargo's behavior + described in a note at: + https://doc.rust-lang.org/nightly/cargo/reference/features.html#dependency-features + */ + enableFeatures = dependencies: features: + assert (builtins.isList features); + assert (builtins.isList dependencies); + let + additionalFeatures = lib.concatMap + ( + dependency: + assert (builtins.isAttrs dependency); + let + enabled = builtins.any (doesFeatureEnableDependency dependency) features; + in + if (dependency.optional or false) && enabled + then [ (dependency.rename or dependency.name) ] + else [ ] + ) + dependencies; + in + sortedUnique (features ++ additionalFeatures); + + /* + Returns the actual features for the given dependency. + + features: The features of the crate that refers this dependency. + */ + dependencyFeatures = features: dependency: + assert (builtins.isList features); + assert (builtins.isAttrs dependency); + let + defaultOrNil = + if dependency.usesDefaultFeatures or true + then [ "default" ] + else [ ]; + explicitFeatures = dependency.features or [ ]; + additionalDependencyFeatures = + let + name = dependency.rename or dependency.name; + stripPrefixMatch = prefix: s: + if lib.hasPrefix prefix s + then lib.removePrefix prefix s + else null; + extractFeature = feature: lib.findFirst + (f: f != null) + null + (map (prefix: stripPrefixMatch prefix feature) [ + (name + "/") + (name + "?/") + ]); + dependencyFeatures = lib.filter (f: f != null) (map extractFeature features); + in + dependencyFeatures; + in + defaultOrNil ++ explicitFeatures ++ additionalDependencyFeatures; + + /* Sorts and removes duplicates from a list of strings. */ + sortedUnique = features: + assert (builtins.isList features); + assert (builtins.all builtins.isString features); + let + outFeaturesSet = lib.foldl (set: feature: set // { "${feature}" = 1; }) { } features; + outFeaturesUnique = builtins.attrNames outFeaturesSet; + in + builtins.sort (a: b: a < b) outFeaturesUnique; + + deprecationWarning = message: value: + if strictDeprecation + then builtins.throw "strictDeprecation enabled, aborting: ${message}" + else builtins.trace message value; + + # + # crate2nix/default.nix (excerpt end) + # + }; +} + diff --git a/web/tvixbolt/Cargo.toml b/web/tvixbolt/Cargo.toml index ce5ffb90e3bd..992930717262 100644 --- a/web/tvixbolt/Cargo.toml +++ b/web/tvixbolt/Cargo.toml @@ -3,24 +3,13 @@ name = "tvixbolt" version = "0.1.0" edition = "2021" -[dependencies] -yew = "0.19.3" -yew-router = "0.16" -codemap = "0.1.3" -serde_urlencoded = "*" # pinned by yew -rnix = "0.11.0" - -# needs to be in sync with nixpkgs -wasm-bindgen = "= 0.2.91" - -[dependencies.tvix-eval] -path = "../../tvix/eval" -default-features = false +[lib] +crate-type = ["cdylib"] -[dependencies.serde] -version = "*" # pinned by yew -features = [ "derive" ] - -[dependencies.web-sys] -version = "*" # pinned by yew -features = [ "HtmlDetailsElement" ] +[dependencies] +yew = { version = "0.21.0", features = ["csr"] } +yew-router = "0.18" +tvix-eval = { path = "../../tvix/eval", default-features = false } +serde = { version = "1.0.204", features = ["derive"] } +web-sys = { version = "0.3.69", features = ["HtmlDetailsElement"] } +wasm-bindgen = "0.2.92" diff --git a/web/tvixbolt/default.nix b/web/tvixbolt/default.nix index 9b6baa582fb0..a3ce1662ff52 100644 --- a/web/tvixbolt/default.nix +++ b/web/tvixbolt/default.nix @@ -1,74 +1,32 @@ -{ depot, lib, pkgs, ... }: - +{ pkgs, lib, depot, ... }: let - wasmRust = pkgs.rust-bin.stable.latest.default.override { - targets = [ "wasm32-unknown-unknown" ]; + pkgsCross = pkgs.pkgsCross.wasm32-unknown-none; +in +(pkgsCross.callPackage ./Cargo.nix { + defaultCrateOverrides = (depot.tvix.utils.defaultCrateOverridesForPkgs pkgsCross) // { + tvixbolt = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; }; - - cargoToml = with builtins; fromTOML (readFile ./Cargo.toml); - - wasmBindgenMatch = - cargoToml.dependencies.wasm-bindgen == "= ${pkgs.wasm-bindgen-cli.version}"; - - assertWasmBindgen = assert (lib.assertMsg wasmBindgenMatch '' - Due to instability in the Rust WASM ecosystem, the trunk build - tool enforces that the Cargo-dependency version of `wasm-bindgen` - MUST match the version of the CLI supplied in the environment. - - This can get out of sync when nixpkgs is updated. To resolve it, - wasm-bindgen must be bumped in the Cargo.toml file and cargo needs - to be run to resolve the dependencies. - - Versions of `wasm-bindgen` in Cargo.toml: - - Expected: '= ${pkgs.wasm-bindgen-cli.version}' - Actual: '${cargoToml.dependencies.wasm-bindgen}' - ''); pkgs.wasm-bindgen-cli; - - deps = [ - pkgs.binaryen - pkgs.sass - pkgs.trunk - - wasmRust - assertWasmBindgen - ]; - - # Cargo.toml needs to be patched with the /nix/store source path of - # tvix-eval. - cargoTomlPatch = pkgs.writeText "tvix-eval-src.patch" '' - diff --git a/Cargo.toml b/Cargo.toml - index 75006bec18..6ca244bbb2 100644 - --- a/Cargo.toml - +++ b/Cargo.toml - @@ -16,7 +16,7 @@ rnix = "0.11.0" - wasm-bindgen = "= 0.2.83" - - [dependencies.tvix-eval] - -path = "../../tvix/eval" - +path = "${depot.tvix.crates.workspaceMembers.tvix-eval.build.src}" - default-features = false - - [dependencies.serde] +}).rootCrate.build.overrideAttrs (oldAttrs: { + installPhase = '' + ${lib.getExe pkgs.wasm-bindgen-cli} \ + --target web \ + --out-dir $out \ + --out-name ${oldAttrs.crateName} \ + --no-typescript \ + target/lib/${oldAttrs.crateName}-${oldAttrs.metadata}.wasm + + mv src/*.{html,css} $out ''; -in -pkgs.rustPlatform.buildRustPackage rec { - pname = "tvixbolt"; - version = "canon"; - src = lib.cleanSource ./.; - - cargoLock.lockFile = ./Cargo.lock; - - patches = [ - cargoTomlPatch - ]; - buildPhase = '' - export PATH=${lib.makeBinPath deps}:$PATH - mkdir home - export HOME=$PWD/home - trunk build --release -d $out + passthru.serve = pkgs.writeShellScriptBin "tvixbolt-serve" '' + ${lib.getExe pkgs.simple-http-server} \ + --index \ + --nocache \ + "$@" \ + ${depot.web.tvixbolt} ''; - dontInstall = true; -} + meta.ci.extraSteps.crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; +}) diff --git a/web/tvixbolt/index.html b/web/tvixbolt/index.html deleted file mode 100644 index 410eb4eae298..000000000000 --- a/web/tvixbolt/index.html +++ /dev/null @@ -1,11 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <link rel="stylesheet" - href="https://static.tvl.su/latest/terminal.min.css" /> - <link data-trunk rel="inline" href="index.css"> - <title>Tvixbolt</title> - </head> -</html> diff --git a/web/tvixbolt/index.css b/web/tvixbolt/src/index.css index 95bd7d098362..95bd7d098362 100644 --- a/web/tvixbolt/index.css +++ b/web/tvixbolt/src/index.css diff --git a/web/tvixbolt/src/index.html b/web/tvixbolt/src/index.html new file mode 100644 index 000000000000..a938c4f4ea5e --- /dev/null +++ b/web/tvixbolt/src/index.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> + <head> + <meta content="text/html;charset=utf-8" http-equiv="Content-Type"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel="stylesheet" href="https://static.tvl.su/latest/terminal.min.css"> + <link rel="stylesheet" href="index.css"> + <title>Tvixbolt</title> + </head> + <body> + <script type="module"> + import init, { main } from './tvixbolt.js'; + + async function run() { + await init(); + main(); + } + + run(); + </script> + </body> diff --git a/web/tvixbolt/src/main.rs b/web/tvixbolt/src/lib.rs index 2e68e03fb0ba..a2bfeb0a5dd1 100644 --- a/web/tvixbolt/src/main.rs +++ b/web/tvixbolt/src/lib.rs @@ -7,11 +7,13 @@ use std::fmt::Write; use serde::{Deserialize, Serialize}; use tvix_eval::observer::{DisassemblingObserver, TracingObserver}; +use wasm_bindgen::prelude::wasm_bindgen; use web_sys::HtmlDetailsElement; use web_sys::HtmlTextAreaElement; use yew::prelude::*; use yew::TargetCast; -use yew_router::{prelude::*, AnyRoute}; +use yew_router::history::BrowserHistory; +use yew_router::history::History; #[derive(Clone)] enum Msg { @@ -116,7 +118,7 @@ impl Component for Model { Msg::NoOp => {} } - let _ = BrowserHistory::new().replace_with_query(AnyRoute::new("/"), self.clone()); + let _ = BrowserHistory::new().replace_with_query("/", self.clone()); true } @@ -264,18 +266,19 @@ fn eval(model: &Model) -> Output { return out; } - let mut eval = tvix_eval::Evaluation::new_pure(); - let source = eval.source_map(); + let mut eval_builder = tvix_eval::Evaluation::builder_pure(); + let source = eval_builder.source_map().clone(); let result = { let mut compiler_observer = DisassemblingObserver::new(source.clone(), &mut out.bytecode); - eval.compiler_observer = Some(&mut compiler_observer); + eval_builder.set_compiler_observer(Some(&mut compiler_observer)); let mut runtime_observer = TracingObserver::new(&mut out.trace); if model.trace { - eval.runtime_observer = Some(&mut runtime_observer); + eval_builder.set_runtime_observer(Some(&mut runtime_observer)); } + let eval = eval_builder.build(); eval.evaluate(&model.code, Some("/nixbolt".into())) }; @@ -310,6 +313,7 @@ fn eval(model: &Model) -> Output { out } -fn main() { - yew::start_app::<Model>(); +#[wasm_bindgen] +pub fn main() { + yew::Renderer::<Model>::new().render(); } diff --git a/web/tvl/blog/2024-08-tvix-update.md b/web/tvl/blog/2024-08-tvix-update.md new file mode 100644 index 000000000000..5fc15c02d164 --- /dev/null +++ b/web/tvl/blog/2024-08-tvix-update.md @@ -0,0 +1,266 @@ +It's already been around half a year since +[the last Tvix update][2024-02-tvix-update], so time for another one! + +Note: This blog post is intended for a technical audience that is already +intimately familiar with Nix, and knows what things like derivations or store +paths are. If you're new to Nix, this will not make a lot of sense to you! + +## Builds +A long-term goal is obviously to be able to use the expressions in nixpkgs to +build things with Tvix. We made progress on many places towards that goal: + +### Drive builds on IO +As already explained in our [first blog post][blog-rewriting-nix], in Tvix, we +want to make IFD a first-class citizen without significant perf cost. + +Nix tries hard to split Evaluation and Building into two phases, visible in +the `nix-instantiate` command which produces `.drv` files in `/nix/store` and +the `nix-build` command which can be invoked on such `.drv` files without +evaluation. +Scheduling (like in Hydra) usually happens by walking the graph of `.drv` files +produced in the first phase. + +As soon as there's some IFD along the path, everything until then gets built in +the Evaluator (which is why IFD is prohibited in nixpkgs). + +Tvix does not have two separate "phases" in a build, only a graph of unfinished +Derivations/Builds and their associated store paths. This graph does not need +to be written to disk, and can grow during runtime, as new Derivations with new +output paths are discovered. + +Build scheduling happens continuously with that graph, for everything that's +really needed, when it's needed. + +We do this by only "forcing" the realization of a specific store path if the +user ultimately wants that specific result to be available on their system, and +transitively, if something else wants it. This includes IFD in a very elegant +way. + +We want to play with this approach as we continue on bringing our build +infrastructure up. + +### Fetchers +There's a few Nix builtins that allow describing a fetch (be it download of a +file from the internet, clone of a git repo). These needed to be implemented +for completeness. We implemented pretty much all downloads of Tarballs, NARs and +plain files, except git repositories, which are left for later. + +Instead of doing these fetches immediately, we added a generic `Fetch` type +that allows describing such fetches *before actually doing them*, similar to +being able to describe builds, and use the same "Drive builds on IO" machinery +to delay these fetches to the point where it's needed. We also show progress +bars when doing fetches. + +Very early, during bootstrapping, nixpkgs relies on some `builtin:fetchurl` +"fake" Derivation, which has some special handling logic in Nix. We implemented +these quirks, by converting it to instances of our `Fetch` type and dealing with +it there in a consistent fashion. + +### More fixes, Refscan +With the above work done, and after fixing some small bugs [^3], we were already +able to build some first few store paths with Tvix and our `runc`-based builder +🎉! + +We didn't get too far though, as we still need to implement reference scanning, +so that's next on our TODO list for here. Stay tuned for further updates there! + +## Eval correctness & Performance +As already written in the previous update, we've been evaluating parts of +`nixpkgs` and ensuring we produce the same derivations. We managed to find and +fix some correctness issues there. + +Even though we don't want to focus too much on performance improvements +until all features of Nix are properly understood and representable with our +architecture, there's been some work on removing some obvious and low-risk +performance bottlenecks. Expect a detailed blog post around that soon after +this one! + +## Tracing / O11Y Support +Tvix got support for Tracing, and is able to emit spans in +[OpenTelemetry][opentelemetry]-compatible format. + +This means, if the necessary tooling is set up to collect such spans [^1], it's +possible to see what's happening inside the different components of Tvix across +process (and machine) boundaries. + +Tvix now also propagates trace IDs via gRPC and HTTP requests [^2], and +continues them if receiving such ones. + +As an example, this allows us to get "callgraphs" on how a tvix-store operation +is processed through a multi-node deployment, and find bottlenecks and places to +optimize performance for. + +Currently, this is compiled in by default, trying to send traces to an endpoint +at `localhost` (as per the official [SDK defaults][otlp-sdk]). It can +be disabled by building without the `otlp` feature, or running with the +`--otlp=false` CLI flag. + +This piggy-backs on the excellent [tracing][tracing-rs] crate, which we already +use for structured logging, so while at it, we improved some log messages and +fields to make it easier to filter for certain types of events. + +We also added support for sending out [Tracy][tracy] traces, though these are +disabled by default. + +Additionally, some CLI entrypoints can now report progress to the user! +For example, when we're fetching something during evaluation +(via `builtins.fetchurl`), or uploading store path contents, we can report on +this. See [here][asciinema-import] for an example. + +We're still considering these outputs as early prototypes, and will refine them as +we go. + +## tvix-castore ingestion generalization +We spent some time refactoring and generalizing tvix-castore importer code. + +It's now generalized on a stream of "ingestion entries" produced in a certain +order, and there's various producers of this stream (reading through the local +filesystem, reading through a NAR, reading through a tarball, soon: traversing +contents of a git repo, …). + +This prevented a lot of code duplication for these various formats, and allows +pulling out helper code for concurrent blob uploading. + +## More tvix-[ca]store backends +We added some more store backends to Tvix: + + - There's a [redb][redb] `PathInfoService` and `DirectoryService`, which + also replaced the previous `sled` default backend. + - There's a [bigtable][bigtable] `PathInfoService` and `DirectoryService` + backend. + - The "simplefs" `BlobService` has been removed, as it can be expressed using + the "objectstore" backend with a `file://` URI. + - There's been some work on feature-flagging certain backends. + +## Documentation reconcilation +Various bits and pieces of documentation have previously been scattered +throughout the Tvix codebase, which wasn't very accessible and quite confusing. + +These have been consolidated into a mdbook (at `//tvix/docs`). + +We plan to properly host these as a website, hopefully providing a better introduction +and overview of Tvix, while adding more content over time. + +## `nar-bridge` RIIR +While the golang implementation of `nar-bridge` did serve us well for a while, +it being the only remaining non-Rust part was a bit annoying. + +Adding some features there meant they would not be accessible in the rest of +Tvix - and the other way round. +Also, we could not open data stores directly from there, but always had to start +a separate `tvix-store daemon`. + +The initial plans for the Rust rewrite were already made quite a while ago, +but we finally managed to finish implementing the remaining bits. `nar-bridge` +is now fully written in Rust, providing the same CLI experience features and +store backends as the rest of Tvix. + +## `crate2nix` and overall rust Nix improvements +We landed some fixes in [crate2nix][crate2nix], the tool we're using to for +per-crate incremental builds of Tvix. + +It now supports the corner cases needed to build WASM - so now +[Tvixbolt][tvixbolt] is built with it, too. + +We also fixed some bugs in how test directories are prepared, which unlocked +running some more tests for filesystem related builtins such as `readDir` in our test suite. + +Additionally, there has been some general improvements around ensuring various +combinations of Tvix feature flags build (now continuously checked by CI), and +reducing the amount of unnecessary rebuilds, by filtering non-sourcecode files +before building. + +These should all improve DX while working on Tvix. + +## Store Composition +Another big missing feature that landed was Store Composition. We briefly spoke +about the Tvix Store Model in the last update, but we didn't go into too much +detail on how that'd work in case there's multiple potential sources for a store +path or some more granular contents (which is pretty much always the case +normally, think about using things from your local store OR then falling back to +a remote place). + +Nix has the default model of using `/nix/store` with a sqlite database for +metadata as a local store, and one or multiple "subsituters" using the Nix HTTP +Binary Cache protocol. + +In Tvix, things need to be a bit more flexible: + - You might be in a setting where you don't have a local `/nix/store` at all. + - You might want to have a view of different substituters/binary caches for + different users. + - You might want to explicitly specify caches in between some of these layers, + and control their config. + +The idea in Tvix is that you'll be able to combine "hierarchies of stores" through +runtime configuration to express all this. + +It's currently behind a `xp-store-composition` feature flag, which adds the +optional `--experimental-store-composition` CLI arg, pointing to a TOML file +specifying the composition configuration. If set, this has priority over the old +CLI args for the three (single) stores. + +We're still not 100% sure how to best expose this functionality, in terms of the +appropriate level of granularity, in a user-friendly format. + +There's also some more combinators and refactors missing, but please let us +know your thoughts! + +## Contributors +There's been a lot of progress, which would not have been possible without our +contributors! Be it a small drive-by contributions, or large efforts, thank +you all! + + - Adam Joseph + - Alice Carroll + - Aspen Smith + - Ben Webb + - binarycat + - Brian Olsen + - Connor Brewster + - Daniel Mendler + - edef + - Edwin Mackenzie-Owen + - espes + - Farid Zakaria + - Florian Klink + - Ilan Joselevich + - Luke Granger-Brown + - Markus Rudy + - Matthew Tromp + - Moritz Sanft + - Padraic-O-Mhuiris + - Peter Kolloch + - Picnoir + - Profpatsch + - Ryan Lahfa + - Simon Hauser + - sinavir + - sterni + - Steven Allen + - tcmal + - toastal + - Vincent Ambo + - Yureka + +--- + +That's it again, try out Tvix and hit us up on IRC or on our mailing list if you +run into any snags, or have any questions. + + +[^1]: Essentially, deploying a collecting agent on your machines, accepting + these traces. +[^2]: Using the `traceparent` header field from https://www.w3.org/TR/trace-context/#trace-context-http-headers-format +[^3]: like `builtins.toFile` not adding files yet, or `inputSources` being missed initially, duh!) + +[2024-02-tvix-update]: https://tvl.fyi/blog/tvix-update-february-24 +[opentelemetry]: https://opentelemetry.io/ +[otlp-sdk]: https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/ +[tracing-rs]: https://tracing.rs/ +[tracy]: https://github.com/wolfpld/tracy +[asciinema-import]: https://asciinema.org/a/Fs4gKTFFpPGYVSna0xjTPGaNp +[blog-rewriting-nix]: https://tvl.fyi/blog/rewriting-nix +[crate2nix]: https://github.com/nix-community/crate2nix +[redb]: https://github.com/cberner/redb +[bigtable]: https://cloud.google.com/bigtable +[tvixbolt]: https://bolt.tvix.dev/ diff --git a/web/tvl/blog/default.nix b/web/tvl/blog/default.nix index 2a1dfe85cc63..966be083b3d3 100644 --- a/web/tvl/blog/default.nix +++ b/web/tvl/blog/default.nix @@ -31,5 +31,12 @@ content = ./2024-02-tvix-update.md; author = "flokli"; } + { + key = "tvix-update-august-24"; + title = "Tvix Status - August '24"; + date = 1723219370; + content = ./2024-08-tvix-update.md; + author = "flokli"; + } ]; } diff --git a/web/tvl/tvl.dot b/web/tvl/tvl.dot index a4ced3d4738d..5a9efd2c0a21 100644 --- a/web/tvl/tvl.dot +++ b/web/tvl/tvl.dot @@ -27,7 +27,7 @@ digraph tvl { flokli [href="https://flokli.de/"]; fzakaria [href="https://fzakaria.com/"]; ghuntley [href="https://ghuntley.com/"]; - grfn [href="http://gws.fyi"]; + aspen [href="http://gws.fyi"]; implr [href="https://twitter.com/implring"]; isomer [href="https://www.lorier.net/"]; j4m3s [href="https://github.com/j4m3s-s"]; @@ -118,7 +118,7 @@ digraph tvl { fzakaria -> google; // random primary - grfn -> wpcarro; + aspen -> wpcarro; aurora -> eve; cynthia -> benjojo; eta -> unspecific; @@ -156,7 +156,7 @@ digraph tvl { lukegb -> benjojo; espes -> benjojo; espes -> aurora; - grfn -> nix; + aspen -> nix; edef -> nix; ezemtsov -> nix; raitobezarius -> nix; |