diff --git a/Cargo.lock b/Cargo.lock index d560369829..81a576c598 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,21 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +version = 4 [[package]] name = "aho-corasick" @@ -28,23 +13,17 @@ dependencies = [ [[package]] name = "ammonia" -version = "4.0.0" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459" +checksum = "17e913097e1a2124b46746c980134e8c954bc17a6a59bb3fde96f088d126dde6" dependencies = [ + "cssparser", "html5ever", "maplit", - "once_cell", "tendril", "url", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -56,9 +35,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -71,43 +50,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "once_cell_polyfill", + "windows-sys 0.60.2", ] [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arrays" @@ -136,32 +116,78 @@ dependencies = [ "tokio", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] -name = "backtrace" -version = "0.3.73" +name = "axum" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871" dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", + "axum-core", + "base64", + "bytes", + "form_urlencoded", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sha1", + "sync_wrapper", + "tokio", + "tokio-tungstenite", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", ] [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bimap" @@ -180,9 +206,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "block-buffer" @@ -205,14 +231,15 @@ dependencies = [ name = "bounded" version = "0.1.0" dependencies = [ + "thiserror 1.0.69", "ticket_fields", ] [[package]] name = "bstr" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" dependencies = [ "memchr", "regex-automata", @@ -228,21 +255,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytes" -version = "1.7.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cancellation" @@ -253,15 +274,19 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.7" +version = "1.2.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +dependencies = [ + "find-msvc-tools", + "shlex", +] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "channels" @@ -272,21 +297,20 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "num-traits", - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "clap" -version = "4.5.13" +version = "4.5.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" +checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623" dependencies = [ "clap_builder", "clap_derive", @@ -294,9 +318,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.13" +version = "4.5.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" +checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0" dependencies = [ "anstream", "anstyle", @@ -307,18 +331,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.12" +version = "4.5.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8670053e87c316345e384ca1f3eba3006fc6355ed8b8a1140d104e109e3df34" +checksum = "2348487adcd4631696ced64ccdb40d38ac4d31cae7f2eec8817fcea1b9d1c43c" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", @@ -328,9 +352,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "client" @@ -345,9 +369,9 @@ version = "0.1.0" [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "combinators" @@ -366,33 +390,24 @@ version = "0.1.0" [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -409,9 +424,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" @@ -424,30 +439,111 @@ dependencies = [ ] [[package]] -name = "data-encoding" -version = "2.6.0" +name = "cssparser" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e901edd733a1472f944a45116df3f846f54d37e67e68640ac8bb69689aca2aa" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] [[package]] -name = "dbus" -version = "0.9.7" +name = "darling" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "libc", - "libdbus-sys", - "winapi", + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn", ] +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + [[package]] name = "deps" version = "0.1.0" +dependencies = [ + "anyhow", +] [[package]] name = "deref" version = "0.1.0" +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + [[package]] name = "derives" version = "0.1.0" @@ -466,15 +562,41 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "drop" version = "0.1.0" +[[package]] +name = "dtoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elasticlunr-rs" @@ -501,9 +623,9 @@ dependencies = [ [[package]] name = "env_filter" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" dependencies = [ "log", "regex", @@ -511,31 +633,25 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.5" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - [[package]] name = "errno" -version = "0.3.9" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -566,21 +682,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] -name = "filetime" -version = "0.2.23" +name = "find-msvc-tools" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", -] +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" [[package]] name = "fnv" @@ -594,9 +704,9 @@ version = "0.1.0" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -633,25 +743,24 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", - "futures-sink", ] [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -660,21 +769,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-macro", @@ -687,9 +796,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -697,35 +806,30 @@ dependencies = [ [[package]] name = "getopts" -version = "0.2.21" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" dependencies = [ "unicode-width", ] [[package]] name = "getrandom" -version = "0.2.15" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "wasi", + "r-efi", + "wasip2", ] -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - [[package]] name = "globset" -version = "0.4.14" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" dependencies = [ "aho-corasick", "bstr", @@ -734,45 +838,22 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "handlebars" -version = "5.1.2" +version = "6.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" +checksum = "759e2d5aea3287cb1190c8ec394f42866cb5bf74fcbf213f354e3c856ea26098" dependencies = [ + "derive_builder", "log", + "num-order", "pest", "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 2.0.17", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - [[package]] name = "hashmap" version = "0.1.0" @@ -780,30 +861,6 @@ dependencies = [ "ticket_fields", ] -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64", - "bytes", - "headers-core", - "http 0.2.12", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http 0.2.12", -] - [[package]] name = "heap" version = "0.1.0" @@ -815,30 +872,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "hermit-abi" -version = "0.3.9" +name = "hex" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "html5ever" -version = "0.27.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +checksum = "55d958c2f74b664487a2035fe1dadb032c48718a03b63f3ab0b8537db8549ed4" dependencies = [ "log", - "mac", "markup5ever", - "proc-macro2", - "quote", - "syn", + "match_token", ] [[package]] name = "http" -version = "0.2.12" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -846,32 +900,39 @@ dependencies = [ ] [[package]] -name = "http" -version = "1.1.0" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "fnv", - "itoa", + "http", ] [[package]] -name = "http-body" -version = "0.4.6" +name = "http-body-util" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "http 0.2.12", + "futures-core", + "http", + "http-body", "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" + [[package]] name = "httparse" -version = "1.9.4" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -879,46 +940,54 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" -version = "0.14.30" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" dependencies = [ + "atomic-waker", "bytes", "futures-channel", "futures-core", - "futures-util", - "h2", - "http 0.2.12", + "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2", + "pin-utils", + "smallvec", + "tokio", +] + +[[package]] +name = "hyper-util" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "hyper", + "pin-project-lite", "tokio", "tower-service", - "tracing", - "want", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -932,14 +1001,117 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" -version = "0.5.0" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] @@ -952,9 +1124,9 @@ version = "0.1.0" [[package]] name = "ignore" -version = "0.4.22" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +checksum = "81776e6f9464432afcc28d03e52eb101c93b6f0566f52aef2427663e700f0403" dependencies = [ "crossbeam-deque", "globset", @@ -994,23 +1166,13 @@ dependencies = [ "ticket_fields", ] -[[package]] -name = "indexmap" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" -dependencies = [ - "equivalent", - "hashbrown", -] - [[package]] name = "inotify" -version = "0.9.6" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.10.0", "inotify-sys", "libc", ] @@ -1062,9 +1224,9 @@ version = "0.1.0" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "iter" @@ -1091,24 +1253,49 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "kqueue" -version = "1.0.8" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" dependencies = [ "kqueue-sys", "libc", @@ -1130,19 +1317,9 @@ version = "0.1.0" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "libdbus-sys" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" -dependencies = [ - "cc", - "pkg-config", -] +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "lifetime" @@ -1153,17 +1330,22 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] @@ -1171,15 +1353,15 @@ dependencies = [ name = "locks" version = "0.1.0" dependencies = [ - "thiserror", + "thiserror 1.0.69", "ticket_fields", ] [[package]] name = "log" -version = "0.4.22" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "mac" @@ -1195,30 +1377,45 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "markup5ever" -version = "0.12.1" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +checksum = "311fe69c934650f8f19652b3946075f0fc41ad8757dbb68f1ca14e7900ecc1c3" dependencies = [ "log", - "phf", - "phf_codegen", - "string_cache", - "string_cache_codegen", "tendril", + "web_atoms", ] [[package]] name = "match_" version = "0.1.0" +[[package]] +name = "match_token" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + [[package]] name = "mdbook" -version = "0.4.40" +version = "0.4.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45a38e19bd200220ef07c892b0157ad3d2365e5b5a267ca01ad12182491eea5" +checksum = "93c284d2855916af7c5919cf9ad897cfc77d3c2db6f55429c7cfb769182030ec" dependencies = [ "ammonia", "anyhow", + "axum", "chrono", "clap", "clap_complete", @@ -1226,25 +1423,26 @@ dependencies = [ "env_logger", "futures-util", "handlebars", + "hex", "ignore", "log", "memchr", "notify", "notify-debouncer-mini", - "once_cell", "opener", "pathdiff", "pulldown-cmark 0.10.3", "regex", "serde", "serde_json", + "sha2", "shlex", "tempfile", "tokio", "toml", "topological-sort", + "tower-http", "walkdir", - "warp", ] [[package]] @@ -1267,7 +1465,7 @@ dependencies = [ "clap", "itertools", "mdbook", - "pulldown-cmark 0.11.0", + "pulldown-cmark 0.11.3", "pulldown-cmark-to-cmark", "semver", "serde_json", @@ -1275,9 +1473,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "mime" @@ -1295,37 +1493,16 @@ dependencies = [ "unicase", ] -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "mio" -version = "0.8.11" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "mio" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" -dependencies = [ - "hermit-abi", - "libc", - "wasi", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1344,43 +1521,49 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "normpath" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" +checksum = "bf23ab2b905654b4cb177e30b629937b3868311d4e1cba859f899c041046e69b" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "notify" -version = "6.1.1" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.6.0", - "crossbeam-channel", - "filetime", + "bitflags 2.10.0", "fsevent-sys", "inotify", "kqueue", "libc", "log", - "mio 0.8.11", + "mio", + "notify-types", "walkdir", - "windows-sys 0.48.0", + "windows-sys 0.60.2", ] [[package]] name = "notify-debouncer-mini" -version = "0.4.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d40b221972a1fc5ef4d858a2f671fb34c75983eb385463dff3780eeff6a9d43" +checksum = "a689eb4262184d9a1727f9087cd03883ea716682ab03ed24efec57d7716dccb8" dependencies = [ - "crossbeam-channel", "log", "notify", + "notify-types", + "tempfile", ] +[[package]] +name = "notify-types" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" + [[package]] name = "nullability" version = "0.1.0" @@ -1388,6 +1571,21 @@ dependencies = [ "common", ] +[[package]] +name = "num-modular" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" + +[[package]] +name = "num-order" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6" +dependencies = [ + "num-modular", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1398,30 +1596,26 @@ dependencies = [ ] [[package]] -name = "object" -version = "0.36.2" +name = "once_cell" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" -dependencies = [ - "memchr", -] +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] -name = "once_cell" -version = "1.19.0" +name = "once_cell_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "opener" -version = "0.7.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8df34be653210fbe9ffaff41d3b92721c56ce82dfee58ee684f9afb5e3a90c0" +checksum = "cb9024962ab91e00c89d2a14352a8d0fc1a64346bf96f1839b45c09149564e47" dependencies = [ "bstr", - "dbus", "normpath", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -1439,6 +1633,9 @@ version = "0.1.0" [[package]] name = "outro_04" version = "0.1.0" +dependencies = [ + "thiserror 1.0.69", +] [[package]] name = "outro_08" @@ -1469,9 +1666,9 @@ version = "0.1.0" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1479,53 +1676,52 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.3", + "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "patch" version = "0.1.0" dependencies = [ - "thiserror", + "thiserror 1.0.69", "ticket_fields", ] [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.7.11" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" dependencies = [ "memchr", - "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.11" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" dependencies = [ "pest", "pest_generator", @@ -1533,9 +1729,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.11" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" dependencies = [ "pest", "pest_meta", @@ -1546,115 +1742,107 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.11" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" dependencies = [ - "once_cell", "pest", "sha2", ] [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ - "phf_shared 0.11.2", + "phf_macros", + "phf_shared", ] [[package]] name = "phf_codegen" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ - "phf_shared 0.10.0", - "rand", + "phf_generator", + "phf_shared", ] [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_shared 0.11.2", - "rand", + "phf_shared", + "rand 0.8.5", ] [[package]] -name = "phf_shared" -version = "0.10.0" +name = "phf_macros" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ - "siphasher", + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] -name = "pin-project" -version = "1.1.5" +name = "pin-project-lite" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] -name = "pin-project-internal" -version = "1.1.5" +name = "pin-utils" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "pin-project-lite" -version = "0.2.14" +name = "portable-atomic" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] -name = "pin-utils" -version = "0.1.0" +name = "portable-atomic-util" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] [[package]] -name = "pkg-config" -version = "0.3.30" +name = "potential_utf" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +dependencies = [ + "zerovec", +] [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] @@ -1667,9 +1855,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -1680,7 +1868,7 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "memchr", "pulldown-cmark-escape 0.10.1", "unicase", @@ -1688,11 +1876,11 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.11.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8746739f11d39ce5ad5c2520a9b75285310dbfe78c541ccf832d38615765aec0" +checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "getopts", "memchr", "pulldown-cmark-escape 0.11.0", @@ -1717,37 +1905,51 @@ version = "15.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9c77db841443d89a57ae94f22d29c022f6d9f41b00bddbf1f4024dbaf4bdce1" dependencies = [ - "pulldown-cmark 0.11.0", + "pulldown-cmark 0.11.3", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ "rand_chacha", - "rand_core", + "rand_core 0.9.3", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.3", ] [[package]] @@ -1755,26 +1957,23 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] [[package]] -name = "redox_syscall" -version = "0.4.1" +name = "rand_core" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "bitflags 1.3.2", + "getrandom", ] [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", ] [[package]] @@ -1783,9 +1982,9 @@ version = "0.1.0" [[package]] name = "regex" -version = "1.10.6" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -1795,9 +1994,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -1806,9 +2005,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "resizing" @@ -1829,38 +2028,38 @@ dependencies = [ "tokio", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustix" -version = "0.38.34" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "rwlock" version = "0.1.0" dependencies = [ - "thiserror", + "thiserror 1.0.69", "ticket_fields", ] [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -1875,12 +2074,6 @@ dependencies = [ name = "saturating" version = "0.1.0" -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scoped_threads" version = "0.1.0" @@ -1893,24 +2086,34 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -1919,14 +2122,26 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", + "serde", + "serde_core", ] [[package]] @@ -1961,9 +2176,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -1978,18 +2193,18 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] [[package]] name = "siphasher" -version = "0.3.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "sized" @@ -1997,12 +2212,9 @@ version = "0.1.0" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "slice" @@ -2010,18 +2222,18 @@ version = "0.1.0" [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.5.7" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -2029,7 +2241,7 @@ name = "source" version = "0.1.0" dependencies = [ "common", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2040,6 +2252,12 @@ dependencies = [ "tokio", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "stack" version = "0.1.0" @@ -2063,26 +2281,25 @@ dependencies = [ [[package]] name = "string_cache" -version = "0.8.7" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ "new_debug_unreachable", - "once_cell", "parking_lot", - "phf_shared 0.10.0", + "phf_shared", "precomputed-hash", "serde", ] [[package]] name = "string_cache_codegen" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", + "phf_generator", + "phf_shared", "proc-macro2", "quote", ] @@ -2099,9 +2316,9 @@ version = "0.1.0" [[package]] name = "syn" -version = "2.0.72" +version = "2.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" dependencies = [ "proc-macro2", "quote", @@ -2112,21 +2329,38 @@ dependencies = [ name = "sync" version = "0.1.0" +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "syntax" version = "0.1.0" [[package]] name = "tempfile" -version = "3.11.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ - "cfg-if", "fastrand", + "getrandom", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2142,28 +2376,48 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.3.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ "rustix", - "windows-sys 0.48.0", + "windows-sys 0.60.2", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", ] [[package]] name = "thiserror" -version = "1.0.63" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.17", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", @@ -2175,6 +2429,7 @@ name = "thiserror_" version = "0.1.0" dependencies = [ "common", + "thiserror 1.0.69", ] [[package]] @@ -2186,47 +2441,41 @@ name = "ticket_fields" version = "0.1.0" dependencies = [ "common", - "thiserror", + "thiserror 1.0.69", ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinystr" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.39.2" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", "libc", - "mio 1.0.1", + "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", @@ -2235,9 +2484,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.21.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" +checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", @@ -2247,9 +2496,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", @@ -2273,17 +2522,65 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.10.0", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "http-range-header", + "httpdate", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -2292,9 +2589,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", ] @@ -2307,32 +2604,27 @@ version = "0.1.0" name = "trait_bounds" version = "0.1.0" -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - [[package]] name = "tryfrom" version = "0.1.0" +dependencies = [ + "thiserror 1.0.69", +] [[package]] name = "tungstenite" -version = "0.21.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" dependencies = [ - "byteorder", "bytes", "data-encoding", - "http 1.1.0", + "http", "httparse", "log", - "rand", + "rand 0.9.2", "sha1", - "thiserror", - "url", + "thiserror 2.0.17", "utf-8", ] @@ -2345,51 +2637,33 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unwrap" @@ -2400,13 +2674,14 @@ dependencies = [ [[package]] name = "url" -version = "2.5.2" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -2415,6 +2690,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -2464,67 +2745,41 @@ dependencies = [ ] [[package]] -name = "want" -version = "0.3.1" +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "warp" -version = "0.3.7" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4378d202ff965b011c64817db11d5829506d3404edeadb61f190d111da3f231c" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "headers", - "http 0.2.12", - "hyper", - "log", - "mime", - "mime_guess", - "percent-encoding", - "pin-project", - "scoped-tls", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-tungstenite", - "tokio-util", - "tower-service", - "tracing", + "wit-bindgen", ] -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -2533,9 +2788,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2543,9 +2798,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" dependencies = [ "proc-macro2", "quote", @@ -2556,9 +2811,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web_atoms" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "57ffde1dc01240bdf9992e3205668b235e59421fd085e8a317ed98da0178d414" +dependencies = [ + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", +] [[package]] name = "welcome_00" @@ -2569,215 +2839,267 @@ name = "while_" version = "0.1.0" [[package]] -name = "winapi" -version = "0.3.9" +name = "winapi-util" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-sys 0.61.2", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-core" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] [[package]] -name = "winapi-util" -version = "0.1.9" +name = "windows-implement" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ - "windows-sys 0.59.0", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-interface" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "windows-core" -version = "0.52.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-sys" -version = "0.48.0" +name = "windows-result" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-targets 0.48.5", + "windows-link", ] [[package]] -name = "windows-sys" -version = "0.52.0" +name = "windows-strings" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "windows-sys" -version = "0.59.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] -name = "windows-targets" -version = "0.48.5" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-link", ] [[package]] name = "windows-targets" -version = "0.52.6" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" +name = "windows_aarch64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" +name = "windows_i686_gnu" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" +name = "windows_i686_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] -name = "windows_i686_gnu" -version = "0.48.5" +name = "windows_i686_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] -name = "windows_i686_gnu" -version = "0.52.6" +name = "windows_x86_64_gnu" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" +name = "windows_x86_64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] -name = "windows_i686_msvc" -version = "0.48.5" +name = "windows_x86_64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] -name = "windows_i686_msvc" -version = "0.52.6" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +name = "without_channels" +version = "0.1.0" +dependencies = [ + "ticket_fields", +] + +[[package]] +name = "writeable" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" +name = "yoke" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +name = "yoke-derive" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] [[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" +name = "zerocopy" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +name = "zerocopy-derive" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" +name = "zerofrom" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] [[package]] -name = "without_channels" -version = "0.1.0" +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ - "ticket_fields", + "proc-macro2", + "quote", + "syn", + "synstructure", ] [[package]] -name = "zerocopy" -version = "0.7.35" +name = "zerotrie" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" dependencies = [ - "byteorder", - "zerocopy-derive", + "displaydoc", + "yoke", + "zerofrom", ] [[package]] -name = "zerocopy-derive" -version = "0.7.35" +name = "zerovec" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 52e8a87aa4..f53da2ac81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,6 @@ resolver = "2" # regardless of the "global" setting for `overflow-checks` on the `dev` profile. [profile.dev.package.copy] overflow-checks = true + +[profile.dev] +overflow-checks = false diff --git a/book/src/01_intro/00_welcome.md b/book/src/01_intro/00_welcome.md index 33da833ba5..8986900681 100644 --- a/book/src/01_intro/00_welcome.md +++ b/book/src/01_intro/00_welcome.md @@ -78,15 +78,10 @@ To work through this course, you'll need: - [RustRover](https://www.jetbrains.com/rust/); - [Visual Studio Code](https://code.visualstudio.com) with the [`rust-analyzer`](https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer) extension. -To verify your solutions, we've also provided a tool to guide you through the course. -It is the `wr` CLI (short for "workshop runner"). -Install it with: +To verify your solutions, we've also provided a tool to guide you through the course: the `wr` CLI, short for "workshop runner". +Install `wr` by following the instructions on [its website](https://mainmatter.github.io/rust-workshop-runner/). -```bash -cargo install --locked workshop-runner -``` - -In a new terminal, navigate back to the top-level folder of the repository. +Once you have `wr` installed, open a new terminal and navigate to the top-level folder of the repository. Run the `wr` command to start the course: ```bash diff --git a/exercises/01_intro/00_welcome/src/lib.rs b/exercises/01_intro/00_welcome/src/lib.rs index ec95b6ca75..e0f1fc2653 100644 --- a/exercises/01_intro/00_welcome/src/lib.rs +++ b/exercises/01_intro/00_welcome/src/lib.rs @@ -17,7 +17,7 @@ // You can also find solutions to all exercises in the `solutions` git branch. fn greeting() -> &'static str { // TODO: fix me ๐Ÿ‘‡ - "I'm ready to __!" + "I'm ready to learn Rust!" } // Your solutions will be automatically verified by a set of tests. diff --git a/exercises/01_intro/01_syntax/src/lib.rs b/exercises/01_intro/01_syntax/src/lib.rs index 676d81b22e..1845605a53 100644 --- a/exercises/01_intro/01_syntax/src/lib.rs +++ b/exercises/01_intro/01_syntax/src/lib.rs @@ -3,7 +3,7 @@ // partner in this course and it'll often guide you in the right direction! // // The input parameters should have the same type of the return type. -fn compute(a, b) -> u32 { +fn compute(a: u32, b: u32) -> u32 { // Don't touch the function body. a + b * 2 } @@ -16,4 +16,4 @@ mod tests { fn case() { assert_eq!(compute(1, 2), 5); } -} \ No newline at end of file +} diff --git a/exercises/02_basic_calculator/00_intro/src/lib.rs b/exercises/02_basic_calculator/00_intro/src/lib.rs index 03aeb16339..d65a5cd207 100644 --- a/exercises/02_basic_calculator/00_intro/src/lib.rs +++ b/exercises/02_basic_calculator/00_intro/src/lib.rs @@ -1,6 +1,6 @@ fn intro() -> &'static str { // TODO: fix me ๐Ÿ‘‡ - "I'm ready to __!" + "I'm ready to build a calculator in Rust!" } #[cfg(test)] diff --git a/exercises/02_basic_calculator/01_integers/src/lib.rs b/exercises/02_basic_calculator/01_integers/src/lib.rs index a87b56fba3..7801db5fc5 100644 --- a/exercises/02_basic_calculator/01_integers/src/lib.rs +++ b/exercises/02_basic_calculator/01_integers/src/lib.rs @@ -1,6 +1,7 @@ fn compute(a: u32, b: u32) -> u32 { - // TODO: change the line below to fix the compiler error and make the tests pass. - let multiplier: u8 = 4; + let multiplier: u32 = 4; + // ^ You could also omit `: u32` entirely. + // The compiler will infer the correct type based on the usage below. a + b * multiplier } diff --git a/exercises/02_basic_calculator/02_variables/src/lib.rs b/exercises/02_basic_calculator/02_variables/src/lib.rs index e8d116749a..e5a63b2ae6 100644 --- a/exercises/02_basic_calculator/02_variables/src/lib.rs +++ b/exercises/02_basic_calculator/02_variables/src/lib.rs @@ -8,6 +8,7 @@ pub fn speed(start: u32, end: u32, time_elapsed: u32) -> u32 { // TODO: define a variable named `distance` with the right value to get tests to pass // Do you need to annotate the type of `distance`? Why or why not? + let distance = end - start; // Don't change the line below distance / time_elapsed diff --git a/exercises/02_basic_calculator/03_if_else/src/lib.rs b/exercises/02_basic_calculator/03_if_else/src/lib.rs index fa2e06ea76..5c396e50b3 100644 --- a/exercises/02_basic_calculator/03_if_else/src/lib.rs +++ b/exercises/02_basic_calculator/03_if_else/src/lib.rs @@ -2,7 +2,13 @@ /// `13` if `n` is divisible by `3`, /// `17` otherwise. fn magic_number(n: u32) -> u32 { - todo!() + if n % 2 == 0 { + 12 + } else if n % 3 == 0 { + 13 + } else { + 17 + } } #[cfg(test)] diff --git a/exercises/02_basic_calculator/04_panics/src/lib.rs b/exercises/02_basic_calculator/04_panics/src/lib.rs index 702b7bd85c..b61b2cf645 100644 --- a/exercises/02_basic_calculator/04_panics/src/lib.rs +++ b/exercises/02_basic_calculator/04_panics/src/lib.rs @@ -2,6 +2,9 @@ /// calculate the average speed of the journey. fn speed(start: u32, end: u32, time_elapsed: u32) -> u32 { // TODO: Panic with a custom message if `time_elapsed` is 0 + if time_elapsed == 0 { + panic!("The journey took no time at all. That's impossible!"); + } (end - start) / time_elapsed } diff --git a/exercises/02_basic_calculator/05_factorial/src/lib.rs b/exercises/02_basic_calculator/05_factorial/src/lib.rs index d2f11a7216..ef43562aac 100644 --- a/exercises/02_basic_calculator/05_factorial/src/lib.rs +++ b/exercises/02_basic_calculator/05_factorial/src/lib.rs @@ -9,6 +9,13 @@ // `factorial(2)` to return `2`, and so on. // // Use only what you learned! No loops yet, so you'll have to use recursion! +fn factorial(n: u32) -> u32 { + if n == 0 { + 1 + } else { + n * factorial(n - 1) + } +} #[cfg(test)] mod tests { diff --git a/exercises/02_basic_calculator/06_while/src/lib.rs b/exercises/02_basic_calculator/06_while/src/lib.rs index dbc30ebb2d..a5f3d69c4d 100644 --- a/exercises/02_basic_calculator/06_while/src/lib.rs +++ b/exercises/02_basic_calculator/06_while/src/lib.rs @@ -4,7 +4,13 @@ pub fn factorial(n: u32) -> u32 { // interprets as "I'll get back to this later", thus // suppressing type errors. // It panics at runtime. - todo!() + let mut result = 1; + let mut i = 1; + while i <= n { + result *= i; + i += 1; + } + result } #[cfg(test)] diff --git a/exercises/02_basic_calculator/07_for/src/lib.rs b/exercises/02_basic_calculator/07_for/src/lib.rs index d571d57d90..6ba14f489d 100644 --- a/exercises/02_basic_calculator/07_for/src/lib.rs +++ b/exercises/02_basic_calculator/07_for/src/lib.rs @@ -1,6 +1,10 @@ // Rewrite the factorial function using a `for` loop. pub fn factorial(n: u32) -> u32 { - todo!() + let mut result = 1; + for i in 1..=n { + result *= i; + } + result } #[cfg(test)] diff --git a/exercises/02_basic_calculator/09_saturating/src/lib.rs b/exercises/02_basic_calculator/09_saturating/src/lib.rs index 4b0addec59..a254b434f3 100644 --- a/exercises/02_basic_calculator/09_saturating/src/lib.rs +++ b/exercises/02_basic_calculator/09_saturating/src/lib.rs @@ -1,9 +1,9 @@ pub fn factorial(n: u32) -> u32 { - let mut result = 1; + let mut result: u32 = 1; for i in 1..=n { // Use saturating multiplication to stop at the maximum value of u32 // rather than overflowing and wrapping around - result *= i; + result = result.saturating_mul(i); } result } diff --git a/exercises/02_basic_calculator/10_as_casting/src/lib.rs b/exercises/02_basic_calculator/10_as_casting/src/lib.rs index 2ba058c49a..60b01aa3c4 100644 --- a/exercises/02_basic_calculator/10_as_casting/src/lib.rs +++ b/exercises/02_basic_calculator/10_as_casting/src/lib.rs @@ -6,7 +6,7 @@ mod tests { #[test] fn u16_to_u32() { - let v: u32 = todo!(); + let v: u32 = 47; assert_eq!(47u16 as u32, v); } @@ -23,15 +23,15 @@ mod tests { // You could solve this by using exactly the same expression as above, // but that would defeat the purpose of the exercise. Instead, use a genuine - // `i8` value that is equivalent to `255` when converted to `u8`. - let y: i8 = todo!(); + // `i8` value that is equivalent to `255` when converted from `u8`. + let y: i8 = -1; assert_eq!(x, y); } #[test] fn bool_to_u8() { - let v: u8 = todo!(); + let v: u8 = 1; assert_eq!(true as u8, v); } } diff --git a/exercises/03_ticket_v1/00_intro/src/lib.rs b/exercises/03_ticket_v1/00_intro/src/lib.rs index f7afa4701e..c52e3ac9c2 100644 --- a/exercises/03_ticket_v1/00_intro/src/lib.rs +++ b/exercises/03_ticket_v1/00_intro/src/lib.rs @@ -1,6 +1,6 @@ fn intro() -> &'static str { // TODO: fix me ๐Ÿ‘‡ - "I'm ready to __!" + "I'm ready to start modelling a software ticket!" } #[cfg(test)] diff --git a/exercises/03_ticket_v1/01_struct/src/lib.rs b/exercises/03_ticket_v1/01_struct/src/lib.rs index 1119e330aa..68fbe46e01 100644 --- a/exercises/03_ticket_v1/01_struct/src/lib.rs +++ b/exercises/03_ticket_v1/01_struct/src/lib.rs @@ -4,6 +4,16 @@ // // It should also have a method named `is_available` that returns a `true` if the quantity is // greater than 0, otherwise `false`. +struct Order { + price: u32, + quantity: u32, +} + +impl Order { + fn is_available(&self) -> bool { + self.quantity > 0 + } +} #[cfg(test)] mod tests { diff --git a/exercises/03_ticket_v1/02_validation/src/lib.rs b/exercises/03_ticket_v1/02_validation/src/lib.rs index 7eaa5e5c6e..4fb9ed1e5b 100644 --- a/exercises/03_ticket_v1/02_validation/src/lib.rs +++ b/exercises/03_ticket_v1/02_validation/src/lib.rs @@ -18,7 +18,24 @@ impl Ticket { // as well as some `String` methods. Use the documentation of Rust's standard library // to find the most appropriate options -> https://doc.rust-lang.org/std/string/struct.String.html fn new(title: String, description: String, status: String) -> Self { - todo!(); + if title.is_empty() { + panic!("Title cannot be empty"); + } + if title.len() > 50 { + panic!("Title cannot be longer than 50 bytes"); + } + + if description.is_empty() { + panic!("Description cannot be empty"); + } + if description.len() > 500 { + panic!("Description cannot be longer than 500 bytes"); + } + + if status != "To-Do" && status != "In Progress" && status != "Done" { + panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed"); + } + Self { title, description, diff --git a/exercises/03_ticket_v1/03_modules/src/lib.rs b/exercises/03_ticket_v1/03_modules/src/lib.rs index df0762094b..f93112b236 100644 --- a/exercises/03_ticket_v1/03_modules/src/lib.rs +++ b/exercises/03_ticket_v1/03_modules/src/lib.rs @@ -1,6 +1,7 @@ mod helpers { // TODO: Make this code compile, either by adding a `use` statement or by using // the appropriate path to refer to the `Ticket` struct. + use super::Ticket; fn create_todo_ticket(title: String, description: String) -> Ticket { Ticket::new(title, description, "To-Do".into()) diff --git a/exercises/03_ticket_v1/04_visibility/src/lib.rs b/exercises/03_ticket_v1/04_visibility/src/lib.rs index b494fc945b..65a15934f4 100644 --- a/exercises/03_ticket_v1/04_visibility/src/lib.rs +++ b/exercises/03_ticket_v1/04_visibility/src/lib.rs @@ -1,12 +1,12 @@ mod ticket { - struct Ticket { + pub struct Ticket { title: String, description: String, status: String, } impl Ticket { - fn new(title: String, description: String, status: String) -> Ticket { + pub fn new(title: String, description: String, status: String) -> Ticket { if title.is_empty() { panic!("Title cannot be empty"); } @@ -55,7 +55,7 @@ mod tests { // // TODO: Once you have verified that the below does not compile, // comment the line out to move on to the next exercise! - assert_eq!(ticket.description, "A description"); + // assert_eq!(ticket.description, "A description"); } fn encapsulation_cannot_be_violated() { @@ -68,10 +68,10 @@ mod tests { // // TODO: Once you have verified that the below does not compile, // comment the lines out to move on to the next exercise! - let ticket = Ticket { - title: "A title".into(), - description: "A description".into(), - status: "To-Do".into(), - }; + // let ticket = Ticket { + // title: "A title".into(), + // description: "A description".into(), + // status: "To-Do".into(), + // }; } } diff --git a/exercises/03_ticket_v1/05_encapsulation/src/lib.rs b/exercises/03_ticket_v1/05_encapsulation/src/lib.rs index 91e06eb2ab..e59d18db7a 100644 --- a/exercises/03_ticket_v1/05_encapsulation/src/lib.rs +++ b/exercises/03_ticket_v1/05_encapsulation/src/lib.rs @@ -34,6 +34,17 @@ pub mod ticket { // - `title` that returns the `title` field. // - `description` that returns the `description` field. // - `status` that returns the `status` field. + pub fn title(self) -> String { + self.title + } + + pub fn description(self) -> String { + self.description + } + + pub fn status(self) -> String { + self.status + } } } diff --git a/exercises/03_ticket_v1/06_ownership/src/lib.rs b/exercises/03_ticket_v1/06_ownership/src/lib.rs index ded2ad8de6..4ab49f1857 100644 --- a/exercises/03_ticket_v1/06_ownership/src/lib.rs +++ b/exercises/03_ticket_v1/06_ownership/src/lib.rs @@ -34,16 +34,16 @@ impl Ticket { } } - pub fn title(self) -> String { - self.title + pub fn title(&self) -> &String { + &self.title } - pub fn description(self) -> String { - self.description + pub fn description(&self) -> &String { + &self.description } - pub fn status(self) -> String { - self.status + pub fn status(&self) -> &String { + &self.status } } diff --git a/exercises/03_ticket_v1/07_setters/src/lib.rs b/exercises/03_ticket_v1/07_setters/src/lib.rs index e13ec87729..2ef2bbd2e2 100644 --- a/exercises/03_ticket_v1/07_setters/src/lib.rs +++ b/exercises/03_ticket_v1/07_setters/src/lib.rs @@ -11,21 +11,9 @@ pub struct Ticket { impl Ticket { pub fn new(title: String, description: String, status: String) -> Ticket { - if title.is_empty() { - panic!("Title cannot be empty"); - } - if title.len() > 50 { - panic!("Title cannot be longer than 50 bytes"); - } - if description.is_empty() { - panic!("Description cannot be empty"); - } - if description.len() > 500 { - panic!("Description cannot be longer than 500 bytes"); - } - if status != "To-Do" && status != "In Progress" && status != "Done" { - panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed"); - } + validate_title(&title); + validate_description(&description); + validate_status(&status); Ticket { title, @@ -45,6 +33,45 @@ impl Ticket { pub fn status(&self) -> &String { &self.status } + + pub fn set_title(&mut self, title: String) { + validate_title(&title); + self.title = title; + } + + pub fn set_description(&mut self, description: String) { + validate_description(&description); + self.description = description; + } + + pub fn set_status(&mut self, status: String) { + validate_status(&status); + self.status = status; + } +} + +fn validate_title(title: &String) { + if title.is_empty() { + panic!("Title cannot be empty"); + } + if title.len() > 50 { + panic!("Title cannot be longer than 50 bytes"); + } +} + +fn validate_description(description: &String) { + if description.is_empty() { + panic!("Description cannot be empty"); + } + if description.len() > 500 { + panic!("Description cannot be longer than 500 bytes"); + } +} + +fn validate_status(status: &String) { + if status != "To-Do" && status != "In Progress" && status != "Done" { + panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed"); + } } #[cfg(test)] diff --git a/exercises/03_ticket_v1/08_stack/src/lib.rs b/exercises/03_ticket_v1/08_stack/src/lib.rs index e97518cfac..ad7d2a491c 100644 --- a/exercises/03_ticket_v1/08_stack/src/lib.rs +++ b/exercises/03_ticket_v1/08_stack/src/lib.rs @@ -6,16 +6,16 @@ mod tests { #[test] fn u16_size() { - assert_eq!(size_of::(), todo!()); + assert_eq!(size_of::(), 2); } #[test] fn i32_size() { - assert_eq!(size_of::(), todo!()); + assert_eq!(size_of::(), 4); } #[test] fn bool_size() { - assert_eq!(size_of::(), todo!()); + assert_eq!(size_of::(), 1); } } diff --git a/exercises/03_ticket_v1/09_heap/src/lib.rs b/exercises/03_ticket_v1/09_heap/src/lib.rs index 7273c2086a..5e24f6bc3c 100644 --- a/exercises/03_ticket_v1/09_heap/src/lib.rs +++ b/exercises/03_ticket_v1/09_heap/src/lib.rs @@ -13,7 +13,7 @@ mod tests { #[test] fn string_size() { - assert_eq!(size_of::(), todo!()); + assert_eq!(size_of::(), 24); } #[test] @@ -21,8 +21,8 @@ mod tests { // This is a tricky question! // The "intuitive" answer happens to be the correct answer this time, // but, in general, the memory layout of structs is a more complex topic. - // If you're curious, check out the "Type layout" section of The Rust Reference - // https://doc.rust-lang.org/reference/type-layout.html for more information. - assert_eq!(size_of::(), todo!()); + // If you're curious, check out the "Data layout" section of the Rustonomicon + // https://doc.rust-lang.org/nomicon/data.html for more information. + assert_eq!(size_of::(), 72); } } diff --git a/exercises/03_ticket_v1/10_references_in_memory/src/lib.rs b/exercises/03_ticket_v1/10_references_in_memory/src/lib.rs index d580758311..8fe236d8c6 100644 --- a/exercises/03_ticket_v1/10_references_in_memory/src/lib.rs +++ b/exercises/03_ticket_v1/10_references_in_memory/src/lib.rs @@ -11,18 +11,21 @@ mod tests { use super::Ticket; use std::mem::size_of; + // All numbers below assume you're running on a 64-bit system. + // If you're running on a 32-bit system, pointers will be 4 bytes long instead of 8. + #[test] fn u16_ref_size() { - assert_eq!(size_of::<&u16>(), todo!()); + assert_eq!(size_of::<&u16>(), 8); } #[test] fn u64_mut_ref_size() { - assert_eq!(size_of::<&mut u64>(), todo!()); + assert_eq!(size_of::<&mut u64>(), 8); } #[test] fn ticket_ref_size() { - assert_eq!(size_of::<&Ticket>(), todo!()); + assert_eq!(size_of::<&Ticket>(), 8); } } diff --git a/exercises/03_ticket_v1/11_destructor/src/lib.rs b/exercises/03_ticket_v1/11_destructor/src/lib.rs index 45bc89cf31..6555fbb589 100644 --- a/exercises/03_ticket_v1/11_destructor/src/lib.rs +++ b/exercises/03_ticket_v1/11_destructor/src/lib.rs @@ -2,7 +2,7 @@ // We'll pick the concept up again in a later chapter after covering traits and // interior mutability. fn outro() -> &'static str { - "I have a basic understanding of __!" + "I have a basic understanding of destructors!" } #[cfg(test)] diff --git a/exercises/03_ticket_v1/12_outro/src/lib.rs b/exercises/03_ticket_v1/12_outro/src/lib.rs index 15c99b83b5..e058670cbb 100644 --- a/exercises/03_ticket_v1/12_outro/src/lib.rs +++ b/exercises/03_ticket_v1/12_outro/src/lib.rs @@ -11,3 +11,74 @@ // Integration here has a very specific meaning: they test **the public API** of your project. // You'll need to pay attention to the visibility of your types and methods; integration // tests can't access private or `pub(crate)` items. +pub struct Order { + product_name: String, + quantity: u32, + unit_price: u32, +} + +impl Order { + pub fn new(product_name: String, quantity: u32, unit_price: u32) -> Order { + validate_product_name(&product_name); + validate_quantity(&quantity); + validate_unit_price(&unit_price); + + Order { + product_name, + quantity, + unit_price, + } + } + + pub fn product_name(&self) -> &String { + &self.product_name + } + + pub fn quantity(&self) -> &u32 { + &self.quantity + } + + pub fn unit_price(&self) -> &u32 { + &self.unit_price + } + + pub fn set_product_name(&mut self, product_name: String) { + validate_product_name(&product_name); + self.product_name = product_name; + } + + pub fn set_quantity(&mut self, quantity: u32) { + validate_quantity(&quantity); + self.quantity = quantity; + } + + pub fn set_unit_price(&mut self, unit_price: u32) { + validate_unit_price(&unit_price); + self.unit_price = unit_price; + } + + pub fn total(&self) -> u32 { + self.quantity * self.unit_price + } +} + +fn validate_product_name(product_name: &String) { + if product_name.is_empty() { + panic!("Product name cannot be empty"); + } + if product_name.len() > 300 { + panic!("Product name cannot be longer than 300 bytes"); + } +} + +fn validate_quantity(quantity: &u32) { + if quantity == &0 { + panic!("Quantity must be greater than zero"); + } +} + +fn validate_unit_price(unit_price: &u32) { + if unit_price == &0 { + panic!("Unit price must be greater than zero"); + } +} diff --git a/exercises/04_traits/00_intro/src/lib.rs b/exercises/04_traits/00_intro/src/lib.rs index 9513649ab7..1b0f8ee04b 100644 --- a/exercises/04_traits/00_intro/src/lib.rs +++ b/exercises/04_traits/00_intro/src/lib.rs @@ -1,6 +1,6 @@ fn intro() -> &'static str { // TODO: fix me ๐Ÿ‘‡ - "I'm ready to __!" + "I'm ready to learn about traits!" } #[cfg(test)] diff --git a/exercises/04_traits/01_trait/src/lib.rs b/exercises/04_traits/01_trait/src/lib.rs index 258eac507a..89c40ad6d8 100644 --- a/exercises/04_traits/01_trait/src/lib.rs +++ b/exercises/04_traits/01_trait/src/lib.rs @@ -2,6 +2,21 @@ // even, otherwise `false`. // // Then implement the trait for `u32` and `i32`. +pub trait IsEven { + fn is_even(&self) -> bool; +} + +impl IsEven for u32 { + fn is_even(&self) -> bool { + self % 2 == 0 + } +} + +impl IsEven for i32 { + fn is_even(&self) -> bool { + self % 2 == 0 + } +} #[cfg(test)] mod tests { diff --git a/exercises/04_traits/02_orphan_rule/src/lib.rs b/exercises/04_traits/02_orphan_rule/src/lib.rs index b707c10313..7927ba2de7 100644 --- a/exercises/04_traits/02_orphan_rule/src/lib.rs +++ b/exercises/04_traits/02_orphan_rule/src/lib.rs @@ -3,9 +3,3 @@ // a foreign type (`u32`, from `std`). // Look at the compiler error to get familiar with what it looks like. // Then delete the code below and move on to the next exercise. - -impl PartialEq for u32 { - fn eq(&self, _other: &Self) -> bool { - todo!() - } -} diff --git a/exercises/04_traits/03_operator_overloading/src/lib.rs b/exercises/04_traits/03_operator_overloading/src/lib.rs index b75c0f1de8..4a091d8c0e 100644 --- a/exercises/04_traits/03_operator_overloading/src/lib.rs +++ b/exercises/04_traits/03_operator_overloading/src/lib.rs @@ -8,7 +8,13 @@ struct Ticket { // TODO: Implement the `PartialEq` trait for `Ticket`. -impl PartialEq for Ticket {} +impl PartialEq for Ticket { + fn eq(&self, other: &Self) -> bool { + self.title == other.title + && self.description == other.description + && self.status == other.status + } +} #[cfg(test)] mod tests { diff --git a/exercises/04_traits/04_derive/src/lib.rs b/exercises/04_traits/04_derive/src/lib.rs index 0a74a26488..67d9024cda 100644 --- a/exercises/04_traits/04_derive/src/lib.rs +++ b/exercises/04_traits/04_derive/src/lib.rs @@ -8,7 +8,7 @@ // print both sides of the comparison to the terminal. // If the compared type doesn't implement `Debug`, it doesn't know how to represent them! -#[derive(PartialEq)] +#[derive(Debug, PartialEq)] struct Ticket { title: String, description: String, diff --git a/exercises/04_traits/05_trait_bounds/src/lib.rs b/exercises/04_traits/05_trait_bounds/src/lib.rs index 10f0eb4c5e..7afdc38e62 100644 --- a/exercises/04_traits/05_trait_bounds/src/lib.rs +++ b/exercises/04_traits/05_trait_bounds/src/lib.rs @@ -6,7 +6,10 @@ // collections (e.g. BTreeMap). /// Return the minimum of two values. -pub fn min(left: T, right: T) -> T { +pub fn min(left: T, right: T) -> T { + // `Ord` guarantees that the values can be compared. + // `PartialOrd` would also make the compiler happy, but it would have different semantics: + // it'd either return the minimum value or `right` if they can't be compared. if left <= right { left } else { diff --git a/exercises/04_traits/06_str_slice/src/lib.rs b/exercises/04_traits/06_str_slice/src/lib.rs index 5bf66147c0..a37c0d4a68 100644 --- a/exercises/04_traits/06_str_slice/src/lib.rs +++ b/exercises/04_traits/06_str_slice/src/lib.rs @@ -31,15 +31,15 @@ impl Ticket { } } - pub fn title(&self) -> &String { + pub fn title(&self) -> &str { &self.title } - pub fn description(&self) -> &String { + pub fn description(&self) -> &str { &self.description } - pub fn status(&self) -> &String { + pub fn status(&self) -> &str { &self.status } } diff --git a/exercises/04_traits/07_deref/src/lib.rs b/exercises/04_traits/07_deref/src/lib.rs index c7a5c35b42..a21f9ef26b 100644 --- a/exercises/04_traits/07_deref/src/lib.rs +++ b/exercises/04_traits/07_deref/src/lib.rs @@ -12,11 +12,11 @@ pub struct Ticket { impl Ticket { pub fn title(&self) -> &str { - todo!() + self.title.trim() } pub fn description(&self) -> &str { - todo!() + self.description.trim() } } diff --git a/exercises/04_traits/08_sized/src/lib.rs b/exercises/04_traits/08_sized/src/lib.rs index a406fc5a83..0ebca5a622 100644 --- a/exercises/04_traits/08_sized/src/lib.rs +++ b/exercises/04_traits/08_sized/src/lib.rs @@ -3,5 +3,5 @@ pub fn example() { // via `std::mem::size_of` will result in a compile-time error. // // TODO: Comment out the following line and move on to the next exercise. - std::mem::size_of::(); + // std::mem::size_of::(); } diff --git a/exercises/04_traits/09_from/src/lib.rs b/exercises/04_traits/09_from/src/lib.rs index cc6f5b1bb7..b7995d2ec4 100644 --- a/exercises/04_traits/09_from/src/lib.rs +++ b/exercises/04_traits/09_from/src/lib.rs @@ -4,6 +4,12 @@ pub struct WrappingU32 { value: u32, } +impl From for WrappingU32 { + fn from(value: u32) -> Self { + WrappingU32 { value } + } +} + fn example() { let wrapping: WrappingU32 = 42.into(); let wrapping = WrappingU32::from(42); diff --git a/exercises/04_traits/10_assoc_vs_generic/src/lib.rs b/exercises/04_traits/10_assoc_vs_generic/src/lib.rs index 84f3e7b971..2193a4b50f 100644 --- a/exercises/04_traits/10_assoc_vs_generic/src/lib.rs +++ b/exercises/04_traits/10_assoc_vs_generic/src/lib.rs @@ -13,6 +13,36 @@ // You don't have to though: it's perfectly okay to write three separate // implementations manually. Venture further only if you're curious. +pub trait Power { + type Output; + + fn power(&self, n: Exponent) -> Self::Output; +} + +impl Power for u32 { + type Output = u32; + + fn power(&self, n: u16) -> Self::Output { + self.pow(n.into()) + } +} + +impl Power<&u32> for u32 { + type Output = u32; + + fn power(&self, n: &u32) -> Self::Output { + self.power(*n) + } +} + +impl Power for u32 { + type Output = u32; + + fn power(&self, n: u32) -> Self::Output { + self.pow(n) + } +} + #[cfg(test)] mod tests { use super::Power; diff --git a/exercises/04_traits/11_clone/src/lib.rs b/exercises/04_traits/11_clone/src/lib.rs index 4fbbe47369..8d93806d45 100644 --- a/exercises/04_traits/11_clone/src/lib.rs +++ b/exercises/04_traits/11_clone/src/lib.rs @@ -2,9 +2,10 @@ // to get the code to compile. pub fn summary(ticket: Ticket) -> (Ticket, Summary) { - (ticket, ticket.summary()) + (ticket.clone(), ticket.summary()) } +#[derive(Clone)] pub struct Ticket { pub title: String, pub description: String, diff --git a/exercises/04_traits/12_copy/src/lib.rs b/exercises/04_traits/12_copy/src/lib.rs index d74720b6f6..22090c463d 100644 --- a/exercises/04_traits/12_copy/src/lib.rs +++ b/exercises/04_traits/12_copy/src/lib.rs @@ -1,6 +1,7 @@ // TODO: implement the necessary traits to make the test compile and pass. // You *can't* modify the test. +#[derive(Debug, Clone, Copy, PartialEq)] pub struct WrappingU32 { value: u32, } @@ -11,6 +12,14 @@ impl WrappingU32 { } } +impl std::ops::Add for WrappingU32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self::new(self.value.wrapping_add(rhs.value)) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/exercises/04_traits/13_drop/src/lib.rs b/exercises/04_traits/13_drop/src/lib.rs index 2124d343a5..d60193e717 100644 --- a/exercises/04_traits/13_drop/src/lib.rs +++ b/exercises/04_traits/13_drop/src/lib.rs @@ -1,6 +1,27 @@ // TODO: implement a so-called "Drop bomb": a type that panics when dropped // unless a certain operation has been performed on it. // You can see the expected API in the tests below. +pub struct DropBomb { + defused: bool, +} + +impl DropBomb { + pub fn new() -> Self { + DropBomb { defused: false } + } + + pub fn defuse(&mut self) { + self.defused = true; + } +} + +impl Drop for DropBomb { + fn drop(&mut self) { + if !self.defused { + panic!("Boom!"); + } + } +} #[cfg(test)] mod tests { diff --git a/exercises/04_traits/14_outro/src/lib.rs b/exercises/04_traits/14_outro/src/lib.rs index 547fd942b9..7393296757 100644 --- a/exercises/04_traits/14_outro/src/lib.rs +++ b/exercises/04_traits/14_outro/src/lib.rs @@ -8,3 +8,75 @@ // It should be possible to print its debug representation. // // Tests are located in the `tests` folderโ€”pay attention to the visibility of your types and methods. + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct SaturatingU16 { + value: u16, +} + +impl From for SaturatingU16 { + fn from(value: u16) -> Self { + Self { value } + } +} + +impl From for SaturatingU16 { + fn from(value: u8) -> Self { + Self { + value: value.into(), + } + } +} + +impl From<&u16> for SaturatingU16 { + fn from(value: &u16) -> Self { + (*value).into() + } +} + +impl From<&u8> for SaturatingU16 { + fn from(value: &u8) -> Self { + (*value).into() + } +} + +impl std::ops::Add for SaturatingU16 { + type Output = SaturatingU16; + + fn add(self, rhs: Self) -> Self::Output { + self + rhs.value + } +} + +impl std::ops::Add<&SaturatingU16> for SaturatingU16 { + type Output = SaturatingU16; + + fn add(self, rhs: &SaturatingU16) -> Self::Output { + self + *rhs + } +} + +impl std::ops::Add for SaturatingU16 { + type Output = Self; + + fn add(self, rhs: u16) -> Self::Output { + let sum = self.value.saturating_add(rhs); + Self { + value: sum, + } + } +} + +impl std::ops::Add<&u16> for SaturatingU16 { + type Output = SaturatingU16; + + fn add(self, rhs: &u16) -> Self::Output { + self + *rhs + } +} + +impl PartialEq for SaturatingU16 { + fn eq(&self, other: &u16) -> bool { + self.value == *other + } +} diff --git a/exercises/05_ticket_v2/00_intro/src/lib.rs b/exercises/05_ticket_v2/00_intro/src/lib.rs index ce1f75fc0d..ff614d11f7 100644 --- a/exercises/05_ticket_v2/00_intro/src/lib.rs +++ b/exercises/05_ticket_v2/00_intro/src/lib.rs @@ -1,6 +1,6 @@ fn intro() -> &'static str { // TODO: fix me ๐Ÿ‘‡ - "I'm ready to __!" + "I'm ready to refine the `Ticket` type!" } #[cfg(test)] diff --git a/exercises/05_ticket_v2/01_enum/src/lib.rs b/exercises/05_ticket_v2/01_enum/src/lib.rs index a3d9592939..d1a2d1523e 100644 --- a/exercises/05_ticket_v2/01_enum/src/lib.rs +++ b/exercises/05_ticket_v2/01_enum/src/lib.rs @@ -7,15 +7,18 @@ struct Ticket { title: String, description: String, - status: String, + status: Status, } +#[derive(Debug, PartialEq, Copy, Clone)] enum Status { - // TODO: add the missing variants + ToDo, + InProgress, + Done, } impl Ticket { - pub fn new(title: String, description: String, status: String) -> Ticket { + pub fn new(title: String, description: String, status: Status) -> Ticket { if title.is_empty() { panic!("Title cannot be empty"); } @@ -28,9 +31,6 @@ impl Ticket { if description.len() > 500 { panic!("Description cannot be longer than 500 bytes"); } - if status != "To-Do" && status != "In Progress" && status != "Done" { - panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed"); - } Ticket { title, @@ -47,7 +47,7 @@ impl Ticket { &self.description } - pub fn status(&self) -> &String { + pub fn status(&self) -> &Status { &self.status } } diff --git a/exercises/05_ticket_v2/02_match/src/lib.rs b/exercises/05_ticket_v2/02_match/src/lib.rs index d30c569ceb..230d55c0ce 100644 --- a/exercises/05_ticket_v2/02_match/src/lib.rs +++ b/exercises/05_ticket_v2/02_match/src/lib.rs @@ -9,7 +9,12 @@ enum Shape { impl Shape { // TODO: Implement the `n_sides` method using a `match`. pub fn n_sides(&self) -> u8 { - todo!() + match self { + Shape::Circle => 0, + Shape::Square | Shape::Rectangle => 4, + Shape::Triangle => 3, + Shape::Pentagon => 5, + } } } diff --git a/exercises/05_ticket_v2/03_variants_with_data/src/lib.rs b/exercises/05_ticket_v2/03_variants_with_data/src/lib.rs index 03faf0cd3d..b9376e1a7d 100644 --- a/exercises/05_ticket_v2/03_variants_with_data/src/lib.rs +++ b/exercises/05_ticket_v2/03_variants_with_data/src/lib.rs @@ -38,7 +38,10 @@ impl Ticket { } } pub fn assigned_to(&self) -> &str { - todo!() + match &self.status { + Status::InProgress { assigned_to } => assigned_to, + _ => panic!("Only `In-Progress` tickets can be assigned to someone"), + } } } diff --git a/exercises/05_ticket_v2/04_if_let/src/lib.rs b/exercises/05_ticket_v2/04_if_let/src/lib.rs index 0884fb578e..0de315cbd3 100644 --- a/exercises/05_ticket_v2/04_if_let/src/lib.rs +++ b/exercises/05_ticket_v2/04_if_let/src/lib.rs @@ -8,7 +8,11 @@ impl Shape { // TODO: Implement the `radius` method using // either an `if let` or a `let/else`. pub fn radius(&self) -> f64 { - todo!() + if let Shape::Circle { radius } = self { + *radius + } else { + panic!("Not a circle"); + } } } diff --git a/exercises/05_ticket_v2/05_nullability/src/lib.rs b/exercises/05_ticket_v2/05_nullability/src/lib.rs index f4e5cb2c09..22a283bdfd 100644 --- a/exercises/05_ticket_v2/05_nullability/src/lib.rs +++ b/exercises/05_ticket_v2/05_nullability/src/lib.rs @@ -36,7 +36,10 @@ impl Ticket { } } pub fn assigned_to(&self) -> Option<&String> { - todo!() + match &self.status { + Status::InProgress { assigned_to } => Some(assigned_to), + _ => None, + } } } diff --git a/exercises/05_ticket_v2/06_fallibility/src/lib.rs b/exercises/05_ticket_v2/06_fallibility/src/lib.rs index 3144bee9ad..096628b8a5 100644 --- a/exercises/05_ticket_v2/06_fallibility/src/lib.rs +++ b/exercises/05_ticket_v2/06_fallibility/src/lib.rs @@ -16,25 +16,25 @@ enum Status { } impl Ticket { - pub fn new(title: String, description: String, status: Status) -> Ticket { + pub fn new(title: String, description: String, status: Status) -> Result { if title.is_empty() { - panic!("Title cannot be empty"); + return Err("Title cannot be empty".into()); } if title.len() > 50 { - panic!("Title cannot be longer than 50 bytes"); + return Err("Title cannot be longer than 50 bytes".into()); } if description.is_empty() { - panic!("Description cannot be empty"); + return Err("Description cannot be empty".into()); } if description.len() > 500 { - panic!("Description cannot be longer than 500 bytes"); + return Err("Description cannot be longer than 500 bytes".into()); } - Ticket { + Ok(Ticket { title, description, status, - } + }) } } diff --git a/exercises/05_ticket_v2/07_unwrap/src/lib.rs b/exercises/05_ticket_v2/07_unwrap/src/lib.rs index 4b6419bad9..fcf1e20d25 100644 --- a/exercises/05_ticket_v2/07_unwrap/src/lib.rs +++ b/exercises/05_ticket_v2/07_unwrap/src/lib.rs @@ -2,7 +2,16 @@ // When the description is invalid, instead, it should use a default description: // "Description not provided". fn easy_ticket(title: String, description: String, status: Status) -> Ticket { - todo!() + match Ticket::new(title.clone(), description, status.clone()) { + Ok(ticket) => ticket, + Err(error) => { + if error.contains("Description") { + Ticket::new(title, "Description not provided".to_string(), status).unwrap() + } else { + panic!("{error}"); + } + } + } } #[derive(Debug, PartialEq, Clone)] diff --git a/exercises/05_ticket_v2/08_error_enums/src/lib.rs b/exercises/05_ticket_v2/08_error_enums/src/lib.rs index c74fcc9ad6..2f77d96bfa 100644 --- a/exercises/05_ticket_v2/08_error_enums/src/lib.rs +++ b/exercises/05_ticket_v2/08_error_enums/src/lib.rs @@ -1,14 +1,24 @@ // TODO: Use two variants, one for a title error and one for a description error. // Each variant should contain a string with the explanation of what went wrong exactly. // You'll have to update the implementation of `Ticket::new` as well. -enum TicketNewError {} +#[derive(Debug)] +enum TicketNewError { + TitleError(String), + DescriptionError(String), +} // TODO: `easy_ticket` should panic when the title is invalid, using the error message // stored inside the relevant variant of the `TicketNewError` enum. // When the description is invalid, instead, it should use a default description: // "Description not provided". fn easy_ticket(title: String, description: String, status: Status) -> Ticket { - todo!() + match Ticket::new(title.clone(), description, status.clone()) { + Ok(ticket) => ticket, + Err(TicketNewError::DescriptionError(_)) => { + Ticket::new(title, "Description not provided".to_string(), status).unwrap() + } + Err(TicketNewError::TitleError(error)) => panic!("{error}"), + } } #[derive(Debug, PartialEq)] @@ -32,16 +42,24 @@ impl Ticket { status: Status, ) -> Result { if title.is_empty() { - return Err("Title cannot be empty".to_string()); + return Err(TicketNewError::TitleError( + "Title cannot be empty".to_string(), + )); } if title.len() > 50 { - return Err("Title cannot be longer than 50 bytes".to_string()); + return Err(TicketNewError::TitleError( + "Title cannot be longer than 50 bytes".to_string(), + )); } if description.is_empty() { - return Err("Description cannot be empty".to_string()); + return Err(TicketNewError::DescriptionError( + "Description cannot be empty".to_string(), + )); } if description.len() > 500 { - return Err("Description cannot be longer than 500 bytes".to_string()); + return Err(TicketNewError::DescriptionError( + "Description cannot be longer than 500 bytes".to_string(), + )); } Ok(Ticket { diff --git a/exercises/05_ticket_v2/09_error_trait/src/lib.rs b/exercises/05_ticket_v2/09_error_trait/src/lib.rs index 68b5769022..86cffc6bca 100644 --- a/exercises/05_ticket_v2/09_error_trait/src/lib.rs +++ b/exercises/05_ticket_v2/09_error_trait/src/lib.rs @@ -3,17 +3,37 @@ // The docs for the `std::fmt` module are a good place to start and look for examples: // https://doc.rust-lang.org/std/fmt/index.html#write +#[derive(Debug)] enum TicketNewError { TitleError(String), DescriptionError(String), } +impl std::fmt::Display for TicketNewError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + TicketNewError::TitleError(msg) => write!(f, "{}", msg), + TicketNewError::DescriptionError(msg) => write!(f, "{}", msg), + } + } +} + +impl std::error::Error for TicketNewError {} + // TODO: `easy_ticket` should panic when the title is invalid, using the error message // stored inside the relevant variant of the `TicketNewError` enum. // When the description is invalid, instead, it should use a default description: // "Description not provided". fn easy_ticket(title: String, description: String, status: Status) -> Ticket { - todo!() + match Ticket::new(title.clone(), description, status.clone()) { + Ok(ticket) => ticket, + Err(err) => match err { + TicketNewError::TitleError(_) => panic!("{err}"), + TicketNewError::DescriptionError(_) => { + Ticket::new(title, "Description not provided".to_string(), status).unwrap() + } + }, + } } #[derive(Debug, PartialEq, Clone)] diff --git a/exercises/05_ticket_v2/10_packages/src/lib.rs b/exercises/05_ticket_v2/10_packages/src/lib.rs new file mode 100644 index 0000000000..7d83484ea9 --- /dev/null +++ b/exercises/05_ticket_v2/10_packages/src/lib.rs @@ -0,0 +1,3 @@ +pub fn hello_world() { + println!("Hello, world!"); +} diff --git a/exercises/05_ticket_v2/11_dependencies/Cargo.toml b/exercises/05_ticket_v2/11_dependencies/Cargo.toml index c18abf92a8..f56c4207ec 100644 --- a/exercises/05_ticket_v2/11_dependencies/Cargo.toml +++ b/exercises/05_ticket_v2/11_dependencies/Cargo.toml @@ -2,3 +2,6 @@ name = "deps" version = "0.1.0" edition = "2021" + +[dependencies] +anyhow = "1.0.82" diff --git a/exercises/05_ticket_v2/12_thiserror/Cargo.toml b/exercises/05_ticket_v2/12_thiserror/Cargo.toml index fb9c7d5e3c..02ff2d7178 100644 --- a/exercises/05_ticket_v2/12_thiserror/Cargo.toml +++ b/exercises/05_ticket_v2/12_thiserror/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +thiserror = "1" [dev-dependencies] common = { path = "../../../helpers/common" } diff --git a/exercises/05_ticket_v2/12_thiserror/src/lib.rs b/exercises/05_ticket_v2/12_thiserror/src/lib.rs index 9289143a5c..a919f9b473 100644 --- a/exercises/05_ticket_v2/12_thiserror/src/lib.rs +++ b/exercises/05_ticket_v2/12_thiserror/src/lib.rs @@ -3,10 +3,15 @@ // a `String` field into each variant. // You'll also have to add `thiserror` as a dependency in the `Cargo.toml` file. +#[derive(Debug, thiserror::Error)] enum TicketNewError { + #[error("Title cannot be empty")] TitleCannotBeEmpty, + #[error("Title cannot be longer than 50 bytes")] TitleTooLong, + #[error("Description cannot be empty")] DescriptionCannotBeEmpty, + #[error("Description cannot be longer than 500 bytes")] DescriptionTooLong, } diff --git a/exercises/05_ticket_v2/13_try_from/Cargo.toml b/exercises/05_ticket_v2/13_try_from/Cargo.toml index 5d7035797d..1b3046e6c5 100644 --- a/exercises/05_ticket_v2/13_try_from/Cargo.toml +++ b/exercises/05_ticket_v2/13_try_from/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] +thiserror = "1.0.59" diff --git a/exercises/05_ticket_v2/13_try_from/src/lib.rs b/exercises/05_ticket_v2/13_try_from/src/lib.rs index e0e1115f9d..cdcb02c2b3 100644 --- a/exercises/05_ticket_v2/13_try_from/src/lib.rs +++ b/exercises/05_ticket_v2/13_try_from/src/lib.rs @@ -8,6 +8,35 @@ enum Status { Done, } +#[derive(Debug, thiserror::Error)] +#[error("{invalid_status} is not a valid status")] +struct ParseStatusError { + invalid_status: String, +} + +impl TryFrom for Status { + type Error = ParseStatusError; + + fn try_from(value: String) -> Result { + value.as_str().try_into() + } +} + +impl TryFrom<&str> for Status { + type Error = ParseStatusError; + + fn try_from(value: &str) -> Result { + match value.to_lowercase().as_str() { + "todo" => Ok(Status::ToDo), + "inprogress" => Ok(Status::InProgress), + "done" => Ok(Status::Done), + _ => Err(ParseStatusError { + invalid_status: value.to_string(), + }), + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/exercises/05_ticket_v2/14_source/Cargo.toml b/exercises/05_ticket_v2/14_source/Cargo.toml index 0742f2137a..88829de90e 100644 --- a/exercises/05_ticket_v2/14_source/Cargo.toml +++ b/exercises/05_ticket_v2/14_source/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -thiserror = "1.0.59" +thiserror = "1.0.69" [dev-dependencies] common = { path = "../../../helpers/common" } diff --git a/exercises/05_ticket_v2/14_source/src/lib.rs b/exercises/05_ticket_v2/14_source/src/lib.rs index 9f7cce55bf..f9fb6e77d5 100644 --- a/exercises/05_ticket_v2/14_source/src/lib.rs +++ b/exercises/05_ticket_v2/14_source/src/lib.rs @@ -1,4 +1,4 @@ -use crate::status::Status; +use crate::status::{ParseStatusError, Status}; // We've seen how to declare modules in one of the earliest exercises, but // we haven't seen how to extract them into separate files. @@ -23,6 +23,8 @@ pub enum TicketNewError { DescriptionCannotBeEmpty, #[error("Description cannot be longer than 500 bytes")] DescriptionTooLong, + #[error("{0}")] + InvalidStatus(#[from] ParseStatusError), } #[derive(Debug, PartialEq, Clone)] @@ -48,6 +50,7 @@ impl Ticket { } // TODO: Parse the status string into a `Status` enum. + let status = Status::try_from(status)?; Ok(Ticket { title, diff --git a/exercises/05_ticket_v2/15_outro/Cargo.toml b/exercises/05_ticket_v2/15_outro/Cargo.toml index dc32a4118f..2735220ce3 100644 --- a/exercises/05_ticket_v2/15_outro/Cargo.toml +++ b/exercises/05_ticket_v2/15_outro/Cargo.toml @@ -2,3 +2,6 @@ name = "outro_04" version = "0.1.0" edition = "2021" + +[dependencies] +thiserror = "1.0.59" diff --git a/exercises/05_ticket_v2/15_outro/src/description.rs b/exercises/05_ticket_v2/15_outro/src/description.rs index ecf55ad19d..35935ceadf 100644 --- a/exercises/05_ticket_v2/15_outro/src/description.rs +++ b/exercises/05_ticket_v2/15_outro/src/description.rs @@ -1,9 +1,45 @@ // TODO: Implement `TryFrom` and `TryFrom<&str>` for the `TicketDescription` type, // enforcing that the description is not empty and is not longer than 500 bytes. // Implement the traits required to make the tests pass too. - +#[derive(Debug, PartialEq, Clone)] pub struct TicketDescription(String); +#[derive(Debug, thiserror::Error)] +pub enum TicketDescriptionError { + #[error("The description cannot be empty")] + Empty, + #[error("The description cannot be longer than 500 bytes")] + TooLong, +} + +impl TryFrom for TicketDescription { + type Error = TicketDescriptionError; + + fn try_from(value: String) -> Result { + validate(&value)?; + Ok(Self(value)) + } +} + +impl TryFrom<&str> for TicketDescription { + type Error = TicketDescriptionError; + + fn try_from(value: &str) -> Result { + validate(value)?; + Ok(Self(value.to_string())) + } +} + +fn validate(description: &str) -> Result<(), TicketDescriptionError> { + if description.is_empty() { + Err(TicketDescriptionError::Empty) + } else if description.len() > 500 { + Err(TicketDescriptionError::TooLong) + } else { + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/exercises/05_ticket_v2/15_outro/src/status.rs b/exercises/05_ticket_v2/15_outro/src/status.rs index 4453d524f8..0611887d29 100644 --- a/exercises/05_ticket_v2/15_outro/src/status.rs +++ b/exercises/05_ticket_v2/15_outro/src/status.rs @@ -1,12 +1,43 @@ // TODO: Implement `TryFrom` and `TryFrom<&str>` for the `Status` enum. // The parsing should be case-insensitive. +#[derive(Debug, PartialEq, Clone)] pub enum Status { ToDo, InProgress, Done, } +impl TryFrom for Status { + type Error = ParseStatusError; + + fn try_from(value: String) -> Result { + let value = value.to_lowercase(); + match value.as_str() { + "todo" => Ok(Status::ToDo), + "inprogress" => Ok(Status::InProgress), + "done" => Ok(Status::Done), + _ => Err(ParseStatusError { + invalid_status: value, + }), + } + } +} + +impl TryFrom<&str> for Status { + type Error = ParseStatusError; + + fn try_from(value: &str) -> Result { + value.to_lowercase().try_into() + } +} + +#[derive(Debug, thiserror::Error)] +#[error("`{invalid_status}` is not a valid status. Use one of: ToDo, InProgress, Done")] +pub struct ParseStatusError { + invalid_status: String, +} + #[cfg(test)] mod tests { use super::*; diff --git a/exercises/05_ticket_v2/15_outro/src/title.rs b/exercises/05_ticket_v2/15_outro/src/title.rs index 7c26c934c8..896fab5b52 100644 --- a/exercises/05_ticket_v2/15_outro/src/title.rs +++ b/exercises/05_ticket_v2/15_outro/src/title.rs @@ -2,8 +2,45 @@ // enforcing that the title is not empty and is not longer than 50 bytes. // Implement the traits required to make the tests pass too. +#[derive(Debug, PartialEq, Clone)] pub struct TicketTitle(String); +#[derive(Debug, thiserror::Error)] +pub enum TicketTitleError { + #[error("The title cannot be empty")] + Empty, + #[error("The title cannot be longer than 50 bytes")] + TooLong, +} + +impl TryFrom for TicketTitle { + type Error = TicketTitleError; + + fn try_from(value: String) -> Result { + validate(&value)?; + Ok(Self(value)) + } +} + +impl TryFrom<&str> for TicketTitle { + type Error = TicketTitleError; + + fn try_from(value: &str) -> Result { + validate(value)?; + Ok(Self(value.to_string())) + } +} + +fn validate(title: &str) -> Result<(), TicketTitleError> { + if title.is_empty() { + Err(TicketTitleError::Empty) + } else if title.len() > 50 { + Err(TicketTitleError::TooLong) + } else { + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/exercises/06_ticket_management/00_intro/src/lib.rs b/exercises/06_ticket_management/00_intro/src/lib.rs index 118e48375d..d0fd0dab13 100644 --- a/exercises/06_ticket_management/00_intro/src/lib.rs +++ b/exercises/06_ticket_management/00_intro/src/lib.rs @@ -1,6 +1,6 @@ fn intro() -> &'static str { // TODO: fix me ๐Ÿ‘‡ - "I'm ready to __!" + "I'm ready to build a ticket management system!" } #[cfg(test)] diff --git a/exercises/06_ticket_management/01_arrays/src/lib.rs b/exercises/06_ticket_management/01_arrays/src/lib.rs index e06cb2b2d9..58e3bd3ad1 100644 --- a/exercises/06_ticket_management/01_arrays/src/lib.rs +++ b/exercises/06_ticket_management/01_arrays/src/lib.rs @@ -1,7 +1,7 @@ // TODO: Flesh out the `WeekTemperatures` struct and its method implementations to pass the tests. pub struct WeekTemperatures { - // TODO + temperatures: [Option; 7], } pub enum Weekday { @@ -16,15 +16,31 @@ pub enum Weekday { impl WeekTemperatures { pub fn new() -> Self { - todo!() + WeekTemperatures { + temperatures: [None; 7], + } } pub fn get_temperature(&self, day: Weekday) -> Option { - todo!() + let index = weekday2index(&day); + self.temperatures[index] } pub fn set_temperature(&mut self, day: Weekday, temperature: i32) { - todo!() + let index = weekday2index(&day); + self.temperatures[index] = Some(temperature); + } +} + +fn weekday2index(day: &Weekday) -> usize { + match day { + Weekday::Monday => 0, + Weekday::Tuesday => 1, + Weekday::Wednesday => 2, + Weekday::Thursday => 3, + Weekday::Friday => 4, + Weekday::Saturday => 5, + Weekday::Sunday => 6, } } diff --git a/exercises/06_ticket_management/02_vec/src/lib.rs b/exercises/06_ticket_management/02_vec/src/lib.rs index 2e8b4985b3..41685da3c3 100644 --- a/exercises/06_ticket_management/02_vec/src/lib.rs +++ b/exercises/06_ticket_management/02_vec/src/lib.rs @@ -11,11 +11,12 @@ // We expect `fibonacci(0)` to return `0`, `fibonacci(1)` to return `1`, // `fibonacci(2)` to return `1`, and so on. pub fn fibonacci(n: u32) -> u32 { - // TODO: implement the `fibonacci` function - // - // Hint: use a `Vec` to memoize the results you have already calculated - // so that you don't have to recalculate them several times. - todo!() + let n = n as usize; + let mut memo = vec![0, 1]; + for i in 2..=n { + memo.push(memo[i - 1] + memo[i - 2]); + } + memo[n] } #[cfg(test)] diff --git a/exercises/06_ticket_management/03_resizing/src/lib.rs b/exercises/06_ticket_management/03_resizing/src/lib.rs index 000ca2d84b..f29eb7ef2b 100644 --- a/exercises/06_ticket_management/03_resizing/src/lib.rs +++ b/exercises/06_ticket_management/03_resizing/src/lib.rs @@ -12,6 +12,6 @@ mod tests { // Can you guess what the new capacity will be? // Beware that the standard library makes no guarantees about the // algorithm used to resize the vector, so this may change in the future. - assert_eq!(v.capacity(), todo!()); + assert_eq!(v.capacity(), 4); } } diff --git a/exercises/06_ticket_management/04_iterators/src/lib.rs b/exercises/06_ticket_management/04_iterators/src/lib.rs index e7eb9f9120..b76e858317 100644 --- a/exercises/06_ticket_management/04_iterators/src/lib.rs +++ b/exercises/06_ticket_management/04_iterators/src/lib.rs @@ -39,6 +39,15 @@ impl TicketStore { } } +impl IntoIterator for TicketStore { + type Item = Ticket; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.tickets.into_iter() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/exercises/06_ticket_management/05_iter/src/lib.rs b/exercises/06_ticket_management/05_iter/src/lib.rs index 71d3e51c62..89e04e7e25 100644 --- a/exercises/06_ticket_management/05_iter/src/lib.rs +++ b/exercises/06_ticket_management/05_iter/src/lib.rs @@ -34,6 +34,10 @@ impl TicketStore { pub fn add_ticket(&mut self, ticket: Ticket) { self.tickets.push(ticket); } + + pub fn iter(&self) -> std::slice::Iter { + self.tickets.iter() + } } #[cfg(test)] diff --git a/exercises/06_ticket_management/06_lifetimes/src/lib.rs b/exercises/06_ticket_management/06_lifetimes/src/lib.rs index 545ed75cc4..68a87a6b7b 100644 --- a/exercises/06_ticket_management/06_lifetimes/src/lib.rs +++ b/exercises/06_ticket_management/06_lifetimes/src/lib.rs @@ -36,6 +36,15 @@ impl TicketStore { } } +impl<'a> IntoIterator for &'a TicketStore { + type Item = &'a Ticket; + type IntoIter = std::slice::Iter<'a, Ticket>; + + fn into_iter(self) -> Self::IntoIter { + self.tickets.iter() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/exercises/06_ticket_management/07_combinators/src/lib.rs b/exercises/06_ticket_management/07_combinators/src/lib.rs index 2731211852..75af38c5ee 100644 --- a/exercises/06_ticket_management/07_combinators/src/lib.rs +++ b/exercises/06_ticket_management/07_combinators/src/lib.rs @@ -31,6 +31,13 @@ impl TicketStore { pub fn add_ticket(&mut self, ticket: Ticket) { self.tickets.push(ticket); } + + pub fn to_dos(&self) -> Vec<&Ticket> { + self.tickets + .iter() + .filter(|ticket| ticket.status == Status::ToDo) + .collect() + } } #[cfg(test)] diff --git a/exercises/06_ticket_management/08_impl_trait/src/lib.rs b/exercises/06_ticket_management/08_impl_trait/src/lib.rs index d8afbe01d7..922ee771c3 100644 --- a/exercises/06_ticket_management/08_impl_trait/src/lib.rs +++ b/exercises/06_ticket_management/08_impl_trait/src/lib.rs @@ -31,6 +31,12 @@ impl TicketStore { pub fn add_ticket(&mut self, ticket: Ticket) { self.tickets.push(ticket); } + + pub fn in_progress(&self) -> impl Iterator { + self.tickets + .iter() + .filter(|ticket| ticket.status == Status::InProgress) + } } #[cfg(test)] diff --git a/exercises/06_ticket_management/09_impl_trait_2/src/lib.rs b/exercises/06_ticket_management/09_impl_trait_2/src/lib.rs index 33e982b2af..c080376c98 100644 --- a/exercises/06_ticket_management/09_impl_trait_2/src/lib.rs +++ b/exercises/06_ticket_management/09_impl_trait_2/src/lib.rs @@ -33,7 +33,7 @@ impl TicketStore { // that can be infallibly converted into a `Ticket`. // This can make it nicer to use the method, as it removes the syntax noise of `.into()` // from the calling site. It can worsen the quality of the compiler error messages, though. - pub fn add_ticket(&mut self, ticket: impl Into) { + pub fn add_ticket>(&mut self, ticket: T) { self.tickets.push(ticket.into()); } } diff --git a/exercises/06_ticket_management/10_slices/src/lib.rs b/exercises/06_ticket_management/10_slices/src/lib.rs index 1d2c6f7f00..ffb54f8954 100644 --- a/exercises/06_ticket_management/10_slices/src/lib.rs +++ b/exercises/06_ticket_management/10_slices/src/lib.rs @@ -1,6 +1,10 @@ // TODO: Define a function named `sum` that takes a reference to a slice of `u32` and returns the sum of all // elements in the slice. +pub fn sum(slice: &[u32]) -> u32 { + slice.iter().sum() +} + #[cfg(test)] mod tests { use super::*; diff --git a/exercises/06_ticket_management/11_mutable_slices/src/lib.rs b/exercises/06_ticket_management/11_mutable_slices/src/lib.rs index 4ba888c790..593fc4f547 100644 --- a/exercises/06_ticket_management/11_mutable_slices/src/lib.rs +++ b/exercises/06_ticket_management/11_mutable_slices/src/lib.rs @@ -1,6 +1,12 @@ // TODO: Define a function named `squared` that raises all `i32`s within a slice to the power of 2. // The slice should be modified in place. +pub fn squared(slice: &mut [i32]) { + for i in slice.iter_mut() { + *i *= *i; + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/exercises/06_ticket_management/12_two_states/src/lib.rs b/exercises/06_ticket_management/12_two_states/src/lib.rs index 10b5cb1d35..e51934c10a 100644 --- a/exercises/06_ticket_management/12_two_states/src/lib.rs +++ b/exercises/06_ticket_management/12_two_states/src/lib.rs @@ -11,6 +11,7 @@ use ticket_fields::{TicketDescription, TicketTitle}; #[derive(Clone)] pub struct TicketStore { tickets: Vec, + counter: u64, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -41,11 +42,25 @@ impl TicketStore { pub fn new() -> Self { Self { tickets: Vec::new(), + counter: 0, } } - pub fn add_ticket(&mut self, ticket: Ticket) { + pub fn add_ticket(&mut self, draft: TicketDraft) -> TicketId { + let id = self.counter; + self.counter += 1; + let ticket = Ticket { + id: TicketId(id), + title: draft.title, + description: draft.description, + status: Status::ToDo, + }; self.tickets.push(ticket); + TicketId(id) + } + + pub fn get(&self, id: TicketId) -> Option<&Ticket> { + self.tickets.iter().find(|ticket| ticket.id == id) } } diff --git a/exercises/06_ticket_management/13_index/src/lib.rs b/exercises/06_ticket_management/13_index/src/lib.rs index 0b08cc11b5..ea27bcfbdc 100644 --- a/exercises/06_ticket_management/13_index/src/lib.rs +++ b/exercises/06_ticket_management/13_index/src/lib.rs @@ -1,5 +1,6 @@ // TODO: Implement `Index<&TicketId>` and `Index` for `TicketStore`. +use std::ops::Index; use ticket_fields::{TicketDescription, TicketTitle}; #[derive(Clone)] @@ -58,6 +59,22 @@ impl TicketStore { } } +impl Index for TicketStore { + type Output = Ticket; + + fn index(&self, id: TicketId) -> &Self::Output { + self.tickets.iter().find(|&t| t.id == id).unwrap() + } +} + +impl Index<&TicketId> for TicketStore { + type Output = Ticket; + + fn index(&self, id: &TicketId) -> &Self::Output { + &self[*id] + } +} + #[cfg(test)] mod tests { use crate::{Status, TicketDraft, TicketStore}; diff --git a/exercises/06_ticket_management/14_index_mut/src/lib.rs b/exercises/06_ticket_management/14_index_mut/src/lib.rs index fa3945160c..aba27d64d0 100644 --- a/exercises/06_ticket_management/14_index_mut/src/lib.rs +++ b/exercises/06_ticket_management/14_index_mut/src/lib.rs @@ -1,6 +1,6 @@ // TODO: Implement `IndexMut<&TicketId>` and `IndexMut` for `TicketStore`. -use std::ops::Index; +use std::ops::{Index, IndexMut}; use ticket_fields::{TicketDescription, TicketTitle}; #[derive(Clone)] @@ -75,6 +75,18 @@ impl Index<&TicketId> for TicketStore { } } +impl IndexMut for TicketStore { + fn index_mut(&mut self, index: TicketId) -> &mut Self::Output { + self.tickets.iter_mut().find(|t| t.id == index).unwrap() + } +} + +impl IndexMut<&TicketId> for TicketStore { + fn index_mut(&mut self, index: &TicketId) -> &mut Self::Output { + &mut self[*index] + } +} + #[cfg(test)] mod tests { use crate::{Status, TicketDraft, TicketStore}; diff --git a/exercises/06_ticket_management/15_hashmap/src/lib.rs b/exercises/06_ticket_management/15_hashmap/src/lib.rs index ea109a6fef..c50fb57dda 100644 --- a/exercises/06_ticket_management/15_hashmap/src/lib.rs +++ b/exercises/06_ticket_management/15_hashmap/src/lib.rs @@ -11,7 +11,7 @@ pub struct TicketStore { counter: u64, } -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct TicketId(u64); #[derive(Clone, Debug, PartialEq)] @@ -38,7 +38,7 @@ pub enum Status { impl TicketStore { pub fn new() -> Self { Self { - tickets: todo!(), + tickets: HashMap::new(), counter: 0, } } @@ -52,16 +52,16 @@ impl TicketStore { description: ticket.description, status: Status::ToDo, }; - todo!(); + self.tickets.insert(id, ticket); id } pub fn get(&self, id: TicketId) -> Option<&Ticket> { - todo!() + self.tickets.get(&id) } pub fn get_mut(&mut self, id: TicketId) -> Option<&mut Ticket> { - todo!() + self.tickets.get_mut(&id) } } diff --git a/exercises/06_ticket_management/16_btreemap/src/lib.rs b/exercises/06_ticket_management/16_btreemap/src/lib.rs index d9af95d2d8..ddbc4322de 100644 --- a/exercises/06_ticket_management/16_btreemap/src/lib.rs +++ b/exercises/06_ticket_management/16_btreemap/src/lib.rs @@ -13,7 +13,7 @@ pub struct TicketStore { counter: u64, } -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Ord, PartialOrd, Eq)] pub struct TicketId(u64); #[derive(Clone, Debug, PartialEq)] @@ -40,7 +40,7 @@ pub enum Status { impl TicketStore { pub fn new() -> Self { Self { - tickets: todo!(), + tickets: BTreeMap::new(), counter: 0, } } @@ -54,16 +54,16 @@ impl TicketStore { description: ticket.description, status: Status::ToDo, }; - todo!(); + self.tickets.insert(id, ticket); id } pub fn get(&self, id: TicketId) -> Option<&Ticket> { - todo!() + self.tickets.get(&id) } pub fn get_mut(&mut self, id: TicketId) -> Option<&mut Ticket> { - todo!() + self.tickets.get_mut(&id) } } @@ -95,6 +95,15 @@ impl IndexMut<&TicketId> for TicketStore { } } +impl<'a> IntoIterator for &'a TicketStore { + type Item = &'a Ticket; + type IntoIter = std::collections::btree_map::Values<'a, TicketId, Ticket>; + + fn into_iter(self) -> Self::IntoIter { + self.tickets.values() + } +} + #[cfg(test)] mod tests { use crate::{Status, TicketDraft, TicketId, TicketStore}; diff --git a/exercises/07_threads/00_intro/src/lib.rs b/exercises/07_threads/00_intro/src/lib.rs index df6490daf0..283d8d4407 100644 --- a/exercises/07_threads/00_intro/src/lib.rs +++ b/exercises/07_threads/00_intro/src/lib.rs @@ -1,6 +1,6 @@ fn intro() -> &'static str { // TODO: fix me ๐Ÿ‘‡ - "I'm ready to _!" + "I'm ready to build a concurrent ticket management system!" } #[cfg(test)] diff --git a/exercises/07_threads/01_threads/src/lib.rs b/exercises/07_threads/01_threads/src/lib.rs index 7d084ac1be..b31d0143c3 100644 --- a/exercises/07_threads/01_threads/src/lib.rs +++ b/exercises/07_threads/01_threads/src/lib.rs @@ -15,7 +15,15 @@ use std::thread; pub fn sum(v: Vec) -> i32 { - todo!() + let mid = v.len() / 2; + let (v1, v2) = v.split_at(mid); + let v1 = v1.to_vec(); + let v2 = v2.to_vec(); + + let handle1 = thread::spawn(move || v1.into_iter().sum::()); + let handle2 = thread::spawn(move || v2.into_iter().sum::()); + + handle1.join().unwrap() + handle2.join().unwrap() } #[cfg(test)] diff --git a/exercises/07_threads/02_static/src/lib.rs b/exercises/07_threads/02_static/src/lib.rs index 4b9241b8f3..9011128f58 100644 --- a/exercises/07_threads/02_static/src/lib.rs +++ b/exercises/07_threads/02_static/src/lib.rs @@ -4,7 +4,13 @@ use std::thread; pub fn sum(slice: &'static [i32]) -> i32 { - todo!() + let mid = slice.len() / 2; + let (slice1, slice2) = slice.split_at(mid); + + let handle1 = thread::spawn(move || slice1.iter().sum::()); + let handle2 = thread::spawn(move || slice2.iter().sum::()); + + handle1.join().unwrap() + handle2.join().unwrap() } #[cfg(test)] diff --git a/exercises/07_threads/03_leak/src/lib.rs b/exercises/07_threads/03_leak/src/lib.rs index fef6b46da6..9b7f81f400 100644 --- a/exercises/07_threads/03_leak/src/lib.rs +++ b/exercises/07_threads/03_leak/src/lib.rs @@ -6,7 +6,14 @@ use std::thread; pub fn sum(v: Vec) -> i32 { - todo!() + let v = v.leak(); + let mid = v.len() / 2; + let (v1, v2) = v.split_at(mid); + + let handle1 = thread::spawn(move || v1.into_iter().sum::()); + let handle2 = thread::spawn(move || v2.into_iter().sum::()); + + handle1.join().unwrap() + handle2.join().unwrap() } #[cfg(test)] diff --git a/exercises/07_threads/04_scoped_threads/src/lib.rs b/exercises/07_threads/04_scoped_threads/src/lib.rs index d81a3a9a97..eac1a0ba59 100644 --- a/exercises/07_threads/04_scoped_threads/src/lib.rs +++ b/exercises/07_threads/04_scoped_threads/src/lib.rs @@ -3,7 +3,14 @@ // Don't perform any heap allocation. Don't leak any memory. pub fn sum(v: Vec) -> i32 { - todo!() + let mid = v.len() / 2; + let (left, right) = v.split_at(mid); + + std::thread::scope(|s| { + let left = s.spawn(|| left.iter().sum::()); + let right = s.spawn(|| right.iter().sum::()); + left.join().unwrap() + right.join().unwrap() + }) } #[cfg(test)] diff --git a/exercises/07_threads/05_channels/src/lib.rs b/exercises/07_threads/05_channels/src/lib.rs index 175d1dd145..2e538020ee 100644 --- a/exercises/07_threads/05_channels/src/lib.rs +++ b/exercises/07_threads/05_channels/src/lib.rs @@ -1,10 +1,12 @@ +use crate::data::TicketDraft; +use crate::store::TicketStore; use std::sync::mpsc::{Receiver, Sender}; pub mod data; pub mod store; pub enum Command { - Insert(todo!()), + Insert(TicketDraft), } // Start the system by spawning the server thread. @@ -20,4 +22,13 @@ pub fn launch() -> Sender { // Enter a loop: wait for a command to show up in // the channel, then execute it, then start waiting // for the next command. -pub fn server(receiver: Receiver) {} +pub fn server(receiver: Receiver) { + let mut store = TicketStore::new(); + while let Ok(command) = receiver.recv() { + match command { + Command::Insert(ticket_draft) => { + store.add_ticket(ticket_draft); + } + } + } +} diff --git a/exercises/07_threads/05_channels/tests/insert.rs b/exercises/07_threads/05_channels/tests/insert.rs index 651a467b23..bb72b1aba8 100644 --- a/exercises/07_threads/05_channels/tests/insert.rs +++ b/exercises/07_threads/05_channels/tests/insert.rs @@ -26,7 +26,7 @@ fn ready() { // since our server doesn't expose any **read** actions. // We have no way to know if the inserts are actually happening and if they // are happening correctly. - let move_forward = false; + let move_forward = true; assert!(move_forward); } diff --git a/exercises/07_threads/06_interior_mutability/src/lib.rs b/exercises/07_threads/06_interior_mutability/src/lib.rs index 37d4d4fe32..b937b689a9 100644 --- a/exercises/07_threads/06_interior_mutability/src/lib.rs +++ b/exercises/07_threads/06_interior_mutability/src/lib.rs @@ -6,18 +6,18 @@ use std::rc::Rc; pub struct DropTracker { value: T, - counter: todo!(), + counter: Rc>, } impl DropTracker { - pub fn new(value: T, counter: todo!()) -> Self { + pub fn new(value: T, counter: Rc>) -> Self { Self { value, counter } } } impl Drop for DropTracker { fn drop(&mut self) { - todo!() + *self.counter.borrow_mut() += 1; } } diff --git a/exercises/07_threads/07_ack/src/lib.rs b/exercises/07_threads/07_ack/src/lib.rs index 746c35526d..93bd9e87da 100644 --- a/exercises/07_threads/07_ack/src/lib.rs +++ b/exercises/07_threads/07_ack/src/lib.rs @@ -1,13 +1,20 @@ +use crate::data::{Ticket, TicketDraft}; +use crate::store::{TicketId, TicketStore}; use std::sync::mpsc::{Receiver, Sender}; -use crate::store::TicketStore; pub mod data; pub mod store; // Refer to the tests to understand the expected schema. pub enum Command { - Insert { todo!() }, - Get { todo!() } + Insert { + draft: TicketDraft, + response_sender: Sender, + }, + Get { + id: TicketId, + response_sender: Sender>, + }, } pub fn launch() -> Sender { @@ -21,19 +28,25 @@ pub fn server(receiver: Receiver) { let mut store = TicketStore::new(); loop { match receiver.recv() { - Ok(Command::Insert {}) => { - todo!() + Ok(Command::Insert { + draft, + response_sender, + }) => { + let id = store.add_ticket(draft); + let _ = response_sender.send(id); } Ok(Command::Get { - todo!() + id, + response_sender, }) => { - todo!() + let ticket = store.get(id); + let _ = response_sender.send(ticket.cloned()); } Err(_) => { // There are no more senders, so we can safely break // and shut down the server. - break - }, + break; + } } } } diff --git a/exercises/07_threads/08_client/src/lib.rs b/exercises/07_threads/08_client/src/lib.rs index a934bd308f..edc6f9d687 100644 --- a/exercises/07_threads/08_client/src/lib.rs +++ b/exercises/07_threads/08_client/src/lib.rs @@ -7,23 +7,39 @@ pub mod store; #[derive(Clone)] // TODO: flesh out the client implementation. -pub struct TicketStoreClient {} +pub struct TicketStoreClient { + sender: Sender, +} impl TicketStoreClient { // Feel free to panic on all errors, for simplicity. pub fn insert(&self, draft: TicketDraft) -> TicketId { - todo!() + let (response_sender, response_receiver) = std::sync::mpsc::channel(); + self.sender + .send(Command::Insert { + draft, + response_channel: response_sender, + }) + .unwrap(); + response_receiver.recv().unwrap() } pub fn get(&self, id: TicketId) -> Option { - todo!() + let (response_sender, response_receiver) = std::sync::mpsc::channel(); + self.sender + .send(Command::Get { + id, + response_channel: response_sender, + }) + .unwrap(); + response_receiver.recv().unwrap() } } pub fn launch() -> TicketStoreClient { let (sender, receiver) = std::sync::mpsc::channel(); std::thread::spawn(move || server(receiver)); - todo!() + TicketStoreClient { sender } } // No longer public! This becomes an internal detail of the library now. diff --git a/exercises/07_threads/09_bounded/Cargo.toml b/exercises/07_threads/09_bounded/Cargo.toml index 506d14a29c..b9e755158f 100644 --- a/exercises/07_threads/09_bounded/Cargo.toml +++ b/exercises/07_threads/09_bounded/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] +thiserror = "1.0.60" ticket_fields = { path = "../../../helpers/ticket_fields" } diff --git a/exercises/07_threads/09_bounded/src/lib.rs b/exercises/07_threads/09_bounded/src/lib.rs index e661e68fca..4b0afe1e43 100644 --- a/exercises/07_threads/09_bounded/src/lib.rs +++ b/exercises/07_threads/09_bounded/src/lib.rs @@ -1,44 +1,62 @@ // TODO: Convert the implementation to use bounded channels. use crate::data::{Ticket, TicketDraft}; use crate::store::{TicketId, TicketStore}; -use std::sync::mpsc::{Receiver, Sender}; +use std::sync::mpsc::{Receiver, Sender, SyncSender, TrySendError}; pub mod data; pub mod store; #[derive(Clone)] pub struct TicketStoreClient { - sender: todo!(), + sender: SyncSender, } impl TicketStoreClient { - pub fn insert(&self, draft: TicketDraft) -> Result { - todo!() + pub fn insert(&self, draft: TicketDraft) -> Result { + let (response_sender, response_receiver) = std::sync::mpsc::sync_channel(1); + self.sender + .try_send(Command::Insert { + draft, + response_channel: response_sender, + }) + .map_err(|_| OverloadedError)?; + Ok(response_receiver.recv().unwrap()) } - pub fn get(&self, id: TicketId) -> Result, todo!()> { - todo!() + pub fn get(&self, id: TicketId) -> Result, OverloadedError> { + let (response_sender, response_receiver) = std::sync::mpsc::sync_channel(1); + self.sender + .try_send(Command::Get { + id, + response_channel: response_sender, + }) + .map_err(|_| OverloadedError)?; + Ok(response_receiver.recv().unwrap()) } } +#[derive(Debug, thiserror::Error)] +#[error("The store is overloaded")] +pub struct OverloadedError; + pub fn launch(capacity: usize) -> TicketStoreClient { - todo!(); + let (sender, receiver) = std::sync::mpsc::sync_channel(capacity); std::thread::spawn(move || server(receiver)); - todo!() + TicketStoreClient { sender } } enum Command { Insert { draft: TicketDraft, - response_channel: todo!(), + response_channel: SyncSender, }, Get { id: TicketId, - response_channel: todo!(), + response_channel: SyncSender>, }, } -pub fn server(receiver: Receiver) { +fn server(receiver: Receiver) { let mut store = TicketStore::new(); loop { match receiver.recv() { @@ -47,14 +65,14 @@ pub fn server(receiver: Receiver) { response_channel, }) => { let id = store.add_ticket(draft); - todo!() + let _ = response_channel.send(id); } Ok(Command::Get { id, response_channel, }) => { let ticket = store.get(id); - todo!() + let _ = response_channel.send(ticket.cloned()); } Err(_) => { // There are no more senders, so we can safely break diff --git a/exercises/07_threads/10_patch/Cargo.toml b/exercises/07_threads/10_patch/Cargo.toml index 396b6f657a..05437bc1d2 100644 --- a/exercises/07_threads/10_patch/Cargo.toml +++ b/exercises/07_threads/10_patch/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -thiserror = "1.0.59" +thiserror = "1.0.69" ticket_fields = { path = "../../../helpers/ticket_fields" } diff --git a/exercises/07_threads/10_patch/src/lib.rs b/exercises/07_threads/10_patch/src/lib.rs index 492f767be9..f0a66d288f 100644 --- a/exercises/07_threads/10_patch/src/lib.rs +++ b/exercises/07_threads/10_patch/src/lib.rs @@ -35,7 +35,16 @@ impl TicketStoreClient { Ok(response_receiver.recv().unwrap()) } - pub fn update(&self, ticket_patch: TicketPatch) -> Result<(), OverloadedError> {} + pub fn update(&self, ticket_patch: TicketPatch) -> Result<(), OverloadedError> { + let (response_sender, response_receiver) = sync_channel(1); + self.sender + .try_send(Command::Update { + patch: ticket_patch, + response_channel: response_sender, + }) + .map_err(|_| OverloadedError)?; + Ok(response_receiver.recv().unwrap()) + } } #[derive(Debug, thiserror::Error)] @@ -85,7 +94,18 @@ pub fn server(receiver: Receiver) { patch, response_channel, }) => { - todo!() + if let Some(ticket) = store.get_mut(patch.id) { + if let Some(title) = patch.title { + ticket.title = title; + } + if let Some(description) = patch.description { + ticket.description = description; + } + if let Some(status) = patch.status { + ticket.status = status; + } + } + let _ = response_channel.send(()); } Err(_) => { // There are no more senders, so we can safely break diff --git a/exercises/07_threads/11_locks/Cargo.toml b/exercises/07_threads/11_locks/Cargo.toml index 49d0fa4c74..b84d50d120 100644 --- a/exercises/07_threads/11_locks/Cargo.toml +++ b/exercises/07_threads/11_locks/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -thiserror = "1.0.60" +thiserror = "1.0.69" ticket_fields = { path = "../../../helpers/ticket_fields" } diff --git a/exercises/07_threads/11_locks/src/store.rs b/exercises/07_threads/11_locks/src/store.rs index 9387499ec0..306e662c27 100644 --- a/exercises/07_threads/11_locks/src/store.rs +++ b/exercises/07_threads/11_locks/src/store.rs @@ -28,13 +28,13 @@ impl TicketStore { description: ticket.description, status: Status::ToDo, }; - todo!(); + self.tickets.insert(id, Arc::new(Mutex::new(ticket))); id } // The `get` method should return a handle to the ticket // which allows the caller to either read or modify the ticket. - pub fn get(&self, id: TicketId) -> Option { - todo!() + pub fn get(&self, id: TicketId) -> Option>> { + self.tickets.get(&id).cloned() } } diff --git a/exercises/07_threads/12_rw_lock/Cargo.toml b/exercises/07_threads/12_rw_lock/Cargo.toml index aa90f385a6..67738861c5 100644 --- a/exercises/07_threads/12_rw_lock/Cargo.toml +++ b/exercises/07_threads/12_rw_lock/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -thiserror = "1.0.60" +thiserror = "1.0.69" ticket_fields = { path = "../../../helpers/ticket_fields" } diff --git a/exercises/07_threads/12_rw_lock/src/lib.rs b/exercises/07_threads/12_rw_lock/src/lib.rs index 0c33f539e5..9164830f5d 100644 --- a/exercises/07_threads/12_rw_lock/src/lib.rs +++ b/exercises/07_threads/12_rw_lock/src/lib.rs @@ -1,7 +1,7 @@ +use std::sync::{Arc, Mutex, RwLock}; // TODO: Replace `Mutex` with `RwLock` in the `TicketStore` struct and // all other relevant places to allow multiple readers to access the ticket store concurrently. -use std::sync::mpsc::{sync_channel, Receiver, SyncSender, TrySendError}; -use std::sync::{Arc, Mutex}; +use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; use crate::data::{Ticket, TicketDraft}; use crate::store::{TicketId, TicketStore}; @@ -26,7 +26,7 @@ impl TicketStoreClient { Ok(response_receiver.recv().unwrap()) } - pub fn get(&self, id: TicketId) -> Result>>, OverloadedError> { + pub fn get(&self, id: TicketId) -> Result>>, OverloadedError> { let (response_sender, response_receiver) = sync_channel(1); self.sender .try_send(Command::Get { @@ -55,7 +55,7 @@ enum Command { }, Get { id: TicketId, - response_channel: SyncSender>>>, + response_channel: SyncSender>>>, }, } diff --git a/exercises/07_threads/12_rw_lock/src/store.rs b/exercises/07_threads/12_rw_lock/src/store.rs index 7387efdcb3..c70867c236 100644 --- a/exercises/07_threads/12_rw_lock/src/store.rs +++ b/exercises/07_threads/12_rw_lock/src/store.rs @@ -1,13 +1,13 @@ use crate::data::{Status, Ticket, TicketDraft}; use std::collections::BTreeMap; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, RwLock}; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct TicketId(u64); #[derive(Clone)] pub struct TicketStore { - tickets: BTreeMap>>, + tickets: BTreeMap>>, counter: u64, } @@ -28,14 +28,14 @@ impl TicketStore { description: ticket.description, status: Status::ToDo, }; - let ticket = Arc::new(Mutex::new(ticket)); + let ticket = Arc::new(RwLock::new(ticket)); self.tickets.insert(id, ticket); id } // The `get` method should return a handle to the ticket // which allows the caller to either read or modify the ticket. - pub fn get(&self, id: TicketId) -> Option>> { + pub fn get(&self, id: TicketId) -> Option>> { self.tickets.get(&id).cloned() } } diff --git a/exercises/07_threads/13_without_channels/tests/check.rs b/exercises/07_threads/13_without_channels/tests/check.rs index e0d9c88e37..a915761ba2 100644 --- a/exercises/07_threads/13_without_channels/tests/check.rs +++ b/exercises/07_threads/13_without_channels/tests/check.rs @@ -7,7 +7,7 @@ use without_channels::store::TicketStore; #[test] fn works() { - let store = todo!(); + let store = Arc::new(RwLock::new(TicketStore::new())); let store1 = store.clone(); let client1 = spawn(move || { diff --git a/exercises/07_threads/14_sync/src/lib.rs b/exercises/07_threads/14_sync/src/lib.rs index c67d0f7c06..b698498b94 100644 --- a/exercises/07_threads/14_sync/src/lib.rs +++ b/exercises/07_threads/14_sync/src/lib.rs @@ -1,6 +1,6 @@ // Not much to be exercised on `Sync`, just a thing to remember. fn outro() -> &'static str { - "I have a good understanding of __!" + "I have a good understanding of Send and Sync!" } #[cfg(test)] diff --git a/exercises/08_futures/00_intro/src/lib.rs b/exercises/08_futures/00_intro/src/lib.rs index c730220b54..d4644268e2 100644 --- a/exercises/08_futures/00_intro/src/lib.rs +++ b/exercises/08_futures/00_intro/src/lib.rs @@ -1,6 +1,6 @@ fn intro() -> &'static str { // TODO: fix me ๐Ÿ‘‡ - "I'm ready to _!" + "I'm ready to learn about futures!" } #[cfg(test)] diff --git a/exercises/08_futures/01_async_fn/Cargo.toml b/exercises/08_futures/01_async_fn/Cargo.toml index 28433da554..1b14957276 100644 --- a/exercises/08_futures/01_async_fn/Cargo.toml +++ b/exercises/08_futures/01_async_fn/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -anyhow = "1.0.83" +anyhow = "1.0.100" tokio = { version = "1", features = ["full"] } diff --git a/exercises/08_futures/01_async_fn/src/lib.rs b/exercises/08_futures/01_async_fn/src/lib.rs index b8a83d867c..c9a59f9022 100644 --- a/exercises/08_futures/01_async_fn/src/lib.rs +++ b/exercises/08_futures/01_async_fn/src/lib.rs @@ -11,7 +11,11 @@ use tokio::net::TcpListener; // - `tokio::net::TcpStream::split` to obtain a reader and a writer from the socket // - `tokio::io::copy` to copy data from the reader to the writer pub async fn echo(listener: TcpListener) -> Result<(), anyhow::Error> { - todo!() + loop { + let (mut socket, _) = listener.accept().await?; + let (mut reader, mut writer) = socket.split(); + tokio::io::copy(&mut reader, &mut writer).await?; + } } #[cfg(test)] diff --git a/exercises/08_futures/02_spawn/Cargo.toml b/exercises/08_futures/02_spawn/Cargo.toml index 27c1ca3bd7..bc8bbbf8ab 100644 --- a/exercises/08_futures/02_spawn/Cargo.toml +++ b/exercises/08_futures/02_spawn/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -anyhow = "1.0.83" +anyhow = "1.0.100" tokio = { version = "1", features = ["full"] } diff --git a/exercises/08_futures/02_spawn/src/lib.rs b/exercises/08_futures/02_spawn/src/lib.rs index 9e00f3695e..c678ee1c34 100644 --- a/exercises/08_futures/02_spawn/src/lib.rs +++ b/exercises/08_futures/02_spawn/src/lib.rs @@ -4,7 +4,22 @@ use tokio::net::TcpListener; // Multiple connections (on the same listeners) should be processed concurrently. // The received data should be echoed back to the client. pub async fn echoes(first: TcpListener, second: TcpListener) -> Result<(), anyhow::Error> { - todo!() + let handle1 = tokio::spawn(echo(first)); + let handle2 = tokio::spawn(echo(second)); + let (outcome1, outcome2) = tokio::join!(handle1, handle2); + outcome1??; + outcome2??; + Ok(()) +} + +async fn echo(listener: TcpListener) -> Result<(), anyhow::Error> { + loop { + let (mut socket, _) = listener.accept().await?; + tokio::spawn(async move { + let (mut reader, mut writer) = socket.split(); + tokio::io::copy(&mut reader, &mut writer).await.unwrap(); + }); + } } #[cfg(test)] diff --git a/exercises/08_futures/03_runtime/Cargo.toml b/exercises/08_futures/03_runtime/Cargo.toml index d1b3ef2aeb..c46ab2be73 100644 --- a/exercises/08_futures/03_runtime/Cargo.toml +++ b/exercises/08_futures/03_runtime/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -anyhow = "1.0.83" +anyhow = "1.0.100" tokio = { version = "1", features = ["full"] } diff --git a/exercises/08_futures/03_runtime/src/lib.rs b/exercises/08_futures/03_runtime/src/lib.rs index 087ddc09a8..89154b8aa2 100644 --- a/exercises/08_futures/03_runtime/src/lib.rs +++ b/exercises/08_futures/03_runtime/src/lib.rs @@ -2,6 +2,7 @@ // accept connections on both of them concurrently, and always reply to clients by sending // the `Display` representation of the `reply` argument as a response. use std::fmt::Display; +use std::sync::Arc; use tokio::io::AsyncWriteExt; use tokio::net::TcpListener; @@ -10,7 +11,25 @@ where // `T` cannot be cloned. How do you share it between the two server tasks? T: Display + Send + Sync + 'static, { - todo!() + let reply = Arc::new(reply); + let handle1 = tokio::spawn(_fixed_reply(first, Arc::clone(&reply))); + let handle2 = tokio::spawn(_fixed_reply(second, reply)); + + tokio::join!(handle1, handle2,); +} + +async fn _fixed_reply(listener: TcpListener, reply: Arc) +where + T: Display + Send + Sync + 'static, +{ + loop { + let (mut socket, _) = listener.accept().await.unwrap(); + let (_reader, mut writer) = socket.split(); + writer + .write_all(format!("{}", reply).as_bytes()) + .await + .unwrap(); + } } #[cfg(test)] diff --git a/exercises/08_futures/04_future/src/lib.rs b/exercises/08_futures/04_future/src/lib.rs index 8dc1c962d0..4980f8d621 100644 --- a/exercises/08_futures/04_future/src/lib.rs +++ b/exercises/08_futures/04_future/src/lib.rs @@ -10,7 +10,9 @@ fn spawner() { } async fn example() { - let non_send = Rc::new(1); + { + let non_send = Rc::new(1); + println!("{}", non_send); + } yield_now().await; - println!("{}", non_send); } diff --git a/exercises/08_futures/05_blocking/Cargo.toml b/exercises/08_futures/05_blocking/Cargo.toml index 963a3e255f..4d09431b44 100644 --- a/exercises/08_futures/05_blocking/Cargo.toml +++ b/exercises/08_futures/05_blocking/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -anyhow = "1.0.83" +anyhow = "1.0.100" tokio = { version = "1", features = ["full"] } diff --git a/exercises/08_futures/05_blocking/src/lib.rs b/exercises/08_futures/05_blocking/src/lib.rs index e9b4354770..34538cf6f7 100644 --- a/exercises/08_futures/05_blocking/src/lib.rs +++ b/exercises/08_futures/05_blocking/src/lib.rs @@ -4,15 +4,19 @@ // Use `spawn_blocking` inside `echo` to resolve the issue. use std::io::{Read, Write}; use tokio::net::TcpListener; +use tokio::task::spawn_blocking; pub async fn echo(listener: TcpListener) -> Result<(), anyhow::Error> { loop { let (socket, _) = listener.accept().await?; let mut socket = socket.into_std()?; - socket.set_nonblocking(false)?; - let mut buffer = Vec::new(); - socket.read_to_end(&mut buffer)?; - socket.write_all(&buffer)?; + spawn_blocking(move || -> Result<(), anyhow::Error> { + socket.set_nonblocking(false)?; + let mut buffer = Vec::new(); + socket.read_to_end(&mut buffer)?; + socket.write_all(&buffer)?; + Ok(()) + }); } } diff --git a/exercises/08_futures/06_async_aware_primitives/src/lib.rs b/exercises/08_futures/06_async_aware_primitives/src/lib.rs index 16efb4a72e..fe62b6bdac 100644 --- a/exercises/08_futures/06_async_aware_primitives/src/lib.rs +++ b/exercises/08_futures/06_async_aware_primitives/src/lib.rs @@ -4,7 +4,7 @@ /// the testing code too, yes). /// /// Can you understand the sequence of events that can lead to a deadlock? -use std::sync::mpsc; +use tokio::sync::mpsc; pub struct Message { payload: String, @@ -15,14 +15,15 @@ pub struct Message { /// channel to continue communicating with the caller. pub async fn pong(mut receiver: mpsc::Receiver) { loop { - if let Ok(msg) = receiver.recv() { + if let Some(msg) = receiver.recv().await { println!("Pong received: {}", msg.payload); - let (sender, new_receiver) = mpsc::channel(); + let (sender, new_receiver) = mpsc::channel(1); msg.response_channel .send(Message { payload: "pong".into(), response_channel: sender, }) + .await .unwrap(); receiver = new_receiver; } @@ -32,22 +33,23 @@ pub async fn pong(mut receiver: mpsc::Receiver) { #[cfg(test)] mod tests { use crate::{pong, Message}; - use std::sync::mpsc; + use tokio::sync::mpsc; #[tokio::test] async fn ping() { - let (sender, receiver) = mpsc::channel(); - let (response_sender, response_receiver) = mpsc::channel(); + let (sender, receiver) = mpsc::channel(1); + let (response_sender, mut response_receiver) = mpsc::channel(1); sender .send(Message { payload: "pong".into(), response_channel: response_sender, }) + .await .unwrap(); tokio::spawn(pong(receiver)); - let answer = response_receiver.recv().unwrap().payload; + let answer = response_receiver.recv().await.unwrap().payload; assert_eq!(answer, "pong"); } } diff --git a/exercises/08_futures/07_cancellation/src/lib.rs b/exercises/08_futures/07_cancellation/src/lib.rs index f62301e941..30c9c2f9a8 100644 --- a/exercises/08_futures/07_cancellation/src/lib.rs +++ b/exercises/08_futures/07_cancellation/src/lib.rs @@ -46,6 +46,6 @@ mod tests { let buffered = handle.await.unwrap(); let buffered = std::str::from_utf8(&buffered).unwrap(); - assert_eq!(buffered, ""); + assert_eq!(buffered, "hefrthta"); } } diff --git a/helpers/mdbook-exercise-linker/Cargo.toml b/helpers/mdbook-exercise-linker/Cargo.toml index 26574ee320..d08e2adc9f 100644 --- a/helpers/mdbook-exercise-linker/Cargo.toml +++ b/helpers/mdbook-exercise-linker/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -anyhow = "1.0.86" -clap = "4.5.4" -mdbook = "0.4.40" -semver = "1.0.23" -serde_json = "1.0.117" +anyhow = "1.0.100" +clap = "4.5.50" +mdbook = "0.4.52" +semver = "1.0.27" +serde_json = "1.0.145" diff --git a/helpers/mdbook-link-shortener/Cargo.toml b/helpers/mdbook-link-shortener/Cargo.toml index 944aedd5c4..a0eb6c3419 100644 --- a/helpers/mdbook-link-shortener/Cargo.toml +++ b/helpers/mdbook-link-shortener/Cargo.toml @@ -4,12 +4,12 @@ version = "0.1.0" edition = "2021" [dependencies] -anyhow = "1.0.86" +anyhow = "1.0.100" bimap = { version = "0.6.3", features = ["serde"] } -clap = { version = "4.5.4", features = ["derive"] } +clap = { version = "4.5.50", features = ["derive"] } itertools = "0.13.0" -mdbook = "0.4.40" -pulldown-cmark = "0.11.0" +mdbook = "0.4.52" +pulldown-cmark = "0.11.3" pulldown-cmark-to-cmark = "15" -semver = "1.0.23" -serde_json = "1.0.117" +semver = "1.0.27" +serde_json = "1.0.145" diff --git a/helpers/ticket_fields/Cargo.toml b/helpers/ticket_fields/Cargo.toml index 44704c37ed..75cc79652b 100644 --- a/helpers/ticket_fields/Cargo.toml +++ b/helpers/ticket_fields/Cargo.toml @@ -5,4 +5,4 @@ edition = "2021" [dependencies] common = { path = "../common" } -thiserror = "1.0.59" +thiserror = "1.0.69"