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
|
// 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) {
|
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