This commit is contained in:
2026-07-25 17:10:06 -04:00
parent 0eba3cfa29
commit 0e297a9fe6
6 changed files with 193 additions and 30 deletions
Generated
+144
View File
@@ -2,6 +2,150 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 4
[[package]]
name = "futures"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
[[package]]
name = "futures-executor"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
[[package]]
name = "futures-macro"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
[[package]]
name = "futures-task"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
[[package]]
name = "futures-util"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"slab",
]
[[package]]
name = "memchr"
version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
[[package]]
name = "pin-project-lite"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]] [[package]]
name = "playground" name = "playground"
version = "0.1.0" version = "0.1.0"
dependencies = [
"futures",
]
[[package]]
name = "proc-macro2"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
dependencies = [
"proc-macro2",
]
[[package]]
name = "slab"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "syn"
version = "2.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+1
View File
@@ -4,3 +4,4 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
futures = "0.3.32"
+10 -9
View File
@@ -1,4 +1,5 @@
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
#[allow(dead_code)]
pub struct EmptyListError; pub struct EmptyListError;
// implementing Error for my error to satisfy Box<dyn std::error::Error> // implementing Error for my error to satisfy Box<dyn std::error::Error>
@@ -13,23 +14,24 @@ impl std::fmt::Display for EmptyListError {
} }
// Result<...,Box<dyn std::error::Error>> is overkill // Result<...,Box<dyn std::error::Error>> is overkill
// this is intuitive enough for caller error detection // this is intuitive enough for caller error detection
// actually probably should use Option instead, but this is better for extension // actually probably should use Option instead, but this is better for extension
#[allow(dead_code)]
pub fn min_and_max(list: &[u32]) -> Result<(u32, u32), EmptyListError> { pub fn min_and_max(list: &[u32]) -> Result<(u32, u32), EmptyListError> {
if list.is_empty() { if list.is_empty() {
return Err(EmptyListError); return Err(EmptyListError);
} }
let mut min:u32 = 100; let mut min: u32 = 100;
let mut max:u32 = 0; let mut max: u32 = 0;
for i in list { for i in list {
if *i > max { if *i > max {
max = *i; max = *i;
} }
if *i < min { if *i < min {
min = *i; min = *i;
} }
} }
Ok((min,max)) Ok((min, max))
} }
#[cfg(test)] #[cfg(test)]
@@ -46,14 +48,14 @@ mod tests {
println!("Expected: {}", *(empty_min_and_max.as_ref().err().unwrap())); println!("Expected: {}", *(empty_min_and_max.as_ref().err().unwrap()));
// array - contiguous, entirely on the stack, fixed at compile time, no pointer indirection // array - contiguous, entirely on the stack, fixed at compile time, no pointer indirection
let l = [ 1, 2, 10, 100, 50, 75, 36, 21]; let l = [1, 2, 10, 100, 50, 75, 36, 21];
let l_min_and_max = min_and_max(&l); let l_min_and_max = min_and_max(&l);
assert!(l_min_and_max.as_ref().unwrap().0 == 1); assert!(l_min_and_max.as_ref().unwrap().0 == 1);
assert!(l_min_and_max.as_ref().unwrap().1 == 100); assert!(l_min_and_max.as_ref().unwrap().1 == 100);
// vec - stack: ptr, len, cap; ptr -> heap: contiguous allocation of capacity // vec - stack: ptr, len, cap; ptr -> heap: contiguous allocation of capacity
// when variable goes out of scope drop() is called to deallocate the heap // when variable goes out of scope drop() is called to deallocate the heap
let v = vec![1,2,3]; let v = vec![1, 2, 3];
let v_min_and_max = min_and_max(&v); let v_min_and_max = min_and_max(&v);
assert!(v_min_and_max.as_ref().unwrap().0 == 1); assert!(v_min_and_max.as_ref().unwrap().0 == 1);
assert!(v_min_and_max.as_ref().unwrap().1 == 3); assert!(v_min_and_max.as_ref().unwrap().1 == 3);
@@ -62,6 +64,5 @@ mod tests {
let r = &s; let r = &s;
println!("{}", *r); // works because there is no implicit move println!("{}", *r); // works because there is no implicit move
// let thing = *r; // doesn't work because String does not implement Copy trait // let thing = *r; // doesn't work because String does not implement Copy trait
} }
} }
+22
View File
@@ -0,0 +1,22 @@
use std::{thread, time};
#[allow(dead_code)]
async fn do_something(number: i8) -> i8 {
println!("number {} is running", number);
let two_seconds = time::Duration::new(2, 0);
thread::sleep(two_seconds);
return 2;
}
#[cfg(test)]
mod tests {
use super::*; // need access to functions above
#[test]
fn test_async() {
let _ = async {
do_something(2).await;
};
assert!(true);
}
}
+3 -4
View File
@@ -1,6 +1,7 @@
mod string;
mod arrays; mod arrays;
mod async_play;
mod fmt_debug; mod fmt_debug;
mod string;
// when a String is passed to this function a move occurs: // when a String is passed to this function a move occurs:
// BUT only the stack allocation (ptr, len, cap) is copied over // BUT only the stack allocation (ptr, len, cap) is copied over
@@ -74,7 +75,7 @@ fn min_and_max(list: &[u32]) -> Result<(u32, u32), EmptyListError> {
} }
fn main() { fn main() {
println!("Hello, world!"); println!("Learning Rust");
fmt_debug::test_report(); fmt_debug::test_report();
let s = String::new(); // no heap allocation until we add characters (capacity > 0) let s = String::new(); // no heap allocation until we add characters (capacity > 0)
@@ -112,6 +113,4 @@ fn main() {
let _s6 = String::from(s_lit); //underlying data copied to heap let _s6 = String::from(s_lit); //underlying data copied to heap
// todo: Cow // todo: Cow
println!("Learning Rust");
} }
+13 -17
View File
@@ -1,4 +1,4 @@
use std::rc::Rc; //use std::rc::Rc;
// when a String is passed to this function a move occurs: // when a String is passed to this function a move occurs:
// BUT only the stack allocation (ptr, len, cap) is copied over // BUT only the stack allocation (ptr, len, cap) is copied over
@@ -7,16 +7,12 @@ use std::rc::Rc;
// Why do we call it a "move"? // Why do we call it a "move"?
// A move indicates ownership transfer, not data transfer // A move indicates ownership transfer, not data transfer
#[allow(dead_code)] #[allow(dead_code)]
fn takes_string(_s: String) { fn takes_string(_s: String) {}
}
// You can do this, but you probably want &str // You can do this, but you probably want &str
// UNLESS you want `&mut String` // UNLESS you want `&mut String`
#[allow(dead_code)] #[allow(dead_code)]
fn takes_string_ref(_s: &String) { fn takes_string_ref(_s: &String) {}
}
// Compilation error and warning: // Compilation error and warning:
// rustc: the size for values of type `str` cannot be known at compilation time // rustc: the size for values of type `str` cannot be known at compilation time
@@ -36,9 +32,7 @@ fn takes_string_ref(_s: &String) {
// this is fine because now the variable is a fat pointer: pointer + length // this is fine because now the variable is a fat pointer: pointer + length
// it's the length aspect that makes us abot to work on the str // it's the length aspect that makes us abot to work on the str
#[allow(dead_code)] #[allow(dead_code)]
fn takes_str_ref(_s: &str) { fn takes_str_ref(_s: &str) {}
}
// yeah, we can do this // yeah, we can do this
fn _get_static_str() -> &'static str { fn _get_static_str() -> &'static str {
@@ -49,6 +43,8 @@ fn _get_static_str() -> &'static str {
// and run the test code only when you run cargo test, not when you run cargo build // and run the test code only when you run cargo test, not when you run cargo build
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::rc::Rc;
use super::*; // need access to functions above use super::*; // need access to functions above
#[test] #[test]
@@ -73,29 +69,29 @@ mod tests {
takes_str_ref(&sss); takes_str_ref(&sss);
// *sss dereferences the String into its underlying str // *sss dereferences the String into its underlying str
takes_str_ref(&*sss); // same as this! takes_str_ref(&*sss); // same as this!
takes_str_ref(sss.as_ref()); // and this! takes_str_ref(sss.as_ref()); // and this!
let s4 = String::from("string4"); let s4 = String::from("string4");
//let s4_slice = s4[0..]; // again we hit no size problem at compile time //let s4_slice = s4[0..]; // again we hit no size problem at compile time
let _s4_slice = &s4[0..]; // but this works, because the &str has the length! let _s4_slice = &s4[0..]; // but this works, because the &str has the length!
// literals // literals
// &'static str is held onto by &str: // &'static str is held onto by &str:
// that's the programs read-only binary // that's the programs read-only binary
let s_lit = "easy as pie, right?"; let s_lit = "easy as pie, right?";
let _s_lit2 : &str = "easy as pie, right?"; // same, data not copied, we just point to it let _s_lit2: &str = "easy as pie, right?"; // same, data not copied, we just point to it
let _s5 = String::from("literal is copied to heap"); // data copied to heap let _s5 = String::from("literal is copied to heap"); // data copied to heap
let _s6 = String::from(s_lit); //underlying data copied to heap let _s6 = String::from(s_lit); //underlying data copied to heap
// Box<str> is owned, heap allocated, fixed size, immutable // Box<str> is owned, heap allocated, fixed size, immutable
// where as `&str` is borrowed view, linked to source, immutable // where as `&str` is borrowed view, linked to source, immutable
// both have (ptr, len) -> underlying mem // both have (ptr, len) -> underlying mem
let _s7 : Box<str> = "hello".into(); let _s7: Box<str> = "hello".into();
// Rc<str> (single-threaded reference counting) // Rc<str> (single-threaded reference counting)
// HEAP memory layout: // HEAP memory layout:
// * counter (strong) // * counter (strong)
// * counter (weak) // * counter (weak)
// * len // * len
// * data // * data
// STACK memory: // STACK memory:
@@ -103,9 +99,9 @@ mod tests {
// * len // * len
// //
// Why are there two lengths? // Why are there two lengths?
let rc_str : Rc<str> = Rc::from("rc_str"); let rc_str: Rc<str> = Rc::from("rc_str");
// let rc_str2 : Rc<str> = rc_str; // this moves // let rc_str2 : Rc<str> = rc_str; // this moves
let rc_str2 : Rc<str> = rc_str.clone(); // copy ptr, increment counter let rc_str2: Rc<str> = rc_str.clone(); // copy ptr, increment counter
println!("printing {}", rc_str); println!("printing {}", rc_str);
println!("printing {}", rc_str); println!("printing {}", rc_str);
println!("printing {}", rc_str2); println!("printing {}", rc_str2);