├── .gitignore ├── 01-basic ├── 01-hello-world │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── 02-Var │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── 03-loop │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── 04-if │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── 05-match │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── 06-func │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── course │ └── leetcode │ │ └── fizz-buzz.rs ├── learn-array │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── learn-hashmap │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── learn-lifetime │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── learn-ownership │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── learn-primitives │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── learn-slice │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── learn-thread │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── learn-trait │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── learn_struct │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── stdin │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs └── vec │ ├── Cargo.toml │ └── src │ └── main.rs ├── README.md ├── build-own-x ├── lang-vm │ └── iridium │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ ├── instruction.rs │ │ ├── main.rs │ │ ├── repl │ │ └── mod.rs │ │ └── vm.rs └── shell │ ├── Cargo.toml │ └── src │ └── main.rs ├── cargo └── README.md ├── design-pattent └── memento-pattent │ ├── Cargo.toml │ ├── README.md │ └── src │ ├── editor.rs │ ├── editorstate.rs │ ├── history.rs │ └── main.rs ├── learn-wasm ├── .appveyor.yml ├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE_APACHE ├── LICENSE_MIT ├── Makefile ├── README.md ├── src │ ├── lib.rs │ └── utils.rs └── tests │ └── web.rs └── web ├── grpc ├── .gitignore ├── Cargo.toml ├── build.rs ├── proto │ └── helloworld.proto └── src │ ├── client.rs │ ├── main.rs │ └── server.rs └── yew-app ├── .gitignore ├── Cargo.toml ├── dist ├── index.html ├── yew-app-5fdf1eddf48554e7.js └── yew-app-5fdf1eddf48554e7_bg.wasm ├── index.html └── src └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Generated by Cargo 7 | # will have compiled files and executables 8 | debug/ 9 | target/ 10 | 11 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 12 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 13 | Cargo.lock 14 | 15 | # These are backup files generated by rustfmt 16 | **/*.rs.bk 17 | 18 | # MSVC Windows builds of rustc generate these, which store debugging information 19 | *.pdb 20 | -------------------------------------------------------------------------------- /01-basic/01-hello-world/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /01-basic/01-hello-world/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-rust" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/01-hello-world/README.md: -------------------------------------------------------------------------------- 1 | # Learn rust 2 | 3 | ## Bắt đầu một ứng dụng với rust 4 | 5 | ```bash 6 | cargo init 7 | ``` 8 | 9 | ## Hello world 10 | 11 | ```rust 12 | fn main() { 13 | println!("Hello, world!"); 14 | } 15 | ``` 16 | 17 | notes: 18 | 19 | - `fn` là keyword dùng để khởi tạo một hàm 20 | - `main` là tên của hàm. Chương trình rust luôn chạy hàm main đầu tiên 21 | - `println!` là `macro` dùng để in ra màn hình. Khái niệm `macro` sẽ được giới thiệu sau 22 | 23 | ### Để chạy ta dùng lệnh 24 | 25 | Check các thư viện và các file trong thư mục 26 | 27 | ```bash 28 | cargo check 29 | ``` 30 | 31 | Chạy chương trình 32 | 33 | ```bash 34 | cargo run 35 | ``` 36 | -------------------------------------------------------------------------------- /01-basic/01-hello-world/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("Hello, world!"); 3 | } 4 | 5 | -------------------------------------------------------------------------------- /01-basic/02-Var/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-basic" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/02-Var/README.md: -------------------------------------------------------------------------------- 1 | # Varibale 2 | 3 | Biến là nơi để chứa dữ liệu. 4 | 5 | Trong rust khai báo biến bằng keyword `let`. Mặc định khi khai báo sẽ là `immutable` (không thể thay đổi giá trị). 6 | 7 | ```rust 8 | fn main() { 9 | let x = 5; 10 | println!("The value of x is: {}", x); 11 | x = 6; 12 | println!("The value of x is: {}", x); 13 | } 14 | ``` 15 | -------------------------------------------------------------------------------- /01-basic/02-Var/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | #[allow(unused_doc_comments)] 4 | #[allow(unused_variables)] 5 | fn main() -> io::Result<()> { 6 | // Mặc định khi khai báo là immutable 7 | let _name = "Nguyen"; 8 | // Biến có thể thay đổi 9 | let _age = 21; 10 | // Hằng số 11 | let _time = 10; 12 | // const vs immutable 13 | /// * immutable có thể khai báo rồi gấn dữ liệu sau đó. 14 | /// * const khi khai báo phải gán luôn 15 | /// * cả 2 đều ko thể thay đổi giá trị. 16 | // Kiểu dữ iệu 17 | // Scalar: integer, float, char, bool 18 | // Compound: Array, Tuple, Slice 19 | let x = 10; // 20 | let xi16: i16 = 10; 21 | 22 | // array 23 | // kích thước cố định, các kiểu dữ liệu giống nhau, mặc định là immutable 24 | let arr: [i32; 3] = [1, 2, 3]; 25 | println!("{:?}", arr); 26 | let [a, b, c] = arr; // destructure array 27 | println!("a = {}", a); 28 | // Tuple 29 | // kích thước cố định, các kiểu dữ liệu khác nhau 30 | let tup: (i32, u64, &str) = (-10, 5, "a"); 31 | println!("{:?}", tup); 32 | 33 | // Slice 34 | let a: [i32; 4] = [1, 2, 3, 4]; // Parent Array 35 | let b: &[i32] = &a; // Slicing whole array 36 | let c = &a[0..4]; // From 0th position to 4th(excluding) 37 | let d = &a[..]; // Slicing whole array 38 | let e = &a[1..3]; // [2, 3] 39 | let f = &a[1..]; // [2, 3, 4] 40 | let g = &a[..3]; // [1, 2, 3] 41 | 42 | println!("{:?} {:?}", a, d); 43 | // String 44 | 45 | let mut fullName = String::from("Nguyen"); 46 | fullName.push_str(":)"); 47 | println!("{:?}", fullName); 48 | // Điều kiện 49 | // if else 50 | // match 51 | // Vòng lặp 52 | // loop 53 | // for 54 | // while 55 | 56 | println!("Hello,"); 57 | 58 | let org_arr = [1, 2, 3, 5, 6, 8, 10, 11]; 59 | let sub_arr = [6, 8, 10]; 60 | let leng = org_arr.len(); 61 | let mut i = 0; 62 | let mut check = false; 63 | while 1 == 1 { 64 | if (i > org_arr.len() - sub_arr.len() + 1) { 65 | break; 66 | } 67 | let tmp = &org_arr[i..i + sub_arr.len()]; 68 | i += 1; 69 | println!("{:?}", tmp); 70 | if tmp == sub_arr { 71 | println!("{:?}", tmp); 72 | println!("{:?}", sub_arr); 73 | println!("{}", tmp == sub_arr); 74 | check = true; 75 | break; 76 | } 77 | } 78 | if check { 79 | println!("YES"); 80 | } else { 81 | println!("NO"); 82 | } 83 | 84 | let input = "adbcdaDd"; 85 | let mut user_input = String::new(); 86 | let stdin = io::stdin(); // We get `Stdin` here. 87 | stdin.read_line(&mut user_input); 88 | 89 | println!("input {} ", user_input); 90 | 91 | Ok(()) 92 | 93 | } 94 | -------------------------------------------------------------------------------- /01-basic/03-loop/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-loop" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/03-loop/README.md: -------------------------------------------------------------------------------- 1 | # Loop 2 | 3 | Rust sử dụng những keyword `for`, `while`, `loop` để khởi tạo vòng lặp -------------------------------------------------------------------------------- /01-basic/03-loop/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut i = 0; 3 | 4 | for j in 0..10 { 5 | println!("i = {}", j) 6 | } 7 | 8 | // while loop 9 | while i < 3 { 10 | println!("i = {}", i); 11 | i += 1; 12 | } 13 | // infinitive loop 14 | 15 | loop { 16 | println!("i = {}", i); 17 | break; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /01-basic/04-if/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-if" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/04-if/README.md: -------------------------------------------------------------------------------- 1 | # If 2 | 3 | Khởi tạo điều kiện trong rust sử dụng `if` 4 | 5 | ```rust 6 | fn main() { 7 | let number = 3; 8 | 9 | if number < 5 { 10 | println!("condition was true"); 11 | } else { 12 | println!("condition was false"); 13 | } 14 | } 15 | ``` 16 | -------------------------------------------------------------------------------- /01-basic/04-if/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | if 7 % 2 == 0 { 3 | println!("7 is even"); 4 | } else { 5 | println!("7 is odd"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /01-basic/05-match/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-match" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/05-match/README.md: -------------------------------------------------------------------------------- 1 | # Match 2 | 3 | In Rust, the match keyword is used to perform a switch-like function. It is used to match a value against a series of patterns and execute code based on the first pattern that matches. The syntax is as follows: 4 | 5 | ```rust 6 | match variable { 7 | pattern1 => code1, 8 | pattern2 => code2, 9 | ... 10 | _ => code_default, 11 | } 12 | ``` 13 | 14 | The variable is the value that you want to match against the patterns. Each pattern is followed by an arrow (=>) and the code that should be executed if the pattern matches. The underscore \_ pattern acts as a default case, similar to the default case in a traditional switch statement. 15 | 16 | For example: 17 | 18 | ```rust 19 | let num = 5; 20 | match num { 21 | 1 => println!("one"), 22 | 2 => println!("two"), 23 | 3 => println!("three"), 24 | 4 => println!("four"), 25 | 5 => println!("five"), 26 | _ => println!("something else"), 27 | } 28 | ``` 29 | 30 | This will print "five" because 5 matches the fifth pattern. 31 | It is important to know that Rust's match statement is exhaustive, meaning that it will always match one of the patterns defined and will not fall through like a C-style switch statement. 32 | -------------------------------------------------------------------------------- /01-basic/05-match/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let num = 5; 3 | match num { 4 | 1 => println!("one"), 5 | 2 => println!("two"), 6 | 3 => println!("three"), 7 | 4 => println!("four"), 8 | 5 => println!("five"), 9 | _ => println!("something else"), 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /01-basic/06-func/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "func" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/06-func/README.md: -------------------------------------------------------------------------------- 1 | # Function 2 | 3 | Khởi tạo hàm trong rust sử dụng `fn` 4 | 5 | ```rust 6 | fn main() { 7 | another_function(5, 6); 8 | } 9 | ``` 10 | -------------------------------------------------------------------------------- /01-basic/06-func/src/main.rs: -------------------------------------------------------------------------------- 1 | fn hello_world() { 2 | println!("Hello, world!"); 3 | } 4 | 5 | fn add(a: i32, b: i32) -> i32 { 6 | a + b 7 | } 8 | 9 | fn print(s: &str) { 10 | println!("{}", s); 11 | } 12 | 13 | fn increment(x: &mut i32) { 14 | *x += 1; 15 | } 16 | 17 | 18 | fn main() { 19 | hello_world(); 20 | println!("1 + 2 = {}", add(1, 2)); 21 | print("Hello, world!"); 22 | 23 | let mut x = 1; 24 | increment(&mut x); 25 | println!("x = {}", x); 26 | } 27 | -------------------------------------------------------------------------------- /01-basic/course/leetcode/fizz-buzz.rs: -------------------------------------------------------------------------------- 1 | pub fn fizz_buzz(n: i32) -> Vec { 2 | let mut result = Vec::new(); 3 | for i in 1..=n { 4 | if i % 15 == 0 { 5 | result.push("FizzBuzz".to_string()); 6 | } else if i % 3 == 0 { 7 | result.push("Fizz".to_string()); 8 | } else if i % 5 == 0 { 9 | result.push("Buzz".to_string()); 10 | } else { 11 | result.push(i.to_string()); 12 | } 13 | } 14 | result 15 | } 16 | 17 | fn main() { 18 | println!("Hello, world!"); 19 | } 20 | -------------------------------------------------------------------------------- /01-basic/learn-array/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-array" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/learn-array/README.md: -------------------------------------------------------------------------------- 1 | Here is an example of declaring and initializing an array in Rust: 2 | 3 | ```rust 4 | let a = [1, 2, 3, 4, 5]; // array of 5 integers 5 | ``` 6 | You can also specify the type of the array elements, like this: 7 | 8 | 9 | ```rust 10 | let b: [i32; 5] = [1, 2, 3, 4, 5]; // array of 5 integers of type i32 11 | ``` 12 | 13 | You can also create an array by using the vec! macro: 14 | 15 | ```rust 16 | let c = vec![1, 2, 3, 4, 5]; // array of 5 integers 17 | ``` 18 | 19 | You can also access elements of an array using the indexing syntax: 20 | 21 | ```rust 22 | let d = [1, 2, 3, 4, 5]; 23 | println!("The third element is {}", d[2]); 24 | ``` 25 | 26 | You can iterate over an array using a for loop: 27 | 28 | ```rust 29 | let e = [1, 2, 3, 4, 5]; 30 | for i in e.iter() { 31 | println!("{}", i); 32 | } 33 | ``` 34 | 35 | You can also use the .len() method to get the length of an array 36 | 37 | ```rust 38 | let f = [1, 2, 3, 4, 5]; 39 | println!("The length of the array is: {}", f.len()); 40 | ``` 41 | 42 | Note that the indexing starts with 0 and the last index is len-1. 43 | -------------------------------------------------------------------------------- /01-basic/learn-array/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let e = [1, 2, 3, 4, 5]; 3 | for i in e.iter() { 4 | println!("{}", i); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /01-basic/learn-hashmap/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-hashmap" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/learn-hashmap/README.md: -------------------------------------------------------------------------------- 1 | # Hashmap 2 | 3 | Bạn có thể sử dụng thư viện `std::collections::HashMap` trong Rust để tạo một hashmap. Ví dụ như sau: 4 | 5 | ```rust 6 | use std::collections::HashMap; 7 | 8 | fn main() { 9 | let mut map = HashMap::new(); 10 | map.insert("Blue".to_string(), 10); 11 | map.insert("Yellow".to_string(), 50); 12 | 13 | for (key, value) in &map { 14 | println!("{}: {}", key, value); 15 | } 16 | } 17 | ``` 18 | -------------------------------------------------------------------------------- /01-basic/learn-hashmap/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | fn main() { 4 | let mut map = HashMap::new(); 5 | map.insert("Blue".to_string(), 10); 6 | map.insert("Yellow".to_string(), 50); 7 | map.insert("10".to_string(), 10); 8 | 9 | for (key, value) in &map { 10 | println!("{}: {}", key, value); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /01-basic/learn-lifetime/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-lifetime" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/learn-lifetime/src/main.rs: -------------------------------------------------------------------------------- 1 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { 2 | if x.len() > y.len() { 3 | x 4 | } else { 5 | y 6 | } 7 | } 8 | 9 | fn main() { 10 | let string1 = String::from("long string is long"); 11 | let string2 = String::from("short"); 12 | 13 | let result = longest(string1.as_str(), string2.as_str()); 14 | println!("The longest string is: {}", result); 15 | 16 | // destroy string1 and string2 17 | let s1; 18 | { 19 | s1 = string1.as_str(); 20 | println!("string1 is {}", s1); 21 | } 22 | println!("string1 is {}", s1); 23 | } 24 | -------------------------------------------------------------------------------- /01-basic/learn-ownership/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-ownership" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/learn-ownership/README.md: -------------------------------------------------------------------------------- 1 | # Rust ownership 2 | Rust has a unique ownership model that is designed to prevent data races and other forms of undefined behavior. 3 | 4 | Here's an example of how ownership works in Rust: 5 | 6 | ```rust 7 | let s = String::from("hello"); 8 | let t = s; 9 | 10 | println!("{}, {}", s, t); 11 | ``` 12 | 13 | 14 | In this example, the variable s is created and assigned the value "hello". Then, the variable t is created and assigned the value of s. 15 | 16 | After this, you will get an error if you try to use s again, because Rust considers s to be "moved" into t. This is because Rust assumes that the original variable is no longer needed, and it wants to ensure that the data it references is not accidentally used after it has been moved. 17 | 18 | In summary, in Rust variables have the ownership of the data and when the ownership is transferred from one variable to another, the previous owner is no longer valid and cannot be used further. 19 | 20 | 21 | In Rust, the & and * symbols are used in the context of references and pointers. 22 | 23 | A reference is a way to refer to some value without taking ownership of it. It is created using the & symbol. For example: 24 | 25 | ```rust 26 | let s = String::from("hello"); 27 | let r = &s; 28 | ``` 29 | In this example, r is a reference to the value of s. It points to the same memory location as s, but it does not own the data. The variable s is still valid and can be used as usual. 30 | 31 | A pointer, on the other hand, is a way to refer to some value by its memory address. It is created using the * symbol. For example: 32 | 33 | ```rust 34 | let s = String::from("hello"); 35 | let p = &s as *const String; 36 | ``` 37 | In this example, p is a pointer to the value of s. It contains the memory address of s, rather than the value itself. Pointers can be dereferenced using the * symbol to access the value they point to. 38 | 39 | It's important to notice that when using pointers, you must ensure that the memory they point to is valid, otherwise you'll get a runtime error. Rust uses a pointer type Option> to handle null or dangling pointer. 40 | 41 | In summary, & is used for creating references and * is used for creating pointers. Both references and pointers allow you to refer to a value without taking ownership of it, but they have different behaviors and uses. -------------------------------------------------------------------------------- /01-basic/learn-ownership/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut num = 10; 3 | println!("num = {}, {:p}", num, &num); 4 | change_v1(num); 5 | change_v2(&mut num); 6 | 7 | let s = String::from("hello"); 8 | let r = &s as *const String; 9 | let s2 = unsafe { &*r }; 10 | let s3 = unsafe { &*r }; 11 | 12 | println!("s = {}, {:p}", s, &s); 13 | println!("r =, {:p}", r); 14 | println!("S2 ={}, {:p}", s2, &s2); 15 | println!("S3 ={}, {:p}", s3, &s3); 16 | } 17 | fn change_v1(num: i32) { 18 | println!("num = {}, {:p}", num, &num); 19 | } 20 | fn change_v2(num: &mut i32) { 21 | *num = 100; 22 | println!("num = {:p}", num); 23 | } 24 | -------------------------------------------------------------------------------- /01-basic/learn-primitives/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-primitives" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/learn-primitives/README.md: -------------------------------------------------------------------------------- 1 | # Các kiểu dữ liệu 2 | 3 | ## Kiểu dữ liệu nguyên thủy (primitives) 4 | 5 | signed integers: i8, i16, i32, i64, i128 and isize (pointer size) 6 | 7 | unsigned integers: u8, u16, u32, u64, u128 and usize (pointer size) 8 | 9 | floating point: f32, f64 10 | 11 | char Unicode scalar values like 'a', 'α' and '∞' (4 bytes each) 12 | 13 | bool either true or false 14 | 15 | and the unit type (), whose only possible value is an empty tuple: () 16 | 17 | Despite the value of a unit type being a tuple, it is not considered a compound type because it does not contain multiple values. 18 | 19 | ## Kiểu dữ liệu phức tạp (compound) 20 | 21 | arrays like [1, 2, 3] 22 | 23 | tuples like (1, true) -------------------------------------------------------------------------------- /01-basic/learn-primitives/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // Variables can be type annotated. 3 | let logical: bool = true; 4 | 5 | let a_float: f64 = 1.0; // Regular annotation 6 | let an_integer = 5i32; // Suffix annotation 7 | 8 | // Or a default will be used. 9 | let default_float = 3.0; // `f64` 10 | let default_integer = 7; // `i32` 11 | 12 | // A type can also be inferred from context 13 | let mut inferred_type = 12; // Type i64 is inferred from another line 14 | inferred_type = 4294967296i64; 15 | 16 | // A mutable variable's value can be changed. 17 | let mut mutable = 12; // Mutable `i32` 18 | mutable = 21; 19 | 20 | // Error! The type of a variable can't be changed. 21 | // mutable = true; 22 | 23 | // Variables can be overwritten with shadowing. 24 | let mutable = true; 25 | } 26 | -------------------------------------------------------------------------------- /01-basic/learn-slice/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-slice" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/learn-slice/README.md: -------------------------------------------------------------------------------- 1 | In Rust, a "slice" is a reference to a contiguous section of an array. It's represented by the &[T] type, where T is the type of the element in the array. 2 | 3 | Here's an example of creating a slice from an array: 4 | 5 | ```rust 6 | let a = [1, 2, 3, 4, 5]; 7 | let b = &a[1..4]; // b is a slice of the elements at index 1, 2, and 3 8 | ``` 9 | You can also create a slice from a vector using the &vec[start..end] syntax: 10 | 11 | ```rust 12 | let c = vec![1, 2, 3, 4, 5]; 13 | let d = &c[1..4]; // d is a slice of the elements at index 1, 2, and 3 14 | ``` 15 | You can iterate over a slice using a for loop: 16 | 17 | ```rust 18 | let e = &[1, 2, 3, 4, 5][1..4]; 19 | for i in e.iter() { 20 | println!("{}", i); 21 | } 22 | ``` 23 | You can also use the .len() method to get the length of a slice: 24 | 25 | ```rust 26 | let f = &[1, 2, 3, 4, 5][1..4]; 27 | println!("The length of the slice is: {}", f.len()); 28 | ``` 29 | Slices are useful when you need to pass a portion of an array or vector to a function without creating a new copy of the data. The original array or vector retains ownership of the data and the slice is a "view" into that data. -------------------------------------------------------------------------------- /01-basic/learn-slice/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let e = &[1, 2, 3, 4, 5][1..4]; 3 | for i in e.iter() { 4 | println!("{}", i); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /01-basic/learn-thread/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-thread" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/learn-thread/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/npv2k1/learn-rust/3b84b71577d6a11b67a0f582132e22f8e658714d/01-basic/learn-thread/README.md -------------------------------------------------------------------------------- /01-basic/learn-thread/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::sync::mpsc; 2 | use std::thread; 3 | use std::time::Duration; 4 | 5 | fn learn_chanel() { 6 | fn main() { 7 | let (tx, rx) = mpsc::channel(); 8 | 9 | tx.send(10).unwrap(); 10 | tx.send(20).unwrap(); 11 | 12 | println!("Received: {:?}", rx.recv()); 13 | println!("Received: {:?}", rx.recv()); 14 | 15 | let tx2 = tx.clone(); 16 | tx2.send(30).unwrap(); 17 | println!("Received: {:?}", rx.recv()); 18 | } 19 | } 20 | 21 | fn unbounded_chanel() { 22 | let (tx, rx) = mpsc::channel(); 23 | 24 | thread::spawn(move || { 25 | let thread_id = thread::current().id(); 26 | for i in 1..10 { 27 | tx.send(format!("Message {i}")).unwrap(); 28 | println!("{thread_id:?}: sent Message {i}"); 29 | } 30 | println!("{thread_id:?}: done"); 31 | }); 32 | thread::sleep(Duration::from_millis(100)); 33 | 34 | for msg in rx.iter() { 35 | println!("Main: got {}", msg); 36 | } 37 | } 38 | 39 | fn main() { 40 | thread::spawn(|| { 41 | for i in 1..10 { 42 | println!("Count in thread: {i}!"); 43 | thread::sleep(Duration::from_millis(5)); 44 | } 45 | }); 46 | 47 | for i in 1..5 { 48 | println!("Main thread: {i}"); 49 | thread::sleep(Duration::from_millis(5)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /01-basic/learn-trait/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-trait" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/learn-trait/src/main.rs: -------------------------------------------------------------------------------- 1 | // Khai báo một enum với các giá trị ShapeType 2 | enum ShapeType { 3 | Circle, 4 | Square, 5 | Triangle, 6 | } 7 | 8 | // Khai báo struct Shape với thuộc tính shape_type 9 | struct Shape { 10 | shape_type: ShapeType, 11 | } 12 | 13 | // Khai báo một trait với phương thức calculate_area 14 | trait CalculateArea { 15 | fn calculate_area(&self) -> f64; 16 | } 17 | 18 | // Implement trait CalculateArea cho struct Shape 19 | impl CalculateArea for Shape { 20 | fn calculate_area(&self) -> f64 { 21 | match self.shape_type { 22 | ShapeType::Circle => 3.14 * 10.0 * 10.0, 23 | ShapeType::Square => 20.0 * 20.0, 24 | ShapeType::Triangle => 0.5 * 20.0 * 30.0, 25 | } 26 | } 27 | } 28 | 29 | type TypeShape = Shape; 30 | 31 | fn main() { 32 | // Khởi tạo một struct Shape với shape_type là Circle 33 | let shape = Shape { 34 | shape_type: ShapeType::Circle, 35 | }; 36 | 37 | // Sử dụng trait CalculateArea cho struct Shape 38 | 39 | println!("Diện tích hình là: {}", ::calculate_area(&shape)); 40 | } 41 | -------------------------------------------------------------------------------- /01-basic/learn_struct/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn_struct" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/learn_struct/src/main.rs: -------------------------------------------------------------------------------- 1 | 2 | #[derive(Debug, Copy, Clone)] 3 | struct Point { 4 | x: f64, 5 | y: f64, 6 | } 7 | 8 | impl Point { 9 | pub fn length (&self) -> f64 { 10 | (self.x * self.x + self.y * self.y).sqrt() 11 | } 12 | 13 | pub fn distance (&self, other: &Point) -> f64 { 14 | let dx = self.x - other.x; 15 | let dy = self.y - other.y; 16 | (dx * dx + dy * dy).sqrt() 17 | } 18 | } 19 | 20 | 21 | 22 | fn main() { 23 | let a = Point { x: 3.0, y: 4.0 }; 24 | println!("length of a is {}", a.length()); 25 | let b = Point { x: 5.0, y: 12.0 }; 26 | println!("distance between a and b is {}", a.distance(&b)); 27 | 28 | println!("point a: {:?}", a); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /01-basic/stdin/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stdin" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/stdin/README.md: -------------------------------------------------------------------------------- 1 | # Nhập xuất cơ bản 2 | 3 | Để nhập một mảng số nguyên từ bàn phím, bạn có thể sử dụng hàm read_line() để nhập một dòng văn bản, sau đó sử dụng hàm split_whitespace() để tách chuỗi văn bản thành các phần tử cách nhau bởi khoảng trắng. Sau đó, bạn có thể dùng hàm parse() của str để chuyển các phần tử này thành các số nguyên. 4 | 5 | ```rust 6 | use std::io; 7 | 8 | fn main() { 9 | println!("Nhập một mảng số nguyên cách nhau bởi khoảng trắng: "); 10 | let mut input = String::new(); 11 | io::stdin().read_line(&mut input).expect("Không thể đọc dòng văn bản"); 12 | let numbers: Vec = input 13 | .split_whitespace() 14 | .map(|s| s.parse().expect("Không thể chuyển đổi thành số")) 15 | .collect(); 16 | println!("Mảng số nguyên: {:?}", numbers); 17 | } 18 | ``` 19 | -------------------------------------------------------------------------------- /01-basic/stdin/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | use std::{io, str::FromStr}; 4 | 5 | fn read_string() -> String { 6 | println!("Nhập một dòng văn bản: "); 7 | let mut input = String::new(); 8 | io::stdin() 9 | .read_line(&mut input) 10 | .expect("Không thể đọc dòng văn bản"); 11 | return input; 12 | } 13 | 14 | fn read_array() -> Vec 15 | where 16 | T: FromStr, 17 | ::Err: std::fmt::Debug, 18 | { 19 | println!("Nhập một mảng số cách nhau bởi khoảng trắng: "); 20 | let mut input = String::new(); 21 | io::stdin().read_line(&mut input).expect("Không thể đọc dòng văn bản"); 22 | input 23 | .split_whitespace() 24 | .map(|s| s.parse().expect("Không thể chuyển đổi thành số")) 25 | .collect() 26 | } 27 | 28 | fn main() { 29 | let numbers = read_array::(); 30 | println!("Mảng số nguyên: {:?}", numbers); 31 | } 32 | -------------------------------------------------------------------------------- /01-basic/vec/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vec" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /01-basic/vec/src/main.rs: -------------------------------------------------------------------------------- 1 | fn sample_vec(){ 2 | let mut arr = Vec::new(); 3 | for i in 1..10 { 4 | arr.push(i); 5 | } 6 | println!("{:?}", arr); 7 | } 8 | 9 | fn main() { 10 | sample_vec(); 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Learn rust 2 | 3 | Rust là một ngôn ngữ lập trình mã nguồn mở, có thể chạy trên nhiều hệ điều hành và nền tảng. Nó được thiết kế để tạo ra mã độc lập và an toàn, với ưu điểm về hiệu suất cao. 4 | 5 | Tính năng khác biệt của rust là cách quản lý bộ nhớ. 6 | 7 | ## Cài đặt 8 | 9 | ### Linux 10 | 11 | ```bash 12 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 13 | ``` 14 | 15 | ## Rust với blockchain 16 | 17 | Rust được sử dụng nhiều trong lập trình blockchain. Rust có thể được dùng để viết core blockchain hoặc smart contract. 18 | 19 | Một số ví dụ: 20 | 21 | - substrate 22 | - solana 23 | - near 24 | 25 | ## Rust với web 26 | 27 | rust có thể dùng để lập trình web frontend với webassembly 28 | 29 | 30 | ## Cheatsheet 31 | 32 | Rust cheatsheet 33 | - https://cheats.rs/ 34 | - https://quickref.me/rust 35 | 36 | 37 | -------------------------------------------------------------------------------- /build-own-x/lang-vm/iridium/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /build-own-x/lang-vm/iridium/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iridium" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /build-own-x/lang-vm/iridium/src/instruction.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, PartialEq)] 2 | pub enum Opcode { 3 | LOAD, 4 | ADD, 5 | SUB, 6 | MUL, 7 | DIV, 8 | HLT, 9 | JMP, 10 | IGL, 11 | JMPF 12 | } 13 | 14 | impl From for Opcode { 15 | fn from(v: u8) -> Self { 16 | match v { 17 | 0 => return Opcode::HLT, 18 | _ => return Opcode::IGL, 19 | } 20 | } 21 | } 22 | 23 | #[derive(Debug, PartialEq)] 24 | pub struct Instruction { 25 | opcode: Opcode, 26 | } 27 | 28 | impl Instruction { 29 | pub fn new(opcode: Opcode) -> Instruction { 30 | Instruction { opcode: opcode } 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::*; 37 | 38 | #[test] 39 | fn test_create_hlt() { 40 | let opcode = Opcode::HLT; 41 | assert_eq!(opcode, Opcode::HLT); 42 | } 43 | 44 | #[test] 45 | fn test_create_instruction() { 46 | let instruction = Instruction::new(Opcode::HLT); 47 | assert_eq!(instruction.opcode, Opcode::HLT); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /build-own-x/lang-vm/iridium/src/main.rs: -------------------------------------------------------------------------------- 1 | pub mod instruction; 2 | pub mod vm; 3 | 4 | pub mod repl; 5 | 6 | fn main() { 7 | let mut repl = repl::REPL::new(); 8 | repl.run(); 9 | } 10 | -------------------------------------------------------------------------------- /build-own-x/lang-vm/iridium/src/repl/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::vm::VM; 2 | use std; 3 | use std::io; 4 | use std::io::Write; 5 | 6 | /// Core structure for the REPL for the Assembler 7 | pub struct REPL { 8 | command_buffer: Vec, 9 | // The VM the REPL will use to execute code 10 | vm: VM, 11 | } 12 | 13 | impl REPL { 14 | /// Creates and returns a new assembly REPL 15 | pub fn new() -> REPL { 16 | REPL { 17 | vm: VM::new(), 18 | command_buffer: vec![], 19 | } 20 | } 21 | 22 | pub fn run(&mut self) { 23 | println!("Welcome to Iridium! Let's be productive!"); 24 | loop { 25 | // This allocates a new String in which to store whatever the user types each iteration. 26 | // TODO: Figure out how create this outside of the loop and re-use it every iteration 27 | let mut buffer = String::new(); 28 | 29 | // Blocking call until the user types in a command 30 | let stdin = io::stdin(); 31 | 32 | // Annoyingly, `print!` does not automatically flush stdout like `println!` does, so we 33 | // have to do that there for the user to see our `>>> ` prompt. 34 | print!(">>> "); 35 | io::stdout().flush().expect("Unable to flush stdout"); 36 | 37 | // Here we'll look at the string the user gave us. 38 | stdin 39 | .read_line(&mut buffer) 40 | .expect("Unable to read line from user"); 41 | let buffer = buffer.trim(); 42 | 43 | // This is the line we add to store a copy of each command 44 | self.command_buffer.push(buffer.to_string()); 45 | 46 | match buffer { 47 | ".quit" => { 48 | println!("Farewell! Have a great day!"); 49 | std::process::exit(0); 50 | } 51 | ".history" => { 52 | for command in &self.command_buffer { 53 | println!("{}", command); 54 | } 55 | } 56 | ".program" => { 57 | println!("Listing instructions currently in VM's program vector:"); 58 | for instruction in &self.vm.program { 59 | println!("{}", instruction); 60 | } 61 | println!("End of Program Listing"); 62 | } 63 | ".registers" => { 64 | println!("Listing registers and all contents:"); 65 | println!("{:#?}", self.vm.registers); 66 | println!("End of Register Listing") 67 | } 68 | _ => { 69 | println!("Invalid input"); 70 | } 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /build-own-x/lang-vm/iridium/src/vm.rs: -------------------------------------------------------------------------------- 1 | use crate::instruction::Opcode; 2 | 3 | // Khai báo struct của máy ảo 4 | pub struct VM { 5 | registers: [i32; 32], // Khai báo thanh ghi là một mảng kiểu i32 kích thược 32 phần tử 6 | pc: usize, // pc để đếm chương trình 7 | program: Vec, // Khai báo chương trình 8 | remainder: u32, // Khai báo thanh nhớ 9 | equal_flag: bool, 10 | } 11 | 12 | impl VM { 13 | // Khởi tạo 1 vm mới 14 | pub fn new() -> VM { 15 | VM { 16 | registers: [0; 32], 17 | program: vec![], 18 | pc: 0, 19 | remainder: 0, 20 | equal_flag: false, 21 | } 22 | } 23 | /// Loops as long as instructions can be executed. 24 | pub fn run(&mut self) { 25 | let mut is_done = false; 26 | while !is_done { 27 | is_done = self.execute_instruction(); 28 | } 29 | } 30 | 31 | /// Executes one instruction. Meant to allow for more controlled execution of the VM 32 | pub fn run_once(&mut self) { 33 | self.execute_instruction(); 34 | } 35 | 36 | fn execute_instruction(&mut self) -> bool { 37 | if self.pc >= self.program.len() { 38 | return false; 39 | } 40 | match self.decode_opcode() { 41 | Opcode::LOAD => { 42 | let register = self.next_8_bits() as usize; 43 | let number = self.next_16_bits() as u32; 44 | self.registers[register] = number as i32; 45 | } 46 | Opcode::HLT => { 47 | println!("HLT encountered"); 48 | return false; 49 | } 50 | Opcode::IGL => { 51 | return true; 52 | } 53 | Opcode::ADD => { 54 | let register1 = self.registers[self.next_8_bits() as usize]; 55 | let register2 = self.registers[self.next_8_bits() as usize]; 56 | self.registers[self.next_8_bits() as usize] = register1 + register2; 57 | } 58 | Opcode::SUB => { 59 | let register1 = self.registers[self.next_8_bits() as usize]; 60 | let register2 = self.registers[self.next_8_bits() as usize]; 61 | self.registers[self.next_8_bits() as usize] = register1 - register2; 62 | } 63 | Opcode::MUL => { 64 | let register1 = self.registers[self.next_8_bits() as usize]; 65 | let register2 = self.registers[self.next_8_bits() as usize]; 66 | self.registers[self.next_8_bits() as usize] = register1 * register2; 67 | } 68 | Opcode::DIV => { 69 | let register1 = self.registers[self.next_8_bits() as usize]; 70 | let register2 = self.registers[self.next_8_bits() as usize]; 71 | self.registers[self.next_8_bits() as usize] = register1 / register2; 72 | self.remainder = (register1 % register2) as u32; 73 | } 74 | Opcode::JMP => { 75 | let target = self.registers[self.next_8_bits() as usize]; 76 | self.pc = target as usize; 77 | } 78 | Opcode::JMPF => { 79 | let value = self.registers[self.next_8_bits() as usize]; 80 | self.pc += value as usize; 81 | } 82 | } 83 | true 84 | } 85 | fn decode_opcode(&mut self) -> Opcode { 86 | let opcode = Opcode::from(self.program[self.pc]); 87 | self.pc += 1; 88 | return opcode; 89 | } 90 | fn next_8_bits(&mut self) -> u8 { 91 | let result = self.program[self.pc]; 92 | self.pc += 1; 93 | return result; 94 | } 95 | 96 | fn next_16_bits(&mut self) -> u16 { 97 | let result = ((self.program[self.pc] as u16) << 8) | self.program[self.pc + 1] as u16; 98 | self.pc += 2; 99 | return result; 100 | } 101 | } 102 | 103 | #[cfg(test)] 104 | mod tests { 105 | use super::*; 106 | 107 | #[test] 108 | fn test_create_vm() { 109 | let test_vm = VM::new(); 110 | assert_eq!(test_vm.registers[0], 0) 111 | } 112 | 113 | #[test] 114 | fn test_opcode_hlt() { 115 | let mut test_vm = VM::new(); 116 | let test_bytes = vec![0, 0, 0, 0]; 117 | test_vm.program = test_bytes; 118 | test_vm.run(); 119 | assert_eq!(test_vm.pc, 1); 120 | } 121 | 122 | #[test] 123 | fn test_opcode_igl() { 124 | let mut test_vm = VM::new(); 125 | let test_bytes = vec![200, 0, 0, 0]; 126 | test_vm.program = test_bytes; 127 | test_vm.run(); 128 | assert_eq!(test_vm.pc, 1); 129 | } 130 | 131 | #[test] 132 | fn test_load_opcode() { 133 | let mut test_vm = VM::new(); 134 | test_vm.program = vec![0, 0, 1, 244]; // Remember, this is how we represent 500 using two u8s in little endian format 135 | test_vm.run(); 136 | assert_eq!(test_vm.registers[0], 500); 137 | } 138 | #[test] 139 | fn test_jmp_opcode() { 140 | let mut test_vm = VM::new(); 141 | test_vm.registers[0] = 1; 142 | test_vm.program = vec![7, 0, 0, 0]; 143 | test_vm.run_once(); 144 | assert_eq!(test_vm.pc, 1); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /build-own-x/shell/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "shell" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /build-own-x/shell/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | env, 3 | io::{stdin, stdout, Write}, 4 | path::Path, 5 | process::{Child, Command, Stdio}, 6 | }; 7 | 8 | fn main() { 9 | loop { 10 | print!("> "); 11 | stdout().flush(); 12 | 13 | let mut input = String::new(); 14 | stdin().read_line(&mut input).unwrap(); 15 | 16 | // must be peekable so we know when we are on the last command 17 | let mut commands = input.trim().split(" | ").peekable(); 18 | let mut previous_command = None; 19 | 20 | while let Some(command) = commands.next() { 21 | let mut parts = command.trim().split_whitespace(); 22 | let command = parts.next().unwrap(); 23 | let args = parts; 24 | 25 | match command { 26 | "cd" => { 27 | let new_dir = args.peekable().peek().map_or("/", |x| *x); 28 | let root = Path::new(new_dir); 29 | if let Err(e) = env::set_current_dir(&root) { 30 | eprintln!("{}", e); 31 | } 32 | 33 | previous_command = None; 34 | } 35 | "exit" => return, 36 | command => { 37 | let stdin = previous_command.map_or(Stdio::inherit(), |output: Child| { 38 | Stdio::from(output.stdout.unwrap()) 39 | }); 40 | 41 | let stdout = if commands.peek().is_some() { 42 | // there is another command piped behind this one 43 | // prepare to send output to the next command 44 | Stdio::piped() 45 | } else { 46 | // there are no more commands piped behind this one 47 | // send output to shell stdout 48 | Stdio::inherit() 49 | }; 50 | 51 | let output = Command::new(command) 52 | .args(args) 53 | .stdin(stdin) 54 | .stdout(stdout) 55 | .spawn(); 56 | 57 | match output { 58 | Ok(output) => { 59 | previous_command = Some(output); 60 | } 61 | Err(e) => { 62 | previous_command = None; 63 | eprintln!("{}", e); 64 | } 65 | }; 66 | } 67 | } 68 | } 69 | 70 | if let Some(mut final_command) = previous_command { 71 | // block until the final command has finished 72 | final_command.wait(); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /cargo/README.md: -------------------------------------------------------------------------------- 1 | # Cargo 2 | 3 | ## cargo command là gì? 4 | 5 | Cargo là trình quản lý gói (package manager) mặc định cho ngôn ngữ lập trình Rust. Nó cung cấp một số câu lệnh để quản lý các gói (packages) và các thư viện được sử dụng trong dự án của bạn, chẳng hạn như cài đặt, cập nhật, và xóa các gói. 6 | 7 | ## Các lệnh sử dụng với cargo 8 | 9 | Một số lệnh thường sử dụng với Cargo là: 10 | 11 | `cargo new`: Tạo một dự án mới với cấu trúc mẫu cơ bản. 12 | 13 | `cargo build`: Biên dịch và xây dựng dự án. 14 | 15 | `cargo run`: Biên dịch và chạy chương trình chính của dự án. 16 | 17 | `cargo check`: Kiểm tra tính hợp lệ của dự án mà không biên dịch nó. 18 | 19 | `cargo test`: Chạy các bài kiểm tra trong dự án. 20 | 21 | `cargo update`: Cập nhật các gói đã cài đặt trong dự án. 22 | 23 | `cargo add`: Thêm một gói vào dự án. 24 | 25 | `cargo remove`: Xóa một gói khỏi dự án. 26 | 27 | `cargo doc`: Tạo tài liệu cho dự án và các gói đã cài đặt. 28 | 29 | `cargo package`: Tạo một gói có thể được phân phối cho các lập trình viên khác sử dụng. 30 | 31 | `cargo publish`: Đăng gói lên trung tâm chứa gói của Rust (crates.io). 32 | 33 | `cargo clean`: Xóa các tập tin tạm thời và tập tin được tạo ra bởi quá trình xây dựng. 34 | -------------------------------------------------------------------------------- /design-pattent/memento-pattent/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memento-pattent" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /design-pattent/memento-pattent/README.md: -------------------------------------------------------------------------------- 1 | # Memento pattent 2 | -------------------------------------------------------------------------------- /design-pattent/memento-pattent/src/editor.rs: -------------------------------------------------------------------------------- 1 | use crate::editorstate::EditorState; 2 | pub(crate) struct Editor { 3 | content: String, 4 | } 5 | 6 | impl Editor { 7 | pub fn new() -> Self { 8 | Self { 9 | content: String::new(), 10 | } 11 | } 12 | pub fn create_state(&self) -> EditorState { 13 | EditorState::new(self.content.clone()) 14 | } 15 | pub fn restore(&mut self, state: EditorState) { 16 | self.content = state.get_content().clone(); 17 | } 18 | pub fn get_content(&self) -> &String { 19 | &self.content 20 | } 21 | pub fn set_content(&mut self, content: String) { 22 | self.content = content; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /design-pattent/memento-pattent/src/editorstate.rs: -------------------------------------------------------------------------------- 1 | pub(crate) struct EditorState { 2 | content: String, 3 | } 4 | impl EditorState { 5 | pub fn new(content: String) -> Self { 6 | Self { content } 7 | } 8 | pub fn get_content(&self) -> &String { 9 | &self.content 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /design-pattent/memento-pattent/src/history.rs: -------------------------------------------------------------------------------- 1 | use crate::editorstate::EditorState; 2 | pub(crate) struct History { 3 | states: Vec, 4 | } 5 | impl History { 6 | pub fn new() -> Self { 7 | Self { states: Vec::new() } 8 | } 9 | pub fn push(&mut self, state: EditorState) { 10 | self.states.push(state); 11 | } 12 | pub fn pop(&mut self) -> Option { 13 | self.states.pop() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /design-pattent/memento-pattent/src/main.rs: -------------------------------------------------------------------------------- 1 | pub mod editor; 2 | pub mod editorstate; 3 | pub mod history; 4 | 5 | fn main() { 6 | let mut editor = editor::Editor::new(); 7 | let mut history = history::History::new(); 8 | 9 | editor.set_content(String::from("a")); 10 | history.push(editor.create_state()); 11 | 12 | editor.set_content(String::from("b")); 13 | history.push(editor.create_state()); 14 | 15 | editor.set_content(String::from("c")); 16 | editor.restore(history.pop().unwrap()); 17 | 18 | println!("{}", editor.get_content()); 19 | } 20 | -------------------------------------------------------------------------------- /learn-wasm/.appveyor.yml: -------------------------------------------------------------------------------- 1 | install: 2 | - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe 3 | - if not defined RUSTFLAGS rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly 4 | - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin 5 | - rustc -V 6 | - cargo -V 7 | 8 | build: false 9 | 10 | test_script: 11 | - cargo test --locked 12 | -------------------------------------------------------------------------------- /learn-wasm/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | bin/ 5 | pkg/ 6 | wasm-pack.log 7 | -------------------------------------------------------------------------------- /learn-wasm/.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | sudo: false 3 | 4 | cache: cargo 5 | 6 | matrix: 7 | include: 8 | 9 | # Builds with wasm-pack. 10 | - rust: beta 11 | env: RUST_BACKTRACE=1 12 | addons: 13 | firefox: latest 14 | chrome: stable 15 | before_script: 16 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 17 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 18 | - cargo install-update -a 19 | - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f 20 | script: 21 | - cargo generate --git . --name testing 22 | # Having a broken Cargo.toml (in that it has curlies in fields) anywhere 23 | # in any of our parent dirs is problematic. 24 | - mv Cargo.toml Cargo.toml.tmpl 25 | - cd testing 26 | - wasm-pack build 27 | - wasm-pack test --chrome --firefox --headless 28 | 29 | # Builds on nightly. 30 | - rust: nightly 31 | env: RUST_BACKTRACE=1 32 | before_script: 33 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 34 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 35 | - cargo install-update -a 36 | - rustup target add wasm32-unknown-unknown 37 | script: 38 | - cargo generate --git . --name testing 39 | - mv Cargo.toml Cargo.toml.tmpl 40 | - cd testing 41 | - cargo check 42 | - cargo check --target wasm32-unknown-unknown 43 | - cargo check --no-default-features 44 | - cargo check --target wasm32-unknown-unknown --no-default-features 45 | - cargo check --no-default-features --features console_error_panic_hook 46 | - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook 47 | - cargo check --no-default-features --features "console_error_panic_hook wee_alloc" 48 | - cargo check --target wasm32-unknown-unknown --no-default-features --features "console_error_panic_hook wee_alloc" 49 | 50 | # Builds on beta. 51 | - rust: beta 52 | env: RUST_BACKTRACE=1 53 | before_script: 54 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 55 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 56 | - cargo install-update -a 57 | - rustup target add wasm32-unknown-unknown 58 | script: 59 | - cargo generate --git . --name testing 60 | - mv Cargo.toml Cargo.toml.tmpl 61 | - cd testing 62 | - cargo check 63 | - cargo check --target wasm32-unknown-unknown 64 | - cargo check --no-default-features 65 | - cargo check --target wasm32-unknown-unknown --no-default-features 66 | - cargo check --no-default-features --features console_error_panic_hook 67 | - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook 68 | # Note: no enabling the `wee_alloc` feature here because it requires 69 | # nightly for now. 70 | -------------------------------------------------------------------------------- /learn-wasm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "learn-wasm" 3 | version = "0.1.0" 4 | authors = ["Phạm Văn Nguyên "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.6", optional = true } 21 | 22 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 23 | # compared to the default allocator's ~10K. It is slower than the default 24 | # allocator, however. 25 | wee_alloc = { version = "0.4.5", optional = true } 26 | 27 | [dev-dependencies] 28 | wasm-bindgen-test = "0.3.13" 29 | 30 | [profile.release] 31 | # Tell `rustc` to optimize for small code size. 32 | opt-level = "s" 33 | -------------------------------------------------------------------------------- /learn-wasm/LICENSE_APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /learn-wasm/LICENSE_MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Phạm Văn Nguyên 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /learn-wasm/Makefile: -------------------------------------------------------------------------------- 1 | build: 2 | wasm-pack build 3 | -------------------------------------------------------------------------------- /learn-wasm/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

