From 4c9a6dec3c2478060da1b758aa12094e1ca01802 Mon Sep 17 00:00:00 2001 From: ehlxr Date: Tue, 16 Jun 2020 18:11:50 +0800 Subject: [PATCH] update at 2020-06-16 18:11:50 by ehlxr --- .gitignore | 4 + Cargo.lock | 58 ++ Cargo.toml | 9 + hello.txt | 1 + src/main.rs | 1488 ++++++++++++++++++++++++++++++++++++++++++++ src/ownership_1.rs | 21 + src/ownership_2.rs | 21 + 7 files changed, 1602 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 hello.txt create mode 100644 src/main.rs create mode 100644 src/ownership_1.rs create mode 100644 src/ownership_2.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b0c4a56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +**/*.rs.bk +.vscode +.idea \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..f055335 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,58 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "hello_macro" +version = "0.1.0" + +[[package]] +name = "hello_macro_derive" +version = "0.1.0" +dependencies = [ + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rust_study" +version = "0.1.0" +dependencies = [ + "hello_macro 0.1.0", + "hello_macro_derive 0.1.0", +] + +[[package]] +name = "syn" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d35a953 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rust_study" +version = "0.1.0" +authors = ["ehlxr "] +edition = "2018" + +[dependencies] +hello_macro = { path = "../hello_macro" } +hello_macro_derive = { path = "../hello_macro/hello_macro_derive" } \ No newline at end of file diff --git a/hello.txt b/hello.txt new file mode 100644 index 0000000..ab66e28 --- /dev/null +++ b/hello.txt @@ -0,0 +1 @@ +ehlxr \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..963b3b9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,1488 @@ +use std::cell::RefCell; +use std::hash::Hash; +use std::ops::Deref; +use std::rc::{Rc, Weak}; +use std::sync::{mpsc, Arc, Mutex}; +use std::time::Duration; +use std::{collections::HashMap, fmt::Display, fs::File, io, io::ErrorKind, thread}; + +fn main() { + let mut s = String::from("Hello"); + s.push_str(", World!"); + println!("{}", s); + + let c: char = 'd'; + println!("{}", c); + + let x = 5; + // cannot assign twice to immutable variable + // x = x + 1; + + // 使用 let 重新定义 x,隐藏了之前 x 的值 + let x = x + 1; + println!("The value of x is {}", x); + + let x = "test"; + println!("The value of x is {}", x); + + // 可变变量 + let mut x = 2; + x = x * 3; + // expected integer, found reference + // x = "test"; + println!("The value of x is {}", x); + + // : 指定变量类型 + let mut y: i32 = 22; + println!("The value of y is {}", y); + + y = 12; + println!("The value of y is {}", y); + + // 可变引用 + let mut s = String::from("hello"); + let s1 = &mut s; + // 在特定作用域中的特定数据有且只有一个可变引用 + // let s2 = &mut s; + + change(s1); + println!("{}", s1); + { + let s2 = &mut s; + println!("{}", s2); + } + + // 多个不可变引用是可以的 + let r1 = &s; + let r2 = &s; + // 不能在拥有不可变引用的同时拥有可变引用 + // let r3 = &mut s; + + println!("{}, {}", r1, r2); + + // --------------------------- + println!("----------------------------------------"); + let home = IpAddr::V4(127, 0, 0, 1); + let loopback = IpAddr::V6(String::from("::1")); + println!("{:?}, {:?}", home, loopback); + + let m = Message::Quit; + m.call(); + + let m = &Message::Move { x: 1, y: 2 }; + match m { + Message::Move { x, y } => println!("x: {}, y: {}", x, y), + _ => {} + } + m.call(); + + let m = Message::Write(String::from("test")); + m.call(); + + let m = Message::ChangeColor(1, 2, 3); + m.call(); + + // --------------------------- + println!("----------------------------------------"); + let my_str = String::from("hello world!"); + // let my_str = "hello world!"; + println!("{}, {}", my_str, first_words(&my_str[..])); + println!("get first word: {}", first_words("hello world")); + + let rect = Rectangle { + width: 21, + height: 23, + }; + println!( + "The area of the rectangle is {} square pixels.", + rect.area() + ); + + let rect1 = Rectangle { + width: 30, + height: 50, + }; + let rect2 = Rectangle { + width: 10, + height: 40, + }; + let rect3 = Rectangle { + width: 60, + height: 45, + }; + + println!("rect1 is {:#?}", rect1); + + println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2)); + println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3)); + + let rece4 = Rectangle::square(8); + println!( + "The area of the rectangle is {} square pixels.", + rece4.area() + ); + + // --------------------------- + println!("-----------------vec-----------------------"); + let mut v = vec![100, 32, 57]; + for i in &mut v { + *i += 50; + } + println!("{:?}", v); + + // let mut v=Vec::new(); + let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9]; + let f = v.get(100); + println!("{:?}", f); + let f = &v[0]; + println!("{}", f); + // v.push(12); + + let d: Option = None; + println!("{:?} {}", d, d.is_none()); + + let s = Some("ddd"); + println!("{:#?}", s); + + let s: Option = Some(2); + println!("{},{}", s.unwrap(), s.is_some()); + + performance_group::clarinet_trio(); + performance_group::instrument::clarinet(); + + let s1 = String::from("Hello"); + let s2 = String::from("World"); + + // + == fn add(self, s: &str) -> String + // 这个语句会获取 s1 的所有权,附加上从 s2 中拷贝的内容,并返回结果的所有权 + let s3 = s1 + &s2; + let s = format!("{}-{}", s2, s3); + println!("{}", s); + + let hello = "你好"; + println!("{}", hello.len()); // output: 6 + + let s = &hello[0..3]; // output: 你 + println!("{}", s); + + for c in hello.chars() { + println!("{}", c); + } + for b in hello.bytes() { + println!("{}", b); + } + + // --------------------------- + println!("----------------------------------------"); + let mut scores = HashMap::new(); + scores.insert(String::from("Blue"), 10); + scores.insert(String::from("Yellow"), 50); + + let team_name = String::from("Blue"); + let score = scores.get(&team_name); + println!("{}", score.unwrap()); + + for (k, v) in scores.iter() { + println!("{}, {}", k, v) + } + + scores.entry(String::from("Yellow")).or_insert(50); + let black = scores.entry(String::from("black")).or_insert(50); + + // cannot borrow `scores` as immutable because it is also borrowed as mutable + // println!("{:?}, {}", scores, black); + println!("{}", black); + println!("{:#?}", scores); + + let text = "hello world wonderful world"; + let mut map = HashMap::new(); + for word in text.split_whitespace() { + let count = map.entry(word).or_insert(0); + *count += 1; + } + println!("{:?}", map); + + // --------------------------- + println!("----------------------------------------"); + let f = match File::open("hello.txt") { + Ok(file) => file, + Err(error) => match error.kind() { + ErrorKind::NotFound => match File::create("hello.txt") { + Ok(file) => file, + Err(e) => panic!("Tried to create file but there was a problem: {:?}", e), + }, + ot_err => panic!("There was a problem opening the file: {:?}", ot_err), + }, + }; + println!("{:?}", f.metadata()); + + match read_username_from_file() { + Ok(st) => println!("{}", st), + Err(err) => panic!("There was a problem read string: {:?}", err), + }; + + let h: std::net::IpAddr = "127.0.0.1".parse().unwrap(); + let s: String = "127.0.0.1".parse().unwrap(); + println!("{:?}, {}", h, s); + + let v = ["d", "fd"]; + println!("{:?}", v); + let v = vec!["d", "fd"]; + println!("{:?}", v); + + // --------------------------- + println!("----------------------------------------"); + let t = Tweet { + username: String::from("horse_ebooks"), + content: String::from("of course, as you probably already know, people"), + reply: false, + retweet: false, + }; + let t1 = returns_summarizable(); + + println!("{}", notify(&t, &t1)); + + let number_list = vec![34, 50, 25, 100, 65]; + let result = largest(&number_list); + println!("The largest number is {}", result); + + let char_list = vec!['y', 'm', 'a', 'q']; + let result = largest(&char_list); + println!("The largest char is {}", result); + + // --------------------------- + println!("----------------------------------------"); + let p = Pair::new(String::from("t"), String::from("s")); + p.cmp_display(); + + let p = Pair::new( + Rectangle { + width: 2, + height: 3, + }, + Rectangle { + width: 4, + height: 9, + }, + ); + println!("{:?}", p); + // no method named `cmp_display` found for type `Pair` in the current scope + // p.cmp_display(); + + // --------------------------- + println!("----------------------------------------"); + let s1 = String::from("abcd"); + let r; + { + let s2 = String::from("qw"); + r = longest(s1.as_str(), s2.as_ref()); + println!("The longest string is {}", r); + } + // `s2` does not live long enough + // println!("The longest string is {}", r); + + let closure = |x: u32| -> u32 { x + 2 }; + // let closure = |x| x + 2; + println!("closure: {}", closure(3)); + + let mut s = String::from("hello"); + let d = change; + d(&mut s); + println!("{}", s); + + generate_workout(10, 3); + + // --------------------------- + println!("----------------------------------------"); + let x = 4; + let equal_to_x = |z| z == x; + println!("{}", equal_to_x(4)); + + let x = vec![1, 2, 3]; + // move 强制闭包获取其使用的环境值的所有权 + let equal_to_x = move |z| z == x; + //value used here after move + // println!("can't use x here: {:?}", x); + let y = vec![1, 2, 3]; + println!("{}", equal_to_x(y)); + + let v1: Vec = vec![1, 2, 3]; + let v2: Vec<_> = v1.iter().map(|x| x + 1).collect(); + println!("{:?}", v2); + + let shoes = vec![ + Shoe { + size: 10, + style: String::from("sneaker"), + }, + Shoe { + size: 13, + style: String::from("sandal"), + }, + Shoe { + size: 10, + style: String::from("boot"), + }, + ]; + let in_my_size = shoes_in_my_size(shoes, 10); + println!("{:?}", in_my_size); + + let counter = Counter::new(); + let v: Vec<_> = counter.into_iter().map(|x| x + 1).collect(); + println!("{:?}", v); + let v: Vec<_> = Counter::new() + .zip(Counter::new().skip(1)) + .map(|(a, b)| a * b) + .collect(); + println!("{:?}", v); + let sum: u32 = Counter::new() + .zip(Counter::new().skip(1)) + .map(|(a, b)| a * b) + .filter(|x| x % 3 == 0) + .sum(); + println!("{}", sum); + + // --------------------------- + println!("----------------------------------------"); + use crate::List::*; + + let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil)))); + + println!("a initial rc count = {}", Rc::strong_count(&a)); + println!("a next item = {:?}", a.tail()); + + let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a)))); + + println!("a rc count after b creation = {}", Rc::strong_count(&a)); + println!("b initial rc count = {}", Rc::strong_count(&b)); + println!("b next item = {:?}", b.tail()); + + if let Some(link) = a.tail() { + *link.borrow_mut() = Rc::clone(&b); + } + + println!("b rc count after changing a = {}", Rc::strong_count(&b)); + println!("a rc count after changing a = {}", Rc::strong_count(&a)); + + // 这会导致栈溢出 + // println!("a next item = {:?}", a.tail()); + // 并不是 a.tail(); 引起死循环,打印函数触发循环引用 + + // --------------------------- + println!("----------------------------------------"); + let leaf = Rc::new(Node { + value: 3, + parent: RefCell::new(Weak::new()), + children: RefCell::new(vec![]), + }); + println!( + "leaf strong = {}, weak = {}, parent = {:?}", + Rc::strong_count(&leaf), + Rc::weak_count(&leaf), + leaf.parent.borrow().upgrade(), + ); + { + let branch = Rc::new(Node { + value: 5, + parent: RefCell::new(Weak::new()), + children: RefCell::new(vec![Rc::clone(&leaf)]), + }); + + *leaf.parent.borrow_mut() = Rc::downgrade(&branch); + // let leaf = Rc::new(Node { + // value: 3, + // parent: RefCell::new(Rc::downgrade(&branch)), + // children: RefCell::new(vec![]), + // }); + + println!( + "branch strong = {}, weak = {}, parent = {:?}", + Rc::strong_count(&branch), + Rc::weak_count(&branch), + branch.parent.borrow().upgrade(), + ); + + println!( + "leaf strong = {}, weak = {}, parent = {:?}", + Rc::strong_count(&leaf), + Rc::weak_count(&leaf), + leaf.parent.borrow().upgrade(), + ); + } // -> 离开作用域,此时,Rc 的强引用(strong_count)为 0,但是 Weak 弱引用数(weak_count)仍然为 1(引用 Weak 的 Rc 仍然存在), + // weak_count 无需计数为 0 就能使 Rc 实例被清理。 + println!( + "leaf strong = {}, weak = {}, parent = {:?}", + Rc::strong_count(&leaf), + Rc::weak_count(&leaf), + leaf.parent.borrow().upgrade(), + ); + + // --------------------------- + println!("----------------------------------------"); + let x = Rc::new(5); + let y = *x; + assert_eq!(5, y); + + let r = Rc::new("Rust".to_string()); + // Rc 不支持解引用移动 + // let x = *r; + // println!("{:?}", x); + println!("{:?}", *r); + + let x = RefCell::new(5); + println!("{}", *x.borrow()); + // 变量 x 非 mut,可通过以下代码修改 x 的值 + *x.borrow_mut() = 7; + println!("{}", *x.borrow()); + + let x = Box::new(5); + let x1 = *x; + println!("Box {}", x1); + + // --------------------------- + println!("--------函数和方法的隐式解引用强制多态--------------"); + // let m = Box::new(String::from("Rust")); + let m = MyBox::new(String::from("Rust")); + //String 上的 Deref 实现: fn deref(&self) -> &str {...} + + // hello_str(&(*m)[..]); + // 当所涉及到的类型定义了 Deref trait,Rust 会分析这些类型并使用任意多次 Deref::deref 调用以获得匹配参数的类型 + // &m -> &String -> &str + hello_str(&m); + + // --------------------------- + println!("---------------------------"); + let jh = thread::spawn(|| { + for i in 1..10 { + println!("hi number {} from the spawned thread!", i); + thread::sleep(Duration::from_millis(1)); + } + }); + + for i in 1..5 { + println!("hi number {} from the main thread!", i); + thread::sleep(Duration::from_millis(1)); + } + jh.join().unwrap(); + + let v = vec![1, 2, 3]; + let handle = thread::spawn(move || { + println!("Here's a vector: {:?}", v); + }); + // drop(v); + // ^ value used here after move + handle.join().unwrap(); + + // --------------------------- + println!("---------------------------"); + let (tx, rx) = mpsc::channel(); + let tx1 = mpsc::Sender::clone(&tx); + thread::spawn(move || { + let vals = vec![ + String::from("hi"), + String::from("from"), + String::from("the"), + String::from("thread"), + ]; + + for val in vals { + tx1.send(val).unwrap(); + thread::sleep(Duration::from_millis(50)); + } + }); + + thread::spawn(move || { + // tx.send(12).unwrap(); + tx.send(String::from("12")).unwrap(); + }); + + for received in rx { + println!("Got: {}", received); + } + + // --------------------------- + println!("---------------------------"); + let counter = Arc::new(Mutex::new(0)); + let mut handles = vec![]; + + for _ in 0..10 { + let counter = Arc::clone(&counter); + let handle = thread::spawn(move || { + let mut num = counter.lock().unwrap(); + + *num += 1; + }); + handles.push(handle); + } + + for handle in handles { + handle.join().unwrap(); + } + + println!("Result: {}", *counter.lock().unwrap()); + + // --------------------------- + println!("---------------------------"); + let screen = Screen { + components: vec![ + Box::new(SelectBox { + width: 75, + height: 10, + options: vec![ + String::from("Yes"), + String::from("Maybe"), + String::from("No"), + ], + }), + Box::new(Button { + width: 50, + height: 10, + label: String::from("OK"), + }), + ], + }; + + screen.run(); + + // --------------------------- + println!("---------------------------"); + + let bt = Bt { + height: 10, + label: Some(String::from("test")), + }; + + let h = bt.label.unwrap(); + println!("{}", h); + // borrow of moved value: `bt` + // println!("{:?}", bt); + + // --------------------------- + println!("---------------------------"); + let favorite_color: Option<&str> = None; + let is_tuesday = false; + let age: Result = "34".parse(); + + if let Some(color) = favorite_color { + println!("Using your favorite color, {}, as the background", color); + } else if is_tuesday { + println!("Tuesday is green day!"); + } else if let Ok(age) = age { + if age > 30 { + println!("Using purple as the background color"); + } else { + println!("Using orange as the background color"); + } + } else { + println!("Using blue as the background color"); + } + + let mut stack = Vec::new(); + stack.push(1); + stack.push(2); + stack.push(3); + while let Some(top) = stack.pop() { + println!("{}", top); + } + + let v = vec!['a', 'b', 'c']; + for (index, value) in v.iter().enumerate() { + println!("{} is at index {}", value, index); + } + + let x: u32 = 5; + let point = (3, x as i32); + print_coordinates(&point); + + // --------------------------- + println!("---------------------------"); + // 匹配字面值 + let x = 1; + match x { + 1 => println!("one"), + 2 => println!("two"), + 3 => println!("three"), + _ => println!("anything"), + } + + // 匹配命名变量 + let x = Some(5); + let y = 10; + match x { + Some(50) => println!("Got 50"), + Some(y) => println!("Matched, y = {:?}", y), + _ => println!("Default case, x = {:?}", x), + } + println!("at the end: x = {:?}, y = {:?}", x, y); + + // 多个模式 + let x = 1; + match x { + 1 | 2 => println!("one or two"), + 3 => println!("three"), + _ => println!("anything"), + } + + // 通过 ... 匹配值的范围 + // 范围只允许用于数字或 char 值 + let x = 5; + match x { + 1...5 => println!("one through five"), + _ => println!("something else"), + } + + let x = 'c'; + match x { + 'a'...'j' => println!("early ASCII letter"), + 'k'...'z' => println!("late ASCII letter"), + _ => println!("something else"), + } + + // 解构结构体 + struct Point { + x: i32, + y: i32, + } + let p = Point { x: 0, y: 7 }; + let Point { x: a, y: b } = p; + assert_eq!(0, a); + assert_eq!(7, b); + + let Point { x, y } = p; + assert_eq!(0, x); + assert_eq!(7, y); + + match p { + Point { x, y: 0 } => println!("On the x axis at {}", x), + Point { x: 0, y } => println!("On the y axis at {}", y), + Point { x, y } => println!("On neither axis: ({}, {})", x, y), + } + + // 解构枚举 + // let msg = Message::ChangeColor(0, 160, 255); + let msg = &Message::Move { x: 1, y: 2 }; + // let msg = &Message::Quit; + match msg { + Message::Quit => println!("The Quit variant has no data to destructure."), + Message::Move { x, y } => { + println!("Move in the x direction {} and in the y direction {}", x, y); + } + Message::Write(text) => println!("Text message: {}", text), + Message::ChangeColor(r, g, b) => { + println!("Change the color to red {}, green {}, and blue {}", r, g, b) + } + } + + // 解构嵌套的结构体 & 枚举 + let msg = Msg::ChangeColor(Color::Hsv(0, 160, 255)); + match msg { + Msg::ChangeColor(Color::_Rgb(r, g, b)) => { + println!("Change the color to red {}, green {}, and blue {}", r, g, b) + } + Msg::ChangeColor(Color::Hsv(h, s, v)) => println!( + "Change the color to hue {}, saturation {}, and value {}", + h, s, v + ), + _ => (), + } + + // 解构引用 + let points = vec![ + Point { x: 0, y: 0 }, + Point { x: 1, y: 5 }, + Point { x: 10, y: -3 }, + ]; + + let sum_of_squares: i32 = points.iter().map(|&Point { x, y }| x * x + y * y).sum(); + println!("{}", sum_of_squares); + + // 解构结构体和元组 + let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 }); + println!("{} {} {} {}", feet, inches, x, y); + + // 忽略模式中的值 + foo(3, 4); + fn foo(_: i32, y: i32) { + println!("This code only uses the y parameter: {}", y); + } + + let mut setting_value = Some(5); + let new_setting_value = Some(10); + match (setting_value, new_setting_value) { + (Some(_), Some(_)) => { + println!("Can't overwrite an existing customized value"); + } + _ => { + setting_value = new_setting_value; + } + } + println!("setting is {:?}", setting_value); + + let numbers = (2, 4, 8, 16, 32); + match numbers { + (first, _, third, _, fifth) => println!("Some numbers: {}, {}, {}", first, third, fifth), + } + match numbers { + (first, .., last) => println!("Some numbers: {}, {}", first, last), + // error: `..` can only be used once per tuple or tuple struct pattern + // (.., second, ..) => println!("Some numbers: {}", second), + } + + // 通过在名字前以一个下划线开头来忽略未使用的变量 + let _x = 5; + // let y = 10; + // ^ help: consider prefixing with an underscore: `_y` + + struct Pt { + x: i32, + _y: i32, + _z: i32, + } + let origin = Pt { x: 0, _y: 0, _z: 0 }; + match origin { + Pt { x, .. } => println!("x is {}", x), + } + + // 匹配守卫提供的额外条件 + let num = Some(4); + match num { + Some(x) if x < 5 => println!("less than five: {}", x), + Some(x) => println!("{}", x), + None => (), + } + + let x = 4; + let y = true; + match x { + // 匹配守卫中引用外部变量 y,而不是创建新变量 y + // if 条件作用于整个 4 | 5 | 6 模式,类似:(4 | 5 | 6) if y => println!("yes"), + 4 | 5 | 6 if y => println!("yes"), + _ => println!("no"), + } + + // 使用 @ 可以在一个模式中同时测试和保存变量值。 + enum Ms { + Hello { id: i32 }, + } + let msg = Ms::Hello { id: 5 }; + match msg { + Ms::Hello { id: id_var @ 3...7 } => println!("Found an id in range: {}", id_var), + // 此匹配分支不能使用 id + Ms::Hello { id: 10...12 } => println!("Found an id in another range"), + Ms::Hello { id } => println!("Found some other id: {}", id), + } + + // 遗留模式: ref 和 ref mut + let robot_name = &Some(String::from("Bors")); + match robot_name { + Some(name) => println!("Found a name: {}", name), + // 老版本中会如下使用 + // &Some(ref name) => println!("Found a name: {}", name), + None => (), + } + println!("robot_name is: {:?}", robot_name); + + // --------------------------- + println!("---------------------------"); + let mut num = 5; + let r1 = &num as *const i32; // 不可变的裸指针 + let r2 = &mut num as *mut i32; // 可变的裸指针 + unsafe { + println!("r1 is: {}", *r1); + println!("r2 is: {}", *r2); + } + + unsafe fn dangerous() { + println!("this dangerous function"); + } + unsafe { + dangerous(); + } + + let mut v = vec![1, 2, 3, 4, 5, 6]; + let r = &mut v[..]; + // let (a, b) = r.split_at_mut(3); + let (a, b) = split_at_mut(r, 3); + println!("{:?}", a); + println!("{:?}", b); + + // 使用 extern 函数调用外部 C 语言代码 + extern "C" { + fn abs(input: i32) -> i32; + } + unsafe { + println!("Absolute value of -3 according to C: {}", abs(-3)); + } + + // 定义可供 C 语言调用的函数 + #[no_mangle] + pub extern "C" fn call_from_c() { + println!("Just called a Rust function from C!"); + } + + // 静态变量 + // 访问不可变静态变量是安全的 + static HELLO_WORLD: &str = "Hello, world!"; + println!("name is: {}", HELLO_WORLD); + + // 访问和修改可变静态变量都是 不安全 的 + add_to_count(3); + unsafe { + println!("COUNTER: {}", COUNTER); + } + + unsafe trait Foo { + // methods go here + } + unsafe impl Foo for i32 { + // method implementations go here + } + + // --------------------------- + println!("---------------------------"); + struct Context<'s>(&'s str); + // 声明一个不短于 'c 的生命周期 's。 + // struct Parser<'c, 's: 'c> { + struct Parser<'c, 's> { + context: &'c Context<'s>, + } + impl<'c, 's> Parser<'c, 's> { + fn parse(&self) -> Result<(), &'s str> { + Err(&self.context.0[1..]) + } + } + fn parse_context(context: Context) -> Result<(), &str> { + Parser { context: &context }.parse() + } + + let centext = Context("test"); + match parse_context(centext) { + Err(s) => println!("{}", s), + _ => (), + } + + // --------------------------- + println!("---------------------------"); + trait Red {} + struct Ball<'a> { + diameter: &'a i32, + } + // impl<'a> Red for Ball<'a> {} + impl Red for Ball<'_> {} + + let num = 5; + let obj = Box::new(Ball { diameter: &num }) as Box; + + // --------------------------- + println!("---------------------------"); + struct StrWrap<'a>(&'a str); + // '_ 表明在此处使用省略的生命周期,这意味着我们仍然知道 StrWrap 包含一个引用,不过无需所有的生命周期注解来知道。 + // fn foo<'a>(string: &'a str) -> StrWrap<'a> { + fn fsw(string: &str) -> StrWrap<'_> { + StrWrap(string) + } + + // --------------------------- + println!("---------------------------"); + fn add_one(x: i32) -> i32 { + x + 1 + } + fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { + f(arg) + f(arg) + } + let answer = do_twice(add_one, 5); + println!("The answer is: {}", answer); + + // --------------------------- + println!("---------------------------"); + let list_of_numbers = vec![1, 2, 3]; + let list_of_strings: Vec = list_of_numbers.iter().map(ToString::to_string).collect(); + // let list_of_strings: Vec = list_of_numbers.iter().map(|i| i.to_string()).collect(); + println!("{:?}", list_of_strings); + + #[derive(Debug)] + enum Status { + Value(u32), + Stop, + } + let list_of_statuses: Vec = (0u32..20).map(Status::Value).collect(); + // let list_of_statuses: Vec = (0u32..20).map(|i| Status::Value(i)).collect(); + println!("{:?}", list_of_statuses); + + fn returns_closure() -> Box i32> { + Box::new(|x| x + 1) + } + let rc = returns_closure(); + println!("{}", rc(12)); + + // --------------------------- + println!("---------------------------"); + use hello_macro::HelloMacro; + use hello_macro_derive::HelloMacro; + + #[derive(HelloMacro)] + struct Pancakes; + + Pancakes::hello_macro(); + + let user1 = User { + username: String::from("hllo"), + email: String::from("hell@world.com"), + sign_in_count: 1, + active: false, + }; + println!("{:?}", user1); + + let s: &str = "Hello"; + println!("{}", s); + let mut s: String = "Hello".to_string(); + let w = "World"; + s.push_str(w);// 并不需要获取 w 的所有权 + s.push('!'); + println!("{} {}", s, w); + + let t = (1, "34"); + test_tuple(t); + println!("{} {}", t.0, t.1); + + let s1 = String::from("Hello, "); + let s2 = String::from("World!"); + let s3 = s1 + &s2; // 注意 s1 被移动了,不能继续使用 + // println!("{} {} {}", s1, s3, s2); + println!("{} {}", s3, s2); + + for c in "नमˑे".chars() { + println!("{}", c); + } + for b in "नमˑे".bytes() { + println!("{}", b); + } + let hello = "Здравствуйте"; + let s = &hello[0..4]; + println!("&hello[0..4]={}", s); +} + +fn test_tuple(t: (i32, &str)) { + println!("{} {}", t.0, t.1); +} + +#[derive(Debug)] +struct User { + username: String, + email: String, + sign_in_count: u64, + active: bool, +} + +static mut COUNTER: u32 = 0; + +fn add_to_count(inc: u32) { + unsafe { + COUNTER += inc; + } +} + +use std::io::Read; +use std::slice; + +fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { + // let len = slice.len(); + // assert!(mid <= len); + // (&mut slice[..mid], &mut slice[mid..]) + + let len = slice.len(); + let ptr = slice.as_mut_ptr(); + + assert!(mid <= len); + + unsafe { + ( + slice::from_raw_parts_mut(ptr, mid), + slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid), + ) + } +} + +fn print_coordinates(&(x, y): &(i32, i32)) { + println!("Current location: ({}, {})", x, y); +} + +#[derive(Debug)] +struct Bt { + height: u32, + label: Option, +} + +#[derive(Debug)] +struct SelectBox { + width: u32, + height: u32, + options: Vec, +} + +impl Draw for SelectBox { + fn draw(&self) { + // code to actually draw a select box + println!("{:?}", self); + } +} + +#[derive(Debug)] +pub struct Button { + pub width: u32, + pub height: u32, + pub label: String, +} + +impl Draw for Button { + fn draw(&self) { + // 实际绘制按钮的代码 + println!("{:?}", self); + } +} + +pub struct Screen { + pub components: Vec>, +} + +impl Screen { + pub fn run(&self) { + for component in self.components.iter() { + component.draw(); + } + } +} + +pub trait Draw { + fn draw(&self); +} + +struct MyBox(T); + +impl MyBox { + fn new(x: T) -> MyBox { + MyBox(x) + } +} + +impl Deref for MyBox { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +fn hello_str(name: &str) { + println!("Hello, {}!", name); +} + +#[derive(Debug)] +enum List { + Cons(i32, RefCell>), + Nil, +} + +impl List { + fn tail(&self) -> Option<&RefCell>> { + use crate::List::*; + match self { + Cons(_, item) => Some(item), + Nil => None, + } + } +} + +#[derive(Debug)] +struct Node { + value: i32, + parent: RefCell>, + children: RefCell>>, +} + +fn change(some_string: &mut String) { + some_string.push_str(", world"); +} + +//enum IpAddrKind { +// V4, +// V6, +//} + +#[derive(Debug)] +enum IpAddr { + V4(u8, u8, u8, u8), + V6(String), +} + +enum Color { + _Rgb(i32, i32, i32), + Hsv(i32, i32, i32), +} + +enum Msg { + _Quit, + ChangeColor(Color), +} + +// Quit 没有关联任何数据。 +// Move 包含一个匿名结构体。 +// Write 包含单独一个 String。 +// ChangeColor 包含三个 i32。 +#[derive(Debug)] +enum Message { + Quit, + Move { x: i32, y: i32 }, + Write(String), + ChangeColor(i32, i32, i32), +} + +impl Message { + fn call(&self) { + println!("this message call."); + } +} + +//fn first_words<'a>(s: &'a str) -> &'a str { +fn first_words(s: &str) -> &str { + let b = s.as_bytes(); + for (i, &item) in b.iter().enumerate() { + if item == b' ' { + return &s[0..i]; + } + } + + &s[..] +} + +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, +} + +impl Rectangle { + fn area(&self) -> u32 { + self.width * self.height + } + + fn can_hold(&self, other: &Rectangle) -> bool { + self.width > other.width && self.height > other.height + } + + fn square(size: u32) -> Rectangle { + Rectangle { + width: size, + height: size, + } + } +} + +mod sound { + pub mod instrument { + pub fn clarinet() { + println!("this clarinet"); + } + } +} + +mod performance_group { + pub use crate::sound::instrument; + + pub fn clarinet_trio() { + instrument::clarinet(); + instrument::clarinet(); + instrument::clarinet(); + } +} + +// 传播错误 +fn read_username_from_file() -> Result { + // 1. + let f = File::open("hello.txt"); + + let mut f = match f { + Ok(file) => file, + Err(error) => return Err(error), + }; + + let mut s = String::new(); + match f.read_to_string(&mut s) { + Ok(_) => Ok(s), + Err(e) => Err(e), + } + + // 2. + // let mut f = File::open("hello.txt")?; + // + // let mut s = String::new(); + // f.read_to_string(&mut s)?; + // Ok(s) + + // 3. + // let mut s = String::new(); + // File::open("hello.txt")?.read_to_string(&mut s)?; + // Ok(s) + + // 4. + // fs::read_to_string("hello.txt") +} + +trait Summary { + fn summarize_author(&self) -> String; + + fn summarize(&self) -> String { + format!("(Read more from {}...)", self.summarize_author()) + } +} + +#[derive(Debug)] +struct Tweet { + pub username: String, + pub content: String, + pub reply: bool, + pub retweet: bool, +} + +impl Summary for Tweet { + fn summarize_author(&self) -> String { + format!("@{}", self.username) + } +} + +impl ToString for Tweet { + fn to_string(&self) -> String { + format!("{:?}", self) + } +} + +//fn notify(t: &T, u: &U) -> String { +// format!("{}, {}", u.summarize(), t.to_string()) +//} + +//fn notify(t: &(impl Summary + ToString), u: &(impl Summary)) -> String { +// format!("{}, {}", u.summarize(), t.to_string()) +//} + +fn notify(t: &T, u: &U) -> String + where + T: Summary + ToString, + U: Summary, +{ + format!("{}, {}", u.summarize(), t.to_string()) +} + +// 返回实现了指定 trait 的方法 +fn returns_summarizable() -> impl Summary { + Tweet { + username: String::from("horse_ebooks"), + content: String::from("of course, as you probably already know, people"), + reply: false, + retweet: false, + } +} + +fn largest(list: &[T]) -> T { + //fn largest(list: &[impl PartialOrd + Copy]) -> impl PartialOrd + Copy { + //fn largest(list: &[T]) -> T + // where T: PartialOrd + Copy { + let mut largest = list[0]; + + for &item in list.iter() { + if item > largest { + largest = item; + } + } + + // for item in list.iter() { + // if *item > largest { + // largest = *item; + // } + // } + + return largest; +} + +#[derive(Debug)] +struct Pair { + x: T, + y: T, +} + +impl Pair { + fn new(x: T, y: T) -> Self { + Self { x, y } + } +} + +// 只有那些为 T 类型实现了 PartialOrd trait(来允许比较)和 Display trait(来启用打印)的 Pair 才会实现 cmp_display 方法 +impl Pair { + fn cmp_display(&self) { + if self.x >= self.y { + println!("The largest member is x = {}", self.x); + } else { + println!("The largest member is y = {}", self.y); + } + } +} + +fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { + if x.len() > y.len() { + x + } else { + y + } +} + +struct Cacher + where + T: Fn(&D) -> F, +{ + calculation: T, + value: HashMap, +} + +impl Cacher + where + D: Hash + Eq, + F: Copy, + T: Fn(&D) -> F, +{ + fn new(calculation: T) -> Cacher { + Self { + calculation, + value: HashMap::::new(), + } + } + + fn value(&mut self, args: D) -> F { + match self.value.get(&args) { + Some(&v) => v, + None => { + let v = (self.calculation)(&args); + let v1 = v.clone(); + + self.value.insert(args, v); + + v1 + } + } + } +} + +fn generate_workout(intensity: u32, random_number: u32) { + // let calculation = |num: u32| -> u32 { + // println!("calculating slowly..."); + // thread::sleep(Duration::from_secs(2)); + // num + // }; + + let mut expensive_result = Cacher::new(|num| { + println!("calculating slowly..."); + thread::sleep(Duration::from_millis(500)); + num + 1 + }); + + if intensity < 25 { + println!("Today, do {} pushups!", expensive_result.value(intensity)); + println!("Next, do {} situps!", expensive_result.value(intensity)); + } else { + if random_number == 3 { + println!("Take a break today! Remember to stay hydrated!"); + } else { + println!( + "Today, run for {} minutes!", + expensive_result.value(intensity) + ); + } + } +} + +#[derive(Debug)] +struct Shoe { + size: u32, + style: String, +} + +fn shoes_in_my_size(shoes: Vec, shoe_size: u32) -> Vec { + shoes + // .iter() // a collection of type `std::vec::Vec` cannot be built from `std::iter::Iterator` + .into_iter() //获取 vector 所有权的迭代器 + .filter(|s| s.size == shoe_size) + .collect() +} + +struct Counter { + count: u32, +} + +impl Counter { + fn new() -> Counter { + Counter { count: 0 } + } +} + +impl Iterator for Counter { + type Item = u32; + + fn next(&mut self) -> Option { + self.count += 1; + + if self.count < 6 { + Some(self.count) + } else { + None + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn call_with_different_values() { + let mut c = Cacher::new(|a| { + println!("cal: {}", a); + a + 1 + }); + + let v1 = c.value(2); + let v1 = c.value(2); + assert_eq!(v1, 3); + + let v2 = c.value(-2); + assert_eq!(v2, -1); + } + + #[test] + fn call_with_different_type() { + let mut c = Cacher::new(|a| { + println!("\ncal: {}", a); + 7 + }); + + let v = c.value("tetsss"); + assert_eq!(v, 7); + } + + #[test] + fn iterator_demonstration() { + let v1 = vec![1, 2, 3]; + let mut v1_iter = v1.iter(); + + assert_eq!(v1_iter.next(), Some(&1)); + assert_eq!(v1_iter.next(), Some(&2)); + assert_eq!(v1_iter.next(), Some(&3)); + assert_eq!(v1_iter.next(), None); + } + + #[test] + fn iterator_sum() { + let v1 = vec![1, 2, 3]; + let v1_iter = v1.iter(); + let total: i32 = v1_iter.sum(); + + assert_eq!(total, 6); + } +} diff --git a/src/ownership_1.rs b/src/ownership_1.rs new file mode 100644 index 0000000..c69fd46 --- /dev/null +++ b/src/ownership_1.rs @@ -0,0 +1,21 @@ +fn main() { + + let s = String::from("hello"); // s 进入作用域 + + takes_ownership(s);// s 的值移动到函数里 ... + + // ... 所以到这里不再有效 + + let x = 5;// x 进入作用域 + + makes_copy(x);// x 应该移动函数里, +// 但 i32 是 Copy 的,所以在后面可继续使用 x +} // 这里, x 先移出了作用域,然后是 s。但因为 s 的值已被移走,所以不会有特殊操作 + +fn takes_ownership(some_string: String) { // some_string 进入作用域 + println!("{}", some_string); +} // 这里,some_string 移出作用域并调用 `drop` 方法。占用的内存被释放 + +fn makes_copy(some_integer: i32) { // some_integer 进入作用域 + println!("{}", some_integer); +} // 这里,some_integer 移出作用域。不会有特殊操作 \ No newline at end of file diff --git a/src/ownership_2.rs b/src/ownership_2.rs new file mode 100644 index 0000000..a703df2 --- /dev/null +++ b/src/ownership_2.rs @@ -0,0 +1,21 @@ +fn main() { + let s1 = gives_ownership(); // gives_ownership 将返回值 移给 s1 + println!("{}", s1); + + let s2 = String::from("hello"); // s2 进入作用域 + // println!("{}", s2); + + let s3 = takes_and_gives_back(s2); // s2 被移动到 takes_and_gives_back 中, 它也将返回值移给 s3 + println!("{}", s3); +} // 这里, s3 移出作用域并被丢弃。s2 也移出作用域,但已被移走,所以什么也不会发生。s1 移出作用域并被丢弃 + +fn gives_ownership() -> String { // gives_ownership 将返回值移动给调用它的函数 + let some_string = String::from("hello"); // some_string 进入作用域. + some_string // 返回 some_string 并移出给调用的函数 +} + +// takes_and_gives_back 将传入字符串并返回该值 +fn takes_and_gives_back(a_string: String) -> String { // a_string 进入作用域 + a_string + // 返回 a_string 并移出给调用的函数 +} \ No newline at end of file