diff --git a/dev-Cargo.toml b/dev-Cargo.toml index 9230c2e948..4f725b704b 120000 --- a/dev-Cargo.toml +++ b/dev-Cargo.toml @@ -1 +1,223 @@ -dev/Cargo.toml \ No newline at end of file +# Don't edit the `bin` list manually! It is updated by `cargo dev update`. This comment line will be stripped in `rustlings init`. +bin = [ + { name = "intro1", path = "../exercises/00_intro/intro1.rs" }, + { name = "intro1_sol", path = "../solutions/00_intro/intro1.rs" }, + { name = "intro2", path = "../exercises/00_intro/intro2.rs" }, + { name = "intro2_sol", path = "../solutions/00_intro/intro2.rs" }, + { name = "variables1", path = "../exercises/01_variables/variables1.rs" }, + { name = "variables1_sol", path = "../solutions/01_variables/variables1.rs" }, + { name = "variables2", path = "../exercises/01_variables/variables2.rs" }, + { name = "variables2_sol", path = "../solutions/01_variables/variables2.rs" }, + { name = "variables3", path = "../exercises/01_variables/variables3.rs" }, + { name = "variables3_sol", path = "../solutions/01_variables/variables3.rs" }, + { name = "variables4", path = "../exercises/01_variables/variables4.rs" }, + { name = "variables4_sol", path = "../solutions/01_variables/variables4.rs" }, + { name = "variables5", path = "../exercises/01_variables/variables5.rs" }, + { name = "variables5_sol", path = "../solutions/01_variables/variables5.rs" }, + { name = "variables6", path = "../exercises/01_variables/variables6.rs" }, + { name = "variables6_sol", path = "../solutions/01_variables/variables6.rs" }, + { name = "functions1", path = "../exercises/02_functions/functions1.rs" }, + { name = "functions1_sol", path = "../solutions/02_functions/functions1.rs" }, + { name = "functions2", path = "../exercises/02_functions/functions2.rs" }, + { name = "functions2_sol", path = "../solutions/02_functions/functions2.rs" }, + { name = "functions3", path = "../exercises/02_functions/functions3.rs" }, + { name = "functions3_sol", path = "../solutions/02_functions/functions3.rs" }, + { name = "functions4", path = "../exercises/02_functions/functions4.rs" }, + { name = "functions4_sol", path = "../solutions/02_functions/functions4.rs" }, + { name = "functions5", path = "../exercises/02_functions/functions5.rs" }, + { name = "functions5_sol", path = "../solutions/02_functions/functions5.rs" }, + { name = "if1", path = "../exercises/03_if/if1.rs" }, + { name = "if1_sol", path = "../solutions/03_if/if1.rs" }, + { name = "if2", path = "../exercises/03_if/if2.rs" }, + { name = "if2_sol", path = "../solutions/03_if/if2.rs" }, + { name = "if3", path = "../exercises/03_if/if3.rs" }, + { name = "if3_sol", path = "../solutions/03_if/if3.rs" }, + { name = "quiz1", path = "../exercises/quizzes/quiz1.rs" }, + { name = "quiz1_sol", path = "../solutions/quizzes/quiz1.rs" }, + { name = "primitive_types1", path = "../exercises/04_primitive_types/primitive_types1.rs" }, + { name = "primitive_types1_sol", path = "../solutions/04_primitive_types/primitive_types1.rs" }, + { name = "primitive_types2", path = "../exercises/04_primitive_types/primitive_types2.rs" }, + { name = "primitive_types2_sol", path = "../solutions/04_primitive_types/primitive_types2.rs" }, + { name = "primitive_types3", path = "../exercises/04_primitive_types/primitive_types3.rs" }, + { name = "primitive_types3_sol", path = "../solutions/04_primitive_types/primitive_types3.rs" }, + { name = "primitive_types4", path = "../exercises/04_primitive_types/primitive_types4.rs" }, + { name = "primitive_types4_sol", path = "../solutions/04_primitive_types/primitive_types4.rs" }, + { name = "primitive_types5", path = "../exercises/04_primitive_types/primitive_types5.rs" }, + { name = "primitive_types5_sol", path = "../solutions/04_primitive_types/primitive_types5.rs" }, + { name = "primitive_types6", path = "../exercises/04_primitive_types/primitive_types6.rs" }, + { name = "primitive_types6_sol", path = "../solutions/04_primitive_types/primitive_types6.rs" }, + { name = "vecs1", path = "../exercises/05_vecs/vecs1.rs" }, + { name = "vecs1_sol", path = "../solutions/05_vecs/vecs1.rs" }, + { name = "vecs2", path = "../exercises/05_vecs/vecs2.rs" }, + { name = "vecs2_sol", path = "../solutions/05_vecs/vecs2.rs" }, + { name = "move_semantics1", path = "../exercises/06_move_semantics/move_semantics1.rs" }, + { name = "move_semantics1_sol", path = "../solutions/06_move_semantics/move_semantics1.rs" }, + { name = "move_semantics2", path = "../exercises/06_move_semantics/move_semantics2.rs" }, + { name = "move_semantics2_sol", path = "../solutions/06_move_semantics/move_semantics2.rs" }, + { name = "move_semantics3", path = "../exercises/06_move_semantics/move_semantics3.rs" }, + { name = "move_semantics3_sol", path = "../solutions/06_move_semantics/move_semantics3.rs" }, + { name = "move_semantics4", path = "../exercises/06_move_semantics/move_semantics4.rs" }, + { name = "move_semantics4_sol", path = "../solutions/06_move_semantics/move_semantics4.rs" }, + { name = "move_semantics5", path = "../exercises/06_move_semantics/move_semantics5.rs" }, + { name = "move_semantics5_sol", path = "../solutions/06_move_semantics/move_semantics5.rs" }, + { name = "structs1", path = "../exercises/07_structs/structs1.rs" }, + { name = "structs1_sol", path = "../solutions/07_structs/structs1.rs" }, + { name = "structs2", path = "../exercises/07_structs/structs2.rs" }, + { name = "structs2_sol", path = "../solutions/07_structs/structs2.rs" }, + { name = "structs3", path = "../exercises/07_structs/structs3.rs" }, + { name = "structs3_sol", path = "../solutions/07_structs/structs3.rs" }, + { name = "enums1", path = "../exercises/08_enums/enums1.rs" }, + { name = "enums1_sol", path = "../solutions/08_enums/enums1.rs" }, + { name = "enums2", path = "../exercises/08_enums/enums2.rs" }, + { name = "enums2_sol", path = "../solutions/08_enums/enums2.rs" }, + { name = "enums3", path = "../exercises/08_enums/enums3.rs" }, + { name = "enums3_sol", path = "../solutions/08_enums/enums3.rs" }, + { name = "strings1", path = "../exercises/09_strings/strings1.rs" }, + { name = "strings1_sol", path = "../solutions/09_strings/strings1.rs" }, + { name = "strings2", path = "../exercises/09_strings/strings2.rs" }, + { name = "strings2_sol", path = "../solutions/09_strings/strings2.rs" }, + { name = "strings3", path = "../exercises/09_strings/strings3.rs" }, + { name = "strings3_sol", path = "../solutions/09_strings/strings3.rs" }, + { name = "strings4", path = "../exercises/09_strings/strings4.rs" }, + { name = "strings4_sol", path = "../solutions/09_strings/strings4.rs" }, + { name = "modules1", path = "../exercises/10_modules/modules1.rs" }, + { name = "modules1_sol", path = "../solutions/10_modules/modules1.rs" }, + { name = "modules2", path = "../exercises/10_modules/modules2.rs" }, + { name = "modules2_sol", path = "../solutions/10_modules/modules2.rs" }, + { name = "modules3", path = "../exercises/10_modules/modules3.rs" }, + { name = "modules3_sol", path = "../solutions/10_modules/modules3.rs" }, + { name = "hashmaps1", path = "../exercises/11_hashmaps/hashmaps1.rs" }, + { name = "hashmaps1_sol", path = "../solutions/11_hashmaps/hashmaps1.rs" }, + { name = "hashmaps2", path = "../exercises/11_hashmaps/hashmaps2.rs" }, + { name = "hashmaps2_sol", path = "../solutions/11_hashmaps/hashmaps2.rs" }, + { name = "hashmaps3", path = "../exercises/11_hashmaps/hashmaps3.rs" }, + { name = "hashmaps3_sol", path = "../solutions/11_hashmaps/hashmaps3.rs" }, + { name = "quiz2", path = "../exercises/quizzes/quiz2.rs" }, + { name = "quiz2_sol", path = "../solutions/quizzes/quiz2.rs" }, + { name = "options1", path = "../exercises/12_options/options1.rs" }, + { name = "options1_sol", path = "../solutions/12_options/options1.rs" }, + { name = "options2", path = "../exercises/12_options/options2.rs" }, + { name = "options2_sol", path = "../solutions/12_options/options2.rs" }, + { name = "options3", path = "../exercises/12_options/options3.rs" }, + { name = "options3_sol", path = "../solutions/12_options/options3.rs" }, + { name = "errors1", path = "../exercises/13_error_handling/errors1.rs" }, + { name = "errors1_sol", path = "../solutions/13_error_handling/errors1.rs" }, + { name = "errors2", path = "../exercises/13_error_handling/errors2.rs" }, + { name = "errors2_sol", path = "../solutions/13_error_handling/errors2.rs" }, + { name = "errors3", path = "../exercises/13_error_handling/errors3.rs" }, + { name = "errors3_sol", path = "../solutions/13_error_handling/errors3.rs" }, + { name = "errors4", path = "../exercises/13_error_handling/errors4.rs" }, + { name = "errors4_sol", path = "../solutions/13_error_handling/errors4.rs" }, + { name = "errors5", path = "../exercises/13_error_handling/errors5.rs" }, + { name = "errors5_sol", path = "../solutions/13_error_handling/errors5.rs" }, + { name = "errors6", path = "../exercises/13_error_handling/errors6.rs" }, + { name = "errors6_sol", path = "../solutions/13_error_handling/errors6.rs" }, + { name = "generics1", path = "../exercises/14_generics/generics1.rs" }, + { name = "generics1_sol", path = "../solutions/14_generics/generics1.rs" }, + { name = "generics2", path = "../exercises/14_generics/generics2.rs" }, + { name = "generics2_sol", path = "../solutions/14_generics/generics2.rs" }, + { name = "traits1", path = "../exercises/15_traits/traits1.rs" }, + { name = "traits1_sol", path = "../solutions/15_traits/traits1.rs" }, + { name = "traits2", path = "../exercises/15_traits/traits2.rs" }, + { name = "traits2_sol", path = "../solutions/15_traits/traits2.rs" }, + { name = "traits3", path = "../exercises/15_traits/traits3.rs" }, + { name = "traits3_sol", path = "../solutions/15_traits/traits3.rs" }, + { name = "traits4", path = "../exercises/15_traits/traits4.rs" }, + { name = "traits4_sol", path = "../solutions/15_traits/traits4.rs" }, + { name = "traits5", path = "../exercises/15_traits/traits5.rs" }, + { name = "traits5_sol", path = "../solutions/15_traits/traits5.rs" }, + { name = "quiz3", path = "../exercises/quizzes/quiz3.rs" }, + { name = "quiz3_sol", path = "../solutions/quizzes/quiz3.rs" }, + { name = "lifetimes1", path = "../exercises/16_lifetimes/lifetimes1.rs" }, + { name = "lifetimes1_sol", path = "../solutions/16_lifetimes/lifetimes1.rs" }, + { name = "lifetimes2", path = "../exercises/16_lifetimes/lifetimes2.rs" }, + { name = "lifetimes2_sol", path = "../solutions/16_lifetimes/lifetimes2.rs" }, + { name = "lifetimes3", path = "../exercises/16_lifetimes/lifetimes3.rs" }, + { name = "lifetimes3_sol", path = "../solutions/16_lifetimes/lifetimes3.rs" }, + { name = "tests1", path = "../exercises/17_tests/tests1.rs" }, + { name = "tests1_sol", path = "../solutions/17_tests/tests1.rs" }, + { name = "tests2", path = "../exercises/17_tests/tests2.rs" }, + { name = "tests2_sol", path = "../solutions/17_tests/tests2.rs" }, + { name = "tests3", path = "../exercises/17_tests/tests3.rs" }, + { name = "tests3_sol", path = "../solutions/17_tests/tests3.rs" }, + { name = "iterators1", path = "../exercises/18_iterators/iterators1.rs" }, + { name = "iterators1_sol", path = "../solutions/18_iterators/iterators1.rs" }, + { name = "iterators2", path = "../exercises/18_iterators/iterators2.rs" }, + { name = "iterators2_sol", path = "../solutions/18_iterators/iterators2.rs" }, + { name = "iterators3", path = "../exercises/18_iterators/iterators3.rs" }, + { name = "iterators3_sol", path = "../solutions/18_iterators/iterators3.rs" }, + { name = "iterators4", path = "../exercises/18_iterators/iterators4.rs" }, + { name = "iterators4_sol", path = "../solutions/18_iterators/iterators4.rs" }, + { name = "iterators5", path = "../exercises/18_iterators/iterators5.rs" }, + { name = "iterators5_sol", path = "../solutions/18_iterators/iterators5.rs" }, + { name = "box1", path = "../exercises/19_smart_pointers/box1.rs" }, + { name = "box1_sol", path = "../solutions/19_smart_pointers/box1.rs" }, + { name = "rc1", path = "../exercises/19_smart_pointers/rc1.rs" }, + { name = "rc1_sol", path = "../solutions/19_smart_pointers/rc1.rs" }, + { name = "arc1", path = "../exercises/19_smart_pointers/arc1.rs" }, + { name = "arc1_sol", path = "../solutions/19_smart_pointers/arc1.rs" }, + { name = "cow1", path = "../exercises/19_smart_pointers/cow1.rs" }, + { name = "cow1_sol", path = "../solutions/19_smart_pointers/cow1.rs" }, + { name = "threads1", path = "../exercises/20_threads/threads1.rs" }, + { name = "threads1_sol", path = "../solutions/20_threads/threads1.rs" }, + { name = "threads2", path = "../exercises/20_threads/threads2.rs" }, + { name = "threads2_sol", path = "../solutions/20_threads/threads2.rs" }, + { name = "threads3", path = "../exercises/20_threads/threads3.rs" }, + { name = "threads3_sol", path = "../solutions/20_threads/threads3.rs" }, + { name = "macros1", path = "../exercises/21_macros/macros1.rs" }, + { name = "macros1_sol", path = "../solutions/21_macros/macros1.rs" }, + { name = "macros2", path = "../exercises/21_macros/macros2.rs" }, + { name = "macros2_sol", path = "../solutions/21_macros/macros2.rs" }, + { name = "macros3", path = "../exercises/21_macros/macros3.rs" }, + { name = "macros3_sol", path = "../solutions/21_macros/macros3.rs" }, + { name = "macros4", path = "../exercises/21_macros/macros4.rs" }, + { name = "macros4_sol", path = "../solutions/21_macros/macros4.rs" }, + { name = "clippy1", path = "../exercises/22_clippy/clippy1.rs" }, + { name = "clippy1_sol", path = "../solutions/22_clippy/clippy1.rs" }, + { name = "clippy2", path = "../exercises/22_clippy/clippy2.rs" }, + { name = "clippy2_sol", path = "../solutions/22_clippy/clippy2.rs" }, + { name = "clippy3", path = "../exercises/22_clippy/clippy3.rs" }, + { name = "clippy3_sol", path = "../solutions/22_clippy/clippy3.rs" }, + { name = "using_as", path = "../exercises/23_conversions/using_as.rs" }, + { name = "using_as_sol", path = "../solutions/23_conversions/using_as.rs" }, + { name = "from_into", path = "../exercises/23_conversions/from_into.rs" }, + { name = "from_into_sol", path = "../solutions/23_conversions/from_into.rs" }, + { name = "from_str", path = "../exercises/23_conversions/from_str.rs" }, + { name = "from_str_sol", path = "../solutions/23_conversions/from_str.rs" }, + { name = "try_from_into", path = "../exercises/23_conversions/try_from_into.rs" }, + { name = "try_from_into_sol", path = "../solutions/23_conversions/try_from_into.rs" }, + { name = "as_ref_mut", path = "../exercises/23_conversions/as_ref_mut.rs" }, + { name = "as_ref_mut_sol", path = "../solutions/23_conversions/as_ref_mut.rs" }, +] + +[package] +name = "exercises" +edition = "2024" +# Don't publish the exercises on crates.io! +publish = false + +[profile.release] +panic = "abort" + +[profile.dev] +panic = "abort" + +[lints.rust] +# You shouldn't write unsafe code in Rustlings! +unsafe_code = "forbid" +# You don't need unstable features in Rustlings and shouldn't rely on them while learning Rust. +unstable_features = "forbid" +# Dead code warnings can't be avoided in some exercises and might distract while learning. +dead_code = "allow" + +[lints.clippy] +# You forgot a `todo!()`! +todo = "forbid" +# This can only happen by mistake in Rustlings. +empty_loop = "forbid" +# No infinite loops are needed in Rustlings. +infinite_loop = "deny" +# You shouldn't leak memory while still learning Rust! +mem_forget = "deny" +# Currently, there are no disallowed methods. This line avoids problems when developing Rustlings. +disallowed_methods = "allow" diff --git a/exercises/00_intro/intro1.exe b/exercises/00_intro/intro1.exe new file mode 100644 index 0000000000..29529eac1a Binary files /dev/null and b/exercises/00_intro/intro1.exe differ diff --git a/exercises/00_intro/intro1.pdb b/exercises/00_intro/intro1.pdb new file mode 100644 index 0000000000..488b133f34 Binary files /dev/null and b/exercises/00_intro/intro1.pdb differ diff --git a/exercises/00_intro/intro1.rs b/exercises/00_intro/intro1.rs index 172a6ab1f2..17981b61ae 100644 --- a/exercises/00_intro/intro1.rs +++ b/exercises/00_intro/intro1.rs @@ -21,4 +21,5 @@ fn main() { println!("The file of this exercise is `exercises/00_intro/intro1.rs`. Have a look!"); println!("The current exercise path will be always shown under the progress bar."); println!("You can click on the path to open the exercise file in your editor."); + println!("This is how we start."); } diff --git a/exercises/00_intro/intro2.exe b/exercises/00_intro/intro2.exe new file mode 100644 index 0000000000..76b4b301c9 Binary files /dev/null and b/exercises/00_intro/intro2.exe differ diff --git a/exercises/00_intro/intro2.pdb b/exercises/00_intro/intro2.pdb new file mode 100644 index 0000000000..c243d88c0a Binary files /dev/null and b/exercises/00_intro/intro2.pdb differ diff --git a/exercises/00_intro/intro2.rs b/exercises/00_intro/intro2.rs index c6cb6451ae..03e376ed35 100644 --- a/exercises/00_intro/intro2.rs +++ b/exercises/00_intro/intro2.rs @@ -1,4 +1,4 @@ fn main() { // TODO: Fix the code to print "Hello world!". - printline!("Hello world!"); + println!("Hello world!"); } diff --git a/exercises/01_variables/variables1.exe b/exercises/01_variables/variables1.exe new file mode 100644 index 0000000000..d67210e879 Binary files /dev/null and b/exercises/01_variables/variables1.exe differ diff --git a/exercises/01_variables/variables1.pdb b/exercises/01_variables/variables1.pdb new file mode 100644 index 0000000000..d239b87f84 Binary files /dev/null and b/exercises/01_variables/variables1.pdb differ diff --git a/exercises/01_variables/variables1.rs b/exercises/01_variables/variables1.rs index f83b44d415..ce244c234b 100644 --- a/exercises/01_variables/variables1.rs +++ b/exercises/01_variables/variables1.rs @@ -1,6 +1,6 @@ fn main() { // TODO: Add the missing keyword. - x = 5; + let x = 5; - println!("x has the value {x}"); + println!("x has the value {x}");// format {variable} } diff --git a/exercises/01_variables/variables2.exe b/exercises/01_variables/variables2.exe new file mode 100644 index 0000000000..b5dfe05328 Binary files /dev/null and b/exercises/01_variables/variables2.exe differ diff --git a/exercises/01_variables/variables2.pdb b/exercises/01_variables/variables2.pdb new file mode 100644 index 0000000000..79d385555b Binary files /dev/null and b/exercises/01_variables/variables2.pdb differ diff --git a/exercises/01_variables/variables2.rs b/exercises/01_variables/variables2.rs index e2a360351a..e2fd5d03f2 100644 --- a/exercises/01_variables/variables2.rs +++ b/exercises/01_variables/variables2.rs @@ -1,6 +1,6 @@ fn main() { // TODO: Change the line below to fix the compiler error. - let x; + let x = 10; if x == 10 { println!("x is ten!"); diff --git a/exercises/01_variables/variables3.exe b/exercises/01_variables/variables3.exe new file mode 100644 index 0000000000..7c456b97b1 Binary files /dev/null and b/exercises/01_variables/variables3.exe differ diff --git a/exercises/01_variables/variables3.pdb b/exercises/01_variables/variables3.pdb new file mode 100644 index 0000000000..9fc2f9a3f5 Binary files /dev/null and b/exercises/01_variables/variables3.pdb differ diff --git a/exercises/01_variables/variables3.rs b/exercises/01_variables/variables3.rs index 06f35bb1e2..0ed3b38bb8 100644 --- a/exercises/01_variables/variables3.rs +++ b/exercises/01_variables/variables3.rs @@ -1,6 +1,6 @@ fn main() { // TODO: Change the line below to fix the compiler error. - let x: i32; + let x: i32 = 0; println!("Number {x}"); } diff --git a/exercises/01_variables/variables4.exe b/exercises/01_variables/variables4.exe new file mode 100644 index 0000000000..47a34f7a2d Binary files /dev/null and b/exercises/01_variables/variables4.exe differ diff --git a/exercises/01_variables/variables4.pdb b/exercises/01_variables/variables4.pdb new file mode 100644 index 0000000000..c76fddf213 Binary files /dev/null and b/exercises/01_variables/variables4.pdb differ diff --git a/exercises/01_variables/variables4.rs b/exercises/01_variables/variables4.rs index 6c138b18b9..90d4ef05d1 100644 --- a/exercises/01_variables/variables4.rs +++ b/exercises/01_variables/variables4.rs @@ -1,6 +1,6 @@ // TODO: Fix the compiler error. fn main() { - let x = 3; + let mut x = 3; println!("Number {x}"); x = 5; // Don't change this line diff --git a/exercises/01_variables/variables5.exe b/exercises/01_variables/variables5.exe new file mode 100644 index 0000000000..965f3e032f Binary files /dev/null and b/exercises/01_variables/variables5.exe differ diff --git a/exercises/01_variables/variables5.pdb b/exercises/01_variables/variables5.pdb new file mode 100644 index 0000000000..a3c26bbe5c Binary files /dev/null and b/exercises/01_variables/variables5.pdb differ diff --git a/exercises/01_variables/variables5.rs b/exercises/01_variables/variables5.rs index cf5620da5f..085e0994f7 100644 --- a/exercises/01_variables/variables5.rs +++ b/exercises/01_variables/variables5.rs @@ -3,6 +3,6 @@ fn main() { println!("Spell a number: {number}"); // TODO: Fix the compiler error by changing the line below without renaming the variable. - number = 3; + let number = 3; println!("Number plus two is: {}", number + 2); } diff --git a/exercises/01_variables/variables6.exe b/exercises/01_variables/variables6.exe new file mode 100644 index 0000000000..e3baaccc12 Binary files /dev/null and b/exercises/01_variables/variables6.exe differ diff --git a/exercises/01_variables/variables6.pdb b/exercises/01_variables/variables6.pdb new file mode 100644 index 0000000000..838dc3d122 Binary files /dev/null and b/exercises/01_variables/variables6.pdb differ diff --git a/exercises/01_variables/variables6.rs b/exercises/01_variables/variables6.rs index 4a040fddac..deb33ed9dd 100644 --- a/exercises/01_variables/variables6.rs +++ b/exercises/01_variables/variables6.rs @@ -1,5 +1,5 @@ // TODO: Change the line below to fix the compiler error. -const NUMBER = 3; +const NUMBER: i32 = 3; fn main() { println!("Number: {NUMBER}"); diff --git a/exercises/02_functions/functions1.exe b/exercises/02_functions/functions1.exe new file mode 100644 index 0000000000..0d193fc6bb Binary files /dev/null and b/exercises/02_functions/functions1.exe differ diff --git a/exercises/02_functions/functions1.pdb b/exercises/02_functions/functions1.pdb new file mode 100644 index 0000000000..bca8eb76ff Binary files /dev/null and b/exercises/02_functions/functions1.pdb differ diff --git a/exercises/02_functions/functions1.rs b/exercises/02_functions/functions1.rs index a812c21bf2..d358ffb43a 100644 --- a/exercises/02_functions/functions1.rs +++ b/exercises/02_functions/functions1.rs @@ -1,4 +1,7 @@ // TODO: Add some function with the name `call_me` without arguments or a return value. +fn call_me() { + println!("Called!"); +} fn main() { call_me(); // Don't change this line diff --git a/exercises/02_functions/functions2.exe b/exercises/02_functions/functions2.exe new file mode 100644 index 0000000000..e25f05f53d Binary files /dev/null and b/exercises/02_functions/functions2.exe differ diff --git a/exercises/02_functions/functions2.pdb b/exercises/02_functions/functions2.pdb new file mode 100644 index 0000000000..8e14b0e9d5 Binary files /dev/null and b/exercises/02_functions/functions2.pdb differ diff --git a/exercises/02_functions/functions2.rs b/exercises/02_functions/functions2.rs index 2c773c6b7f..a2cffc1a7b 100644 --- a/exercises/02_functions/functions2.rs +++ b/exercises/02_functions/functions2.rs @@ -1,5 +1,5 @@ // TODO: Add the missing type of the argument `num` after the colon `:`. -fn call_me(num:) { +fn call_me(num: i32) { for i in 0..num { println!("Ring! Call number {}", i + 1); } diff --git a/exercises/02_functions/functions3.exe b/exercises/02_functions/functions3.exe new file mode 100644 index 0000000000..53822f33f8 Binary files /dev/null and b/exercises/02_functions/functions3.exe differ diff --git a/exercises/02_functions/functions3.pdb b/exercises/02_functions/functions3.pdb new file mode 100644 index 0000000000..d8a1419aac Binary files /dev/null and b/exercises/02_functions/functions3.pdb differ diff --git a/exercises/02_functions/functions3.rs b/exercises/02_functions/functions3.rs index 8d65477219..59fd310a20 100644 --- a/exercises/02_functions/functions3.rs +++ b/exercises/02_functions/functions3.rs @@ -6,5 +6,5 @@ fn call_me(num: u8) { fn main() { // TODO: Fix the function call. - call_me(); + call_me(3); } diff --git a/exercises/02_functions/functions4.exe b/exercises/02_functions/functions4.exe new file mode 100644 index 0000000000..2a47b297f8 Binary files /dev/null and b/exercises/02_functions/functions4.exe differ diff --git a/exercises/02_functions/functions4.pdb b/exercises/02_functions/functions4.pdb new file mode 100644 index 0000000000..8f2f3f3c07 Binary files /dev/null and b/exercises/02_functions/functions4.pdb differ diff --git a/exercises/02_functions/functions4.rs b/exercises/02_functions/functions4.rs index b22bffdaf2..60ab17d4f8 100644 --- a/exercises/02_functions/functions4.rs +++ b/exercises/02_functions/functions4.rs @@ -8,7 +8,7 @@ fn is_even(num: i64) -> bool { } // TODO: Fix the function signature. -fn sale_price(price: i64) -> { +fn sale_price(price: i64) -> i64{ if is_even(price) { price - 10 } else { diff --git a/exercises/02_functions/functions5.exe b/exercises/02_functions/functions5.exe new file mode 100644 index 0000000000..80ed154d32 Binary files /dev/null and b/exercises/02_functions/functions5.exe differ diff --git a/exercises/02_functions/functions5.pdb b/exercises/02_functions/functions5.pdb new file mode 100644 index 0000000000..6ed88473ba Binary files /dev/null and b/exercises/02_functions/functions5.pdb differ diff --git a/exercises/02_functions/functions5.rs b/exercises/02_functions/functions5.rs index 34a2ac7dce..a063100408 100644 --- a/exercises/02_functions/functions5.rs +++ b/exercises/02_functions/functions5.rs @@ -1,6 +1,6 @@ // TODO: Fix the function body without changing the signature. fn square(num: i32) -> i32 { - num * num; + num * num } fn main() { diff --git a/exercises/03_if/if1.exe b/exercises/03_if/if1.exe new file mode 100644 index 0000000000..8da7bee6c3 Binary files /dev/null and b/exercises/03_if/if1.exe differ diff --git a/exercises/03_if/if1.pdb b/exercises/03_if/if1.pdb new file mode 100644 index 0000000000..9df3dd176b Binary files /dev/null and b/exercises/03_if/if1.pdb differ diff --git a/exercises/03_if/if1.rs b/exercises/03_if/if1.rs index e5a3c5a5b2..311b05315b 100644 --- a/exercises/03_if/if1.rs +++ b/exercises/03_if/if1.rs @@ -1,4 +1,9 @@ fn bigger(a: i32, b: i32) -> i32 { + if a > b { + a + } else { + b + } // TODO: Complete this function to return the bigger number! // If both numbers are equal, any of them can be returned. // Do not use: @@ -7,7 +12,7 @@ fn bigger(a: i32, b: i32) -> i32 { } fn main() { - // You can optionally experiment here. + println!("The bigger number is {}", bigger(89,30));// You can optionally experiment here. } // Don't mind this for now :) diff --git a/exercises/03_if/if2.exe b/exercises/03_if/if2.exe new file mode 100644 index 0000000000..a814f9110d Binary files /dev/null and b/exercises/03_if/if2.exe differ diff --git a/exercises/03_if/if2.pdb b/exercises/03_if/if2.pdb new file mode 100644 index 0000000000..31d102c396 Binary files /dev/null and b/exercises/03_if/if2.pdb differ diff --git a/exercises/03_if/if2.rs b/exercises/03_if/if2.rs index ca8493cc81..b98e8a5690 100644 --- a/exercises/03_if/if2.rs +++ b/exercises/03_if/if2.rs @@ -2,13 +2,15 @@ fn picky_eater(food: &str) -> &str { if food == "strawberry" { "Yummy!" + } else if food == "potato" { + "I guess I can eat that." } else { - 1 + "No thanks!" } } fn main() { - // You can optionally experiment here. + println!("The food is {}", picky_eater("strawberry")); } // TODO: Read the tests to understand the desired behavior. diff --git a/exercises/03_if/if3.exe b/exercises/03_if/if3.exe new file mode 100644 index 0000000000..989c99572b Binary files /dev/null and b/exercises/03_if/if3.exe differ diff --git a/exercises/03_if/if3.pdb b/exercises/03_if/if3.pdb new file mode 100644 index 0000000000..285242d489 Binary files /dev/null and b/exercises/03_if/if3.pdb differ diff --git a/exercises/03_if/if3.rs b/exercises/03_if/if3.rs index 89164eb218..7d40b529d2 100644 --- a/exercises/03_if/if3.rs +++ b/exercises/03_if/if3.rs @@ -3,11 +3,11 @@ fn animal_habitat(animal: &str) -> &str { let identifier = if animal == "crab" { 1 } else if animal == "gopher" { - 2.0 + 2 } else if animal == "snake" { 3 } else { - "Unknown" + 4 }; // Don't change the expression below! @@ -23,7 +23,9 @@ fn animal_habitat(animal: &str) -> &str { } fn main() { - // You can optionally experiment here. + let animal: &str = "gopher"; + println!("The habitat of a {animal} is {}", animal_habitat(animal)); +// You can optionally experiment here. } // Don't change the tests! diff --git a/exercises/04_primitive_types/primitive_types1.exe b/exercises/04_primitive_types/primitive_types1.exe new file mode 100644 index 0000000000..e949983225 Binary files /dev/null and b/exercises/04_primitive_types/primitive_types1.exe differ diff --git a/exercises/04_primitive_types/primitive_types1.pdb b/exercises/04_primitive_types/primitive_types1.pdb new file mode 100644 index 0000000000..5a70066e98 Binary files /dev/null and b/exercises/04_primitive_types/primitive_types1.pdb differ diff --git a/exercises/04_primitive_types/primitive_types1.rs b/exercises/04_primitive_types/primitive_types1.rs index 84923c7500..c464bd9f10 100644 --- a/exercises/04_primitive_types/primitive_types1.rs +++ b/exercises/04_primitive_types/primitive_types1.rs @@ -9,6 +9,7 @@ fn main() { // TODO: Define a boolean variable with the name `is_evening` before the `if` statement below. // The value of the variable should be the negation (opposite) of `is_morning`. // let … + let is_evening = !is_morning; if is_evening { println!("Good evening!"); } diff --git a/exercises/04_primitive_types/primitive_types2.exe b/exercises/04_primitive_types/primitive_types2.exe new file mode 100644 index 0000000000..1d5da9f2a1 Binary files /dev/null and b/exercises/04_primitive_types/primitive_types2.exe differ diff --git a/exercises/04_primitive_types/primitive_types2.pdb b/exercises/04_primitive_types/primitive_types2.pdb new file mode 100644 index 0000000000..f1b75b9735 Binary files /dev/null and b/exercises/04_primitive_types/primitive_types2.pdb differ diff --git a/exercises/04_primitive_types/primitive_types2.rs b/exercises/04_primitive_types/primitive_types2.rs index 14018475dd..18f9d4089a 100644 --- a/exercises/04_primitive_types/primitive_types2.rs +++ b/exercises/04_primitive_types/primitive_types2.rs @@ -17,6 +17,7 @@ fn main() { // Try a letter, try a digit (in single quotes), try a special character, try a character // from a different language than your own, try an emoji 😉 // let your_character = ''; + let your_character = '😉'; if your_character.is_alphabetic() { println!("Alphabetical!"); diff --git a/exercises/04_primitive_types/primitive_types3.exe b/exercises/04_primitive_types/primitive_types3.exe new file mode 100644 index 0000000000..20d80d152a Binary files /dev/null and b/exercises/04_primitive_types/primitive_types3.exe differ diff --git a/exercises/04_primitive_types/primitive_types3.pdb b/exercises/04_primitive_types/primitive_types3.pdb new file mode 100644 index 0000000000..659fc66015 Binary files /dev/null and b/exercises/04_primitive_types/primitive_types3.pdb differ diff --git a/exercises/04_primitive_types/primitive_types3.rs b/exercises/04_primitive_types/primitive_types3.rs index 9b79c0cf2a..a27d293052 100644 --- a/exercises/04_primitive_types/primitive_types3.rs +++ b/exercises/04_primitive_types/primitive_types3.rs @@ -1,7 +1,16 @@ fn main() { // TODO: Create an array called `a` with at least 100 elements in it. // let a = ??? - + let a: [i32; 100] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]; if a.len() >= 100 { println!("Wow, that's a big array!"); } else { diff --git a/exercises/04_primitive_types/primitive_types4.exe b/exercises/04_primitive_types/primitive_types4.exe new file mode 100644 index 0000000000..759479ac80 Binary files /dev/null and b/exercises/04_primitive_types/primitive_types4.exe differ diff --git a/exercises/04_primitive_types/primitive_types4.pdb b/exercises/04_primitive_types/primitive_types4.pdb new file mode 100644 index 0000000000..175ed200f2 Binary files /dev/null and b/exercises/04_primitive_types/primitive_types4.pdb differ diff --git a/exercises/04_primitive_types/primitive_types4.rs b/exercises/04_primitive_types/primitive_types4.rs index 16e4fd9321..1a4bdde587 100644 --- a/exercises/04_primitive_types/primitive_types4.rs +++ b/exercises/04_primitive_types/primitive_types4.rs @@ -1,5 +1,6 @@ fn main() { // You can optionally experiment here. + } #[cfg(test)] @@ -10,7 +11,7 @@ mod tests { // TODO: Get a slice called `nice_slice` out of the array `a` so that the test passes. // let nice_slice = ??? - + let nice_slice = &a[1..4]; assert_eq!([2, 3, 4], nice_slice); } } diff --git a/exercises/04_primitive_types/primitive_types5.exe b/exercises/04_primitive_types/primitive_types5.exe new file mode 100644 index 0000000000..ef53313196 Binary files /dev/null and b/exercises/04_primitive_types/primitive_types5.exe differ diff --git a/exercises/04_primitive_types/primitive_types5.pdb b/exercises/04_primitive_types/primitive_types5.pdb new file mode 100644 index 0000000000..ed31330b35 Binary files /dev/null and b/exercises/04_primitive_types/primitive_types5.pdb differ diff --git a/exercises/04_primitive_types/primitive_types5.rs b/exercises/04_primitive_types/primitive_types5.rs index 6e00ef51f8..e2f7316d96 100644 --- a/exercises/04_primitive_types/primitive_types5.rs +++ b/exercises/04_primitive_types/primitive_types5.rs @@ -3,6 +3,6 @@ fn main() { // TODO: Destructure the `cat` tuple in one statement so that the println works. // let /* your pattern here */ = cat; - + let (name, age) = cat; println!("{name} is {age} years old"); } diff --git a/exercises/04_primitive_types/primitive_types6.exe b/exercises/04_primitive_types/primitive_types6.exe new file mode 100644 index 0000000000..debd36d217 Binary files /dev/null and b/exercises/04_primitive_types/primitive_types6.exe differ diff --git a/exercises/04_primitive_types/primitive_types6.pdb b/exercises/04_primitive_types/primitive_types6.pdb new file mode 100644 index 0000000000..bbe73257f7 Binary files /dev/null and b/exercises/04_primitive_types/primitive_types6.pdb differ diff --git a/exercises/04_primitive_types/primitive_types6.rs b/exercises/04_primitive_types/primitive_types6.rs index a97e53110e..109eeb82a6 100644 --- a/exercises/04_primitive_types/primitive_types6.rs +++ b/exercises/04_primitive_types/primitive_types6.rs @@ -11,7 +11,8 @@ mod tests { // TODO: Use a tuple index to access the second element of `numbers` // and assign it to a variable called `second`. // let second = ???; - + let second = numbers.1; + println!("The second number is: {}", second); assert_eq!(second, 2, "This is not the 2nd number in the tuple!"); } } diff --git a/exercises/05_vecs/vecs1.exe b/exercises/05_vecs/vecs1.exe new file mode 100644 index 0000000000..1b317233a3 Binary files /dev/null and b/exercises/05_vecs/vecs1.exe differ diff --git a/exercises/05_vecs/vecs1.pdb b/exercises/05_vecs/vecs1.pdb new file mode 100644 index 0000000000..dd76bf6f9e Binary files /dev/null and b/exercises/05_vecs/vecs1.pdb differ diff --git a/exercises/05_vecs/vecs1.rs b/exercises/05_vecs/vecs1.rs index 68e1affaa7..39e659f273 100644 --- a/exercises/05_vecs/vecs1.rs +++ b/exercises/05_vecs/vecs1.rs @@ -4,12 +4,12 @@ fn array_and_vec() -> ([i32; 4], Vec) { // TODO: Create a vector called `v` which contains the exact same elements as in the array `a`. // Use the vector macro. // let v = ???; - + let v: Vec = vec![10, 20, 30, 40]; (a, v) } fn main() { - // You can optionally experiment here. + println!("Output is {:?}", array_and_vec()); } #[cfg(test)] diff --git a/exercises/05_vecs/vecs2.exe b/exercises/05_vecs/vecs2.exe new file mode 100644 index 0000000000..b07d059ffd Binary files /dev/null and b/exercises/05_vecs/vecs2.exe differ diff --git a/exercises/05_vecs/vecs2.pdb b/exercises/05_vecs/vecs2.pdb new file mode 100644 index 0000000000..b3aee53d20 Binary files /dev/null and b/exercises/05_vecs/vecs2.pdb differ diff --git a/exercises/05_vecs/vecs2.rs b/exercises/05_vecs/vecs2.rs index a9be2580f2..1ec77f7ad4 100644 --- a/exercises/05_vecs/vecs2.rs +++ b/exercises/05_vecs/vecs2.rs @@ -4,6 +4,7 @@ fn vec_loop(input: &[i32]) -> Vec { for element in input { // TODO: Multiply each element in the `input` slice by 2 and push it to // the `output` vector. + output.push(element * 2); } output @@ -24,7 +25,7 @@ fn vec_map(input: &[i32]) -> Vec { input .iter() .map(|element| { - // ??? + element * 2 }) .collect() } diff --git a/exercises/06_move_semantics/move_semantics1.exe b/exercises/06_move_semantics/move_semantics1.exe new file mode 100644 index 0000000000..acc1fdec48 Binary files /dev/null and b/exercises/06_move_semantics/move_semantics1.exe differ diff --git a/exercises/06_move_semantics/move_semantics1.pdb b/exercises/06_move_semantics/move_semantics1.pdb new file mode 100644 index 0000000000..f0d281f06c Binary files /dev/null and b/exercises/06_move_semantics/move_semantics1.pdb differ diff --git a/exercises/06_move_semantics/move_semantics1.rs b/exercises/06_move_semantics/move_semantics1.rs index 4eb3d618ef..811b3a7764 100644 --- a/exercises/06_move_semantics/move_semantics1.rs +++ b/exercises/06_move_semantics/move_semantics1.rs @@ -1,6 +1,6 @@ // TODO: Fix the compiler error in this function. fn fill_vec(vec: Vec) -> Vec { - let vec = vec; + let mut vec = vec; vec.push(88); @@ -9,6 +9,8 @@ fn fill_vec(vec: Vec) -> Vec { fn main() { // You can optionally experiment here. + let vec_i: Vec = vec![1, 2, 3]; + println!("Output is {:?}", fill_vec(vec_i)); } #[cfg(test)] diff --git a/exercises/06_move_semantics/move_semantics2.exe b/exercises/06_move_semantics/move_semantics2.exe new file mode 100644 index 0000000000..9b5bf7512c Binary files /dev/null and b/exercises/06_move_semantics/move_semantics2.exe differ diff --git a/exercises/06_move_semantics/move_semantics2.pdb b/exercises/06_move_semantics/move_semantics2.pdb new file mode 100644 index 0000000000..b689c2dc03 Binary files /dev/null and b/exercises/06_move_semantics/move_semantics2.pdb differ diff --git a/exercises/06_move_semantics/move_semantics2.rs b/exercises/06_move_semantics/move_semantics2.rs index a3ab7a0f18..e205b81357 100644 --- a/exercises/06_move_semantics/move_semantics2.rs +++ b/exercises/06_move_semantics/move_semantics2.rs @@ -20,7 +20,7 @@ mod tests { fn move_semantics2() { let vec0 = vec![22, 44, 66]; - let vec1 = fill_vec(vec0); + let vec1 = fill_vec(vec0.clone()); assert_eq!(vec0, [22, 44, 66]); assert_eq!(vec1, [22, 44, 66, 88]); diff --git a/exercises/06_move_semantics/move_semantics3.exe b/exercises/06_move_semantics/move_semantics3.exe new file mode 100644 index 0000000000..0742c764c3 Binary files /dev/null and b/exercises/06_move_semantics/move_semantics3.exe differ diff --git a/exercises/06_move_semantics/move_semantics3.pdb b/exercises/06_move_semantics/move_semantics3.pdb new file mode 100644 index 0000000000..6a2ce8ee6e Binary files /dev/null and b/exercises/06_move_semantics/move_semantics3.pdb differ diff --git a/exercises/06_move_semantics/move_semantics3.rs b/exercises/06_move_semantics/move_semantics3.rs index 11dbbbebff..4a90c2117c 100644 --- a/exercises/06_move_semantics/move_semantics3.rs +++ b/exercises/06_move_semantics/move_semantics3.rs @@ -1,5 +1,5 @@ // TODO: Fix the compiler error in the function without adding any new line. -fn fill_vec(vec: Vec) -> Vec { +fn fill_vec(mut vec: Vec) -> Vec { vec.push(88); vec diff --git a/exercises/06_move_semantics/move_semantics4.exe b/exercises/06_move_semantics/move_semantics4.exe new file mode 100644 index 0000000000..60a5dbc20a Binary files /dev/null and b/exercises/06_move_semantics/move_semantics4.exe differ diff --git a/exercises/06_move_semantics/move_semantics4.pdb b/exercises/06_move_semantics/move_semantics4.pdb new file mode 100644 index 0000000000..8f73ac3969 Binary files /dev/null and b/exercises/06_move_semantics/move_semantics4.pdb differ diff --git a/exercises/06_move_semantics/move_semantics4.rs b/exercises/06_move_semantics/move_semantics4.rs index 56da988cd4..89b412f093 100644 --- a/exercises/06_move_semantics/move_semantics4.rs +++ b/exercises/06_move_semantics/move_semantics4.rs @@ -10,8 +10,8 @@ mod tests { fn move_semantics4() { let mut x = Vec::new(); let y = &mut x; - let z = &mut x; y.push(42); + let z = &mut x; z.push(13); assert_eq!(x, [42, 13]); } diff --git a/exercises/06_move_semantics/move_semantics5.exe b/exercises/06_move_semantics/move_semantics5.exe new file mode 100644 index 0000000000..24dc10030d Binary files /dev/null and b/exercises/06_move_semantics/move_semantics5.exe differ diff --git a/exercises/06_move_semantics/move_semantics5.pdb b/exercises/06_move_semantics/move_semantics5.pdb new file mode 100644 index 0000000000..93d95590aa Binary files /dev/null and b/exercises/06_move_semantics/move_semantics5.pdb differ diff --git a/exercises/06_move_semantics/move_semantics5.rs b/exercises/06_move_semantics/move_semantics5.rs index cd0dafd08d..78d8c77e54 100644 --- a/exercises/06_move_semantics/move_semantics5.rs +++ b/exercises/06_move_semantics/move_semantics5.rs @@ -4,12 +4,12 @@ // removing references (the character `&`). // Shouldn't take ownership -fn get_char(data: String) -> char { +fn get_char(data: &String) -> char { data.chars().last().unwrap() } // Should take ownership -fn string_uppercase(mut data: &String) { +fn string_uppercase(mut data: String) { data = data.to_uppercase(); println!("{data}"); @@ -18,7 +18,7 @@ fn string_uppercase(mut data: &String) { fn main() { let data = "Rust is great!".to_string(); - get_char(data); + get_char(&data); - string_uppercase(&data); + string_uppercase(data); } diff --git a/exercises/07_structs/structs1.exe b/exercises/07_structs/structs1.exe new file mode 100644 index 0000000000..ba1a2638dd Binary files /dev/null and b/exercises/07_structs/structs1.exe differ diff --git a/exercises/07_structs/structs1.pdb b/exercises/07_structs/structs1.pdb new file mode 100644 index 0000000000..12e6f690cf Binary files /dev/null and b/exercises/07_structs/structs1.pdb differ diff --git a/exercises/07_structs/structs1.rs b/exercises/07_structs/structs1.rs index 959c4c6a68..407c4a29d3 100644 --- a/exercises/07_structs/structs1.rs +++ b/exercises/07_structs/structs1.rs @@ -1,9 +1,12 @@ struct ColorRegularStruct { // TODO: Add the fields that the test `regular_structs` expects. // What types should the fields have? What are the minimum and maximum values for RGB colors? + red: u8, + green: u8, + blue: u8, } -struct ColorTupleStruct(/* TODO: Add the fields that the test `tuple_structs` expects */); +struct ColorTupleStruct(u8, u8, u8); #[derive(Debug)] struct UnitStruct; @@ -20,7 +23,11 @@ mod tests { fn regular_structs() { // TODO: Instantiate a regular struct. // let green = - + let green = ColorRegularStruct { + red: 0, + green: 255, + blue: 0, + }; assert_eq!(green.red, 0); assert_eq!(green.green, 255); assert_eq!(green.blue, 0); @@ -30,7 +37,7 @@ mod tests { fn tuple_structs() { // TODO: Instantiate a tuple struct. // let green = - + let green = ColorTupleStruct(0, 255, 0); assert_eq!(green.0, 0); assert_eq!(green.1, 255); assert_eq!(green.2, 0); @@ -40,6 +47,7 @@ mod tests { fn unit_structs() { // TODO: Instantiate a unit struct. // let unit_struct = + let unit_struct = UnitStruct; let message = format!("{unit_struct:?}s are fun!"); assert_eq!(message, "UnitStructs are fun!"); diff --git a/exercises/07_structs/structs2.exe b/exercises/07_structs/structs2.exe new file mode 100644 index 0000000000..170e8a9c08 Binary files /dev/null and b/exercises/07_structs/structs2.exe differ diff --git a/exercises/07_structs/structs2.pdb b/exercises/07_structs/structs2.pdb new file mode 100644 index 0000000000..07056dc6e2 Binary files /dev/null and b/exercises/07_structs/structs2.pdb differ diff --git a/exercises/07_structs/structs2.rs b/exercises/07_structs/structs2.rs index 79141af95d..fd9b4344db 100644 --- a/exercises/07_structs/structs2.rs +++ b/exercises/07_structs/structs2.rs @@ -35,7 +35,17 @@ mod tests { // TODO: Create your own order using the update syntax and template above! // let your_order = + let your_order = Order{ + name: String::from("Hacker in Rust"), + count: 1, + year: order_template.year, + made_by_phone: order_template.made_by_phone, + made_by_mobile: order_template.made_by_mobile, + made_by_email: order_template.made_by_email, + item_number: order_template.item_number, + + }; assert_eq!(your_order.name, "Hacker in Rust"); assert_eq!(your_order.year, order_template.year); assert_eq!(your_order.made_by_phone, order_template.made_by_phone); diff --git a/exercises/07_structs/structs3.exe b/exercises/07_structs/structs3.exe new file mode 100644 index 0000000000..42967c15fe Binary files /dev/null and b/exercises/07_structs/structs3.exe differ diff --git a/exercises/07_structs/structs3.pdb b/exercises/07_structs/structs3.pdb new file mode 100644 index 0000000000..bc6fe17c6a Binary files /dev/null and b/exercises/07_structs/structs3.pdb differ diff --git a/exercises/07_structs/structs3.rs b/exercises/07_structs/structs3.rs index 69e5ced7f8..4aeef894d7 100644 --- a/exercises/07_structs/structs3.rs +++ b/exercises/07_structs/structs3.rs @@ -24,14 +24,16 @@ impl Package { } // TODO: Add the correct return type to the function signature. - fn is_international(&self) { + fn is_international(&self) -> bool { // TODO: Read the tests that use this method to find out when a package // is considered international. + self.sender_country != self.recipient_country } // TODO: Add the correct return type to the function signature. - fn get_fees(&self, cents_per_gram: u32) { + fn get_fees(&self, cents_per_gram: u32) -> u32 { // TODO: Calculate the package's fees. + self.weight_in_grams * cents_per_gram } } diff --git a/exercises/08_enums/enums1.exe b/exercises/08_enums/enums1.exe new file mode 100644 index 0000000000..695d0b4f13 Binary files /dev/null and b/exercises/08_enums/enums1.exe differ diff --git a/exercises/08_enums/enums1.pdb b/exercises/08_enums/enums1.pdb new file mode 100644 index 0000000000..ba487d64d8 Binary files /dev/null and b/exercises/08_enums/enums1.pdb differ diff --git a/exercises/08_enums/enums1.rs b/exercises/08_enums/enums1.rs index c0d0c308d2..db3f1dffca 100644 --- a/exercises/08_enums/enums1.rs +++ b/exercises/08_enums/enums1.rs @@ -1,6 +1,11 @@ #[derive(Debug)] enum Message { // TODO: Define a few types of messages as used below. + Quit, + Move, + Echo, + ChangeColor, + Resize, } fn main() { diff --git a/exercises/08_enums/enums2.exe b/exercises/08_enums/enums2.exe new file mode 100644 index 0000000000..5e66091f2e Binary files /dev/null and b/exercises/08_enums/enums2.exe differ diff --git a/exercises/08_enums/enums2.pdb b/exercises/08_enums/enums2.pdb new file mode 100644 index 0000000000..49a2d5ef11 Binary files /dev/null and b/exercises/08_enums/enums2.pdb differ diff --git a/exercises/08_enums/enums2.rs b/exercises/08_enums/enums2.rs index d70f6398d1..0723b96cc9 100644 --- a/exercises/08_enums/enums2.rs +++ b/exercises/08_enums/enums2.rs @@ -7,6 +7,11 @@ struct Point { #[derive(Debug)] enum Message { // TODO: Define the different variants used below. + Resize { width: u64, height: u64 }, + Move(Point), + Echo(String), + ChangeColor(u8, u8, u8), + Quit, } impl Message { diff --git a/exercises/08_enums/enums3.exe b/exercises/08_enums/enums3.exe new file mode 100644 index 0000000000..0eca8ce087 Binary files /dev/null and b/exercises/08_enums/enums3.exe differ diff --git a/exercises/08_enums/enums3.pdb b/exercises/08_enums/enums3.pdb new file mode 100644 index 0000000000..62ea89fb72 Binary files /dev/null and b/exercises/08_enums/enums3.pdb differ diff --git a/exercises/08_enums/enums3.rs b/exercises/08_enums/enums3.rs index cb05f657c2..464a3ec2ca 100644 --- a/exercises/08_enums/enums3.rs +++ b/exercises/08_enums/enums3.rs @@ -46,6 +46,15 @@ impl State { fn process(&mut self, message: Message) { // TODO: Create a match expression to process the different message // variants using the methods defined above. + + match message { + Message::Resize { width, height } => self.resize(width, height), + Message::Move(point) => self.move_position(point), + Message::Echo(s) => self.echo(s), + Message::ChangeColor(r, g, b) => self.change_color(r, g, b), + Message::Quit => self.quit(), + } + } } diff --git a/exercises/09_strings/strings1.exe b/exercises/09_strings/strings1.exe new file mode 100644 index 0000000000..2e6024cbb5 Binary files /dev/null and b/exercises/09_strings/strings1.exe differ diff --git a/exercises/09_strings/strings1.pdb b/exercises/09_strings/strings1.pdb new file mode 100644 index 0000000000..15df83f766 Binary files /dev/null and b/exercises/09_strings/strings1.pdb differ diff --git a/exercises/09_strings/strings1.rs b/exercises/09_strings/strings1.rs index 6abdbb48f0..06755aae40 100644 --- a/exercises/09_strings/strings1.rs +++ b/exercises/09_strings/strings1.rs @@ -1,6 +1,6 @@ // TODO: Fix the compiler error without changing the function signature. fn current_favorite_color() -> String { - "blue" + "blue".to_string() } fn main() { diff --git a/exercises/09_strings/strings2.exe b/exercises/09_strings/strings2.exe new file mode 100644 index 0000000000..ae4b404ee9 Binary files /dev/null and b/exercises/09_strings/strings2.exe differ diff --git a/exercises/09_strings/strings2.pdb b/exercises/09_strings/strings2.pdb new file mode 100644 index 0000000000..bbf016d6f2 Binary files /dev/null and b/exercises/09_strings/strings2.pdb differ diff --git a/exercises/09_strings/strings2.rs b/exercises/09_strings/strings2.rs index 93d9cb6b7f..2ed89c5666 100644 --- a/exercises/09_strings/strings2.rs +++ b/exercises/09_strings/strings2.rs @@ -6,7 +6,7 @@ fn is_a_color_word(attempt: &str) -> bool { fn main() { let word = String::from("green"); // Don't change this line. - if is_a_color_word(word) { + if is_a_color_word(&word) { println!("That is a color word I know!"); } else { println!("That is not a color word I know."); diff --git a/exercises/09_strings/strings3.exe b/exercises/09_strings/strings3.exe new file mode 100644 index 0000000000..dc3d09b832 Binary files /dev/null and b/exercises/09_strings/strings3.exe differ diff --git a/exercises/09_strings/strings3.pdb b/exercises/09_strings/strings3.pdb new file mode 100644 index 0000000000..40c61b5cf6 Binary files /dev/null and b/exercises/09_strings/strings3.pdb differ diff --git a/exercises/09_strings/strings3.rs b/exercises/09_strings/strings3.rs index f5e45b0ffc..233759d6c0 100644 --- a/exercises/09_strings/strings3.rs +++ b/exercises/09_strings/strings3.rs @@ -1,13 +1,16 @@ fn trim_me(input: &str) -> &str { // TODO: Remove whitespace from both ends of a string. + input.trim() } fn compose_me(input: &str) -> String { // TODO: Add " world!" to the string! There are multiple ways to do this. + format!("{} world!", input) } fn replace_me(input: &str) -> String { // TODO: Replace "cars" in the string with "balloons". + input.replace("cars", "balloons") } fn main() { diff --git a/exercises/09_strings/strings4.exe b/exercises/09_strings/strings4.exe new file mode 100644 index 0000000000..b03f8d6cc8 Binary files /dev/null and b/exercises/09_strings/strings4.exe differ diff --git a/exercises/09_strings/strings4.pdb b/exercises/09_strings/strings4.pdb new file mode 100644 index 0000000000..c5486e5d80 Binary files /dev/null and b/exercises/09_strings/strings4.pdb differ diff --git a/exercises/09_strings/strings4.rs b/exercises/09_strings/strings4.rs index 473072636d..3f7c5e7121 100644 --- a/exercises/09_strings/strings4.rs +++ b/exercises/09_strings/strings4.rs @@ -13,25 +13,25 @@ fn string(arg: String) { // Your task is to replace `placeholder(…)` with either `string_slice(…)` // or `string(…)` depending on what you think each value is. fn main() { - placeholder("blue"); + string_slice("blue"); - placeholder("red".to_string()); + string("red".to_string()); - placeholder(String::from("hi")); + string(String::from("hi")); - placeholder("rust is fun!".to_owned()); + string("rust is fun!".to_owned()); - placeholder("nice weather".into()); + string("nice weather".into()); - placeholder(format!("Interpolation {}", "Station")); + string(format!("Interpolation {}", "Station")); // WARNING: This is byte indexing, not character indexing. // Character indexing can be done using `s.chars().nth(INDEX)`. - placeholder(&String::from("abc")[0..1]); + string_slice(&String::from("abc")[0..1]); - placeholder(" hello there ".trim()); + string_slice(" hello there ".trim()); - placeholder("Happy Monday!".replace("Mon", "Tues")); + string("Happy Monday!".replace("Mon", "Tues")); - placeholder("mY sHiFt KeY iS sTiCkY".to_lowercase()); + string("mY sHiFt KeY iS sTiCkY".to_lowercase()); } diff --git a/exercises/10_modules/modules1.exe b/exercises/10_modules/modules1.exe new file mode 100644 index 0000000000..e77f4747ba Binary files /dev/null and b/exercises/10_modules/modules1.exe differ diff --git a/exercises/10_modules/modules1.pdb b/exercises/10_modules/modules1.pdb new file mode 100644 index 0000000000..02b2c56aad Binary files /dev/null and b/exercises/10_modules/modules1.pdb differ diff --git a/exercises/10_modules/modules1.rs b/exercises/10_modules/modules1.rs index d97ab23a53..81981dfca5 100644 --- a/exercises/10_modules/modules1.rs +++ b/exercises/10_modules/modules1.rs @@ -5,7 +5,7 @@ mod sausage_factory { String::from("Ginger") } - fn make_sausage() { + pub fn make_sausage() { get_secret_recipe(); println!("sausage!"); } diff --git a/exercises/10_modules/modules2.exe b/exercises/10_modules/modules2.exe new file mode 100644 index 0000000000..6c1ecd1312 Binary files /dev/null and b/exercises/10_modules/modules2.exe differ diff --git a/exercises/10_modules/modules2.pdb b/exercises/10_modules/modules2.pdb new file mode 100644 index 0000000000..dd4c89a526 Binary files /dev/null and b/exercises/10_modules/modules2.pdb differ diff --git a/exercises/10_modules/modules2.rs b/exercises/10_modules/modules2.rs index 782a70eace..66ef90b970 100644 --- a/exercises/10_modules/modules2.rs +++ b/exercises/10_modules/modules2.rs @@ -5,7 +5,8 @@ mod delicious_snacks { // TODO: Add the following two `use` statements after fixing them. // use self::fruits::PEAR as ???; // use self::veggies::CUCUMBER as ???; - + pub use self::fruits::PEAR as fruit; + pub use self::veggies::CUCUMBER as veggie; mod fruits { pub const PEAR: &str = "Pear"; pub const APPLE: &str = "Apple"; @@ -15,6 +16,7 @@ mod delicious_snacks { pub const CUCUMBER: &str = "Cucumber"; pub const CARROT: &str = "Carrot"; } + } fn main() { diff --git a/exercises/10_modules/modules3.exe b/exercises/10_modules/modules3.exe new file mode 100644 index 0000000000..de9078c9c5 Binary files /dev/null and b/exercises/10_modules/modules3.exe differ diff --git a/exercises/10_modules/modules3.pdb b/exercises/10_modules/modules3.pdb new file mode 100644 index 0000000000..e14660b204 Binary files /dev/null and b/exercises/10_modules/modules3.pdb differ diff --git a/exercises/10_modules/modules3.rs b/exercises/10_modules/modules3.rs index 691608d275..832902a40c 100644 --- a/exercises/10_modules/modules3.rs +++ b/exercises/10_modules/modules3.rs @@ -4,7 +4,7 @@ // TODO: Bring `SystemTime` and `UNIX_EPOCH` from the `std::time` module into // your scope. Bonus style points if you can do it with one line! // use ???; - +use std::time::{SystemTime, UNIX_EPOCH}; fn main() { match SystemTime::now().duration_since(UNIX_EPOCH) { Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()), diff --git a/exercises/11_hashmaps/hashmaps1.exe b/exercises/11_hashmaps/hashmaps1.exe new file mode 100644 index 0000000000..1c0696beb2 Binary files /dev/null and b/exercises/11_hashmaps/hashmaps1.exe differ diff --git a/exercises/11_hashmaps/hashmaps1.pdb b/exercises/11_hashmaps/hashmaps1.pdb new file mode 100644 index 0000000000..5c23897e4d Binary files /dev/null and b/exercises/11_hashmaps/hashmaps1.pdb differ diff --git a/exercises/11_hashmaps/hashmaps1.rs b/exercises/11_hashmaps/hashmaps1.rs index 74001d0432..66acc43ccb 100644 --- a/exercises/11_hashmaps/hashmaps1.rs +++ b/exercises/11_hashmaps/hashmaps1.rs @@ -9,12 +9,13 @@ use std::collections::HashMap; fn fruit_basket() -> HashMap { // TODO: Declare the hash map. // let mut basket = - + let mut basket: HashMap = HashMap::new(); // Two bananas are already given for you :) basket.insert(String::from("banana"), 2); // TODO: Put more fruits in your basket. - + basket.insert(String::from("apple"), 3); + basket.insert(String::from("mango"), 1); basket } diff --git a/exercises/11_hashmaps/hashmaps2.exe b/exercises/11_hashmaps/hashmaps2.exe new file mode 100644 index 0000000000..182aaff737 Binary files /dev/null and b/exercises/11_hashmaps/hashmaps2.exe differ diff --git a/exercises/11_hashmaps/hashmaps2.pdb b/exercises/11_hashmaps/hashmaps2.pdb new file mode 100644 index 0000000000..b21bfce69d Binary files /dev/null and b/exercises/11_hashmaps/hashmaps2.pdb differ diff --git a/exercises/11_hashmaps/hashmaps2.rs b/exercises/11_hashmaps/hashmaps2.rs index e9f53fea3c..db527c93be 100644 --- a/exercises/11_hashmaps/hashmaps2.rs +++ b/exercises/11_hashmaps/hashmaps2.rs @@ -32,6 +32,7 @@ fn fruit_basket(basket: &mut HashMap) { // TODO: Insert new fruits if they are not already present in the // basket. Note that you are not allowed to put any type of fruit that's // already present! + basket.entry(fruit).or_insert(1); } } @@ -41,6 +42,7 @@ fn main() { #[cfg(test)] mod tests { + use std::iter::FromIterator; use super::*; // Don't modify this function! @@ -89,7 +91,7 @@ mod tests { for fruit_kind in fruit_kinds { let Some(amount) = basket.get(&fruit_kind) else { - panic!("Fruit kind {fruit_kind:?} was not found in basket"); + panic!("{}", "Fruit kind {fruit_kind:?} was not found in basket"); }; assert!(*amount > 0); } diff --git a/exercises/11_hashmaps/hashmaps3.exe b/exercises/11_hashmaps/hashmaps3.exe new file mode 100644 index 0000000000..f855bff173 Binary files /dev/null and b/exercises/11_hashmaps/hashmaps3.exe differ diff --git a/exercises/11_hashmaps/hashmaps3.pdb b/exercises/11_hashmaps/hashmaps3.pdb new file mode 100644 index 0000000000..5dd111281e Binary files /dev/null and b/exercises/11_hashmaps/hashmaps3.pdb differ diff --git a/exercises/11_hashmaps/hashmaps3.rs b/exercises/11_hashmaps/hashmaps3.rs index 5b390ab9b8..12b54c5863 100644 --- a/exercises/11_hashmaps/hashmaps3.rs +++ b/exercises/11_hashmaps/hashmaps3.rs @@ -31,6 +31,26 @@ fn build_scores_table(results: &str) -> HashMap<&str, TeamScores> { // Keep in mind that goals scored by team 1 will be the number of goals // conceded by team 2. Similarly, goals scored by team 2 will be the // number of goals conceded by team 1. + + scores + .entry(team_1_name) + .or_insert_with(TeamScores::default) + .goals_scored += team_1_score; + + scores + .entry(team_1_name) + .or_insert_with(TeamScores::default) + .goals_conceded += team_2_score; + + scores + .entry(team_2_name) + .or_insert_with(TeamScores::default) + .goals_scored += team_2_score; + + scores + .entry(team_2_name) + .or_insert_with(TeamScores::default) + .goals_conceded += team_1_score; } scores @@ -54,9 +74,11 @@ England,Spain,1,0"; fn build_scores() { let scores = build_scores_table(RESULTS); - assert!(["England", "France", "Germany", "Italy", "Poland", "Spain"] - .into_iter() - .all(|team_name| scores.contains_key(team_name))); + assert!( + ["England", "France", "Germany", "Italy", "Poland", "Spain"] + .into_iter() + .all(|team_name| scores.contains_key(team_name)) + ); } #[test] diff --git a/exercises/12_options/options1.exe b/exercises/12_options/options1.exe new file mode 100644 index 0000000000..178b5a9809 Binary files /dev/null and b/exercises/12_options/options1.exe differ diff --git a/exercises/12_options/options1.pdb b/exercises/12_options/options1.pdb new file mode 100644 index 0000000000..87c7150aa5 Binary files /dev/null and b/exercises/12_options/options1.pdb differ diff --git a/exercises/12_options/options1.rs b/exercises/12_options/options1.rs index d0c412a8d4..42c5d17861 100644 --- a/exercises/12_options/options1.rs +++ b/exercises/12_options/options1.rs @@ -3,7 +3,13 @@ // someone eats it all, so no ice cream is left (value 0). Return `None` if // `hour_of_day` is higher than 23. fn maybe_ice_cream(hour_of_day: u16) -> Option { - // TODO: Complete the function body. + if hour_of_day > 23 { + None + } else if hour_of_day < 22 { + Some(5) + } else { + Some(0) + } } fn main() { @@ -20,7 +26,7 @@ mod tests { // Option? let ice_creams = maybe_ice_cream(12); - assert_eq!(ice_creams, 5); // Don't change this line. + assert_eq!(ice_creams, Some(5)); // Don't change this line. } #[test] diff --git a/exercises/12_options/options1_test.exe b/exercises/12_options/options1_test.exe new file mode 100644 index 0000000000..abff129781 Binary files /dev/null and b/exercises/12_options/options1_test.exe differ diff --git a/exercises/12_options/options1_test.pdb b/exercises/12_options/options1_test.pdb new file mode 100644 index 0000000000..b9df5583c9 Binary files /dev/null and b/exercises/12_options/options1_test.pdb differ diff --git a/exercises/12_options/options2.exe b/exercises/12_options/options2.exe new file mode 100644 index 0000000000..e928ed8678 Binary files /dev/null and b/exercises/12_options/options2.exe differ diff --git a/exercises/12_options/options2.pdb b/exercises/12_options/options2.pdb new file mode 100644 index 0000000000..19407d3b82 Binary files /dev/null and b/exercises/12_options/options2.pdb differ diff --git a/exercises/12_options/options2.rs b/exercises/12_options/options2.rs index 07c27c6ec2..1039d61db4 100644 --- a/exercises/12_options/options2.rs +++ b/exercises/12_options/options2.rs @@ -10,7 +10,7 @@ mod tests { let optional_target = Some(target); // TODO: Make this an if-let statement whose value is `Some`. - word = optional_target { + if let Some(word) = optional_target { assert_eq!(word, target); } } @@ -29,7 +29,7 @@ mod tests { // TODO: Make this a while-let statement. Remember that `Vec::pop()` // adds another layer of `Option`. You can do nested pattern matching // in if-let and while-let statements. - integer = optional_integers.pop() { + while let Some(Some(integer)) = optional_integers.pop() { assert_eq!(integer, cursor); cursor -= 1; } diff --git a/exercises/12_options/options3.exe b/exercises/12_options/options3.exe new file mode 100644 index 0000000000..f2d2698921 Binary files /dev/null and b/exercises/12_options/options3.exe differ diff --git a/exercises/12_options/options3.pdb b/exercises/12_options/options3.pdb new file mode 100644 index 0000000000..ae70f08e75 Binary files /dev/null and b/exercises/12_options/options3.pdb differ diff --git a/exercises/12_options/options3.rs b/exercises/12_options/options3.rs index c97b1d3cf4..d138fb7b1e 100644 --- a/exercises/12_options/options3.rs +++ b/exercises/12_options/options3.rs @@ -8,7 +8,7 @@ fn main() { let optional_point = Some(Point { x: 100, y: 200 }); // TODO: Fix the compiler error by adding something to this match statement. - match optional_point { + match &optional_point { Some(p) => println!("Coordinates are {},{}", p.x, p.y), _ => panic!("No match!"), } diff --git a/exercises/13_error_handling/errors1.exe b/exercises/13_error_handling/errors1.exe new file mode 100644 index 0000000000..6473551151 Binary files /dev/null and b/exercises/13_error_handling/errors1.exe differ diff --git a/exercises/13_error_handling/errors1.pdb b/exercises/13_error_handling/errors1.pdb new file mode 100644 index 0000000000..96a5790293 Binary files /dev/null and b/exercises/13_error_handling/errors1.pdb differ diff --git a/exercises/13_error_handling/errors1.rs b/exercises/13_error_handling/errors1.rs index e07fddc3cd..0cced95850 100644 --- a/exercises/13_error_handling/errors1.rs +++ b/exercises/13_error_handling/errors1.rs @@ -4,12 +4,12 @@ // construct to `Option` that can be used to express error conditions. Change // the function signature and body to return `Result` instead // of `Option`. -fn generate_nametag_text(name: String) -> Option { +fn generate_nametag_text(name: String) -> Result { if name.is_empty() { // Empty names aren't allowed - None + Err("Empty names aren't allowed".to_string()) } else { - Some(format!("Hi! My name is {name}")) + Ok(format!("Hi! My name is {name}")) } } diff --git a/exercises/13_error_handling/errors2.exe b/exercises/13_error_handling/errors2.exe new file mode 100644 index 0000000000..66644614e0 Binary files /dev/null and b/exercises/13_error_handling/errors2.exe differ diff --git a/exercises/13_error_handling/errors2.pdb b/exercises/13_error_handling/errors2.pdb new file mode 100644 index 0000000000..b879e211ba Binary files /dev/null and b/exercises/13_error_handling/errors2.pdb differ diff --git a/exercises/13_error_handling/errors2.rs b/exercises/13_error_handling/errors2.rs index defe359b48..3d850f76b5 100644 --- a/exercises/13_error_handling/errors2.rs +++ b/exercises/13_error_handling/errors2.rs @@ -21,7 +21,7 @@ fn total_cost(item_quantity: &str) -> Result { let cost_per_item = 5; // TODO: Handle the error case as described above. - let qty = item_quantity.parse::(); + let qty = item_quantity.parse::()?; Ok(qty * cost_per_item + processing_fee) } diff --git a/exercises/13_error_handling/errors2_test b/exercises/13_error_handling/errors2_test new file mode 100644 index 0000000000..a593754f35 Binary files /dev/null and b/exercises/13_error_handling/errors2_test differ diff --git a/exercises/13_error_handling/errors2_test.pdb b/exercises/13_error_handling/errors2_test.pdb new file mode 100644 index 0000000000..1ae5d2d809 Binary files /dev/null and b/exercises/13_error_handling/errors2_test.pdb differ diff --git a/exercises/13_error_handling/errors3.exe b/exercises/13_error_handling/errors3.exe new file mode 100644 index 0000000000..831562eb51 Binary files /dev/null and b/exercises/13_error_handling/errors3.exe differ diff --git a/exercises/13_error_handling/errors3.pdb b/exercises/13_error_handling/errors3.pdb new file mode 100644 index 0000000000..10b47a3994 Binary files /dev/null and b/exercises/13_error_handling/errors3.pdb differ diff --git a/exercises/13_error_handling/errors3.rs b/exercises/13_error_handling/errors3.rs index 8e8c38a2a1..bf21bbc622 100644 --- a/exercises/13_error_handling/errors3.rs +++ b/exercises/13_error_handling/errors3.rs @@ -15,7 +15,7 @@ fn total_cost(item_quantity: &str) -> Result { // TODO: Fix the compiler error by changing the signature and body of the // `main` function. -fn main() { +fn main() -> Result<(), ParseIntError> { let mut tokens = 100; let pretend_user_input = "8"; @@ -28,4 +28,6 @@ fn main() { tokens -= cost; println!("You now have {tokens} tokens."); } + + Ok(()) } diff --git a/exercises/13_error_handling/errors4.exe b/exercises/13_error_handling/errors4.exe new file mode 100644 index 0000000000..2a688d173d Binary files /dev/null and b/exercises/13_error_handling/errors4.exe differ diff --git a/exercises/13_error_handling/errors4.pdb b/exercises/13_error_handling/errors4.pdb new file mode 100644 index 0000000000..e0b5601b6e Binary files /dev/null and b/exercises/13_error_handling/errors4.pdb differ diff --git a/exercises/13_error_handling/errors4.rs b/exercises/13_error_handling/errors4.rs index ba01e54bf5..327b38f3a7 100644 --- a/exercises/13_error_handling/errors4.rs +++ b/exercises/13_error_handling/errors4.rs @@ -10,7 +10,13 @@ struct PositiveNonzeroInteger(u64); impl PositiveNonzeroInteger { fn new(value: i64) -> Result { // TODO: This function shouldn't always return an `Ok`. - Ok(Self(value as u64)) + if value < 0 { + Err(CreationError::Negative) + } else if value == 0 { + Err(CreationError::Zero) + } else { + Ok(Self(value as u64)) + } } } diff --git a/exercises/13_error_handling/errors5.exe b/exercises/13_error_handling/errors5.exe new file mode 100644 index 0000000000..045d4d3bd2 Binary files /dev/null and b/exercises/13_error_handling/errors5.exe differ diff --git a/exercises/13_error_handling/errors5.pdb b/exercises/13_error_handling/errors5.pdb new file mode 100644 index 0000000000..418a64a712 Binary files /dev/null and b/exercises/13_error_handling/errors5.pdb differ diff --git a/exercises/13_error_handling/errors5.rs b/exercises/13_error_handling/errors5.rs index 125779b867..405f0dc45d 100644 --- a/exercises/13_error_handling/errors5.rs +++ b/exercises/13_error_handling/errors5.rs @@ -48,7 +48,7 @@ impl PositiveNonzeroInteger { // TODO: Add the correct return type `Result<(), Box>`. What can we // use to describe both errors? Is there a trait which both errors implement? -fn main() { +fn main() -> Result<(), Box> { let pretend_user_input = "42"; let x: i64 = pretend_user_input.parse()?; println!("output={:?}", PositiveNonzeroInteger::new(x)?); diff --git a/exercises/13_error_handling/errors6.exe b/exercises/13_error_handling/errors6.exe new file mode 100644 index 0000000000..43a1d4538b Binary files /dev/null and b/exercises/13_error_handling/errors6.exe differ diff --git a/exercises/13_error_handling/errors6.pdb b/exercises/13_error_handling/errors6.pdb new file mode 100644 index 0000000000..06758328cb Binary files /dev/null and b/exercises/13_error_handling/errors6.pdb differ diff --git a/exercises/13_error_handling/errors6.rs b/exercises/13_error_handling/errors6.rs index b1995e036a..353b50b2ab 100644 --- a/exercises/13_error_handling/errors6.rs +++ b/exercises/13_error_handling/errors6.rs @@ -25,7 +25,9 @@ impl ParsePosNonzeroError { } // TODO: Add another error conversion function here. - // fn from_parse_int(???) -> Self { ??? } + fn from_parse_int(err: ParseIntError) -> Self { + Self::ParseInt(err) + } } #[derive(PartialEq, Debug)] @@ -43,7 +45,7 @@ impl PositiveNonzeroInteger { fn parse(s: &str) -> Result { // TODO: change this to return an appropriate error instead of panicking // when `parse()` returns an error. - let x: i64 = s.parse().unwrap(); + let x: i64 = s.parse().map_err(ParsePosNonzeroError::from_parse_int)?; Self::new(x).map_err(ParsePosNonzeroError::from_creation) } } diff --git a/exercises/14_generics/generics1.exe b/exercises/14_generics/generics1.exe new file mode 100644 index 0000000000..90c6406fa2 Binary files /dev/null and b/exercises/14_generics/generics1.exe differ diff --git a/exercises/14_generics/generics1.pdb b/exercises/14_generics/generics1.pdb new file mode 100644 index 0000000000..4c9c190d31 Binary files /dev/null and b/exercises/14_generics/generics1.pdb differ diff --git a/exercises/14_generics/generics1.rs b/exercises/14_generics/generics1.rs index 87ed990b65..e13fd828f1 100644 --- a/exercises/14_generics/generics1.rs +++ b/exercises/14_generics/generics1.rs @@ -6,7 +6,7 @@ fn main() { // TODO: Fix the compiler error by annotating the type of the vector // `Vec`. Choose `T` as some integer type that can be created from // `u8` and `i8`. - let mut numbers = Vec::new(); + let mut numbers: Vec = Vec::new(); // Don't change the lines below. let n1: u8 = 42; diff --git a/exercises/14_generics/generics2.exe b/exercises/14_generics/generics2.exe new file mode 100644 index 0000000000..25c34f3ce1 Binary files /dev/null and b/exercises/14_generics/generics2.exe differ diff --git a/exercises/14_generics/generics2.pdb b/exercises/14_generics/generics2.pdb new file mode 100644 index 0000000000..70f21a5c24 Binary files /dev/null and b/exercises/14_generics/generics2.pdb differ diff --git a/exercises/14_generics/generics2.rs b/exercises/14_generics/generics2.rs index 8908725bf9..ba77625854 100644 --- a/exercises/14_generics/generics2.rs +++ b/exercises/14_generics/generics2.rs @@ -1,12 +1,12 @@ // This powerful wrapper provides the ability to store a positive integer value. // TODO: Rewrite it using a generic so that it supports wrapping ANY type. -struct Wrapper { - value: u32, +struct Wrapper { + value: T, } // TODO: Adapt the struct's implementation to be generic over the wrapped value. -impl Wrapper { - fn new(value: u32) -> Self { +impl Wrapper { + fn new(value: T) -> Self { Wrapper { value } } } diff --git a/exercises/15_traits/traits1.exe b/exercises/15_traits/traits1.exe new file mode 100644 index 0000000000..fa74e97fc0 Binary files /dev/null and b/exercises/15_traits/traits1.exe differ diff --git a/exercises/15_traits/traits1.pdb b/exercises/15_traits/traits1.pdb new file mode 100644 index 0000000000..e282457b4c Binary files /dev/null and b/exercises/15_traits/traits1.pdb differ diff --git a/exercises/15_traits/traits1.rs b/exercises/15_traits/traits1.rs index 85be17ea82..fad6a50892 100644 --- a/exercises/15_traits/traits1.rs +++ b/exercises/15_traits/traits1.rs @@ -6,6 +6,9 @@ trait AppendBar { impl AppendBar for String { // TODO: Implement `AppendBar` for the type `String`. + fn append_bar(self) -> Self { + self + "Bar" + } } fn main() { diff --git a/exercises/15_traits/traits2.exe b/exercises/15_traits/traits2.exe new file mode 100644 index 0000000000..0e51785450 Binary files /dev/null and b/exercises/15_traits/traits2.exe differ diff --git a/exercises/15_traits/traits2.pdb b/exercises/15_traits/traits2.pdb new file mode 100644 index 0000000000..3412539fed Binary files /dev/null and b/exercises/15_traits/traits2.pdb differ diff --git a/exercises/15_traits/traits2.rs b/exercises/15_traits/traits2.rs index d724dc288e..923945d709 100644 --- a/exercises/15_traits/traits2.rs +++ b/exercises/15_traits/traits2.rs @@ -4,7 +4,12 @@ trait AppendBar { // TODO: Implement the trait `AppendBar` for a vector of strings. // `append_bar` should push the string "Bar" into the vector. - +impl AppendBar for Vec { + fn append_bar(mut self) -> Self { + self.push(String::from("Bar")); + self + } +} fn main() { // You can optionally experiment here. } diff --git a/exercises/15_traits/traits3.exe b/exercises/15_traits/traits3.exe new file mode 100644 index 0000000000..ba33f0516c Binary files /dev/null and b/exercises/15_traits/traits3.exe differ diff --git a/exercises/15_traits/traits3.pdb b/exercises/15_traits/traits3.pdb new file mode 100644 index 0000000000..c2ae4cead3 Binary files /dev/null and b/exercises/15_traits/traits3.pdb differ diff --git a/exercises/15_traits/traits3.rs b/exercises/15_traits/traits3.rs index c244650da6..3bc158542e 100644 --- a/exercises/15_traits/traits3.rs +++ b/exercises/15_traits/traits3.rs @@ -3,7 +3,9 @@ trait Licensed { // implementors like the two structs below can share that default behavior // without repeating the function. // The default license information should be the string "Default license". - fn licensing_info(&self) -> String; + fn licensing_info(&self) -> String{ + "Default license".to_string() + } } struct SomeSoftware { diff --git a/exercises/15_traits/traits4.exe b/exercises/15_traits/traits4.exe new file mode 100644 index 0000000000..943f7eb979 Binary files /dev/null and b/exercises/15_traits/traits4.exe differ diff --git a/exercises/15_traits/traits4.pdb b/exercises/15_traits/traits4.pdb new file mode 100644 index 0000000000..1bd6b5a59c Binary files /dev/null and b/exercises/15_traits/traits4.pdb differ diff --git a/exercises/15_traits/traits4.rs b/exercises/15_traits/traits4.rs index 80092a6466..b23dcdda95 100644 --- a/exercises/15_traits/traits4.rs +++ b/exercises/15_traits/traits4.rs @@ -11,7 +11,7 @@ impl Licensed for SomeSoftware {} impl Licensed for OtherSoftware {} // TODO: Fix the compiler error by only changing the signature of this function. -fn compare_license_types(software1: ???, software2: ???) -> bool { +fn compare_license_types(software1: impl Licensed, software2: impl Licensed) -> bool { software1.licensing_info() == software2.licensing_info() } diff --git a/exercises/15_traits/traits5.exe b/exercises/15_traits/traits5.exe new file mode 100644 index 0000000000..12318894ca Binary files /dev/null and b/exercises/15_traits/traits5.exe differ diff --git a/exercises/15_traits/traits5.pdb b/exercises/15_traits/traits5.pdb new file mode 100644 index 0000000000..b41d8bbb67 Binary files /dev/null and b/exercises/15_traits/traits5.pdb differ diff --git a/exercises/15_traits/traits5.rs b/exercises/15_traits/traits5.rs index 5b356ac738..3f4843712d 100644 --- a/exercises/15_traits/traits5.rs +++ b/exercises/15_traits/traits5.rs @@ -19,7 +19,7 @@ impl SomeTrait for OtherStruct {} impl OtherTrait for OtherStruct {} // TODO: Fix the compiler error by only changing the signature of this function. -fn some_func(item: ???) -> bool { +fn some_func(item: impl SomeTrait + OtherTrait) -> bool { item.some_function() && item.other_function() } diff --git a/exercises/16_lifetimes/lifetimes1.exe b/exercises/16_lifetimes/lifetimes1.exe new file mode 100644 index 0000000000..dad6db69b9 Binary files /dev/null and b/exercises/16_lifetimes/lifetimes1.exe differ diff --git a/exercises/16_lifetimes/lifetimes1.pdb b/exercises/16_lifetimes/lifetimes1.pdb new file mode 100644 index 0000000000..2138bb94d8 Binary files /dev/null and b/exercises/16_lifetimes/lifetimes1.pdb differ diff --git a/exercises/16_lifetimes/lifetimes1.rs b/exercises/16_lifetimes/lifetimes1.rs index 19e2d398b5..683bd75592 100644 --- a/exercises/16_lifetimes/lifetimes1.rs +++ b/exercises/16_lifetimes/lifetimes1.rs @@ -4,7 +4,7 @@ // not own their own data. What if their owner goes out of scope? // TODO: Fix the compiler error by updating the function signature. -fn longest(x: &str, y: &str) -> &str { +fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { diff --git a/exercises/16_lifetimes/lifetimes2.exe b/exercises/16_lifetimes/lifetimes2.exe new file mode 100644 index 0000000000..f194be4fae Binary files /dev/null and b/exercises/16_lifetimes/lifetimes2.exe differ diff --git a/exercises/16_lifetimes/lifetimes2.pdb b/exercises/16_lifetimes/lifetimes2.pdb new file mode 100644 index 0000000000..5a5d541151 Binary files /dev/null and b/exercises/16_lifetimes/lifetimes2.pdb differ diff --git a/exercises/16_lifetimes/lifetimes2.rs b/exercises/16_lifetimes/lifetimes2.rs index de5a5dfc79..e7893b76f1 100644 --- a/exercises/16_lifetimes/lifetimes2.rs +++ b/exercises/16_lifetimes/lifetimes2.rs @@ -15,6 +15,6 @@ fn main() { { let string2 = String::from("xyz"); result = longest(&string1, &string2); + println!("The longest string is '{result}'"); } - println!("The longest string is '{result}'"); } diff --git a/exercises/16_lifetimes/lifetimes3.exe b/exercises/16_lifetimes/lifetimes3.exe new file mode 100644 index 0000000000..9793585939 Binary files /dev/null and b/exercises/16_lifetimes/lifetimes3.exe differ diff --git a/exercises/16_lifetimes/lifetimes3.pdb b/exercises/16_lifetimes/lifetimes3.pdb new file mode 100644 index 0000000000..02075b0df7 Binary files /dev/null and b/exercises/16_lifetimes/lifetimes3.pdb differ diff --git a/exercises/16_lifetimes/lifetimes3.rs b/exercises/16_lifetimes/lifetimes3.rs index 1cc27592c6..91e3922c26 100644 --- a/exercises/16_lifetimes/lifetimes3.rs +++ b/exercises/16_lifetimes/lifetimes3.rs @@ -1,9 +1,9 @@ // Lifetimes are also needed when structs hold references. // TODO: Fix the compiler errors about the struct. -struct Book { - author: &str, - title: &str, +struct Book<'a> { + author: &'a str, + title: &'a str, } fn main() { diff --git a/exercises/17_tests/tests1.exe b/exercises/17_tests/tests1.exe new file mode 100644 index 0000000000..f4f448e18e Binary files /dev/null and b/exercises/17_tests/tests1.exe differ diff --git a/exercises/17_tests/tests1.pdb b/exercises/17_tests/tests1.pdb new file mode 100644 index 0000000000..e3ac5ca687 Binary files /dev/null and b/exercises/17_tests/tests1.pdb differ diff --git a/exercises/17_tests/tests1.rs b/exercises/17_tests/tests1.rs index 7529f9f049..1cd8b7659b 100644 --- a/exercises/17_tests/tests1.rs +++ b/exercises/17_tests/tests1.rs @@ -13,11 +13,14 @@ fn main() { mod tests { // TODO: Import `is_even`. You can use a wildcard to import everything in // the outer module. - - #[test] + + use is_even; + #[test] fn you_can_assert() { // TODO: Test the function `is_even` with some values. - assert!(); - assert!(); + + assert!(is_even(2)); + assert!(!is_even(3)); } + } diff --git a/exercises/17_tests/tests2.exe b/exercises/17_tests/tests2.exe new file mode 100644 index 0000000000..c68ea4f218 Binary files /dev/null and b/exercises/17_tests/tests2.exe differ diff --git a/exercises/17_tests/tests2.pdb b/exercises/17_tests/tests2.pdb new file mode 100644 index 0000000000..f175d5fdf9 Binary files /dev/null and b/exercises/17_tests/tests2.pdb differ diff --git a/exercises/17_tests/tests2.rs b/exercises/17_tests/tests2.rs index 0c6573e8f0..52faa7bb5d 100644 --- a/exercises/17_tests/tests2.rs +++ b/exercises/17_tests/tests2.rs @@ -15,9 +15,9 @@ mod tests { #[test] fn you_can_assert_eq() { // TODO: Test the function `power_of_2` with some values. - assert_eq!(); - assert_eq!(); - assert_eq!(); - assert_eq!(); + assert_eq!(power_of_2(0), 1); + assert_eq!(power_of_2(1), 2); + assert_eq!(power_of_2(2), 4); + assert_eq!(power_of_2(3), 8); } } diff --git a/exercises/17_tests/tests3.exe b/exercises/17_tests/tests3.exe new file mode 100644 index 0000000000..c56688c3ec Binary files /dev/null and b/exercises/17_tests/tests3.exe differ diff --git a/exercises/17_tests/tests3.pdb b/exercises/17_tests/tests3.pdb new file mode 100644 index 0000000000..348151f8a2 Binary files /dev/null and b/exercises/17_tests/tests3.pdb differ diff --git a/exercises/17_tests/tests3.rs b/exercises/17_tests/tests3.rs index 822184ef75..cebb249b0e 100644 --- a/exercises/17_tests/tests3.rs +++ b/exercises/17_tests/tests3.rs @@ -29,13 +29,14 @@ mod tests { // TODO: This test should check if the rectangle has the size that we // pass to its constructor. let rect = Rectangle::new(10, 20); - assert_eq!(todo!(), 10); // Check width - assert_eq!(todo!(), 20); // Check height + assert_eq!(rect.width, 10); // Check width + assert_eq!(rect.height, 20); // Check height } // TODO: This test should check if the program panics when we try to create // a rectangle with negative width. #[test] + #[should_panic] // 添加 should_panic 属性 fn negative_width() { let _rect = Rectangle::new(-10, 10); } @@ -43,7 +44,8 @@ mod tests { // TODO: This test should check if the program panics when we try to create // a rectangle with negative height. #[test] + #[should_panic] // 添加 should_panic 属性 fn negative_height() { let _rect = Rectangle::new(10, -10); } -} +} \ No newline at end of file diff --git a/exercises/18_iterators/iterators1.exe b/exercises/18_iterators/iterators1.exe new file mode 100644 index 0000000000..c4962a7e03 Binary files /dev/null and b/exercises/18_iterators/iterators1.exe differ diff --git a/exercises/18_iterators/iterators1.pdb b/exercises/18_iterators/iterators1.pdb new file mode 100644 index 0000000000..9790bb96ab Binary files /dev/null and b/exercises/18_iterators/iterators1.pdb differ diff --git a/exercises/18_iterators/iterators1.rs b/exercises/18_iterators/iterators1.rs index ca937ed00e..71d8112b1e 100644 --- a/exercises/18_iterators/iterators1.rs +++ b/exercises/18_iterators/iterators1.rs @@ -13,13 +13,13 @@ mod tests { let my_fav_fruits = ["banana", "custard apple", "avocado", "peach", "raspberry"]; // TODO: Create an iterator over the array. - let mut fav_fruits_iterator = todo!(); + let mut fav_fruits_iterator = my_fav_fruits.iter(); assert_eq!(fav_fruits_iterator.next(), Some(&"banana")); - assert_eq!(fav_fruits_iterator.next(), todo!()); // TODO: Replace `todo!()` + assert_eq!(fav_fruits_iterator.next(), Some(&"custard apple")); // TODO: Replace `todo!()` assert_eq!(fav_fruits_iterator.next(), Some(&"avocado")); - assert_eq!(fav_fruits_iterator.next(), todo!()); // TODO: Replace `todo!()` + assert_eq!(fav_fruits_iterator.next(), Some(&"peach")); // TODO: Replace `todo!()` assert_eq!(fav_fruits_iterator.next(), Some(&"raspberry")); - assert_eq!(fav_fruits_iterator.next(), todo!()); // TODO: Replace `todo!()` + assert_eq!(fav_fruits_iterator.next(), None); // TODO: Replace `todo!()` } } diff --git a/exercises/18_iterators/iterators2.exe b/exercises/18_iterators/iterators2.exe new file mode 100644 index 0000000000..04cce7b96c Binary files /dev/null and b/exercises/18_iterators/iterators2.exe differ diff --git a/exercises/18_iterators/iterators2.pdb b/exercises/18_iterators/iterators2.pdb new file mode 100644 index 0000000000..5fe4567284 Binary files /dev/null and b/exercises/18_iterators/iterators2.pdb differ diff --git a/exercises/18_iterators/iterators2.rs b/exercises/18_iterators/iterators2.rs index 5903e657e9..fe277609ff 100644 --- a/exercises/18_iterators/iterators2.rs +++ b/exercises/18_iterators/iterators2.rs @@ -7,7 +7,7 @@ fn capitalize_first(input: &str) -> String { let mut chars = input.chars(); match chars.next() { None => String::new(), - Some(first) => todo!(), + Some(first) => first.to_uppercase().collect::() + chars.as_str(), } } @@ -16,6 +16,7 @@ fn capitalize_first(input: &str) -> String { // ["hello", "world"] -> ["Hello", "World"] fn capitalize_words_vector(words: &[&str]) -> Vec { // ??? + words.iter().map(|word| capitalize_first(word)).collect() } // TODO: Apply the `capitalize_first` function again to a slice of string @@ -23,6 +24,7 @@ fn capitalize_words_vector(words: &[&str]) -> Vec { // ["hello", " ", "world"] -> "Hello World" fn capitalize_words_string(words: &[&str]) -> String { // ??? + words.iter().map(|word| capitalize_first(word)).collect() } fn main() { diff --git a/exercises/18_iterators/iterators3 b/exercises/18_iterators/iterators3 new file mode 100644 index 0000000000..e4bbf4e828 Binary files /dev/null and b/exercises/18_iterators/iterators3 differ diff --git a/exercises/18_iterators/iterators3.exe b/exercises/18_iterators/iterators3.exe new file mode 100644 index 0000000000..bc593f5b20 Binary files /dev/null and b/exercises/18_iterators/iterators3.exe differ diff --git a/exercises/18_iterators/iterators3.pdb b/exercises/18_iterators/iterators3.pdb new file mode 100644 index 0000000000..d78c849768 Binary files /dev/null and b/exercises/18_iterators/iterators3.pdb differ diff --git a/exercises/18_iterators/iterators3.rs b/exercises/18_iterators/iterators3.rs index 6b1eca1734..44f9e14b16 100644 --- a/exercises/18_iterators/iterators3.rs +++ b/exercises/18_iterators/iterators3.rs @@ -1,3 +1,5 @@ +use std::convert::{TryFrom, TryInto}; + #[derive(Debug, PartialEq, Eq)] enum DivisionError { // Example: 42 / 0 @@ -11,21 +13,35 @@ enum DivisionError { // TODO: Calculate `a` divided by `b` if `a` is evenly divisible by `b`. // Otherwise, return a suitable error. fn divide(a: i64, b: i64) -> Result { - todo!(); + if b == 0 { + return Err(DivisionError::DivideByZero); + } + + if a == i64::MIN && b == -1 { + return Err(DivisionError::IntegerOverflow); + } + + if a % b != 0 { + return Err(DivisionError::NotDivisible); + } + + Ok(a / b) } // TODO: Add the correct return type and complete the function body. // Desired output: `Ok([1, 11, 1426, 3])` -fn result_with_list() { +fn result_with_list() -> Result<[i64; 4], DivisionError> { let numbers = [27, 297, 38502, 81]; - let division_results = numbers.into_iter().map(|n| divide(n, 27)); + let results: Result, DivisionError> = numbers.iter().map(|&n| divide(n, 27)).collect(); + results.and_then(|v| <[i64; 4]>::try_from(v).map_err(|_| DivisionError::NotDivisible)) } // TODO: Add the correct return type and complete the function body. // Desired output: `[Ok(1), Ok(11), Ok(1426), Ok(3)]` -fn list_of_results() { +fn list_of_results() -> [Result; 4] { let numbers = [27, 297, 38502, 81]; - let division_results = numbers.into_iter().map(|n| divide(n, 27)); + let division_results: Vec<_> = numbers.iter().map(|&n| divide(n, 27)).collect(); + division_results.try_into().unwrap() } fn main() { diff --git a/exercises/18_iterators/iterators3_test b/exercises/18_iterators/iterators3_test new file mode 100644 index 0000000000..2827817e2f Binary files /dev/null and b/exercises/18_iterators/iterators3_test differ diff --git a/exercises/18_iterators/iterators3_test.pdb b/exercises/18_iterators/iterators3_test.pdb new file mode 100644 index 0000000000..b7768f6c21 Binary files /dev/null and b/exercises/18_iterators/iterators3_test.pdb differ diff --git a/exercises/18_iterators/iterators4.exe b/exercises/18_iterators/iterators4.exe new file mode 100644 index 0000000000..0c39a9edae Binary files /dev/null and b/exercises/18_iterators/iterators4.exe differ diff --git a/exercises/18_iterators/iterators4.pdb b/exercises/18_iterators/iterators4.pdb new file mode 100644 index 0000000000..9d9cc97be8 Binary files /dev/null and b/exercises/18_iterators/iterators4.pdb differ diff --git a/exercises/18_iterators/iterators4.rs b/exercises/18_iterators/iterators4.rs index c296f0e426..42bc60eca8 100644 --- a/exercises/18_iterators/iterators4.rs +++ b/exercises/18_iterators/iterators4.rs @@ -10,6 +10,7 @@ fn factorial(num: u64) -> u64 { // - additional variables // For an extra challenge, don't use: // - recursion + (1..=num).product() } fn main() { diff --git a/exercises/18_iterators/iterators5.exe b/exercises/18_iterators/iterators5.exe new file mode 100644 index 0000000000..f8ef029022 Binary files /dev/null and b/exercises/18_iterators/iterators5.exe differ diff --git a/exercises/18_iterators/iterators5.pdb b/exercises/18_iterators/iterators5.pdb new file mode 100644 index 0000000000..5a639b3515 Binary files /dev/null and b/exercises/18_iterators/iterators5.pdb differ diff --git a/exercises/18_iterators/iterators5.rs b/exercises/18_iterators/iterators5.rs index 7e434cc5f9..9bdf420469 100644 --- a/exercises/18_iterators/iterators5.rs +++ b/exercises/18_iterators/iterators5.rs @@ -28,6 +28,7 @@ fn count_for(map: &HashMap, value: Progress) -> usize { fn count_iterator(map: &HashMap, value: Progress) -> usize { // `map` is a hash map with `String` keys and `Progress` values. // map = { "variables1": Complete, "from_str": None, … } + map.values().filter(|&&v| v == value).count() } fn count_collection_for(collection: &[HashMap], value: Progress) -> usize { @@ -48,6 +49,11 @@ fn count_collection_iterator(collection: &[HashMap], value: Pr // `collection` is a slice of hash maps. // collection = [{ "variables1": Complete, "from_str": None, … }, // { "variables2": Complete, … }, … ] + collection + .iter() + .flat_map(|map| map.values()) + .filter(|&&v| v == value) + .count() } fn main() { diff --git a/exercises/19_smart_pointers/arc1.exe b/exercises/19_smart_pointers/arc1.exe new file mode 100644 index 0000000000..6b46b306d5 Binary files /dev/null and b/exercises/19_smart_pointers/arc1.exe differ diff --git a/exercises/19_smart_pointers/arc1.pdb b/exercises/19_smart_pointers/arc1.pdb new file mode 100644 index 0000000000..66b4aea672 Binary files /dev/null and b/exercises/19_smart_pointers/arc1.pdb differ diff --git a/exercises/19_smart_pointers/arc1.rs b/exercises/19_smart_pointers/arc1.rs index 6bb860f93f..5673b70a31 100644 --- a/exercises/19_smart_pointers/arc1.rs +++ b/exercises/19_smart_pointers/arc1.rs @@ -23,13 +23,13 @@ fn main() { let numbers: Vec<_> = (0..100u32).collect(); // TODO: Define `shared_numbers` by using `Arc`. - // let shared_numbers = ???; - + let shared_numbers = Arc::new(numbers); + let mut join_handles = Vec::new(); for offset in 0..8 { // TODO: Define `child_numbers` using `shared_numbers`. - // let child_numbers = ???; + let child_numbers = Arc::clone(&shared_numbers); let handle = thread::spawn(move || { let sum: u32 = child_numbers.iter().filter(|&&n| n % 8 == offset).sum(); diff --git a/exercises/19_smart_pointers/box1.exe b/exercises/19_smart_pointers/box1.exe new file mode 100644 index 0000000000..269104f34a Binary files /dev/null and b/exercises/19_smart_pointers/box1.exe differ diff --git a/exercises/19_smart_pointers/box1.pdb b/exercises/19_smart_pointers/box1.pdb new file mode 100644 index 0000000000..40b32c2958 Binary files /dev/null and b/exercises/19_smart_pointers/box1.pdb differ diff --git a/exercises/19_smart_pointers/box1.rs b/exercises/19_smart_pointers/box1.rs index d70e1c3d39..1f81bb7396 100644 --- a/exercises/19_smart_pointers/box1.rs +++ b/exercises/19_smart_pointers/box1.rs @@ -12,18 +12,18 @@ // TODO: Use a `Box` in the enum definition to make the code compile. #[derive(PartialEq, Debug)] enum List { - Cons(i32, List), + Cons(i32, Box), Nil, } // TODO: Create an empty cons list. fn create_empty_list() -> List { - todo!() + List::Nil } // TODO: Create a non-empty cons list. fn create_non_empty_list() -> List { - todo!() + List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil)))) } fn main() { diff --git a/exercises/19_smart_pointers/box1_test b/exercises/19_smart_pointers/box1_test new file mode 100644 index 0000000000..00abb52e8c Binary files /dev/null and b/exercises/19_smart_pointers/box1_test differ diff --git a/exercises/19_smart_pointers/box1_test.pdb b/exercises/19_smart_pointers/box1_test.pdb new file mode 100644 index 0000000000..3e2a4a8e33 Binary files /dev/null and b/exercises/19_smart_pointers/box1_test.pdb differ diff --git a/exercises/19_smart_pointers/cow1.exe b/exercises/19_smart_pointers/cow1.exe new file mode 100644 index 0000000000..52712d9ed2 Binary files /dev/null and b/exercises/19_smart_pointers/cow1.exe differ diff --git a/exercises/19_smart_pointers/cow1.pdb b/exercises/19_smart_pointers/cow1.pdb new file mode 100644 index 0000000000..e2f9af9225 Binary files /dev/null and b/exercises/19_smart_pointers/cow1.pdb differ diff --git a/exercises/19_smart_pointers/cow1.rs b/exercises/19_smart_pointers/cow1.rs index 1566500716..0c9c1d6acd 100644 --- a/exercises/19_smart_pointers/cow1.rs +++ b/exercises/19_smart_pointers/cow1.rs @@ -39,7 +39,7 @@ mod tests { let mut input = Cow::from(&vec); abs_all(&mut input); // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`. - assert!(matches!(input, todo!())); + assert!(matches!(input, Cow::Borrowed(_))); } #[test] @@ -52,7 +52,7 @@ mod tests { let mut input = Cow::from(vec); abs_all(&mut input); // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`. - assert!(matches!(input, todo!())); + assert!(matches!(input, Cow::Owned(_))); } #[test] @@ -64,6 +64,6 @@ mod tests { let mut input = Cow::from(vec); abs_all(&mut input); // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`. - assert!(matches!(input, todo!())); + assert!(matches!(input, Cow::Owned(_))); } } diff --git a/exercises/19_smart_pointers/cow1_test b/exercises/19_smart_pointers/cow1_test new file mode 100644 index 0000000000..32beb96395 Binary files /dev/null and b/exercises/19_smart_pointers/cow1_test differ diff --git a/exercises/19_smart_pointers/cow1_test.pdb b/exercises/19_smart_pointers/cow1_test.pdb new file mode 100644 index 0000000000..2e6634a28c Binary files /dev/null and b/exercises/19_smart_pointers/cow1_test.pdb differ diff --git a/exercises/19_smart_pointers/rc1.exe b/exercises/19_smart_pointers/rc1.exe new file mode 100644 index 0000000000..a5521de354 Binary files /dev/null and b/exercises/19_smart_pointers/rc1.exe differ diff --git a/exercises/19_smart_pointers/rc1.pdb b/exercises/19_smart_pointers/rc1.pdb new file mode 100644 index 0000000000..474ab5634c Binary files /dev/null and b/exercises/19_smart_pointers/rc1.pdb differ diff --git a/exercises/19_smart_pointers/rc1.rs b/exercises/19_smart_pointers/rc1.rs index ecd3438701..5c9ce8465e 100644 --- a/exercises/19_smart_pointers/rc1.rs +++ b/exercises/19_smart_pointers/rc1.rs @@ -60,17 +60,17 @@ mod tests { jupiter.details(); // TODO - let saturn = Planet::Saturn(Rc::new(Sun)); + let saturn = Planet::Saturn(Rc::clone(&sun)); println!("reference count = {}", Rc::strong_count(&sun)); // 7 references saturn.details(); // TODO - let uranus = Planet::Uranus(Rc::new(Sun)); + let uranus = Planet::Uranus(Rc::clone(&sun)); println!("reference count = {}", Rc::strong_count(&sun)); // 8 references uranus.details(); // TODO - let neptune = Planet::Neptune(Rc::new(Sun)); + let neptune = Planet::Neptune(Rc::clone(&sun)); println!("reference count = {}", Rc::strong_count(&sun)); // 9 references neptune.details(); @@ -92,12 +92,15 @@ mod tests { println!("reference count = {}", Rc::strong_count(&sun)); // 4 references // TODO + drop(earth); println!("reference count = {}", Rc::strong_count(&sun)); // 3 references // TODO + drop(venus); println!("reference count = {}", Rc::strong_count(&sun)); // 2 references // TODO + drop(mercury); println!("reference count = {}", Rc::strong_count(&sun)); // 1 reference assert_eq!(Rc::strong_count(&sun), 1); diff --git a/exercises/19_smart_pointers/rc1_test b/exercises/19_smart_pointers/rc1_test new file mode 100644 index 0000000000..14ad3d3ce0 Binary files /dev/null and b/exercises/19_smart_pointers/rc1_test differ diff --git a/exercises/19_smart_pointers/rc1_test.pdb b/exercises/19_smart_pointers/rc1_test.pdb new file mode 100644 index 0000000000..dd4e5a45a9 Binary files /dev/null and b/exercises/19_smart_pointers/rc1_test.pdb differ diff --git a/exercises/20_threads/threads1.exe b/exercises/20_threads/threads1.exe new file mode 100644 index 0000000000..6c5bd4f3fd Binary files /dev/null and b/exercises/20_threads/threads1.exe differ diff --git a/exercises/20_threads/threads1.pdb b/exercises/20_threads/threads1.pdb new file mode 100644 index 0000000000..f93f32b2a8 Binary files /dev/null and b/exercises/20_threads/threads1.pdb differ diff --git a/exercises/20_threads/threads1.rs b/exercises/20_threads/threads1.rs index dbc64b1644..84f094c8a3 100644 --- a/exercises/20_threads/threads1.rs +++ b/exercises/20_threads/threads1.rs @@ -24,6 +24,7 @@ fn main() { for handle in handles { // TODO: Collect the results of all threads into the `results` vector. // Use the `JoinHandle` struct which is returned by `thread::spawn`. + results.push(handle.join().unwrap()); } if results.len() != 10 { diff --git a/exercises/20_threads/threads2.exe b/exercises/20_threads/threads2.exe new file mode 100644 index 0000000000..803bbfb093 Binary files /dev/null and b/exercises/20_threads/threads2.exe differ diff --git a/exercises/20_threads/threads2.pdb b/exercises/20_threads/threads2.pdb new file mode 100644 index 0000000000..f3d0d0ea2a Binary files /dev/null and b/exercises/20_threads/threads2.pdb differ diff --git a/exercises/20_threads/threads2.rs b/exercises/20_threads/threads2.rs index 7020cb9cea..e599d2bfca 100644 --- a/exercises/20_threads/threads2.rs +++ b/exercises/20_threads/threads2.rs @@ -2,7 +2,11 @@ // work. But this time, the spawned threads need to be in charge of updating a // shared value: `JobStatus.jobs_done` -use std::{sync::Arc, thread, time::Duration}; +use std::{ + sync::{Arc, Mutex}, + thread, + time::Duration, +}; struct JobStatus { jobs_done: u32, @@ -10,7 +14,7 @@ struct JobStatus { fn main() { // TODO: `Arc` isn't enough if you want a **mutable** shared state. - let status = Arc::new(JobStatus { jobs_done: 0 }); + let status = Arc::new(Mutex::new(JobStatus { jobs_done: 0 })); let mut handles = Vec::new(); for _ in 0..10 { @@ -19,7 +23,7 @@ fn main() { thread::sleep(Duration::from_millis(250)); // TODO: You must take an action before you update a shared value. - status_shared.jobs_done += 1; + status_shared.lock().unwrap().jobs_done += 1; }); handles.push(handle); } @@ -30,5 +34,5 @@ fn main() { } // TODO: Print the value of `JobStatus.jobs_done`. - println!("Jobs done: {}", todo!()); + println!("Jobs done: {}", status.lock().unwrap().jobs_done); } diff --git a/exercises/20_threads/threads3.exe b/exercises/20_threads/threads3.exe new file mode 100644 index 0000000000..1d20617073 Binary files /dev/null and b/exercises/20_threads/threads3.exe differ diff --git a/exercises/20_threads/threads3.pdb b/exercises/20_threads/threads3.pdb new file mode 100644 index 0000000000..d268fd539a Binary files /dev/null and b/exercises/20_threads/threads3.pdb differ diff --git a/exercises/20_threads/threads3.rs b/exercises/20_threads/threads3.rs index 6d16bd9fec..f219d11f43 100644 --- a/exercises/20_threads/threads3.rs +++ b/exercises/20_threads/threads3.rs @@ -17,8 +17,12 @@ impl Queue { fn send_tx(q: Queue, tx: mpsc::Sender) { // TODO: We want to send `tx` to both threads. But currently, it is moved // into the first thread. How could you solve this problem? + let first_half = q.first_half; + let second_half = q.second_half; + let tx_clone = tx.clone(); + thread::spawn(move || { - for val in q.first_half { + for val in first_half { println!("Sending {val:?}"); tx.send(val).unwrap(); thread::sleep(Duration::from_millis(250)); @@ -26,9 +30,9 @@ fn send_tx(q: Queue, tx: mpsc::Sender) { }); thread::spawn(move || { - for val in q.second_half { + for val in second_half { println!("Sending {val:?}"); - tx.send(val).unwrap(); + tx_clone.send(val).unwrap(); thread::sleep(Duration::from_millis(250)); } }); diff --git a/exercises/21_macros/macros1.exe b/exercises/21_macros/macros1.exe new file mode 100644 index 0000000000..f738f21f47 Binary files /dev/null and b/exercises/21_macros/macros1.exe differ diff --git a/exercises/21_macros/macros1.pdb b/exercises/21_macros/macros1.pdb new file mode 100644 index 0000000000..f3a618ddd9 Binary files /dev/null and b/exercises/21_macros/macros1.pdb differ diff --git a/exercises/21_macros/macros1.rs b/exercises/21_macros/macros1.rs index fb3c3ff9b3..fb550f9d61 100644 --- a/exercises/21_macros/macros1.rs +++ b/exercises/21_macros/macros1.rs @@ -6,5 +6,5 @@ macro_rules! my_macro { fn main() { // TODO: Fix the macro call. - my_macro(); + my_macro!(); } diff --git a/exercises/21_macros/macros2.exe b/exercises/21_macros/macros2.exe new file mode 100644 index 0000000000..43b8321dc0 Binary files /dev/null and b/exercises/21_macros/macros2.exe differ diff --git a/exercises/21_macros/macros2.pdb b/exercises/21_macros/macros2.pdb new file mode 100644 index 0000000000..df2612988d Binary files /dev/null and b/exercises/21_macros/macros2.pdb differ diff --git a/exercises/21_macros/macros2.rs b/exercises/21_macros/macros2.rs index 2d9dec76ca..a56d137f36 100644 --- a/exercises/21_macros/macros2.rs +++ b/exercises/21_macros/macros2.rs @@ -1,10 +1,12 @@ -fn main() { - my_macro!(); -} - // TODO: Fix the compiler error by moving the whole definition of this macro. macro_rules! my_macro { () => { println!("Check out my macro!"); }; } + +fn main() { + my_macro!(); +} + + diff --git a/exercises/21_macros/macros3.exe b/exercises/21_macros/macros3.exe new file mode 100644 index 0000000000..c2598f6586 Binary files /dev/null and b/exercises/21_macros/macros3.exe differ diff --git a/exercises/21_macros/macros3.pdb b/exercises/21_macros/macros3.pdb new file mode 100644 index 0000000000..ab42a6273b Binary files /dev/null and b/exercises/21_macros/macros3.pdb differ diff --git a/exercises/21_macros/macros3.rs b/exercises/21_macros/macros3.rs index 95374948be..e1c874e480 100644 --- a/exercises/21_macros/macros3.rs +++ b/exercises/21_macros/macros3.rs @@ -1,11 +1,12 @@ // TODO: Fix the compiler error without taking the macro definition out of this // module. mod macros { - macro_rules! my_macro { + +} +macro_rules! my_macro { () => { println!("Check out my macro!"); }; - } } fn main() { diff --git a/exercises/21_macros/macros4.exe b/exercises/21_macros/macros4.exe new file mode 100644 index 0000000000..7cd365df22 Binary files /dev/null and b/exercises/21_macros/macros4.exe differ diff --git a/exercises/21_macros/macros4.pdb b/exercises/21_macros/macros4.pdb new file mode 100644 index 0000000000..d23ea183de Binary files /dev/null and b/exercises/21_macros/macros4.pdb differ diff --git a/exercises/21_macros/macros4.rs b/exercises/21_macros/macros4.rs index 9d77f6a5c8..7be6c5a90c 100644 --- a/exercises/21_macros/macros4.rs +++ b/exercises/21_macros/macros4.rs @@ -3,10 +3,10 @@ macro_rules! my_macro { () => { println!("Check out my macro!"); - } + }; ($val:expr) => { println!("Look at this other macro: {}", $val); - } + }; } fn main() { diff --git a/exercises/22_clippy/clippy1.exe b/exercises/22_clippy/clippy1.exe new file mode 100644 index 0000000000..95475fb57e Binary files /dev/null and b/exercises/22_clippy/clippy1.exe differ diff --git a/exercises/22_clippy/clippy1.pdb b/exercises/22_clippy/clippy1.pdb new file mode 100644 index 0000000000..10abf4d032 Binary files /dev/null and b/exercises/22_clippy/clippy1.pdb differ diff --git a/exercises/22_clippy/clippy1.rs b/exercises/22_clippy/clippy1.rs index 7165da4559..15ae5a0fa3 100644 --- a/exercises/22_clippy/clippy1.rs +++ b/exercises/22_clippy/clippy1.rs @@ -6,7 +6,7 @@ fn main() { // TODO: Fix the Clippy lint in this line. - let pi = 3.14; + let pi: f32 = std::f32::consts::PI; let radius: f32 = 5.0; let area = pi * radius.powi(2); diff --git a/exercises/22_clippy/clippy2.exe b/exercises/22_clippy/clippy2.exe new file mode 100644 index 0000000000..99a0b5d92c Binary files /dev/null and b/exercises/22_clippy/clippy2.exe differ diff --git a/exercises/22_clippy/clippy2.pdb b/exercises/22_clippy/clippy2.pdb new file mode 100644 index 0000000000..f901b0fb57 Binary files /dev/null and b/exercises/22_clippy/clippy2.pdb differ diff --git a/exercises/22_clippy/clippy2.rs b/exercises/22_clippy/clippy2.rs index 8cfe6f80a2..c0533ed8ff 100644 --- a/exercises/22_clippy/clippy2.rs +++ b/exercises/22_clippy/clippy2.rs @@ -2,7 +2,7 @@ fn main() { let mut res = 42; let option = Some(12); // TODO: Fix the Clippy lint. - for x in option { + if let Some(x) = option { res += x; } diff --git a/exercises/22_clippy/clippy3.exe b/exercises/22_clippy/clippy3.exe new file mode 100644 index 0000000000..589568681b Binary files /dev/null and b/exercises/22_clippy/clippy3.exe differ diff --git a/exercises/22_clippy/clippy3.pdb b/exercises/22_clippy/clippy3.pdb new file mode 100644 index 0000000000..9e1012954e Binary files /dev/null and b/exercises/22_clippy/clippy3.pdb differ diff --git a/exercises/22_clippy/clippy3.rs b/exercises/22_clippy/clippy3.rs index 7a3cb39006..bb9b2ac99b 100644 --- a/exercises/22_clippy/clippy3.rs +++ b/exercises/22_clippy/clippy3.rs @@ -7,23 +7,22 @@ fn main() { let my_option: Option<&str> = None; // Assume that you don't know the value of `my_option`. // In the case of `Some`, we want to print its value. - if my_option.is_none() { - println!("{}", my_option.unwrap()); + if let Some(val) = my_option { + println!("{}", val); } let my_arr = &[ - -1, -2, -3 + -1, -2, -3, -4, -5, -6 ]; println!("My array! Here it is: {my_arr:?}"); - let my_empty_vec = vec![1, 2, 3, 4, 5].resize(0, 5); + let my_empty_vec: Vec = vec![]; println!("This Vec is empty, see? {my_empty_vec:?}"); let mut value_a = 45; let mut value_b = 66; // Let's swap these two! - value_a = value_b; - value_b = value_a; + (value_a, value_b) = (value_b, value_a); println!("value a: {value_a}; value b: {value_b}"); } diff --git a/exercises/23_conversions/as_ref_mut.exe b/exercises/23_conversions/as_ref_mut.exe new file mode 100644 index 0000000000..d6b4f7af2f Binary files /dev/null and b/exercises/23_conversions/as_ref_mut.exe differ diff --git a/exercises/23_conversions/as_ref_mut.pdb b/exercises/23_conversions/as_ref_mut.pdb new file mode 100644 index 0000000000..455f3f5799 Binary files /dev/null and b/exercises/23_conversions/as_ref_mut.pdb differ diff --git a/exercises/23_conversions/as_ref_mut.rs b/exercises/23_conversions/as_ref_mut.rs index d7892dd490..e95a7a8e67 100644 --- a/exercises/23_conversions/as_ref_mut.rs +++ b/exercises/23_conversions/as_ref_mut.rs @@ -5,20 +5,22 @@ // Obtain the number of bytes (not characters) in the given argument // (`.len()` returns the number of bytes in a string). // TODO: Add the `AsRef` trait appropriately as a trait bound. -fn byte_counter(arg: T) -> usize { +fn byte_counter>(arg: T) -> usize { arg.as_ref().len() } // Obtain the number of characters (not bytes) in the given argument. // TODO: Add the `AsRef` trait appropriately as a trait bound. -fn char_counter(arg: T) -> usize { +fn char_counter>(arg: T) -> usize { arg.as_ref().chars().count() } // Squares a number using `as_mut()`. // TODO: Add the appropriate trait bound. -fn num_sq(arg: &mut T) { +fn num_sq>(arg: &mut T) { // TODO: Implement the function body. + let num = arg.as_mut(); + *num *= *num; } fn main() { diff --git a/exercises/23_conversions/from_into.exe b/exercises/23_conversions/from_into.exe new file mode 100644 index 0000000000..65b8d9a242 Binary files /dev/null and b/exercises/23_conversions/from_into.exe differ diff --git a/exercises/23_conversions/from_into.pdb b/exercises/23_conversions/from_into.pdb new file mode 100644 index 0000000000..e456113c0b Binary files /dev/null and b/exercises/23_conversions/from_into.pdb differ diff --git a/exercises/23_conversions/from_into.rs b/exercises/23_conversions/from_into.rs index bc2783a30f..cce1772222 100644 --- a/exercises/23_conversions/from_into.rs +++ b/exercises/23_conversions/from_into.rs @@ -34,7 +34,24 @@ impl Default for Person { // 5. Parse the second element from the split operation into a `u8` as the age. // 6. If parsing the age fails, return the default of `Person`. impl From<&str> for Person { - fn from(s: &str) -> Self {} + fn from(s: &str) -> Self { + let parts: Vec<&str> = s.split(',').collect(); + if parts.len() != 2 { + return Person::default(); + } + let name = parts[0]; + if name.is_empty() { + return Person::default(); + } + let age = match parts[1].parse::() { + Ok(age) => age, + Err(_) => return Person::default(), + }; + Person { + name: String::from(name), + age, + } + } } fn main() { diff --git a/exercises/23_conversions/from_str.exe b/exercises/23_conversions/from_str.exe new file mode 100644 index 0000000000..06b4d835ea Binary files /dev/null and b/exercises/23_conversions/from_str.exe differ diff --git a/exercises/23_conversions/from_str.pdb b/exercises/23_conversions/from_str.pdb new file mode 100644 index 0000000000..e689119f65 Binary files /dev/null and b/exercises/23_conversions/from_str.pdb differ diff --git a/exercises/23_conversions/from_str.rs b/exercises/23_conversions/from_str.rs index ec6d3fd129..47f85d45c5 100644 --- a/exercises/23_conversions/from_str.rs +++ b/exercises/23_conversions/from_str.rs @@ -41,7 +41,21 @@ enum ParsePersonError { impl FromStr for Person { type Err = ParsePersonError; - fn from_str(s: &str) -> Result {} + fn from_str(s: &str) -> Result { + let parts: Vec<&str> = s.split(',').collect(); + if parts.len() != 2 { + return Err(ParsePersonError::BadLen); + } + let name = parts[0]; + if name.is_empty() { + return Err(ParsePersonError::NoName); + } + let age = parts[1].parse::().map_err(ParsePersonError::ParseInt)?; + Ok(Person { + name: String::from(name), + age, + }) + } } fn main() { diff --git a/exercises/23_conversions/try_from_into.exe b/exercises/23_conversions/try_from_into.exe new file mode 100644 index 0000000000..ddcdb34982 Binary files /dev/null and b/exercises/23_conversions/try_from_into.exe differ diff --git a/exercises/23_conversions/try_from_into.pdb b/exercises/23_conversions/try_from_into.pdb new file mode 100644 index 0000000000..e13faed7c2 Binary files /dev/null and b/exercises/23_conversions/try_from_into.pdb differ diff --git a/exercises/23_conversions/try_from_into.rs b/exercises/23_conversions/try_from_into.rs index f3ae80a9e4..9e646076d9 100644 --- a/exercises/23_conversions/try_from_into.rs +++ b/exercises/23_conversions/try_from_into.rs @@ -28,14 +28,33 @@ enum IntoColorError { impl TryFrom<(i16, i16, i16)> for Color { type Error = IntoColorError; - fn try_from(tuple: (i16, i16, i16)) -> Result {} + fn try_from(tuple: (i16, i16, i16)) -> Result { + let (r, g, b) = tuple; + if r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 { + return Err(IntoColorError::IntConversion); + } + Ok(Color { + red: r as u8, + green: g as u8, + blue: b as u8, + }) + } } // TODO: Array implementation. impl TryFrom<[i16; 3]> for Color { type Error = IntoColorError; - fn try_from(arr: [i16; 3]) -> Result {} + fn try_from(arr: [i16; 3]) -> Result { + if arr[0] < 0 || arr[0] > 255 || arr[1] < 0 || arr[1] > 255 || arr[2] < 0 || arr[2] > 255 { + return Err(IntoColorError::IntConversion); + } + Ok(Color { + red: arr[0] as u8, + green: arr[1] as u8, + blue: arr[2] as u8, + }) + } } // TODO: Slice implementation. @@ -43,7 +62,25 @@ impl TryFrom<[i16; 3]> for Color { impl TryFrom<&[i16]> for Color { type Error = IntoColorError; - fn try_from(slice: &[i16]) -> Result {} + fn try_from(slice: &[i16]) -> Result { + if slice.len() != 3 { + return Err(IntoColorError::BadLen); + } + if slice[0] < 0 + || slice[0] > 255 + || slice[1] < 0 + || slice[1] > 255 + || slice[2] < 0 + || slice[2] > 255 + { + return Err(IntoColorError::IntConversion); + } + Ok(Color { + red: slice[0] as u8, + green: slice[1] as u8, + blue: slice[2] as u8, + }) + } } fn main() { diff --git a/exercises/23_conversions/using_as.rs b/exercises/23_conversions/using_as.rs index c131d1f32f..dff453b202 100644 --- a/exercises/23_conversions/using_as.rs +++ b/exercises/23_conversions/using_as.rs @@ -5,7 +5,7 @@ fn average(values: &[f64]) -> f64 { let total = values.iter().sum::(); // TODO: Make a conversion before dividing. - total / values.len() + total / values.len() as f64 } fn main() { diff --git a/exercises/quizzes/quiz1.exe b/exercises/quizzes/quiz1.exe new file mode 100644 index 0000000000..a32a8eccd2 Binary files /dev/null and b/exercises/quizzes/quiz1.exe differ diff --git a/exercises/quizzes/quiz1.pdb b/exercises/quizzes/quiz1.pdb new file mode 100644 index 0000000000..32adb7ed8f Binary files /dev/null and b/exercises/quizzes/quiz1.pdb differ diff --git a/exercises/quizzes/quiz1.rs b/exercises/quizzes/quiz1.rs index 04fb2aaf8d..42acfcb924 100644 --- a/exercises/quizzes/quiz1.rs +++ b/exercises/quizzes/quiz1.rs @@ -10,7 +10,13 @@ // TODO: Write a function that calculates the price of an order of apples given // the quantity bought. -// fn calculate_price_of_apples(???) -> ??? { ??? } +fn calculate_price_of_apples(quantity: u32) -> u32 { + if quantity > 40 { + quantity + } else { + quantity * 2 + } +} fn main() { // You can optionally experiment here. diff --git a/exercises/quizzes/quiz2.exe b/exercises/quizzes/quiz2.exe new file mode 100644 index 0000000000..5c1689d913 Binary files /dev/null and b/exercises/quizzes/quiz2.exe differ diff --git a/exercises/quizzes/quiz2.pdb b/exercises/quizzes/quiz2.pdb new file mode 100644 index 0000000000..d7787a9d2e Binary files /dev/null and b/exercises/quizzes/quiz2.pdb differ diff --git a/exercises/quizzes/quiz2.rs b/exercises/quizzes/quiz2.rs index 2cddba907e..a616b9ced6 100644 --- a/exercises/quizzes/quiz2.rs +++ b/exercises/quizzes/quiz2.rs @@ -27,7 +27,16 @@ mod my_module { use super::Command; // TODO: Complete the function as described above. - // pub fn transformer(input: ???) -> ??? { ??? } + pub fn transformer(input: Vec<(String, Command)>) -> Vec { + input + .into_iter() + .map(|(s, cmd)| match cmd { + Command::Uppercase => s.to_uppercase(), + Command::Trim => s.trim().to_string(), + Command::Append(n) => s + &"bar".repeat(n), + }) + .collect() + } } fn main() { @@ -37,8 +46,8 @@ fn main() { #[cfg(test)] mod tests { // TODO: What do we need to import to have `transformer` in scope? - // use ???; use super::Command; + use super::my_module::transformer; #[test] fn it_works() { diff --git a/exercises/quizzes/quiz3.exe b/exercises/quizzes/quiz3.exe new file mode 100644 index 0000000000..c23917cf2f Binary files /dev/null and b/exercises/quizzes/quiz3.exe differ diff --git a/exercises/quizzes/quiz3.pdb b/exercises/quizzes/quiz3.pdb new file mode 100644 index 0000000000..a9f747d5e1 Binary files /dev/null and b/exercises/quizzes/quiz3.pdb differ diff --git a/exercises/quizzes/quiz3.rs b/exercises/quizzes/quiz3.rs index c877c5f8e6..98d094d985 100644 --- a/exercises/quizzes/quiz3.rs +++ b/exercises/quizzes/quiz3.rs @@ -12,14 +12,14 @@ // block to support alphabetical report cards in addition to numerical ones. // TODO: Adjust the struct as described above. -struct ReportCard { - grade: f32, +struct ReportCard { + grade: G, student_name: String, student_age: u8, } // TODO: Adjust the impl block as described above. -impl ReportCard { +impl ReportCard { fn print(&self) -> String { format!( "{} ({}) - achieved a grade of {}", diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 0000000000..a1f1e488b8 --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "xtask" +version = "0.1.0" +edition.workspace = true + +[dependencies] +environment.path = "../environment" +course.path = "../course" +clap = { version = "4.5", features = ["derive"] } +anyhow = "1.0" +colored = "2.0" +indicatif = "0.17" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +walkdir = "2.3" +regex = "1.10" +tempfile = "3.8" diff --git a/xtask/src/eval.rs b/xtask/src/eval.rs new file mode 100644 index 0000000000..7bb1c74b8b --- /dev/null +++ b/xtask/src/eval.rs @@ -0,0 +1,554 @@ +use anyhow::{Context, Result}; +use clap::Args; +use colored::*; +use indicatif::{ProgressBar, ProgressStyle}; +use serde::{Deserialize, Serialize}; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; +use std::time::Instant; +use tempfile; + +#[derive(Args)] +pub struct EvalArgs { + /// 要评分的课程名称,不传则自动对所有已配置课程评分 + #[clap(long)] + course: Option, + + /// 练习目录路径,默认为当前目录 + #[clap(short, long, default_value = ".")] + path: PathBuf, + + /// 是否显示详细输出 + #[clap(short, long)] + verbose: bool, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ExerciseResult { + pub name: String, + pub result: bool, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Statistics { + pub total_exercations: usize, + pub total_succeeds: usize, + pub total_failures: usize, + pub total_time: u64, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct GradeResult { + pub exercises: Vec, + pub statistics: Statistics, +} + +impl EvalArgs { + pub fn eval(self) { + if let Err(e) = self.run_eval() { + eprintln!("{} {}", "评分失败:".red().bold(), e); + } + } + + /// 评测learning-lm-rs项目 + fn eval_learning_lm(&self, lm_path: &Path) -> Result<(Vec, usize, usize, usize)> { + println!("{}", "评测 learning-lm-rs 项目...".blue().bold()); + + let manifest_path = lm_path.join("Cargo.toml"); + if !manifest_path.exists() { + println!("{} {} {}", "警告:".yellow().bold(), "找不到 learning-lm-rs/Cargo.toml 文件:", manifest_path.display()); + return Ok((Vec::new(), 0, 0, 0)); + } + + println!("{} {}", "运行测试:".blue().bold(), "cargo test --release"); + let test_output = Command::new("cargo") + .arg("test") + .arg("--manifest-path") + .arg(&manifest_path) + .arg("--release") + .current_dir(lm_path) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .context("运行 learning-lm-rs 测试失败")?; + + let success = test_output.status.success(); + + if self.verbose || !success { + println!("{}", String::from_utf8_lossy(&test_output.stdout)); + println!("{}", String::from_utf8_lossy(&test_output.stderr)); + } + + // learning-lm-rs 只包含 model.rs 和 operators.rs + let lm_exercises = ["model.rs", "operators.rs"]; + let total_exercations = lm_exercises.len(); + let mut exercise_results = Vec::new(); + let mut total_succeeds = 0; + let mut total_failures = 0; + + for &exercise_name in lm_exercises.iter() { + exercise_results.push(ExerciseResult { + name: exercise_name.to_string(), + result: success, + }); + if success { + total_succeeds += 1; + println!("{} {}", "✓".green().bold(), exercise_name); + } else { + total_failures += 1; + println!("{} {}", "✗".red().bold(), exercise_name); + } + } + println!("评测完成!"); + + Ok((exercise_results, total_succeeds, total_failures, total_exercations)) + } + + /// 评测learning-cxx项目 + fn eval_learning_cxx(&self, course_path: &Path) -> Result<(Vec, usize, usize, usize)> { + println!("{}", "评测 learning-cxx 项目...".blue().bold()); + + // 运行xmake run summary命令获取评测结果 + let output = Command::new("xmake") + .arg("run") + .arg("summary") + .current_dir(course_path) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .context("运行 xmake run summary 失败")?; + + let output_str = String::from_utf8_lossy(&output.stdout); + let error_str = String::from_utf8_lossy(&output.stderr); + + if self.verbose { + println!("{}", output_str); + println!("{}", error_str); + } + + let mut exercise_results = Vec::new(); + let mut total_succeeds = 0; + let mut total_failures = 0; + let mut total_exercations = 0; + + // 移除ANSI转义序列的正则表达式 + let re = regex::Regex::new(r"\x1b\[[0-9;]*[a-zA-Z]").unwrap(); + + // 解析输出结果 + for line in output_str.lines() { + // 跳过错误信息行 + if line.contains("error:") { + continue; + } + + if line.contains("exercise") && (line.contains("passed") || line.contains("failed")) { + total_exercations += 1; + let parts: Vec<&str> = line.split_whitespace().collect(); + if let Some(exercise_name) = parts.first() { + // 移除ANSI转义序列 + let clean_name = re.replace_all(exercise_name, "").to_string(); + let result = line.contains("passed"); + if result { + total_succeeds += 1; + println!("{} {}", "✓".green().bold(), clean_name); + } else { + total_failures += 1; + println!("{} {}", "✗".red().bold(), clean_name); + } + exercise_results.push(ExerciseResult { name: clean_name, result }); + } + } + } + + // 如果没有从stdout找到结果,尝试从stderr中解析 + if total_exercations == 0 { + for line in error_str.lines() { + // 跳过错误信息行 + if line.contains("error:") { + continue; + } + + if line.contains("exercise") && (line.contains("passed") || line.contains("failed")) { + total_exercations += 1; + let parts: Vec<&str> = line.split_whitespace().collect(); + if let Some(exercise_name) = parts.first() { + // 移除ANSI转义序列并处理exercise前缀 + let clean_name = re.replace_all(exercise_name, "").to_string(); + let name = clean_name.trim_start_matches("exercise").to_string(); + let result = line.contains("passed"); + if result { + total_succeeds += 1; + println!("{} exercise{}", "✓".green().bold(), name); + } else { + total_failures += 1; + println!("{} exercise{}", "✗".red().bold(), name); + } + exercise_results.push(ExerciseResult { name: format!("exercise{}", name), result }); + } + } + } + } + + println!("评测完成!"); + Ok((exercise_results, total_succeeds, total_failures, total_exercations)) + } + + /// 评测rustlings或其他项目 + fn eval_rustlings(&self, course_path: &Path) -> Result<(Vec, usize, usize, usize)> { + println!("{}", "评测 rustlings 项目...".blue().bold()); + + // 使用 rustc 编译和运行测试来评测 + println!("{}", "使用 rustc 编译和运行测试来评测...".blue().bold()); + + // 处理 Rustlings 或其他非 learning-lm-rs 项目 + let exercise_files = find_exercise_files(course_path, &None)?; + let total_exercations = exercise_files.len(); + println!("{} {} {}", "找到".blue().bold(), total_exercations, "个练习文件".blue().bold()); + + if total_exercations == 0 { + println!("{}", "未找到练习文件,评测结束。".yellow()); + return Ok((Vec::new(), 0, 0, 0)); + } + + let bar = ProgressBar::new(total_exercations as u64); + bar.set_style( + ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})") + .unwrap() + .progress_chars("##-"), + ); + + let mut exercise_results = Vec::new(); + let mut total_succeeds = 0; + let mut total_failures = 0; + + for exercise_path in exercise_files.iter() { + bar.inc(1); + let (name, result, _time) = grade_exercise(exercise_path, self.verbose)?; + if result { + total_succeeds += 1; + } else { + total_failures += 1; + } + exercise_results.push(ExerciseResult { name, result }); + } + bar.finish_with_message("评测完成!"); + + Ok((exercise_results, total_succeeds, total_failures, total_exercations)) + } + + fn run_eval(&self) -> Result<()> { + println!("{}", "开始评测练习...".blue().bold()); + let start_time = Instant::now(); + + // 获取当前工作目录 + let current_dir = std::env::current_dir().context("无法获取当前工作目录")?; + + // 确定exercises目录 + let absolute_path = current_dir.join(&self.path); + let exercises_dir = if absolute_path.ends_with("exercises") { + absolute_path.clone() + } else { + absolute_path.join("exercises") + }; + + if !exercises_dir.exists() { + println!("{} {}", "警告:".yellow().bold(), "找不到exercises目录"); + return Ok(()); + } + + let mut exercise_results = Vec::new(); + let mut total_succeeds = 0; + let mut total_failures = 0; + let mut total_exercations = 0; + + // 如果指定了course参数,只评测指定的课程 + if let Some(course) = &self.course { + let course_path = exercises_dir.join(course); + if !course_path.exists() { + println!("{} {}", "警告:".yellow().bold(), format!("找不到课程目录: {}", course_path.display())); + return Ok(()); + } + + println!("{} {}", "评测指定课程:".blue().bold(), course); + let (results, succeeds, failures, exercations) = match course.as_str() { + "learning-lm-rs" => self.eval_learning_lm(&course_path)?, + "learning-cxx" => self.eval_learning_cxx(&course_path)?, + _ => self.eval_rustlings(&course_path)? + }; + + exercise_results.extend(results); + total_succeeds += succeeds; + total_failures += failures; + total_exercations += exercations; + } else { + // 自动评测所有课程 + println!("{}", "自动评测所有课程...".blue().bold()); + + // 获取exercises目录下的所有子目录 + let entries = fs::read_dir(&exercises_dir) + .context(format!("无法读取目录: {}", exercises_dir.display()))?; + + for entry in entries { + let entry = entry.context("读取目录项失败")?; + let path = entry.path(); + + if path.is_dir() { + let course_name = path.file_name() + .and_then(|name| name.to_str()) + .unwrap_or("未知课程"); + + println!("{} {}", "\n评测课程:".blue().bold(), course_name); + + let (results, succeeds, failures, exercations) = match course_name { + "learning-lm-rs" => self.eval_learning_lm(&path)?, + "learning-cxx" => self.eval_learning_cxx(&path)?, + _ => self.eval_rustlings(&path)? + }; + + exercise_results.extend(results); + total_succeeds += succeeds; + total_failures += failures; + total_exercations += exercations; + } + } + } + + let total_time = start_time.elapsed().as_secs(); + + // 打印统计信息 + println!("{}", "评测结果统计".green().bold()); + println!("{}: {}", "总练习数".blue(), total_exercations); + println!("{}: {}", "通过数量".green(), total_succeeds); + println!("{}: {}", "失败数量".red(), total_failures); + println!("{}: {}秒", "总耗时".blue(), total_time); + + let pass_rate = if total_exercations > 0 { + (total_succeeds as f32 / total_exercations as f32) * 100.0 + } else { + 0.0 + }; + println!("{}: {:.2}%", "通过率".green(), pass_rate); + + if total_failures > 0 { + println!(""); + println!("{}", "失败的练习:".red().bold()); + for exercise in exercise_results.iter() { + if !exercise.result { + println!(" {}", exercise.name.red()); + } + } + } + + let result = GradeResult { + exercises: exercise_results, + statistics: Statistics { + total_exercations, + total_succeeds, + total_failures, + total_time, + }, + }; + + // 使用固定的结果文件名 + let result_filename = "eval_result.json"; + let json_result = serde_json::to_string_pretty(&result)?; + fs::write(&result_filename, json_result)?; + println!(""); + println!("{} {}", "评测结果已保存到".blue(), result_filename.blue()); + + Ok(()) + } +} + + + +/// 查找指定目录下的所有练习文件 +fn find_exercise_files(course_path: &Path, _course: &Option) -> Result> { + let mut exercise_files = Vec::new(); + + if !course_path.exists() { + println!("{} {}", "警告:".yellow().bold(), format!("找不到课程目录: {}", course_path.display())); + return Ok(Vec::new()); + } + + // 对于learning-lm-rs项目,只返回model.rs和operators.rs + if course_path.file_name().map_or(false, |name| name == "learning-lm-rs") { + let src_path = course_path.join("src"); + if src_path.exists() { + println!("{} {}", "找到learning-lm-rs项目:".blue().bold(), src_path.display()); + let model_path = src_path.join("model.rs"); + let operators_path = src_path.join("operators.rs"); + + if model_path.exists() { + println!("{} {}", "找到练习文件:".blue(), model_path.display()); + exercise_files.push(model_path); + } else { + println!("{} {}", "警告:".yellow().bold(), "找不到model.rs文件"); + } + + if operators_path.exists() { + println!("{} {}", "找到练习文件:".blue(), operators_path.display()); + exercise_files.push(operators_path); + } else { + println!("{} {}", "警告:".yellow().bold(), "找不到operators.rs文件"); + } + + return Ok(exercise_files); + } + } + + // 对于rustlings项目,只查找exercises目录下的文件 + if course_path.file_name().map_or(false, |name| name == "rustlings") { + let exercises_path = course_path.join("exercises"); + if !exercises_path.exists() { + println!("{} {}", "警告:".yellow().bold(), "找不到rustlings的exercises目录"); + return Ok(Vec::new()); + } + + for entry in walkdir::WalkDir::new(&exercises_path) + .into_iter() + .filter_map(|e| e.ok()) + { + let path = entry.path(); + if path.is_file() && path.extension().map_or(false, |ext| ext == "rs") { + let file_name = path.file_name().unwrap().to_string_lossy(); + if !file_name.starts_with("test_") && !file_name.starts_with("helper_") { + exercise_files.push(path.to_path_buf()); + } + } + } + } else { + // 对于其他项目,遍历目录查找练习文件 + for entry in walkdir::WalkDir::new(course_path) + .into_iter() + .filter_map(|e| e.ok()) + { + let path = entry.path(); + if path.components().any(|c| c.as_os_str() == "target") { + continue; + } + if path.is_file() && path.extension().map_or(false, |ext| ext == "rs") { + let file_name = path.file_name().unwrap().to_string_lossy(); + if !file_name.starts_with("test_") && !file_name.starts_with("helper_") { + exercise_files.push(path.to_path_buf()); + } + } + } + } + + Ok(exercise_files) +} + +/// 评测单个 Rustlings 练习文件 (不再处理 learning-lm-rs) +fn grade_exercise(exercise_path: &Path, verbose: bool) -> Result<(String, bool, u64)> { + let start = Instant::now(); + let exercise_name = exercise_path + .file_name() + .context("无法获取文件名")? + .to_string_lossy() + .to_string(); + + println!("{} {}", "评测练习:".blue().bold(), exercise_name); + + // 检查是否是 clippy 练习 + let is_clippy_exercise = exercise_path.to_string_lossy().contains("clippy"); + + // 如果是 clippy 练习,使用 cargo clippy 命令检查 + if is_clippy_exercise { + // 创建一个临时目录来存放 Cargo.toml 和源文件 + let temp_dir = tempfile::tempdir().context("创建临时目录失败")?; + let temp_dir_path = temp_dir.path(); + + // 创建 Cargo.toml 文件 + let cargo_toml_content = r#"[package] +name = "clippy_check" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "clippy_check" +path = "src/main.rs" +"#; + let cargo_toml_path = temp_dir_path.join("Cargo.toml"); + fs::write(&cargo_toml_path, cargo_toml_content).context("写入 Cargo.toml 失败")?; + + // 创建 src 目录 + let src_dir = temp_dir_path.join("src"); + fs::create_dir(&src_dir).context("创建 src 目录失败")?; + + // 复制练习文件到 src/main.rs + let exercise_content = fs::read_to_string(exercise_path).context("读取练习文件失败")?; + let main_rs_path = src_dir.join("main.rs"); + fs::write(&main_rs_path, exercise_content).context("写入 main.rs 失败")?; + + // 运行 cargo clippy + let clippy_output = Command::new("cargo") + .arg("clippy") + .arg("--manifest-path") + .arg(&cargo_toml_path) + .arg("--") + .arg("-D") + .arg("warnings") + .current_dir(temp_dir_path) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .context(format!("运行 cargo clippy 检查 {} 失败", exercise_name))?; + + let clippy_success = clippy_output.status.success(); + + if !clippy_success { + if verbose { + println!("{}", String::from_utf8_lossy(&clippy_output.stdout)); + println!("{}", String::from_utf8_lossy(&clippy_output.stderr)); + } + println!("{} {}", "✗".red().bold(), exercise_name); + return Ok((exercise_name, false, start.elapsed().as_secs())); + } + } + + // 对于rustlings练习,直接使用rustc编译和运行测试 + let test_output = Command::new("rustc") + .arg(exercise_path) + .arg("--test") + .arg("-o") + .arg(format!("target/debug/{}", exercise_name)) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .context(format!("编译练习 {} 失败", exercise_name))?; + + let success = test_output.status.success(); + + if !success { + if verbose { + println!("{}", String::from_utf8_lossy(&test_output.stdout)); + println!("{}", String::from_utf8_lossy(&test_output.stderr)); + } + println!("{} {}", "✗".red().bold(), exercise_name); + return Ok((exercise_name, false, start.elapsed().as_secs())); + } + + // 编译成功,运行测试 + let test_output = Command::new(format!("target/debug/{}", exercise_name)) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .context(format!("运行练习 {} 失败", exercise_name))?; + + let success = test_output.status.success(); + + if verbose || !success { + println!("{}", String::from_utf8_lossy(&test_output.stdout)); + println!("{}", String::from_utf8_lossy(&test_output.stderr)); + } + + if success { + println!("{} {}", "✓".green().bold(), exercise_name); + } else { + println!("{} {}", "✗".red().bold(), exercise_name); + } + + Ok((exercise_name, success, start.elapsed().as_secs())) +} diff --git a/xtask/src/learn.rs b/xtask/src/learn.rs new file mode 100644 index 0000000000..cd468ca133 --- /dev/null +++ b/xtask/src/learn.rs @@ -0,0 +1,65 @@ +use anyhow::{Context, Result}; +use clap::Args; +use colored::*; +use std::fs; +use std::path::Path; +use std::process::Command; + +#[derive(Args)] +pub struct LearnArgs { + /// 课程名称 + course: String, + /// 传入 fork 仓库地址,以 git submodule 方式配置 + #[clap(long)] + submodule: Option, +} + +impl LearnArgs { + pub fn learn(self) { + if let Err(e) = self.run_learn() { + eprintln!("{} {}", "配置课程失败:".red().bold(), e); + } + } + + fn run_learn(&self) -> Result<()> { + println!("{} {}", "开始配置课程:".blue().bold(), self.course); + + // 确保exercises目录存在 + let exercises_dir = Path::new("exercises"); + if !exercises_dir.exists() { + fs::create_dir_all(exercises_dir) + .context("创建exercises目录失败")?; + } + + // 如果提供了子模块地址,则克隆仓库 + if let Some(repo_url) = &self.submodule { + println!("{} {}", "克隆仓库:".blue().bold(), repo_url); + + // 检查是否已存在同名子模块 + let course_dir = exercises_dir.join(&self.course); + if course_dir.exists() { + println!("{} {}", "警告:".yellow().bold(), format!("目录 {} 已存在,将被覆盖", course_dir.display())); + fs::remove_dir_all(&course_dir) + .context(format!("删除已存在的目录 {} 失败", course_dir.display()))?; + } + + // 使用git命令添加子模块 + let status = Command::new("git") + .args(["submodule", "add", "-f", repo_url, &format!("exercises/{}", self.course)]) + .status() + .context("执行git submodule add命令失败")?; + + if !status.success() { + return Err(anyhow::anyhow!("git submodule add命令执行失败")); + } + + println!("{} {}", "成功配置课程:".green().bold(), self.course); + println!("{} {}", "练习已克隆到:".green(), format!("exercises/{}", self.course)); + println!("{}", "你现在可以使用 'cargo xtask eval' 命令来评测练习".blue()); + } else { + println!("{}", "未提供仓库地址,请使用 --submodule 参数指定仓库地址".yellow()); + } + + Ok(()) + } +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 0000000000..38b9bebc10 --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,38 @@ +mod eval; +mod learn; +mod setup; + +use clap::Parser; +use eval::EvalArgs; +use learn::LearnArgs; +use setup::SetupArgs; + +#[macro_use] +extern crate clap; + +fn main() { + use Commands::*; + match Cli::parse().command { + Setup(args) => args.setup(), + Learn(args) => args.learn(), + Eval(args) => args.eval(), + } +} + +#[derive(Parser)] +#[clap(name = "learning-in-camp")] +#[clap(version, about, long_about = None)] +struct Cli { + #[clap(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + /// 安装指定开发环境 + Setup(SetupArgs), + /// 配置指定课程仓库 + Learn(LearnArgs), + /// 评分 + Eval(EvalArgs), +} diff --git a/xtask/src/setup.rs b/xtask/src/setup.rs new file mode 100644 index 0000000000..041a8301ce --- /dev/null +++ b/xtask/src/setup.rs @@ -0,0 +1,9 @@ +#[derive(Args)] +pub struct SetupArgs { + /// 配置的环境名称 + env: String, +} + +impl SetupArgs { + pub fn setup(self) {} +}