fixing ownership issues done, may have to come back

This commit is contained in:
Rowan Torbitzky-Lane 2025-03-20 20:04:40 -05:00
parent 84a954a0ca
commit aa3e08fcfb
3 changed files with 126 additions and 0 deletions

7
ch4/fixing_ownership_issues/Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "fixing_ownership_issues"
version = "0.1.0"

View File

@ -0,0 +1,6 @@
[package]
name = "fixing_ownership_issues"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@ -0,0 +1,113 @@
// This section covers some common ownership errors.
// I'll probably have to come back to this section. I'm not enjoying
// this part of Rust so learning this is not my favorite.
use std::rc::Rc;
fn main() {
// ------------------------------------------------------------------------
// fixing an unsafe program: not enough permissions
let name = vec![String::from("Ferris!")];
let first = &name[0];
stringify_name_with_title(&name);
println!("{}", first);
// ------------------------------------------------------------------------
// fixing an unsafe program: copying vs. moving out of a collection
let v: Vec<i32> = vec![0, 1, 2];
let n_ref: &i32 = &v[0];
let n: i32 = *n_ref;
// If a value does not own head data, then it can be copied without a move
// Unlike what's happening below
// i32 doesn't own head data, so it can be copied without a move
// String does own heap data, so it can't be copied without a move
// &String doesn't own heap data, so it can be copied without a move
// Solution 1: Avoid taking ownership with immutable reference
let vs: Vec<String> = vec![String::from("Hello world")];
let s_ref: &String = &vs[0];
// let s: String = *s_ref;
println!("{s_ref}");
// Solution 2: Clone the data if want ownership
// Solution 3: Use Vec::remove to move string out of the vector
// ------------------------------------------------------------------------
// fixing an safe program: mutating different tuple fields
let mut name = (String::from("Ferris"), String::from("Rustacean"));
let first = &name.0;
name.1.push_str(", Esq.");
println!("{first} {}", name.1);
}
// fixing an unsafe program: returing a reference to the stack
// fn return_a_string() -> &String {
// let s = String::from("Hello World");
// &s
// fails because this function will get allocated but s is owned by this function.
// }
fn return_a_string_diff_owner() -> String {
let s = String::from("Hello world");
s
}
// static means it lives forever
fn return_a_string_static() -> &'static str {
"Hello world"
}
// rc is a reference-counted pointer. More in ch14
// only clones a pointer to s and not the data itself
fn return_a_string_rc() -> Rc<String> {
let s = Rc::new(String::from("Hello world"));
Rc::clone(&s)
}
// caller provides a slot with a mutable reference
fn return_a_string_slot(output: &mut String) {
output.replace_range(.., "Hello world");
}
// fixing an unsafe program: not enough permissions
// Replace "&Vec<String>" with "$mut Vec<String>". THIS IS NOT A GOOD SOLUTION!
// Functions shouldn't mutate their inputs if the caller would not expect it.
// Basically just don't use mut in functions. Make a copy of the variable instead
// if mutating it.
fn stringify_name_with_title(name: &Vec<String>) -> String {
let mut name_clone = name.clone();
name_clone.push(String::from("Esq."));
let full = name_clone.join(" ");
full
}
fn stringify_name_with_title_final(name: &Vec<String>) -> String {
let mut full = name.join(" ");
full.push_str(" Esq.");
full
}
// fixing an unsafe program: aliasing and mutating a data structure
// This function fails
// fn add_big_strings(dst: &mut Vec<String>, src: &[String]) {
// let largest: &String = dst.iter().max_by_key(|s| s.len()).unwrap();
// for s in src {
// if s.len() > largest.len() {
// dst.push(s.clone());
// }
// }
// }
// The fix for above since we only need the length
// Shortens the lifetime of borrows on dst to not overlap with
// mutation to dst.
fn add_big_strings(dst: &mut Vec<String>, src: &[String]) {
let largest_len: usize = dst.iter().max_by_key(|s| s.len()).unwrap().len();
for s in src {
if s.len() > largest_len {
dst.push(s.clone());
}
}
}