A few simple problems
You can create a "problems" Rust project in your repository to try your solutions to those simple problems.
Lifetimes
The trim
method on str
(and thus on String
thanks to Deref
) removes the blanks at the beginning and at the end of a string. Its signature is:
fn trim(&self) -> &str;
which is, thanks to lifetimes elision, a shortcut for
fn trim<'a>(&'a self) -> &'a str;
Who is the owner?
The following code fails to compile:
fn ret_string() -> String { String::from(" A String object ") } fn main() { let s = ret_string().trim(); assert_eq!(s, "A String object"); }
Why? Ask yourself: what is the lifetime of s
? Who is the owner of the underlying string with spaces (every object has an owner)?
❎ Fix the code so that it compiles (and the s
variable represents the trimmed string). Note that you can reuse the same variable name.
Select between alternatives
❎ Add the most appropriate lifetimes to the following function:
fn choose_str(s1: &str, s2: &str, select_s1: bool) -> &str {
if select_s1 { s1 } else { s2 }
}
At call time, s1
and s2
may have different lifetimes and we don't want any constraint between the lifetimes of those two strings.
Write a OOR (owned or ref) type
For this problem, do not look at the standard Cow
type.
We want to create a OOR
type which can store either a String
or a &str
to avoid copying a string which already exists in the environment.
❎ Write a OOR
enum with two alternatives: Owned
which stored a String
and Borrowed
which stores a &str
.
It will require using a generic parameter. What does it represent?
❎ Implement the Deref
trait for the OOR
structure so that it dereferences into an a &str
. What is the lifetime of the resulting &str
(note that you have no choice there)? Why is that always appropriate?
❎ Check that you can now call &str
methods directly on an arbitrary OOR
object by writing some tests.
❎ Write a DerefMut
trait for the OOR
structure. If you have not stored a String
, you will have to mutate and store a String
before you can hand out a &mut str
because you can't transform your inner &str
into &mut str
.
❎ Check that you can run the following test:
// Check Deref for both variants of OOR
let s1 = OOR::Owned(String::from(" Hello, world. "));
assert_eq!(s1.trim(), "Hello, world.");
let mut s2 = OOR::Borrowed(" Hello, world! ");
assert_eq!(s2.trim(), "Hello, world!");
// Check choose
let s = choose_str(&s1, &s2, true);
assert_eq!(s.trim(), "Hello, world.");
let s = choose_str(&s1, &s2, false);
assert_eq!(s.trim(), "Hello, world!");
// Check DerefMut, a borrowed string should become owned
assert!(matches!(s1, OOR::Owned(_)));
assert!(matches!(s2, OOR::Borrowed(_)));
unsafe {
for c in s2.as_bytes_mut() {
if *c == b'!' {
*c = b'?';
}
}
}
assert!(matches!(s2, OOR::Owned(_)));
assert_eq!(s2.trim(), "Hello, world?");