@@ -14,7 +14,7 @@ version = "0.1.0"
dependencies = [
"auto_update",
"editor",
- "futures 0.3.25",
+ "futures 0.3.28",
"gpui",
"language",
"project",
@@ -30,7 +30,16 @@ version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [
- "gimli",
+ "gimli 0.26.2",
+]
+
+[[package]]
+name = "addr2line"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
+dependencies = [
+ "gimli 0.27.2",
]
[[package]]
@@ -51,7 +60,18 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
- "getrandom 0.2.8",
+ "getrandom 0.2.9",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "ahash"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
+dependencies = [
+ "cfg-if 1.0.0",
"once_cell",
"version_check",
]
@@ -65,6 +85,15 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "aho-corasick"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "alacritty_config"
version = "0.1.1-dev"
@@ -82,7 +111,7 @@ source = "git+https://github.com/zed-industries/alacritty?rev=a51dbe25d67e84d6ed
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
]
[[package]]
@@ -92,7 +121,7 @@ source = "git+https://github.com/zed-industries/alacritty?rev=a51dbe25d67e84d6ed
dependencies = [
"alacritty_config",
"alacritty_config_derive",
- "base64",
+ "base64 0.13.1",
"bitflags",
"dirs 4.0.0",
"libc",
@@ -145,15 +174,15 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.66"
+version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "arrayref"
-version = "0.3.6"
+version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
+checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
[[package]]
name = "arrayvec"
@@ -232,9 +261,9 @@ dependencies = [
[[package]]
name = "async-executor"
-version = "1.5.0"
+version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b"
+checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb"
dependencies = [
"async-lock",
"async-task",
@@ -273,32 +302,31 @@ dependencies = [
[[package]]
name = "async-io"
-version = "1.12.0"
+version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794"
+checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
dependencies = [
"async-lock",
"autocfg 1.1.0",
+ "cfg-if 1.0.0",
"concurrent-queue",
"futures-lite",
- "libc",
"log",
"parking",
"polling",
+ "rustix 0.37.19",
"slab",
"socket2",
"waker-fn",
- "windows-sys 0.42.0",
]
[[package]]
name = "async-lock"
-version = "2.6.0"
+version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685"
+checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7"
dependencies = [
"event-listener",
- "futures-lite",
]
[[package]]
@@ -318,15 +346,15 @@ name = "async-pipe"
version = "0.1.3"
source = "git+https://github.com/zed-industries/async-pipe-rs?rev=82d00a04211cf4e1236029aa03e6b6ce2a74c553#82d00a04211cf4e1236029aa03e6b6ce2a74c553"
dependencies = [
- "futures 0.3.25",
+ "futures 0.3.28",
"log",
]
[[package]]
name = "async-process"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4"
+checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9"
dependencies = [
"async-io",
"async-lock",
@@ -335,9 +363,9 @@ dependencies = [
"cfg-if 1.0.0",
"event-listener",
"futures-lite",
- "libc",
+ "rustix 0.37.19",
"signal-hook",
- "windows-sys 0.42.0",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -348,18 +376,18 @@ checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
]
[[package]]
name = "async-recursion"
-version = "1.0.0"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea"
+checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.15",
]
[[package]]
@@ -372,7 +400,7 @@ dependencies = [
"async-global-executor",
"async-io",
"async-lock",
- "crossbeam-utils 0.8.14",
+ "crossbeam-utils 0.8.15",
"futures-channel",
"futures-core",
"futures-io",
@@ -390,23 +418,24 @@ dependencies = [
[[package]]
name = "async-stream"
-version = "0.3.3"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e"
+checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
dependencies = [
"async-stream-impl",
"futures-core",
+ "pin-project-lite 0.2.9",
]
[[package]]
name = "async-stream-impl"
-version = "0.3.3"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
+checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.15",
]
[[package]]
@@ -419,7 +448,7 @@ dependencies = [
"filetime",
"libc",
"pin-project",
- "redox_syscall",
+ "redox_syscall 0.2.16",
"xattr",
]
@@ -443,13 +472,13 @@ dependencies = [
[[package]]
name = "async-trait"
-version = "0.1.59"
+version = "0.1.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
+checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.15",
]
[[package]]
@@ -486,9 +515,9 @@ dependencies = [
[[package]]
name = "atomic-waker"
-version = "1.0.0"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
+checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
[[package]]
name = "atty"
@@ -548,9 +577,9 @@ checksum = "acee9fd5073ab6b045a275b3e709c163dd36c90685219cb21804a147b58dba43"
dependencies = [
"async-trait",
"axum-core",
- "base64",
+ "base64 0.13.1",
"bitflags",
- "bytes 1.3.0",
+ "bytes 1.4.0",
"futures-util",
"headers",
"http",
@@ -582,7 +611,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc"
dependencies = [
"async-trait",
- "bytes 1.3.0",
+ "bytes 1.4.0",
"futures-util",
"http",
"http-body",
@@ -598,7 +627,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69034b3b0fd97923eee2ce8a47540edb21e07f48f87f67d44bb4271cec622bdb"
dependencies = [
"axum",
- "bytes 1.3.0",
+ "bytes 1.4.0",
"futures-util",
"http",
"mime",
@@ -614,16 +643,16 @@ dependencies = [
[[package]]
name = "backtrace"
-version = "0.3.66"
+version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
+checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
dependencies = [
- "addr2line",
+ "addr2line 0.19.0",
"cc",
"cfg-if 1.0.0",
"libc",
- "miniz_oxide 0.5.4",
- "object 0.29.0",
+ "miniz_oxide 0.6.2",
+ "object 0.30.3",
"rustc-demangle",
]
@@ -637,7 +666,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
]
[[package]]
@@ -646,11 +675,17 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+[[package]]
+name = "base64"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+
[[package]]
name = "base64ct"
-version = "1.5.3"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
+checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bincode"
@@ -671,7 +706,7 @@ dependencies = [
"cexpr",
"clang-sys",
"clap 2.34.0",
- "env_logger",
+ "env_logger 0.9.3",
"lazy_static",
"lazycell",
"log",
@@ -707,18 +742,18 @@ dependencies = [
[[package]]
name = "block-buffer"
-version = "0.10.3"
+version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "blocking"
-version = "1.3.0"
+version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8"
+checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65"
dependencies = [
"async-channel",
"async-lock",
@@ -726,51 +761,52 @@ dependencies = [
"atomic-waker",
"fastrand",
"futures-lite",
+ "log",
]
[[package]]
name = "borsh"
-version = "0.9.3"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa"
+checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b"
dependencies = [
"borsh-derive",
- "hashbrown 0.11.2",
+ "hashbrown 0.13.2",
]
[[package]]
name = "borsh-derive"
-version = "0.9.3"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775"
+checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7"
dependencies = [
"borsh-derive-internal",
"borsh-schema-derive-internal",
"proc-macro-crate",
"proc-macro2",
- "syn",
+ "syn 1.0.109",
]
[[package]]
name = "borsh-derive-internal"
-version = "0.9.3"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065"
+checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
]
[[package]]
name = "borsh-schema-derive-internal"
-version = "0.9.3"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0"
+checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
]
[[package]]
@@ -803,45 +839,47 @@ dependencies = [
[[package]]
name = "bstr"
-version = "0.2.17"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
+checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09"
dependencies = [
"memchr",
+ "serde",
]
[[package]]
name = "bumpalo"
-version = "3.11.1"
+version = "3.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
+checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b"
[[package]]
name = "bytecheck"
-version = "0.6.9"
+version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d11cac2c12b5adc6570dad2ee1b87eff4955dac476fe12d81e5fdd352e52406f"
+checksum = "13fe11640a23eb24562225322cd3e452b93a3d4091d62fab69c70542fcd17d1f"
dependencies = [
"bytecheck_derive",
"ptr_meta",
+ "simdutf8",
]
[[package]]
name = "bytecheck_derive"
-version = "0.6.9"
+version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf"
+checksum = "e31225543cb46f81a7e224762764f4a6a0f097b1db0b175f69e8065efaa42de5"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
]
[[package]]
name = "bytemuck"
-version = "1.12.3"
+version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f"
+checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
[[package]]
name = "byteorder"
@@ -861,9 +899,9 @@ dependencies = [
[[package]]
name = "bytes"
-version = "1.3.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]]
name = "call"
@@ -874,7 +912,7 @@ dependencies = [
"client",
"collections",
"fs",
- "futures 0.3.25",
+ "futures 0.3.28",
"gpui",
"language",
"live_kit_client",
@@ -894,7 +932,7 @@ checksum = "e54b86398b5852ddd45784b1d9b196b98beb39171821bad4b8b44534a1e87927"
dependencies = [
"cap-primitives",
"cap-std",
- "io-lifetimes",
+ "io-lifetimes 0.5.3",
"winapi 0.3.9",
]
@@ -905,13 +943,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb8fca3e81fae1d91a36e9784ca22a39ef623702b5f7904d89dc31f10184a178"
dependencies = [
"ambient-authority",
- "errno",
+ "errno 0.2.8",
"fs-set-times",
"io-extras",
- "io-lifetimes",
+ "io-lifetimes 0.5.3",
"ipnet",
"maybe-owned",
- "rustix",
+ "rustix 0.33.7",
"winapi 0.3.9",
"winapi-util",
"winx",
@@ -935,9 +973,9 @@ checksum = "2247568946095c7765ad2b441a56caffc08027734c634a6d5edda648f04e32eb"
dependencies = [
"cap-primitives",
"io-extras",
- "io-lifetimes",
+ "io-lifetimes 0.5.3",
"ipnet",
- "rustix",
+ "rustix 0.33.7",
]
[[package]]
@@ -948,7 +986,7 @@ checksum = "c50472b6ebc302af0401fa3fb939694cd8ff00e0d4c9182001e434fc822ab83a"
dependencies = [
"cap-primitives",
"once_cell",
- "rustix",
+ "rustix 0.33.7",
"winx",
]
@@ -960,9 +998,9 @@ checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6"
[[package]]
name = "cc"
-version = "1.0.77"
+version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
dependencies = [
"jobserver",
]
@@ -990,9 +1028,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-version = "0.4.23"
+version = "0.4.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
+checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
dependencies = [
"iana-time-zone",
"js-sys",
@@ -1006,9 +1044,9 @@ dependencies = [
[[package]]
name = "chunked_transfer"
-version = "1.4.0"
+version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
+checksum = "cca491388666e04d7248af3f60f0c40cfb0991c72205595d7c396e3510207d1a"
[[package]]
name = "cipher"
@@ -1021,9 +1059,9 @@ dependencies = [
[[package]]
name = "clang-sys"
-version = "1.4.0"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3"
+checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
dependencies = [
"glob",
"libc",
@@ -1047,9 +1085,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "3.2.23"
+version = "3.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
+checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
dependencies = [
"atty",
"bitflags",
@@ -1064,15 +1102,15 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "3.2.18"
+version = "3.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
+checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008"
dependencies = [
- "heck 0.4.0",
+ "heck 0.4.1",
"proc-macro-error",
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.109",
]
[[package]]
@@ -1089,7 +1127,7 @@ name = "cli"
version = "0.1.0"
dependencies = [
"anyhow",
- "clap 3.2.23",
+ "clap 3.2.25",
"core-foundation",
"core-services",
"dirs 3.0.2",
@@ -1108,7 +1146,7 @@ dependencies = [
"async-tungstenite",
"collections",
"db",
- "futures 0.3.25",
+ "futures 0.3.28",
"gpui",
"image",
"lazy_static",
@@ -1125,11 +1163,11 @@ dependencies = [
"sum_tree",
"tempfile",
"thiserror",
- "time 0.3.17",
+ "time 0.3.21",
"tiny_http",
"url",
"util",
- "uuid 1.2.2",
+ "uuid 1.3.2",
]
[[package]]
@@ -1141,9 +1179,9 @@ dependencies = [
[[package]]
name = "cmake"
-version = "0.1.49"
+version = "0.1.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c"
+checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
dependencies = [
"cc",
]
@@ -1195,18 +1233,18 @@ dependencies = [
"async-tungstenite",
"axum",
"axum-extra",
- "base64",
+ "base64 0.13.1",
"call",
- "clap 3.2.23",
+ "clap 3.2.25",
"client",
"collections",
"ctor",
"dashmap",
"editor",
- "env_logger",
+ "env_logger 0.9.3",
"envy",
"fs",
- "futures 0.3.25",
+ "futures 0.3.28",
"git",
"gpui",
"hyper",
@@ -1236,7 +1274,7 @@ dependencies = [
"sha-1 0.9.8",
"sqlx",
"theme",
- "time 0.3.17",
+ "time 0.3.21",
"tokio",
"tokio-tungstenite",
"toml",
@@ -1263,7 +1301,7 @@ dependencies = [
"context_menu",
"editor",
"feedback",
- "futures 0.3.25",
+ "futures 0.3.28",
"fuzzy",
"gpui",
"log",
@@ -1299,7 +1337,7 @@ dependencies = [
"collections",
"ctor",
"editor",
- "env_logger",
+ "env_logger 0.9.3",
"fuzzy",
"gpui",
"picker",
@@ -1313,11 +1351,11 @@ dependencies = [
[[package]]
name = "concurrent-queue"
-version = "2.0.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b"
+checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c"
dependencies = [
- "crossbeam-utils 0.8.14",
+ "crossbeam-utils 0.8.15",
]
[[package]]
@@ -1342,7 +1380,7 @@ dependencies = [
"collections",
"context_menu",
"fs",
- "futures 0.3.25",
+ "futures 0.3.28",
"gpui",
"language",
"log",
@@ -1366,7 +1404,7 @@ dependencies = [
"context_menu",
"copilot",
"editor",
- "futures 0.3.25",
+ "futures 0.3.28",
"gpui",
"settings",
"smol",
@@ -1445,9 +1483,9 @@ dependencies = [
[[package]]
name = "cpufeatures"
-version = "0.2.5"
+version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
+checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58"
dependencies = [
"libc",
]
@@ -1472,7 +1510,7 @@ dependencies = [
"cranelift-codegen-shared",
"cranelift-entity",
"cranelift-isle",
- "gimli",
+ "gimli 0.26.2",
"log",
"regalloc2",
"smallvec",
@@ -1550,18 +1588,18 @@ dependencies = [
[[package]]
name = "crc"
-version = "3.0.0"
+version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3"
+checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe"
dependencies = [
"crc-catalog",
]
[[package]]
name = "crc-catalog"
-version = "2.1.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff"
+checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484"
[[package]]
name = "crc32fast"
@@ -1584,35 +1622,35 @@ dependencies = [
[[package]]
name = "crossbeam-channel"
-version = "0.5.6"
+version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
dependencies = [
"cfg-if 1.0.0",
- "crossbeam-utils 0.8.14",
+ "crossbeam-utils 0.8.15",
]
[[package]]
name = "crossbeam-deque"
-version = "0.8.2"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-epoch",
- "crossbeam-utils 0.8.14",
+ "crossbeam-utils 0.8.15",
]
[[package]]
name = "crossbeam-epoch"
-version = "0.9.13"
+version = "0.9.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
+checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
dependencies = [
"autocfg 1.1.0",
"cfg-if 1.0.0",
- "crossbeam-utils 0.8.14",
- "memoffset 0.7.1",
+ "crossbeam-utils 0.8.15",
+ "memoffset 0.8.0",
"scopeguard",
]
@@ -1623,7 +1661,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
dependencies = [
"cfg-if 1.0.0",
- "crossbeam-utils 0.8.14",
+ "crossbeam-utils 0.8.15",
]
[[package]]
@@ -1639,9 +1677,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
-version = "0.8.14"
+version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
+checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if 1.0.0",
]
@@ -1673,7 +1711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
dependencies = [
"quote",
- "syn",
+ "syn 1.0.109",
]
[[package]]
@@ -1693,9 +1731,9 @@ dependencies = [
[[package]]
name = "curl-sys"
-version = "0.4.59+curl-7.86.0"
+version = "0.4.61+curl-8.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6cfce34829f448b08f55b7db6d0009e23e2e86a34e8c2b366269bf5799b4a407"
+checksum = "14d05c10f541ae6f3bc5b3d923c20001f47db7d5f0b2bc6ad16490133842db79"
dependencies = [
"cc",
"libc",
@@ -1709,9 +1747,9 @@ dependencies = [
[[package]]
name = "cxx"
-version = "1.0.83"
+version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf"
+checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93"
dependencies = [
"cc",
"cxxbridge-flags",
@@ -1721,9 +1759,9 @@ dependencies = [
[[package]]
name = "cxx-build"
-version = "1.0.83"
+version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39"
+checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b"
dependencies = [
"cc",
"codespan-reporting",
@@ -1731,24 +1769,24 @@ dependencies = [
"proc-macro2",
"quote",
"scratch",
- "syn",
+ "syn 2.0.15",
]
[[package]]
name = "cxxbridge-flags"
-version = "1.0.83"
+version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12"
+checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb"
[[package]]
name = "cxxbridge-macro"
-version = "1.0.83"
+version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6"
+checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.15",
]
[[package]]
@@ -1761,7 +1799,7 @@ dependencies = [
"hashbrown 0.12.3",
"lock_api",
"once_cell",
- "parking_lot_core 0.9.5",
+ "parking_lot_core 0.9.7",
]
[[package]]
@@ -1780,7 +1818,7 @@ dependencies = [
"anyhow",
"async-trait",
"collections",
- "env_logger",
+ "env_logger 0.9.3",
"gpui",
"indoc",
"lazy_static",
@@ -1864,7 +1902,7 @@ version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
- "block-buffer 0.10.3",
+ "block-buffer 0.10.4",
"crypto-common",
"subtle",
]
@@ -0,0 +1,608 @@
+use anyhow::{anyhow, Result};
+use collections::{hash_map, BTreeMap, HashMap, HashSet};
+use schemars::JsonSchema;
+use serde::{de::DeserializeOwned, Serialize};
+use serde_json::value::RawValue;
+use smallvec::SmallVec;
+use std::{
+ any::{type_name, Any, TypeId},
+ cmp::Ordering,
+ fmt::Debug,
+ mem,
+ path::Path,
+ sync::Arc,
+};
+use util::{merge_non_null_json_value_into, ResultExt as _};
+
+/// A value that can be defined as a user setting.
+///
+/// Settings can be loaded from a combination of multiple JSON files.
+pub trait Setting: 'static + Debug {
+ /// The name of a field within the JSON file from which this setting should
+ /// be deserialized. If this is `None`, then the setting will be deserialized
+ /// from the root object.
+ const FIELD_NAME: Option<&'static str> = None;
+
+ /// The type that is stored in an individual JSON file.
+ type FileContent: DeserializeOwned + JsonSchema;
+
+ /// The logic for combining together values from one or more JSON files into the
+ /// final value for this setting.
+ ///
+ /// The user values are ordered from least specific (the global settings file)
+ /// to most specific (the innermost local settings file).
+ fn load(default_value: &Self::FileContent, user_values: &[&Self::FileContent]) -> Self;
+
+ fn load_via_json_merge(
+ default_value: &Self::FileContent,
+ user_values: &[&Self::FileContent],
+ ) -> Self
+ where
+ Self: DeserializeOwned,
+ Self::FileContent: Serialize,
+ {
+ let mut merged = serde_json::Value::Null;
+ for value in [default_value].iter().chain(user_values) {
+ merge_non_null_json_value_into(serde_json::to_value(value).unwrap(), &mut merged);
+ }
+ serde_json::from_value(merged).unwrap()
+ }
+}
+
+/// A set of strongly-typed setting values defined via multiple JSON files.
+#[derive(Default)]
+pub struct SettingsStore {
+ setting_keys: Vec<(Option<&'static str>, TypeId)>,
+ setting_values: HashMap<TypeId, Box<dyn AnySettingValue>>,
+ default_deserialized_settings: DeserializedSettingMap,
+ user_deserialized_settings: Option<DeserializedSettingMap>,
+ local_deserialized_settings: BTreeMap<Arc<Path>, DeserializedSettingMap>,
+ changed_setting_types: HashSet<TypeId>,
+}
+
+#[derive(Debug)]
+struct SettingValue<T> {
+ global_value: Option<T>,
+ local_values: Vec<(Arc<Path>, T)>,
+}
+
+trait AnySettingValue: Debug {
+ fn setting_type_name(&self) -> &'static str;
+ fn deserialize_setting(&self, json: &str) -> Result<DeserializedSetting>;
+ fn load_setting(
+ &self,
+ default_value: &DeserializedSetting,
+ custom: &[&DeserializedSetting],
+ ) -> Box<dyn Any>;
+ fn value_for_path(&self, path: Option<&Path>) -> &dyn Any;
+ fn set_global_value(&mut self, value: Box<dyn Any>);
+ fn set_local_value(&mut self, path: Arc<Path>, value: Box<dyn Any>);
+}
+
+struct DeserializedSetting(Box<dyn Any>);
+
+type DeserializedSettingMap = HashMap<TypeId, DeserializedSetting>;
+
+impl SettingsStore {
+ /// Add a new type of setting to the store.
+ ///
+ /// This should be done before any settings are loaded.
+ pub fn register_setting<T: Setting>(&mut self) {
+ let type_id = TypeId::of::<T>();
+
+ let entry = self.setting_values.entry(type_id);
+ if matches!(entry, hash_map::Entry::Occupied(_)) {
+ panic!("duplicate setting type: {}", type_name::<T>());
+ }
+ entry.or_insert(Box::new(SettingValue::<T> {
+ global_value: None,
+ local_values: Vec::new(),
+ }));
+
+ match self
+ .setting_keys
+ .binary_search_by_key(&T::FIELD_NAME, |e| e.0)
+ {
+ Ok(ix) | Err(ix) => self.setting_keys.insert(ix, (T::FIELD_NAME, type_id)),
+ }
+ }
+
+ /// Get the value of a setting.
+ ///
+ /// Panics if settings have not yet been loaded, or there is no default
+ /// value for this setting.
+ pub fn get<T: Setting>(&self, path: Option<&Path>) -> &T {
+ self.setting_values
+ .get(&TypeId::of::<T>())
+ .unwrap()
+ .value_for_path(path)
+ .downcast_ref::<T>()
+ .unwrap()
+ }
+
+ /// Set the default settings via a JSON string.
+ ///
+ /// The string should contain a JSON object with a default value for every setting.
+ pub fn set_default_settings(&mut self, default_settings_content: &str) -> Result<()> {
+ self.default_deserialized_settings = self.load_setting_map(default_settings_content)?;
+ if self.default_deserialized_settings.len() != self.setting_keys.len() {
+ return Err(anyhow!(
+ "default settings file is missing fields: {:?}",
+ self.setting_keys
+ .iter()
+ .filter(|(_, type_id)| !self
+ .default_deserialized_settings
+ .contains_key(type_id))
+ .map(|(name, _)| *name)
+ .collect::<Vec<_>>()
+ ));
+ }
+ self.recompute_values(false, None, None);
+ Ok(())
+ }
+
+ /// Set the user settings via a JSON string.
+ pub fn set_user_settings(&mut self, user_settings_content: &str) -> Result<()> {
+ let user_settings = self.load_setting_map(user_settings_content)?;
+ let old_user_settings =
+ mem::replace(&mut self.user_deserialized_settings, Some(user_settings));
+ self.recompute_values(true, None, old_user_settings);
+ Ok(())
+ }
+
+ /// Add or remove a set of local settings via a JSON string.
+ pub fn set_local_settings(
+ &mut self,
+ path: Arc<Path>,
+ settings_content: Option<&str>,
+ ) -> Result<()> {
+ let removed_map = if let Some(settings_content) = settings_content {
+ self.local_deserialized_settings
+ .insert(path.clone(), self.load_setting_map(settings_content)?);
+ None
+ } else {
+ self.local_deserialized_settings.remove(&path)
+ };
+ self.recompute_values(true, Some(&path), removed_map);
+ Ok(())
+ }
+
+ fn recompute_values(
+ &mut self,
+ user_settings_changed: bool,
+ changed_local_path: Option<&Path>,
+ old_settings_map: Option<DeserializedSettingMap>,
+ ) {
+ // Identify all of the setting types that have changed.
+ let new_settings_map = if let Some(changed_path) = changed_local_path {
+ &self.local_deserialized_settings.get(changed_path).unwrap()
+ } else if user_settings_changed {
+ self.user_deserialized_settings.as_ref().unwrap()
+ } else {
+ &self.default_deserialized_settings
+ };
+ self.changed_setting_types.clear();
+ self.changed_setting_types.extend(new_settings_map.keys());
+ if let Some(previous_settings_map) = old_settings_map {
+ self.changed_setting_types
+ .extend(previous_settings_map.keys());
+ }
+
+ // Reload the global and local values for every changed setting.
+ let mut user_values_stack = Vec::<&DeserializedSetting>::new();
+ for setting_type_id in self.changed_setting_types.iter() {
+ let setting_value = self.setting_values.get_mut(setting_type_id).unwrap();
+
+ // Build the prioritized list of deserialized values to pass to the setting's
+ // load function.
+ user_values_stack.clear();
+ if let Some(user_settings) = &self.user_deserialized_settings {
+ if let Some(user_value) = user_settings.get(setting_type_id) {
+ user_values_stack.push(&user_value);
+ }
+ }
+
+ // If the global settings file changed, reload the global value for the field.
+ if changed_local_path.is_none() {
+ let global_value = setting_value.load_setting(
+ &self.default_deserialized_settings[setting_type_id],
+ &user_values_stack,
+ );
+ setting_value.set_global_value(global_value);
+ }
+
+ // Reload the local values for the setting.
+ let user_value_stack_len = user_values_stack.len();
+ for (path, deserialized_values) in &self.local_deserialized_settings {
+ // If a local settings file changed, then avoid recomputing local
+ // settings for any path outside of that directory.
+ if changed_local_path.map_or(false, |changed_local_path| {
+ !path.starts_with(changed_local_path)
+ }) {
+ continue;
+ }
+
+ // Ignore recomputing settings for any path that hasn't customized that setting.
+ let Some(deserialized_value) = deserialized_values.get(setting_type_id) else {
+ continue;
+ };
+
+ // Build a stack of all of the local values for that setting.
+ user_values_stack.truncate(user_value_stack_len);
+ for (preceding_path, preceding_deserialized_values) in
+ &self.local_deserialized_settings
+ {
+ if preceding_path >= path {
+ break;
+ }
+ if !path.starts_with(preceding_path) {
+ continue;
+ }
+
+ if let Some(preceding_deserialized_value) =
+ preceding_deserialized_values.get(setting_type_id)
+ {
+ user_values_stack.push(&*preceding_deserialized_value);
+ }
+ }
+ user_values_stack.push(&*deserialized_value);
+
+ // Load the local value for the field.
+ let local_value = setting_value.load_setting(
+ &self.default_deserialized_settings[setting_type_id],
+ &user_values_stack,
+ );
+ setting_value.set_local_value(path.clone(), local_value);
+ }
+ }
+ }
+
+ /// Deserialize the given JSON string into a map keyed by setting type.
+ ///
+ /// Returns an error if the string doesn't contain a valid JSON object.
+ fn load_setting_map(&self, json: &str) -> Result<DeserializedSettingMap> {
+ let mut map = DeserializedSettingMap::default();
+ let settings_content_by_key: BTreeMap<&str, &RawValue> = serde_json::from_str(json)?;
+ let mut setting_types_by_key = self.setting_keys.iter().peekable();
+
+ // Load all of the fields that don't have a key.
+ while let Some((setting_key, setting_type_id)) = setting_types_by_key.peek() {
+ if setting_key.is_some() {
+ break;
+ }
+ setting_types_by_key.next();
+ if let Some(deserialized_value) = self
+ .setting_values
+ .get(setting_type_id)
+ .unwrap()
+ .deserialize_setting(json)
+ .log_err()
+ {
+ map.insert(*setting_type_id, deserialized_value);
+ }
+ }
+
+ // For each key in the file, load all of the settings that belong to that key.
+ for (key, key_content) in settings_content_by_key {
+ while let Some((setting_key, setting_type_id)) = setting_types_by_key.peek() {
+ let setting_key = setting_key.expect("setting names are ordered");
+ match setting_key.cmp(key) {
+ Ordering::Less => {
+ setting_types_by_key.next();
+ continue;
+ }
+ Ordering::Greater => break,
+ Ordering::Equal => {
+ if let Some(deserialized_value) = self
+ .setting_values
+ .get(setting_type_id)
+ .unwrap()
+ .deserialize_setting(key_content.get())
+ .log_err()
+ {
+ map.insert(*setting_type_id, deserialized_value);
+ }
+ setting_types_by_key.next();
+ }
+ }
+ }
+ }
+ Ok(map)
+ }
+}
+
+impl<T: Setting> AnySettingValue for SettingValue<T> {
+ fn setting_type_name(&self) -> &'static str {
+ type_name::<T>()
+ }
+
+ fn load_setting(
+ &self,
+ default_value: &DeserializedSetting,
+ user_values: &[&DeserializedSetting],
+ ) -> Box<dyn Any> {
+ let default_value = default_value.0.downcast_ref::<T::FileContent>().unwrap();
+ let values: SmallVec<[&T::FileContent; 6]> = user_values
+ .iter()
+ .map(|value| value.0.downcast_ref().unwrap())
+ .collect();
+ Box::new(T::load(default_value, &values))
+ }
+
+ fn deserialize_setting(&self, json: &str) -> Result<DeserializedSetting> {
+ let value = serde_json::from_str::<T::FileContent>(json)?;
+ Ok(DeserializedSetting(Box::new(value)))
+ }
+
+ fn value_for_path(&self, path: Option<&Path>) -> &dyn Any {
+ if let Some(path) = path {
+ for (settings_path, value) in self.local_values.iter().rev() {
+ if path.starts_with(&settings_path) {
+ return value;
+ }
+ }
+ }
+ self.global_value.as_ref().unwrap()
+ }
+
+ fn set_global_value(&mut self, value: Box<dyn Any>) {
+ self.global_value = Some(*value.downcast().unwrap());
+ }
+
+ fn set_local_value(&mut self, path: Arc<Path>, value: Box<dyn Any>) {
+ let value = *value.downcast().unwrap();
+ match self.local_values.binary_search_by_key(&&path, |e| &e.0) {
+ Ok(ix) => self.local_values[ix].1 = value,
+ Err(ix) => self.local_values.insert(ix, (path, value)),
+ }
+ }
+}
+
+impl Debug for SettingsStore {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ return f
+ .debug_struct("SettingsStore")
+ .field(
+ "setting_value_sets_by_type",
+ &self
+ .setting_values
+ .values()
+ .map(|set| (set.setting_type_name(), set))
+ .collect::<HashMap<_, _>>(),
+ )
+ .finish_non_exhaustive();
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use serde_derive::Deserialize;
+
+ #[test]
+ fn test_settings_store() {
+ let mut store = SettingsStore::default();
+ store.register_setting::<UserSettings>();
+ store.register_setting::<TurboSetting>();
+ store.register_setting::<MultiKeySettings>();
+
+ // error - missing required field in default settings
+ store
+ .set_default_settings(
+ r#"{
+ "user": {
+ "name": "John Doe",
+ "age": 30,
+ "staff": false
+ }
+ }"#,
+ )
+ .unwrap_err();
+
+ // error - type error in default settings
+ store
+ .set_default_settings(
+ r#"{
+ "turbo": "the-wrong-type",
+ "user": {
+ "name": "John Doe",
+ "age": 30,
+ "staff": false
+ }
+ }"#,
+ )
+ .unwrap_err();
+
+ // valid default settings.
+ store
+ .set_default_settings(
+ r#"{
+ "turbo": false,
+ "user": {
+ "name": "John Doe",
+ "age": 30,
+ "staff": false
+ }
+ }"#,
+ )
+ .unwrap();
+
+ assert_eq!(store.get::<TurboSetting>(None), &TurboSetting(false));
+ assert_eq!(
+ store.get::<UserSettings>(None),
+ &UserSettings {
+ name: "John Doe".to_string(),
+ age: 30,
+ staff: false,
+ }
+ );
+ assert_eq!(
+ store.get::<MultiKeySettings>(None),
+ &MultiKeySettings {
+ key1: String::new(),
+ key2: String::new(),
+ }
+ );
+
+ store
+ .set_user_settings(
+ r#"{
+ "turbo": true,
+ "user": { "age": 31 },
+ "key1": "a"
+ }"#,
+ )
+ .unwrap();
+
+ assert_eq!(store.get::<TurboSetting>(None), &TurboSetting(true));
+ assert_eq!(
+ store.get::<UserSettings>(None),
+ &UserSettings {
+ name: "John Doe".to_string(),
+ age: 31,
+ staff: false
+ }
+ );
+
+ store
+ .set_local_settings(
+ Path::new("/root1").into(),
+ Some(r#"{ "user": { "staff": true } }"#),
+ )
+ .unwrap();
+ store
+ .set_local_settings(
+ Path::new("/root1/subdir").into(),
+ Some(r#"{ "user": { "name": "Jane Doe" } }"#),
+ )
+ .unwrap();
+
+ store
+ .set_local_settings(
+ Path::new("/root2").into(),
+ Some(r#"{ "user": { "age": 42 }, "key2": "b" }"#),
+ )
+ .unwrap();
+
+ assert_eq!(
+ store.get::<UserSettings>(Some(Path::new("/root1/something"))),
+ &UserSettings {
+ name: "John Doe".to_string(),
+ age: 31,
+ staff: true
+ }
+ );
+ assert_eq!(
+ store.get::<UserSettings>(Some(Path::new("/root1/subdir/something"))),
+ &UserSettings {
+ name: "Jane Doe".to_string(),
+ age: 31,
+ staff: true
+ }
+ );
+ assert_eq!(
+ store.get::<UserSettings>(Some(Path::new("/root2/something"))),
+ &UserSettings {
+ name: "John Doe".to_string(),
+ age: 42,
+ staff: false
+ }
+ );
+ assert_eq!(
+ store.get::<MultiKeySettings>(Some(Path::new("/root2/something"))),
+ &MultiKeySettings {
+ key1: "a".to_string(),
+ key2: "b".to_string(),
+ }
+ );
+ }
+
+ #[derive(Debug, PartialEq, Deserialize)]
+ struct UserSettings {
+ name: String,
+ age: u32,
+ staff: bool,
+ }
+
+ #[derive(Serialize, Deserialize, JsonSchema)]
+ struct UserSettingsJson {
+ name: Option<String>,
+ age: Option<u32>,
+ staff: Option<bool>,
+ }
+
+ impl Setting for UserSettings {
+ const FIELD_NAME: Option<&'static str> = Some("user");
+ type FileContent = UserSettingsJson;
+
+ fn load(default_value: &UserSettingsJson, user_values: &[&UserSettingsJson]) -> Self {
+ Self::load_via_json_merge(default_value, user_values)
+ }
+ }
+
+ #[derive(Debug, Deserialize, PartialEq)]
+ struct TurboSetting(bool);
+
+ impl Setting for TurboSetting {
+ const FIELD_NAME: Option<&'static str> = Some("turbo");
+ type FileContent = Option<bool>;
+
+ fn load(default_value: &Option<bool>, user_values: &[&Option<bool>]) -> Self {
+ Self::load_via_json_merge(default_value, user_values)
+ }
+ }
+
+ #[derive(Clone, Debug, PartialEq, Deserialize)]
+ struct MultiKeySettings {
+ #[serde(default)]
+ key1: String,
+ #[serde(default)]
+ key2: String,
+ }
+
+ #[derive(Serialize, Deserialize, JsonSchema)]
+ struct MultiKeySettingsJson {
+ key1: Option<String>,
+ key2: Option<String>,
+ }
+
+ impl Setting for MultiKeySettings {
+ type FileContent = MultiKeySettingsJson;
+
+ fn load(
+ default_value: &MultiKeySettingsJson,
+ user_values: &[&MultiKeySettingsJson],
+ ) -> Self {
+ Self::load_via_json_merge(default_value, user_values)
+ }
+ }
+
+ #[derive(Debug, Deserialize)]
+ struct JournalSettings {
+ pub path: String,
+ pub hour_format: HourFormat,
+ }
+
+ #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
+ #[serde(rename_all = "snake_case")]
+ enum HourFormat {
+ Hour12,
+ Hour24,
+ }
+
+ #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
+ struct JournalSettingsJson {
+ pub path: Option<String>,
+ pub hour_format: Option<HourFormat>,
+ }
+
+ impl Setting for JournalSettings {
+ const FIELD_NAME: Option<&'static str> = Some("journal");
+
+ type FileContent = JournalSettingsJson;
+
+ fn load(default_value: &JournalSettingsJson, user_values: &[&JournalSettingsJson]) -> Self {
+ Self::load_via_json_merge(default_value, user_values)
+ }
+ }
+}