summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--exercises/19_smart_pointers/cow1.rs78
-rw-r--r--rustlings-macros/info.toml6
-rw-r--r--solutions/19_smart_pointers/cow1.rs69
3 files changed, 106 insertions, 47 deletions
diff --git a/exercises/19_smart_pointers/cow1.rs b/exercises/19_smart_pointers/cow1.rs
index 754c0ba..5ecf848 100644
--- a/exercises/19_smart_pointers/cow1.rs
+++ b/exercises/19_smart_pointers/cow1.rs
@@ -1,24 +1,18 @@
-// This exercise explores the Cow, or Clone-On-Write type. Cow is a
-// clone-on-write smart pointer. It can enclose and provide immutable access to
-// borrowed data, and clone the data lazily when mutation or ownership is
-// required. The type is designed to work with general borrowed data via the
-// Borrow trait.
-//
-// This exercise is meant to show you what to expect when passing data to Cow.
-// Fix the unit tests by checking for Cow::Owned(_) and Cow::Borrowed(_) at the
-// TODO markers.
+// This exercise explores the `Cow` (Clone-On-Write) smart pointer. It can
+// enclose and provide immutable access to borrowed data and clone the data
+// lazily when mutation or ownership is required. The type is designed to work
+// with general borrowed data via the `Borrow` trait.
use std::borrow::Cow;
-fn abs_all<'a, 'b>(input: &'a mut Cow<'b, [i32]>) -> &'a mut Cow<'b, [i32]> {
- for i in 0..input.len() {
- let v = input[i];
- if v < 0 {
+fn abs_all(input: &mut Cow<[i32]>) {
+ for ind in 0..input.len() {
+ let value = input[ind];
+ if value < 0 {
// Clones into a vector if not already owned.
- input.to_mut()[i] = -v;
+ input.to_mut()[ind] = -value;
}
}
- input
}
fn main() {
@@ -30,47 +24,45 @@ mod tests {
use super::*;
#[test]
- fn reference_mutation() -> Result<(), &'static str> {
+ fn reference_mutation() {
// Clone occurs because `input` needs to be mutated.
- let slice = [-1, 0, 1];
- let mut input = Cow::from(&slice[..]);
- match abs_all(&mut input) {
- Cow::Owned(_) => Ok(()),
- _ => Err("Expected owned value"),
- }
+ let vec = vec![-1, 0, 1];
+ let mut input = Cow::from(&vec);
+ abs_all(&mut input);
+ assert!(matches!(input, Cow::Owned(_)));
}
#[test]
- fn reference_no_mutation() -> Result<(), &'static str> {
+ fn reference_no_mutation() {
// No clone occurs because `input` doesn't need to be mutated.
- let slice = [0, 1, 2];
- let mut input = Cow::from(&slice[..]);
- match abs_all(&mut input) {
- // TODO
- }
+ let vec = vec![0, 1, 2];
+ let mut input = Cow::from(&vec);
+ abs_all(&mut input);
+ // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`.
+ assert!(matches!(input, todo!()));
}
#[test]
- fn owned_no_mutation() -> Result<(), &'static str> {
- // We can also pass `slice` without `&` so Cow owns it directly. In this
- // case no mutation occurs and thus also no clone, but the result is
+ fn owned_no_mutation() {
+ // We can also pass `vec` without `&` so `Cow` owns it directly. In this
+ // case, no mutation occurs and thus also no clone. But the result is
// still owned because it was never borrowed or mutated.
- let slice = vec![0, 1, 2];
- let mut input = Cow::from(slice);
- match abs_all(&mut input) {
- // TODO
- }
+ let vec = vec![0, 1, 2];
+ let mut input = Cow::from(vec);
+ abs_all(&mut input);
+ // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`.
+ assert!(matches!(input, todo!()));
}
#[test]
- fn owned_mutation() -> Result<(), &'static str> {
+ fn owned_mutation() {
// Of course this is also the case if a mutation does occur. In this
- // case the call to `to_mut()` in the abs_all() function returns a
+ // case, the call to `to_mut()` in the `abs_all` function returns a
// reference to the same data as before.
- let slice = vec![-1, 0, 1];
- let mut input = Cow::from(slice);
- match abs_all(&mut input) {
- // TODO
- }
+ let vec = vec![-1, 0, 1];
+ let mut input = Cow::from(vec);
+ abs_all(&mut input);
+ // TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`.
+ assert!(matches!(input, todo!()));
}
}
diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml
index 23b6181..cacdad9 100644
--- a/rustlings-macros/info.toml
+++ b/rustlings-macros/info.toml
@@ -1020,11 +1020,11 @@ https://doc.rust-lang.org/stable/book/ch16-00-concurrency.html"""
name = "cow1"
dir = "19_smart_pointers"
hint = """
-If `Cow` already owns the data it doesn't need to clone it when `to_mut()` is
+If `Cow` already owns the data, it doesn't need to clone it when `to_mut()` is
called.
-Check out https://doc.rust-lang.org/std/borrow/enum.Cow.html for documentation
-on the `Cow` type."""
+Check out the documentation of the `Cow` type:
+https://doc.rust-lang.org/std/borrow/enum.Cow.html"""
# THREADS
diff --git a/solutions/19_smart_pointers/cow1.rs b/solutions/19_smart_pointers/cow1.rs
index 4e18198..0a21a91 100644
--- a/solutions/19_smart_pointers/cow1.rs
+++ b/solutions/19_smart_pointers/cow1.rs
@@ -1 +1,68 @@
-// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
+// This exercise explores the `Cow` (Clone-On-Write) smart pointer. It can
+// enclose and provide immutable access to borrowed data and clone the data
+// lazily when mutation or ownership is required. The type is designed to work
+// with general borrowed data via the `Borrow` trait.
+
+use std::borrow::Cow;
+
+fn abs_all(input: &mut Cow<[i32]>) {
+ for ind in 0..input.len() {
+ let value = input[ind];
+ if value < 0 {
+ // Clones into a vector if not already owned.
+ input.to_mut()[ind] = -value;
+ }
+ }
+}
+
+fn main() {
+ // You can optionally experiment here.
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn reference_mutation() {
+ // Clone occurs because `input` needs to be mutated.
+ let vec = vec![-1, 0, 1];
+ let mut input = Cow::from(&vec);
+ abs_all(&mut input);
+ assert!(matches!(input, Cow::Owned(_)));
+ }
+
+ #[test]
+ fn reference_no_mutation() {
+ // No clone occurs because `input` doesn't need to be mutated.
+ let vec = vec![0, 1, 2];
+ let mut input = Cow::from(&vec);
+ abs_all(&mut input);
+ assert!(matches!(input, Cow::Borrowed(_)));
+ // ^^^^^^^^^^^^^^^^
+ }
+
+ #[test]
+ fn owned_no_mutation() {
+ // We can also pass `vec` without `&` so `Cow` owns it directly. In this
+ // case, no mutation occurs and thus also no clone. But the result is
+ // still owned because it was never borrowed or mutated.
+ let vec = vec![0, 1, 2];
+ let mut input = Cow::from(vec);
+ abs_all(&mut input);
+ assert!(matches!(input, Cow::Owned(_)));
+ // ^^^^^^^^^^^^^
+ }
+
+ #[test]
+ fn owned_mutation() {
+ // Of course this is also the case if a mutation does occur. In this
+ // case, the call to `to_mut()` in the `abs_all` function returns a
+ // reference to the same data as before.
+ let vec = vec![-1, 0, 1];
+ let mut input = Cow::from(vec);
+ abs_all(&mut input);
+ assert!(matches!(input, Cow::Owned(_)));
+ // ^^^^^^^^^^^^^
+ }
+}