wasm-pack-template

4 | 5 | A template for kick starting a Rust and WebAssembly project using wasm-pack. 6 | 7 |

8 | Build Status 9 |

10 | 11 |

12 | Tutorial 13 | | 14 | Chat 15 |

16 | 17 | Built with 🦀🕸 by The Rust and WebAssembly Working Group 18 |
19 | 20 | ## About 21 | 22 | [**📚 Read this template tutorial! 📚**][template-docs] 23 | 24 | This template is designed for compiling Rust libraries into WebAssembly and 25 | publishing the resulting package to NPM. 26 | 27 | Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other 28 | templates and usages of `wasm-pack`. 29 | 30 | [tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html 31 | [template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html 32 | 33 | ## 🚴 Usage 34 | 35 | ### 🐑 Use `cargo generate` to Clone this Template 36 | 37 | [Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate) 38 | 39 | ``` 40 | cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project 41 | cd my-project 42 | ``` 43 | 44 | ### 🛠️ Build with `wasm-pack build` 45 | 46 | ``` 47 | wasm-pack build 48 | ``` 49 | 50 | ### 🔬 Test in Headless Browsers with `wasm-pack test` 51 | 52 | ``` 53 | wasm-pack test --headless --firefox 54 | ``` 55 | 56 | ### 🎁 Publish to NPM with `wasm-pack publish` 57 | 58 | ``` 59 | wasm-pack publish 60 | ``` 61 | 62 | ## 🔋 Batteries Included 63 | 64 | * [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating 65 | between WebAssembly and JavaScript. 66 | * [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook) 67 | for logging panic messages to the developer console. 68 | * [`wee_alloc`](https://github.com/rustwasm/wee_alloc), an allocator optimized 69 | for small code size. 70 | * `LICENSE-APACHE` and `LICENSE-MIT`: most Rust projects are licensed this way, so these are included for you 71 | 72 | ## License 73 | 74 | Licensed under either of 75 | 76 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 77 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 78 | 79 | at your option. 80 | 81 | ### Contribution 82 | 83 | Unless you explicitly state otherwise, any contribution intentionally 84 | submitted for inclusion in the work by you, as defined in the Apache-2.0 85 | license, shall be dual licensed as above, without any additional terms or 86 | conditions. -------------------------------------------------------------------------------- /learn-wasm/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod utils; 2 | 3 | use wasm_bindgen::prelude::*; 4 | 5 | // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global 6 | // allocator. 7 | #[cfg(feature = "wee_alloc")] 8 | #[global_allocator] 9 | static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; 10 | 11 | #[wasm_bindgen] 12 | extern { 13 | fn alert(s: &str); 14 | } 15 | 16 | #[wasm_bindgen] 17 | pub fn greet() { 18 | alert("Hello, learn-wasm!"); 19 | } 20 | -------------------------------------------------------------------------------- /learn-wasm/src/utils.rs: -------------------------------------------------------------------------------- 1 | pub fn set_panic_hook() { 2 | // When the `console_error_panic_hook` feature is enabled, we can call the 3 | // `set_panic_hook` function at least once during initialization, and then 4 | // we will get better error messages if our code ever panics. 5 | // 6 | // For more details see 7 | // https://github.com/rustwasm/console_error_panic_hook#readme 8 | #[cfg(feature = "console_error_panic_hook")] 9 | console_error_panic_hook::set_once(); 10 | } 11 | -------------------------------------------------------------------------------- /learn-wasm/tests/web.rs: -------------------------------------------------------------------------------- 1 | //! Test suite for the Web and headless browsers. 2 | 3 | #![cfg(target_arch = "wasm32")] 4 | 5 | extern crate wasm_bindgen_test; 6 | use wasm_bindgen_test::*; 7 | 8 | wasm_bindgen_test_configure!(run_in_browser); 9 | 10 | #[wasm_bindgen_test] 11 | fn pass() { 12 | assert_eq!(1 + 1, 2); 13 | } 14 | -------------------------------------------------------------------------------- /web/grpc/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /web/grpc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-ownership" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | [[bin]] # Bin to run the HelloWorld gRPC server 8 | name = "helloworld-server" 9 | path = "src/server.rs" 10 | 11 | [[bin]] # Bin to run the HelloWorld gRPC client 12 | name = "helloworld-client" 13 | path = "src/client.rs" 14 | 15 | [dependencies] 16 | rand = "0.8.5" 17 | tonic = "0.8" 18 | prost = "0.11" 19 | tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } 20 | 21 | [build-dependencies] 22 | tonic-build = "0.8" 23 | -------------------------------------------------------------------------------- /web/grpc/build.rs: -------------------------------------------------------------------------------- 1 | fn main() -> Result<(), Box> { 2 | tonic_build::compile_protos("proto/helloworld.proto")?; 3 | Ok(()) 4 | } 5 | -------------------------------------------------------------------------------- /web/grpc/proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package helloworld; 3 | 4 | service Greeter { 5 | rpc SayHello (HelloRequest) returns (HelloReply); 6 | } 7 | 8 | service CalculatorService{ 9 | rpc Sum(SumRequest) returns (SumResponse); 10 | } 11 | message HelloRequest { 12 | string name = 1; 13 | } 14 | 15 | message HelloReply { 16 | string message = 1; 17 | } 18 | 19 | 20 | message SumRequest { 21 | int32 a = 1; 22 | int32 b = 2; 23 | } 24 | 25 | message SumResponse { 26 | int32 sum = 1; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /web/grpc/src/client.rs: -------------------------------------------------------------------------------- 1 | use hello_world::greeter_client::GreeterClient; 2 | use hello_world::HelloRequest; 3 | 4 | pub mod hello_world { 5 | tonic::include_proto!("helloworld"); 6 | } 7 | 8 | #[tokio::main] 9 | async fn main() -> Result<(), Box> { 10 | let mut client = GreeterClient::connect("http://[::1]:50051").await?; 11 | 12 | let request = tonic::Request::new(HelloRequest { 13 | name: "Tonic".into(), 14 | }); 15 | 16 | let response = client.say_hello(request).await?; 17 | 18 | println!("RESPONSE={:?}", response); 19 | 20 | Ok(()) 21 | } -------------------------------------------------------------------------------- /web/grpc/src/main.rs: -------------------------------------------------------------------------------- 1 | use rand::prelude::*; 2 | 3 | fn main() { 4 | // let s1 = String::from("hello"); 5 | // let s2 = s1; // Khi gán thế này thì quyền sở hữu (ownership bị chuyển hoàn toàn sang s2 và s1 bị hủy) 6 | 7 | // let s3 = &s2; 8 | // println!("{:?}",s2); 9 | 10 | let x: u8 = random(); 11 | println!("{}", x); 12 | 13 | // println!("{}, world!", s1); 14 | } 15 | -------------------------------------------------------------------------------- /web/grpc/src/server.rs: -------------------------------------------------------------------------------- 1 | use tonic::{transport::Server, Request, Response, Status}; 2 | 3 | use hello_world::greeter_server::{Greeter, GreeterServer}; 4 | use hello_world::{HelloReply, HelloRequest}; 5 | 6 | use hello_world::calculator_service_server::{CalculatorService, CalculatorServiceServer}; 7 | use hello_world::{SumRequest, SumResponse}; 8 | 9 | pub mod hello_world { 10 | tonic::include_proto!("helloworld"); 11 | } 12 | 13 | #[derive(Debug, Default)] 14 | pub struct MyGreeter {} 15 | 16 | #[tonic::async_trait] 17 | impl Greeter for MyGreeter { 18 | async fn say_hello( 19 | &self, 20 | request: Request, 21 | ) -> Result, Status> { 22 | } 23 | } 24 | 25 | pub struct MyCalculator {} 26 | 27 | #[tonic::async_trait] 28 | impl CalculatorService for MyCalculator { 29 | fn sum( 30 | &self, 31 | request: tonic::Request, 32 | ) -> Result, Status> { 33 | let sum = request.into_inner().a + request.into_inner().b; 34 | 35 | let response: SumResponse = SumResponse { sum: sum }; 36 | 37 | Ok(Response::new(response)); 38 | } 39 | } 40 | 41 | #[tokio::main] 42 | async fn main() -> Result<(), Box> { 43 | let addr = "[::1]:50051".parse()?; 44 | let greeter = MyGreeter::default(); 45 | 46 | Server::builder() 47 | .add_service(GreeterServer::new(greeter)) 48 | .serve(addr) 49 | .await?; 50 | 51 | Ok(()) 52 | } 53 | -------------------------------------------------------------------------------- /web/yew-app/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /web/yew-app/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "yew-app" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | yew = "0.19" 10 | 11 | -------------------------------------------------------------------------------- /web/yew-app/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Yew App 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /web/yew-app/dist/yew-app-5fdf1eddf48554e7.js: -------------------------------------------------------------------------------- 1 | 2 | let wasm; 3 | 4 | const heap = new Array(32).fill(undefined); 5 | 6 | heap.push(undefined, null, true, false); 7 | 8 | function getObject(idx) { return heap[idx]; } 9 | 10 | let heap_next = heap.length; 11 | 12 | function addHeapObject(obj) { 13 | if (heap_next === heap.length) heap.push(heap.length + 1); 14 | const idx = heap_next; 15 | heap_next = heap[idx]; 16 | 17 | heap[idx] = obj; 18 | return idx; 19 | } 20 | 21 | function isLikeNone(x) { 22 | return x === undefined || x === null; 23 | } 24 | 25 | let cachedFloat64Memory0 = new Float64Array(); 26 | 27 | function getFloat64Memory0() { 28 | if (cachedFloat64Memory0.byteLength === 0) { 29 | cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); 30 | } 31 | return cachedFloat64Memory0; 32 | } 33 | 34 | let cachedInt32Memory0 = new Int32Array(); 35 | 36 | function getInt32Memory0() { 37 | if (cachedInt32Memory0.byteLength === 0) { 38 | cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); 39 | } 40 | return cachedInt32Memory0; 41 | } 42 | 43 | const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); 44 | 45 | cachedTextDecoder.decode(); 46 | 47 | let cachedUint8Memory0 = new Uint8Array(); 48 | 49 | function getUint8Memory0() { 50 | if (cachedUint8Memory0.byteLength === 0) { 51 | cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); 52 | } 53 | return cachedUint8Memory0; 54 | } 55 | 56 | function getStringFromWasm0(ptr, len) { 57 | return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); 58 | } 59 | 60 | function dropObject(idx) { 61 | if (idx < 36) return; 62 | heap[idx] = heap_next; 63 | heap_next = idx; 64 | } 65 | 66 | function takeObject(idx) { 67 | const ret = getObject(idx); 68 | dropObject(idx); 69 | return ret; 70 | } 71 | 72 | function debugString(val) { 73 | // primitive types 74 | const type = typeof val; 75 | if (type == 'number' || type == 'boolean' || val == null) { 76 | return `${val}`; 77 | } 78 | if (type == 'string') { 79 | return `"${val}"`; 80 | } 81 | if (type == 'symbol') { 82 | const description = val.description; 83 | if (description == null) { 84 | return 'Symbol'; 85 | } else { 86 | return `Symbol(${description})`; 87 | } 88 | } 89 | if (type == 'function') { 90 | const name = val.name; 91 | if (typeof name == 'string' && name.length > 0) { 92 | return `Function(${name})`; 93 | } else { 94 | return 'Function'; 95 | } 96 | } 97 | // objects 98 | if (Array.isArray(val)) { 99 | const length = val.length; 100 | let debug = '['; 101 | if (length > 0) { 102 | debug += debugString(val[0]); 103 | } 104 | for(let i = 1; i < length; i++) { 105 | debug += ', ' + debugString(val[i]); 106 | } 107 | debug += ']'; 108 | return debug; 109 | } 110 | // Test for built-in 111 | const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); 112 | let className; 113 | if (builtInMatches.length > 1) { 114 | className = builtInMatches[1]; 115 | } else { 116 | // Failed to match the standard '[object ClassName]' 117 | return toString.call(val); 118 | } 119 | if (className == 'Object') { 120 | // we're a user defined class or Object 121 | // JSON.stringify avoids problems with cycles, and is generally much 122 | // easier than looping through ownProperties of `val`. 123 | try { 124 | return 'Object(' + JSON.stringify(val) + ')'; 125 | } catch (_) { 126 | return 'Object'; 127 | } 128 | } 129 | // errors 130 | if (val instanceof Error) { 131 | return `${val.name}: ${val.message}\n${val.stack}`; 132 | } 133 | // TODO we could test for more things here, like `Set`s and `Map`s. 134 | return className; 135 | } 136 | 137 | let WASM_VECTOR_LEN = 0; 138 | 139 | const cachedTextEncoder = new TextEncoder('utf-8'); 140 | 141 | const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' 142 | ? function (arg, view) { 143 | return cachedTextEncoder.encodeInto(arg, view); 144 | } 145 | : function (arg, view) { 146 | const buf = cachedTextEncoder.encode(arg); 147 | view.set(buf); 148 | return { 149 | read: arg.length, 150 | written: buf.length 151 | }; 152 | }); 153 | 154 | function passStringToWasm0(arg, malloc, realloc) { 155 | 156 | if (realloc === undefined) { 157 | const buf = cachedTextEncoder.encode(arg); 158 | const ptr = malloc(buf.length); 159 | getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); 160 | WASM_VECTOR_LEN = buf.length; 161 | return ptr; 162 | } 163 | 164 | let len = arg.length; 165 | let ptr = malloc(len); 166 | 167 | const mem = getUint8Memory0(); 168 | 169 | let offset = 0; 170 | 171 | for (; offset < len; offset++) { 172 | const code = arg.charCodeAt(offset); 173 | if (code > 0x7F) break; 174 | mem[ptr + offset] = code; 175 | } 176 | 177 | if (offset !== len) { 178 | if (offset !== 0) { 179 | arg = arg.slice(offset); 180 | } 181 | ptr = realloc(ptr, len, len = offset + arg.length * 3); 182 | const view = getUint8Memory0().subarray(ptr + offset, ptr + len); 183 | const ret = encodeString(arg, view); 184 | 185 | offset += ret.written; 186 | } 187 | 188 | WASM_VECTOR_LEN = offset; 189 | return ptr; 190 | } 191 | 192 | function makeClosure(arg0, arg1, dtor, f) { 193 | const state = { a: arg0, b: arg1, cnt: 1, dtor }; 194 | const real = (...args) => { 195 | // First up with a closure we increment the internal reference 196 | // count. This ensures that the Rust closure environment won't 197 | // be deallocated while we're invoking it. 198 | state.cnt++; 199 | try { 200 | return f(state.a, state.b, ...args); 201 | } finally { 202 | if (--state.cnt === 0) { 203 | wasm.__wbindgen_export_2.get(state.dtor)(state.a, state.b); 204 | state.a = 0; 205 | 206 | } 207 | } 208 | }; 209 | real.original = state; 210 | 211 | return real; 212 | } 213 | function __wbg_adapter_18(arg0, arg1, arg2) { 214 | wasm._dyn_core__ops__function__Fn__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hbb0a1736f251e571(arg0, arg1, addHeapObject(arg2)); 215 | } 216 | 217 | let cachedUint32Memory0 = new Uint32Array(); 218 | 219 | function getUint32Memory0() { 220 | if (cachedUint32Memory0.byteLength === 0) { 221 | cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer); 222 | } 223 | return cachedUint32Memory0; 224 | } 225 | 226 | function getArrayJsValueFromWasm0(ptr, len) { 227 | const mem = getUint32Memory0(); 228 | const slice = mem.subarray(ptr / 4, ptr / 4 + len); 229 | const result = []; 230 | for (let i = 0; i < slice.length; i++) { 231 | result.push(takeObject(slice[i])); 232 | } 233 | return result; 234 | } 235 | 236 | function handleError(f, args) { 237 | try { 238 | return f.apply(this, args); 239 | } catch (e) { 240 | wasm.__wbindgen_exn_store(addHeapObject(e)); 241 | } 242 | } 243 | 244 | async function load(module, imports) { 245 | if (typeof Response === 'function' && module instanceof Response) { 246 | if (typeof WebAssembly.instantiateStreaming === 'function') { 247 | try { 248 | return await WebAssembly.instantiateStreaming(module, imports); 249 | 250 | } catch (e) { 251 | if (module.headers.get('Content-Type') != 'application/wasm') { 252 | console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); 253 | 254 | } else { 255 | throw e; 256 | } 257 | } 258 | } 259 | 260 | const bytes = await module.arrayBuffer(); 261 | return await WebAssembly.instantiate(bytes, imports); 262 | 263 | } else { 264 | const instance = await WebAssembly.instantiate(module, imports); 265 | 266 | if (instance instanceof WebAssembly.Instance) { 267 | return { instance, module }; 268 | 269 | } else { 270 | return instance; 271 | } 272 | } 273 | } 274 | 275 | function getImports() { 276 | const imports = {}; 277 | imports.wbg = {}; 278 | imports.wbg.__wbindgen_object_clone_ref = function(arg0) { 279 | const ret = getObject(arg0); 280 | return addHeapObject(ret); 281 | }; 282 | imports.wbg.__wbindgen_number_get = function(arg0, arg1) { 283 | const obj = getObject(arg1); 284 | const ret = typeof(obj) === 'number' ? obj : undefined; 285 | getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret; 286 | getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); 287 | }; 288 | imports.wbg.__wbindgen_number_new = function(arg0) { 289 | const ret = arg0; 290 | return addHeapObject(ret); 291 | }; 292 | imports.wbg.__wbindgen_string_new = function(arg0, arg1) { 293 | const ret = getStringFromWasm0(arg0, arg1); 294 | return addHeapObject(ret); 295 | }; 296 | imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) { 297 | try { 298 | console.error(getStringFromWasm0(arg0, arg1)); 299 | } finally { 300 | wasm.__wbindgen_free(arg0, arg1); 301 | } 302 | }; 303 | imports.wbg.__wbg_new_abda76e883ba8a5f = function() { 304 | const ret = new Error(); 305 | return addHeapObject(ret); 306 | }; 307 | imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) { 308 | const ret = getObject(arg1).stack; 309 | const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 310 | const len0 = WASM_VECTOR_LEN; 311 | getInt32Memory0()[arg0 / 4 + 1] = len0; 312 | getInt32Memory0()[arg0 / 4 + 0] = ptr0; 313 | }; 314 | imports.wbg.__wbindgen_object_drop_ref = function(arg0) { 315 | takeObject(arg0); 316 | }; 317 | imports.wbg.__wbg_warn_0b90a269a514ae1d = function(arg0, arg1) { 318 | var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); 319 | wasm.__wbindgen_free(arg0, arg1 * 4); 320 | console.warn(...v0); 321 | }; 322 | imports.wbg.__wbg_instanceof_Window_acc97ff9f5d2c7b4 = function(arg0) { 323 | let result; 324 | try { 325 | result = getObject(arg0) instanceof Window; 326 | } catch { 327 | result = false; 328 | } 329 | const ret = result; 330 | return ret; 331 | }; 332 | imports.wbg.__wbg_document_3ead31dbcad65886 = function(arg0) { 333 | const ret = getObject(arg0).document; 334 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 335 | }; 336 | imports.wbg.__wbg_body_3cb4b4042b9a632b = function(arg0) { 337 | const ret = getObject(arg0).body; 338 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 339 | }; 340 | imports.wbg.__wbg_createElement_976dbb84fe1661b5 = function() { return handleError(function (arg0, arg1, arg2) { 341 | const ret = getObject(arg0).createElement(getStringFromWasm0(arg1, arg2)); 342 | return addHeapObject(ret); 343 | }, arguments) }; 344 | imports.wbg.__wbg_createElementNS_1561aca8ee3693c0 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { 345 | const ret = getObject(arg0).createElementNS(arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); 346 | return addHeapObject(ret); 347 | }, arguments) }; 348 | imports.wbg.__wbg_createTextNode_300f845fab76642f = function(arg0, arg1, arg2) { 349 | const ret = getObject(arg0).createTextNode(getStringFromWasm0(arg1, arg2)); 350 | return addHeapObject(ret); 351 | }; 352 | imports.wbg.__wbg_parentElement_0cffb3ceb0f107bd = function(arg0) { 353 | const ret = getObject(arg0).parentElement; 354 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 355 | }; 356 | imports.wbg.__wbg_lastChild_a2f5ed739809bb31 = function(arg0) { 357 | const ret = getObject(arg0).lastChild; 358 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 359 | }; 360 | imports.wbg.__wbg_setnodeValue_4077cafeefd0725e = function(arg0, arg1, arg2) { 361 | getObject(arg0).nodeValue = arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2); 362 | }; 363 | imports.wbg.__wbg_appendChild_e513ef0e5098dfdd = function() { return handleError(function (arg0, arg1) { 364 | const ret = getObject(arg0).appendChild(getObject(arg1)); 365 | return addHeapObject(ret); 366 | }, arguments) }; 367 | imports.wbg.__wbg_insertBefore_9f2d2defb9471006 = function() { return handleError(function (arg0, arg1, arg2) { 368 | const ret = getObject(arg0).insertBefore(getObject(arg1), getObject(arg2)); 369 | return addHeapObject(ret); 370 | }, arguments) }; 371 | imports.wbg.__wbg_removeChild_6751e9ca5d9aaf00 = function() { return handleError(function (arg0, arg1) { 372 | const ret = getObject(arg0).removeChild(getObject(arg1)); 373 | return addHeapObject(ret); 374 | }, arguments) }; 375 | imports.wbg.__wbg_value_ccb32485ee1b3928 = function(arg0, arg1) { 376 | const ret = getObject(arg1).value; 377 | const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 378 | const len0 = WASM_VECTOR_LEN; 379 | getInt32Memory0()[arg0 / 4 + 1] = len0; 380 | getInt32Memory0()[arg0 / 4 + 0] = ptr0; 381 | }; 382 | imports.wbg.__wbg_setvalue_df64bc6794c098f2 = function(arg0, arg1, arg2) { 383 | getObject(arg0).value = getStringFromWasm0(arg1, arg2); 384 | }; 385 | imports.wbg.__wbg_instanceof_Element_33bd126d58f2021b = function(arg0) { 386 | let result; 387 | try { 388 | result = getObject(arg0) instanceof Element; 389 | } catch { 390 | result = false; 391 | } 392 | const ret = result; 393 | return ret; 394 | }; 395 | imports.wbg.__wbg_namespaceURI_e19c7be2c60e5b5c = function(arg0, arg1) { 396 | const ret = getObject(arg1).namespaceURI; 397 | var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 398 | var len0 = WASM_VECTOR_LEN; 399 | getInt32Memory0()[arg0 / 4 + 1] = len0; 400 | getInt32Memory0()[arg0 / 4 + 0] = ptr0; 401 | }; 402 | imports.wbg.__wbg_removeAttribute_beaed7727852af78 = function() { return handleError(function (arg0, arg1, arg2) { 403 | getObject(arg0).removeAttribute(getStringFromWasm0(arg1, arg2)); 404 | }, arguments) }; 405 | imports.wbg.__wbg_setAttribute_d8436c14a59ab1af = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { 406 | getObject(arg0).setAttribute(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); 407 | }, arguments) }; 408 | imports.wbg.__wbg_setchecked_f1e1f3e62cdca8e7 = function(arg0, arg1) { 409 | getObject(arg0).checked = arg1 !== 0; 410 | }; 411 | imports.wbg.__wbg_value_b2a620d34c663701 = function(arg0, arg1) { 412 | const ret = getObject(arg1).value; 413 | const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 414 | const len0 = WASM_VECTOR_LEN; 415 | getInt32Memory0()[arg0 / 4 + 1] = len0; 416 | getInt32Memory0()[arg0 / 4 + 0] = ptr0; 417 | }; 418 | imports.wbg.__wbg_setvalue_e5b519cca37d82a7 = function(arg0, arg1, arg2) { 419 | getObject(arg0).value = getStringFromWasm0(arg1, arg2); 420 | }; 421 | imports.wbg.__wbg_target_bf704b7db7ad1387 = function(arg0) { 422 | const ret = getObject(arg0).target; 423 | return isLikeNone(ret) ? 0 : addHeapObject(ret); 424 | }; 425 | imports.wbg.__wbg_cancelBubble_8c0bdf21c08f1717 = function(arg0) { 426 | const ret = getObject(arg0).cancelBubble; 427 | return ret; 428 | }; 429 | imports.wbg.__wbg_addEventListener_1fc744729ac6dc27 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { 430 | getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), getObject(arg4)); 431 | }, arguments) }; 432 | imports.wbg.__wbg_newnoargs_b5b063fc6c2f0376 = function(arg0, arg1) { 433 | const ret = new Function(getStringFromWasm0(arg0, arg1)); 434 | return addHeapObject(ret); 435 | }; 436 | imports.wbg.__wbg_call_97ae9d8645dc388b = function() { return handleError(function (arg0, arg1) { 437 | const ret = getObject(arg0).call(getObject(arg1)); 438 | return addHeapObject(ret); 439 | }, arguments) }; 440 | imports.wbg.__wbg_valueOf_6b6effad03e5c546 = function(arg0) { 441 | const ret = getObject(arg0).valueOf(); 442 | return ret; 443 | }; 444 | imports.wbg.__wbg_is_40a66842732708e7 = function(arg0, arg1) { 445 | const ret = Object.is(getObject(arg0), getObject(arg1)); 446 | return ret; 447 | }; 448 | imports.wbg.__wbg_new_0b9bfdd97583284e = function() { 449 | const ret = new Object(); 450 | return addHeapObject(ret); 451 | }; 452 | imports.wbg.__wbg_globalThis_7f206bda628d5286 = function() { return handleError(function () { 453 | const ret = globalThis.globalThis; 454 | return addHeapObject(ret); 455 | }, arguments) }; 456 | imports.wbg.__wbg_self_6d479506f72c6a71 = function() { return handleError(function () { 457 | const ret = self.self; 458 | return addHeapObject(ret); 459 | }, arguments) }; 460 | imports.wbg.__wbg_window_f2557cc78490aceb = function() { return handleError(function () { 461 | const ret = window.window; 462 | return addHeapObject(ret); 463 | }, arguments) }; 464 | imports.wbg.__wbg_global_ba75c50d1cf384f4 = function() { return handleError(function () { 465 | const ret = global.global; 466 | return addHeapObject(ret); 467 | }, arguments) }; 468 | imports.wbg.__wbg_get_765201544a2b6869 = function() { return handleError(function (arg0, arg1) { 469 | const ret = Reflect.get(getObject(arg0), getObject(arg1)); 470 | return addHeapObject(ret); 471 | }, arguments) }; 472 | imports.wbg.__wbg_set_bf3f89b92d5a34bf = function() { return handleError(function (arg0, arg1, arg2) { 473 | const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); 474 | return ret; 475 | }, arguments) }; 476 | imports.wbg.__wbindgen_is_undefined = function(arg0) { 477 | const ret = getObject(arg0) === undefined; 478 | return ret; 479 | }; 480 | imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { 481 | const ret = debugString(getObject(arg1)); 482 | const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); 483 | const len0 = WASM_VECTOR_LEN; 484 | getInt32Memory0()[arg0 / 4 + 1] = len0; 485 | getInt32Memory0()[arg0 / 4 + 0] = ptr0; 486 | }; 487 | imports.wbg.__wbindgen_throw = function(arg0, arg1) { 488 | throw new Error(getStringFromWasm0(arg0, arg1)); 489 | }; 490 | imports.wbg.__wbindgen_closure_wrapper784 = function(arg0, arg1, arg2) { 491 | const ret = makeClosure(arg0, arg1, 131, __wbg_adapter_18); 492 | return addHeapObject(ret); 493 | }; 494 | 495 | return imports; 496 | } 497 | 498 | function initMemory(imports, maybe_memory) { 499 | 500 | } 501 | 502 | function finalizeInit(instance, module) { 503 | wasm = instance.exports; 504 | init.__wbindgen_wasm_module = module; 505 | cachedFloat64Memory0 = new Float64Array(); 506 | cachedInt32Memory0 = new Int32Array(); 507 | cachedUint32Memory0 = new Uint32Array(); 508 | cachedUint8Memory0 = new Uint8Array(); 509 | 510 | wasm.__wbindgen_start(); 511 | return wasm; 512 | } 513 | 514 | function initSync(module) { 515 | const imports = getImports(); 516 | 517 | initMemory(imports); 518 | 519 | if (!(module instanceof WebAssembly.Module)) { 520 | module = new WebAssembly.Module(module); 521 | } 522 | 523 | const instance = new WebAssembly.Instance(module, imports); 524 | 525 | return finalizeInit(instance, module); 526 | } 527 | 528 | async function init(input) { 529 | if (typeof input === 'undefined') { 530 | input = new URL('yew-app-5fdf1eddf48554e7_bg.wasm', import.meta.url); 531 | } 532 | const imports = getImports(); 533 | 534 | if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { 535 | input = fetch(input); 536 | } 537 | 538 | initMemory(imports); 539 | 540 | const { instance, module } = await load(await input, imports); 541 | 542 | return finalizeInit(instance, module); 543 | } 544 | 545 | export { initSync } 546 | export default init; 547 | -------------------------------------------------------------------------------- /web/yew-app/dist/yew-app-5fdf1eddf48554e7_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/npv2k1/learn-rust/3b84b71577d6a11b67a0f582132e22f8e658714d/web/yew-app/dist/yew-app-5fdf1eddf48554e7_bg.wasm -------------------------------------------------------------------------------- /web/yew-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Yew App 7 | 8 | 9 | -------------------------------------------------------------------------------- /web/yew-app/src/main.rs: -------------------------------------------------------------------------------- 1 | use yew::prelude::*; 2 | 3 | enum Msg { 4 | AddOne, 5 | } 6 | 7 | struct Model { 8 | value: i64, 9 | } 10 | 11 | impl Component for Model { 12 | type Message = Msg; 13 | type Properties = (); 14 | 15 | fn create(_ctx: &Context) -> Self { 16 | Self { 17 | value: 0, 18 | } 19 | } 20 | 21 | fn update(&mut self, _ctx: &Context, msg: Self::Message) -> bool { 22 | match msg { 23 | Msg::AddOne => { 24 | self.value += 1; 25 | // the value has changed so we need to 26 | // re-render for it to appear on the page 27 | true 28 | } 29 | } 30 | } 31 | 32 | fn view(&self, ctx: &Context) -> Html { 33 | // This gives us a component's "`Scope`" which allows us to send messages, etc to the component. 34 | let link = ctx.link(); 35 | html! { 36 |
37 | 38 |

{ self.value }

39 |
40 | } 41 | } 42 | } 43 | 44 | fn main() { 45 | yew::start_app::(); 46 | } --------------------------------------------------------------------------------