Merge commit '802db7e483c2b83175f9591be919d7ceb1eae7d7' into adr009/zset-ffi
# Conflicts: # Cargo.nix # Cargo.toml
This commit is contained in:
Generated
+100
-55
@@ -205,7 +205,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.6",
|
||||
"syn 3.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -243,9 +243,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.4.7"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54413ede23c2daf518f35156dfde027feb2374004d63bd497f983c8db9c0e313"
|
||||
checksum = "50a649af8a827553c29fb0cb4bd4a6f1a0dd695bd3232b9bc98bd9c8a3ffbb8b"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
@@ -319,7 +319,7 @@ dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.6",
|
||||
"syn 3.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -499,7 +499,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 3.0.6",
|
||||
"syn 3.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -510,7 +510,7 @@ checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 3.0.6",
|
||||
"syn 3.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -585,9 +585,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.18.0"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34"
|
||||
checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be"
|
||||
|
||||
[[package]]
|
||||
name = "enum_dispatch"
|
||||
@@ -655,9 +655,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.13"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef25905e51abafe4dcea6c15fec58c57b601cdbd0ee53d22ea1d3016c587d39b"
|
||||
checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484"
|
||||
|
||||
[[package]]
|
||||
name = "finl_unicode"
|
||||
@@ -952,6 +952,15 @@ dependencies = [
|
||||
"improvise-formula",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "improvise-incremental"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"improvise-core",
|
||||
"improvise-io",
|
||||
"proptest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "improvise-io"
|
||||
version = "0.1.0-rc2"
|
||||
@@ -1043,9 +1052,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indoc"
|
||||
version = "2.0.7"
|
||||
version = "2.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
|
||||
checksum = "a37b2691796cffeb8a8cd305ac66e65841559f147f4e63231d0eafa4db5384d1"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
@@ -1060,7 +1069,7 @@ dependencies = [
|
||||
"indoc",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.6",
|
||||
"syn 3.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1114,15 +1123,15 @@ checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.189"
|
||||
version = "0.2.190"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
||||
checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
@@ -1187,12 +1196,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mac_address"
|
||||
version = "1.1.8"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0aeb26bf5e836cc1c341c8106051b573f1766dfa05aa87f0b98be5e51b02303"
|
||||
checksum = "b367b50a9be9a5d3b5718c1da74e5d6b9c17647f89752ee2562a470cc3c4eb1a"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"winapi",
|
||||
"nix 0.30.1",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1234,9 +1243,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.2.3"
|
||||
version = "1.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8"
|
||||
checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
@@ -1249,6 +1258,18 @@ name = "nix"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
||||
dependencies = [
|
||||
"bitflags 2.13.2",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.13.2",
|
||||
"cfg-if",
|
||||
@@ -1423,19 +1444,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.9.2"
|
||||
version = "2.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45d3aca230fad2e6f6317ca0a72724338c4960cb97168a85cdee66df4a9a21a8"
|
||||
checksum = "b568374ba38b33a6c627141f891faf16902b08d2db26b8ede1bcb0a15b1919fa"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"psm",
|
||||
"stacker",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.9.2"
|
||||
version = "2.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "284b60557f2c4a2e72ad3f2d34d42685a2fa4a6a61d0d2a10c0ae2a5e916c2cf"
|
||||
checksum = "b66e184b924cebaaff20ab2256ca52f12332d528a39aa76553b5d96f92aacf7f"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
@@ -1443,22 +1466,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.9.2"
|
||||
version = "2.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d9d1f08a115309ee99268cf85e5228e0e56aa9caf8841ec12866b6be07c3109"
|
||||
checksum = "a87478d267e4de54a626af9754f2f0f58e927aac6ed0575fe89bc05ad6851694"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
"syn 3.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.9.2"
|
||||
version = "2.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed93ba1a9ffcca32130a5188701c81c0c49cf00d4b7c5007d5148951d743adcb"
|
||||
checksum = "4f986f248b4241ac359b831f6139aaa34e03b08a37b6caf7e201a33f95c869e1"
|
||||
dependencies = [
|
||||
"pest",
|
||||
]
|
||||
@@ -1529,9 +1552,9 @@ checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
checksum = "4a6394b9e965e73d0a289ee54f589087e2c676aedf60885baf52c76b771e4958"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
@@ -1579,6 +1602,15 @@ dependencies = [
|
||||
"unarray",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psm"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
@@ -1932,7 +1964,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.6",
|
||||
"syn 3.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2015,9 +2047,9 @@ checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
|
||||
checksum = "33f4fe9184a62d842c9ef383018f3306d8ba224fd9d836f56d7288308847c256"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
@@ -2027,9 +2059,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.16.2"
|
||||
version = "1.16.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e"
|
||||
checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
@@ -2041,6 +2073,19 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stacker"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "707f49d46706bacf8a2b00d51dace3f9de527c13eec3778f570c411f89e69967"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"psm",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
@@ -2098,9 +2143,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.6"
|
||||
version = "3.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee"
|
||||
checksum = "d62a2e0561533f2ca2561d0cf27fd9fedb640a1bf2616ff5d5c80d99017faadc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2172,7 +2217,7 @@ dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"memmem",
|
||||
"nix",
|
||||
"nix 0.29.0",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"ordered-float",
|
||||
@@ -2233,7 +2278,7 @@ checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.6",
|
||||
"syn 3.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2259,9 +2304,9 @@ checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.53.1"
|
||||
version = "1.53.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed"
|
||||
checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
@@ -2280,7 +2325,7 @@ checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.6",
|
||||
"syn 3.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2361,9 +2406,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.9.0"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
|
||||
checksum = "357cc3acc6a036009fd6c973ed009037c732d60d0b4f6c673e9041497482a28f"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
@@ -2402,9 +2447,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.26.1"
|
||||
version = "1.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce"
|
||||
checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606"
|
||||
dependencies = [
|
||||
"atomic",
|
||||
"getrandom 0.4.3",
|
||||
@@ -2494,7 +2539,7 @@ dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.6",
|
||||
"syn 3.0.7",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -2706,18 +2751,18 @@ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.58"
|
||||
version = "0.8.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c17e8fafad82b542ff3717217ecdc736231b59e387768c9630123b4ce4d2db44"
|
||||
checksum = "86502bf56ac7c77571a32e2647bb2a15894565e981fb2a48d7bde2d91c965a9d"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.58"
|
||||
version = "0.8.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "595f56e044df4f46a0c9a626f65c3d99eb8488f7e8a8baa12dd76326d9710bf2"
|
||||
checksum = "5457206954b06561e2608c7e19cf58b1926586d999c246eebe4502f7e2039d1a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@@ -103,6 +103,16 @@ rec {
|
||||
# File a bug if you depend on any for non-debug work!
|
||||
debug = internal.debugCrate { inherit packageId; };
|
||||
};
|
||||
"improvise-incremental" = rec {
|
||||
packageId = "improvise-incremental";
|
||||
build = internal.buildRustCrateWithFeatures {
|
||||
packageId = "improvise-incremental";
|
||||
};
|
||||
|
||||
# Debug support which might change between releases.
|
||||
# File a bug if you depend on any for non-debug work!
|
||||
debug = internal.debugCrate { inherit packageId; };
|
||||
};
|
||||
"improvise-io" = rec {
|
||||
packageId = "improvise-io";
|
||||
build = internal.buildRustCrateWithFeatures {
|
||||
@@ -721,14 +731,14 @@ rec {
|
||||
}
|
||||
{
|
||||
name = "syn";
|
||||
packageId = "syn 3.0.6";
|
||||
packageId = "syn 3.0.7";
|
||||
features = [ "full" "fold" ];
|
||||
}
|
||||
];
|
||||
devDependencies = [
|
||||
{
|
||||
name = "syn";
|
||||
packageId = "syn 3.0.6";
|
||||
packageId = "syn 3.0.7";
|
||||
features = [ "full" "fold" "parsing" ];
|
||||
}
|
||||
];
|
||||
@@ -817,9 +827,9 @@ rec {
|
||||
};
|
||||
"cc" = rec {
|
||||
crateName = "cc";
|
||||
version = "1.4.7";
|
||||
version = "1.7.0";
|
||||
edition = "2021";
|
||||
sha256 = "04z3q2wqsg4qgx4vsqsd01s27svz0bgdymjiyccgbnn24gg3whal";
|
||||
sha256 = "12xvzyiwincbr6djn8ykbdlxv87ilva4pjxhkz156xc2iaplk9jh";
|
||||
dependencies = [
|
||||
{
|
||||
name = "find-msvc-tools";
|
||||
@@ -1062,7 +1072,7 @@ rec {
|
||||
}
|
||||
{
|
||||
name = "syn";
|
||||
packageId = "syn 3.0.6";
|
||||
packageId = "syn 3.0.7";
|
||||
features = [ "full" ];
|
||||
}
|
||||
];
|
||||
@@ -1577,7 +1587,7 @@ rec {
|
||||
}
|
||||
{
|
||||
name = "syn";
|
||||
packageId = "syn 3.0.6";
|
||||
packageId = "syn 3.0.7";
|
||||
features = [ "full" "extra-traits" ];
|
||||
}
|
||||
];
|
||||
@@ -1608,7 +1618,7 @@ rec {
|
||||
}
|
||||
{
|
||||
name = "syn";
|
||||
packageId = "syn 3.0.6";
|
||||
packageId = "syn 3.0.7";
|
||||
}
|
||||
];
|
||||
|
||||
@@ -1855,9 +1865,9 @@ rec {
|
||||
};
|
||||
"either" = rec {
|
||||
crateName = "either";
|
||||
version = "1.18.0";
|
||||
version = "1.19.0";
|
||||
edition = "2021";
|
||||
sha256 = "0d7dx31sf8rakcgp63070ngb2vkjynrni866pnx879pawndgnai5";
|
||||
sha256 = "1gjq21g0sgk5ylpj85zafcinwhh3jj91i6drhb4278vw2v17370f";
|
||||
features = {
|
||||
"default" = [ "std" ];
|
||||
"serde" = [ "dep:serde" ];
|
||||
@@ -2047,9 +2057,9 @@ rec {
|
||||
};
|
||||
"find-msvc-tools" = rec {
|
||||
crateName = "find-msvc-tools";
|
||||
version = "0.1.13";
|
||||
version = "0.1.14";
|
||||
edition = "2021";
|
||||
sha256 = "16ykhz2icc0xx8i3vr8fpp6h3djpik2zw5bcxbff9bxba5g909gg";
|
||||
sha256 = "112ljldlv150fpl8xr2jl5czg51k3kdfn6cy5fqdsvkl14sgpp5f";
|
||||
libName = "find_msvc_tools";
|
||||
|
||||
};
|
||||
@@ -3047,6 +3057,30 @@ rec {
|
||||
}
|
||||
];
|
||||
|
||||
};
|
||||
"improvise-incremental" = rec {
|
||||
crateName = "improvise-incremental";
|
||||
version = "0.1.0";
|
||||
edition = "2024";
|
||||
src = lib.cleanSourceWith { filter = sourceFilter; src = ./crates/improvise-incremental; };
|
||||
libName = "improvise_incremental";
|
||||
dependencies = [
|
||||
{
|
||||
name = "improvise-core";
|
||||
packageId = "improvise-core";
|
||||
}
|
||||
];
|
||||
devDependencies = [
|
||||
{
|
||||
name = "improvise-io";
|
||||
packageId = "improvise-io";
|
||||
}
|
||||
{
|
||||
name = "proptest";
|
||||
packageId = "proptest";
|
||||
}
|
||||
];
|
||||
|
||||
};
|
||||
"improvise-io" = rec {
|
||||
crateName = "improvise-io";
|
||||
@@ -3379,9 +3413,9 @@ rec {
|
||||
};
|
||||
"indoc" = rec {
|
||||
crateName = "indoc";
|
||||
version = "2.0.7";
|
||||
version = "2.0.8";
|
||||
edition = "2021";
|
||||
sha256 = "01np60qdq6lvgh8ww2caajn9j4dibx9n58rvzf7cya1jz69mrkvr";
|
||||
sha256 = "1lc4agds9bqf3lin6kkz2jgmahaqwrkaq1fkij5fpzvcg68jcyx3";
|
||||
procMacro = true;
|
||||
authors = [
|
||||
"David Tolnay <dtolnay@gmail.com>"
|
||||
@@ -3429,7 +3463,7 @@ rec {
|
||||
}
|
||||
{
|
||||
name = "syn";
|
||||
packageId = "syn 3.0.6";
|
||||
packageId = "syn 3.0.7";
|
||||
features = [ "derive" "full" ];
|
||||
}
|
||||
];
|
||||
@@ -3557,9 +3591,9 @@ rec {
|
||||
};
|
||||
"lazy_static" = rec {
|
||||
crateName = "lazy_static";
|
||||
version = "1.5.0";
|
||||
version = "1.5.1";
|
||||
edition = "2015";
|
||||
sha256 = "1zk6dqqni0193xg6iijh7i3i44sryglwgvx20spdvwk3r6sbrlmv";
|
||||
sha256 = "1yqaqmp510xw2ldpw88mx9b5s5qj8flb4rw0wd9ks1zpk9j0z1r0";
|
||||
authors = [
|
||||
"Marvin Löbel <loebel.marvin@gmail.com>"
|
||||
];
|
||||
@@ -3570,9 +3604,9 @@ rec {
|
||||
};
|
||||
"libc" = rec {
|
||||
crateName = "libc";
|
||||
version = "0.2.189";
|
||||
version = "0.2.190";
|
||||
edition = "2021";
|
||||
sha256 = "1whjfs375vlng2q6yrbzs73cvp5lm3w1n2gfqajb2vgf7zg3xbry";
|
||||
sha256 = "0y5yap4bfp7rfsldcbk9pb5alcgygca5xn1n2pmh181zdpf3spff";
|
||||
features = {
|
||||
"default" = [ "std" ];
|
||||
"rustc-dep-of-std" = [ "align" "rustc-std-workspace-core" ];
|
||||
@@ -3738,24 +3772,24 @@ rec {
|
||||
};
|
||||
"mac_address" = rec {
|
||||
crateName = "mac_address";
|
||||
version = "1.1.8";
|
||||
version = "1.2.0";
|
||||
edition = "2018";
|
||||
sha256 = "00r3n18mxglq1dzshnm0vxk1fgsp3c2hd08w6hfcqdp8ymmv5bn0";
|
||||
sha256 = "06pbqk1hqiraavi2wxc9gxj1g73bbm7af7ccf6sx79g9kc5barxk";
|
||||
authors = [
|
||||
"rep-nop <repnop@outlook.com>"
|
||||
];
|
||||
dependencies = [
|
||||
{
|
||||
name = "nix";
|
||||
packageId = "nix";
|
||||
packageId = "nix 0.30.1";
|
||||
target = { target, features }: (("linux" == target."os" or null) || ("macos" == target."os" or null) || ("freebsd" == target."os" or null) || ("netbsd" == target."os" or null) || ("openbsd" == target."os" or null) || ("android" == target."os" or null) || ("illumos" == target."os" or null));
|
||||
features = [ "net" ];
|
||||
}
|
||||
{
|
||||
name = "winapi";
|
||||
packageId = "winapi";
|
||||
name = "windows-sys";
|
||||
packageId = "windows-sys";
|
||||
target = { target, features }: (target."windows" or false);
|
||||
features = [ "winerror" "ws2def" "iphlpapi" ];
|
||||
features = [ "Win32_Networking_WinSock" "Win32_NetworkManagement_IpHelper" "Win32_NetworkManagement_Ndis" ];
|
||||
}
|
||||
];
|
||||
features = {
|
||||
@@ -3860,9 +3894,9 @@ rec {
|
||||
};
|
||||
"mio" = rec {
|
||||
crateName = "mio";
|
||||
version = "1.2.3";
|
||||
version = "1.2.4";
|
||||
edition = "2021";
|
||||
sha256 = "1n5ryp7j5fga38z7php5yy9k7ia24rp6cl9gm27zwar6khz4862b";
|
||||
sha256 = "1vl6px9zy0pwhlwnw3cknsqyzkg8bcpiwiq4cgicf2fwgywfv20p";
|
||||
authors = [
|
||||
"Carl Lerche <me@carllerche.com>"
|
||||
"Thomas de Zeeuw <thomasdezeeuw@gmail.com>"
|
||||
@@ -3898,7 +3932,7 @@ rec {
|
||||
};
|
||||
resolvedDefaultFeatures = [ "default" "log" "net" "os-ext" "os-poll" ];
|
||||
};
|
||||
"nix" = rec {
|
||||
"nix 0.29.0" = rec {
|
||||
crateName = "nix";
|
||||
version = "0.29.0";
|
||||
edition = "2021";
|
||||
@@ -3906,6 +3940,53 @@ rec {
|
||||
authors = [
|
||||
"The nix-rust Project Developers"
|
||||
];
|
||||
dependencies = [
|
||||
{
|
||||
name = "bitflags";
|
||||
packageId = "bitflags 2.13.2";
|
||||
}
|
||||
{
|
||||
name = "cfg-if";
|
||||
packageId = "cfg-if";
|
||||
}
|
||||
{
|
||||
name = "libc";
|
||||
packageId = "libc";
|
||||
features = [ "extra_traits" ];
|
||||
}
|
||||
];
|
||||
buildDependencies = [
|
||||
{
|
||||
name = "cfg_aliases";
|
||||
packageId = "cfg_aliases";
|
||||
}
|
||||
];
|
||||
features = {
|
||||
"aio" = [ "pin-utils" ];
|
||||
"dir" = [ "fs" ];
|
||||
"memoffset" = [ "dep:memoffset" ];
|
||||
"mount" = [ "uio" ];
|
||||
"mqueue" = [ "fs" ];
|
||||
"net" = [ "socket" ];
|
||||
"pin-utils" = [ "dep:pin-utils" ];
|
||||
"ptrace" = [ "process" ];
|
||||
"sched" = [ "process" ];
|
||||
"signal" = [ "process" ];
|
||||
"socket" = [ "memoffset" ];
|
||||
"ucontext" = [ "signal" ];
|
||||
"user" = [ "feature" ];
|
||||
"zerocopy" = [ "fs" "uio" ];
|
||||
};
|
||||
resolvedDefaultFeatures = [ "default" "fs" "mman" ];
|
||||
};
|
||||
"nix 0.30.1" = rec {
|
||||
crateName = "nix";
|
||||
version = "0.30.1";
|
||||
edition = "2021";
|
||||
sha256 = "1dixahq9hk191g0c2ydc0h1ppxj0xw536y6rl63vlnp06lx3ylkl";
|
||||
authors = [
|
||||
"The nix-rust Project Developers"
|
||||
];
|
||||
dependencies = [
|
||||
{
|
||||
name = "bitflags";
|
||||
@@ -3935,6 +4016,7 @@ rec {
|
||||
features = {
|
||||
"aio" = [ "pin-utils" ];
|
||||
"dir" = [ "fs" ];
|
||||
"event" = [ "poll" ];
|
||||
"memoffset" = [ "dep:memoffset" ];
|
||||
"mount" = [ "uio" ];
|
||||
"mqueue" = [ "fs" ];
|
||||
@@ -3948,7 +4030,7 @@ rec {
|
||||
"user" = [ "feature" ];
|
||||
"zerocopy" = [ "fs" "uio" ];
|
||||
};
|
||||
resolvedDefaultFeatures = [ "default" "fs" "memoffset" "mman" "net" "socket" ];
|
||||
resolvedDefaultFeatures = [ "default" "memoffset" "net" "socket" ];
|
||||
};
|
||||
"nom" = rec {
|
||||
crateName = "nom";
|
||||
@@ -4436,9 +4518,9 @@ rec {
|
||||
};
|
||||
"pest" = rec {
|
||||
crateName = "pest";
|
||||
version = "2.9.2";
|
||||
version = "2.9.3";
|
||||
edition = "2021";
|
||||
sha256 = "1a11k95dyrpfrn2ql5lprdh4k31k4hksg83w67vfdlps62iarls5";
|
||||
sha256 = "1yhr35ds3c5ww7nvh9nvs842p40nmwgqj7ql4z3accwbld5kfs5m";
|
||||
authors = [
|
||||
"Dragoș Tiselice <dragostiselice@gmail.com>"
|
||||
];
|
||||
@@ -4448,6 +4530,16 @@ rec {
|
||||
packageId = "memchr";
|
||||
optional = true;
|
||||
}
|
||||
{
|
||||
name = "psm";
|
||||
packageId = "psm";
|
||||
optional = true;
|
||||
}
|
||||
{
|
||||
name = "stacker";
|
||||
packageId = "stacker";
|
||||
optional = true;
|
||||
}
|
||||
{
|
||||
name = "ucd-trie";
|
||||
packageId = "ucd-trie";
|
||||
@@ -4459,15 +4551,15 @@ rec {
|
||||
"memchr" = [ "dep:memchr" ];
|
||||
"miette-error" = [ "std" "pretty-print" "dep:miette" ];
|
||||
"pretty-print" = [ "dep:serde" "dep:serde_json" ];
|
||||
"std" = [ "ucd-trie/std" ];
|
||||
"std" = [ "ucd-trie/std" "dep:stacker" "dep:psm" ];
|
||||
};
|
||||
resolvedDefaultFeatures = [ "default" "memchr" "std" ];
|
||||
};
|
||||
"pest_derive" = rec {
|
||||
crateName = "pest_derive";
|
||||
version = "2.9.2";
|
||||
version = "2.9.3";
|
||||
edition = "2021";
|
||||
sha256 = "1ky22vlsbqha1jhx5l31d95gm8l54va38b9zmmr2wjicgxan0jr8";
|
||||
sha256 = "0zygma96zndmadjsg6m353ak48ziab55c8mb43zsmsscj95ihvmn";
|
||||
procMacro = true;
|
||||
authors = [
|
||||
"Dragoș Tiselice <dragostiselice@gmail.com>"
|
||||
@@ -4493,9 +4585,9 @@ rec {
|
||||
};
|
||||
"pest_generator" = rec {
|
||||
crateName = "pest_generator";
|
||||
version = "2.9.2";
|
||||
version = "2.9.3";
|
||||
edition = "2021";
|
||||
sha256 = "029igkh6nsw62bn4325gkjm5c3lf4bjqbkv8jblrwc0ml441z78x";
|
||||
sha256 = "150nhpb5mh4vx1gmgl3fmix953pmy3r595xg4sk59pp4cz97hx58";
|
||||
authors = [
|
||||
"Dragoș Tiselice <dragostiselice@gmail.com>"
|
||||
];
|
||||
@@ -4519,7 +4611,7 @@ rec {
|
||||
}
|
||||
{
|
||||
name = "syn";
|
||||
packageId = "syn 2.0.119";
|
||||
packageId = "syn 3.0.7";
|
||||
}
|
||||
];
|
||||
features = {
|
||||
@@ -4531,9 +4623,9 @@ rec {
|
||||
};
|
||||
"pest_meta" = rec {
|
||||
crateName = "pest_meta";
|
||||
version = "2.9.2";
|
||||
version = "2.9.3";
|
||||
edition = "2021";
|
||||
sha256 = "1jxd8gbm328lsl3m0z2b1pq9ri60h4f7122i189k5jpwkwdbm4zd";
|
||||
sha256 = "1qb9r2akz8q1wbvwmdipiaq06km3m8wn27w3kcssqha2icj6z62g";
|
||||
authors = [
|
||||
"Dragoș Tiselice <dragostiselice@gmail.com>"
|
||||
];
|
||||
@@ -4706,9 +4798,9 @@ rec {
|
||||
};
|
||||
"powerfmt" = rec {
|
||||
crateName = "powerfmt";
|
||||
version = "0.2.0";
|
||||
version = "0.2.1";
|
||||
edition = "2021";
|
||||
sha256 = "14ckj2xdpkhv3h6l5sdmb9f1d57z8hbfpdldjc2vl5givq2y77j3";
|
||||
sha256 = "0n293rvnpisjmxdqhq6zmrvcdql7j1c4zrcy5053vrv5x6wr8qsa";
|
||||
authors = [
|
||||
"Jacob Pratt <jacob@jhpratt.dev>"
|
||||
];
|
||||
@@ -4863,6 +4955,22 @@ rec {
|
||||
};
|
||||
resolvedDefaultFeatures = [ "bit-set" "default" "fork" "regex-syntax" "rusty-fork" "std" "tempfile" "timeout" ];
|
||||
};
|
||||
"psm" = rec {
|
||||
crateName = "psm";
|
||||
version = "0.1.24";
|
||||
edition = "2015";
|
||||
sha256 = "0428cnwx8i9dhkcjwzap0amg9cjk8nhj0xr5hkhm6zl543r9y2r0";
|
||||
authors = [
|
||||
"Simonas Kazlauskas <psm@kazlauskas.me>"
|
||||
];
|
||||
buildDependencies = [
|
||||
{
|
||||
name = "cc";
|
||||
packageId = "cc";
|
||||
}
|
||||
];
|
||||
|
||||
};
|
||||
"quick-error" = rec {
|
||||
crateName = "quick-error";
|
||||
version = "1.2.3";
|
||||
@@ -6145,7 +6253,7 @@ rec {
|
||||
}
|
||||
{
|
||||
name = "syn";
|
||||
packageId = "syn 3.0.6";
|
||||
packageId = "syn 3.0.7";
|
||||
usesDefaultFeatures = false;
|
||||
features = [ "clone-impls" "derive" "parsing" "printing" "proc-macro" ];
|
||||
}
|
||||
@@ -6407,9 +6515,9 @@ rec {
|
||||
};
|
||||
"siphasher" = rec {
|
||||
crateName = "siphasher";
|
||||
version = "1.0.3";
|
||||
version = "1.0.4";
|
||||
edition = "2018";
|
||||
sha256 = "0jg6l9xyzca5vy4h6gf8r6p4kk84g98fk95pzig1kq6cr4z8grcf";
|
||||
sha256 = "0mn28y43123jdpskdn6r9wibmn066f7h30zkkqn88bd6hj8zxx1k";
|
||||
authors = [
|
||||
"Frank Denis <github@pureftpd.org>"
|
||||
];
|
||||
@@ -6438,9 +6546,9 @@ rec {
|
||||
};
|
||||
"smallvec" = rec {
|
||||
crateName = "smallvec";
|
||||
version = "1.16.2";
|
||||
version = "1.16.3";
|
||||
edition = "2018";
|
||||
sha256 = "13iai5hhwyp8z0pbn8r11q4j5956jaxhcbvvf2drm17f1q7myfgr";
|
||||
sha256 = "06z0akmcq2zc9qg22dxda298p50gg3di5ggl3y2nllag8ypwhgav";
|
||||
authors = [
|
||||
"The Servo Project Developers"
|
||||
];
|
||||
@@ -6481,6 +6589,49 @@ rec {
|
||||
};
|
||||
resolvedDefaultFeatures = [ "all" ];
|
||||
};
|
||||
"stacker" = rec {
|
||||
crateName = "stacker";
|
||||
version = "0.1.25";
|
||||
edition = "2021";
|
||||
sha256 = "0rwrws4iyh8cay7pghzf2dy55pprwfn1vm805f5czfh6cza4jzvh";
|
||||
authors = [
|
||||
"Alex Crichton <alex@alexcrichton.com>"
|
||||
"Simonas Kazlauskas <stacker@kazlauskas.me>"
|
||||
];
|
||||
dependencies = [
|
||||
{
|
||||
name = "cfg-if";
|
||||
packageId = "cfg-if";
|
||||
}
|
||||
{
|
||||
name = "libc";
|
||||
packageId = "libc";
|
||||
}
|
||||
{
|
||||
name = "psm";
|
||||
packageId = "psm";
|
||||
}
|
||||
{
|
||||
name = "windows-sys";
|
||||
packageId = "windows-sys";
|
||||
target = { target, features }: (target.name == "arm64ec-pc-windows-msvc");
|
||||
features = [ "Win32_System_Memory" "Win32_System_Threading" "Win32_Foundation" ];
|
||||
}
|
||||
{
|
||||
name = "windows-sys";
|
||||
packageId = "windows-sys";
|
||||
target = { target, features }: ((target."windows" or false) && (!("arm64ec" == target."arch" or null)));
|
||||
features = [ "Win32_System_Memory" "Win32_System_Threading" "Win32_Foundation" ];
|
||||
}
|
||||
];
|
||||
buildDependencies = [
|
||||
{
|
||||
name = "cc";
|
||||
packageId = "cc";
|
||||
}
|
||||
];
|
||||
|
||||
};
|
||||
"static_assertions" = rec {
|
||||
crateName = "static_assertions";
|
||||
version = "1.1.0";
|
||||
@@ -6623,11 +6774,11 @@ rec {
|
||||
};
|
||||
resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" ];
|
||||
};
|
||||
"syn 3.0.6" = rec {
|
||||
"syn 3.0.7" = rec {
|
||||
crateName = "syn";
|
||||
version = "3.0.6";
|
||||
version = "3.0.7";
|
||||
edition = "2021";
|
||||
sha256 = "1vmw7s58rzrs926nv5m06x7qbgswm1aa9iw3s1bj5var47kyi4w5";
|
||||
sha256 = "1p5agw0rj3f8spsnyqgj3c569nzyv5zz430xasi2qgskc42jwann";
|
||||
authors = [
|
||||
"David Tolnay <dtolnay@gmail.com>"
|
||||
];
|
||||
@@ -6854,7 +7005,7 @@ rec {
|
||||
}
|
||||
{
|
||||
name = "nix";
|
||||
packageId = "nix";
|
||||
packageId = "nix 0.29.0";
|
||||
target = { target, features }: (target."unix" or false);
|
||||
features = [ "mman" "fs" ];
|
||||
}
|
||||
@@ -7040,7 +7191,7 @@ rec {
|
||||
}
|
||||
{
|
||||
name = "syn";
|
||||
packageId = "syn 3.0.6";
|
||||
packageId = "syn 3.0.7";
|
||||
}
|
||||
];
|
||||
|
||||
@@ -7133,9 +7284,9 @@ rec {
|
||||
};
|
||||
"tokio" = rec {
|
||||
crateName = "tokio";
|
||||
version = "1.53.1";
|
||||
version = "1.53.2";
|
||||
edition = "2021";
|
||||
sha256 = "1v8b3b45pkpbibls75yniqbvx5dlks2708141ljni5mnf6lawb10";
|
||||
sha256 = "0i202ksji8q2asvii0adzgi8m0z93z3j7apn62qfh8d6qzy92pz9";
|
||||
authors = [
|
||||
"Tokio Contributors <team@tokio.rs>"
|
||||
];
|
||||
@@ -7262,7 +7413,7 @@ rec {
|
||||
}
|
||||
{
|
||||
name = "syn";
|
||||
packageId = "syn 3.0.6";
|
||||
packageId = "syn 3.0.7";
|
||||
features = [ "full" ];
|
||||
}
|
||||
];
|
||||
@@ -7513,9 +7664,9 @@ rec {
|
||||
};
|
||||
"unicase" = rec {
|
||||
crateName = "unicase";
|
||||
version = "2.9.0";
|
||||
version = "2.10.0";
|
||||
edition = "2018";
|
||||
sha256 = "0hh1wrfd7807mfph2q67jsxqgw8hm82xg2fb8ln8cvblkwxbri6v";
|
||||
sha256 = "13x2h9s4jhch7rknqkqb1pb35irpj00fswy9ssgh0dm0qsnc6z1m";
|
||||
authors = [
|
||||
"Sean McArthur <sean@seanmonstar.com>"
|
||||
];
|
||||
@@ -7609,9 +7760,9 @@ rec {
|
||||
};
|
||||
"uuid" = rec {
|
||||
crateName = "uuid";
|
||||
version = "1.26.1";
|
||||
version = "1.28.0";
|
||||
edition = "2021";
|
||||
sha256 = "1kl5nb7r3gpmkc43d6nbayvzqhcp2grczk6c7bxv80b6x70xmxif";
|
||||
sha256 = "01mnlhz09hwdjaxwzjd6bql3fjb5zl9n8dzaxn7dvdxyhiiiihbw";
|
||||
authors = [
|
||||
"Ashley Mannix<ashleymannix@live.com.au>"
|
||||
"Dylan DPC<dylan.dpc@gmail.com>"
|
||||
@@ -7888,7 +8039,7 @@ rec {
|
||||
}
|
||||
{
|
||||
name = "syn";
|
||||
packageId = "syn 3.0.6";
|
||||
packageId = "syn 3.0.7";
|
||||
features = [ "visit" "visit-mut" "full" "extra-traits" ];
|
||||
}
|
||||
{
|
||||
@@ -8644,7 +8795,7 @@ rec {
|
||||
features = {
|
||||
"debug" = [ "impl-debug" ];
|
||||
};
|
||||
resolvedDefaultFeatures = [ "consoleapi" "fileapi" "handleapi" "impl-default" "iphlpapi" "memoryapi" "namedpipeapi" "processenv" "processthreadsapi" "synchapi" "winbase" "winerror" "winnls" "winnt" "winsock2" "winuser" "ws2def" ];
|
||||
resolvedDefaultFeatures = [ "consoleapi" "fileapi" "handleapi" "impl-default" "memoryapi" "namedpipeapi" "processenv" "processthreadsapi" "synchapi" "winbase" "winerror" "winnls" "winnt" "winsock2" "winuser" ];
|
||||
};
|
||||
"winapi-i686-pc-windows-gnu" = rec {
|
||||
crateName = "winapi-i686-pc-windows-gnu";
|
||||
@@ -9065,7 +9216,7 @@ rec {
|
||||
"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_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_SystemServices" "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_NetworkManagement" "Win32_NetworkManagement_IpHelper" "Win32_NetworkManagement_Ndis" "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_Memory" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "default" ];
|
||||
};
|
||||
"winnow" = rec {
|
||||
crateName = "winnow";
|
||||
@@ -9114,9 +9265,9 @@ rec {
|
||||
};
|
||||
"zerocopy" = rec {
|
||||
crateName = "zerocopy";
|
||||
version = "0.8.58";
|
||||
version = "0.8.62";
|
||||
edition = "2021";
|
||||
sha256 = "0i6vsbj4qfqj62b8qxl7wdcin8rnqz6pw88p6zzl5dc2mnpqyzn1";
|
||||
sha256 = "17asjqfdkqmxsx42myw1x5jlb28m5axlf9ifldqpbiy7dbsjnl46";
|
||||
dependencies = [
|
||||
{
|
||||
name = "zerocopy-derive";
|
||||
@@ -9146,9 +9297,9 @@ rec {
|
||||
};
|
||||
"zerocopy-derive" = rec {
|
||||
crateName = "zerocopy-derive";
|
||||
version = "0.8.58";
|
||||
version = "0.8.62";
|
||||
edition = "2021";
|
||||
sha256 = "1whbf7cjcqyp5nhvma78yy489swr7mfgc9m6r6h4ckyz8kh5cpsr";
|
||||
sha256 = "06lx0gigf0j5pvp4dhlrv636b4mib37ijzlcc3i62rdhailj0msl";
|
||||
procMacro = true;
|
||||
libName = "zerocopy_derive";
|
||||
dependencies = [
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
[workspace]
|
||||
members = [".", "crates/improvise-formula", "crates/improvise-core", "crates/improvise-protocol", "crates/improvise-io", "crates/improvise-command", "crates/improvise-wasm-client", "crates/improvise-ws-server", "crates/improvise-worker-server", "crates/gp-tree", "crates/improvise-gp", "crates/numtower", "crates/zset", "crates/zset-ffi"]
|
||||
members = [".", "crates/improvise-formula", "crates/improvise-core", "crates/improvise-protocol", "crates/improvise-io", "crates/improvise-command", "crates/improvise-wasm-client", "crates/improvise-ws-server", "crates/improvise-worker-server", "crates/gp-tree", "crates/improvise-gp", "crates/numtower", "crates/zset", "crates/improvise-incremental", "crates/zset-ffi"]
|
||||
|
||||
[package]
|
||||
name = "improvise"
|
||||
@@ -70,9 +70,9 @@ improvise-wasm-client = { path = "crates/improvise-wasm-client" }
|
||||
improvise-protocol = { path = "crates/improvise-protocol", features = ["test-support"] }
|
||||
# `tests/headless_cli.rs` detaches the binary from any terminal with `setsid`.
|
||||
libc = "0.2"
|
||||
pest = "2.9.2"
|
||||
pest_derive = "2.9.2"
|
||||
pest_meta = "2.9.2"
|
||||
pest = "2.9.3"
|
||||
pest_derive = "2.9.3"
|
||||
pest_meta = "2.9.3"
|
||||
proptest = "1"
|
||||
tempfile = "3"
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
# `improvise-incremental`: the reasoning
|
||||
|
||||
`crates/improvise-incremental` is ADR 009 step 2 (improvise-t8ow, epic improvise-bw4p): the
|
||||
plug. It holds the `Derived` trait, `Eager` (today's evaluator behind it) and the
|
||||
differential harness every later backend is checked with. There is no incremental backend
|
||||
here, the evaluator is untouched and no existing crate changed. The decisions are the ADR's
|
||||
(`context/adr/009-incremental-evaluation.md`, clause 2). The evidence for each test is in
|
||||
`context/test-evidence/improvise-incremental.md`.
|
||||
|
||||
## The shape
|
||||
|
||||
| item | what it is |
|
||||
|---|---|
|
||||
| `Derived` | the two things the evaluator reads: `value(key, agg)` and `raw_fold(partial)` |
|
||||
| `Eager` | an owned `Model` plus its None categories; every answer is a call into `Model` |
|
||||
| `Maintained` | a `Derived` that is told each `Edit`; `Eager` is one |
|
||||
| `Edit` | one model mutation as data (set, clear, add or remove a formula, set a measure's aggregation) |
|
||||
| `probes`, `Probe` | every question worth asking of a model, and a way to put it to any backend |
|
||||
| `differential` | runs one edit sequence on a candidate and on `Eager`, comparing every probe at every step |
|
||||
| `Divergence`, `Report` | what a failure names (step, probe, both answers) and what a pass compared |
|
||||
|
||||
## Interpretations
|
||||
|
||||
Clause 2 names the trait and says what it carries ("the formula result at a key, and the raw
|
||||
fold of the cells that match a partial key") and nothing else. These are the readings taken.
|
||||
|
||||
1. **`Derived` lives in this crate, not in improvise-core.** The ADR says improvise-core
|
||||
"gains a trait". Putting it there changes an existing crate's source, which the brief for
|
||||
this step ruled out, and the brief was ambiguous about it. This departs from the accepted
|
||||
ADR's text, so it is flagged to the user and not decided here: improvise-bw4p.2 moves it
|
||||
(one file and a `pub use`, since the trait names only core types). While it sits
|
||||
downstream, core cannot read through it, which is the clause's point.
|
||||
2. **Two methods, the minimum.** `value(key, agg)` is the formula result at a key, or the cell
|
||||
as stored or folded; `raw_fold(partial)` is the fold of matching stored cells. `agg` is
|
||||
`Aggregation`, the evaluator's own type. Hidden-item `covers`, totals and occupancy are not
|
||||
in the trait, so the differential cannot probe them, and a hidden item (view state) cannot
|
||||
be exercised at all. The ADR's differential compares "every drawn cell, total and occupancy
|
||||
count"; improvise-bw4p.3 adds them. A group is exercised: a stored key with one coordinate
|
||||
replaced by its item's group is a probe.
|
||||
3. **`raw_fold` is never a formula, and `Eager` enforces it.** For a partial naming a formula
|
||||
target `Eager::raw_fold` is `None`; otherwise it is `evaluate_aggregated(partial, OverHidden)`,
|
||||
because the evaluator's own raw fold (`aggregate_raw`, `aggregate_cell_values`) is private to
|
||||
core. Calling it through the public path is exact for any partial that names no formula
|
||||
target. improvise-bw4p.2 exposes the raw fold from core so `Eager` stops going round.
|
||||
4. **`Eager` recomputes formulas after every edit.** Production does it in `rebuild_layout`
|
||||
(`Model::recompute_formulas(none_cats)`), and an over-hidden read of a formula cell reads
|
||||
the cache it fills. So `Eager` carries the None categories of the view it stands for and
|
||||
recomputes under them after each edit, as a layout rebuild does.
|
||||
5. **`Edit` is the vocabulary of the harness, not of the wire.** Five variants, each one
|
||||
public `Model` call. A later step adds variants for what it maintains (an item added, a
|
||||
category removed); the harness does not care which. An `Edit` fault reaches both sides of a
|
||||
differential alike, so it is pinned only where a direct `Eager` test reads the result:
|
||||
`ClearCell`, `AddFormula` and `RemoveFormula`, and `SetMeasureAgg` through the fold tests.
|
||||
`SetCell` is read by nearly every test.
|
||||
6. **Values agree by float rules with every NaN one value** (`same_value`), the rule clause 3
|
||||
states for cell deltas. Signed zero compares equal, so a later `ExactSum` cannot be told
|
||||
from eager's sum by the sign of a zero here; clause 8 has its own property test for that.
|
||||
7. **No `zset` dependency yet.** Nothing in this step uses a Z-set. It arrives with the first
|
||||
backend, as the cell delta of step 3.
|
||||
|
||||
## What the harness checks
|
||||
|
||||
`differential(model, none_cats, candidate, edits)` builds `Eager` over a clone of the model,
|
||||
applies each edit to both, and after step 0 and after every edit asks both every probe. The
|
||||
probe set **accumulates**: probes from the model at every earlier step stay asked, so a backend
|
||||
that goes on answering for a removed formula diverges. A pass returns a `Report` of how many
|
||||
states and answers were compared.
|
||||
|
||||
`probes(model)` takes the base keys (each stored key, and each with one coordinate replaced by
|
||||
its item's group), every sub-partial of a base key dropping at most `MAX_DROPPED = 3`
|
||||
coordinates plus the empty key, and each formula's target over each of those. Each key is asked
|
||||
as an exact value, an over-hidden value and a raw fold. A fold dropping more than three
|
||||
coordinates from a stored key is not asked about. `edit_probes`
|
||||
adds the key an edit names, so a cleared cell is asked about after it is gone. A divergence
|
||||
reads `divergence at step N: <probe>: eager <a> != candidate <b>`.
|
||||
|
||||
**A limit, stated plainly (improvise-bw4p.4).** The probe set is every stored key's
|
||||
sub-partials, not the keys a view draws. A view with four or more categories on None draws a cell
|
||||
that drops four or more coordinates of a stored key, and the harness checks none of those cells:
|
||||
a rival wrong only at `{C0=a, _Measure=Revenue}` over a five-category model passes. Neither
|
||||
shipped demo reaches the limit, so the corpus does not show it. Raising `MAX_DROPPED` is not the
|
||||
answer, because `sub_partials` walks all 2^n subsets of a key whatever the limit is (93ms at 20
|
||||
categories and 225ms at 22 in a debug build, per call). The fix is to probe the keys each view
|
||||
draws, with steps 3 and 4; until then a candidate on such a view is under-checked.
|
||||
|
||||
The corpus the tests use is `examples/demo.improv` and `web/demo.improv`, loaded through
|
||||
`improvise_io::persistence::load`, and hand-built models (formulas, text, mixed values, a group).
|
||||
`eager_matches_the_evaluator_on_the_shipped_documents` takes every view's None categories; the
|
||||
differential runs take the first per document, and the largest document only its first four
|
||||
edits, to keep the binary under two seconds in a debug build. A proptest (256 cases) runs random
|
||||
edit sequences against a candidate that rebuilds an `Eager` from scratch on each edit.
|
||||
@@ -0,0 +1,194 @@
|
||||
# Test evidence: `improvise-incremental`
|
||||
|
||||
What each test guards, which rival it was run against, and where that rival failed. The
|
||||
reasoning is in `context/code/improvise-incremental.md`; the decisions are ADR 009 clause 2's.
|
||||
|
||||
**How the rivals are kept.** The `the_harness_catches_*` tests run `differential` on a
|
||||
`Rival`, an `Eager` told every edit and wrong in one way, and assert the step at which the
|
||||
harness reports the divergence. They run on every build, so each rival is watched failing on
|
||||
every run and not once by hand.
|
||||
|
||||
**Injected in the source.** Eighteen faults were put into `src/eager.rs`, `src/harness.rs`
|
||||
and `src/edit.rs` one at a time, each run against the whole suite and each reverted and
|
||||
followed by a full rerun. The failing tests, by name (a fault no test names survived, and
|
||||
none did):
|
||||
- `Eager::value` ignores its `Aggregation`: `eager_follows_an_edit_to_the_cell_a_fold_reads`,
|
||||
`eager_matches_the_evaluator_on_the_shipped_documents`, `eager_raw_fold_is_never_a_formula`,
|
||||
`eager_value_reads_a_formula_exactly_and_folded`,
|
||||
`the_harness_catches_a_backend_that_ignores_the_aggregation`,
|
||||
`the_harness_catches_a_wrong_folded_formula_value`;
|
||||
- `Eager::raw_fold` reads `Exact`: `eager_raw_fold_sums_by_default`,
|
||||
`eager_raw_fold_follows_the_measures_aggregation`, `eager_raw_fold_of_text_is_unanimous_or_mixed`,
|
||||
`eager_numbers_among_text_are_mixed`, `eager_follows_an_edit_to_the_cell_a_fold_reads`,
|
||||
`eager_matches_the_evaluator_on_the_shipped_documents`,
|
||||
`the_harness_catches_a_raw_fold_that_returns_a_formula`;
|
||||
- `Eager::raw_fold` returns a formula's value: `eager_raw_fold_is_never_a_formula`,
|
||||
`eager_matches_the_evaluator_on_the_shipped_documents`,
|
||||
`the_harness_catches_a_raw_fold_that_returns_a_formula`;
|
||||
- `Eager::apply` does not recompute formulas: `eager_follows_an_edit_to_the_cell_a_fold_reads`,
|
||||
`a_maintained_eager_equals_a_fresh_one_over_random_edit_sequences`;
|
||||
- the harness compares only the first edit: `the_harness_catches_a_backend_that_ignores_a_clear`,
|
||||
`…_ignores_the_measure_aggregation`, `…_goes_stale_after_two_edits`,
|
||||
`the_harness_catches_a_backend_that_keeps_answering_for_a_removed_formula`;
|
||||
- the harness never reports a divergence: all nine `the_harness_catches_*` tests;
|
||||
- `same_value` always true: `same_value_follows_the_float_rules_and_is_exact_elsewhere` and four
|
||||
`the_harness_catches_*` tests;
|
||||
- `same_value` NaN unequal, signed zero by bits, any two text equal: each fails
|
||||
`same_value_follows_the_float_rules_and_is_exact_elsewhere` and nothing else;
|
||||
- `probes` omit formula cells: `probes_cover_folds_formulas_measures_and_groups` and four
|
||||
`the_harness_catches_*` tests;
|
||||
- `probes` drop at most one coordinate: `probes_cover_folds_formulas_measures_and_groups`,
|
||||
`the_harness_catches_a_fault_that_only_shows_after_two_coordinates_are_dropped`;
|
||||
- `probes` omit raw folds: `probes_cover_folds_formulas_measures_and_groups`,
|
||||
`an_edit_names_its_key_as_two_value_probes_and_a_fold`,
|
||||
`the_harness_catches_a_raw_fold_that_returns_a_formula`;
|
||||
- `probes` omit group keys: `probes_cover_folds_formulas_measures_and_groups`,
|
||||
`the_harness_catches_a_wrong_group_fold`;
|
||||
- the probe history is forgotten between steps: `…_goes_stale_after_two_edits`,
|
||||
`…_ignores_a_clear`, `the_harness_catches_a_backend_that_keeps_answering_for_a_removed_formula`;
|
||||
- `edit_probes` names nothing: `an_edit_names_its_key_as_two_value_probes_and_a_fold`;
|
||||
- `Edit::AddFormula` as a no-op: `eager_add_and_remove_formula_change_what_a_key_reads`;
|
||||
- `Edit::ClearCell` applied as `SetCell(0.0)`, which both sides of a differential share and so
|
||||
only a direct `Eager` test can see: `eager_clear_cell_leaves_the_key_absent`.
|
||||
|
||||
## eager_raw_fold_sums_by_default
|
||||
|
||||
Hand-computed: Revenue under Product A is 10 + 5 = 15. Fails on the `raw_fold`-reads-`Exact`
|
||||
rival (a partial key names no stored cell, so the answer is `None`).
|
||||
|
||||
## eager_raw_fold_follows_the_measures_aggregation
|
||||
|
||||
After `measure_agg[Revenue] = Max` the same fold is 10, and Cost, unchanged, still sums to 6.
|
||||
A fold that always sums fails on the first; one that always takes the maximum fails on the second.
|
||||
|
||||
## eager_raw_fold_of_text_is_unanimous_or_mixed
|
||||
|
||||
Note under A is two equal texts and reads as that text; under B it is two different texts and
|
||||
reads `Error("mixed")`. A fold that drops text, which the evaluator used to do (gotcha 7),
|
||||
returns `None` for both.
|
||||
|
||||
## eager_numbers_among_text_are_mixed
|
||||
|
||||
A text among numbers is `Error("mixed")`, not the sum of the numbers.
|
||||
|
||||
## eager_value_reads_a_formula_exactly_and_folded
|
||||
|
||||
`Profit = Revenue - Cost` reads 6 at East/A exactly, and 9 at Product A with Region over
|
||||
hidden: (10 + 5) - (4 + 2), the fold taken before the subtraction. Fails on the
|
||||
`value`-ignores-`Aggregation` rival.
|
||||
|
||||
## eager_follows_an_edit_to_the_cell_a_fold_reads
|
||||
|
||||
After East/A Revenue becomes 20 the fold is 25 and the folded Profit 19. The Profit half is
|
||||
what fails when `apply` forgets to recompute formulas: the folded cache is then stale.
|
||||
|
||||
## eager_matches_the_evaluator_on_the_shipped_documents
|
||||
|
||||
Both shipped documents, every view's None categories, and the hand model: every probe of
|
||||
`Eager` equals a direct `evaluate_aggregated` on a model recomputed under the same None
|
||||
categories, and the probe set is non-empty. Fails on both aggregation rivals.
|
||||
|
||||
## eager_agrees_with_itself_over_every_corpus_edit_sequence
|
||||
|
||||
`differential` over a generated edit sequence on each corpus model returns a `Report` with
|
||||
`edits + 1` steps and a non-zero probe count. The count assertion is what a harness that
|
||||
compared nothing would fail; the step count is what one that stopped early would fail.
|
||||
## the_harness_passes_a_backend_that_is_right
|
||||
|
||||
The control for the `catches` tests: `Eager` as the candidate over the hand-built edits is a
|
||||
pass, so a harness that rejects everything is seen.
|
||||
|
||||
## the_harness_catches_a_backend_that_ignores_the_aggregation
|
||||
|
||||
A candidate that reads every `value` as `Exact` diverges at step 0, first at the full-key
|
||||
formula cell `{East, A, Profit}` over hidden (eager `None`, candidate `6`).
|
||||
|
||||
## the_harness_catches_a_backend_that_ignores_the_measure_aggregation
|
||||
|
||||
A candidate that drops `SetMeasureAgg` diverges at step 2, the edit that sets it, on a Revenue key.
|
||||
|
||||
## the_harness_catches_a_backend_that_goes_stale_after_two_edits
|
||||
|
||||
A candidate that stops applying edits after the second diverges at step 3, on a Revenue key.
|
||||
A prefix of steps cannot see a backend that goes wrong late.
|
||||
|
||||
## the_harness_catches_a_backend_that_ignores_a_clear
|
||||
|
||||
A candidate that keeps a cleared cell diverges at step 3 and the message names it.
|
||||
|
||||
## the_harness_catches_a_wrong_folded_formula_value
|
||||
|
||||
Review of PR 343 (Codex P1): a rival wrong only at `value({Product=A, _Measure=Profit}, OverHidden)`,
|
||||
the Profit cell a view with Region on None draws, passed 128 probes, because formula cells were
|
||||
built over full keys only. Now the divergence is at step 0 on exactly that probe, eager `9`,
|
||||
candidate `-999`.
|
||||
|
||||
## the_harness_catches_a_backend_that_keeps_answering_for_a_removed_formula
|
||||
|
||||
Review of PR 343: probes were rebuilt from the post-edit model, so a candidate that ignores
|
||||
`RemoveFormula` was never asked about Profit again. Probes now accumulate over every step. The
|
||||
divergence is at the last step, on a Profit key, eager `None`, candidate `Some`.
|
||||
|
||||
## the_harness_catches_a_fault_that_only_shows_after_two_coordinates_are_dropped
|
||||
|
||||
Review of PR 343 (Copilot): only one-coordinate partials and the empty key were probed. A rival
|
||||
wrong only at `{_Measure=Revenue}` now diverges at step 0 on `Value({_Measure=Revenue}, Exact)`.
|
||||
The bound is `MAX_DROPPED = 3` coordinates; a fold dropping more is not asked about.
|
||||
|
||||
## the_harness_catches_a_raw_fold_that_returns_a_formula
|
||||
|
||||
Review of PR 343 (Copilot): `raw_fold` is documented never to be a formula. A rival whose
|
||||
`raw_fold` is `value(partial, OverHidden)` diverges at step 0 on a `RawFold` of a Profit partial
|
||||
(eager `None`, candidate `Some`). It could not be seen while `Eager` itself returned the formula.
|
||||
|
||||
## the_harness_catches_a_wrong_group_fold
|
||||
|
||||
A group name stands in for an item in the probe keys. A rival wrong only at
|
||||
`{Region=Coastal, Product=A, _Measure=Revenue}` diverges at step 0, eager `15`, candidate `-999`.
|
||||
|
||||
## eager_folds_a_group_it_is_asked_about
|
||||
|
||||
The group fold in the grouped model is East + West = 15 exactly, so the rival test above has a
|
||||
true answer to differ from.
|
||||
|
||||
## eager_raw_fold_is_never_a_formula
|
||||
|
||||
At `{Product=A, _Measure=Profit}` the folded value is `9` and the raw fold is `None`. Fails on the
|
||||
fault that lets `raw_fold` read the formula cache.
|
||||
|
||||
## eager_add_and_remove_formula_change_what_a_key_reads
|
||||
|
||||
Review of PR 343: `Edit::AddFormula` as a no-op left all 25 tests green, because an `Edit` fault
|
||||
reaches both sides of a differential alike. `Double = Revenue * 2` reads `None` before the edit
|
||||
and `20` at East/A after it, and `None` again after `RemoveFormula`. Fails on `AddFormula` as a
|
||||
no-op.
|
||||
|
||||
## eager_clear_cell_leaves_the_key_absent
|
||||
|
||||
After `ClearCell` the key reads `None` and the model holds no cell. A `ClearCell` applied as
|
||||
`SetCell(0.0)` hits both sides of a differential identically, so only this direct test fails.
|
||||
|
||||
## same_value_follows_the_float_rules_and_is_exact_elsewhere
|
||||
|
||||
NaN equals NaN, `-0.0` equals `0.0`, `1.0` differs from `1.0000000000000002`, texts and errors
|
||||
compare exactly, and `None` equals only `None`. Each of three one-line faults in `same_value`
|
||||
(NaN unequal, signed zero by bits, any two texts equal) survived the whole suite until this test
|
||||
existed.
|
||||
|
||||
## probes_cover_folds_formulas_measures_and_groups
|
||||
|
||||
`probes` includes a raw fold, a full key, a folded formula cell under both aggregations, the
|
||||
two-dropped key `{_Measure=Revenue}`, the empty key and a group key. Review of PR 343 showed
|
||||
`probes` omitting formula cells, `_Measure` keys or raw folds left every test green.
|
||||
|
||||
## an_edit_names_its_key_as_two_value_probes_and_a_fold
|
||||
|
||||
`edit_probes` of a `ClearCell` names the cleared key three ways, and of an edit naming no key
|
||||
names nothing.
|
||||
|
||||
## a_maintained_eager_equals_a_fresh_one_over_random_edit_sequences
|
||||
|
||||
Clause 2 asks for a property test over a random edit sequence. A proptest (256 cases, up to four
|
||||
edits of five kinds over the hand-built model) runs `differential` with a candidate that rebuilds
|
||||
an `Eager` from scratch on every edit. It fails on the `Eager::apply`-skips-recompute fault, which
|
||||
is the property: maintaining in place equals building afresh.
|
||||
@@ -17,7 +17,7 @@ serde = { version = "1", features = ["derive"] }
|
||||
# wasm-clean.
|
||||
siphasher = "1"
|
||||
# Unicode full case folding for slugify (ADR 007 answer 26). no_std, no dependencies.
|
||||
unicase = "2.9"
|
||||
unicase = "2.10"
|
||||
|
||||
[features]
|
||||
# Exposes the fold-evaluation counter to other crates' tests (improvise-0jw5).
|
||||
|
||||
@@ -8,11 +8,11 @@ repository = "https://github.com/fiddlerwoaroof/improvise"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
pest = "2.9.2"
|
||||
pest_derive = "2.9.2"
|
||||
pest = "2.9.3"
|
||||
pest_derive = "2.9.3"
|
||||
# For FormulaId alone, which crosses the wire (improvise-km71); no AST derive.
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
pest_meta = "2.9.2"
|
||||
pest_meta = "2.9.3"
|
||||
proptest = "1"
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "improvise-incremental"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
license = "Apache-2.0"
|
||||
description = "The seam between improvise-core and the incremental circuit: the Derived trait, the Eager oracle and the differential harness (ADR 009 clause 2)."
|
||||
|
||||
# ADR 009 clause 2: depends on improvise-core, never the other way round. The
|
||||
# `zset` edge arrives with the first backend that uses it (step 3), not before.
|
||||
[dependencies]
|
||||
improvise-core = { path = "../improvise-core" }
|
||||
|
||||
[dev-dependencies]
|
||||
improvise-io = { path = "../improvise-io" }
|
||||
proptest = "1"
|
||||
@@ -0,0 +1,46 @@
|
||||
//! Today's evaluator behind the trait. Temporary (ADR 009 clause 2).
|
||||
|
||||
use crate::{Derived, Edit, Maintained};
|
||||
use improvise_core::model::cell::{CellKey, CellValue};
|
||||
use improvise_core::model::{Aggregation, Model};
|
||||
|
||||
/// A model plus the None categories its formulas were last recomputed under.
|
||||
/// It adds no logic: every answer is a call into `Model`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Eager {
|
||||
model: Model,
|
||||
none_cats: Vec<String>,
|
||||
}
|
||||
|
||||
impl Eager {
|
||||
pub fn new(mut model: Model, none_cats: Vec<String>) -> Self {
|
||||
model.recompute_formulas(&none_cats);
|
||||
Eager { model, none_cats }
|
||||
}
|
||||
|
||||
pub fn model(&self) -> &Model {
|
||||
&self.model
|
||||
}
|
||||
}
|
||||
|
||||
impl Derived for Eager {
|
||||
fn value(&self, key: &CellKey, agg: Aggregation) -> Option<CellValue> {
|
||||
self.model.evaluate_aggregated(key, agg)
|
||||
}
|
||||
|
||||
fn raw_fold(&self, partial: &CellKey) -> Option<CellValue> {
|
||||
match self.model.formula_for(partial) {
|
||||
Some(_) => None,
|
||||
None => self
|
||||
.model
|
||||
.evaluate_aggregated(partial, Aggregation::OverHidden),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Maintained for Eager {
|
||||
fn apply(&mut self, edit: &Edit) {
|
||||
edit.apply(&mut self.model);
|
||||
self.model.recompute_formulas(&self.none_cats);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
//! One mutation of a model, as data, so a sequence can be replayed on two backends.
|
||||
|
||||
use improvise_core::formula::ast::{AggFunc, Formula};
|
||||
use improvise_core::model::Model;
|
||||
use improvise_core::model::cell::{CellKey, CellValue};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Edit {
|
||||
SetCell(CellKey, CellValue),
|
||||
ClearCell(CellKey),
|
||||
AddFormula(Formula),
|
||||
RemoveFormula {
|
||||
target: String,
|
||||
target_category: String,
|
||||
},
|
||||
SetMeasureAgg {
|
||||
measure: String,
|
||||
func: AggFunc,
|
||||
},
|
||||
}
|
||||
|
||||
impl Edit {
|
||||
/// The one place an edit becomes a call on the model.
|
||||
pub fn apply(&self, model: &mut Model) {
|
||||
match self {
|
||||
Edit::SetCell(key, value) => model.set_cell(key.clone(), value.clone()),
|
||||
Edit::ClearCell(key) => model.clear_cell(key),
|
||||
Edit::AddFormula(formula) => model.add_formula(formula.clone()),
|
||||
Edit::RemoveFormula {
|
||||
target,
|
||||
target_category,
|
||||
} => model.remove_formula(target, target_category),
|
||||
Edit::SetMeasureAgg { measure, func } => {
|
||||
model.measure_agg.insert(measure.clone(), func.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The key an edit names, if it names one: always probed after it.
|
||||
pub fn key(&self) -> Option<&CellKey> {
|
||||
match self {
|
||||
Edit::SetCell(key, _) | Edit::ClearCell(key) => Some(key),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
//! The differential harness: one edit sequence, two backends, every probe after every step.
|
||||
|
||||
use crate::{Derived, Eager, Edit};
|
||||
use improvise_core::model::cell::{CellKey, CellValue};
|
||||
use improvise_core::model::{Aggregation, Model};
|
||||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
|
||||
/// A backend that holds state of its own and is told each edit.
|
||||
pub trait Maintained: Derived {
|
||||
fn apply(&mut self, edit: &Edit);
|
||||
}
|
||||
|
||||
/// One question put to both backends.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Probe {
|
||||
Value(CellKey, Aggregation),
|
||||
RawFold(CellKey),
|
||||
}
|
||||
|
||||
impl Probe {
|
||||
pub fn ask(&self, backend: &dyn Derived) -> Option<CellValue> {
|
||||
match self {
|
||||
Probe::Value(key, agg) => backend.value(key, *agg),
|
||||
Probe::RawFold(partial) => backend.raw_fold(partial),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Divergence {
|
||||
/// 0 is the model as built, `n` the state after edit `n`.
|
||||
pub step: usize,
|
||||
pub probe: Probe,
|
||||
pub eager: Option<CellValue>,
|
||||
pub candidate: Option<CellValue>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Divergence {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"divergence at step {}: {:?}: eager {:?} != candidate {:?}",
|
||||
self.step, self.probe, self.eager, self.candidate
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// How many states and how many answers were compared: a run that compared
|
||||
/// nothing must be visible as such.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Report {
|
||||
pub steps: usize,
|
||||
pub probes: usize,
|
||||
}
|
||||
|
||||
/// Values agree when equal by float rules with every NaN one value, so a NaN
|
||||
/// answer is not a divergence from itself.
|
||||
pub fn same_value(a: &Option<CellValue>, b: &Option<CellValue>) -> bool {
|
||||
match (a, b) {
|
||||
(Some(CellValue::Number(x)), Some(CellValue::Number(y))) => {
|
||||
x == y || (x.is_nan() && y.is_nan())
|
||||
}
|
||||
_ => a == b,
|
||||
}
|
||||
}
|
||||
|
||||
/// The most coordinates a probed partial key drops from a stored key; the
|
||||
/// empty key is probed as well. A fold dropping more is not asked about.
|
||||
pub const MAX_DROPPED: usize = 3;
|
||||
|
||||
/// The questions asked of a backend, once each, in the order first added.
|
||||
#[derive(Default)]
|
||||
struct Asked {
|
||||
seen: HashSet<(CellKey, u8)>,
|
||||
order: Vec<Probe>,
|
||||
}
|
||||
|
||||
impl Asked {
|
||||
fn extend(&mut self, probes: impl IntoIterator<Item = Probe>) {
|
||||
for p in probes {
|
||||
let tag = match &p {
|
||||
Probe::Value(k, Aggregation::Exact) => (k.clone(), 0),
|
||||
Probe::Value(k, Aggregation::OverHidden) => (k.clone(), 1),
|
||||
Probe::RawFold(k) => (k.clone(), 2),
|
||||
};
|
||||
if self.seen.insert(tag) {
|
||||
self.order.push(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn all_three(key: CellKey) -> [Probe; 3] {
|
||||
[
|
||||
Probe::Value(key.clone(), Aggregation::Exact),
|
||||
Probe::Value(key.clone(), Aggregation::OverHidden),
|
||||
Probe::RawFold(key),
|
||||
]
|
||||
}
|
||||
|
||||
/// Every key `key` keeps after dropping at most `MAX_DROPPED` coordinates.
|
||||
fn sub_partials(key: &CellKey) -> impl Iterator<Item = CellKey> + '_ {
|
||||
let n = key.0.len();
|
||||
(0..1u64 << n)
|
||||
.filter(|mask| mask.count_ones() as usize <= MAX_DROPPED)
|
||||
.map(move |mask| {
|
||||
let kept = (0..n)
|
||||
.filter(|i| mask >> i & 1 == 0)
|
||||
.map(|i| key.0[i].clone());
|
||||
CellKey::new(kept.collect())
|
||||
})
|
||||
}
|
||||
|
||||
/// Every question worth asking of `model`; the bound and the key set are
|
||||
/// in `context/code/improvise-incremental.md`.
|
||||
pub fn probes(model: &Model) -> Vec<Probe> {
|
||||
let stored: Vec<CellKey> = model.data.iter_cells().map(|(k, _)| k).collect();
|
||||
let grouped = stored.iter().flat_map(|k| {
|
||||
k.0.iter().filter_map(|(cat, item)| {
|
||||
let group = model.category(cat)?.items.get(item)?.group.clone()?;
|
||||
Some(k.clone().with(cat, group))
|
||||
})
|
||||
});
|
||||
let base: Vec<CellKey> = stored.iter().cloned().chain(grouped).collect();
|
||||
let partials = base
|
||||
.iter()
|
||||
.flat_map(sub_partials)
|
||||
.chain(std::iter::once(CellKey::new(vec![])));
|
||||
let mut asked = Asked::default();
|
||||
for key in partials {
|
||||
let formula_cells = model
|
||||
.formulas()
|
||||
.iter()
|
||||
.map(|f| key.clone().with(&f.target_category, &f.target))
|
||||
.collect::<Vec<_>>();
|
||||
asked.extend(all_three(key));
|
||||
asked.extend(formula_cells.into_iter().flat_map(all_three));
|
||||
}
|
||||
asked.order
|
||||
}
|
||||
|
||||
/// What an edit names: its key, asked all three ways, after the edit.
|
||||
pub fn edit_probes(edit: &Edit) -> Vec<Probe> {
|
||||
edit.key()
|
||||
.cloned()
|
||||
.into_iter()
|
||||
.flat_map(all_three)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn compare(
|
||||
step: usize,
|
||||
eager: &Eager,
|
||||
candidate: &dyn Derived,
|
||||
asked: &Asked,
|
||||
) -> Result<usize, Divergence> {
|
||||
for probe in &asked.order {
|
||||
let (want, got) = (probe.ask(eager), probe.ask(candidate));
|
||||
if !same_value(&want, &got) {
|
||||
return Err(Divergence {
|
||||
step,
|
||||
probe: probe.clone(),
|
||||
eager: want,
|
||||
candidate: got,
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(asked.order.len())
|
||||
}
|
||||
|
||||
/// Runs `edits` on `candidate` and on `Eager`, comparing every probe ever
|
||||
/// asked (so a removed formula stays asked about) at each step. `candidate` is built from `model` with the same `none_cats`.
|
||||
pub fn differential<C: Maintained>(
|
||||
model: &Model,
|
||||
none_cats: &[String],
|
||||
mut candidate: C,
|
||||
edits: &[Edit],
|
||||
) -> Result<Report, Divergence> {
|
||||
let mut eager = Eager::new(model.clone(), none_cats.to_vec());
|
||||
let mut asked = Asked::default();
|
||||
asked.extend(probes(eager.model()));
|
||||
let mut probes_run = compare(0, &eager, &candidate, &asked)?;
|
||||
for (n, edit) in edits.iter().enumerate() {
|
||||
eager.apply(edit);
|
||||
candidate.apply(edit);
|
||||
asked.extend(probes(eager.model()));
|
||||
asked.extend(edit_probes(edit));
|
||||
probes_run += compare(n + 1, &eager, &candidate, &asked)?;
|
||||
}
|
||||
Ok(Report {
|
||||
steps: edits.len() + 1,
|
||||
probes: probes_run,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//! The plug: what the evaluator reads, and the oracle that answers it today.
|
||||
//! Reasoning: `context/code/improvise-incremental.md`.
|
||||
|
||||
mod eager;
|
||||
mod edit;
|
||||
mod harness;
|
||||
|
||||
pub use eager::Eager;
|
||||
pub use edit::Edit;
|
||||
pub use harness::{
|
||||
Divergence, MAX_DROPPED, Maintained, Probe, Report, differential, edit_probes, probes,
|
||||
same_value,
|
||||
};
|
||||
|
||||
use improvise_core::model::Aggregation;
|
||||
use improvise_core::model::cell::{CellKey, CellValue};
|
||||
|
||||
/// The two things the evaluator reads (ADR 009 clause 2).
|
||||
pub trait Derived {
|
||||
/// The value at `key`: the formula result when a formula owns it, else the
|
||||
/// cell as stored or folded over what `agg` hides. `Model::evaluate_aggregated`.
|
||||
fn value(&self, key: &CellKey, agg: Aggregation) -> Option<CellValue>;
|
||||
|
||||
/// The raw fold of the stored cells that match `partial`, by the measure's
|
||||
/// aggregation. Never a formula: `None` for a partial naming a formula target.
|
||||
fn raw_fold(&self, partial: &CellKey) -> Option<CellValue>;
|
||||
}
|
||||
@@ -0,0 +1,633 @@
|
||||
//! `Eager` against the evaluator, and the harness against wrong backends.
|
||||
//! Evidence: `context/test-evidence/improvise-incremental.md`.
|
||||
|
||||
use improvise_core::formula::ast::AggFunc;
|
||||
use improvise_core::formula::parse_formula;
|
||||
use improvise_core::model::cell::{CellKey, CellValue};
|
||||
use improvise_core::model::{Aggregation, Model};
|
||||
use improvise_core::view::Axis;
|
||||
use improvise_incremental::{
|
||||
Derived, Divergence, Eager, Edit, Maintained, Probe, differential, probes, same_value,
|
||||
};
|
||||
use proptest::prelude::*;
|
||||
use std::path::Path;
|
||||
|
||||
fn key(region: &str, product: &str, measure: &str) -> CellKey {
|
||||
CellKey::new(vec![
|
||||
("Region".into(), region.into()),
|
||||
("Product".into(), product.into()),
|
||||
("_Measure".into(), measure.into()),
|
||||
])
|
||||
}
|
||||
|
||||
fn partial(product: &str, measure: &str) -> CellKey {
|
||||
CellKey::new(vec![
|
||||
("Product".into(), product.into()),
|
||||
("_Measure".into(), measure.into()),
|
||||
])
|
||||
}
|
||||
|
||||
fn num(n: f64) -> Option<CellValue> {
|
||||
Some(CellValue::Number(n))
|
||||
}
|
||||
|
||||
fn text(s: &str) -> Option<CellValue> {
|
||||
Some(CellValue::Text(s.into()))
|
||||
}
|
||||
|
||||
fn mixed() -> Option<CellValue> {
|
||||
Some(CellValue::Error("mixed".into()))
|
||||
}
|
||||
|
||||
/// Region is the None category. Revenue and Cost are numbers; Note is text,
|
||||
/// unanimous under A and conflicting under B.
|
||||
fn hand_model() -> Model {
|
||||
let mut m = Model::new("hand");
|
||||
for (cat, items) in [("Region", ["East", "West"]), ("Product", ["A", "B"])] {
|
||||
m.add_category(cat).unwrap();
|
||||
for item in items {
|
||||
m.category_mut(cat).unwrap().add_item(item);
|
||||
}
|
||||
}
|
||||
for measure in ["Revenue", "Cost", "Note"] {
|
||||
m.category_mut("_Measure").unwrap().add_item(measure);
|
||||
}
|
||||
let rows = [
|
||||
("East", "A", 10.0, 4.0, "n", "n"),
|
||||
("West", "A", 5.0, 2.0, "n", "n"),
|
||||
("East", "B", 7.0, 3.0, "x", "x"),
|
||||
("West", "B", 1.0, 1.0, "y", "y"),
|
||||
];
|
||||
for (r, p, rev, cost, note, _) in rows {
|
||||
m.set_cell(key(r, p, "Revenue"), CellValue::Number(rev));
|
||||
m.set_cell(key(r, p, "Cost"), CellValue::Number(cost));
|
||||
m.set_cell(key(r, p, "Note"), CellValue::Text(note.into()));
|
||||
}
|
||||
m.add_formula(parse_formula("Profit = Revenue - Cost", "_Measure").unwrap());
|
||||
m
|
||||
}
|
||||
|
||||
fn hand_eager() -> Eager {
|
||||
Eager::new(hand_model(), vec!["Region".into()])
|
||||
}
|
||||
|
||||
fn hand_edits() -> Vec<Edit> {
|
||||
vec![
|
||||
Edit::SetCell(key("East", "A", "Revenue"), CellValue::Number(20.0)),
|
||||
Edit::SetMeasureAgg {
|
||||
measure: "Revenue".into(),
|
||||
func: AggFunc::Max,
|
||||
},
|
||||
Edit::ClearCell(key("West", "A", "Revenue")),
|
||||
Edit::SetCell(key("West", "B", "Revenue"), CellValue::Text("oops".into())),
|
||||
Edit::AddFormula(parse_formula("Double = Revenue * 2", "_Measure").unwrap()),
|
||||
Edit::RemoveFormula {
|
||||
target: "Profit".into(),
|
||||
target_category: "_Measure".into(),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_raw_fold_sums_by_default() {
|
||||
assert_eq!(hand_eager().raw_fold(&partial("A", "Revenue")), num(15.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_raw_fold_follows_the_measures_aggregation() {
|
||||
let mut eager = hand_eager();
|
||||
eager.apply(&Edit::SetMeasureAgg {
|
||||
measure: "Revenue".into(),
|
||||
func: AggFunc::Max,
|
||||
});
|
||||
assert_eq!(eager.raw_fold(&partial("A", "Revenue")), num(10.0));
|
||||
assert_eq!(eager.raw_fold(&partial("A", "Cost")), num(6.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_raw_fold_of_text_is_unanimous_or_mixed() {
|
||||
let eager = hand_eager();
|
||||
assert_eq!(eager.raw_fold(&partial("A", "Note")), text("n"));
|
||||
assert_eq!(eager.raw_fold(&partial("B", "Note")), mixed());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_value_reads_a_formula_exactly_and_folded() {
|
||||
let eager = hand_eager();
|
||||
assert_eq!(
|
||||
eager.value(&key("East", "A", "Profit"), Aggregation::Exact),
|
||||
num(6.0)
|
||||
);
|
||||
assert_eq!(
|
||||
eager.value(&partial("A", "Profit"), Aggregation::OverHidden),
|
||||
num(9.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_follows_an_edit_to_the_cell_a_fold_reads() {
|
||||
let mut eager = hand_eager();
|
||||
eager.apply(&Edit::SetCell(
|
||||
key("East", "A", "Revenue"),
|
||||
CellValue::Number(20.0),
|
||||
));
|
||||
assert_eq!(eager.raw_fold(&partial("A", "Revenue")), num(25.0));
|
||||
assert_eq!(
|
||||
eager.value(&partial("A", "Profit"), Aggregation::OverHidden),
|
||||
num(19.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_numbers_among_text_are_mixed() {
|
||||
let mut eager = hand_eager();
|
||||
eager.apply(&Edit::SetCell(
|
||||
key("West", "B", "Revenue"),
|
||||
CellValue::Text("oops".into()),
|
||||
));
|
||||
assert_eq!(eager.raw_fold(&partial("B", "Revenue")), mixed());
|
||||
}
|
||||
|
||||
fn corpus() -> Vec<(String, Model, Vec<String>)> {
|
||||
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../..");
|
||||
let mut out = Vec::new();
|
||||
for file in ["examples/demo.improv", "web/demo.improv"] {
|
||||
let wb = improvise_io::persistence::load(&root.join(file)).unwrap();
|
||||
let mut seen: Vec<Vec<String>> = Vec::new();
|
||||
for (name, view) in &wb.views {
|
||||
let none: Vec<String> = view
|
||||
.categories_on(Axis::None)
|
||||
.into_iter()
|
||||
.map(String::from)
|
||||
.collect();
|
||||
if !seen.contains(&none) {
|
||||
seen.push(none.clone());
|
||||
out.push((format!("{file}:{name}"), wb.model.clone(), none));
|
||||
}
|
||||
}
|
||||
}
|
||||
out.push(("hand".into(), hand_model(), vec!["Region".into()]));
|
||||
out
|
||||
}
|
||||
|
||||
/// Edits built from the model's own first cell: overwrite, text, clear, a new
|
||||
/// record, a new aggregation, and the first formula removed then restored.
|
||||
fn edits_for(model: &Model) -> Vec<Edit> {
|
||||
let Some((first, _)) = model.data.iter_cells().next() else {
|
||||
return vec![];
|
||||
};
|
||||
let (last_cat, _) = first.0.last().unwrap().clone();
|
||||
let measure = first.get("_Measure").map(String::from);
|
||||
let fresh = first.clone().with(last_cat, "Zz-new");
|
||||
let mut edits = vec![
|
||||
Edit::SetCell(first.clone(), CellValue::Number(7.5)),
|
||||
Edit::SetCell(first.clone(), CellValue::Text("t".into())),
|
||||
Edit::SetCell(fresh.clone(), CellValue::Number(3.0)),
|
||||
Edit::ClearCell(first),
|
||||
];
|
||||
edits.extend(measure.map(|m| Edit::SetMeasureAgg {
|
||||
measure: m,
|
||||
func: AggFunc::Max,
|
||||
}));
|
||||
if let Some(f) = model.formulas().first() {
|
||||
edits.push(Edit::RemoveFormula {
|
||||
target: f.target.clone(),
|
||||
target_category: f.target_category.clone(),
|
||||
});
|
||||
edits.push(Edit::AddFormula(f.clone()));
|
||||
}
|
||||
edits.push(Edit::ClearCell(fresh));
|
||||
edits
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_matches_the_evaluator_on_the_shipped_documents() {
|
||||
for (name, model, none) in corpus() {
|
||||
let eager = Eager::new(model.clone(), none.clone());
|
||||
let mut direct = model.clone();
|
||||
direct.recompute_formulas(&none);
|
||||
let asked = probes(eager.model());
|
||||
assert!(!asked.is_empty(), "{name}: no probes");
|
||||
for probe in asked {
|
||||
let want = match &probe {
|
||||
Probe::Value(k, a) => direct.evaluate_aggregated(k, *a),
|
||||
Probe::RawFold(k) if direct.formula_for(k).is_some() => None,
|
||||
Probe::RawFold(k) => direct.evaluate_aggregated(k, Aggregation::OverHidden),
|
||||
};
|
||||
assert_eq!(probe.ask(&eager), want, "{name}: {probe:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_agrees_with_itself_over_every_corpus_edit_sequence() {
|
||||
let mut files_done: Vec<String> = Vec::new();
|
||||
for (name, model, none) in corpus() {
|
||||
let file = name.split(':').next().unwrap().to_string();
|
||||
if files_done.contains(&file) {
|
||||
continue;
|
||||
}
|
||||
files_done.push(file);
|
||||
let mut edits = edits_for(&model);
|
||||
// Probes grow with the cells squared-ish, and a debug build pays for it.
|
||||
if model.data.iter_cells().count() > 40 {
|
||||
edits.truncate(4);
|
||||
}
|
||||
let report = differential(
|
||||
&model,
|
||||
&none,
|
||||
Eager::new(model.clone(), none.clone()),
|
||||
&edits,
|
||||
)
|
||||
.unwrap_or_else(|d| panic!("{name}: {d}"));
|
||||
assert_eq!(report.steps, edits.len() + 1, "{name}");
|
||||
assert!(report.probes > 0, "{name}");
|
||||
}
|
||||
}
|
||||
|
||||
fn grouped_model() -> Model {
|
||||
let mut m = Model::new("grouped");
|
||||
m.add_category("Region").unwrap();
|
||||
m.add_category("Product").unwrap();
|
||||
m.category_mut("Region")
|
||||
.unwrap()
|
||||
.add_group(improvise_core::model::category::Group::new("Coastal"));
|
||||
let region = m.category_mut("Region").unwrap();
|
||||
region.add_item_in_group("East", "Coastal");
|
||||
region.add_item_in_group("West", "Coastal");
|
||||
region.add_item("Inland");
|
||||
m.category_mut("Product").unwrap().add_item("A");
|
||||
m.category_mut("_Measure").unwrap().add_item("Revenue");
|
||||
for (r, v) in [("East", 10.0), ("West", 5.0), ("Inland", 2.0)] {
|
||||
m.set_cell(key(r, "A", "Revenue"), CellValue::Number(v));
|
||||
}
|
||||
m
|
||||
}
|
||||
|
||||
fn coastal() -> CellKey {
|
||||
key("Coastal", "A", "Revenue")
|
||||
}
|
||||
|
||||
/// A wrong backend: an `Eager` told every edit, answering one thing wrongly.
|
||||
#[derive(Clone, Copy)]
|
||||
enum Fault {
|
||||
IgnoresAggregation,
|
||||
IgnoresMeasureAggregation,
|
||||
GoesStaleAfterTwoEdits,
|
||||
IgnoresClear,
|
||||
WrongFoldedFormula,
|
||||
IgnoresRemoveFormula,
|
||||
WrongWhenTwoAreDropped,
|
||||
RawFoldReturnsFormula,
|
||||
WrongOnAGroup,
|
||||
}
|
||||
|
||||
struct Rival {
|
||||
inner: Eager,
|
||||
fault: Fault,
|
||||
seen: usize,
|
||||
}
|
||||
|
||||
impl Rival {
|
||||
fn over(inner: Eager, fault: Fault) -> Self {
|
||||
Rival {
|
||||
inner,
|
||||
fault,
|
||||
seen: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn of(fault: Fault) -> Self {
|
||||
Self::over(hand_eager(), fault)
|
||||
}
|
||||
}
|
||||
|
||||
impl Derived for Rival {
|
||||
fn value(&self, k: &CellKey, agg: Aggregation) -> Option<CellValue> {
|
||||
let wrong = match self.fault {
|
||||
Fault::WrongFoldedFormula => {
|
||||
*k == partial("A", "Profit") && agg == Aggregation::OverHidden
|
||||
}
|
||||
Fault::WrongWhenTwoAreDropped => *k == only_revenue(),
|
||||
Fault::WrongOnAGroup => *k == coastal() && agg == Aggregation::Exact,
|
||||
_ => false,
|
||||
};
|
||||
match (wrong, self.fault) {
|
||||
(true, _) => num(-999.0),
|
||||
(_, Fault::IgnoresAggregation) => self.inner.value(k, Aggregation::Exact),
|
||||
_ => self.inner.value(k, agg),
|
||||
}
|
||||
}
|
||||
|
||||
fn raw_fold(&self, p: &CellKey) -> Option<CellValue> {
|
||||
match self.fault {
|
||||
Fault::WrongWhenTwoAreDropped if *p == only_revenue() => num(-999.0),
|
||||
Fault::RawFoldReturnsFormula => self.inner.value(p, Aggregation::OverHidden),
|
||||
_ => self.inner.raw_fold(p),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Maintained for Rival {
|
||||
fn apply(&mut self, edit: &Edit) {
|
||||
self.seen += 1;
|
||||
let skip = match (self.fault, edit) {
|
||||
(Fault::IgnoresMeasureAggregation, Edit::SetMeasureAgg { .. }) => true,
|
||||
(Fault::GoesStaleAfterTwoEdits, _) => self.seen > 2,
|
||||
(Fault::IgnoresClear, Edit::ClearCell(_)) => true,
|
||||
(Fault::IgnoresRemoveFormula, Edit::RemoveFormula { .. }) => true,
|
||||
_ => false,
|
||||
};
|
||||
if !skip {
|
||||
self.inner.apply(edit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn only_revenue() -> CellKey {
|
||||
CellKey::new(vec![("_Measure".into(), "Revenue".into())])
|
||||
}
|
||||
|
||||
fn measure_of(probe: &Probe) -> Option<&str> {
|
||||
match probe {
|
||||
Probe::Value(k, _) | Probe::RawFold(k) => k.get("_Measure"),
|
||||
}
|
||||
}
|
||||
|
||||
fn run_rival(fault: Fault) -> Result<improvise_incremental::Report, Divergence> {
|
||||
differential(
|
||||
&hand_model(),
|
||||
&["Region".to_string()],
|
||||
Rival::of(fault),
|
||||
&hand_edits(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_harness_passes_a_backend_that_is_right() {
|
||||
let report = differential(
|
||||
&hand_model(),
|
||||
&["Region".to_string()],
|
||||
hand_eager(),
|
||||
&hand_edits(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(report.steps, hand_edits().len() + 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_harness_catches_a_backend_that_ignores_the_aggregation() {
|
||||
let d = run_rival(Fault::IgnoresAggregation).unwrap_err();
|
||||
assert_eq!(d.step, 0);
|
||||
assert_eq!(
|
||||
d.probe,
|
||||
Probe::Value(key("East", "A", "Profit"), Aggregation::OverHidden)
|
||||
);
|
||||
assert_eq!((d.eager, d.candidate), (None, num(6.0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_harness_catches_a_backend_that_ignores_the_measure_aggregation() {
|
||||
let d = run_rival(Fault::IgnoresMeasureAggregation).unwrap_err();
|
||||
assert_eq!(d.step, 2, "{d}");
|
||||
assert_eq!(measure_of(&d.probe), Some("Revenue"), "{d}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_harness_catches_a_backend_that_goes_stale_after_two_edits() {
|
||||
let d = run_rival(Fault::GoesStaleAfterTwoEdits).unwrap_err();
|
||||
assert_eq!(d.step, 3, "{d}");
|
||||
assert_eq!(measure_of(&d.probe), Some("Revenue"), "{d}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_harness_catches_a_backend_that_ignores_a_clear() {
|
||||
let d = run_rival(Fault::IgnoresClear).unwrap_err();
|
||||
assert_eq!(d.step, 3, "{d}");
|
||||
assert_eq!(measure_of(&d.probe), Some("Revenue"), "{d}");
|
||||
assert!(d.to_string().starts_with("divergence at step 3:"), "{d}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_harness_catches_a_wrong_folded_formula_value() {
|
||||
let d = run_rival(Fault::WrongFoldedFormula).unwrap_err();
|
||||
assert_eq!(d.step, 0);
|
||||
assert_eq!(
|
||||
d.probe,
|
||||
Probe::Value(partial("A", "Profit"), Aggregation::OverHidden)
|
||||
);
|
||||
assert_eq!((d.eager, d.candidate), (num(9.0), num(-999.0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_harness_catches_a_backend_that_keeps_answering_for_a_removed_formula() {
|
||||
let d = run_rival(Fault::IgnoresRemoveFormula).unwrap_err();
|
||||
assert_eq!(d.step, hand_edits().len(), "{d}");
|
||||
assert_eq!(measure_of(&d.probe), Some("Profit"), "{d}");
|
||||
assert!(d.eager.is_none() && d.candidate.is_some(), "{d}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_harness_catches_a_fault_that_only_shows_after_two_coordinates_are_dropped() {
|
||||
let d = run_rival(Fault::WrongWhenTwoAreDropped).unwrap_err();
|
||||
assert_eq!(d.step, 0);
|
||||
assert_eq!(d.probe, Probe::Value(only_revenue(), Aggregation::Exact));
|
||||
assert_eq!(d.candidate, num(-999.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_harness_catches_a_raw_fold_that_returns_a_formula() {
|
||||
let d = run_rival(Fault::RawFoldReturnsFormula).unwrap_err();
|
||||
assert_eq!(d.step, 0);
|
||||
assert!(matches!(d.probe, Probe::RawFold(_)), "{d}");
|
||||
assert_eq!(measure_of(&d.probe), Some("Profit"), "{d}");
|
||||
assert!(d.eager.is_none() && d.candidate.is_some(), "{d}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_harness_catches_a_wrong_group_fold() {
|
||||
let eager = Eager::new(grouped_model(), vec![]);
|
||||
let d = differential(
|
||||
&grouped_model(),
|
||||
&[],
|
||||
Rival::over(eager, Fault::WrongOnAGroup),
|
||||
&[],
|
||||
)
|
||||
.unwrap_err();
|
||||
assert_eq!(d.probe, Probe::Value(coastal(), Aggregation::Exact));
|
||||
assert_eq!((d.eager, d.candidate), (num(15.0), num(-999.0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_folds_a_group_it_is_asked_about() {
|
||||
let eager = Eager::new(grouped_model(), vec![]);
|
||||
assert_eq!(eager.value(&coastal(), Aggregation::Exact), num(15.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_raw_fold_is_never_a_formula() {
|
||||
let eager = hand_eager();
|
||||
assert_eq!(
|
||||
eager.value(&partial("A", "Profit"), Aggregation::OverHidden),
|
||||
num(9.0)
|
||||
);
|
||||
assert_eq!(eager.raw_fold(&partial("A", "Profit")), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_add_and_remove_formula_change_what_a_key_reads() {
|
||||
let mut eager = hand_eager();
|
||||
let k = key("East", "A", "Double");
|
||||
assert_eq!(eager.value(&k, Aggregation::Exact), None);
|
||||
eager.apply(&Edit::AddFormula(
|
||||
parse_formula("Double = Revenue * 2", "_Measure").unwrap(),
|
||||
));
|
||||
assert_eq!(eager.value(&k, Aggregation::Exact), num(20.0));
|
||||
eager.apply(&Edit::RemoveFormula {
|
||||
target: "Double".into(),
|
||||
target_category: "_Measure".into(),
|
||||
});
|
||||
assert_eq!(eager.value(&k, Aggregation::Exact), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_clear_cell_leaves_the_key_absent() {
|
||||
let mut eager = hand_eager();
|
||||
let k = key("East", "A", "Revenue");
|
||||
eager.apply(&Edit::ClearCell(k.clone()));
|
||||
assert_eq!(eager.value(&k, Aggregation::Exact), None);
|
||||
assert_eq!(eager.model().get_cell(&k), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn same_value_follows_the_float_rules_and_is_exact_elsewhere() {
|
||||
let n = |x: f64| num(x);
|
||||
assert!(same_value(&n(f64::NAN), &n(f64::NAN)));
|
||||
assert!(same_value(&n(-0.0), &n(0.0)));
|
||||
assert!(!same_value(&n(1.0), &n(1.000_000_000_000_000_2)));
|
||||
assert!(!same_value(&n(1.0), &n(f64::NAN)));
|
||||
assert!(same_value(&text("a"), &text("a")));
|
||||
assert!(!same_value(&text("a"), &text("b")));
|
||||
let err = |s: &str| Some(CellValue::Error(s.into()));
|
||||
assert!(same_value(&err("mixed"), &err("mixed")));
|
||||
assert!(!same_value(&err("mixed"), &err("circular")));
|
||||
assert!(!same_value(&None, &n(0.0)));
|
||||
assert!(same_value(&None, &None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn probes_cover_folds_formulas_measures_and_groups() {
|
||||
let hand = probes(&hand_model());
|
||||
let has = |p: Probe| hand.contains(&p);
|
||||
assert!(has(Probe::RawFold(partial("A", "Revenue"))));
|
||||
assert!(has(Probe::Value(
|
||||
key("East", "A", "Revenue"),
|
||||
Aggregation::Exact
|
||||
)));
|
||||
assert!(has(Probe::Value(
|
||||
partial("A", "Profit"),
|
||||
Aggregation::Exact
|
||||
)));
|
||||
assert!(has(Probe::Value(
|
||||
partial("A", "Profit"),
|
||||
Aggregation::OverHidden
|
||||
)));
|
||||
assert!(has(Probe::Value(only_revenue(), Aggregation::OverHidden)));
|
||||
assert!(has(Probe::RawFold(CellKey::new(vec![]))));
|
||||
let grouped = probes(&grouped_model());
|
||||
assert!(grouped.contains(&Probe::Value(coastal(), Aggregation::Exact)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_edit_names_its_key_as_two_value_probes_and_a_fold() {
|
||||
let k = key("East", "A", "Revenue");
|
||||
let asked = improvise_incremental::edit_probes(&Edit::ClearCell(k.clone()));
|
||||
assert!(asked.contains(&Probe::Value(k.clone(), Aggregation::Exact)));
|
||||
assert!(asked.contains(&Probe::Value(k.clone(), Aggregation::OverHidden)));
|
||||
assert!(asked.contains(&Probe::RawFold(k)));
|
||||
let none = improvise_incremental::edit_probes(&Edit::SetMeasureAgg {
|
||||
measure: "Revenue".into(),
|
||||
func: AggFunc::Max,
|
||||
});
|
||||
assert!(none.is_empty());
|
||||
}
|
||||
|
||||
/// An `Eager` rebuilt from scratch on every edit: maintaining one in place
|
||||
/// must give the same answers as building it afresh.
|
||||
struct Fresh {
|
||||
model: Model,
|
||||
none: Vec<String>,
|
||||
eager: Eager,
|
||||
}
|
||||
|
||||
impl Derived for Fresh {
|
||||
fn value(&self, k: &CellKey, agg: Aggregation) -> Option<CellValue> {
|
||||
self.eager.value(k, agg)
|
||||
}
|
||||
|
||||
fn raw_fold(&self, p: &CellKey) -> Option<CellValue> {
|
||||
self.eager.raw_fold(p)
|
||||
}
|
||||
}
|
||||
|
||||
impl Maintained for Fresh {
|
||||
fn apply(&mut self, edit: &Edit) {
|
||||
edit.apply(&mut self.model);
|
||||
self.eager = Eager::new(self.model.clone(), self.none.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn any_key() -> impl Strategy<Value = CellKey> {
|
||||
(
|
||||
prop::sample::select(vec!["East", "West"]),
|
||||
prop::sample::select(vec!["A", "B"]),
|
||||
prop::sample::select(vec!["Revenue", "Cost", "Note"]),
|
||||
)
|
||||
.prop_map(|(r, p, m)| key(r, p, m))
|
||||
}
|
||||
|
||||
fn any_value() -> impl Strategy<Value = CellValue> {
|
||||
prop_oneof![
|
||||
(-4i32..5).prop_map(|n| CellValue::Number(f64::from(n))),
|
||||
Just(CellValue::Number(-0.0)),
|
||||
prop::sample::select(vec!["n", "x"]).prop_map(|t| CellValue::Text(t.into())),
|
||||
]
|
||||
}
|
||||
|
||||
fn any_edit() -> impl Strategy<Value = Edit> {
|
||||
prop_oneof![
|
||||
(any_key(), any_value()).prop_map(|(k, v)| Edit::SetCell(k, v)),
|
||||
any_key().prop_map(Edit::ClearCell),
|
||||
prop::sample::select(vec!["Profit = Revenue - Cost", "Double = Revenue * 2"])
|
||||
.prop_map(|raw| Edit::AddFormula(parse_formula(raw, "_Measure").unwrap())),
|
||||
prop::sample::select(vec!["Profit", "Double"]).prop_map(|t| Edit::RemoveFormula {
|
||||
target: t.into(),
|
||||
target_category: "_Measure".into(),
|
||||
}),
|
||||
(
|
||||
prop::sample::select(vec!["Revenue", "Cost"]),
|
||||
prop::sample::select(vec![AggFunc::Sum, AggFunc::Max, AggFunc::Min, AggFunc::Avg]),
|
||||
)
|
||||
.prop_map(|(m, func)| Edit::SetMeasureAgg {
|
||||
measure: m.into(),
|
||||
func,
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn a_maintained_eager_equals_a_fresh_one_over_random_edit_sequences(
|
||||
edits in prop::collection::vec(any_edit(), 0..4)
|
||||
) {
|
||||
let model = hand_model();
|
||||
let none = vec!["Region".to_string()];
|
||||
let fresh = Fresh {
|
||||
model: model.clone(),
|
||||
none: none.clone(),
|
||||
eager: Eager::new(model.clone(), none.clone()),
|
||||
};
|
||||
let run = differential(&model, &none, fresh, &edits);
|
||||
prop_assert!(run.is_ok(), "{}", run.unwrap_err());
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,8 @@ chrono = { version = "0.4", features = ["serde"] }
|
||||
csv = "1"
|
||||
flate2 = "1"
|
||||
indexmap = "2"
|
||||
pest = "2.9.2"
|
||||
pest_derive = "2.9.2"
|
||||
pest = "2.9.3"
|
||||
pest_derive = "2.9.3"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
# Parses JSON a user's numbers cross, so it must read back the f64 written: per crate,
|
||||
# because each build stands alone (improvise-6yvg, context/code/protocol.md).
|
||||
@@ -47,6 +47,6 @@ features = [
|
||||
]
|
||||
|
||||
[dev-dependencies]
|
||||
pest_meta = "2.9.2"
|
||||
pest_meta = "2.9.3"
|
||||
proptest = "1"
|
||||
tempfile = "3"
|
||||
|
||||
Generated
+12
-12
@@ -47,11 +47,11 @@
|
||||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
"lastModified": 1789760033,
|
||||
"narHash": "sha256-jtT4yxZpR8seYnlCMMWSSPlFN92zO6ICuZ8pJrmi86k=",
|
||||
"lastModified": 1790899423,
|
||||
"narHash": "sha256-THGtz65UGJU+sonZidRboyCMk+9DclpMF7pwL4uDV4M=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "73b980519cefc727a5f6cc8e5c0947a2f9be6edd",
|
||||
"rev": "47b6b27ed9a3a9181415e4367d0c30ab2a0e0250",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -71,11 +71,11 @@
|
||||
"pre-commit-hooks": "pre-commit-hooks"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1782759041,
|
||||
"narHash": "sha256-2577vxyoBa8+ZRiXr3CuPtOuEtPRYsFPSZuEc/KI/80=",
|
||||
"lastModified": 1790579054,
|
||||
"narHash": "sha256-S2NrwKB7aQa6HZsg2UGCmzQPI5Dw+bqUPm8R23BAUh8=",
|
||||
"owner": "nix-community",
|
||||
"repo": "crate2nix",
|
||||
"rev": "5e1ecfd2d15b34ec90c2e51fdffbe8116595a767",
|
||||
"rev": "1cb60331b14f15dad145dbd4e207c1ec110e5675",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -297,11 +297,11 @@
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1790185690,
|
||||
"narHash": "sha256-xJ+X4hBtOcAFGBOe5nAMyMUeF9foJBmIOu3NjBqBycU=",
|
||||
"lastModified": 1791456040,
|
||||
"narHash": "sha256-H83yz/do+hjOO0uujHyH8RgtIQP2v7Mw+cLwcZK/xKc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4975466d324710c576dc11ad614684e6bd8cad8e",
|
||||
"rev": "e7439b6b14ad3cc35d05608ebca9bce01a25f5f8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -368,11 +368,11 @@
|
||||
"nixpkgs": "nixpkgs_5"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1790234952,
|
||||
"narHash": "sha256-tjQa1vDoHJir4lasZTakz/xgmsfB6SRjeQqaIbefFOk=",
|
||||
"lastModified": 1791535654,
|
||||
"narHash": "sha256-QFgGi6Wgh7AgqPFdAXEmkTgnR0B5M0omheIHvo/02dU=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "ed34466c59b766481248959a21a6e46cf0c60468",
|
||||
"rev": "4ca2963243427cb86bd6b4d9ca6010db0162a619",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -121,8 +121,10 @@
|
||||
pkgs.rust-analyzer
|
||||
crate2nix.packages.${system}.default
|
||||
pkgs.cargo-expand
|
||||
pkgs.cargo-edit
|
||||
pkgs.cargo-llvm-cov
|
||||
pkgs.global
|
||||
pkgs.iconv
|
||||
pkgs.universal-ctags
|
||||
beads.packages.${system}.default
|
||||
codeMaat
|
||||
|
||||
Generated
+44
-11
@@ -307,19 +307,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.9.2"
|
||||
version = "2.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45d3aca230fad2e6f6317ca0a72724338c4960cb97168a85cdee66df4a9a21a8"
|
||||
checksum = "b568374ba38b33a6c627141f891faf16902b08d2db26b8ede1bcb0a15b1919fa"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"psm",
|
||||
"stacker",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.9.2"
|
||||
version = "2.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "284b60557f2c4a2e72ad3f2d34d42685a2fa4a6a61d0d2a10c0ae2a5e916c2cf"
|
||||
checksum = "b66e184b924cebaaff20ab2256ca52f12332d528a39aa76553b5d96f92aacf7f"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
@@ -327,22 +329,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.9.2"
|
||||
version = "2.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d9d1f08a115309ee99268cf85e5228e0e56aa9caf8841ec12866b6be07c3109"
|
||||
checksum = "a87478d267e4de54a626af9754f2f0f58e927aac6ed0575fe89bc05ad6851694"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
"syn 3.0.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.9.2"
|
||||
version = "2.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed93ba1a9ffcca32130a5188701c81c0c49cf00d4b7c5007d5148951d743adcb"
|
||||
checksum = "4f986f248b4241ac359b831f6139aaa34e03b08a37b6caf7e201a33f95c869e1"
|
||||
dependencies = [
|
||||
"pest",
|
||||
]
|
||||
@@ -362,6 +364,15 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psm"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.47"
|
||||
@@ -450,6 +461,19 @@ version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "stacker"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "707f49d46706bacf8a2b00d51dace3f9de527c13eec3778f570c411f89e69967"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"psm",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.119"
|
||||
@@ -489,9 +513,9 @@ checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.9.0"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
|
||||
checksum = "357cc3acc6a036009fd6c973ed009037c732d60d0b4f6c673e9041497482a28f"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
@@ -624,6 +648,15 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zlib-rs"
|
||||
version = "0.6.8"
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
"numtower"
|
||||
# ADR 009 clause 1: std-only; nothing depends on it yet.
|
||||
"zset"
|
||||
# ADR 009 clause 2: the Derived trait, Eager and the differential harness.
|
||||
"improvise-incremental"
|
||||
];
|
||||
pFlags = crates: lib.concatMapStringsSep " " (c: "-p ${c}") crates;
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ const SECTIONS = [
|
||||
["context/code/gp.md", "code/gp", "gp-tree and improvise-gp"],
|
||||
["context/code/numtower.md", "code/numtower", "numtower, the numeric tower"],
|
||||
["context/code/zset.md", "code/zset", "zset, the Z-set group"],
|
||||
["context/code/improvise-incremental.md", "code/improvise-incremental", "improvise-incremental, the plug"],
|
||||
["context/code/kb-tool.md", "code/kb-tool", "The kb tool"],
|
||||
["context/code/tooling.md", "code/tooling", "The repository's own checkers"],
|
||||
],
|
||||
@@ -89,6 +90,7 @@ const SECTIONS = [
|
||||
["context/test-evidence/gp.md", "test-evidence/gp", "gp-tree and improvise-gp"],
|
||||
["context/test-evidence/numtower.md", "test-evidence/numtower", "numtower"],
|
||||
["context/test-evidence/zset.md", "test-evidence/zset", "zset"],
|
||||
["context/test-evidence/improvise-incremental.md", "test-evidence/improvise-incremental", "improvise-incremental"],
|
||||
["context/test-evidence/tooling.md", "test-evidence/tooling", "The repository's own gates"],
|
||||
["context/test-evidence/layout-cost.md", "test-evidence/layout-cost", "Layout and keypress cost"],
|
||||
["context/test-evidence/scale-bisect.md", "test-evidence/scale-bisect", "Scale bisect"],
|
||||
|
||||
Reference in New Issue
Block a user