From 052260364a3dc52da57c46dced673d03d832e8be Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Sat, 19 Oct 2024 23:48:23 +0200 Subject: [PATCH] Chapter 3 to 6 --- Cargo.lock | 356 ++++++++++-------- exercises/03_ticket_v1/00_intro/src/lib.rs | 2 +- exercises/03_ticket_v1/01_struct/src/lib.rs | 11 + .../03_ticket_v1/02_validation/src/lib.rs | 32 +- exercises/03_ticket_v1/03_modules/src/lib.rs | 1 + .../03_ticket_v1/04_visibility/src/lib.rs | 16 +- .../03_ticket_v1/05_encapsulation/src/lib.rs | 12 + .../03_ticket_v1/06_ownership/src/lib.rs | 12 +- exercises/03_ticket_v1/07_setters/src/lib.rs | 38 +- exercises/03_ticket_v1/08_stack/src/lib.rs | 6 +- exercises/03_ticket_v1/09_heap/src/lib.rs | 4 +- .../10_references_in_memory/src/lib.rs | 6 +- .../03_ticket_v1/11_destructor/src/lib.rs | 2 +- exercises/03_ticket_v1/12_outro/src/lib.rs | 69 ++++ exercises/04_traits/00_intro/src/lib.rs | 2 +- exercises/04_traits/01_trait/src/lib.rs | 16 + exercises/04_traits/02_orphan_rule/src/lib.rs | 10 +- .../03_operator_overloading/src/lib.rs | 8 +- exercises/04_traits/04_derive/src/lib.rs | 2 +- .../04_traits/05_trait_bounds/src/lib.rs | 5 +- exercises/04_traits/06_str_slice/src/lib.rs | 6 +- exercises/04_traits/07_deref/src/lib.rs | 4 +- exercises/04_traits/08_sized/src/lib.rs | 2 +- exercises/04_traits/09_from/src/lib.rs | 6 + .../04_traits/10_assoc_vs_generic/src/lib.rs | 33 ++ exercises/04_traits/11_clone/src/lib.rs | 3 +- exercises/04_traits/12_copy/src/lib.rs | 10 + exercises/04_traits/13_drop/src/lib.rs | 22 ++ exercises/04_traits/14_outro/src/lib.rs | 69 ++++ exercises/05_ticket_v2/00_intro/src/lib.rs | 2 +- exercises/05_ticket_v2/01_enum/src/lib.rs | 14 +- exercises/05_ticket_v2/02_match/src/lib.rs | 7 +- .../03_variants_with_data/src/lib.rs | 5 +- exercises/05_ticket_v2/04_if_let/src/lib.rs | 6 +- .../05_ticket_v2/05_nullability/src/lib.rs | 5 +- .../05_ticket_v2/06_fallibility/src/lib.rs | 14 +- exercises/05_ticket_v2/07_unwrap/src/lib.rs | 50 ++- .../05_ticket_v2/08_error_enums/src/lib.rs | 68 +++- .../05_ticket_v2/09_error_trait/src/lib.rs | 87 +++-- exercises/05_ticket_v2/10_packages/src/lib.rs | 3 + .../05_ticket_v2/11_dependencies/Cargo.toml | 3 + .../05_ticket_v2/12_thiserror/Cargo.toml | 1 + .../05_ticket_v2/12_thiserror/src/lib.rs | 16 + exercises/05_ticket_v2/13_try_from/src/lib.rs | 19 + exercises/05_ticket_v2/14_source/src/lib.rs | 16 +- exercises/05_ticket_v2/15_outro/Cargo.toml | 3 + .../05_ticket_v2/15_outro/src/description.rs | 32 ++ exercises/05_ticket_v2/15_outro/src/status.rs | 20 + exercises/05_ticket_v2/15_outro/src/title.rs | 32 ++ .../06_ticket_management/00_intro/src/lib.rs | 2 +- .../06_ticket_management/01_arrays/src/lib.rs | 10 +- .../06_ticket_management/02_vec/Cargo.toml | 3 + .../06_ticket_management/02_vec/src/lib.rs | 18 +- .../03_resizing/src/lib.rs | 2 +- .../04_iterators/src/lib.rs | 9 + .../06_ticket_management/05_iter/src/lib.rs | 4 + .../06_lifetimes/src/lib.rs | 9 + .../07_combinators/src/lib.rs | 7 + .../08_impl_trait/src/lib.rs | 6 + .../09_impl_trait_2/src/lib.rs | 5 +- .../06_ticket_management/10_slices/src/lib.rs | 4 + .../11_mutable_slices/src/lib.rs | 6 + .../12_two_states/src/lib.rs | 17 +- .../06_ticket_management/13_index/src/lib.rs | 16 + .../14_index_mut/src/lib.rs | 14 +- .../15_hashmap/src/lib.rs | 10 +- .../16_btreemap/src/lib.rs | 18 +- exercises/07_threads/00_intro/src/lib.rs | 2 +- exercises/07_threads/01_threads/src/lib.rs | 10 +- exercises/07_threads/02_static/src/lib.rs | 7 +- exercises/07_threads/03_leak/src/lib.rs | 1 + 71 files changed, 1031 insertions(+), 317 deletions(-) create mode 100644 exercises/05_ticket_v2/10_packages/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d560369..0dc0878 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" @@ -105,9 +105,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "arrays" @@ -138,23 +138,23 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -240,9 +240,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cancellation" @@ -253,9 +253,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.7" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -284,9 +287,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.13" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -294,9 +297,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.13" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -307,18 +310,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.12" +version = "4.5.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8670053e87c316345e384ca1f3eba3006fc6355ed8b8a1140d104e109e3df34" +checksum = "9646e2e245bf62f45d39a0f3f36f1171ad1ea0d6967fd114bca72cb02a8fcdfb" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", @@ -366,15 +369,15 @@ 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.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -443,6 +446,9 @@ dependencies = [ [[package]] name = "deps" version = "0.1.0" +dependencies = [ + "anyhow", +] [[package]] name = "deref" @@ -566,20 +572,20 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] @@ -633,9 +639,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -643,15 +649,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-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 +666,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", @@ -717,15 +723,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "globset" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", "bstr", @@ -769,9 +775,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "hashmap" @@ -869,9 +875,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -887,9 +893,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -911,9 +917,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -952,9 +958,9 @@ version = "0.1.0" [[package]] name = "ignore" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" dependencies = [ "crossbeam-deque", "globset", @@ -996,9 +1002,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.3.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", "hashbrown", @@ -1097,9 +1103,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -1124,15 +1130,21 @@ dependencies = [ "libc", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "leaking" version = "0.1.0" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libdbus-sys" @@ -1144,6 +1156,17 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall", +] + [[package]] name = "lifetime" version = "0.1.0" @@ -1267,7 +1290,7 @@ dependencies = [ "clap", "itertools", "mdbook", - "pulldown-cmark 0.11.0", + "pulldown-cmark 0.11.3", "pulldown-cmark-to-cmark", "semver", "serde_json", @@ -1297,11 +1320,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -1318,9 +1341,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", @@ -1399,29 +1422,29 @@ dependencies = [ [[package]] name = "object" -version = "0.36.2" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opener" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8df34be653210fbe9ffaff41d3b92721c56ce82dfee58ee684f9afb5e3a90c0" +checksum = "d0812e5e4df08da354c851a3376fead46db31c2214f849d3de356d774d057681" dependencies = [ "bstr", "dbus", "normpath", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1439,6 +1462,9 @@ version = "0.1.0" [[package]] name = "outro_04" version = "0.1.0" +dependencies = [ + "thiserror", +] [[package]] name = "outro_08" @@ -1485,7 +1511,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.3", + "redox_syscall", "smallvec", "windows-targets 0.52.6", ] @@ -1500,9 +1526,9 @@ dependencies = [ [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" [[package]] name = "percent-encoding" @@ -1512,9 +1538,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.11" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" dependencies = [ "memchr", "thiserror", @@ -1523,9 +1549,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.11" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" dependencies = [ "pest", "pest_generator", @@ -1533,9 +1559,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.11" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" dependencies = [ "pest", "pest_meta", @@ -1546,9 +1572,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.11" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" dependencies = [ "once_cell", "pest", @@ -1614,18 +1640,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", @@ -1646,9 +1672,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "ppv-lite86" @@ -1667,9 +1693,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] @@ -1688,9 +1714,9 @@ 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", "getopts", @@ -1717,14 +1743,14 @@ 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.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1761,18 +1787,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -1783,9 +1800,9 @@ version = "0.1.0" [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", @@ -1795,9 +1812,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -1806,9 +1823,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "resizing" @@ -1837,9 +1854,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", @@ -1899,18 +1916,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -1919,9 +1936,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -2099,9 +2116,9 @@ version = "0.1.0" [[package]] name = "syn" -version = "2.0.72" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -2118,15 +2135,15 @@ version = "0.1.0" [[package]] name = "tempfile" -version = "3.11.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2142,28 +2159,28 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" dependencies = [ "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -2175,6 +2192,7 @@ name = "thiserror_" version = "0.1.0" dependencies = [ "common", + "thiserror", ] [[package]] @@ -2206,14 +2224,14 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.2" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", - "mio 1.0.1", + "mio 1.0.2", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -2247,9 +2265,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -2275,9 +2293,9 @@ checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" [[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" @@ -2351,9 +2369,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[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" @@ -2366,30 +2384,30 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unwrap" @@ -2442,6 +2460,9 @@ dependencies = [ [[package]] name = "vec" version = "0.1.0" +dependencies = [ + "lazy_static", +] [[package]] name = "version_check" @@ -2508,19 +2529,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", @@ -2533,9 +2555,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2543,9 +2565,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", @@ -2556,9 +2578,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "welcome_00" diff --git a/exercises/03_ticket_v1/00_intro/src/lib.rs b/exercises/03_ticket_v1/00_intro/src/lib.rs index f7afa47..c52e3ac 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 1119e33..df71eb4 100644 --- a/exercises/03_ticket_v1/01_struct/src/lib.rs +++ b/exercises/03_ticket_v1/01_struct/src/lib.rs @@ -5,6 +5,17 @@ // 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 { + pub fn is_available(&self) -> bool { + self.quantity > 0 + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/exercises/03_ticket_v1/02_validation/src/lib.rs b/exercises/03_ticket_v1/02_validation/src/lib.rs index 7eaa5e5..6456a17 100644 --- a/exercises/03_ticket_v1/02_validation/src/lib.rs +++ b/exercises/03_ticket_v1/02_validation/src/lib.rs @@ -1,3 +1,13 @@ +// enum Status { +// Todo, +// InProgress, +// Done, +// } + +// impl From for Status { +// fn from(str: String) -> Self {} +// } + struct Ticket { title: String, description: String, @@ -18,7 +28,27 @@ 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!(); + match status.as_str() { + "To-Do" | "In Progress" | "Done" => {} + _ => panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed"), + } + + 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"); + } + 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 df07620..f93112b 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 b494fc9..65a1593 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 91e06eb..44ebdd3 100644 --- a/exercises/03_ticket_v1/05_encapsulation/src/lib.rs +++ b/exercises/03_ticket_v1/05_encapsulation/src/lib.rs @@ -30,6 +30,18 @@ pub mod ticket { } } + pub fn title(self) -> String { + self.title + } + + pub fn description(self) -> String { + self.description + } + + pub fn status(self) -> String { + self.status + } + // TODO: Add three public methods to the `Ticket` struct: // - `title` that returns the `title` field. // - `description` that returns the `description` field. diff --git a/exercises/03_ticket_v1/06_ownership/src/lib.rs b/exercises/03_ticket_v1/06_ownership/src/lib.rs index ded2ad8..4ab49f1 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 e13ec87..9d66e2f 100644 --- a/exercises/03_ticket_v1/07_setters/src/lib.rs +++ b/exercises/03_ticket_v1/07_setters/src/lib.rs @@ -11,40 +11,66 @@ pub struct Ticket { impl Ticket { pub fn new(title: String, description: String, status: String) -> Ticket { + Ticket::check_title(&title); + Ticket::check_description(&description); + Ticket::check_status(&status); + Ticket { + title, + description, + status, + } + } + + fn check_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 check_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 check_status(status: &String) { if status != "To-Do" && status != "In Progress" && status != "Done" { panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed"); } - - Ticket { - title, - description, - status, - } } pub fn title(&self) -> &String { &self.title } + pub fn set_title(&mut self, title: String) { + Ticket::check_title(&title); + self.title = title; + } + pub fn description(&self) -> &String { &self.description } + pub fn set_description(&mut self, description: String) { + Ticket::check_description(&description); + self.description = description; + } + pub fn status(&self) -> &String { &self.status } + + pub fn set_status(&mut self, status: String) { + Ticket::check_status(&status); + self.status = status; + } } #[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 e97518c..ad7d2a4 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 24d0c6e..5e24f6b 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] @@ -23,6 +23,6 @@ mod tests { // but, in general, the memory layout of structs is a more complex topic. // 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::(), todo!()); + 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 d580758..d184a19 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 @@ -13,16 +13,16 @@ mod tests { #[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 45bc89c..6555fbb 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 15c99b8..5ae1621 100644 --- a/exercises/03_ticket_v1/12_outro/src/lib.rs +++ b/exercises/03_ticket_v1/12_outro/src/lib.rs @@ -11,3 +11,72 @@ // 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) -> Self { + Order::check_product_name(&product_name); + Order::check_quantity(quantity); + Order::check_unit_price(unit_price); + + Order { + product_name, + quantity, + unit_price, + } + } + + fn check_product_name(product_name: &String) { + if product_name.len() == 0 || product_name.len() > 300 { + panic!("Product name cannot be empty or be longer than 300 bytes"); + } + } + + fn check_quantity(quantity: u32) { + if quantity == 0 { + panic!("Quantity must be greater than 0"); + } + } + + fn check_unit_price(unit_price: u32) { + if unit_price == 0 { + panic!("Unit price must be greater than 0"); + } + } + + pub fn product_name(&self) -> &String { + &self.product_name + } + + pub fn set_product_name(&mut self, product_name: String) { + Order::check_product_name(&product_name); + self.product_name = product_name; + } + + pub fn quantity(&self) -> &u32 { + &self.quantity + } + + pub fn set_quantity(&mut self, quantity: u32) { + Order::check_quantity(quantity); + self.quantity = quantity; + } + + pub fn unit_price(&self) -> &u32 { + &self.unit_price + } + + pub fn set_unit_price(&mut self, unit_price: u32) { + Order::check_unit_price(unit_price); + self.unit_price = unit_price; + } + + pub fn total(&self) -> u32 { + self.quantity * self.unit_price + } +} diff --git a/exercises/04_traits/00_intro/src/lib.rs b/exercises/04_traits/00_intro/src/lib.rs index 9513649..1b0f8ee 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 258eac5..af400da 100644 --- a/exercises/04_traits/01_trait/src/lib.rs +++ b/exercises/04_traits/01_trait/src/lib.rs @@ -3,6 +3,22 @@ // // 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 { use super::*; diff --git a/exercises/04_traits/02_orphan_rule/src/lib.rs b/exercises/04_traits/02_orphan_rule/src/lib.rs index b707c10..e862fa8 100644 --- a/exercises/04_traits/02_orphan_rule/src/lib.rs +++ b/exercises/04_traits/02_orphan_rule/src/lib.rs @@ -4,8 +4,8 @@ // 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!() - } -} +// 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 b75c0f1..06c2e36 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: &Ticket) -> 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 0a74a26..d39d6c5 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(PartialEq, Debug)] 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 10f0eb4..9327d86 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 +where + T: Ord, +{ 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 5bf6614..a37c0d4 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 c7a5c35..a21f9ef 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 a406fc5..0ebca5a 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 cc6f5b1..b7995d2 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 84f3e7b..f1b8407 100644 --- a/exercises/04_traits/10_assoc_vs_generic/src/lib.rs +++ b/exercises/04_traits/10_assoc_vs_generic/src/lib.rs @@ -12,6 +12,39 @@ // interested in learning more about it. // You don't have to though: it's perfectly okay to write three separate // implementations manually. Venture further only if you're curious. +trait Power { + fn power(&self, n: T) -> u32; +} + +impl Power for u32 { + fn power(&self, n: u16) -> u32 { + let mut v = *self; + for _ in 1..n { + v *= self; + } + v + } +} + +impl Power for u32 { + fn power(&self, n: u32) -> u32 { + let mut v = *self; + for _ in 1..n { + v *= self; + } + v + } +} + +impl Power<&u32> for u32 { + fn power(&self, n: &u32) -> u32 { + let mut v = *self; + for _ in 1..*n { + v *= self; + } + v + } +} #[cfg(test)] mod tests { diff --git a/exercises/04_traits/11_clone/src/lib.rs b/exercises/04_traits/11_clone/src/lib.rs index 4fbbe47..8d93806 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 d74720b..b9ebc02 100644 --- a/exercises/04_traits/12_copy/src/lib.rs +++ b/exercises/04_traits/12_copy/src/lib.rs @@ -1,6 +1,9 @@ // TODO: implement the necessary traits to make the test compile and pass. // You *can't* modify the test. +use std::ops::Add; + +#[derive(Clone, Copy, Debug, PartialEq)] pub struct WrappingU32 { value: u32, } @@ -11,6 +14,13 @@ impl WrappingU32 { } } +impl Add for WrappingU32 { + type Output = Self; + fn add(self, other: WrappingU32) -> Self::Output { + Self::new(self.value.wrapping_add(other.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 2124d34..7c23a90 100644 --- a/exercises/04_traits/13_drop/src/lib.rs +++ b/exercises/04_traits/13_drop/src/lib.rs @@ -2,6 +2,28 @@ // unless a certain operation has been performed on it. // You can see the expected API in the tests below. +struct DropBomb { + defused: bool, +} + +impl DropBomb { + pub fn new() -> Self { + Self { 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 { use super::*; diff --git a/exercises/04_traits/14_outro/src/lib.rs b/exercises/04_traits/14_outro/src/lib.rs index 547fd94..c58c507 100644 --- a/exercises/04_traits/14_outro/src/lib.rs +++ b/exercises/04_traits/14_outro/src/lib.rs @@ -8,3 +8,72 @@ // 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. + +use std::ops::Add; + +#[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 Add for SaturatingU16 { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + self + rhs.value + } +} + +impl Add<&SaturatingU16> for SaturatingU16 { + type Output = SaturatingU16; + fn add(self, rhs: &Self) -> Self::Output { + self + *rhs + } +} + +impl Add for SaturatingU16 { + type Output = SaturatingU16; + fn add(self, rhs: u16) -> Self::Output { + SaturatingU16 { + value: self.value.saturating_add(rhs), + } + } +} + +impl 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 ce1f75f..ff614d1 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 a3d9592..4490975 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, Clone, Copy)] 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 d30c569..12c7b4a 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 { + Self::Circle => 0, + Self::Square | Self::Rectangle => 4, + Self::Triangle => 3, + Self::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 03faf0c..e2f60af 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 { ref 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 0884fb5..5605cd8 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 f4e5cb2..8da9f35 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 { ref 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 3144bee..de9bc30 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".to_string()); } if title.len() > 50 { - panic!("Title cannot be longer than 50 bytes"); + return Err("Title cannot be longer than 50 bytes".to_string()); } if description.is_empty() { - panic!("Description cannot be empty"); + return Err("Description cannot be empty".to_string()); } if description.len() > 500 { - panic!("Description cannot be longer than 500 bytes"); + return Err("Description cannot be longer than 500 bytes".to_string()); } - 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 4b6419b..8905194 100644 --- a/exercises/05_ticket_v2/07_unwrap/src/lib.rs +++ b/exercises/05_ticket_v2/07_unwrap/src/lib.rs @@ -2,7 +2,20 @@ // 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!() + if let Err(str) = validated_title(&title) { + panic!("{}", str); + } + + Ticket::new( + title, + if let Err(_) = validation_description(&description) { + "Description not provided".to_string() + } else { + description + }, + status, + ) + .unwrap() } #[derive(Debug, PartialEq, Clone)] @@ -19,19 +32,34 @@ enum Status { Done, } +fn validated_title(title: &str) -> Result<(), String> { + if title.is_empty() { + Err("Title cannot be empty".to_string()) + } else if title.len() > 50 { + Err("Title cannot be longer than 50 bytes".to_string()) + } else { + Ok(()) + } +} + +fn validation_description(description: &str) -> Result<(), String> { + if description.is_empty() { + Err("Description cannot be empty".to_string()) + } else if description.len() > 500 { + Err("Description cannot be longer than 500 bytes".to_string()) + } else { + Ok(()) + } +} + impl Ticket { pub fn new(title: String, description: String, status: Status) -> Result { - if title.is_empty() { - return Err("Title cannot be empty".to_string()); - } - if title.len() > 50 { - return Err("Title cannot be longer than 50 bytes".to_string()); + if let Err(e) = validated_title(&title) { + return Err(e); } - if description.is_empty() { - return Err("Description cannot be empty".to_string()); - } - if description.len() > 500 { - return Err("Description cannot be longer than 500 bytes".to_string()); + + if let Err(e) = validation_description(&description) { + return Err(e); } Ok(Ticket { 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 c74fcc9..6a84edc 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,31 @@ // 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!() + if let Err(str) = validated_title(&title) { + panic!("{}", str); + } + + Ticket::new( + title, + if let Err(_) = validation_description(&description) { + "Description not provided".to_string() + } else { + description + }, + status, + ) + .unwrap() } #[derive(Debug, PartialEq)] @@ -25,30 +42,43 @@ enum Status { Done, } +fn validated_title(title: &str) -> Result<(), String> { + if title.is_empty() { + Err("Title cannot be empty".to_string()) + } else if title.len() > 50 { + Err("Title cannot be longer than 50 bytes".to_string()) + } else { + Ok(()) + } +} + +fn validation_description(description: &str) -> Result<(), String> { + if description.is_empty() { + Err("Description cannot be empty".to_string()) + } else if description.len() > 500 { + Err("Description cannot be longer than 500 bytes".to_string()) + } else { + Ok(()) + } +} + impl Ticket { pub fn new( title: String, description: String, status: Status, ) -> Result { - if title.is_empty() { - return Err("Title cannot be empty".to_string()); - } - if title.len() > 50 { - return Err("Title cannot be longer than 50 bytes".to_string()); + if let Err(e) = validated_title(&title) { + Err(TicketNewError::TitleError(e)) + } else if let Err(e) = validation_description(&description) { + Err(TicketNewError::DescriptionError(e)) + } else { + Ok(Ticket { + title, + description, + status, + }) } - if description.is_empty() { - return Err("Description cannot be empty".to_string()); - } - if description.len() > 500 { - return Err("Description cannot be longer than 500 bytes".to_string()); - } - - Ok(Ticket { - title, - description, - status, - }) } } 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 68b5769..ef054bc 100644 --- a/exercises/05_ticket_v2/09_error_trait/src/lib.rs +++ b/exercises/05_ticket_v2/09_error_trait/src/lib.rs @@ -2,18 +2,46 @@ // When implementing `Display`, you may want to use the `write!` macro from Rust's standard library. // 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 { + write!( + f, + "{}", + match self { + TicketNewError::TitleError(str) => str, + TicketNewError::DescriptionError(str) => str, + } + ) + } +} + +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!() + if let Err(str) = validated_title(&title) { + panic!("{str}"); + } + + Ticket::new( + title, + if let Err(_) = validation_description(&description) { + "Description not provided".to_string() + } else { + description + }, + status, + ) + .unwrap() } #[derive(Debug, PartialEq, Clone)] @@ -30,38 +58,43 @@ enum Status { Done, } +fn validated_title(title: &str) -> Result<(), String> { + if title.is_empty() { + Err("Title cannot be empty".to_string()) + } else if title.len() > 50 { + Err("Title cannot be longer than 50 bytes".to_string()) + } else { + Ok(()) + } +} + +fn validation_description(description: &str) -> Result<(), String> { + if description.is_empty() { + Err("Description cannot be empty".to_string()) + } else if description.len() > 500 { + Err("Description cannot be longer than 500 bytes".to_string()) + } else { + Ok(()) + } +} + impl Ticket { pub fn new( title: String, description: String, status: Status, ) -> Result { - if title.is_empty() { - return Err(TicketNewError::TitleError( - "Title cannot be empty".to_string(), - )); + if let Err(e) = validated_title(&title) { + Err(TicketNewError::TitleError(e)) + } else if let Err(e) = validation_description(&description) { + Err(TicketNewError::DescriptionError(e)) + } else { + Ok(Ticket { + title, + description, + status, + }) } - if title.len() > 50 { - return Err(TicketNewError::TitleError( - "Title cannot be longer than 50 bytes".to_string(), - )); - } - if description.is_empty() { - return Err(TicketNewError::DescriptionError( - "Description cannot be empty".to_string(), - )); - } - if description.len() > 500 { - return Err(TicketNewError::DescriptionError( - "Description cannot be longer than 500 bytes".to_string(), - )); - } - - Ok(Ticket { - title, - description, - status, - }) } } 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 0000000..29fc0a5 --- /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 c18abf9..f3d0e45 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" diff --git a/exercises/05_ticket_v2/12_thiserror/Cargo.toml b/exercises/05_ticket_v2/12_thiserror/Cargo.toml index fb9c7d5..02ff2d7 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 9289143..3a8c19a 100644 --- a/exercises/05_ticket_v2/12_thiserror/src/lib.rs +++ b/exercises/05_ticket_v2/12_thiserror/src/lib.rs @@ -3,13 +3,29 @@ // a `String` field into each variant. // You'll also have to add `thiserror` as a dependency in the `Cargo.toml` file. +use thiserror::Error; + +#[derive(Error, Debug)] 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, } +// impl std::fmt::Display for TicketNewError { +// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +// write!(f, "{:?}", self) +// } +// } + #[derive(Debug, PartialEq, Clone)] struct Ticket { title: String, 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 e0e1115..e3dbef9 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,25 @@ enum Status { Done, } +impl TryFrom<&str> for Status { + type Error = String; + fn try_from(value: &str) -> Result { + match value.to_lowercase().as_str() { + "todo" | "to-do" | "to do" => Ok(Status::ToDo), + "inprogress" | "in progress" => Ok(Status::InProgress), + "done" => Ok(Status::Done), + _ => Err(format!("Uknown status: {}", value)), + } + } +} + +impl TryFrom for Status { + type Error = String; + fn try_from(value: String) -> Result { + value.as_str().try_into() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/exercises/05_ticket_v2/14_source/src/lib.rs b/exercises/05_ticket_v2/14_source/src/lib.rs index 9f7cce5..6568e52 100644 --- a/exercises/05_ticket_v2/14_source/src/lib.rs +++ b/exercises/05_ticket_v2/14_source/src/lib.rs @@ -1,3 +1,5 @@ +use std::string::ParseError; + use crate::status::Status; // We've seen how to declare modules in one of the earliest exercises, but @@ -17,12 +19,18 @@ mod status; pub 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, + + #[error("{0}")] + InvalidStatus(#[from] status::ParseStatusError), } #[derive(Debug, PartialEq, Clone)] @@ -33,7 +41,11 @@ pub struct Ticket { } impl Ticket { - pub fn new(title: String, description: String, status: String) -> Result { + pub fn new( + title: String, + description: String, + status_str: String, + ) -> Result { if title.is_empty() { return Err(TicketNewError::TitleCannotBeEmpty); } @@ -47,7 +59,7 @@ impl Ticket { return Err(TicketNewError::DescriptionTooLong); } - // TODO: Parse the status string into a `Status` enum. + let status = Status::try_from(status_str)?; Ok(Ticket { title, diff --git a/exercises/05_ticket_v2/15_outro/Cargo.toml b/exercises/05_ticket_v2/15_outro/Cargo.toml index dc32a41..f944048 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" diff --git a/exercises/05_ticket_v2/15_outro/src/description.rs b/exercises/05_ticket_v2/15_outro/src/description.rs index ecf55ad..c059427 100644 --- a/exercises/05_ticket_v2/15_outro/src/description.rs +++ b/exercises/05_ticket_v2/15_outro/src/description.rs @@ -2,8 +2,40 @@ // enforcing that the description is not empty and is not longer than 500 bytes. // Implement the traits required to make the tests pass too. +use thiserror::Error; + +#[derive(Debug, PartialEq, Clone)] pub struct TicketDescription(String); +#[derive(Debug, Error)] +pub enum TicketDescriptionError { + #[error("The description cannot be empty")] + Empty, + + #[error("The description cannot be longer than 500 bytes")] + TooLong, +} + +impl TryFrom<&str> for TicketDescription { + type Error = TicketDescriptionError; + fn try_from(value: &str) -> Result { + TicketDescription::try_from(value.to_string()) + } +} + +impl TryFrom for TicketDescription { + type Error = TicketDescriptionError; + fn try_from(value: String) -> Result { + if value.len() > 500 { + Err(TicketDescriptionError::TooLong) + } else if value.is_empty() { + Err(TicketDescriptionError::Empty) + } else { + Ok(TicketDescription(value)) + } + } +} + #[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 4453d52..1f6b12f 100644 --- a/exercises/05_ticket_v2/15_outro/src/status.rs +++ b/exercises/05_ticket_v2/15_outro/src/status.rs @@ -1,12 +1,32 @@ // 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<&str> for Status { + type Error = String; + fn try_from(value: &str) -> Result { + match value.to_lowercase().as_str() { + "todo" | "to-do" | "to do" => Ok(Status::ToDo), + "inprogress" | "in progress" => Ok(Status::InProgress), + "done" => Ok(Status::Done), + _ => Err(format!("Can't parse status '{value}'").to_string()), + } + } +} + +impl TryFrom for Status { + type Error = String; + fn try_from(value: String) -> Result { + Status::try_from(value.as_str()) + } +} + #[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 cb31996..1ac7374 100644 --- a/exercises/05_ticket_v2/15_outro/src/title.rs +++ b/exercises/05_ticket_v2/15_outro/src/title.rs @@ -2,8 +2,40 @@ // enforcing that the title is not empty and is not longer than 50 characters. // Implement the traits required to make the tests pass too. +use thiserror::Error; + +#[derive(Debug, PartialEq, Clone)] pub struct TicketTitle(String); +#[derive(Debug, Error)] +pub enum TitleError { + #[error("The title cannot be empty")] + Empty, + + #[error("The title cannot be longer than 50 bytes")] + TooLong, +} + +impl TryFrom<&str> for TicketTitle { + type Error = TitleError; + fn try_from(value: &str) -> Result { + TicketTitle::try_from(value.to_string()) + } +} + +impl TryFrom for TicketTitle { + type Error = TitleError; + fn try_from(value: String) -> Result { + if value.len() > 50 { + Err(TitleError::TooLong) + } else if value.is_empty() { + Err(TitleError::Empty) + } else { + Ok(TicketTitle(value)) + } + } +} + #[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 118e483..d0fd0da 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 e06cb2b..49a20a4 100644 --- a/exercises/06_ticket_management/01_arrays/src/lib.rs +++ b/exercises/06_ticket_management/01_arrays/src/lib.rs @@ -1,11 +1,11 @@ // TODO: Flesh out the `WeekTemperatures` struct and its method implementations to pass the tests. pub struct WeekTemperatures { - // TODO + values: [Option; 7], } pub enum Weekday { - Monday, + Monday = 0, Tuesday, Wednesday, Thursday, @@ -16,15 +16,15 @@ pub enum Weekday { impl WeekTemperatures { pub fn new() -> Self { - todo!() + WeekTemperatures { values: [None; 7] } } pub fn get_temperature(&self, day: Weekday) -> Option { - todo!() + self.values[day as usize] } pub fn set_temperature(&mut self, day: Weekday, temperature: i32) { - todo!() + self.values[day as usize] = Some(temperature); } } diff --git a/exercises/06_ticket_management/02_vec/Cargo.toml b/exercises/06_ticket_management/02_vec/Cargo.toml index 66ee1de..6e3a2fa 100644 --- a/exercises/06_ticket_management/02_vec/Cargo.toml +++ b/exercises/06_ticket_management/02_vec/Cargo.toml @@ -2,3 +2,6 @@ name = "vec" version = "0.1.0" edition = "2021" + +[dependencies] +lazy_static = "1" diff --git a/exercises/06_ticket_management/02_vec/src/lib.rs b/exercises/06_ticket_management/02_vec/src/lib.rs index 2e8b498..08051b0 100644 --- a/exercises/06_ticket_management/02_vec/src/lib.rs +++ b/exercises/06_ticket_management/02_vec/src/lib.rs @@ -10,12 +10,28 @@ // // We expect `fibonacci(0)` to return `0`, `fibonacci(1)` to return `1`, // `fibonacci(2)` to return `1`, and so on. + +use lazy_static::lazy_static; +use std::sync::Mutex; + +lazy_static! { + static ref fibonacci_values: Mutex> = Mutex::new(vec![0, 1]); +} + 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 mut values = fibonacci_values.lock().unwrap(); + while values.len() <= n as usize { + let l = values.len(); + let v1 = values[l - 2]; + let v2 = values[l - 1]; + values.push(v1 + v2); + } + values[n as usize] } #[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 000ca2d..f29eb7e 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 d55906c..7425a08 100644 --- a/exercises/06_ticket_management/04_iterators/src/lib.rs +++ b/exercises/06_ticket_management/04_iterators/src/lib.rs @@ -10,6 +10,15 @@ pub struct TicketStore { tickets: Vec, } +impl IntoIterator for TicketStore { + type Item = Ticket; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.tickets.into_iter() + } +} + #[derive(Clone, Debug, PartialEq)] pub struct Ticket { pub title: TicketTitle, diff --git a/exercises/06_ticket_management/05_iter/src/lib.rs b/exercises/06_ticket_management/05_iter/src/lib.rs index da75366..0039136 100644 --- a/exercises/06_ticket_management/05_iter/src/lib.rs +++ b/exercises/06_ticket_management/05_iter/src/lib.rs @@ -30,6 +30,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 545ed75..ec4538e 100644 --- a/exercises/06_ticket_management/06_lifetimes/src/lib.rs +++ b/exercises/06_ticket_management/06_lifetimes/src/lib.rs @@ -6,6 +6,15 @@ pub struct TicketStore { tickets: Vec, } +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() + } +} + #[derive(Clone, Debug, PartialEq)] pub struct Ticket { pub title: TicketTitle, diff --git a/exercises/06_ticket_management/07_combinators/src/lib.rs b/exercises/06_ticket_management/07_combinators/src/lib.rs index 2731211..11e81a5 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(|t| t.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 d8afbe0..53eb290 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(|t| t.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 33e982b..fa3e99c 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,10 @@ 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) + where + T: Into, + { 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 1d2c6f7..9f996b2 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. +fn sum(elements: &[u32]) -> u32 { + elements.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 4ba888c..6b1eff5 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. +fn squared(numbers: &mut [i32]) { + for mut n in numbers { + *n *= *n; + } +} + #[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 10b5cb1..360b07a 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, + next_id: u64, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -41,11 +42,25 @@ impl TicketStore { pub fn new() -> Self { Self { tickets: Vec::new(), + next_id: 0, } } - pub fn add_ticket(&mut self, ticket: Ticket) { + pub fn add_ticket(&mut self, ticket_draft: TicketDraft) -> TicketId { + let id = TicketId(self.next_id); + self.next_id += 1; + let ticket = Ticket { + id, + title: ticket_draft.title, + description: ticket_draft.description, + status: Status::ToDo, + }; self.tickets.push(ticket); + id + } + + pub fn get(&self, id: TicketId) -> Option<&Ticket> { + self.tickets.iter().find(|t| t.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 0b08cc1..8b5fa13 100644 --- a/exercises/06_ticket_management/13_index/src/lib.rs +++ b/exercises/06_ticket_management/13_index/src/lib.rs @@ -1,5 +1,7 @@ // TODO: Implement `Index<&TicketId>` and `Index` for `TicketStore`. +use std::ops::Index; + use ticket_fields::{TicketDescription, TicketTitle}; #[derive(Clone)] @@ -58,6 +60,20 @@ impl TicketStore { } } +impl Index for TicketStore { + type Output = Ticket; + fn index(&self, index: TicketId) -> &Self::Output { + self.get(index).unwrap() + } +} + +impl Index<&TicketId> for TicketStore { + type Output = Ticket; + fn index(&self, index: &TicketId) -> &Self::Output { + self.index(*index) // or &self.index[*index]. + } +} + #[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 fa39451..aba27d6 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 ea109a6..ce21ecd 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, PartialOrd, Ord, 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 d9af95d..256619e 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, Eq, PartialOrd, Ord)] 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,24 @@ 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) + } +} + +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().into_iter() } } diff --git a/exercises/07_threads/00_intro/src/lib.rs b/exercises/07_threads/00_intro/src/lib.rs index df6490d..283d8d4 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 7d084ac..49a8292 100644 --- a/exercises/07_threads/01_threads/src/lib.rs +++ b/exercises/07_threads/01_threads/src/lib.rs @@ -12,10 +12,16 @@ // slices of the vector directly. You'll need to allocate new // vectors for each half of the original vector. We'll see why // this is necessary in the next exercise. -use std::thread; +use std::{thread, vec::Vec}; pub fn sum(v: Vec) -> i32 { - todo!() + let v1 = v[0..v.len() / 2].to_vec(); + let v2 = v[v.len() / 2..].to_vec(); + + let t1 = thread::spawn(move || v1.iter().sum::()); + let t2 = thread::spawn(move || v2.iter().sum::()); + + t1.join().unwrap() + t2.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 4b9241b..2f608d5 100644 --- a/exercises/07_threads/02_static/src/lib.rs +++ b/exercises/07_threads/02_static/src/lib.rs @@ -4,7 +4,12 @@ use std::thread; pub fn sum(slice: &'static [i32]) -> i32 { - todo!() + let (s1, s2) = slice.split_at(slice.len() / 2); + + let t1 = thread::spawn(|| s1.iter().sum::()); + let t2 = thread::spawn(|| s2.iter().sum::()); + + t1.join().unwrap() + t2.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 fef6b46..b232826 100644 --- a/exercises/07_threads/03_leak/src/lib.rs +++ b/exercises/07_threads/03_leak/src/lib.rs @@ -6,6 +6,7 @@ use std::thread; pub fn sum(v: Vec) -> i32 { + // Vec::leak(self) todo!() } -- 2.45.2