Compare commits
3 Commits
2a696fdfa9
...
1008a76306
Author | SHA1 | Date | |
---|---|---|---|
1008a76306 | |||
aa3e08fcfb | |||
84a954a0ca |
7
ch4/fixing_ownership_issues/Cargo.lock
generated
Normal file
7
ch4/fixing_ownership_issues/Cargo.lock
generated
Normal 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"
|
6
ch4/fixing_ownership_issues/Cargo.toml
Normal file
6
ch4/fixing_ownership_issues/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "fixing_ownership_issues"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
113
ch4/fixing_ownership_issues/src/main.rs
Normal file
113
ch4/fixing_ownership_issues/src/main.rs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
@ -100,8 +100,13 @@ fn main() {
|
||||
// -----------------------------------------------------------------------------
|
||||
// Data must outlive all of its references
|
||||
|
||||
// Ended at:
|
||||
// https://rust-book.cs.brown.edu/ch04-02-references-and-borrowing.html#summary
|
||||
// -----------------------------------------------------------------------------
|
||||
// Summary
|
||||
|
||||
// References provide ability to read/write data with consuming ownership.
|
||||
// References created with borrows (& and &mut) used dereferenced with * (often implictly)
|
||||
|
||||
// Off to fixing ownership issues in ch4.3
|
||||
}
|
||||
|
||||
fn greet(g1: String, g2: String) {
|
||||
|
7
ch4/slice_type/Cargo.lock
generated
Normal file
7
ch4/slice_type/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "slice_type"
|
||||
version = "0.1.0"
|
6
ch4/slice_type/Cargo.toml
Normal file
6
ch4/slice_type/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "slice_type"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
54
ch4/slice_type/src/main.rs
Normal file
54
ch4/slice_type/src/main.rs
Normal file
@ -0,0 +1,54 @@
|
||||
// Section 4.4
|
||||
// slices allow for reference in contiguous sequences of elements
|
||||
// inside of a collection.
|
||||
//
|
||||
// Part of writing fast Rust code is also understanding how
|
||||
// allocations work. This portion of the book is important, and I
|
||||
// need to come back and read it later.
|
||||
|
||||
fn main() {
|
||||
let mut s = String::from("hello world");
|
||||
let word = first_word(&s);
|
||||
|
||||
// borrowed here. Not allowed
|
||||
// s.clear();
|
||||
// print!("word: {word}");
|
||||
|
||||
// Range syntax. the .. like Haskell
|
||||
let s = String::from("hello");
|
||||
let slice = &s[0..2];
|
||||
let slice = &s[..2];
|
||||
let slice = &s[..]; // can just slice the whole thing
|
||||
|
||||
// Is this possible?
|
||||
// no
|
||||
// let temp_arr_size = 5;
|
||||
// let temparr = [1; temp_arr_size];
|
||||
}
|
||||
|
||||
// This isn't part of the section, just me testing out ownership
|
||||
fn mod_string(s: &mut String) -> &String {
|
||||
s.push_str("hello");
|
||||
s
|
||||
}
|
||||
|
||||
fn first_word(s: &String) -> &str {
|
||||
let bytes = s.as_bytes();
|
||||
for (i, &item) in bytes.iter().enumerate() {
|
||||
if item == b' ' {
|
||||
return &s[0..i];
|
||||
}
|
||||
}
|
||||
&s[..]
|
||||
}
|
||||
|
||||
// as.bytes() makes this an immutable reference
|
||||
// fn example_test() {
|
||||
// let mut s = String::from("hello");
|
||||
// for &item in s.as_bytes().iter() {
|
||||
// if item == b'l' {
|
||||
// s.push_str(" world");
|
||||
// }
|
||||
// }
|
||||
// println!("{s}");
|
||||
// }
|
Loading…
x
Reference in New Issue
Block a user