├── .gitignore ├── README.md ├── algorithms ├── README.md └── hacker_rank │ ├── .gitignore │ ├── Cargo.toml │ └── src │ ├── flower_bouquets.rs │ ├── lib.rs │ └── strings.rs ├── ffi ├── README.md ├── c-call-rust │ ├── .gitignore │ ├── Cargo.toml │ ├── c-src │ │ └── main.c │ ├── makefile │ └── src │ │ ├── c_call_rust.h │ │ └── lib.rs ├── example_01 │ ├── .gitignore │ ├── Cargo.toml │ ├── Makefile │ ├── csrc │ │ └── hello.c │ └── src │ │ ├── example_01.h │ │ └── lib.rs ├── example_02 │ ├── .gitignore │ ├── Cargo.toml │ ├── Makefile │ ├── csrc │ │ └── main.c │ └── src │ │ ├── example_02.h │ │ └── lib.rs ├── example_03 │ ├── .gitignore │ ├── Cargo.toml │ ├── Makefile │ ├── cbindgen.toml │ ├── csrc │ │ └── main.c │ ├── example_03_header.h │ └── src │ │ ├── example_03.h │ │ └── lib.rs ├── example_04 │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ ├── ffi │ │ ├── Cargo.toml │ │ ├── cbindgen.toml │ │ ├── example_04_header.h │ │ └── src │ │ │ └── lib.rs │ ├── python │ │ └── main.py │ └── src │ │ └── lib.rs ├── example_09 │ ├── .gitignore │ ├── Cargo.toml │ ├── csrc │ │ ├── cfoo.c │ │ └── libcfoo.so │ ├── libcfoo.so │ └── src │ │ └── main.rs ├── example_10 │ ├── .gitignore │ ├── Cargo.toml │ ├── csrc │ │ ├── compile.sh │ │ └── sumsquare.c │ ├── libsumsquare.so │ └── src │ │ └── main.rs ├── nix │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ ├── main.c │ │ └── main.rs ├── rust-call-c │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ ├── array.rs │ │ ├── ffi_array │ │ ├── c_utils.c │ │ └── libc_utils.so │ │ ├── ffi_opaque │ │ ├── Makefile │ │ ├── ffi_test.c │ │ ├── ffi_test.h │ │ └── libffi_test.so │ │ ├── layout.rs │ │ ├── main.rs │ │ ├── opaque.rs │ │ └── time.rs └── secp256k1-sys │ ├── .gitignore │ ├── Cargo.toml │ ├── build.rs │ ├── include │ ├── secp256k1.h │ └── test.c │ ├── src │ └── lib.rs │ └── wrapper.h ├── head-first ├── .gitignore ├── Cargo.toml ├── README.md ├── async-primer │ ├── async-example │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── file.rs │ │ │ ├── file1.txt │ │ │ ├── file2.txt │ │ │ └── main.rs │ ├── multi-example │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── file.rs │ │ │ ├── file1.txt │ │ │ ├── file2.txt │ │ │ └── main.rs │ └── sync-example │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ ├── file.rs │ │ ├── file1.txt │ │ ├── file2.txt │ │ └── main.rs ├── http │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ ├── main.rs │ │ ├── rpc_client.rs │ │ └── rpc_server.rs ├── merkle-tree │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── lib.rs ├── rust-trait │ ├── Cargo.toml │ └── src │ │ ├── abstract_type.rs │ │ ├── bound.rs │ │ ├── interface.rs │ │ ├── lib.rs │ │ └── tag.rs ├── src │ └── main.rs ├── std-box │ ├── example_Box.rs │ ├── example_Deref.rs │ └── example_TraitObject.rs ├── std-cell │ ├── example_Cell.rs │ └── example_RefCell.rs ├── std-marker │ └── example_Send_Sync.rs └── tarpc │ ├── .gitignore │ ├── Cargo.toml │ └── src │ ├── client.rs │ ├── lib.rs │ └── server.rs └── simple ├── .gitignore ├── Cargo.toml ├── README.md ├── function ├── .gitignore ├── Cargo.toml └── src │ └── main.rs ├── httpie ├── .gitignore ├── Cargo.toml └── src │ └── main.rs ├── src ├── collections.rs ├── control_flow.rs ├── error_handling.rs ├── generics_trait.rs ├── main.rs ├── primitives.rs ├── statement.rs ├── tcp_server_example.rs ├── test.rs ├── time_intervals.rs └── variable.rs └── string ├── print.c ├── print.js ├── rustre ├── .gitignore ├── Cargo.toml └── src │ └── main.rs ├── upper.c └── woops.c /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .devcontainer -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rust 语言学习笔记 2 | 3 | * [精简手册](https://lester123.gitbook.io/rust/) 4 | * [基础](./simple/README.md) 5 | * [实战](./head-first/README.md) 6 | * [FFI](./ffi/README.md) 7 | -------------------------------------------------------------------------------- /algorithms/README.md: -------------------------------------------------------------------------------- 1 | # Algorithms 2 | 3 | This is a collection of Rust implementations for various algorithm problems. 4 | 5 | * `hacker-rant` - [HackerRank](https://www.hackerrank.com/) -------------------------------------------------------------------------------- /algorithms/hacker_rank/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | .vscode 13 | -------------------------------------------------------------------------------- /algorithms/hacker_rank/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hacker-rank" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" -------------------------------------------------------------------------------- /algorithms/hacker_rank/src/flower_bouquets.rs: -------------------------------------------------------------------------------- 1 | // A person can create a flower bouquet with either 3 roses (cost of bouquet = p) or 1 rose and 1 cosmos (cost = q) In an array of flowers. 2 | // The person has to select contiguous set of flowers i.e. 2 or 3 to gain maximum cost. 3 | // Input format: A string of 0(denotes rose) and 1(denotes cosmos). Output : Maximum cost. 4 | // Examples: 5 | // Input: p = 2, q = 3, s = 0001000 Output: 5 6 | // Input: p = 2, q = 3, s = 001101011 Output: 9 7 | fn flower_bouquets(p: i32, q: i32, s: &str) -> i32 { 8 | let mut dp = vec![0; s.len()]; 9 | let mut str = String::new(); 10 | 11 | for (i, ch) in s.chars().enumerate() { 12 | dp[i] = if i == 0 { 0 } else { dp[i - 1] }; 13 | 14 | str.push(ch); 15 | 16 | if str.contains("000") { 17 | if i == 2 { 18 | dp[i] = p; 19 | } else { 20 | dp[i] = dp[i - 1].max(p + dp[i - 3]); 21 | } 22 | } else if str.contains("01") || str.contains("10") { 23 | if i == 1 { 24 | dp[i] = q; 25 | } else { 26 | dp[i] = dp[i - 1].max(q + dp[i - 2]); 27 | } 28 | } 29 | 30 | if i >= 2 { 31 | str.clear(); 32 | str.push(ch); 33 | } 34 | } 35 | 36 | dp[s.len() - 1] 37 | } 38 | 39 | #[test] 40 | fn test_flower_bouquets() { 41 | assert_eq!(flower_bouquets(2, 3, "0001000"), 5); 42 | assert_eq!(flower_bouquets(2, 3, "001101011"), 9); 43 | assert_eq!(flower_bouquets(10, 1, "0"), 0); 44 | } -------------------------------------------------------------------------------- /algorithms/hacker_rank/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod strings; 2 | pub mod flower_bouquets; -------------------------------------------------------------------------------- /algorithms/hacker_rank/src/strings.rs: -------------------------------------------------------------------------------- 1 | fn super_reduced_string(s: &str) -> String { 2 | let mut stack = Vec::new(); 3 | 4 | for c in s.chars() { 5 | if stack.last() == Some(&c) { 6 | stack.pop(); 7 | } else { 8 | stack.push(c); 9 | } 10 | } 11 | 12 | if stack.is_empty() { 13 | "Empty String".to_string() 14 | } else { 15 | stack.into_iter().collect() 16 | } 17 | } 18 | 19 | fn camelcase(s: &str) -> i32 { 20 | let mut count = 1; 21 | for c in s.chars() { 22 | if c.is_uppercase() { 23 | count += 1; 24 | } 25 | } 26 | return count; 27 | } 28 | 29 | fn alternate(s: &str) -> i32 { 30 | let chars: Vec = s.chars().collect(); 31 | let mut max_length = 0; 32 | for c1 in 'a'..='z' { 33 | for c2 in (c1 as u8 + 1)..=b'z' { 34 | let a = c1 as char; 35 | let b = c2 as char; 36 | let mut last_char = None; 37 | let mut length = 0; 38 | for &c in &chars { 39 | if c != a && c != b { 40 | continue; 41 | } 42 | if last_char == Some(c) { 43 | length = 0; 44 | break; 45 | } 46 | last_char = Some(c); 47 | length += 1; 48 | } 49 | if length > max_length { 50 | max_length = length; 51 | } 52 | } 53 | } 54 | max_length 55 | } 56 | 57 | #[cfg(test)] 58 | mod tests { 59 | use super::*; 60 | 61 | #[test] 62 | fn test_super_reduced_string() { 63 | assert_eq!(super_reduced_string("aab"), "b"); 64 | assert_eq!(super_reduced_string("abba"), "Empty String"); 65 | assert_eq!(super_reduced_string("aaabccddd"), "abd"); 66 | assert_eq!(super_reduced_string("abcdeedcba"), "Empty String"); 67 | assert_eq!(super_reduced_string(""), "Empty String"); 68 | } 69 | 70 | #[test] 71 | fn test_camelcase() { 72 | assert_eq!(camelcase("oneTwoThree"), 3); 73 | assert_eq!(camelcase("helloWorld"), 2); 74 | assert_eq!(camelcase("thisIsACamelCaseString"), 6); 75 | } 76 | 77 | #[test] 78 | fn test_alternate() { 79 | assert_eq!(alternate("abaacdabd"), 4); 80 | assert_eq!(alternate("beabeefeab"), 5); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /ffi/README.md: -------------------------------------------------------------------------------- 1 | # Rust FFI 2 | 3 | ## c-call-rust 4 | 5 | 6 | ## rust-call-c 7 | 8 | ### 示例代码 9 | 10 | * [在 C 中调用 Rust 函数]() 11 | * [在 Rust 中调用 C 函数]() 12 | -------------------------------------------------------------------------------- /ffi/c-call-rust/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /ffi/c-call-rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "c-call-rust" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | 11 | [lib] 12 | name = "c_call_rust" 13 | crate-type = ["staticlib", "cdylib"] 14 | -------------------------------------------------------------------------------- /ffi/c-call-rust/c-src/main.c: -------------------------------------------------------------------------------- 1 | #include "c_call_rust.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) { 7 | call_from_rust(); 8 | 9 | int my_array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 10 | int total = sum(my_array, 10); 11 | printf("The total is %d\n", total); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /ffi/c-call-rust/makefile: -------------------------------------------------------------------------------- 1 | GCC_BIN ?= $(shell which gcc) 2 | CARGO_BIN ?= $(shell which cargo) 3 | 4 | run: clean build 5 | ./c-src/main 6 | 7 | clean: 8 | $(CARGO_BIN) clean 9 | rm -f ./c-src/main 10 | 11 | build: 12 | $(CARGO_BIN) build 13 | $(GCC_BIN) -o ./c-src/main ./c-src/main.c -Isrc -L ./target/debug -lc_call_rust -------------------------------------------------------------------------------- /ffi/c-call-rust/src/c_call_rust.h: -------------------------------------------------------------------------------- 1 | void call_from_rust(); 2 | int sum(const int* my_array, int length); -------------------------------------------------------------------------------- /ffi/c-call-rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::ffi::CString; 2 | use std::os::raw::c_char; 3 | use std::os::raw::c_int; 4 | use std::slice; 5 | 6 | #[no_mangle] 7 | pub extern "C" fn call_from_rust() { 8 | println!("This is a Rust function for C!"); 9 | } 10 | 11 | // #[no_mangle] 12 | // pub extern rust_printer(input: *const c_char) -> *mut c_char { 13 | // let mut hello = String::from("Hello World!"); 14 | // let c_str_to_print = CString::new(hello).unwrap(); 15 | // // 使用 as_ptr 将 CString 转化成 char 指针传给 C 函数 16 | // c_str_to_print.as_ptr() 17 | // } 18 | 19 | 20 | #[no_mangle] 21 | pub extern fn sum(array: *const c_int, length: c_int) -> c_int { 22 | assert!(!array.is_null(), "Null pointer in sum()"); 23 | unsafe { 24 | let array: &[c_int] = slice::from_raw_parts(array, length as usize); 25 | array.into_iter().sum() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ffi/example_01/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | vgcore.* 13 | -------------------------------------------------------------------------------- /ffi/example_01/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "example_01" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | 11 | [lib] 12 | name = "example_01" 13 | crate-type = ["staticlib", "cdylib"] -------------------------------------------------------------------------------- /ffi/example_01/Makefile: -------------------------------------------------------------------------------- 1 | GCC_BIN ?= $(shell which gcc) 2 | CARGO_BIN ?= $(shell which cargo) 3 | 4 | run: clean build 5 | ./csrc/hello 6 | 7 | clean: 8 | $(CARGO_BIN) clean 9 | rm -f ./csrc/hello 10 | 11 | build: 12 | $(CARGO_BIN) build --release 13 | $(GCC_BIN) -o ./csrc/hello ./csrc/hello.c -Isrc -L. -l:target/release/libexample_01.so -------------------------------------------------------------------------------- /ffi/example_01/csrc/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "example_01.h" 6 | 7 | int main(void) { 8 | // basic string - char array 9 | char hello1[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; 10 | printf("C hello 1: %s\n", hello1); 11 | char hello2[6] = "Hello"; 12 | printf("C hello 2: %s\n", hello2); 13 | if (strcmp(hello1, hello2) ==0) 14 | { 15 | printf("hello 1 and 2 are equal\n"); 16 | } else 17 | { 18 | printf("hello 1 and 2 are different\n"); 19 | } 20 | 21 | // basic string - char pointer 22 | // char *str; 23 | // str = "hello"; // Stored in read only part of data segment 24 | // *(str+1) = 'i'; // Segmentation fault error: trying to modify read only memory 25 | 26 | char hello_s[] = "hello"; // Stored in stack segment 27 | *hello_s = 'H'; // No problem: String is now Hello 28 | printf("new string in stack is %s\n", hello_s); 29 | 30 | int size = 6; 31 | char *hello_h = (char *)malloc(sizeof(char)*size); // Stored in heap segment 32 | *(hello_h+0) = 'h'; 33 | *(hello_h+1) = 'e'; 34 | *(hello_h+2) = 'l'; 35 | *(hello_h+3) = 'l'; 36 | *(hello_h+4) = 'o'; 37 | *(hello_h+5) = '\0'; 38 | *(hello_h+0) = 'H'; // No problem: String is now Hello 39 | printf("new string in heap is: %s\n", hello_h); 40 | free(hello_h); 41 | 42 | char *c_str = "hello"; 43 | print_str(c_str); // Problem: still reachable 44 | c_str = change_str(c_str); // change the previous content 45 | printf("C side result: %s\n", c_str); 46 | free_str(c_str); 47 | 48 | // C generate strings 49 | char *c_hello = (char *)malloc(sizeof(char)*size); 50 | *(c_hello+0) = 'H'; 51 | *(c_hello+1) = 'e'; 52 | *(c_hello+2) = 'l'; 53 | *(c_hello+3) = 'l'; 54 | *(c_hello+4) = 'o'; 55 | *(c_hello+5) = '\0'; 56 | printf("C side generate: %s\n", c_hello); 57 | print_str(c_hello); 58 | char *c_hello_world = change_str(c_hello); 59 | printf("C side result: %s\n", c_hello_world); 60 | free(c_hello); 61 | free_str(c_hello_world); 62 | 63 | char *c_ping = generate_str(); 64 | printf("C side print: %s\n", c_ping); 65 | free_str(c_ping); 66 | } -------------------------------------------------------------------------------- /ffi/example_01/src/example_01.h: -------------------------------------------------------------------------------- 1 | void print_str(const char *str); 2 | char *change_str(char str[]); 3 | char *generate_str(); 4 | void free_str(char *); -------------------------------------------------------------------------------- /ffi/example_01/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::c_char; 2 | use std::ffi::{CStr, CString}; 3 | 4 | #[no_mangle] 5 | pub extern "C" fn print_str(s: *const c_char) { 6 | let slice = unsafe { 7 | assert!(!s.is_null()); 8 | CStr::from_ptr(s) 9 | }; 10 | let r_str = slice.to_str().unwrap(); 11 | println!("Rust side print: {:?}", r_str); 12 | } 13 | 14 | #[no_mangle] 15 | pub extern "C" fn change_str(s: *mut c_char) -> *mut c_char { 16 | let mut string = unsafe { 17 | assert!(!s.is_null()); 18 | CStr::from_ptr(s).to_string_lossy().into_owned() 19 | }; 20 | string.push_str(" World!"); 21 | println!("Rust side change: {:?}", string); 22 | let c_str_changed = CString::new(string).unwrap(); 23 | c_str_changed.into_raw() 24 | } 25 | 26 | #[no_mangle] 27 | pub extern "C" fn generate_str() -> *mut c_char { 28 | let ping = String::from("ping"); 29 | println!("Rust side generate: {:?}", ping); 30 | let c_str_ping = CString::new(ping).unwrap(); 31 | c_str_ping.into_raw() 32 | } 33 | 34 | #[no_mangle] 35 | pub extern "C" fn free_str(s: *mut c_char) { 36 | unsafe { 37 | if s.is_null() { 38 | return; 39 | } 40 | CString::from_raw(s) 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /ffi/example_02/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | vgcore.* 13 | -------------------------------------------------------------------------------- /ffi/example_02/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "example_02" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | rand = "0.7.3" 11 | 12 | [lib] 13 | name = "example_02" 14 | crate-type = ["staticlib", "cdylib"] -------------------------------------------------------------------------------- /ffi/example_02/Makefile: -------------------------------------------------------------------------------- 1 | GCC_BIN ?= $(shell which gcc) 2 | CARGO_BIN ?= $(shell which cargo) 3 | 4 | run: clean build 5 | ./csrc/main 6 | 7 | clean: 8 | $(CARGO_BIN) clean 9 | rm -f ./csrc/main 10 | 11 | build: 12 | $(CARGO_BIN) build --release 13 | $(GCC_BIN) -o ./csrc/main ./csrc/main.c -Isrc -L. -l:target/release/libexample_02.so -------------------------------------------------------------------------------- /ffi/example_02/csrc/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "example_02.h" 4 | 5 | int main(void) { 6 | char version[] = "v1"; 7 | printf("C call Rust Result: %d\n", handle_result(version)); 8 | *(version+1) = '2'; 9 | printf("C call Rust Result: %d\n", handle_result(version)); 10 | char *n_version = NULL; 11 | printf("C call Rust Result error: %d\n", handle_result(n_version)); 12 | 13 | float x = 2.0, y = 3.0; 14 | printf("C call Rust Option value: %d\n", handle_option(x, y)); 15 | x = 2.0, y = 0.0; 16 | printf("C call Rust Option None: %d\n", handle_option(x, y)); 17 | 18 | printf("C call Rust panic: %d\n", no_panic()); 19 | } -------------------------------------------------------------------------------- /ffi/example_02/src/example_02.h: -------------------------------------------------------------------------------- 1 | int handle_result(const char *str); 2 | int handle_option(float x, float y); 3 | int no_panic(); -------------------------------------------------------------------------------- /ffi/example_02/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::{c_char, c_float, c_void}; 2 | use std::ffi::CStr; 3 | use std::panic::catch_unwind; 4 | 5 | fn may_panic() { 6 | if rand::random() { 7 | panic!("panic happens"); 8 | } 9 | } 10 | 11 | #[no_mangle] 12 | pub unsafe extern "C" fn no_panic() -> i32 { 13 | let result = catch_unwind(may_panic); 14 | match result { 15 | Ok(_) => 0, 16 | Err(_) => -1, 17 | } 18 | } 19 | 20 | #[derive(Debug)] 21 | enum Version { Version1, Version2 } 22 | 23 | fn parse_version(header: &str) -> Result { 24 | match header { 25 | "" => Err("invalid header length"), 26 | "v1" => Ok(Version::Version1), 27 | "v2" => Ok(Version::Version2), 28 | _ => Err("invalid version"), 29 | } 30 | } 31 | 32 | #[no_mangle] 33 | pub unsafe extern "C" fn handle_result(s: *const c_char) -> i32 { 34 | if (s as *mut c_void).is_null() { 35 | return -1; 36 | } 37 | 38 | let vb = CStr::from_ptr(s).to_str().unwrap(); 39 | let version = parse_version(vb); 40 | match version { 41 | Ok(_) => 0, 42 | Err(_) => -1, 43 | } 44 | } 45 | 46 | fn divide(numerator: f32, denominator: f32) -> Option { 47 | if denominator == 0.0 { 48 | None 49 | } else { 50 | Some(numerator / denominator) 51 | } 52 | } 53 | 54 | #[no_mangle] 55 | pub unsafe extern "C" fn handle_option(x: c_float, y: c_float) -> i32 { 56 | // The return value of the function is an option 57 | let result = divide(x, y); 58 | 59 | // Pattern match to retrieve the value 60 | match result { 61 | // The division was valid 62 | Some(_) => 0, 63 | // The division was invalid 64 | None => -1, 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /ffi/example_03/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | vgcore.* 13 | -------------------------------------------------------------------------------- /ffi/example_03/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "example_03" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | 11 | 12 | [lib] 13 | crate-type = ["cdylib"] -------------------------------------------------------------------------------- /ffi/example_03/Makefile: -------------------------------------------------------------------------------- 1 | GCC_BIN ?= $(shell which gcc) 2 | CARGO_BIN ?= $(shell which cargo) 3 | 4 | run: clean build 5 | ./csrc/main 6 | 7 | clean: 8 | $(CARGO_BIN) clean 9 | rm -f ./csrc/main 10 | 11 | build: 12 | $(CARGO_BIN) build --release 13 | $(GCC_BIN) -o ./csrc/main ./csrc/main.c -Isrc -L. -l:target/release/libexample_03.so -------------------------------------------------------------------------------- /ffi/example_03/cbindgen.toml: -------------------------------------------------------------------------------- 1 | language = "C" 2 | no_includes = true 3 | 4 | [export] 5 | prefix = "capi_" 6 | 7 | [enum] 8 | rename_variants = "SnakeCase" -------------------------------------------------------------------------------- /ffi/example_03/csrc/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "example_03.h" 4 | 5 | int main(void) { 6 | Student *c_ptr = student_alice(); 7 | printf("Student Num: %d\t Total: %d\t Name: %s\t\n", c_ptr->num, c_ptr->total, c_ptr->name); 8 | student_free(c_ptr); 9 | 10 | 11 | Student *stu = student_new(); 12 | printf("Before fill data: Student Num: %d\t Total: %d\t Name: %s\t Scores: %.1f\t%.1f\t%.1f\n", 13 | stu->num, stu->total, stu->name, 14 | stu->scores[0], stu->scores[1], stu->scores[2]); 15 | stu->num = 2; 16 | stu->total = 212; 17 | strcpy(stu->name, "Bob"); 18 | stu->scores[0] = 60.6; 19 | stu->scores[1] = 70.7; 20 | stu->scores[2] = 80.8; 21 | printf("After fill data: Student Num: %d\t Total: %d\t Name: %s\t Scores: %.1f\t%.1f\t%.1f\n", 22 | stu->num, stu->total, stu->name, 23 | stu->scores[0], stu->scores[1], stu->scores[2]); 24 | student_free(stu); 25 | 26 | return 0; 27 | } 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ffi/example_03/example_03_header.h: -------------------------------------------------------------------------------- 1 | typedef enum { 2 | boy, 3 | girl, 4 | } capi_gender; 5 | 6 | typedef struct { 7 | int num; 8 | int total; 9 | char name[20]; 10 | float scores[3]; 11 | capi_gender gender; 12 | } capi_student; 13 | 14 | capi_student *student_new(void); 15 | 16 | capi_student *student_alice(void); 17 | 18 | void student_free(capi_student *p_stu); 19 | -------------------------------------------------------------------------------- /ffi/example_03/src/example_03.h: -------------------------------------------------------------------------------- 1 | typedef struct Student 2 | { 3 | int num; 4 | int total; 5 | char name[20]; 6 | float scores[3]; 7 | } Student; 8 | 9 | Student *student_new(); 10 | Student *student_alice(); 11 | void student_free(Student *p_stu); 12 | -------------------------------------------------------------------------------- /ffi/example_03/src/lib.rs: -------------------------------------------------------------------------------- 1 | // We have a lot of c-types in here, stop warning about their names! 2 | #![allow(non_camel_case_types)] 3 | 4 | use std::os::raw::{c_char, c_float, c_int}; 5 | 6 | #[repr(C)] 7 | #[derive(Debug)] 8 | pub enum gender { 9 | BOY, 10 | GIRL, 11 | } 12 | 13 | #[repr(C)] 14 | #[derive(Debug)] 15 | pub struct student { 16 | pub num: c_int, 17 | pub total: c_int, 18 | pub name: [c_char; 20], 19 | pub scores: [c_float; 3], 20 | pub gender: gender, 21 | } 22 | 23 | // Default constructor 24 | impl Default for student { 25 | fn default() -> Self { 26 | student { 27 | num: 0 as c_int, 28 | total: 0 as c_int, 29 | name: [0 as c_char; 20], 30 | scores: [0.0 as c_float; 3], 31 | gender: gender::BOY, 32 | } 33 | } 34 | } 35 | 36 | #[no_mangle] 37 | pub extern "C" fn student_new() -> *mut student { 38 | let new_stu: student = Default::default(); 39 | Box::into_raw(Box::new(new_stu)) 40 | } 41 | 42 | #[no_mangle] 43 | pub extern "C" fn student_alice() -> *mut student { 44 | let mut init_char_array: [c_char; 20] = [0; 20]; 45 | for (dest, src) in init_char_array.iter_mut().zip(b"Alice\0".iter()) { 46 | *dest = *src as _; 47 | } 48 | let scores = [92.5, 87.5, 90.0]; 49 | let alice = student { 50 | num: 1 as c_int, 51 | total: 280, 52 | name: init_char_array, 53 | scores, 54 | gender: gender::GIRL, 55 | }; 56 | Box::into_raw(Box::new(alice)) 57 | } 58 | 59 | #[no_mangle] 60 | pub extern "C" fn student_free(p_stu: *mut student) { 61 | if !p_stu.is_null() { 62 | unsafe { 63 | println!("rust side print: {:?}", Box::from_raw(p_stu)); 64 | Box::from_raw(p_stu) 65 | }; 66 | } 67 | } -------------------------------------------------------------------------------- /ffi/example_04/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target 4 | **/target 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | vgcore.* 14 | -------------------------------------------------------------------------------- /ffi/example_04/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "example_04" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | 11 | -------------------------------------------------------------------------------- /ffi/example_04/README.md: -------------------------------------------------------------------------------- 1 | ## example_04 2 | 3 | 在 Python 中调用 Rust 代码的示例。 4 | 5 | * Python FFI 库有 [ctypes](https://docs.python.org/3/library/ctypes.html) 和 [cffi](https://cffi.readthedocs.io/en/latest/) 库 6 | 7 | ### 示例说明 8 | 9 | * `src` 目录: Rust 源码 10 | * `ffi` 目录: Rust 源码导出的 FFI 代码 11 | * `python` 目录: Python 源码 12 | * 本示例采用的是 `cffi` 库 13 | 14 | ### 运行步骤 15 | 16 | 1. 在 `ffi` 目录下,执行 `cargo build` 生成 Rust 源码的动态库(Linux平台,`libexample_04.so`)。 17 | 2. 在 `python` 目录下,运行 `python main.py`。 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ffi/example_04/ffi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "example_04" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | libc = "0.2" 11 | 12 | [lib] 13 | name = "example_04" 14 | crate-type = ["cdylib"] -------------------------------------------------------------------------------- /ffi/example_04/ffi/cbindgen.toml: -------------------------------------------------------------------------------- 1 | language = "C" 2 | no_includes = true -------------------------------------------------------------------------------- /ffi/example_04/ffi/example_04_header.h: -------------------------------------------------------------------------------- 1 | typedef struct c_tuple { 2 | unsigned int integer; 3 | bool boolean; 4 | } c_tuple; 5 | 6 | unsigned int fibonacci(unsigned int index); 7 | 8 | unsigned int count_char(const char *s); 9 | 10 | struct c_tuple handle_tuple(struct c_tuple tup); 11 | 12 | int sum_of_even(const int *ptr, size_t len); 13 | -------------------------------------------------------------------------------- /ffi/example_04/ffi/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::{c_char, c_uint, c_int}; 2 | use std::ffi::CStr; 3 | use std::convert::From; 4 | use std::slice; 5 | use libc::size_t; 6 | 7 | #[no_mangle] 8 | pub extern "C" fn fibonacci(index: c_uint) -> c_uint { 9 | if index <= 2 { 10 | 1 11 | } else { 12 | fibonacci(index - 1) + fibonacci(index - 2) 13 | } 14 | } 15 | 16 | #[no_mangle] 17 | pub extern "C" fn count_char(s: *const c_char) -> c_uint { 18 | let c_str = unsafe { 19 | assert!(!s.is_null()); 20 | CStr::from_ptr(s) 21 | }; 22 | let r_str = c_str.to_str().unwrap(); 23 | r_str.chars().count() as u32 24 | } 25 | 26 | // A struct that can be passed between C and Rust 27 | #[repr(C)] 28 | pub struct c_tuple { 29 | integer: c_uint, 30 | boolean: bool, 31 | } 32 | 33 | impl From for (u32, bool) { 34 | fn from(tup: c_tuple) -> (u32, bool) { 35 | (tup.integer, tup.boolean) 36 | } 37 | } 38 | 39 | impl From<(u32, bool)> for c_tuple { 40 | fn from(tup: (u32, bool)) -> c_tuple { 41 | c_tuple { 42 | integer: tup.0, 43 | boolean: tup.1, 44 | } 45 | } 46 | } 47 | 48 | #[no_mangle] 49 | pub extern "C" fn handle_tuple(tup: c_tuple) -> c_tuple { 50 | let (integer, boolean) = tup.into(); 51 | 52 | (integer + 1, !boolean).into() 53 | } 54 | 55 | #[no_mangle] 56 | pub extern "C" fn sum_of_even(ptr: *const c_int, len: size_t) -> c_int { 57 | let slice = unsafe { 58 | assert!(!ptr.is_null()); 59 | slice::from_raw_parts(ptr, len as usize) 60 | }; 61 | 62 | let sum = slice.iter() 63 | .filter(|&&num| num % 2 == 0) 64 | .fold(0, |sum, &num| sum + num); 65 | sum as c_int 66 | } -------------------------------------------------------------------------------- /ffi/example_04/python/main.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | try: 4 | from cffi import FFI 5 | except ImportError: 6 | print "pip install cffi" 7 | 8 | ffi = FFI() 9 | 10 | ffi.cdef(""" 11 | typedef struct c_tuple { 12 | unsigned int integer; 13 | bool boolean; 14 | } c_tuple; 15 | unsigned int fibonacci(unsigned int index); 16 | unsigned int count_char(const char *s); 17 | struct c_tuple handle_tuple(struct c_tuple tup); 18 | int sum_of_even(const int *ptr, size_t len); 19 | """) 20 | 21 | lib = ffi.dlopen("../ffi/target/debug/libexample_04.so") 22 | 23 | print "fibonacci(2) from Rust: ", lib.fibonacci(2) 24 | print "fibonacci(4) from Rust: ", lib.fibonacci(4) 25 | print "fibonacci(6) from Rust: ", lib.fibonacci(6) 26 | 27 | print 'count_char("hello") from Rust: ', lib.count_char("hello") 28 | print 'count_char("你好") from Rust: ', lib.count_char(u"你好".encode('utf-8')) 29 | 30 | 31 | py_cdata = ffi.new('c_tuple *') 32 | py_cdata.integer = 100 33 | py_cdata.boolean = True 34 | print('cdata = {0}, {1}'.format(py_cdata.integer, py_cdata.boolean)) 35 | new_py_cdata = lib.handle_tuple(py_cdata[0]) 36 | print('change cdata = {0}, {1}'.format(new_py_cdata.integer, new_py_cdata.boolean)) 37 | 38 | 39 | array = ffi.new("int[]", [1, 4, 9, 16, 25]) 40 | print 'sum_of_even from Rust: ', lib.sum_of_even(array, len(array)) 41 | 42 | -------------------------------------------------------------------------------- /ffi/example_04/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub fn fibonacci(index: u32) -> u32 { 2 | if index <= 2 { 3 | 1 4 | } else { 5 | fibonacci(index - 1) + fibonacci(index - 2) 6 | } 7 | } 8 | 9 | pub fn count_char(s: &str) -> u32 { 10 | s.chars().count() as u32 11 | } 12 | 13 | pub fn handle_tuple(pair: (u32, bool)) -> (u32, bool) { 14 | let (integer, boolean) = pair; 15 | 16 | (integer + 1, !boolean) 17 | } 18 | 19 | pub fn sum_of_even_fixed(array: [i32; 10]) -> i32 { 20 | array.iter() 21 | .filter(|&&num| num % 2 == 0) 22 | .fold(0, |sum, &num| sum + num) 23 | } 24 | 25 | pub fn sum_of_even(slice: &[i32]) -> i32 { 26 | slice.iter() 27 | .filter(|&&num| num % 2 == 0) 28 | .fold(0, |sum, &num| sum + num) 29 | } 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use super::*; 34 | 35 | #[test] 36 | fn test_fibonacci() { 37 | assert_eq!(fibonacci(2), 1); 38 | assert_eq!(fibonacci(4), 3); 39 | assert_eq!(fibonacci(6), 8); 40 | } 41 | 42 | #[test] 43 | fn test_count_char() { 44 | let hello = "hello"; 45 | assert_eq!(count_char(hello), 5); 46 | let hello_utf8 = "你好"; 47 | assert_eq!(count_char(hello_utf8), 2); 48 | } 49 | 50 | #[test] 51 | fn test_handle_tuple() { 52 | let pair = (100, true); 53 | assert_eq!(handle_tuple(pair), (101, false)); 54 | } 55 | 56 | #[test] 57 | fn test_sum_of_even() { 58 | let array = [1,2,3,4,5,6,7,8,9,10]; 59 | assert_eq!(sum_of_even(&array), 30); 60 | assert_eq!(sum_of_even(&array[..5]), 6); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ffi/example_09/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | vgcore.* 13 | -------------------------------------------------------------------------------- /ffi/example_09/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "example_09" 3 | version = "0.1.0" 4 | authors = ["ubuntu"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /ffi/example_09/csrc/cfoo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef struct Student 6 | { 7 | int num; 8 | int total; 9 | char name[20]; 10 | float scores[3]; 11 | } Student; 12 | 13 | void print_data(Student *stu) 14 | { 15 | printf("C side print: %d %s %d %.2f %.2f %.2f\n", 16 | stu->num, 17 | stu->name, 18 | stu->total, 19 | stu->scores[0], 20 | stu->scores[1], 21 | stu->scores[2]); 22 | } 23 | 24 | void fill_data(Student *stu) 25 | { 26 | stu->num = 2; 27 | stu->total = 100; 28 | strcpy(stu->name, "Bob"); 29 | stu->scores[0] = 60.6; 30 | stu->scores[1] = 70.7; 31 | stu->scores[2] = 80.8; 32 | } -------------------------------------------------------------------------------- /ffi/example_09/csrc/libcfoo.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesterli/rust-practice/a50cae0eddc75999fb5bae4fe4b34ecd78329dca/ffi/example_09/csrc/libcfoo.so -------------------------------------------------------------------------------- /ffi/example_09/libcfoo.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesterli/rust-practice/a50cae0eddc75999fb5bae4fe4b34ecd78329dca/ffi/example_09/libcfoo.so -------------------------------------------------------------------------------- /ffi/example_09/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::{c_char, c_float, c_int}; 2 | 3 | #[repr(C)] 4 | #[derive(Debug)] 5 | pub struct CStudent { 6 | pub num: c_int, 7 | pub total: c_int, 8 | pub name: [c_char; 20], 9 | pub scores: [c_float; 3], 10 | } 11 | 12 | // Default constructor 13 | impl Default for CStudent { 14 | fn default() -> Self { 15 | CStudent { 16 | num: 0 as c_int, 17 | total: 0 as c_int, 18 | name: [0 as c_char; 20], 19 | scores: [0.0 as c_float; 3], 20 | } 21 | } 22 | } 23 | 24 | #[link(name = "cfoo")] 25 | extern "C" { 26 | fn print_data(p_stu: *mut CStudent); 27 | fn fill_data(p_stu: *mut CStudent); 28 | } 29 | 30 | 31 | fn main() { 32 | // Initialization of allocated memory 33 | let new_stu: CStudent = Default::default(); 34 | println!("rust side print new_stu: {:?}", new_stu); 35 | let box_new_stu = Box::new(new_stu); 36 | let p_stu = Box::into_raw(box_new_stu); 37 | 38 | unsafe { 39 | fill_data(p_stu); 40 | print_data(p_stu); 41 | //Box::from_raw(p_stu); 42 | println!("rust side print Bob: {:?}", Box::from_raw(p_stu)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ffi/example_10/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | vgcore.* 13 | -------------------------------------------------------------------------------- /ffi/example_10/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "example_10" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /ffi/example_10/csrc/compile.sh: -------------------------------------------------------------------------------- 1 | gcc -fPIC -shared -o ../libsumsquare.so sumsquare.c -------------------------------------------------------------------------------- /ffi/example_10/csrc/sumsquare.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef void (*SumSquareCB)(int result, void *user_data); 4 | 5 | void sum_square_cb(int a, int b, SumSquareCB cb, void *user_data) { 6 | int result = a*a + b*b; 7 | cb(result, user_data); 8 | } -------------------------------------------------------------------------------- /ffi/example_10/libsumsquare.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesterli/rust-practice/a50cae0eddc75999fb5bae4fe4b34ecd78329dca/ffi/example_10/libsumsquare.so -------------------------------------------------------------------------------- /ffi/example_10/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::{c_int, c_void}; 2 | 3 | pub type SumSquareCB = unsafe extern fn(c_int, *mut c_void); 4 | 5 | #[link(name = "sumsquare")] 6 | extern { 7 | pub fn sum_square_cb(a: c_int, b: c_int, cb: SumSquareCB, user_data: *mut c_void); 8 | } 9 | 10 | unsafe extern fn hook(result: c_int, user_data: *mut c_void) 11 | where 12 | F: FnMut(c_int), 13 | { 14 | (*(user_data as *mut F))(result) 15 | } 16 | 17 | pub fn get_callback(_closure: &F) -> SumSquareCB 18 | where 19 | F: FnMut(c_int), 20 | { 21 | hook:: 22 | } 23 | 24 | #[derive(Debug, Default, Clone, PartialEq)] 25 | struct SumRecord { 26 | total: c_int, 27 | calls: usize, 28 | } 29 | 30 | fn main() { 31 | let mut record = SumRecord::default(); 32 | 33 | unsafe { 34 | let mut closure = |result: c_int| { 35 | record.total += result; 36 | record.calls += 1; 37 | }; 38 | let callback = get_callback(&closure); 39 | 40 | sum_square_cb(1, 2, callback, &mut closure as *mut _ as *mut c_void); 41 | 42 | sum_square_cb(3, 4, callback, &mut closure as *mut _ as *mut c_void); 43 | } 44 | 45 | println!("The sum is {:?}", record); 46 | } 47 | -------------------------------------------------------------------------------- /ffi/nix/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /ffi/nix/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nix" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | nix = "0.17.0" -------------------------------------------------------------------------------- /ffi/nix/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | pid_t child = fork(); 7 | if (child) 8 | { 9 | sleep(5); 10 | kill(child, SIGKILL); 11 | } 12 | else 13 | { 14 | for (;;) 15 | // 循环直到被 kill 掉 16 | ; 17 | } 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /ffi/nix/src/main.rs: -------------------------------------------------------------------------------- 1 | // use nix::unistd::*; 2 | 3 | // fn main() { 4 | // match fork() { 5 | // Ok(ForkResult::Parent { child }) => { 6 | // // 在父进程中 7 | // println!("Hello, I am parent thread: {}", getpid()); 8 | // } 9 | // Ok(ForkResult::Child) => { 10 | // // 在子进程中 11 | // println!("Hello, I am child thread: {}", getpid()); 12 | // println!("My parent thread: {}", getppid()); 13 | // } 14 | // Err(errno) => { 15 | // // fork 创建子进程失败 16 | // println!("Fork creation failed!"); 17 | // } 18 | // } 19 | // } 20 | 21 | use nix::sys::signal::*; 22 | use nix::unistd::*; 23 | 24 | fn main() { 25 | match fork().expect("fork failed") { 26 | ForkResult::Parent{ child } => { 27 | sleep(5); 28 | kill(child, SIGKILL).expect("kill failed"); 29 | } 30 | ForkResult::Child => { 31 | // 直到被 kill 掉 32 | loop {} 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /ffi/rust-call-c/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /ffi/rust-call-c/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-call-c" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | libc = "0.2" 11 | libloading = "0.6.2" -------------------------------------------------------------------------------- /ffi/rust-call-c/src/array.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::c_int; 2 | 3 | // 对 C 库中的 sum 函数进行 Rust 绑定: 4 | extern "C" { 5 | fn sum(my_array: *const c_int, length: c_int) -> c_int; 6 | } 7 | 8 | fn main() { 9 | let numbers: [c_int; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 10 | 11 | unsafe { 12 | let total = sum(numbers.as_ptr(), numbers.len() as c_int); 13 | println!("The total is {}", total); 14 | 15 | assert_eq!(total, numbers.iter().sum()); 16 | } 17 | } -------------------------------------------------------------------------------- /ffi/rust-call-c/src/ffi_array/c_utils.c: -------------------------------------------------------------------------------- 1 | int sum(const int* my_array, int length) { 2 | int total = 0; 3 | 4 | for(int i = 0; i < length; i++) { 5 | total += my_array[i]; 6 | } 7 | 8 | return total; 9 | } -------------------------------------------------------------------------------- /ffi/rust-call-c/src/ffi_array/libc_utils.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesterli/rust-practice/a50cae0eddc75999fb5bae4fe4b34ecd78329dca/ffi/rust-call-c/src/ffi_array/libc_utils.so -------------------------------------------------------------------------------- /ffi/rust-call-c/src/ffi_opaque/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -Werror 3 | OBJ=libffi_test.o 4 | 5 | libffi_test.so: $(OBJ) 6 | gcc -shared -o $@ $(OBJ) 7 | 8 | $(OBJ): ffi_test.c ffi_test.h 9 | $(CC) -c -o $(OBJ) -fpic $< $(CFLAGS) -------------------------------------------------------------------------------- /ffi/rust-call-c/src/ffi_opaque/ffi_test.c: -------------------------------------------------------------------------------- 1 | #include "ffi_test.h" 2 | 3 | struct object { 4 | int info; 5 | }; 6 | 7 | /** 8 | * Returns the size of the object struct. 9 | */ 10 | size_t sizeof_obj(void) { 11 | return sizeof(struct object); 12 | } 13 | 14 | /** 15 | * Allocates memory for a new object on the heap and returns a pointer to it. 16 | */ 17 | struct object* init(void) { 18 | struct object* obj = (struct object*)malloc(sizeof_obj()); 19 | obj->info = 0; 20 | 21 | return obj; 22 | } 23 | 24 | /** 25 | * Frees the memory allocated for the object. 26 | */ 27 | void free_object(struct object* obj) { 28 | free(obj); 29 | } 30 | 31 | /** 32 | * Returns the version of the C API used by this library. 33 | */ 34 | int get_api_version(void) { 35 | return 0; 36 | } 37 | 38 | /** 39 | * Returns the value of the info field of the given object struct. 40 | */ 41 | int get_info(const struct object* obj) { 42 | return obj->info; 43 | } 44 | 45 | /** 46 | * Sets the info field of the object struct. 47 | */ 48 | void set_info(struct object* obj, int arg) { 49 | obj->info = arg; 50 | } -------------------------------------------------------------------------------- /ffi/rust-call-c/src/ffi_opaque/ffi_test.h: -------------------------------------------------------------------------------- 1 | #ifndef FFI_TEST_H 2 | #define FFI_TEST_H 3 | 4 | #include 5 | 6 | struct object; 7 | 8 | struct object* init(void); 9 | void free_object(struct object*); 10 | int get_api_version(void); 11 | int get_info(const struct object*); 12 | void set_info(struct object*, int); 13 | size_t sizeof_obj(void); 14 | 15 | #endif /* FFI_TEST_H */ -------------------------------------------------------------------------------- /ffi/rust-call-c/src/ffi_opaque/libffi_test.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lesterli/rust-practice/a50cae0eddc75999fb5bae4fe4b34ecd78329dca/ffi/rust-call-c/src/ffi_opaque/libffi_test.so -------------------------------------------------------------------------------- /ffi/rust-call-c/src/layout.rs: -------------------------------------------------------------------------------- 1 | use std::mem; 2 | 3 | // 默认布局 4 | struct DefaultStruct { 5 | first: i8, 6 | second: i16, 7 | third: i8 8 | } 9 | 10 | // 默认布局,对齐方式降低到 1 11 | #[repr(packed(1))] 12 | struct PackedStruct { 13 | first: i8, 14 | second: i16, 15 | third: i8 16 | } 17 | 18 | // C 布局 19 | #[repr(C)] 20 | struct CStruct { 21 | first: i8, 22 | second: i16, 23 | third: i8 24 | } 25 | 26 | // C 布局, 对齐方式升高到 4 27 | #[repr(C, align(4))] 28 | struct AlignedStruct { 29 | first: i8, 30 | second: i16, 31 | third: i8 32 | } 33 | 34 | // C 布局的元组结构体 35 | #[repr(C)] 36 | struct TupleStruct(i8, i16, i8); 37 | 38 | // C 布局,重新调整字段的顺序可以缩小类型大小 39 | #[repr(C)] 40 | struct FieldStructOptimized { 41 | first: i8, 42 | third: i8, 43 | second: i16 44 | } 45 | 46 | // 联合类型的大小等于其字段类型的最大值 47 | #[repr(C)] 48 | union ExampleUnion { 49 | smaller: i8, 50 | larger: i16 51 | } 52 | 53 | 54 | fn main() { 55 | assert_eq!(mem::align_of::(), 2); 56 | assert_eq!(mem::size_of::(), 6); 57 | assert_eq!(mem::align_of::(), 2); 58 | 59 | assert_eq!(mem::align_of::(), 1); 60 | assert_eq!(mem::align_of::(), 4); 61 | 62 | assert_eq!(mem::size_of::(), 4); 63 | 64 | assert_eq!(mem::size_of::(), 6); 65 | 66 | assert_eq!(mem::size_of::(), 2); 67 | } -------------------------------------------------------------------------------- /ffi/rust-call-c/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::ffi::CString; 2 | use std::os::raw::c_char; 3 | 4 | // 外部块 5 | extern "C" { 6 | // 标准库 abs函数 7 | #[link_name = "abs"] 8 | fn abs_in_rust(input: i32) -> i32; 9 | 10 | #[link_name = "printf"] 11 | fn printf_in_rust(input: *const c_char) -> i32; 12 | } 13 | 14 | fn abs_example() { 15 | unsafe { 16 | println!("abs(-1) is {}", abs_in_rust(-1)); 17 | } 18 | } 19 | 20 | use std::str; 21 | 22 | mod time; 23 | 24 | fn time_example() { 25 | let mut v: Vec = vec![0; 80]; 26 | let mut t = time::tm { 27 | tm_sec: 15, 28 | tm_min: 09, 29 | tm_hour: 18, 30 | tm_mday: 14, 31 | tm_mon: 04, 32 | tm_year: 120, 33 | tm_wday: 4, 34 | tm_yday: 135, 35 | tm_isdst: 0, 36 | }; 37 | let format = b"%Y-%m-%d %H:%M:%S\0".as_ptr(); 38 | unsafe { 39 | time::strftime_in_rust(v.as_mut_ptr(), 80, format, &mut t); 40 | 41 | let s = match str::from_utf8(v.as_slice()) { 42 | Ok(r) => r, 43 | Err(e) => panic!("Invalid UTF-8 sequence: {}", e), 44 | }; 45 | 46 | println!("result: {}", s); 47 | } 48 | } 49 | 50 | fn main() { 51 | abs_example(); 52 | time_example(); 53 | } -------------------------------------------------------------------------------- /ffi/rust-call-c/src/opaque.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::c_int; 2 | 3 | 4 | #[repr(C)] 5 | pub struct OpaqueObject { 6 | _private: [u8; 0], 7 | } 8 | 9 | extern "C" { 10 | pub fn free_object(obj: *mut OpaqueObject); 11 | pub fn init() -> *mut OpaqueObject; 12 | pub fn get_api_version() -> c_int; 13 | pub fn get_info(obj: *const OpaqueObject) -> c_int; 14 | pub fn set_info(obj: *mut OpaqueObject, info: c_int); 15 | } 16 | 17 | fn main() { 18 | unsafe { 19 | let obj = init(); 20 | println!("Original value: {}", get_info(obj)); 21 | 22 | set_info(obj, 521); 23 | println!("New value: {}", get_info(obj)); 24 | } 25 | } -------------------------------------------------------------------------------- /ffi/rust-call-c/src/time.rs: -------------------------------------------------------------------------------- 1 | use libc::{c_int, size_t}; 2 | 3 | #[repr(C)] 4 | pub struct tm { 5 | pub tm_sec: c_int, 6 | pub tm_min: c_int, 7 | pub tm_hour: c_int, 8 | pub tm_mday: c_int, 9 | pub tm_mon: c_int, 10 | pub tm_year: c_int, 11 | pub tm_wday: c_int, 12 | pub tm_yday: c_int, 13 | pub tm_isdst: c_int, 14 | } 15 | 16 | 17 | extern { 18 | // 标准库 strftime函数的 Rust FFI 绑定 19 | #[link_name = "strftime"] 20 | pub fn strftime_in_rust(stra: *mut u8, maxsize: size_t, format: *const u8, timeptr: *mut tm) -> size_t; 21 | } -------------------------------------------------------------------------------- /ffi/secp256k1-sys/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /ffi/secp256k1-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "libsecp256k1-sys" 3 | version = "0.1.0" 4 | authors = ["ubuntu"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [lib] 10 | name = "secp256k1" 11 | path = "src/lib.rs" 12 | 13 | [dependencies] 14 | 15 | [build-dependencies] 16 | bindgen = "0.55.1" 17 | -------------------------------------------------------------------------------- /ffi/secp256k1-sys/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::path::PathBuf; 3 | 4 | fn main() { 5 | println!("cargo:rustc-link-lib=secp256k1"); 6 | println!("cargo:rerun-if-changed=wrapper.h"); 7 | 8 | let bindings = bindgen::Builder::default() 9 | .header("wrapper.h") 10 | .parse_callbacks(Box::new(bindgen::CargoCallbacks)) 11 | .generate() 12 | .expect("Unable to generate bindings"); 13 | 14 | let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); 15 | bindings 16 | .write_to_file(out_path.join("bindings.rs")) 17 | .expect("Couldn't write bindings!"); 18 | } -------------------------------------------------------------------------------- /ffi/secp256k1-sys/include/secp256k1.h: -------------------------------------------------------------------------------- 1 | #ifndef _SECP256K1_ 2 | # define _SECP256K1_ 3 | 4 | # ifdef __cplusplus 5 | extern "C" { 6 | # endif 7 | 8 | #include 9 | 10 | /* These rules specify the order of arguments in API calls: 11 | * 12 | * 1. Context pointers go first, followed by output arguments, combined 13 | * output/input arguments, and finally input-only arguments. 14 | * 2. Array lengths always immediately the follow the argument whose length 15 | * they describe, even if this violates rule 1. 16 | * 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated 17 | * later go first. This means: signatures, public nonces, private nonces, 18 | * messages, public keys, secret keys, tweaks. 19 | * 4. Arguments that are not data pointers go last, from more complex to less 20 | * complex: function pointers, algorithm names, messages, void pointers, 21 | * counts, flags, booleans. 22 | * 5. Opaque data pointers follow the function pointer they are to be passed to. 23 | */ 24 | 25 | /** Opaque data structure that holds context information (precomputed tables etc.). 26 | * 27 | * The purpose of context structures is to cache large precomputed data tables 28 | * that are expensive to construct, and also to maintain the randomization data 29 | * for blinding. 30 | * 31 | * Do not create a new context object for each operation, as construction is 32 | * far slower than all other API calls (~100 times slower than an ECDSA 33 | * verification). 34 | * 35 | * A constructed context can safely be used from multiple threads 36 | * simultaneously, but API call that take a non-const pointer to a context 37 | * need exclusive access to it. In particular this is the case for 38 | * secp256k1_context_destroy and secp256k1_context_randomize. 39 | * 40 | * Regarding randomization, either do it once at creation time (in which case 41 | * you do not need any locking for the other calls), or use a read-write lock. 42 | */ 43 | typedef struct secp256k1_context_struct secp256k1_context; 44 | 45 | /** Opaque data structure that holds a parsed and valid public key. 46 | * 47 | * The exact representation of data inside is implementation defined and not 48 | * guaranteed to be portable between different platforms or versions. It is 49 | * however guaranteed to be 64 bytes in size, and can be safely copied/moved. 50 | * If you need to convert to a format suitable for storage, transmission, or 51 | * comparison, use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. 52 | */ 53 | typedef struct { 54 | unsigned char data[64]; 55 | } secp256k1_pubkey; 56 | 57 | /** Opaque data structured that holds a parsed ECDSA signature. 58 | * 59 | * The exact representation of data inside is implementation defined and not 60 | * guaranteed to be portable between different platforms or versions. It is 61 | * however guaranteed to be 64 bytes in size, and can be safely copied/moved. 62 | * If you need to convert to a format suitable for storage, transmission, or 63 | * comparison, use the secp256k1_ecdsa_signature_serialize_* and 64 | * secp256k1_ecdsa_signature_parse_* functions. 65 | */ 66 | typedef struct { 67 | unsigned char data[64]; 68 | } secp256k1_ecdsa_signature; 69 | 70 | /** A pointer to a function to deterministically generate a nonce. 71 | * 72 | * Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. 73 | * Out: nonce32: pointer to a 32-byte array to be filled by the function. 74 | * In: msg32: the 32-byte message hash being verified (will not be NULL) 75 | * key32: pointer to a 32-byte secret key (will not be NULL) 76 | * algo16: pointer to a 16-byte array describing the signature 77 | * algorithm (will be NULL for ECDSA for compatibility). 78 | * data: Arbitrary data pointer that is passed through. 79 | * attempt: how many iterations we have tried to find a nonce. 80 | * This will almost always be 0, but different attempt values 81 | * are required to result in a different nonce. 82 | * 83 | * Except for test cases, this function should compute some cryptographic hash of 84 | * the message, the algorithm, the key and the attempt. 85 | */ 86 | typedef int (*secp256k1_nonce_function)( 87 | unsigned char *nonce32, 88 | const unsigned char *msg32, 89 | const unsigned char *key32, 90 | const unsigned char *algo16, 91 | void *data, 92 | unsigned int attempt 93 | ); 94 | 95 | # if !defined(SECP256K1_GNUC_PREREQ) 96 | # if defined(__GNUC__)&&defined(__GNUC_MINOR__) 97 | # define SECP256K1_GNUC_PREREQ(_maj,_min) \ 98 | ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) 99 | # else 100 | # define SECP256K1_GNUC_PREREQ(_maj,_min) 0 101 | # endif 102 | # endif 103 | 104 | # if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) 105 | # if SECP256K1_GNUC_PREREQ(2,7) 106 | # define SECP256K1_INLINE __inline__ 107 | # elif (defined(_MSC_VER)) 108 | # define SECP256K1_INLINE __inline 109 | # else 110 | # define SECP256K1_INLINE 111 | # endif 112 | # else 113 | # define SECP256K1_INLINE inline 114 | # endif 115 | 116 | #ifndef SECP256K1_API 117 | # if defined(_WIN32) 118 | # ifdef SECP256K1_BUILD 119 | # define SECP256K1_API __declspec(dllexport) 120 | # else 121 | # define SECP256K1_API 122 | # endif 123 | # elif defined(__GNUC__) && defined(SECP256K1_BUILD) 124 | # define SECP256K1_API __attribute__ ((visibility ("default"))) 125 | # else 126 | # define SECP256K1_API 127 | # endif 128 | #endif 129 | 130 | /**Warning attributes 131 | * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out 132 | * some paranoid null checks. */ 133 | # if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) 134 | # define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) 135 | # else 136 | # define SECP256K1_WARN_UNUSED_RESULT 137 | # endif 138 | # if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) 139 | # define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) 140 | # else 141 | # define SECP256K1_ARG_NONNULL(_x) 142 | # endif 143 | 144 | /** All flags' lower 8 bits indicate what they're for. Do not use directly. */ 145 | #define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) 146 | #define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) 147 | #define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) 148 | /** The higher bits contain the actual data. Do not use directly. */ 149 | #define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) 150 | #define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) 151 | #define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) 152 | 153 | /** Flags to pass to secp256k1_context_create. */ 154 | #define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) 155 | #define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) 156 | #define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) 157 | 158 | /** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */ 159 | #define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) 160 | #define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) 161 | 162 | /** Prefix byte used to tag various encoded curvepoints for specific purposes */ 163 | #define SECP256K1_TAG_PUBKEY_EVEN 0x02 164 | #define SECP256K1_TAG_PUBKEY_ODD 0x03 165 | #define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04 166 | #define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06 167 | #define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 168 | 169 | /** Create a secp256k1 context object. 170 | * 171 | * Returns: a newly created context object. 172 | * In: flags: which parts of the context to initialize. 173 | * 174 | * See also secp256k1_context_randomize. 175 | */ 176 | SECP256K1_API secp256k1_context* secp256k1_context_create( 177 | unsigned int flags 178 | ) SECP256K1_WARN_UNUSED_RESULT; 179 | 180 | /** Copies a secp256k1 context object. 181 | * 182 | * Returns: a newly created context object. 183 | * Args: ctx: an existing context to copy (cannot be NULL) 184 | */ 185 | SECP256K1_API secp256k1_context* secp256k1_context_clone( 186 | const secp256k1_context* ctx 187 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; 188 | 189 | /** Destroy a secp256k1 context object. 190 | * 191 | * The context pointer may not be used afterwards. 192 | * Args: ctx: an existing context to destroy (cannot be NULL) 193 | */ 194 | SECP256K1_API void secp256k1_context_destroy( 195 | secp256k1_context* ctx 196 | ); 197 | 198 | /** Set a callback function to be called when an illegal argument is passed to 199 | * an API call. It will only trigger for violations that are mentioned 200 | * explicitly in the header. 201 | * 202 | * The philosophy is that these shouldn't be dealt with through a 203 | * specific return value, as calling code should not have branches to deal with 204 | * the case that this code itself is broken. 205 | * 206 | * On the other hand, during debug stage, one would want to be informed about 207 | * such mistakes, and the default (crashing) may be inadvisable. 208 | * When this callback is triggered, the API function called is guaranteed not 209 | * to cause a crash, though its return value and output arguments are 210 | * undefined. 211 | * 212 | * Args: ctx: an existing context object (cannot be NULL) 213 | * In: fun: a pointer to a function to call when an illegal argument is 214 | * passed to the API, taking a message and an opaque pointer 215 | * (NULL restores a default handler that calls abort). 216 | * data: the opaque pointer to pass to fun above. 217 | */ 218 | SECP256K1_API void secp256k1_context_set_illegal_callback( 219 | secp256k1_context* ctx, 220 | void (*fun)(const char* message, void* data), 221 | const void* data 222 | ) SECP256K1_ARG_NONNULL(1); 223 | 224 | /** Set a callback function to be called when an internal consistency check 225 | * fails. The default is crashing. 226 | * 227 | * This can only trigger in case of a hardware failure, miscompilation, 228 | * memory corruption, serious bug in the library, or other error would can 229 | * otherwise result in undefined behaviour. It will not trigger due to mere 230 | * incorrect usage of the API (see secp256k1_context_set_illegal_callback 231 | * for that). After this callback returns, anything may happen, including 232 | * crashing. 233 | * 234 | * Args: ctx: an existing context object (cannot be NULL) 235 | * In: fun: a pointer to a function to call when an internal error occurs, 236 | * taking a message and an opaque pointer (NULL restores a default 237 | * handler that calls abort). 238 | * data: the opaque pointer to pass to fun above. 239 | */ 240 | SECP256K1_API void secp256k1_context_set_error_callback( 241 | secp256k1_context* ctx, 242 | void (*fun)(const char* message, void* data), 243 | const void* data 244 | ) SECP256K1_ARG_NONNULL(1); 245 | 246 | /** Parse a variable-length public key into the pubkey object. 247 | * 248 | * Returns: 1 if the public key was fully valid. 249 | * 0 if the public key could not be parsed or is invalid. 250 | * Args: ctx: a secp256k1 context object. 251 | * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a 252 | * parsed version of input. If not, its value is undefined. 253 | * In: input: pointer to a serialized public key 254 | * inputlen: length of the array pointed to by input 255 | * 256 | * This function supports parsing compressed (33 bytes, header byte 0x02 or 257 | * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header 258 | * byte 0x06 or 0x07) format public keys. 259 | */ 260 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( 261 | const secp256k1_context* ctx, 262 | secp256k1_pubkey* pubkey, 263 | const unsigned char *input, 264 | size_t inputlen 265 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 266 | 267 | /** Serialize a pubkey object into a serialized byte sequence. 268 | * 269 | * Returns: 1 always. 270 | * Args: ctx: a secp256k1 context object. 271 | * Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if 272 | * compressed==1) byte array to place the serialized key 273 | * in. 274 | * In/Out: outputlen: a pointer to an integer which is initially set to the 275 | * size of output, and is overwritten with the written 276 | * size. 277 | * In: pubkey: a pointer to a secp256k1_pubkey containing an 278 | * initialized public key. 279 | * flags: SECP256K1_EC_COMPRESSED if serialization should be in 280 | * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. 281 | */ 282 | SECP256K1_API int secp256k1_ec_pubkey_serialize( 283 | const secp256k1_context* ctx, 284 | unsigned char *output, 285 | size_t *outputlen, 286 | const secp256k1_pubkey* pubkey, 287 | unsigned int flags 288 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 289 | 290 | /** Parse an ECDSA signature in compact (64 bytes) format. 291 | * 292 | * Returns: 1 when the signature could be parsed, 0 otherwise. 293 | * Args: ctx: a secp256k1 context object 294 | * Out: sig: a pointer to a signature object 295 | * In: input64: a pointer to the 64-byte array to parse 296 | * 297 | * The signature must consist of a 32-byte big endian R value, followed by a 298 | * 32-byte big endian S value. If R or S fall outside of [0..order-1], the 299 | * encoding is invalid. R and S with value 0 are allowed in the encoding. 300 | * 301 | * After the call, sig will always be initialized. If parsing failed or R or 302 | * S are zero, the resulting sig value is guaranteed to fail validation for any 303 | * message and public key. 304 | */ 305 | SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( 306 | const secp256k1_context* ctx, 307 | secp256k1_ecdsa_signature* sig, 308 | const unsigned char *input64 309 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 310 | 311 | /** Parse a DER ECDSA signature. 312 | * 313 | * Returns: 1 when the signature could be parsed, 0 otherwise. 314 | * Args: ctx: a secp256k1 context object 315 | * Out: sig: a pointer to a signature object 316 | * In: input: a pointer to the signature to be parsed 317 | * inputlen: the length of the array pointed to be input 318 | * 319 | * This function will accept any valid DER encoded signature, even if the 320 | * encoded numbers are out of range. 321 | * 322 | * After the call, sig will always be initialized. If parsing failed or the 323 | * encoded numbers are out of range, signature validation with it is 324 | * guaranteed to fail for every message and public key. 325 | */ 326 | SECP256K1_API int secp256k1_ecdsa_signature_parse_der( 327 | const secp256k1_context* ctx, 328 | secp256k1_ecdsa_signature* sig, 329 | const unsigned char *input, 330 | size_t inputlen 331 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 332 | 333 | /** Serialize an ECDSA signature in DER format. 334 | * 335 | * Returns: 1 if enough space was available to serialize, 0 otherwise 336 | * Args: ctx: a secp256k1 context object 337 | * Out: output: a pointer to an array to store the DER serialization 338 | * In/Out: outputlen: a pointer to a length integer. Initially, this integer 339 | * should be set to the length of output. After the call 340 | * it will be set to the length of the serialization (even 341 | * if 0 was returned). 342 | * In: sig: a pointer to an initialized signature object 343 | */ 344 | SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( 345 | const secp256k1_context* ctx, 346 | unsigned char *output, 347 | size_t *outputlen, 348 | const secp256k1_ecdsa_signature* sig 349 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 350 | 351 | /** Serialize an ECDSA signature in compact (64 byte) format. 352 | * 353 | * Returns: 1 354 | * Args: ctx: a secp256k1 context object 355 | * Out: output64: a pointer to a 64-byte array to store the compact serialization 356 | * In: sig: a pointer to an initialized signature object 357 | * 358 | * See secp256k1_ecdsa_signature_parse_compact for details about the encoding. 359 | */ 360 | SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( 361 | const secp256k1_context* ctx, 362 | unsigned char *output64, 363 | const secp256k1_ecdsa_signature* sig 364 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 365 | 366 | /** Verify an ECDSA signature. 367 | * 368 | * Returns: 1: correct signature 369 | * 0: incorrect or unparseable signature 370 | * Args: ctx: a secp256k1 context object, initialized for verification. 371 | * In: sig: the signature being verified (cannot be NULL) 372 | * msg32: the 32-byte message hash being verified (cannot be NULL) 373 | * pubkey: pointer to an initialized public key to verify with (cannot be NULL) 374 | * 375 | * To avoid accepting malleable signatures, only ECDSA signatures in lower-S 376 | * form are accepted. 377 | * 378 | * If you need to accept ECDSA signatures from sources that do not obey this 379 | * rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to 380 | * validation, but be aware that doing so results in malleable signatures. 381 | * 382 | * For details, see the comments for that function. 383 | */ 384 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( 385 | const secp256k1_context* ctx, 386 | const secp256k1_ecdsa_signature *sig, 387 | const unsigned char *msg32, 388 | const secp256k1_pubkey *pubkey 389 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 390 | 391 | /** Convert a signature to a normalized lower-S form. 392 | * 393 | * Returns: 1 if sigin was not normalized, 0 if it already was. 394 | * Args: ctx: a secp256k1 context object 395 | * Out: sigout: a pointer to a signature to fill with the normalized form, 396 | * or copy if the input was already normalized. (can be NULL if 397 | * you're only interested in whether the input was already 398 | * normalized). 399 | * In: sigin: a pointer to a signature to check/normalize (cannot be NULL, 400 | * can be identical to sigout) 401 | * 402 | * With ECDSA a third-party can forge a second distinct signature of the same 403 | * message, given a single initial signature, but without knowing the key. This 404 | * is done by negating the S value modulo the order of the curve, 'flipping' 405 | * the sign of the random point R which is not included in the signature. 406 | * 407 | * Forgery of the same message isn't universally problematic, but in systems 408 | * where message malleability or uniqueness of signatures is important this can 409 | * cause issues. This forgery can be blocked by all verifiers forcing signers 410 | * to use a normalized form. 411 | * 412 | * The lower-S form reduces the size of signatures slightly on average when 413 | * variable length encodings (such as DER) are used and is cheap to verify, 414 | * making it a good choice. Security of always using lower-S is assured because 415 | * anyone can trivially modify a signature after the fact to enforce this 416 | * property anyway. 417 | * 418 | * The lower S value is always between 0x1 and 419 | * 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, 420 | * inclusive. 421 | * 422 | * No other forms of ECDSA malleability are known and none seem likely, but 423 | * there is no formal proof that ECDSA, even with this additional restriction, 424 | * is free of other malleability. Commonly used serialization schemes will also 425 | * accept various non-unique encodings, so care should be taken when this 426 | * property is required for an application. 427 | * 428 | * The secp256k1_ecdsa_sign function will by default create signatures in the 429 | * lower-S form, and secp256k1_ecdsa_verify will not accept others. In case 430 | * signatures come from a system that cannot enforce this property, 431 | * secp256k1_ecdsa_signature_normalize must be called before verification. 432 | */ 433 | SECP256K1_API int secp256k1_ecdsa_signature_normalize( 434 | const secp256k1_context* ctx, 435 | secp256k1_ecdsa_signature *sigout, 436 | const secp256k1_ecdsa_signature *sigin 437 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); 438 | 439 | /** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. 440 | * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of 441 | * extra entropy. 442 | */ 443 | SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; 444 | 445 | /** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ 446 | SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default; 447 | 448 | /** Create an ECDSA signature. 449 | * 450 | * Returns: 1: signature created 451 | * 0: the nonce generation function failed, or the private key was invalid. 452 | * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) 453 | * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) 454 | * In: msg32: the 32-byte message hash being signed (cannot be NULL) 455 | * seckey: pointer to a 32-byte secret key (cannot be NULL) 456 | * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used 457 | * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) 458 | * 459 | * The created signature is always in lower-S form. See 460 | * secp256k1_ecdsa_signature_normalize for more details. 461 | */ 462 | SECP256K1_API int secp256k1_ecdsa_sign( 463 | const secp256k1_context* ctx, 464 | secp256k1_ecdsa_signature *sig, 465 | const unsigned char *msg32, 466 | const unsigned char *seckey, 467 | secp256k1_nonce_function noncefp, 468 | const void *ndata 469 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); 470 | 471 | /** Verify an ECDSA secret key. 472 | * 473 | * Returns: 1: secret key is valid 474 | * 0: secret key is invalid 475 | * Args: ctx: pointer to a context object (cannot be NULL) 476 | * In: seckey: pointer to a 32-byte secret key (cannot be NULL) 477 | */ 478 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( 479 | const secp256k1_context* ctx, 480 | const unsigned char *seckey 481 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); 482 | 483 | /** Compute the public key for a secret key. 484 | * 485 | * Returns: 1: secret was valid, public key stores 486 | * 0: secret was invalid, try again 487 | * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) 488 | * Out: pubkey: pointer to the created public key (cannot be NULL) 489 | * In: seckey: pointer to a 32-byte private key (cannot be NULL) 490 | */ 491 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( 492 | const secp256k1_context* ctx, 493 | secp256k1_pubkey *pubkey, 494 | const unsigned char *seckey 495 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 496 | 497 | /** Negates a private key in place. 498 | * 499 | * Returns: 1 always 500 | * Args: ctx: pointer to a context object 501 | * In/Out: pubkey: pointer to the public key to be negated (cannot be NULL) 502 | */ 503 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate( 504 | const secp256k1_context* ctx, 505 | unsigned char *seckey 506 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); 507 | 508 | /** Negates a public key in place. 509 | * 510 | * Returns: 1 always 511 | * Args: ctx: pointer to a context object 512 | * In/Out: pubkey: pointer to the public key to be negated (cannot be NULL) 513 | */ 514 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate( 515 | const secp256k1_context* ctx, 516 | secp256k1_pubkey *pubkey 517 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); 518 | 519 | /** Tweak a private key by adding tweak to it. 520 | * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for 521 | * uniformly random 32-byte arrays, or if the resulting private key 522 | * would be invalid (only when the tweak is the complement of the 523 | * private key). 1 otherwise. 524 | * Args: ctx: pointer to a context object (cannot be NULL). 525 | * In/Out: seckey: pointer to a 32-byte private key. 526 | * In: tweak: pointer to a 32-byte tweak. 527 | */ 528 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( 529 | const secp256k1_context* ctx, 530 | unsigned char *seckey, 531 | const unsigned char *tweak 532 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 533 | 534 | /** Tweak a public key by adding tweak times the generator to it. 535 | * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for 536 | * uniformly random 32-byte arrays, or if the resulting public key 537 | * would be invalid (only when the tweak is the complement of the 538 | * corresponding private key). 1 otherwise. 539 | * Args: ctx: pointer to a context object initialized for validation 540 | * (cannot be NULL). 541 | * In/Out: pubkey: pointer to a public key object. 542 | * In: tweak: pointer to a 32-byte tweak. 543 | */ 544 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( 545 | const secp256k1_context* ctx, 546 | secp256k1_pubkey *pubkey, 547 | const unsigned char *tweak 548 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 549 | 550 | /** Tweak a private key by multiplying it by a tweak. 551 | * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for 552 | * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. 553 | * Args: ctx: pointer to a context object (cannot be NULL). 554 | * In/Out: seckey: pointer to a 32-byte private key. 555 | * In: tweak: pointer to a 32-byte tweak. 556 | */ 557 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( 558 | const secp256k1_context* ctx, 559 | unsigned char *seckey, 560 | const unsigned char *tweak 561 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 562 | 563 | /** Tweak a public key by multiplying it by a tweak value. 564 | * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for 565 | * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. 566 | * Args: ctx: pointer to a context object initialized for validation 567 | * (cannot be NULL). 568 | * In/Out: pubkey: pointer to a public key obkect. 569 | * In: tweak: pointer to a 32-byte tweak. 570 | */ 571 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( 572 | const secp256k1_context* ctx, 573 | secp256k1_pubkey *pubkey, 574 | const unsigned char *tweak 575 | ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 576 | 577 | /** Updates the context randomization to protect against side-channel leakage. 578 | * Returns: 1: randomization successfully updated 579 | * 0: error 580 | * Args: ctx: pointer to a context object (cannot be NULL) 581 | * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) 582 | * 583 | * While secp256k1 code is written to be constant-time no matter what secret 584 | * values are, it's possible that a future compiler may output code which isn't, 585 | * and also that the CPU may not emit the same radio frequencies or draw the same 586 | * amount power for all values. 587 | * 588 | * This function provides a seed which is combined into the blinding value: that 589 | * blinding value is added before each multiplication (and removed afterwards) so 590 | * that it does not affect function results, but shields against attacks which 591 | * rely on any input-dependent behaviour. 592 | * 593 | * You should call this after secp256k1_context_create or 594 | * secp256k1_context_clone, and may call this repeatedly afterwards. 595 | */ 596 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( 597 | secp256k1_context* ctx, 598 | const unsigned char *seed32 599 | ) SECP256K1_ARG_NONNULL(1); 600 | 601 | /** Add a number of public keys together. 602 | * Returns: 1: the sum of the public keys is valid. 603 | * 0: the sum of the public keys is not valid. 604 | * Args: ctx: pointer to a context object 605 | * Out: out: pointer to a public key object for placing the resulting public key 606 | * (cannot be NULL) 607 | * In: ins: pointer to array of pointers to public keys (cannot be NULL) 608 | * n: the number of public keys to add together (must be at least 1) 609 | */ 610 | SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( 611 | const secp256k1_context* ctx, 612 | secp256k1_pubkey *out, 613 | const secp256k1_pubkey * const * ins, 614 | size_t n 615 | ) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); 616 | 617 | # ifdef __cplusplus 618 | } 619 | # endif 620 | 621 | #endif 622 | -------------------------------------------------------------------------------- /ffi/secp256k1-sys/include/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "./secp256k1.h" 4 | 5 | // 返回16进制字符代表的整数值 6 | int hex2int(unsigned char x){ 7 | if(x >= '0' && x <= '9'){ 8 | return (x - '0'); 9 | } 10 | if(x >= 'A' && x <= 'F'){ 11 | return (x - 'A' + 10); 12 | } 13 | if(x >= 'a' && x <= 'f'){ 14 | return (x - 'a' + 10); 15 | } 16 | return -1; 17 | } 18 | /** 测试主函数 */ 19 | int main(int argc, char** argv) { 20 | unsigned char prikeyhex[] = "9a9a6539856be209b8ea2adbd155c0919646d108515b60b7b13d6a79f1ae5174"; 21 | int len = sizeof(prikeyhex) / 2; // 私钥长度 - 32字节 22 | unsigned char prikey[len]; // 私钥存储 23 | int ii; // 索引值 24 | int ret; // 返回值 25 | 26 | unsigned char CPubKey[65]; // 公钥存储 27 | size_t clen; // 返回公钥长度 28 | 29 | secp256k1_context *secp256k1_context_sign; 30 | secp256k1_pubkey pubkey; // secp256k1返回公钥 31 | // 将私钥字符串转换为字节存储 32 | for(ii = 0; ii < sizeof(prikeyhex); ii+=2){ 33 | prikey[ii/2] = hex2int(prikeyhex[ii]) * 16 + hex2int(prikeyhex[ii + 1]); 34 | } 35 | // 打印私钥 36 | printf("Private key: "); 37 | for(ii = 0; ii < len; ii++) 38 | { 39 | printf("%02x",prikey[ii]); 40 | } 41 | printf("\n"); 42 | // 生成公钥 43 | secp256k1_context_sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); 44 | ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &pubkey, prikey); 45 | 46 | // 打印公钥 47 | if(ret){ 48 | printf("Public key : "); 49 | printf("[X("); 50 | for(ii = 63; ii >= 32; ii--){ 51 | printf("%02x", pubkey.data[ii]); 52 | } 53 | printf("):Y("); 54 | for(ii = 31; ii >= 0; ii--){ 55 | printf("%02x", pubkey.data[ii]); 56 | } 57 | printf(")]\n"); 58 | // 获取压缩公钥 59 | clen = 65; 60 | secp256k1_ec_pubkey_serialize(secp256k1_context_sign, CPubKey, &clen, &pubkey, SECP256K1_EC_COMPRESSED); 61 | printf("Compressed key : "); 62 | for(ii = 0; ii < clen; ii++){ 63 | printf("%02x", CPubKey[ii]); 64 | } 65 | printf("\n"); 66 | // 获取非压缩公钥 67 | clen = 65; 68 | secp256k1_ec_pubkey_serialize(secp256k1_context_sign, CPubKey, &clen, &pubkey, SECP256K1_EC_UNCOMPRESSED); 69 | printf("Uncompressed key: "); 70 | for(ii = 0; ii < clen; ii++){ 71 | printf("%02x", CPubKey[ii]); 72 | } 73 | printf("\n"); 74 | } 75 | if (secp256k1_context_sign) { 76 | secp256k1_context_destroy(secp256k1_context_sign); 77 | } 78 | return 0; 79 | } -------------------------------------------------------------------------------- /ffi/secp256k1-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_upper_case_globals)] 2 | #![allow(non_camel_case_types)] 3 | #![allow(non_snake_case)] 4 | 5 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::*; 10 | 11 | #[test] 12 | fn test_context_sign() { 13 | assert_eq!(SECP256K1_CONTEXT_SIGN, 513); 14 | } 15 | 16 | #[test] 17 | fn test_create_pubkey() { 18 | // secp256k1返回公钥 19 | let mut pubkey: secp256k1_pubkey = secp256k1_pubkey { 20 | data: [0; 64], 21 | }; 22 | let prikey: u8 = 1; 23 | 24 | unsafe { 25 | let context = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); 26 | assert!(!context.is_null()); 27 | let ret = secp256k1_ec_pubkey_create(& *context, &mut pubkey, &prikey); 28 | assert_eq!(ret, 1); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /ffi/secp256k1-sys/wrapper.h: -------------------------------------------------------------------------------- 1 | #include -------------------------------------------------------------------------------- /head-first/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # These are backup files generated by rustfmt 6 | **/*.rs.bk 7 | 8 | .vscode 9 | -------------------------------------------------------------------------------- /head-first/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "head-first" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | clap = "2.33.0" 9 | ring = "0.16.9" 10 | 11 | merkle_tree = { package = "merkle_tree", path = "merkle-tree" } -------------------------------------------------------------------------------- /head-first/README.md: -------------------------------------------------------------------------------- 1 | # Rust实战 2 | 3 | ## 并发 4 | 5 | 创建一个新线程,调用`thread::spawn`函数并传递一个闭包,其重包含希望在新线程运行的代码。 6 | 7 | 一个确保安全并发的方式是消息传递(message passing),线程通过发送包含数据的消息来相互通信。 8 | 9 | > “Do not communicate by sharing memory; instead, share memory by communicating.” 10 | 11 | 通道(channel)来实现消息传递,创建通道,使用`mpsc::channel`函数。 12 | 13 | 不允许在线程间直接传递引用,那如何在多个线程间安全地共享变量呢? 14 | 15 | 不可变的变量,通过`Arc`来共享,它是`Rc`的线程安全版本,其内部使用了原子操作。 16 | 17 | 有两个并发概念是内嵌于语言中的:`std::marker`中的`Sync`和`Send` trait,使得并发保证能被扩展到用户定义的和标准库中提供的类型中。 18 | 19 | ## 代码实现 20 | 21 | * [并发](./std-marker/example_Send_Sync.rs) 22 | 23 | -------------------------------------------------------------------------------- /head-first/async-primer/async-example/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk -------------------------------------------------------------------------------- /head-first/async-primer/async-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "async-example" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | futures = "0.3.4" 9 | async-std = "1.5.0" -------------------------------------------------------------------------------- /head-first/async-primer/async-example/src/file.rs: -------------------------------------------------------------------------------- 1 | // use std::fs::File; 2 | // use std::io::{self, Read}; 3 | 4 | // pub async fn read_file(path: &str) -> io::Result { 5 | // let mut file = File::open(path)?; 6 | // let mut buffer = String::new(); 7 | // file.read_to_string(&mut buffer)?; 8 | // Ok(buffer) 9 | // } 10 | 11 | // We use async_std instead of std, it's that simple. 12 | use async_std::io; 13 | use async_std::fs::File; 14 | use async_std::prelude::*; 15 | 16 | pub async fn read_file(path: &str) -> io::Result { 17 | let mut file = File::open(path).await?; 18 | let mut buffer = String::new(); 19 | file.read_to_string(&mut buffer).await?; 20 | Ok(buffer) 21 | } -------------------------------------------------------------------------------- /head-first/async-primer/async-example/src/file1.txt: -------------------------------------------------------------------------------- 1 | file1 2 | file 3 | file 4 | file 5 | file 6 | file 7 | file 8 | file1 9 | file 10 | file 11 | file 12 | file 13 | file 14 | file 15 | file1 16 | file 17 | file 18 | file 19 | file 20 | file 21 | file 22 | file1 23 | file 24 | file 25 | file 26 | file 27 | file 28 | file 29 | file1 30 | file 31 | file 32 | file 33 | file 34 | file 35 | file 36 | file1 37 | file 38 | file 39 | file 40 | file 41 | file 42 | file 43 | file1 44 | file 45 | file 46 | file 47 | file 48 | file 49 | file 50 | file1 51 | file 52 | file 53 | file 54 | file 55 | file 56 | file 57 | file1 58 | file 59 | file 60 | file 61 | file 62 | file 63 | file 64 | file1 65 | file 66 | file 67 | file 68 | file 69 | file 70 | file 71 | file1 72 | file 73 | file 74 | file 75 | file 76 | file 77 | file 78 | file1 79 | file 80 | file 81 | file 82 | file 83 | file 84 | file 85 | file1 86 | file 87 | file 88 | file 89 | file 90 | file 91 | file 92 | file1 93 | file 94 | file 95 | file 96 | file 97 | file 98 | file 99 | file1 100 | file 101 | file 102 | file 103 | file 104 | file 105 | file 106 | file1 107 | file 108 | file 109 | file 110 | file 111 | file 112 | file 113 | file1 114 | file 115 | file 116 | file 117 | file 118 | file 119 | file 120 | file1 121 | file 122 | file 123 | file 124 | file 125 | file 126 | file 127 | file1 128 | file 129 | file 130 | file 131 | file 132 | file 133 | file 134 | file1 135 | file 136 | file 137 | file 138 | file 139 | file 140 | file 141 | file1 142 | file 143 | file 144 | file 145 | file 146 | file 147 | file 148 | file1 149 | file 150 | file 151 | file 152 | file 153 | file 154 | file 155 | file1 156 | file 157 | file 158 | file 159 | file 160 | file 161 | file 162 | file1 163 | file 164 | file 165 | file 166 | file 167 | file 168 | file 169 | file1 170 | file 171 | file 172 | file 173 | file 174 | file 175 | file 176 | file1 177 | file 178 | file 179 | file 180 | file 181 | file 182 | file 183 | file1 184 | file 185 | file 186 | file 187 | file 188 | file 189 | file 190 | file1 191 | file 192 | file 193 | file 194 | file 195 | file 196 | file 197 | file1 198 | file 199 | file 200 | file 201 | file 202 | file 203 | file 204 | file1 205 | file 206 | file 207 | file 208 | file 209 | file 210 | file 211 | file1 212 | file 213 | file 214 | file 215 | file 216 | file 217 | file 218 | file1 219 | file 220 | file 221 | file 222 | file 223 | file 224 | file 225 | file1 226 | file 227 | file 228 | file 229 | file 230 | file 231 | file 232 | file1 233 | file 234 | file 235 | file 236 | file 237 | file 238 | file 239 | file1 240 | file 241 | file 242 | file 243 | file 244 | file 245 | file 246 | file1 247 | file 248 | file 249 | file 250 | file 251 | file 252 | file 253 | file1 254 | file 255 | file 256 | file 257 | file 258 | file 259 | file 260 | file1 261 | file 262 | file 263 | file 264 | file 265 | file 266 | file 267 | file1 268 | file 269 | file 270 | file 271 | file 272 | file 273 | file 274 | file1 275 | file 276 | file 277 | file 278 | file 279 | file 280 | file 281 | file1 282 | file 283 | file 284 | file 285 | file 286 | file 287 | file 288 | file1 289 | file 290 | file 291 | file 292 | file 293 | file 294 | file 295 | file1 296 | file 297 | file 298 | file 299 | file 300 | file 301 | file 302 | file1 303 | file 304 | file 305 | file 306 | file 307 | file 308 | file 309 | file1 310 | file 311 | file 312 | file 313 | file 314 | file 315 | file 316 | file1 317 | file 318 | file 319 | file 320 | file 321 | file 322 | file 323 | file1 324 | file 325 | file 326 | file 327 | file 328 | file 329 | file 330 | file1 331 | file 332 | file 333 | file 334 | file 335 | file 336 | file 337 | file1 338 | file 339 | file 340 | file 341 | file 342 | file 343 | file 344 | file1 345 | file 346 | file 347 | file 348 | file 349 | file 350 | file 351 | file1 352 | file 353 | file 354 | file 355 | file 356 | file 357 | file 358 | file1 359 | file 360 | file 361 | file 362 | file 363 | file 364 | file 365 | file1 366 | file 367 | file 368 | file 369 | file 370 | file 371 | file 372 | file1 373 | file 374 | file 375 | file 376 | file 377 | file 378 | file 379 | file1 380 | file 381 | file 382 | file 383 | file 384 | file 385 | file 386 | file1 387 | file 388 | file 389 | file 390 | file 391 | file 392 | file 393 | file1 394 | file 395 | file 396 | file 397 | file 398 | file 399 | file 400 | file1 401 | file 402 | file 403 | file 404 | file 405 | file 406 | file 407 | file1 408 | file 409 | file 410 | file 411 | file 412 | file 413 | file 414 | file1 415 | file 416 | file 417 | file 418 | file 419 | file 420 | file 421 | file1 422 | file 423 | file 424 | file 425 | file 426 | file 427 | file 428 | file1 429 | file 430 | file 431 | file 432 | file 433 | file 434 | file 435 | file1 436 | file 437 | file 438 | file 439 | file 440 | file 441 | file 442 | file1 443 | file 444 | file 445 | file 446 | file 447 | file 448 | file 449 | file1 450 | file 451 | file 452 | file 453 | file 454 | file 455 | file 456 | file1 457 | file 458 | file 459 | file 460 | file 461 | file 462 | file 463 | file1 464 | file 465 | file 466 | file 467 | file 468 | file 469 | file 470 | file1 471 | file 472 | file 473 | file 474 | file 475 | file 476 | file 477 | file1 478 | file 479 | file 480 | file 481 | file 482 | file 483 | file 484 | file1 485 | file 486 | file 487 | file 488 | file 489 | file 490 | file 491 | file1 492 | file 493 | file 494 | file 495 | file 496 | file 497 | file 498 | file1 499 | file 500 | file 501 | file 502 | file 503 | file 504 | file 505 | file1 506 | file 507 | file 508 | file 509 | file 510 | file 511 | file 512 | file1 513 | file 514 | file 515 | file 516 | file 517 | file 518 | file 519 | file1 520 | file 521 | file 522 | file 523 | file 524 | file 525 | file 526 | file1 527 | file 528 | file 529 | file 530 | file 531 | file 532 | file 533 | file1 534 | file 535 | file 536 | file 537 | file 538 | file 539 | file 540 | file1 541 | file 542 | file 543 | file 544 | file 545 | file 546 | file 547 | file1 548 | file 549 | file 550 | file 551 | file 552 | file 553 | file 554 | file1 555 | file 556 | file 557 | file 558 | file 559 | file 560 | file 561 | file1 562 | file 563 | file 564 | file 565 | file 566 | file 567 | file 568 | file1 569 | file 570 | file 571 | file 572 | file 573 | file 574 | file 575 | file1 576 | file 577 | file 578 | file 579 | file 580 | file 581 | file 582 | file1 583 | file 584 | file 585 | file 586 | file 587 | file 588 | file 589 | file1 590 | file 591 | file 592 | file 593 | file 594 | file 595 | file 596 | file1 597 | file 598 | file 599 | file 600 | file 601 | file 602 | file 603 | file1 604 | file 605 | file 606 | file 607 | file 608 | file 609 | file 610 | file1 611 | file 612 | file 613 | file 614 | file 615 | file 616 | file 617 | file1 618 | file 619 | file 620 | file 621 | file 622 | file 623 | file 624 | file1 625 | file 626 | file 627 | file 628 | file 629 | file 630 | file 631 | file1 632 | file 633 | file 634 | file 635 | file 636 | file 637 | file 638 | file1 639 | file 640 | file 641 | file 642 | file 643 | file 644 | file 645 | file1 646 | file 647 | file 648 | file 649 | file 650 | file 651 | file 652 | file1 653 | file 654 | file 655 | file 656 | file 657 | file 658 | file 659 | file1 660 | file 661 | file 662 | file 663 | file 664 | file 665 | file 666 | file1 667 | file 668 | file 669 | file 670 | file 671 | file 672 | file 673 | file1 674 | file 675 | file 676 | file 677 | file 678 | file 679 | file 680 | file1 681 | file 682 | file 683 | file 684 | file 685 | file 686 | file 687 | file1 688 | file 689 | file 690 | file 691 | file 692 | file 693 | file 694 | file1 695 | file 696 | file 697 | file 698 | file 699 | file 700 | file 701 | file1 702 | file 703 | file 704 | file 705 | file 706 | file 707 | file 708 | file1 709 | file 710 | file 711 | file 712 | file 713 | file 714 | file 715 | file1 716 | file 717 | file 718 | file 719 | file 720 | file 721 | file 722 | file1 723 | file 724 | file 725 | file 726 | file 727 | file 728 | file 729 | file1 730 | file 731 | file 732 | file 733 | file 734 | file 735 | file 736 | file1 737 | file 738 | file 739 | file 740 | file 741 | file 742 | file 743 | file1 744 | file 745 | file 746 | file 747 | file 748 | file 749 | file 750 | file1 751 | file 752 | file 753 | file 754 | file 755 | file 756 | file 757 | file1 758 | file 759 | file 760 | file 761 | file 762 | file 763 | file 764 | file1 765 | file 766 | file 767 | file 768 | file 769 | file 770 | file 771 | file1 772 | file 773 | file 774 | file 775 | file 776 | file 777 | file 778 | file1 779 | file 780 | file 781 | file 782 | file 783 | file 784 | file 785 | file1 786 | file 787 | file 788 | file 789 | file 790 | file 791 | file 792 | file1 793 | file 794 | file 795 | file 796 | file 797 | file 798 | file 799 | file1 800 | file 801 | file 802 | file 803 | file 804 | file 805 | file 806 | file1 807 | file 808 | file 809 | file 810 | file 811 | file 812 | file 813 | file1 814 | file 815 | file 816 | file 817 | file 818 | file 819 | file 820 | file1 821 | file 822 | file 823 | file 824 | file 825 | file 826 | file 827 | file1 828 | file 829 | file 830 | file 831 | file 832 | file 833 | file 834 | file1 835 | file 836 | file 837 | file 838 | file 839 | file 840 | file 841 | file1 842 | file 843 | file 844 | file 845 | file 846 | file 847 | file 848 | file1 849 | file 850 | file 851 | file 852 | file 853 | file 854 | file 855 | file1 856 | file 857 | file 858 | file 859 | file 860 | file 861 | file 862 | file1 863 | file 864 | file 865 | file 866 | file 867 | file 868 | file 869 | file1 870 | file 871 | file 872 | file 873 | file 874 | file 875 | file 876 | file1 877 | file 878 | file 879 | file 880 | file 881 | file 882 | file 883 | file1 884 | file 885 | file 886 | file 887 | file 888 | file 889 | file 890 | file1 891 | file 892 | file 893 | file 894 | file 895 | file 896 | file 897 | file1 898 | file 899 | file 900 | file 901 | file 902 | file 903 | file 904 | file1 905 | file 906 | file 907 | file 908 | file 909 | file 910 | file 911 | file1 912 | file 913 | file 914 | file 915 | file 916 | file 917 | file 918 | file1 919 | file 920 | file 921 | file 922 | file 923 | file 924 | file 925 | file1 926 | file 927 | file 928 | file 929 | file 930 | file 931 | file 932 | file1 933 | file 934 | file 935 | file 936 | file 937 | file 938 | file 939 | file1 940 | file 941 | file 942 | file 943 | file 944 | file 945 | file 946 | file1 947 | file 948 | file 949 | file 950 | file 951 | file 952 | file 953 | file1 954 | file 955 | file 956 | file 957 | file 958 | file 959 | file 960 | file1 961 | file 962 | file 963 | file 964 | file 965 | file 966 | file 967 | file1 968 | file 969 | file 970 | file 971 | file 972 | file 973 | file 974 | file1 975 | file 976 | file 977 | file 978 | file 979 | file 980 | file 981 | file1 982 | file 983 | file 984 | file 985 | file 986 | file 987 | file 988 | file1 989 | file 990 | file 991 | file 992 | file 993 | file 994 | file 995 | file1 996 | file 997 | file 998 | file 999 | file 1000 | file 1001 | file 1002 | file1 1003 | file 1004 | file 1005 | file 1006 | file 1007 | file 1008 | file 1009 | file1 1010 | file 1011 | file 1012 | file 1013 | file 1014 | file 1015 | file 1016 | file1 1017 | file 1018 | file 1019 | file 1020 | file 1021 | file 1022 | file 1023 | file1 1024 | file 1025 | file 1026 | file 1027 | file 1028 | file 1029 | file 1030 | file1 1031 | file 1032 | file 1033 | file 1034 | file 1035 | file 1036 | file 1037 | file1 1038 | file 1039 | file 1040 | file 1041 | file 1042 | file 1043 | file 1044 | file1 1045 | file 1046 | file 1047 | file 1048 | file 1049 | file 1050 | file -------------------------------------------------------------------------------- /head-first/async-primer/async-example/src/file2.txt: -------------------------------------------------------------------------------- 1 | file2 -------------------------------------------------------------------------------- /head-first/async-primer/async-example/src/main.rs: -------------------------------------------------------------------------------- 1 | use futures::executor::block_on; 2 | use futures::join; 3 | use std::io; 4 | 5 | mod file; 6 | 7 | // fn main() -> io::Result<()> { 8 | // let r1 = file::read_file("src/file1.txt"); 9 | // let r2 = file::read_file("src/file2.txt"); 10 | 11 | // let f1 = r1.await; 12 | // let f2 = r2.await; 13 | 14 | // dbg!(f1); 15 | // dbg!(f2); 16 | 17 | // Ok(()) 18 | // } 19 | 20 | 21 | fn main() -> io::Result<()> { 22 | 23 | println!("Program started"); 24 | 25 | // Block on the final future 26 | block_on(load_files()); 27 | 28 | Ok(()) 29 | } 30 | 31 | async fn load_files() { 32 | // Join the two futures together 33 | join!(load_file_1(), load_file_2()); 34 | } 35 | 36 | async fn load_file_1() { 37 | let r1 = file::read_file("src/file1.txt").await; 38 | println!("file 1 size: {}", r1.unwrap().len()); 39 | } 40 | 41 | async fn load_file_2() { 42 | let r2 = file::read_file("src/file2.txt").await; 43 | println!("file 2 size: {}", r2.unwrap().len()); 44 | } -------------------------------------------------------------------------------- /head-first/async-primer/multi-example/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk -------------------------------------------------------------------------------- /head-first/async-primer/multi-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "multi-example" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | lazy_static = "1.4.0" -------------------------------------------------------------------------------- /head-first/async-primer/multi-example/src/file.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::{self, Read}; 3 | 4 | pub fn read_file(path: &str) -> io::Result { 5 | let mut file = File::open(path)?; 6 | let mut buffer = String::new(); 7 | file.read_to_string(&mut buffer)?; 8 | Ok(buffer) 9 | } -------------------------------------------------------------------------------- /head-first/async-primer/multi-example/src/file1.txt: -------------------------------------------------------------------------------- 1 | file1 2 | file 3 | file 4 | file 5 | file 6 | file 7 | file 8 | file1 9 | file 10 | file 11 | file 12 | file 13 | file 14 | file 15 | file1 16 | file 17 | file 18 | file 19 | file 20 | file 21 | file 22 | file1 23 | file 24 | file 25 | file 26 | file 27 | file 28 | file 29 | file1 30 | file 31 | file 32 | file 33 | file 34 | file 35 | file 36 | file1 37 | file 38 | file 39 | file 40 | file 41 | file 42 | file 43 | file1 44 | file 45 | file 46 | file 47 | file 48 | file 49 | file 50 | file1 51 | file 52 | file 53 | file 54 | file 55 | file 56 | file 57 | file1 58 | file 59 | file 60 | file 61 | file 62 | file 63 | file 64 | file1 65 | file 66 | file 67 | file 68 | file 69 | file 70 | file 71 | file1 72 | file 73 | file 74 | file 75 | file 76 | file 77 | file 78 | file1 79 | file 80 | file 81 | file 82 | file 83 | file 84 | file 85 | file1 86 | file 87 | file 88 | file 89 | file 90 | file 91 | file 92 | file1 93 | file 94 | file 95 | file 96 | file 97 | file 98 | file 99 | file1 100 | file 101 | file 102 | file 103 | file 104 | file 105 | file 106 | file1 107 | file 108 | file 109 | file 110 | file 111 | file 112 | file 113 | file1 114 | file 115 | file 116 | file 117 | file 118 | file 119 | file 120 | file1 121 | file 122 | file 123 | file 124 | file 125 | file 126 | file 127 | file1 128 | file 129 | file 130 | file 131 | file 132 | file 133 | file 134 | file1 135 | file 136 | file 137 | file 138 | file 139 | file 140 | file 141 | file1 142 | file 143 | file 144 | file 145 | file 146 | file 147 | file 148 | file1 149 | file 150 | file 151 | file 152 | file 153 | file 154 | file 155 | file1 156 | file 157 | file 158 | file 159 | file 160 | file 161 | file 162 | file1 163 | file 164 | file 165 | file 166 | file 167 | file 168 | file 169 | file1 170 | file 171 | file 172 | file 173 | file 174 | file 175 | file 176 | file1 177 | file 178 | file 179 | file 180 | file 181 | file 182 | file 183 | file1 184 | file 185 | file 186 | file 187 | file 188 | file 189 | file 190 | file1 191 | file 192 | file 193 | file 194 | file 195 | file 196 | file 197 | file1 198 | file 199 | file 200 | file 201 | file 202 | file 203 | file 204 | file1 205 | file 206 | file 207 | file 208 | file 209 | file 210 | file 211 | file1 212 | file 213 | file 214 | file 215 | file 216 | file 217 | file 218 | file1 219 | file 220 | file 221 | file 222 | file 223 | file 224 | file 225 | file1 226 | file 227 | file 228 | file 229 | file 230 | file 231 | file 232 | file1 233 | file 234 | file 235 | file 236 | file 237 | file 238 | file 239 | file1 240 | file 241 | file 242 | file 243 | file 244 | file 245 | file 246 | file1 247 | file 248 | file 249 | file 250 | file 251 | file 252 | file 253 | file1 254 | file 255 | file 256 | file 257 | file 258 | file 259 | file 260 | file1 261 | file 262 | file 263 | file 264 | file 265 | file 266 | file 267 | file1 268 | file 269 | file 270 | file 271 | file 272 | file 273 | file 274 | file1 275 | file 276 | file 277 | file 278 | file 279 | file 280 | file 281 | file1 282 | file 283 | file 284 | file 285 | file 286 | file 287 | file 288 | file1 289 | file 290 | file 291 | file 292 | file 293 | file 294 | file 295 | file1 296 | file 297 | file 298 | file 299 | file 300 | file 301 | file 302 | file1 303 | file 304 | file 305 | file 306 | file 307 | file 308 | file 309 | file1 310 | file 311 | file 312 | file 313 | file 314 | file 315 | file 316 | file1 317 | file 318 | file 319 | file 320 | file 321 | file 322 | file 323 | file1 324 | file 325 | file 326 | file 327 | file 328 | file 329 | file 330 | file1 331 | file 332 | file 333 | file 334 | file 335 | file 336 | file 337 | file1 338 | file 339 | file 340 | file 341 | file 342 | file 343 | file 344 | file1 345 | file 346 | file 347 | file 348 | file 349 | file 350 | file 351 | file1 352 | file 353 | file 354 | file 355 | file 356 | file 357 | file 358 | file1 359 | file 360 | file 361 | file 362 | file 363 | file 364 | file 365 | file1 366 | file 367 | file 368 | file 369 | file 370 | file 371 | file 372 | file1 373 | file 374 | file 375 | file 376 | file 377 | file 378 | file 379 | file1 380 | file 381 | file 382 | file 383 | file 384 | file 385 | file 386 | file1 387 | file 388 | file 389 | file 390 | file 391 | file 392 | file 393 | file1 394 | file 395 | file 396 | file 397 | file 398 | file 399 | file 400 | file1 401 | file 402 | file 403 | file 404 | file 405 | file 406 | file 407 | file1 408 | file 409 | file 410 | file 411 | file 412 | file 413 | file 414 | file1 415 | file 416 | file 417 | file 418 | file 419 | file 420 | file 421 | file1 422 | file 423 | file 424 | file 425 | file 426 | file 427 | file 428 | file1 429 | file 430 | file 431 | file 432 | file 433 | file 434 | file 435 | file1 436 | file 437 | file 438 | file 439 | file 440 | file 441 | file 442 | file1 443 | file 444 | file 445 | file 446 | file 447 | file 448 | file 449 | file1 450 | file 451 | file 452 | file 453 | file 454 | file 455 | file 456 | file1 457 | file 458 | file 459 | file 460 | file 461 | file 462 | file 463 | file1 464 | file 465 | file 466 | file 467 | file 468 | file 469 | file 470 | file1 471 | file 472 | file 473 | file 474 | file 475 | file 476 | file 477 | file1 478 | file 479 | file 480 | file 481 | file 482 | file 483 | file 484 | file1 485 | file 486 | file 487 | file 488 | file 489 | file 490 | file 491 | file1 492 | file 493 | file 494 | file 495 | file 496 | file 497 | file 498 | file1 499 | file 500 | file 501 | file 502 | file 503 | file 504 | file 505 | file1 506 | file 507 | file 508 | file 509 | file 510 | file 511 | file 512 | file1 513 | file 514 | file 515 | file 516 | file 517 | file 518 | file 519 | file1 520 | file 521 | file 522 | file 523 | file 524 | file 525 | file 526 | file1 527 | file 528 | file 529 | file 530 | file 531 | file 532 | file 533 | file1 534 | file 535 | file 536 | file 537 | file 538 | file 539 | file 540 | file1 541 | file 542 | file 543 | file 544 | file 545 | file 546 | file 547 | file1 548 | file 549 | file 550 | file 551 | file 552 | file 553 | file 554 | file1 555 | file 556 | file 557 | file 558 | file 559 | file 560 | file 561 | file1 562 | file 563 | file 564 | file 565 | file 566 | file 567 | file 568 | file1 569 | file 570 | file 571 | file 572 | file 573 | file 574 | file 575 | file1 576 | file 577 | file 578 | file 579 | file 580 | file 581 | file 582 | file1 583 | file 584 | file 585 | file 586 | file 587 | file 588 | file 589 | file1 590 | file 591 | file 592 | file 593 | file 594 | file 595 | file 596 | file1 597 | file 598 | file 599 | file 600 | file 601 | file 602 | file 603 | file1 604 | file 605 | file 606 | file 607 | file 608 | file 609 | file 610 | file1 611 | file 612 | file 613 | file 614 | file 615 | file 616 | file 617 | file1 618 | file 619 | file 620 | file 621 | file 622 | file 623 | file 624 | file1 625 | file 626 | file 627 | file 628 | file 629 | file 630 | file 631 | file1 632 | file 633 | file 634 | file 635 | file 636 | file 637 | file 638 | file1 639 | file 640 | file 641 | file 642 | file 643 | file 644 | file 645 | file1 646 | file 647 | file 648 | file 649 | file 650 | file 651 | file 652 | file1 653 | file 654 | file 655 | file 656 | file 657 | file 658 | file 659 | file1 660 | file 661 | file 662 | file 663 | file 664 | file 665 | file 666 | file1 667 | file 668 | file 669 | file 670 | file 671 | file 672 | file 673 | file1 674 | file 675 | file 676 | file 677 | file 678 | file 679 | file 680 | file1 681 | file 682 | file 683 | file 684 | file 685 | file 686 | file 687 | file1 688 | file 689 | file 690 | file 691 | file 692 | file 693 | file 694 | file1 695 | file 696 | file 697 | file 698 | file 699 | file 700 | file 701 | file1 702 | file 703 | file 704 | file 705 | file 706 | file 707 | file 708 | file1 709 | file 710 | file 711 | file 712 | file 713 | file 714 | file 715 | file1 716 | file 717 | file 718 | file 719 | file 720 | file 721 | file 722 | file1 723 | file 724 | file 725 | file 726 | file 727 | file 728 | file 729 | file1 730 | file 731 | file 732 | file 733 | file 734 | file 735 | file 736 | file1 737 | file 738 | file 739 | file 740 | file 741 | file 742 | file 743 | file1 744 | file 745 | file 746 | file 747 | file 748 | file 749 | file 750 | file1 751 | file 752 | file 753 | file 754 | file 755 | file 756 | file 757 | file1 758 | file 759 | file 760 | file 761 | file 762 | file 763 | file 764 | file1 765 | file 766 | file 767 | file 768 | file 769 | file 770 | file 771 | file1 772 | file 773 | file 774 | file 775 | file 776 | file 777 | file 778 | file1 779 | file 780 | file 781 | file 782 | file 783 | file 784 | file 785 | file1 786 | file 787 | file 788 | file 789 | file 790 | file 791 | file 792 | file1 793 | file 794 | file 795 | file 796 | file 797 | file 798 | file 799 | file1 800 | file 801 | file 802 | file 803 | file 804 | file 805 | file 806 | file1 807 | file 808 | file 809 | file 810 | file 811 | file 812 | file 813 | file1 814 | file 815 | file 816 | file 817 | file 818 | file 819 | file 820 | file1 821 | file 822 | file 823 | file 824 | file 825 | file 826 | file 827 | file1 828 | file 829 | file 830 | file 831 | file 832 | file 833 | file 834 | file1 835 | file 836 | file 837 | file 838 | file 839 | file 840 | file 841 | file1 842 | file 843 | file 844 | file 845 | file 846 | file 847 | file 848 | file1 849 | file 850 | file 851 | file 852 | file 853 | file 854 | file 855 | file1 856 | file 857 | file 858 | file 859 | file 860 | file 861 | file 862 | file1 863 | file 864 | file 865 | file 866 | file 867 | file 868 | file 869 | file1 870 | file 871 | file 872 | file 873 | file 874 | file 875 | file 876 | file1 877 | file 878 | file 879 | file 880 | file 881 | file 882 | file 883 | file1 884 | file 885 | file 886 | file 887 | file 888 | file 889 | file 890 | file1 891 | file 892 | file 893 | file 894 | file 895 | file 896 | file 897 | file1 898 | file 899 | file 900 | file 901 | file 902 | file 903 | file 904 | file1 905 | file 906 | file 907 | file 908 | file 909 | file 910 | file 911 | file1 912 | file 913 | file 914 | file 915 | file 916 | file 917 | file 918 | file1 919 | file 920 | file 921 | file 922 | file 923 | file 924 | file 925 | file1 926 | file 927 | file 928 | file 929 | file 930 | file 931 | file 932 | file1 933 | file 934 | file 935 | file 936 | file 937 | file 938 | file 939 | file1 940 | file 941 | file 942 | file 943 | file 944 | file 945 | file 946 | file1 947 | file 948 | file 949 | file 950 | file 951 | file 952 | file 953 | file1 954 | file 955 | file 956 | file 957 | file 958 | file 959 | file 960 | file1 961 | file 962 | file 963 | file 964 | file 965 | file 966 | file 967 | file1 968 | file 969 | file 970 | file 971 | file 972 | file 973 | file 974 | file1 975 | file 976 | file 977 | file 978 | file 979 | file 980 | file 981 | file1 982 | file 983 | file 984 | file 985 | file 986 | file 987 | file 988 | file1 989 | file 990 | file 991 | file 992 | file 993 | file 994 | file 995 | file1 996 | file 997 | file 998 | file 999 | file 1000 | file 1001 | file 1002 | file1 1003 | file 1004 | file 1005 | file 1006 | file 1007 | file 1008 | file 1009 | file1 1010 | file 1011 | file 1012 | file 1013 | file 1014 | file 1015 | file 1016 | file1 1017 | file 1018 | file 1019 | file 1020 | file 1021 | file 1022 | file 1023 | file1 1024 | file 1025 | file 1026 | file 1027 | file 1028 | file 1029 | file 1030 | file1 1031 | file 1032 | file 1033 | file 1034 | file 1035 | file 1036 | file 1037 | file1 1038 | file 1039 | file 1040 | file 1041 | file 1042 | file 1043 | file 1044 | file1 1045 | file 1046 | file 1047 | file 1048 | file 1049 | file 1050 | file -------------------------------------------------------------------------------- /head-first/async-primer/multi-example/src/file2.txt: -------------------------------------------------------------------------------- 1 | file2 -------------------------------------------------------------------------------- /head-first/async-primer/multi-example/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::sync::RwLock; 3 | use std::thread; 4 | 5 | use lazy_static::lazy_static; 6 | 7 | mod file; 8 | 9 | // A sync primitive that allows to read/write from variables between threads. 10 | // we declare the variables here, this requires the lazy_static crate 11 | lazy_static! { 12 | static ref FILE1: RwLock = RwLock::new(String::from("")); 13 | static ref FILE2: RwLock = RwLock::new(String::from("")); 14 | } 15 | 16 | fn main() -> io::Result<()> { 17 | println!("program started"); 18 | 19 | let thread_1 = thread::spawn(|| { 20 | let mut w1 = FILE1.write().unwrap(); 21 | *w1 = file::read_file("src/file1.txt").unwrap(); 22 | println!("read file 1"); 23 | }); 24 | 25 | println!("Launched Thread 1"); 26 | 27 | let thread_2 = thread::spawn(|| { 28 | let mut w2 = FILE2.write().unwrap(); 29 | *w2 = file::read_file("src/file2.txt").unwrap(); 30 | println!("read file 2"); 31 | }); 32 | 33 | println!("Launched Thread 2"); 34 | 35 | let mut rf1: bool = false; 36 | let mut rf2: bool = false; 37 | 38 | loop { 39 | // read() 40 | // let r1 = FILE1.read().unwrap(); 41 | // let r2 = FILE2.read().unwrap(); 42 | 43 | // if *r1 != String::from("") && rf1 == false { 44 | // println!("completed file 1"); 45 | // rf1 = true; 46 | // } 47 | 48 | // if *r2 != String::from("") && rf2 == false { 49 | // println!("completed file 2"); 50 | // rf2 = true; 51 | // } 52 | 53 | // try_read() 54 | let r1 = FILE1.try_read(); 55 | let r2 = FILE2.try_read(); 56 | 57 | match r1 { 58 | Ok(v) => { 59 | if *v != String::from("") && rf1 == false { 60 | println!("completed file 1"); 61 | rf1 = true; 62 | } 63 | } 64 | // If rwlock can't be acquired, ignore the error 65 | Err(_) => {} 66 | } 67 | 68 | match r2 { 69 | Ok(v) => { 70 | if *v != String::from("") && rf2 == false { 71 | println!("completed file 2"); 72 | rf2 = true; 73 | } 74 | } 75 | // If rwlock can't be acquired, ignore the error 76 | Err(_) => {} 77 | } 78 | } 79 | 80 | Ok(()) 81 | } -------------------------------------------------------------------------------- /head-first/async-primer/sync-example/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk -------------------------------------------------------------------------------- /head-first/async-primer/sync-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sync-example" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /head-first/async-primer/sync-example/src/file.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::{self, Read}; 3 | 4 | pub fn read_file(path: &str) -> io::Result { 5 | let mut file = File::open(path)?; 6 | let mut buffer = String::new(); 7 | file.read_to_string(&mut buffer)?; 8 | Ok(buffer) 9 | } -------------------------------------------------------------------------------- /head-first/async-primer/sync-example/src/file1.txt: -------------------------------------------------------------------------------- 1 | file1 -------------------------------------------------------------------------------- /head-first/async-primer/sync-example/src/file2.txt: -------------------------------------------------------------------------------- 1 | file2 -------------------------------------------------------------------------------- /head-first/async-primer/sync-example/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | mod file; 4 | 5 | fn main() -> io::Result<()> { 6 | println!("program started"); 7 | 8 | let file1 = file::read_file("src/file1.txt")?; 9 | println!("processed file 1"); 10 | 11 | let file2 = file::read_file("src/file2.txt")?; 12 | println!("processed file 2"); 13 | 14 | dbg!(&file1); 15 | dbg!(&file2); 16 | 17 | Ok(()) 18 | } -------------------------------------------------------------------------------- /head-first/http/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # These are backup files generated by rustfmt 6 | **/*.rs.bk -------------------------------------------------------------------------------- /head-first/http/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "http" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | reqwest = { version = "0.11", features = ["blocking"] } 11 | html2md = "0.2" 12 | 13 | futures = "0.1.26" 14 | hyper = { version = "0.14.27", optional = true } 15 | 16 | jsonrpc-core = "14.0.3" 17 | jsonrpc-core-client = "14.0.3" 18 | jsonrpc-http-server = "14.0.3" 19 | jsonrpc-client-transports = "14.0.3" 20 | jsonrpc-derive = "14.0.3" -------------------------------------------------------------------------------- /head-first/http/src/main.rs: -------------------------------------------------------------------------------- 1 | mod rpc_server; 2 | mod rpc_client; 3 | 4 | use std::fs; 5 | 6 | use hyper::rt; 7 | use std::time::Duration; 8 | use std::net::SocketAddr; 9 | 10 | use jsonrpc_core::futures::Future; 11 | use jsonrpc_http_server::*; 12 | use jsonrpc_client_transports::transports::http; 13 | use rpc_server::Rpc; 14 | use jsonrpc_core::{Result}; 15 | use jsonrpc_core_client::transports::local; 16 | use self::rpc_server::gen_client; 17 | 18 | fn id(t: T) -> T { 19 | t 20 | } 21 | 22 | fn example() { 23 | let mut io = rpc_server::rpc_handler(); 24 | 25 | let request = r#"{"jsonrpc": "2.0", "method": "hello", "params": ["world"], "id": 1}"#; 26 | let response = r#"{"jsonrpc":"2.0","result":"hello world","id":1}"#; 27 | 28 | assert_eq!(io.handle_request(request).wait().unwrap(), Some(response.to_string())); 29 | } 30 | 31 | fn example2() { 32 | // init RPC server 33 | let server = rpc_server::RpcServer::serve(id); 34 | let (tx, rx) = std::sync::mpsc::channel(); 35 | 36 | // create connect 37 | let run = http::connect(&server.uri) 38 | .and_then(|client: rpc_client::RpcClient| { 39 | client.hello("http").and_then(move |result| { 40 | drop(client); 41 | let _ = tx.send(result); 42 | Ok(()) 43 | }) 44 | }) 45 | .map_err(|e| println!("RPC Client error: {:?}", e)); 46 | 47 | rt::run(run); 48 | 49 | // get response 50 | let result = rx.recv_timeout(Duration::from_secs(3)).unwrap(); 51 | assert_eq!("hello http", result); 52 | } 53 | 54 | struct RpcImpl; 55 | 56 | impl Rpc for RpcImpl { 57 | fn add(&self, a: u64, b: u64) -> Result { 58 | Ok(a + b) 59 | } 60 | } 61 | 62 | fn example3() { 63 | let mut handler = rpc_server::rpc_handler(); 64 | handler.extend_with(RpcImpl.to_delegate()); 65 | 66 | // let server_details = "0.0.0.0:15678"; 67 | // let server_addr: SocketAddr = server_details.parse().unwrap(); 68 | // let new_server = rpc_server::start_http(&server_addr, handler); 69 | 70 | let fut = { 71 | let (client, server) = local::connect::(handler); 72 | client.add(5, 6).map(|res| println!("5 + 6 = {}", res)).join(server) 73 | }; 74 | fut.wait().unwrap(); 75 | } 76 | 77 | fn example1() { 78 | // init RPC server 79 | let server_details = "0.0.0.0:15678"; 80 | let socket_addr: SocketAddr = server_details.parse().unwrap(); 81 | let mut handler = rpc_server::rpc_handler(); 82 | let new_server = rpc_server::start_http(&socket_addr, handler); 83 | let server_uri = format!("http://{}", socket_addr); 84 | 85 | let (tx, rx) = std::sync::mpsc::channel(); 86 | 87 | // create connect 88 | let run = http::connect(&server_uri) 89 | .and_then(|client: rpc_client::RpcClient| { 90 | client.hello("http rpc").and_then(move |result| { 91 | drop(client); 92 | let _ = tx.send(result); 93 | Ok(()) 94 | }) 95 | }) 96 | .map_err(|e| println!("RPC Client error: {:?}", e)); 97 | 98 | rt::run(run); 99 | 100 | // get response 101 | let result = rx.recv_timeout(Duration::from_secs(3)).unwrap(); 102 | assert_eq!("hello http rpc", result); 103 | println!("RPC Client example1: {:?}", result); 104 | } 105 | 106 | fn scrape_url() { 107 | let url = "https://www.rust-lang.org/"; 108 | let output = "rust.md"; 109 | 110 | println!("Fetching url: {}", url); 111 | let body = reqwest::blocking::get(url).unwrap().text().unwrap(); 112 | 113 | println!("Converting html to markdown..."); 114 | let md = html2md::parse_html(&body); 115 | 116 | fs::write(output, md.as_bytes()).unwrap(); 117 | println!("Converted markdown has been saved in {}.", output); 118 | } 119 | 120 | fn main() { 121 | scrape_url(); 122 | example(); 123 | example1(); 124 | example2(); 125 | example3(); 126 | } -------------------------------------------------------------------------------- /head-first/http/src/rpc_client.rs: -------------------------------------------------------------------------------- 1 | use jsonrpc_core_client::{RpcChannel, TypedClient, RpcError}; 2 | 3 | use futures::Future; 4 | 5 | #[derive(Clone)] 6 | pub struct RpcClient(TypedClient); 7 | 8 | impl From for RpcClient { 9 | fn from(channel: RpcChannel) -> Self { 10 | RpcClient(channel.into()) 11 | } 12 | } 13 | 14 | impl RpcClient { 15 | pub fn hello(&self, msg: &'static str) -> impl Future { 16 | self.0.call_method("hello", "String", (msg,)) 17 | } 18 | 19 | pub fn fail(&self) -> impl Future { 20 | self.0.call_method("fail", "()", ()) 21 | } 22 | 23 | pub fn notify(&self, value: u64) -> impl Future { 24 | self.0.notify("notify", (value,)) 25 | } 26 | } -------------------------------------------------------------------------------- /head-first/http/src/rpc_server.rs: -------------------------------------------------------------------------------- 1 | use std::net::SocketAddr; 2 | use std::io; 3 | 4 | use jsonrpc_core::{Error, ErrorCode, IoHandler, Params, Value, Result}; 5 | use jsonrpc_http_server::{Server, ServerBuilder, RestApi}; 6 | use jsonrpc_derive::rpc; 7 | 8 | pub struct RpcServer { 9 | pub uri: String, 10 | socket_addr: SocketAddr, 11 | server: Option, 12 | } 13 | 14 | impl RpcServer { 15 | pub fn serve ServerBuilder>(alter: F) -> Self { 16 | let builder = ServerBuilder::new(rpc_handler()).rest_api(RestApi::Unsecure); 17 | 18 | let server = alter(builder).start_http(&"127.0.0.1:0".parse().unwrap()).unwrap(); 19 | let socket_addr = server.address().clone(); 20 | let uri = format!("http://{}", socket_addr); 21 | 22 | RpcServer { 23 | uri, 24 | socket_addr, 25 | server: Some(server), 26 | } 27 | } 28 | 29 | fn start(&mut self) { 30 | if self.server.is_none() { 31 | let server = ServerBuilder::new(rpc_handler()) 32 | .rest_api(RestApi::Unsecure) 33 | .start_http(&self.socket_addr) 34 | .unwrap(); 35 | self.server = Some(server); 36 | } else { 37 | panic!("Server already running") 38 | } 39 | } 40 | 41 | fn stop(&mut self) { 42 | let server = self.server.take(); 43 | if let Some(server) = server { 44 | server.close(); 45 | } 46 | } 47 | } 48 | 49 | pub fn rpc_handler() -> IoHandler { 50 | let mut io = IoHandler::default(); 51 | io.add_method("hello", |params: Params| match params.parse::<(String,)>() { 52 | Ok((msg,)) => Ok(Value::String(format!("hello {}", msg))), 53 | _ => Ok(Value::String("world".into())), 54 | }); 55 | io.add_method("fail", |_: Params| Err(Error::new(ErrorCode::ServerError(-34)))); 56 | io.add_notification("notify", |params: Params| { 57 | let (value,) = params.parse::<(u64,)>().expect("expected one u64 as param"); 58 | assert_eq!(value, 12); 59 | }); 60 | 61 | io 62 | } 63 | 64 | /// Maximal payload accepted by RPC servers. 65 | const MAX_PAYLOAD: usize = 15 * 1024 * 1024; 66 | 67 | /// Type alias for http server 68 | pub type HttpServer = Server; 69 | 70 | /// The RPC IoHandler containing all requested APIs. 71 | pub type RpcHandler = IoHandler; 72 | 73 | /// Start HTTP server listening on given address. 74 | /// 75 | /// **Note**: Only available if `not(target_os = "unknown")`. 76 | pub fn start_http( 77 | addr: &std::net::SocketAddr, 78 | io: RpcHandler, 79 | ) -> io::Result { 80 | ServerBuilder::new(io) 81 | //.threads(4) 82 | .rest_api(RestApi::Unsecure) 83 | .max_request_body_size(MAX_PAYLOAD) 84 | .start_http(addr) 85 | } 86 | 87 | /// API 88 | #[rpc] 89 | pub trait Rpc { 90 | /// Adds two numbers and returns a result 91 | #[rpc(name = "add")] 92 | fn add(&self, a: u64, b: u64) -> Result; 93 | } -------------------------------------------------------------------------------- /head-first/merkle-tree/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /head-first/merkle-tree/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "merkle_tree" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | ring = "0.16.9" -------------------------------------------------------------------------------- /head-first/merkle-tree/README.md: -------------------------------------------------------------------------------- 1 | ## Merkle Tree 2 | 3 | The implementation of Merkle Tree in Rust. 4 | 5 | This tree is stored in a vector. 6 | 7 | For example, there are four items, merkle tree is kept like: 8 | [hash0,hash1,hash2,hash3,hash01,hash23,root] 9 | 10 | While building a tree, if there is an odd number of nodes at the given level, the last node will be duplicated. 11 | 12 | ## Usage example 13 | 14 | ```Rust 15 | extern crate ring; 16 | 17 | use ring::digest::{Algorithm, SHA512}; 18 | use merkle_tree::MerkleTree; 19 | 20 | static ALGO: &'static Algorithm = &SHA512; 21 | 22 | fn main() { 23 | let values = vec!["one", "two", "three", "four"]; 24 | let tree = MerkleTree::new(&values, ALGO); 25 | let proof = tree.build_proof(&"one"); 26 | let vec = proof.unwrap(); 27 | tree.validate(&vec); 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /head-first/merkle-tree/src/lib.rs: -------------------------------------------------------------------------------- 1 | /// The implementation of Merkle Tree in Rust. 2 | 3 | extern crate ring; 4 | 5 | use std::convert::AsRef; 6 | use std::hash::Hash; 7 | 8 | use ring::digest::{Algorithm, Context, Digest}; 9 | 10 | /// This tree is stored in a vector. 11 | /// 12 | /// For example, there are four items, merkle tree is kept like: 13 | /// [hash0,hash1,hash2,hash3,hash01,hash23,root] 14 | /// 15 | /// # Usage example 16 | /// 17 | /// ``` 18 | /// extern crate ring; 19 | /// 20 | /// use ring::digest::{Algorithm, SHA512}; 21 | /// use merkle_tree::MerkleTree; 22 | /// 23 | /// static ALGO: &'static Algorithm = &SHA512; 24 | /// 25 | /// fn main() { 26 | /// let values = vec!["one", "two", "three", "four"]; 27 | /// let tree = MerkleTree::new(&values, ALGO); 28 | /// let proof = tree.build_proof(&"one"); 29 | /// let vec = proof.unwrap(); 30 | /// tree.validate(&vec); 31 | /// } 32 | /// ``` 33 | /// 34 | 35 | pub struct MerkleTree { 36 | array: Vec, 37 | height: usize, 38 | items_count: usize, 39 | algo: &'static Algorithm, 40 | } 41 | 42 | impl MerkleTree { 43 | /// Build Merkle Tree 44 | pub fn new>(values: &Vec, algo: &'static Algorithm) -> MerkleTree { 45 | let (height, array) = build_tree(values, algo); 46 | MerkleTree { 47 | array: array, 48 | height: height, 49 | items_count: values.len(), 50 | algo: algo, 51 | } 52 | } 53 | 54 | /// Generate Merkle Proof 55 | pub fn build_proof>(&self, value: &T) -> Option> { 56 | let hash = get_hash(value.as_ref(), self.algo).as_ref().to_vec(); 57 | let index = self.find_item(&hash); 58 | let mut vec = vec![]; 59 | match index { 60 | Some(i) => { 61 | vec.push(&self.array[(i * self.algo.output_len)..(i * self.algo.output_len + self.algo.output_len)]); 62 | Some(self.add_level(0, i, self.items_count, vec)) 63 | } 64 | None => None 65 | } 66 | } 67 | 68 | fn find_item(&self, hash: &Vec) -> Option { 69 | let mut result = None; 70 | // linear search item in a loop 71 | for index in 0..self.items_count { 72 | let start = index * self.algo.output_len; 73 | if hash.as_slice() == &self.array[start..(start + self.algo.output_len)] { 74 | result = Some(index); 75 | break; 76 | } 77 | } 78 | result 79 | } 80 | 81 | /// Recursion 82 | fn add_level<'a>(&'a self, start_index: usize, index: usize, mut level_len: usize, mut result: Vec<&'a [u8]>) -> Vec<&'a [u8]> { 83 | level_len += level_len & 1; 84 | let (sibling, parent) = calculate_relatives(index); 85 | //Add sibling to result 86 | result.push(&self.array[ 87 | (start_index + sibling * self.algo.output_len)..(start_index + sibling * self.algo.output_len + self.algo.output_len) 88 | ]); 89 | let next_level_len = level_len / 2; 90 | // Do not include root to proof 91 | if next_level_len == 1 { 92 | return result; 93 | } 94 | self.add_level(start_index + level_len * self.algo.output_len, parent, next_level_len, result) 95 | } 96 | 97 | pub fn is_empty(&self) -> bool { 98 | self.nodes_count() == 0 99 | } 100 | 101 | pub fn get_root(&self) -> &[u8] { 102 | if self.is_empty() { 103 | return &[]; 104 | } 105 | let root_index = self.array.len() - self.algo.output_len; 106 | &self.array[root_index..] // Last item 107 | } 108 | 109 | pub fn nodes_count(&self) -> usize { 110 | self.array.len() / self.algo.output_len 111 | } 112 | 113 | pub fn leafs_count(&self) -> usize { 114 | self.items_count 115 | } 116 | 117 | pub fn data_size(&self) -> usize { 118 | self.array.len() 119 | } 120 | 121 | pub fn height(&self) -> usize { 122 | self.height 123 | } 124 | 125 | /// fold() takes two arguments: an initial hash(01) 126 | /// and a closure with two arguments 127 | pub fn validate(&self, proof: &Vec<&[u8]>) -> bool { 128 | proof[2..].iter() 129 | .fold( 130 | get_pair_hash(proof[0], proof[1], self.algo), 131 | |a, b| get_pair_hash(a.as_ref(), b, self.algo) 132 | ).as_ref() == self.get_root() 133 | } 134 | } 135 | 136 | /// "2i 2i+1" schema 137 | fn calculate_relatives(index: usize) -> (usize, usize) { 138 | let mut sibling = index; 139 | if index & 1 == 0 { 140 | sibling += 1 141 | } else { 142 | sibling -= 1 143 | }; 144 | let parent = (index + 1 + ((index + 1) & 1)) / 2 - 1; 145 | (sibling, parent) 146 | } 147 | 148 | /// While building a tree, if there is an odd number of nodes at the given 149 | /// level, the last node will be duplicated. 150 | fn build_tree>(values: &Vec, algo: &'static Algorithm) -> (usize, Vec) { 151 | let vec_len = calculate_vec_len(values.len(), algo); 152 | let mut tree: Vec = Vec::with_capacity(vec_len); 153 | for (_i, v) in values.iter().enumerate() { //Hash leafs 154 | let digest = get_hash(v.as_ref(), algo); 155 | let hash = digest.as_ref(); 156 | tree.extend_from_slice(hash); 157 | } 158 | let height = build_level(&mut tree, 0, values.len(), algo); 159 | (height, tree) 160 | } 161 | 162 | /// length = (leafs + nodes) * output_len 163 | fn calculate_vec_len(len: usize, algo: &'static Algorithm) -> usize { 164 | //Determine leafs number is even or odd 165 | let mut result = len + (len & 1); 166 | let mut level = result; 167 | while level > 1 { 168 | level += level & 1; 169 | level = level / 2; 170 | result += level; 171 | } 172 | //output_len is the length of a finalized digest 173 | result * algo.output_len 174 | } 175 | 176 | /// Return tree weight and build nodes 177 | fn build_level(tree: &mut Vec, prev_level_start: usize, mut prev_level_len: usize, algo: &'static Algorithm) -> usize { 178 | if prev_level_len & 1 == 1 { 179 | //Previous level has odd number of children 180 | let prev = &tree[(prev_level_start * algo.output_len + (prev_level_len - 1) * algo.output_len)..] 181 | .to_owned(); 182 | //Duplicate last item 183 | tree.extend_from_slice(prev); 184 | prev_level_len += 1; 185 | } 186 | let level_len = prev_level_len / 2; 187 | for i in 0..level_len { 188 | let begin = prev_level_start * algo.output_len + i * 2 * algo.output_len; 189 | let middle = begin + algo.output_len; 190 | let end = middle + algo.output_len; 191 | let hash = get_pair_hash( 192 | &tree[begin..middle], //Left node 193 | &tree[middle..end], //Right node 194 | algo); 195 | tree.extend_from_slice(hash.as_ref()); 196 | }; 197 | if level_len > 1 { 198 | return build_level(tree, prev_level_start + prev_level_len, level_len, algo) + 1; 199 | } 200 | if level_len > 0 { 201 | return 2; 202 | } 203 | return 0; 204 | } 205 | 206 | /// Generate Node hash 207 | pub fn get_pair_hash(x: &[u8], y: &[u8], algo: &'static Algorithm) -> Digest { 208 | let left = x; 209 | let right = y; 210 | let mut ctx = Context::new(algo); 211 | ctx.update(left); 212 | ctx.update(right); 213 | ctx.finish() 214 | } 215 | 216 | /// Hash function 217 | pub fn get_hash(x: &[u8], algo: &'static Algorithm) -> Digest { 218 | let mut ctx = Context::new(algo); 219 | ctx.update(x); 220 | ctx.finish() 221 | } 222 | 223 | #[cfg(test)] 224 | mod tests { 225 | use ring::digest::{Algorithm, Context, Digest, SHA512}; 226 | use super::MerkleTree; 227 | 228 | static ALGO: &'static Algorithm = &SHA512; 229 | 230 | #[test] 231 | fn test_build_tree_with_0_values() { 232 | let values: Vec<&str> = vec![]; 233 | let tree = MerkleTree::new(&values, ALGO); 234 | 235 | assert_eq!(true, tree.is_empty()); 236 | assert_eq!(0, tree.height()); 237 | assert_eq!(0, tree.nodes_count()); 238 | assert_eq!(0, tree.data_size()); 239 | let empty_root: Vec = vec![]; 240 | assert_eq!(empty_root, tree.get_root()); 241 | } 242 | 243 | #[test] 244 | fn test_build_tree_with_odd_number_of_values() { 245 | let values = vec!["one", "two", "three"]; 246 | let tree = MerkleTree::new(&values, ALGO); 247 | 248 | let _d0: Digest = super::get_hash(values[0].as_ref(), ALGO); 249 | let _d1: Digest = super::get_hash(values[1].as_ref(), ALGO); 250 | let _d2: Digest = super::get_hash(values[2].as_ref(), ALGO); 251 | let _d3: Digest = super::get_hash(values[2].as_ref(), ALGO); 252 | 253 | let _d01 = hash_pair(_d0.as_ref(), _d1.as_ref(), ALGO); 254 | let _d23 = hash_pair(_d2.as_ref(), _d3.as_ref(), ALGO); 255 | let _pair = super::get_pair_hash(_d01.as_ref(), _d23.as_ref(), ALGO); 256 | 257 | assert_eq!(false, tree.is_empty()); 258 | assert_eq!(3, tree.height()); 259 | assert_eq!(7, tree.nodes_count()); 260 | assert_eq!(7 * ALGO.output_len, tree.data_size()); 261 | assert_eq!(_pair.as_ref(), tree.get_root()); 262 | } 263 | 264 | #[test] 265 | fn test_build_tree_with_even_number_of_values() { 266 | let values = vec!["one", "two", "three", "four"]; 267 | let tree = MerkleTree::new(&values, ALGO); 268 | 269 | let _d0: Digest = super::get_hash(values[0].as_ref(), ALGO); 270 | let _d1: Digest = super::get_hash(values[1].as_ref(), ALGO); 271 | let _d2: Digest = super::get_hash(values[2].as_ref(), ALGO); 272 | let _d3: Digest = super::get_hash(values[3].as_ref(), ALGO); 273 | 274 | let _d01 = hash_pair(_d0.as_ref(), _d1.as_ref(), ALGO); 275 | let _d23 = hash_pair(_d2.as_ref(), _d3.as_ref(), ALGO); 276 | let _pair = super::get_pair_hash(_d01.as_ref(), _d23.as_ref(), ALGO); 277 | 278 | assert_eq!(false, tree.is_empty()); 279 | assert_eq!(3, tree.height()); 280 | assert_eq!(7, tree.nodes_count()); 281 | assert_eq!(7 * ALGO.output_len, tree.data_size()); 282 | assert_eq!(_pair.as_ref(), tree.get_root()); 283 | } 284 | 285 | #[test] 286 | fn test_root_hash_same_if_values_were_same() { 287 | let values = vec!["one", "one", "one", "one"]; 288 | let tree = MerkleTree::new(&values, ALGO); 289 | 290 | let _d0: Digest = super::get_hash(values[0].as_ref(), ALGO); 291 | let _d1: Digest = super::get_hash(values[1].as_ref(), ALGO); 292 | let _d2: Digest = super::get_hash(values[2].as_ref(), ALGO); 293 | let _d3: Digest = super::get_hash(values[3].as_ref(), ALGO); 294 | 295 | let _d01 = hash_pair(_d0.as_ref(), _d1.as_ref(), ALGO); 296 | let _d23 = hash_pair(_d2.as_ref(), _d3.as_ref(), ALGO); 297 | let _pair = super::get_pair_hash(_d23.as_ref(), _d01.as_ref(), ALGO); 298 | 299 | assert_eq!(false, tree.is_empty()); 300 | assert_eq!(3, tree.height()); 301 | assert_eq!(7, tree.nodes_count()); 302 | assert_eq!(7 * ALGO.output_len, tree.data_size()); 303 | assert_eq!(_pair.as_ref(), tree.get_root()); 304 | } 305 | 306 | #[test] 307 | fn test_root_hash_different_reverse_values() { 308 | let values1 = vec!["one", "two"]; 309 | let tree1 = MerkleTree::new(&values1, ALGO); 310 | 311 | let values2 = vec!["two", "one"]; 312 | let tree2 = MerkleTree::new(&values2, ALGO); 313 | 314 | assert_ne!(tree1.get_root(), tree2.get_root()); 315 | } 316 | 317 | #[test] 318 | fn test_generate_merkle_proof_and_validate() { 319 | let values = vec!["one", "two", "three", "four"]; 320 | let tree = MerkleTree::new(&values, ALGO); 321 | 322 | for v in values { 323 | let proof = tree.build_proof(&v); 324 | assert_eq!(true, proof.is_some()); 325 | let vec = proof.unwrap(); 326 | assert_eq!(3, vec.len()); 327 | tree.validate(&vec); 328 | } 329 | 330 | let absent = vec!["qqq", "www", "eee", "rrr"]; 331 | for v in absent { 332 | let proof = tree.build_proof(&v); 333 | assert_eq!(true, proof.is_none()); 334 | } 335 | } 336 | 337 | #[test] 338 | fn test_provide_bad_merkle_proof() { 339 | let values = vec!["one", "two", "three", "four"]; 340 | let tree = MerkleTree::new(&values, ALGO); 341 | let proof = tree.build_proof(&"one"); 342 | 343 | assert_eq!(true, proof.is_some()); 344 | let _d0: Digest = super::get_hash("five".as_ref(), ALGO); 345 | let proof_vec = proof.unwrap(); 346 | let vec = vec![proof_vec[0], proof_vec[1], _d0.as_ref()]; 347 | assert_eq!(false, tree.validate(&vec)); 348 | } 349 | 350 | // helper function 351 | fn hash_pair(x: &[u8], y: &[u8], algo: &'static Algorithm) -> Digest { 352 | let mut ctx = Context::new(algo); 353 | ctx.update(x); 354 | ctx.update(y); 355 | ctx.finish() 356 | } 357 | 358 | } 359 | 360 | 361 | 362 | -------------------------------------------------------------------------------- /head-first/rust-trait/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-trait" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /head-first/rust-trait/src/abstract_type.rs: -------------------------------------------------------------------------------- 1 | pub fn trait_object() { 2 | #[derive(Debug)] 3 | struct Foo; 4 | trait Bar { 5 | fn baz(&self); 6 | } 7 | impl Bar for Foo { 8 | fn baz(&self) { println!("{:?}", self) } 9 | } 10 | fn static_dispatch(t: &T) where T:Bar { 11 | t.baz(); 12 | } 13 | fn dynamic_dispatch(t: &Bar) { 14 | t.baz(); 15 | } 16 | let foo = Foo; 17 | static_dispatch(&foo); 18 | dynamic_dispatch(&foo); 19 | } 20 | 21 | 22 | pub fn impl_trait(){ 23 | use std::fmt::Debug; 24 | pub trait Fly { 25 | fn fly(&self) -> bool; 26 | } 27 | #[derive(Debug)] 28 | struct Duck; 29 | #[derive(Debug)] 30 | struct Pig; 31 | impl Fly for Duck { 32 | fn fly(&self) -> bool { 33 | return true; 34 | } 35 | } 36 | impl Fly for Pig { 37 | fn fly(&self) -> bool { 38 | return false; 39 | } 40 | } 41 | fn fly_static(s: impl Fly+Debug) -> bool { 42 | s.fly() 43 | } 44 | fn can_fly(s: impl Fly+Debug) -> impl Fly { 45 | if s.fly(){ 46 | println!("{:?} can fly", s); 47 | }else{ 48 | println!("{:?} can't fly", s); 49 | } 50 | s 51 | } 52 | fn dyn_can_fly(s: impl Fly+Debug+'static) -> Box { 53 | if s.fly(){ 54 | println!("{:?} can fly", s); 55 | }else{ 56 | println!("{:?} can't fly", s); 57 | } 58 | Box::new(s) 59 | } 60 | let pig = Pig; 61 | assert_eq!(fly_static(pig), false); 62 | let duck = Duck; 63 | assert_eq!(fly_static(duck), true); 64 | 65 | let pig = Pig; 66 | can_fly(pig); 67 | let duck = Duck; 68 | can_fly(duck); 69 | 70 | let duck = Duck; 71 | dyn_can_fly(duck); 72 | } 73 | 74 | fn main() { 75 | trait_object(); 76 | impl_trait(); 77 | } -------------------------------------------------------------------------------- /head-first/rust-trait/src/bound.rs: -------------------------------------------------------------------------------- 1 | pub fn trait_bound(){ 2 | use std::ops::Add; 3 | // fn sum>(a: T, b: T) -> T{ 4 | // a + b 5 | // } 6 | fn sum(a: T, b: T) -> T where T: Add { 7 | a + b 8 | } 9 | assert_eq!(sum(1u32, 2u32), 3); 10 | assert_eq!(sum(1u64, 2u64), 3); 11 | } 12 | 13 | fn main() { 14 | trait_bound(); 15 | } -------------------------------------------------------------------------------- /head-first/rust-trait/src/interface.rs: -------------------------------------------------------------------------------- 1 | pub fn generics_trait(){ 2 | trait Add { 3 | fn my_add(self, rhs: RHS) -> Output; 4 | } 5 | impl Add for i32 { 6 | fn my_add(self, rhs: i32) -> i32 { 7 | self + rhs 8 | } 9 | } 10 | impl Add for u32 { 11 | fn my_add(self, rhs: u32) -> i32 { 12 | (self + rhs ) as i32 13 | } 14 | } 15 | 16 | let (a, b, c, d) = (1i32, 2i32, 3u32, 4u32); 17 | let x: i32 = a.my_add(b); 18 | let y: i32 = c.my_add(d); 19 | assert_eq!(x, 3i32); 20 | assert_eq!(y, 7i32); 21 | } 22 | 23 | fn main() { 24 | generics_trait(); 25 | } -------------------------------------------------------------------------------- /head-first/rust-trait/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() { 5 | assert_eq!(2 + 2, 4); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /head-first/rust-trait/src/tag.rs: -------------------------------------------------------------------------------- 1 | pub fn test_copy_trait(){ 2 | fn test_copy(i: T) { 3 | println!("hhh"); 4 | } 5 | let a = "String"; 6 | test_copy(a); 7 | } 8 | 9 | pub fn sync_send_trait(){ 10 | use std::thread; 11 | let mut x = vec![1, 2, 3, 4]; 12 | thread::spawn(move || x.push(1)); 13 | } 14 | 15 | fn main() { 16 | test_copy_trait(); 17 | sync_send_trait(); 18 | } -------------------------------------------------------------------------------- /head-first/src/main.rs: -------------------------------------------------------------------------------- 1 | //use std::cell::Cell; 2 | // 3 | //fn foo(cell: &Cell) { 4 | // let value = cell.get(); 5 | // cell.set(value * 2); 6 | //} 7 | 8 | //struct Foo { 9 | // x: u32, 10 | //} 11 | // 12 | //fn print_foo(foo: &Foo) { 13 | // println!("x={}", foo.x); 14 | //} 15 | 16 | //fn change_foo(foo: &Foo) { 17 | // foo.x = foo.x *2; 18 | //} 19 | 20 | //fn change_foo(foo: &mut Foo) { 21 | // foo.x = foo.x * 2; 22 | //} 23 | 24 | //use std::cell::UnsafeCell; 25 | //use std::cell::Cell; 26 | 27 | //fn main() { 28 | 29 | // let mut s = String::from("hello"); 30 | // let r1 = &mut s; 31 | // let r2 = &mut s; // 可变引用,不能有别名 32 | // println!("{}, {}", r1, r2); 33 | 34 | // let x = 1; 35 | // let y = &mut x; // 当有一个不可变值时,不能可变的借用它 36 | 37 | // let mut data = 1_i32; 38 | // let p : &i32 = &data; 39 | // data = 10; 40 | // println!("{}", *p); 41 | 42 | // let data : Cell = Cell::new(1); 43 | // let p = &data; 44 | // data.set(10); 45 | // println!("{}", p.get()); 46 | // 47 | // p.set(20); 48 | // println!("{:?}", data); 49 | 50 | //} 51 | 52 | 53 | // let cell = Cell::new(0); 54 | // let value = cell.get(); 55 | // let new_value = cell.get() + 1; 56 | // foo(&cell); 57 | // cell.set(new_value); // oops, we clobbered the work done by foo 58 | 59 | // use std::thread; 60 | // use std::time::Duration; 61 | 62 | // fn main() { 63 | // let t = thread::Builder::new() 64 | // .name("child1".to_string()) 65 | // .spawn(move || { 66 | // println!("enter child thread."); 67 | // thread::park(); 68 | // println!("resume child thread"); 69 | // }).unwrap(); 70 | // println!("spawn a thread"); 71 | // thread::sleep(Duration::new(5,0)); 72 | // t.thread().unpark(); 73 | // t.join(); 74 | // println!("child thread finished"); 75 | // } 76 | extern crate ring; 77 | 78 | use ring::digest::{Algorithm, SHA512}; 79 | use merkle_tree::MerkleTree; 80 | 81 | static ALGO: &'static Algorithm = &SHA512; 82 | 83 | fn main() { 84 | let values = vec!["one", "two", "three", "four"]; 85 | let tree = MerkleTree::new(&values, ALGO); 86 | let proof = tree.build_proof(&"one"); 87 | let vec = proof.unwrap(); 88 | tree.validate(&vec); 89 | } 90 | 91 | 92 | -------------------------------------------------------------------------------- /head-first/std-box/example_Box.rs: -------------------------------------------------------------------------------- 1 | use List::{Cons, Nil}; 2 | 3 | #[derive(Debug)] 4 | enum List { 5 | Cons(T, Box>), 6 | Nil, 7 | } 8 | 9 | fn main() { 10 | let recursive_list: List = Cons(1, Box::new(Cons(2, Box::new(Nil)))); 11 | println!("{:?}", recursive_list); // 打印出:Cons(1, Cons(2, Nil)) 12 | } -------------------------------------------------------------------------------- /head-first/std-box/example_Deref.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Deref; 2 | 3 | #[derive(Debug)] 4 | struct MyBox { 5 | value : T, 6 | } 7 | 8 | impl Deref for MyBox { 9 | type Target = T; 10 | 11 | fn deref(&self) -> &Self::Target { 12 | &self.value 13 | } 14 | } 15 | 16 | fn main() { 17 | let instance = MyBox{value : 10}; 18 | assert_eq!(10, *instance); 19 | println!("{}, {}", *instance, *(instance.deref())); 20 | } -------------------------------------------------------------------------------- /head-first/std-box/example_TraitObject.rs: -------------------------------------------------------------------------------- 1 | trait T { 2 | fn m(&self) -> u64; 3 | } 4 | 5 | struct S { 6 | i: u64 7 | } 8 | 9 | impl T for S { 10 | fn m(&self) -> u64 { self.i } 11 | } 12 | 13 | fn f(x: Box) { 14 | println!("{}", x.m()) 15 | } 16 | 17 | fn main() { 18 | let s = S{i : 100}; 19 | println!("{}", s.m());// 20 | 21 | let b: Box = Box::new(S{i: 100}); 22 | f(b); // 动态调度 23 | } -------------------------------------------------------------------------------- /head-first/std-cell/example_Cell.rs: -------------------------------------------------------------------------------- 1 | use std::cell::Cell; 2 | 3 | struct SomeStruct { 4 | regular_field: u8, 5 | special_field: Cell, 6 | } 7 | 8 | fn main() { 9 | let my_struct = SomeStruct { 10 | regular_field: 0, 11 | special_field: Cell::new(1), 12 | }; 13 | 14 | let new_value = 100; 15 | // my_struct.regular_field = new_value; // ERROR: `my_struct`是不可变的 16 | 17 | my_struct.special_field.set(new_value); // WORKS: `special_field`是`Cell`类型的,它是可变的 18 | assert_eq!(my_struct.special_field.get(), new_value); 19 | } -------------------------------------------------------------------------------- /head-first/std-cell/example_RefCell.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | 3 | fn main() { 4 | let c = RefCell::new(5); 5 | *c.borrow_mut() = 7; 6 | assert_eq!(7, *c.borrow()); 7 | 8 | let x = RefCell::new(vec![1,2,3]); 9 | println!("{:?}", x.borrow()); 10 | x.borrow_mut().push(4); 11 | println!("{:?}", x.borrow()); 12 | } -------------------------------------------------------------------------------- /head-first/std-marker/example_Send_Sync.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | //use std::rc::Rc; 3 | use std::sync::{Arc, Mutex}; 4 | //use std::cell::RefCell; 5 | 6 | fn main() { 7 | //let mut s = Rc::new("example".to_string()); 8 | //let s = Arc::new(RefCell::new("example".to_string())); 9 | let s = Arc::new(Mutex::new("example".to_string())); 10 | let mut v = vec![]; 11 | for _ in 0..2 { 12 | //let mut s_clone = s.clone(); 13 | let s_clone = s.clone(); 14 | let child = thread::spawn(move || { 15 | let mut s_clone = s_clone.lock().unwrap(); 16 | s_clone.push_str(" Send and Sync!"); 17 | println!("{:?}", s_clone); 18 | }); 19 | v.push(child); 20 | } 21 | for child in v { 22 | child.join().unwrap(); 23 | } 24 | println!("{:?}", s); 25 | } -------------------------------------------------------------------------------- /head-first/tarpc/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk -------------------------------------------------------------------------------- /head-first/tarpc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tarpc" 3 | version = "0.6.0" 4 | authors = ["Tim Kuehn "] 5 | edition = "2018" 6 | license = "MIT" 7 | documentation = "https://docs.rs/tarpc-example-service" 8 | homepage = "https://github.com/google/tarpc" 9 | repository = "https://github.com/google/tarpc" 10 | keywords = ["rpc", "network", "server", "microservices", "example"] 11 | categories = ["asynchronous", "network-programming"] 12 | readme = "../README.md" 13 | description = "An example server built on tarpc." 14 | 15 | [dependencies] 16 | clap = "2.0" 17 | futures = "0.3" 18 | serde = { version = "1.0" } 19 | tarpc = { version = "0.20", features = ["full"] } 20 | tokio = { version = "0.2", features = ["full"] } 21 | tokio-serde = { version = "0.6", features = ["json"] } 22 | env_logger = "0.6" 23 | 24 | [lib] 25 | name = "service" 26 | path = "src/lib.rs" 27 | 28 | [[bin]] 29 | name = "server" 30 | path = "src/server.rs" 31 | 32 | [[bin]] 33 | name = "client" 34 | path = "src/client.rs" 35 | -------------------------------------------------------------------------------- /head-first/tarpc/src/client.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file or at 5 | // https://opensource.org/licenses/MIT. 6 | 7 | use clap::{App, Arg}; 8 | use std::{io, net::SocketAddr}; 9 | use tarpc::{client, context}; 10 | use tokio_serde::formats::Json; 11 | 12 | #[tokio::main] 13 | async fn main() -> io::Result<()> { 14 | let flags = App::new("Hello Client") 15 | .version("0.1") 16 | .author("Tim ") 17 | .about("Say hello!") 18 | .arg( 19 | Arg::with_name("server_addr") 20 | .long("server_addr") 21 | .value_name("ADDRESS") 22 | .help("Sets the server address to connect to.") 23 | .required(true) 24 | .takes_value(true), 25 | ) 26 | .arg( 27 | Arg::with_name("name") 28 | .short("n") 29 | .long("name") 30 | .value_name("STRING") 31 | .help("Sets the name to say hello to.") 32 | .required(true) 33 | .takes_value(true), 34 | ) 35 | .get_matches(); 36 | 37 | let server_addr = flags.value_of("server_addr").unwrap(); 38 | let server_addr = server_addr 39 | .parse::() 40 | .unwrap_or_else(|e| panic!(r#"--server_addr value "{}" invalid: {}"#, server_addr, e)); 41 | 42 | let name = flags.value_of("name").unwrap().into(); 43 | 44 | let transport = tarpc::serde_transport::tcp::connect(server_addr, Json::default()).await?; 45 | 46 | // WorldClient is generated by the service attribute. It has a constructor `new` that takes a 47 | // config and any Transport as input. 48 | let mut client = service::WorldClient::new(client::Config::default(), transport).spawn()?; 49 | 50 | // The client has an RPC method for each RPC defined in the annotated trait. It takes the same 51 | // args as defined, with the addition of a Context, which is always the first arg. The Context 52 | // specifies a deadline and trace information which can be helpful in debugging requests. 53 | let hello = client.hello(context::current(), name).await?; 54 | 55 | println!("{}", hello); 56 | 57 | Ok(()) 58 | } -------------------------------------------------------------------------------- /head-first/tarpc/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file or at 5 | // https://opensource.org/licenses/MIT. 6 | 7 | /// This is the service definition. It looks a lot like a trait definition. 8 | /// It defines one RPC, hello, which takes one arg, name, and returns a String. 9 | #[tarpc::service] 10 | pub trait World { 11 | /// Returns a greeting for name. 12 | async fn hello(name: String) -> String; 13 | } -------------------------------------------------------------------------------- /head-first/tarpc/src/server.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Use of this source code is governed by an MIT-style 4 | // license that can be found in the LICENSE file or at 5 | // https://opensource.org/licenses/MIT. 6 | 7 | use clap::{App, Arg}; 8 | use futures::{ 9 | future::{self, Ready}, 10 | prelude::*, 11 | }; 12 | use service::World; 13 | use std::{ 14 | io, 15 | net::{IpAddr, SocketAddr}, 16 | }; 17 | use tarpc::{ 18 | context, 19 | server::{self, Channel, Handler}, 20 | }; 21 | use tokio_serde::formats::Json; 22 | 23 | // This is the type that implements the generated World trait. It is the business logic 24 | // and is used to start the server. 25 | #[derive(Clone)] 26 | struct HelloServer(SocketAddr); 27 | 28 | impl World for HelloServer { 29 | // Each defined rpc generates two items in the trait, a fn that serves the RPC, and 30 | // an associated type representing the future output by the fn. 31 | 32 | type HelloFut = Ready; 33 | 34 | fn hello(self, _: context::Context, name: String) -> Self::HelloFut { 35 | future::ready(format!( 36 | "Hello, {}! You are connected from {:?}.", 37 | name, self.0 38 | )) 39 | } 40 | } 41 | 42 | #[tokio::main] 43 | async fn main() -> io::Result<()> { 44 | env_logger::init(); 45 | 46 | let flags = App::new("Hello Server") 47 | .version("0.1") 48 | .author("Tim ") 49 | .about("Say hello!") 50 | .arg( 51 | Arg::with_name("port") 52 | .short("p") 53 | .long("port") 54 | .value_name("NUMBER") 55 | .help("Sets the port number to listen on") 56 | .required(true) 57 | .takes_value(true), 58 | ) 59 | .get_matches(); 60 | 61 | let port = flags.value_of("port").unwrap(); 62 | let port = port 63 | .parse() 64 | .unwrap_or_else(|e| panic!(r#"--port value "{}" invalid: {}"#, port, e)); 65 | 66 | let server_addr = (IpAddr::from([0, 0, 0, 0]), port); 67 | 68 | // JSON transport is provided by the json_transport tarpc module. It makes it easy 69 | // to start up a serde-powered json serialization strategy over TCP. 70 | tarpc::serde_transport::tcp::listen(&server_addr, Json::default) 71 | .await? 72 | // Ignore accept errors. 73 | .filter_map(|r| future::ready(r.ok())) 74 | .map(server::BaseChannel::with_defaults) 75 | // Limit channels to 1 per IP. 76 | .max_channels_per_key(1, |t| t.as_ref().peer_addr().unwrap().ip()) 77 | // serve is generated by the service attribute. It takes as input any type implementing 78 | // the generated World trait. 79 | .map(|channel| { 80 | let server = HelloServer(channel.as_ref().as_ref().peer_addr().unwrap()); 81 | channel.respond_with(server.serve()).execute() 82 | }) 83 | // Max 10 channels. 84 | .buffer_unordered(10) 85 | .for_each(|_| async {}) 86 | .await; 87 | 88 | Ok(()) 89 | } -------------------------------------------------------------------------------- /simple/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /simple/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simple" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | rand = "0.6.5" -------------------------------------------------------------------------------- /simple/README.md: -------------------------------------------------------------------------------- 1 | # Rust基础 2 | 3 | ## [概述](https://mp.weixin.qq.com/s/raM8bpGFIukWVNcR2G4pmw) 4 | 5 | 摘录片段: 6 | Rust代码非常接近自然语言。 7 | 8 | ```Rust 9 | 5.times(|| println!("Hello Rust")); 10 | 2.days().from_now(); 11 | ``` 12 | 13 | ## [基本语法](https://mp.weixin.qq.com/s/okwXAj6eqB31R5mYmaqKZQ) 14 | 15 | Rust一切皆表达式。 16 | 17 | ### 闭包 18 | 19 | 闭包语法:由管道符和花括号组合而成。管道符里是闭包函数的参数,花括号里是函数执行体。参数类型,花括号和返回值均可省略。示例如下: 20 | 21 | ```Rust 22 | |a: i32, b: i32| -> i32 { a + b } 23 | ``` 24 | 25 | * Fn, 调用参数为&self,表示闭包以不可变借用的方式捕获环境中的自由变量,可以多次调用 26 | * FnMut, 调用参数为&mut self,表示闭包以可变借用的方式捕获环境中的自由变量,可以多次调用 27 | * FnOnce,调用参数为self,表示闭包通过转移所有权方式捕获环境中的自由变量,会消耗自己,只能调用一次 28 | 29 | 个人觉得闭包这种语法糖降低了代码的可读性,一段好的代码,要有良好的阅读体验,而不是写的时候方便。 30 | 31 | ## [数据类型](https://mp.weixin.qq.com/s/wSqRC-h-RsiNbUuPNVaLMw) 32 | 33 | 利用元组,函数可以返回多个值。 34 | 35 | 什么是字符串? 36 | 37 | Rust原始的字符串类型:`str`,它是固定长度的。 38 | 39 | 字符串切片slice:`&str`,它是储存在别处的UTF-8编码字符串数据的引用。 40 | 41 | 而称作`String`类型的字符串是由标准库提供的,它是可增长的、可变长度的、有所有权的、UTF-8编码的字符串类型。 42 | 43 | ## [核心概念](https://mp.weixin.qq.com/s/BqtbSUkOZ-DSbv3Mt2UdrQ) 44 | 45 | ### 类型系统 46 | 47 | Rust是一门强类型且类型安全的静态语言。 48 | 49 | 一个类型系统允许一段代码在不同上下文中具有不同的类型,多态类型系统。三种多态方式: 50 | 51 | * 参数化多态,泛型 52 | * 子类型多态,面向对象语言,Java中的继承概念 53 | * 特定多态,同一行为定义,不同上下文中有不同的行为实现,函数重载 54 | 55 | `trait`的概念:它是Rust中提供的一种实现特定多态的方法,类似于其他语言中的接口(interfaces)。 56 | 57 | ### 所有权系统 58 | 59 | 所有权的规则: 60 | 61 | * Rust中的每一个值,都有一个被称为其所有者(owner)的变量 62 | * 值有且只有一个所有者 63 | * 当所有者(变量)离开作用域,这个值将被丢弃 64 | 65 | 所有权转移,一个值的所有权被转移给另外一个变量绑定的过程。 66 | 67 | 复制语义和移动语义来对应值语义和引用语义。实现`Copy trait`的类型拥有复制语义。 68 | 69 | 移动move语义:一个旧的变量(数据存在堆上)在将其赋值给其他变量后,意味着它的所有权被移动了。 70 | 71 | ### 模块系统 72 | 73 | 包`crate`的概念:crate代表一个二进制或库项目,用crate root来描述如何构建这个crate的文件。 74 | 75 | ### 错误处理 76 | 77 | 使用`Result`类型来处理潜在的错误。Result枚举,它定义有两个成员,Ok和Err: 78 | 79 | ```Rust 80 | enum Result { 81 | Ok(T), 82 | Err(E), 83 | } 84 | ``` 85 | 86 | ## 练习代码 87 | 88 | * [表达式](./src/statement.rs) 89 | * [变量](./src/variable.rs) 90 | * [函数](./src/function.rs) 91 | * [流程控制](./src/control_flow.rs) 92 | * [原始类型](./src/primitives.rs) 93 | * [集合类型](./src/collections.rs) 94 | * [类型系统](./src/generics_trait.rs) 95 | * [所有权系统]() -------------------------------------------------------------------------------- /simple/function/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /simple/function/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "function" 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 | -------------------------------------------------------------------------------- /simple/function/src/main.rs: -------------------------------------------------------------------------------- 1 | /// 函数作为参数 2 | pub fn math(op: fn(i32, i32) -> i32, a: i32, b: i32) -> i32 { 3 | op(a,b) 4 | } 5 | fn sum(a: i32, b: i32) -> i32 { 6 | a + b 7 | } 8 | fn product(a: i32, b: i32) -> i32 { 9 | a * b 10 | } 11 | 12 | /// 函数作为返回值 13 | fn is_true() -> bool { true } 14 | pub fn true_maker() -> fn() -> bool { is_true } 15 | 16 | /// CTFE编译时函数执行 17 | const fn init_len() -> usize { return 5; } 18 | 19 | /// 匿名函数闭包作为参数 20 | fn closure_math i32>(op: F) -> i32 { 21 | // 通过添加一对圆括号,调用传入的闭包 22 | op() 23 | } 24 | 25 | /// 匿名函数闭包作为返回值 26 | fn two_times_impl() -> impl Fn(i32) -> i32 { 27 | let i = 2; 28 | // 使用 move 转移变量 i 的所有权,避免悬挂指针,安全返回闭包 29 | move |j| j * i 30 | } 31 | 32 | /// geektime: function 33 | fn apply(value: i32, f: fn(i32) -> i32) -> i32 { 34 | f(value) 35 | } 36 | 37 | fn square(value: i32) -> i32 { 38 | value * value 39 | } 40 | 41 | fn cube(value: i32) -> i32 { 42 | value * value * value 43 | } 44 | 45 | fn pi() -> f64 { 46 | 3.1415925 47 | } 48 | 49 | fn not_pi() { 50 | // 如果最后一个表达式后添加了; 分号,隐含其返回值为 unit 51 | 3.1425926; 52 | } 53 | 54 | #[cfg(test)] 55 | mod tests { 56 | use super::*; 57 | 58 | #[test] 59 | fn test_fn_return() { 60 | assert_eq!(pi(), 3.1415925); 61 | assert_eq!(not_pi(), ()); 62 | } 63 | 64 | #[test] 65 | fn test_apply() { 66 | assert_eq!(apply(2, square), 4); 67 | assert_eq!(apply(2, cube), 8); 68 | } 69 | 70 | #[test] 71 | fn test_math() { 72 | assert_eq!(math(sum, 2, 3), 5); 73 | assert_eq!(math(product, 2, 3), 6); 74 | } 75 | } 76 | 77 | fn main() { 78 | println!("is_pi: {:?}, is_unit1: {:?}", pi(), not_pi()); 79 | 80 | println!("apply square: {}", apply(2, square)); 81 | println!("apply cube: {}", apply(2, cube)); 82 | 83 | // 默认函数名是函数类型,参数显式指定了函数的类型,被转换成函数指针类型 84 | let a = 2; 85 | let b = 3; 86 | println!("2+3={}", math(sum, a, b)); 87 | println!("2*3={}", math(product, a, b)); 88 | 89 | // 返回函数指针 90 | println!("return {:p}", true_maker()); 91 | // 函数指针加上括号,就会调用该函数 92 | println!("return {}", true_maker()()); 93 | 94 | // 数组的长度是编译时常量,必须在编译时确定其值 95 | let arr = [0; init_len()]; 96 | println!("array length is {}", arr.len()); 97 | 98 | let out = 42; 99 | // add 函数内使用外部定义的变量 out,编译器会报错 100 | // fn add(i: i32, j: i32) -> i32 { i + j + out } 101 | // 匿名函数,闭包可捕获外部变量 out 102 | let closure_annotated = |i: i32, j: i32| -> i32 { i + j + out }; 103 | // 闭包自动推断输入和返回类型,个人觉得可读性不好 104 | let closure_inferred = |i, j| i + j + out; 105 | let i = 1; 106 | let j = 2; 107 | println!("closure annotated: 1+2+42={}", closure_annotated(i, j)); 108 | println!("closure inferred: 1+2+42={}", closure_inferred(i, j)); 109 | 110 | // 传入闭包:|| a + b 111 | println!("closure: 2+3={}", closure_math(|| a + b)); 112 | // 传入闭包:|| a * b 113 | println!("closure: 2*3={}", closure_math(|| a * b)); 114 | 115 | let result = two_times_impl(); 116 | println!("closure: 2's two times is {}", result(2)); 117 | } -------------------------------------------------------------------------------- /simple/httpie/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /simple/httpie/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "httpie" 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 | anyhow = "1.0" 10 | clap = { version = "4.4.6", features = ["derive"] } 11 | colored = "2.0.4" 12 | mime = "0.3.17" 13 | reqwest = { version = "0.11", features = ["json"] } 14 | tokio = { version = "1", features = ["full"] } 15 | syntect = "5.0" -------------------------------------------------------------------------------- /simple/httpie/src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{anyhow, Result}; 2 | use clap::{Args, Parser, Subcommand}; 3 | use colored::*; 4 | use mime::Mime; 5 | use reqwest::{header, Client, Response, Url}; 6 | use std::{collections::HashMap, str::FromStr}; 7 | use syntect::{ 8 | easy::HighlightLines, 9 | highlighting::{ThemeSet, Style}, 10 | parsing::SyntaxSet, 11 | util::{as_24_bit_terminal_escaped, LinesWithEndings}, 12 | }; 13 | 14 | #[derive(Parser, Debug)] 15 | struct Opts { 16 | #[command(subcommand)] 17 | cmd: Commands, 18 | } 19 | 20 | #[derive(Subcommand, Debug)] 21 | enum Commands { 22 | Get(Get), 23 | Post(Post), 24 | } 25 | 26 | #[derive(Args, Debug)] 27 | struct Get { 28 | #[arg(value_parser = parse_url)] 29 | url: String, 30 | } 31 | 32 | #[derive(Args, Debug)] 33 | struct Post { 34 | #[arg(value_parser = parse_url)] 35 | url: String, 36 | #[arg(value_parser = parse_kv_pair)] 37 | body: Vec, 38 | } 39 | 40 | #[derive(Clone, Debug, PartialEq)] 41 | struct KvPair { 42 | k: String, 43 | v: String, 44 | } 45 | 46 | impl FromStr for KvPair { 47 | type Err = anyhow::Error; 48 | 49 | fn from_str(s: &str) -> Result { 50 | let mut split = s.split('='); 51 | let err = || anyhow!(format!("Failed to parse {}", s)); 52 | 53 | Ok(Self { 54 | k: (split.next().ok_or_else(err)?).to_string(), 55 | v: (split.next().ok_or_else(err)?).to_string(), 56 | }) 57 | } 58 | } 59 | 60 | fn parse_kv_pair(s: &str) -> Result { 61 | s.parse() 62 | } 63 | 64 | fn parse_url(s: &str) -> Result { 65 | let _url: Url = s.parse()?; 66 | 67 | Ok(s.into()) 68 | } 69 | 70 | async fn get(client: Client, args: &Get) -> Result<()> { 71 | let resp = client.get(&args.url).send().await?; 72 | println!("{:?}", resp.text().await?); 73 | 74 | Ok(()) 75 | } 76 | 77 | async fn post(client: Client, args: &Post) -> Result<()> { 78 | let mut body = HashMap::new(); 79 | for pair in args.body.iter() { 80 | body.insert(&pair.k, &pair.v); 81 | } 82 | 83 | let resp = client.post(&args.url).json(&body).send().await?; 84 | 85 | Ok(print_resp(resp).await?) 86 | } 87 | 88 | fn print_status(resp: &Response) { 89 | let status = format!("{:?} {}", resp.version(), resp.status()).blue(); 90 | println!("{}\n", status); 91 | } 92 | 93 | fn print_headers(resp: &Response) { 94 | for (name, value) in resp.headers() { 95 | println!("{}: {:?}", name.to_string().green(), value); 96 | } 97 | print!("\n"); 98 | } 99 | 100 | fn print_body(m: Option, body: &String) { 101 | match m { 102 | Some(v) if v == mime::APPLICATION_JSON => print_syntect(body, "json"), 103 | Some(v) if v == mime::TEXT_HTML => print_syntect(body, "html"), 104 | 105 | _ => println!("{}", body), 106 | } 107 | } 108 | 109 | fn print_syntect(s: &str, ext: &str) { 110 | // Load these once at the start of your program 111 | let ps = SyntaxSet::load_defaults_newlines(); 112 | let ts = ThemeSet::load_defaults(); 113 | let syntax = ps.find_syntax_by_extension(ext).unwrap(); 114 | let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]); 115 | for line in LinesWithEndings::from(s) { 116 | let ranges: Vec<(Style, &str)> = h.highlight_line(line, &ps).unwrap(); 117 | let escaped = as_24_bit_terminal_escaped(&ranges[..], true); 118 | print!("{}", escaped); 119 | } 120 | } 121 | 122 | fn get_content_type(resp: &Response) -> Option { 123 | resp.headers() 124 | .get(header::CONTENT_TYPE) 125 | .map(|v| v.to_str().unwrap().parse().unwrap()) 126 | } 127 | 128 | async fn print_resp(resp: Response) -> Result<()> { 129 | print_status(&resp); 130 | print_headers(&resp); 131 | let mime = get_content_type(&resp); 132 | let body = resp.text().await?; 133 | print_body(mime, &body); 134 | 135 | Ok(()) 136 | } 137 | 138 | #[tokio::main] 139 | async fn main() -> Result<()> { 140 | let opts: Opts = Opts::parse(); 141 | println!("{:?}", opts); 142 | let client = Client::new(); 143 | let result = match opts.cmd { 144 | Commands::Get(ref args) => get(client, args).await?, 145 | Commands::Post(ref args) => post(client, args).await?, 146 | }; 147 | 148 | Ok(result) 149 | } -------------------------------------------------------------------------------- /simple/src/collections.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 统计一些文本中每一个单词分别出现了多少次 4 | fn count_word() { 5 | let text = "hello world wonderful world"; 6 | let mut map = HashMap::new(); 7 | 8 | for word in text.split_whitespace() { 9 | let count = map.entry(word).or_insert(0); 10 | *count += 1; 11 | } 12 | println!("count {:?}", map); 13 | } 14 | 15 | fn vector_example() { 16 | let v: Vec = Vec::new(); 17 | println!("vec size {}", v.len()); 18 | let mut v = Vec::new(); 19 | v.push(8); 20 | println!("after push vec size {}", v.len()); 21 | let v = vec![1, 2]; 22 | println!("vec get element {}", &v[0]); 23 | for i in &v { 24 | println!("vec each item {}", i); 25 | } 26 | } 27 | 28 | fn hashmap_example() { 29 | let mut hmap = HashMap::new(); 30 | hmap.insert("one", 1); 31 | hmap.insert("one", 2); 32 | for (key, value) in &hmap { 33 | println!("init hashmap {}: {}", key, value); 34 | } 35 | { 36 | let val = hmap.entry("two").or_insert(3); 37 | println!("insert {}", val); 38 | } 39 | println!("after insert hashmap {:?}", hmap); 40 | } 41 | 42 | fn string_example() { 43 | let mut s = String::from("str"); 44 | s.push_str("add"); 45 | println!("s {}", s); 46 | for c in s.chars() { 47 | println!("char {}", c); 48 | } 49 | } 50 | 51 | fn overlap() { 52 | let a = [1, 2, 3]; 53 | let b = [1, 2, 3, 4]; 54 | 55 | let c: Vec = a.iter().zip(&b).map(|(a, b)| a & b).collect(); 56 | println!("overlap {:?}", c); 57 | } 58 | 59 | fn bunch_of_numbers() -> Vec { 60 | (0..10).collect() 61 | } 62 | 63 | fn new_vector_example() { 64 | let nums = bunch_of_numbers(); 65 | 66 | match nums.last() { 67 | Some(&0) => println!("Last number is zero"), 68 | Some(n) => println!("Last number is {}", n), 69 | None => println!("There are no numbers"), 70 | } 71 | } 72 | 73 | fn slices_example() { 74 | let mut foo = [0u8; 5]; 75 | foo[1] = 1; 76 | foo[2] = 2; 77 | 78 | let bar = &foo[..3]; 79 | println!("{:?}", bar); 80 | } 81 | 82 | fn main() { 83 | vector_example(); 84 | hashmap_example(); 85 | string_example(); 86 | count_word(); 87 | overlap(); 88 | new_vector_example(); 89 | slices_example(); 90 | } -------------------------------------------------------------------------------- /simple/src/control_flow.rs: -------------------------------------------------------------------------------- 1 | /** 2 | * 条件表达式 3 | */ 4 | pub fn if_expr(x: i32) -> i32 { 5 | let n = if x < 10 && x > -10 { 6 | 10 * x 7 | } else { 8 | // 如果传入奇数,返回类型为i32,编译器是否会报错? 9 | x / 2 10 | }; 11 | return n; 12 | } 13 | 14 | /** 15 | * 循环表达式 while 16 | */ 17 | pub fn while_expr() { 18 | let mut n = 1; 19 | while n < 16 { 20 | if n % 15 == 0 { 21 | println!("3 and 5‘s multiple {}", n); 22 | } else if n % 5 == 0 { 23 | println!("5‘s multiple {}", n); 24 | } 25 | n += 1; 26 | } 27 | } 28 | 29 | /** 30 | * 循环表达式 loop 31 | */ 32 | pub fn loop_expr() { 33 | let mut n = 1; 34 | loop { 35 | if n % 15 == 0 { 36 | println!("3 and 5‘s multiple {}", n); 37 | } else if n % 3 == 0 { 38 | println!("3‘s multiple {}", n); 39 | } else if n > 16 { 40 | break; 41 | } 42 | n += 1; 43 | } 44 | } 45 | 46 | /** 47 | * 循环表达式 for...in 48 | */ 49 | pub fn for_expr() { 50 | for n in 1..16 { 51 | if n % 15 == 0 { 52 | println!("3 and 5‘s multiple {}", n); 53 | } else if n % 5 == 0 { 54 | println!("5‘s multiple {}", n); 55 | } 56 | } 57 | } 58 | 59 | /** 60 | * match表达式 61 | */ 62 | pub fn match_expr(n: i32) { 63 | match n { 64 | 0 => println!("match number"), 65 | 1...3 => println!("match range"), 66 | | 5 | 7 | 13 => println!("match branch"), 67 | n @ 42 => println!("binding {}", n), 68 | _ => println!("default"), 69 | } 70 | } 71 | 72 | /** 73 | * while let表达式 74 | */ 75 | pub fn while_let_pop() { 76 | let mut v = vec![1,2,3]; 77 | // 动态数组的pop方法会返回Option类型,数组被取空会返回None 78 | // 使用match表达式,需要匹配两种情况:Some(x)和None 79 | while let Some(x) = v.pop() { 80 | println!("{}", x); 81 | } 82 | } 83 | 84 | fn main() { 85 | let x = 13; 86 | // Rust编译器根据上下文,会将结果截取 87 | println!("result={}", if_expr(x)); 88 | 89 | while_expr(); 90 | loop_expr(); 91 | for_expr(); 92 | 93 | let mut n = 2; 94 | match_expr(n); 95 | n = 5; 96 | match_expr(n); 97 | n = 42; 98 | match_expr(n); 99 | n = 100; 100 | match_expr(n); 101 | 102 | while_let_pop(); 103 | } -------------------------------------------------------------------------------- /simple/src/error_handling.rs: -------------------------------------------------------------------------------- 1 | fn add_numbers(numbers: &[i32]) -> i32 { 2 | let a = numbers[0]; 3 | let b = numbers[1]; 4 | 5 | a + b 6 | } 7 | 8 | fn add_numbers_with_option(numbers: &[i32]) -> Option { 9 | let a = numbers.get(0)?; // `get` return Option 10 | let b = numbers.get(1)?; // ? will early return on None 11 | // consider dereferencing the borrow: `*b` 12 | a.checked_add(*b) // returns None on overflow 13 | } 14 | 15 | fn main() { 16 | let arr_normal: [i32; 3] = [1, 2, 3]; 17 | println!("addition: {}",add_numbers(&arr_normal)); 18 | let arr_max: [i32; 3] = [std::i32::MAX, 2, 3]; 19 | // thread 'main' panicked at 'attempt to add with overflow' 20 | // println!("addition: {}",add_numbers(&arr_max)); 21 | println!("addition: {:?}",add_numbers_with_option(&arr_max)); 22 | } -------------------------------------------------------------------------------- /simple/src/generics_trait.rs: -------------------------------------------------------------------------------- 1 | /** 2 | * 找数字列表中最大的数字 3 | */ 4 | fn largest(list: &[i32]) -> i32 { 5 | let mut largest = list[0]; 6 | 7 | for &item in list.iter() { 8 | if item > largest { 9 | largest = item; 10 | } 11 | } 12 | largest 13 | } 14 | 15 | /** 16 | * 泛型实现找列表中最大值 17 | */ 18 | fn generics_largest(list: &[T]) -> &T { 19 | let mut largest = &list[0]; 20 | 21 | for item in list.iter() { 22 | if item > largest { 23 | largest = item; 24 | } 25 | } 26 | 27 | &largest 28 | } 29 | 30 | // 结构体泛型 31 | struct Point { 32 | x: T, 33 | y: U, 34 | } 35 | 36 | // 方法中定义泛型,必须在 impl 后面声明 T 37 | impl Point { 38 | fn x(&self) -> &T { 39 | &self.x 40 | } 41 | 42 | // 结构体定义中的泛型类型参数并不总是与结构体方法签名中使用的泛型是同一类型 43 | fn mixup(self, other: Point) -> Point { 44 | Point { 45 | x: self.x, 46 | y: other.y, 47 | } 48 | } 49 | } 50 | 51 | /** 52 | * trait 53 | */ 54 | trait Arithmetic { 55 | fn add(&self) -> i32; 56 | } 57 | 58 | struct MyPoint { 59 | x: i32, 60 | y: i32, 61 | } 62 | 63 | // 为类型实现trait 64 | impl Arithmetic for MyPoint { 65 | fn add(&self) -> i32 { 66 | self.x + self.y 67 | } 68 | } 69 | 70 | // trait 作为参数 71 | fn sum(item: impl Arithmetic) { 72 | println!("sum {}", item.add()); 73 | } 74 | 75 | fn main() { 76 | let number_list = vec![34, 50, 25, 100, 65]; 77 | let result = largest(&number_list); 78 | println!("The largest number is {}", result); 79 | 80 | let char_list = vec!['y', 'm', 'a', 'q']; 81 | let result = generics_largest(&char_list); 82 | println!("The largest char is {}", result); 83 | 84 | let p = Point { x: 5, y: 1.0 }; 85 | println!("p.x = {}", p.x()); 86 | 87 | let p2 = Point { x: "Hello", y: 'c'}; 88 | let p3 = p.mixup(p2); 89 | println!("p3.x = {}, p3.y = {}", p3.x, p3.y); 90 | 91 | let mp = MyPoint { x: 5, y: 10 }; 92 | println!("mp.x + mp.y: {}", mp.add()); 93 | 94 | sum(mp); 95 | } -------------------------------------------------------------------------------- /simple/src/main.rs: -------------------------------------------------------------------------------- 1 | // guess game from TRLB 2 | extern crate rand; 3 | 4 | use rand::Rng; 5 | use std::cmp::Ordering; 6 | use std::io; 7 | 8 | fn main() { 9 | println!("Guess the number!"); 10 | 11 | let rand_number = rand::thread_rng().gen_range(1, 101); 12 | 13 | loop { 14 | println!("Please input your guess."); 15 | 16 | let mut guess = String::new(); 17 | 18 | io::stdin() 19 | .read_line(&mut guess) 20 | .expect("Failed to read line"); 21 | 22 | let guess: u32 = match guess.trim().parse() { 23 | Ok(num) => num, 24 | Err(_) => continue, 25 | }; 26 | 27 | println!("Your guess {}", guess); 28 | 29 | match guess.cmp(&rand_number) { 30 | Ordering::Less => println!("Too small"), 31 | Ordering::Greater => println!("Too big"), 32 | Ordering::Equal => { 33 | println!("You win"); 34 | break; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /simple/src/primitives.rs: -------------------------------------------------------------------------------- 1 | fn array_example () { 2 | 3 | // 创建数组方式一:[x, y, z] 4 | let arr: [i32; 3] = [1, 2, 3]; 5 | let mut mut_arr = [4, 5, 6]; 6 | mut_arr[0] = 0; 7 | 8 | assert_eq!(3, arr[2]); 9 | assert_eq!(0, mut_arr[0]); 10 | // 这个循环输出: 1 2 3 11 | for x in &arr { 12 | print!("{} ", x); 13 | } 14 | println!(); 15 | 16 | // 创建数组方式二:[x; N] 17 | let mut array: [i32; 3] = [0; 3]; 18 | array[1] = 1; 19 | array[2] = 2; 20 | 21 | assert_eq!([1, 2], &array[1..]); 22 | // 元素个数小于等于32的数组,实现了`trait IntoIterator` 23 | // 这个循环输出: 0 1 2 24 | for x in &array { 25 | print!("{} ", x); 26 | } 27 | println!(); 28 | 29 | let array: [i32; 33] = [0; 33]; 30 | // error[E0277]: `&[i32; 33]` is not an iterator 31 | // for x in &array { 32 | // print!("{} ", x); 33 | // } 34 | // 通过调用slice方法将数组强制类型转换为slice 35 | for x in array.iter() { 36 | print!("{} ", x); 37 | } 38 | println!(); 39 | } 40 | 41 | fn tuple_example() { 42 | let tup: (u8, i32, f64) = (1, 100, 1.1314); 43 | let (x, y, z) = tup; 44 | let f_number = tup.2; 45 | let one_tup = (1.1,); 46 | println!("elements in tuple {},{},{}", x, y, z); 47 | println!("third element in tuple {}", f_number); 48 | println!("one element in tuple {}", one_tup.0); 49 | } 50 | 51 | fn struct_example() { 52 | struct Person { 53 | age: u8, 54 | is_child: bool, 55 | } 56 | struct OnePerson(u8, bool); 57 | struct UnitStruct; 58 | let alice = Person {age: 10, is_child: true}; 59 | let bob = OnePerson(32, false); 60 | let x = UnitStruct; 61 | println!("alice age {} is child {}", alice.age, alice.is_child); 62 | println!("bob age {} is child {}", bob.0, bob.1); 63 | println!("unit struct {:p}", &x); 64 | 65 | impl Person { 66 | fn create_person(age: u8, is_child: bool) -> Person { 67 | Person{age, is_child} 68 | } 69 | fn check_child(&self) -> bool { 70 | if self.is_child && self.age < 18 { 71 | return true; 72 | } else { 73 | return false; 74 | } 75 | } 76 | } 77 | let peter = Person::create_person(33, true); 78 | println!("peter age {} is child {}", peter.age, peter.is_child); 79 | println!("peter is child {}", peter.check_child()); 80 | } 81 | 82 | fn enum_example() { 83 | enum Number { 84 | Integer(i64), 85 | Float { 86 | inner: f64 87 | }, 88 | } 89 | let a = Number::Integer(10); 90 | let b = Number::Float { 91 | inner: 3.14 92 | }; 93 | match a { 94 | Number::Integer(n) => println!("a is integer: {}", n), 95 | Number::Float {inner} => println!("a is float: {}", inner), 96 | } 97 | if let Number::Float { inner } = b { 98 | println!("b is float: {}", inner); 99 | } 100 | } 101 | 102 | fn basic_example() { 103 | // 布尔类型 104 | let a_boolean: bool = true; 105 | 106 | // 数值类型 107 | let a_float: f32 = 1.0; // 变量常规声明 108 | let an_integer = 6i16; // 变量后缀声明 109 | 110 | // 可根据上下文自动推断类型 111 | let mut inferred_type = 8; // 根据下一行的赋值推断为i64类型 112 | inferred_type = 64i64; 113 | 114 | // 无法类型推断时,按默认方式取类型 115 | let default_float = 2.0; // 浮点数值为f64 116 | let default_integer = 5; // 整型数值为i32 117 | 118 | // 字符类型 119 | let a_char: char = 'a'; 120 | } 121 | 122 | fn main() { 123 | array_example(); 124 | tuple_example(); 125 | struct_example(); 126 | enum_example(); 127 | basic_example(); 128 | } -------------------------------------------------------------------------------- /simple/src/statement.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | pub fn answer() -> () { 3 | // 声明语句 4 | let a = 40; 5 | let b = 2; 6 | // 表达式语句:以分号结尾的表达式 7 | // println! 宏语句:名字以叹号结尾,并像函数一样被调用 8 | println!("40 + 2 = {}", sum(a, b)); 9 | } 10 | /// 求和函数 11 | pub fn sum(a: i32, b: i32) -> i32 { 12 | // 表达式,无分号返回求值结果 13 | a + b 14 | // Rust中不用return关键字,从代码可读性是否加上好些? 15 | // return a + b; 16 | } 17 | answer(); 18 | } -------------------------------------------------------------------------------- /simple/src/tcp_server_example.rs: -------------------------------------------------------------------------------- 1 | // 引入相关的Rust标准库std 2 | use std::thread; 3 | use std::net::{TcpListener, TcpStream, Shutdown}; 4 | use std::io::{Read, Write}; 5 | 6 | // 处理tcp客户端的函数 7 | fn handle_client(mut stream: TcpStream) { 8 | // 初始化100字节 9 | let mut data = [0 as u8; 100]; 10 | // 读取客户端的数据 11 | while match stream.read(&mut data) { 12 | Ok(size) => { 13 | // 将客户端的数据echo返回 14 | stream.write(&data[0..size]).unwrap(); 15 | true 16 | }, 17 | Err(_) => { 18 | println!("An error occurred, terminating connection with {}", stream.peer_addr().unwrap()); 19 | stream.shutdown(Shutdown::Both).unwrap(); 20 | false 21 | } 22 | } {} 23 | } 24 | 25 | // 主函数 26 | fn main() { 27 | // 监听本机的6666端口 28 | let listener = TcpListener::bind("127.0.0.1:6666").unwrap(); 29 | // 打印提示信息 30 | println!("Server listening on port 6666"); 31 | // 监听每个连接 32 | for stream in listener.incoming() { 33 | match stream { 34 | // 连接成功 35 | Ok(stream) => { 36 | println!("New connection: {}", stream.peer_addr().unwrap()); 37 | // 启动线程 38 | thread::spawn(move|| { 39 | // 调用handle_client函数处理tcp连接 40 | handle_client(stream) 41 | }); 42 | } 43 | // 连接失败 44 | Err(e) => { 45 | println!("Error: {}", e); 46 | } 47 | } 48 | } 49 | // 关闭socket 50 | drop(listener); 51 | } -------------------------------------------------------------------------------- /simple/src/test.rs: -------------------------------------------------------------------------------- 1 | /// There's a room with a TV and people are coming in and out to watch it. 2 | /// The TV is on only when there's at least a person in the room. 3 | /// For each person that comes in, we record the start and end time. 4 | /// We want to know for how long the TV has been on. 5 | /// In other words:Given a list of arrays of time intervals, 6 | /// write a function that calculates the total amount of time covered by the intervals. 7 | ///```rust 8 | ///input = [(1,4), (2,3)]> 3 input = [(4,6), (1,2)]> 3 9 | ///input = [(1,4), (6,8), (2,4), (7,9), (10, 15)]> 11 10 | ///``` 11 | 12 | /// 时间段类型 13 | type TimeIntervals = (i32, i32); 14 | 15 | /// 合并有重叠的时间段 16 | fn merge_intervals(input: &[TimeIntervals]) -> Vec { 17 | let mut output: Vec = Vec::new(); 18 | let mut j = 0; 19 | let mut current_end = 0; 20 | for i in 0..input.len() { 21 | if input[i].1 > current_end { 22 | current_end = input[i].1; 23 | } 24 | println!("j {:?}", &j); 25 | if i == (input.len() - 1) || input[i+1].0 > current_end { 26 | output.push((input[j].0, current_end)); 27 | j = i + 1; // 28 | } 29 | println!("current_end {:?}", ¤t_end); 30 | } 31 | output 32 | } 33 | 34 | /// 累加时间段 35 | fn sum_time_interval(input: &TimeIntervals) -> i32 { 36 | input.1 - input.0 37 | } 38 | 39 | fn main() { 40 | //let mut input = [(1,4), (2,3)]; 41 | //let mut input = [(4,6), (1,2)]; 42 | let mut input = [(1,4), (6,8), (2,4), (7,9), (10,15), (2,6)]; 43 | //let mut input = [(1,3), (2,6), (8,10), (15,18)]; 44 | input.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap()); 45 | println!("sorted input {:?}", &input); 46 | 47 | let merged_input = merge_intervals(&input); 48 | println!("merged input {:?}", &merged_input); 49 | 50 | let mut sum = 0; 51 | for item in &merged_input { 52 | sum = sum + sum_time_interval(item); 53 | } 54 | println!("finally sum {:?}", sum); 55 | } -------------------------------------------------------------------------------- /simple/src/time_intervals.rs: -------------------------------------------------------------------------------- 1 | /// There's a room with a TV and people are coming in and out to watch it. 2 | /// The TV is on only when there's at least a person in the room. 3 | /// For each person that comes in, we record the start and end time. 4 | /// We want to know for how long the TV has been on. 5 | /// In other words:Given a list of arrays of time intervals, 6 | /// write a function that calculates the total amount of time covered by the intervals. 7 | ///```rust 8 | ///input = [(1,4), (2,3)]> 3 input = [(4,6), (1,2)]> 3 9 | ///input = [(1,4), (6,8), (2,4), (7,9), (10, 15)]> 11 10 | ///```
 11 | 12 | /// 时间段类型 13 | type TimeIntervals = (i32, i32); 14 | 15 | /// 合并有重叠的时间段 16 | fn merge_intervals(input: &[TimeIntervals]) -> Vec { 17 | let mut output: Vec = Vec::new(); 18 | let mut j = 0; 19 | let mut current_end = 0; 20 | for i in 0..input.len() { 21 | if input[i].1 > current_end { 22 | current_end = input[i].1; 23 | } 24 | println!("j {:?}", &j); 25 | if i == (input.len() - 1) || input[i+1].0 > current_end { 26 | output.push((input[j].0, current_end)); 27 | j = i + 1; // 28 | } 29 | println!("current_end {:?}", ¤t_end); 30 | } 31 | output 32 | } 33 | 34 | /// 累加时间段 35 | fn sum_time_interval(input: &TimeIntervals) -> i32 { 36 | input.1 - input.0 37 | } 38 | 39 | fn main() { 40 | //let mut input = [(1,4), (2,3)]; 41 | //let mut input = [(4,6), (1,2)]; 42 | let mut input = [(1,4), (6,8), (2,4), (7,9), (10,15), (2,6)]; 43 | //let mut input = [(1,3), (2,6), (8,10), (15,18)]; 44 | input.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap()); 45 | println!("sorted input {:?}", &input); 46 | 47 | let merged_input = merge_intervals(&input); 48 | println!("merged input {:?}", &merged_input); 49 | 50 | let mut sum = 0; 51 | for item in &merged_input { 52 | sum = sum + sum_time_interval(item); 53 | } 54 | println!("finally sum {:?}", sum); 55 | } -------------------------------------------------------------------------------- /simple/src/variable.rs: -------------------------------------------------------------------------------- 1 | const INT1: i32 = 1; 2 | const BIT2: u32 = 1 << 1; 3 | const STRING: &'static str = "String"; 4 | 5 | static RUST: &'static str = "Rust"; 6 | static mut MUT_INT: i32 = 1; 7 | 8 | #[derive(Debug)] 9 | struct BitString<'a> { 10 | mybit: u32, 11 | mystring: &'a str, 12 | } 13 | 14 | const BIT_STRING: BitString<'static> = BitString { 15 | mybit: BIT2, 16 | mystring: STRING, 17 | }; 18 | 19 | fn is_big(n: i32) -> bool { 20 | // 在一般函数中访问常量 21 | n > INT1 22 | } 23 | 24 | fn main() { 25 | // 在 main 函数中访问常量 26 | println!("{:?}", INT1); 27 | println!("{:?}", BIT2); 28 | println!("{:?}", STRING); 29 | println!("{:#?}", BIT_STRING); 30 | 31 | // 报错!不能修改一个 `const` 常量 32 | INT1 = 5; 33 | let n = 4; 34 | println!("{} is {}", n, if is_big(n) { "big" } else { "small" }); 35 | 36 | 37 | MUT_INT = 5; 38 | 39 | 40 | let a = 1; 41 | // 默认不可变绑定,不能重新赋值 42 | // a = 2; 43 | // 可使用mut关键字,创建可变绑定 44 | println!("a {:p}", &a); 45 | let mut b = 2; 46 | b = 3; 47 | println!("b was changed: {}", b); 48 | 49 | // 变量遮蔽:连续定义同名变量 50 | let s = "Hello Rust"; 51 | let s = "Hello World"; 52 | // 变量生命周期,词法作用域 53 | { 54 | let s = "Hello Rust"; 55 | } 56 | println!("s is {}", s); 57 | 58 | pub fn tmp() -> i32 { 59 | return 1; 60 | } 61 | // 借用操作符&,获取表达式内存地址 62 | let x = &tmp(); 63 | // 值表达式不能出现在位置上下文中,E0070 64 | // tmp() = *x; 65 | println!("x is memory address: {:p}", x); 66 | // 声明动态数组,vec! 67 | let mut c = vec![1,2,3]; 68 | // 使用借用操作符&,得到引用类型 69 | let d = &mut c; 70 | d.push(4); 71 | println!("{:?}", d); 72 | // 字面常量是值表达式,在位置上下文中求值创建临时值 73 | let e = &42; 74 | // 使用解引用操作符*,取得引用中的值 75 | println!("reference e's value is {}", *e) 76 | } -------------------------------------------------------------------------------- /simple/string/print.c: -------------------------------------------------------------------------------- 1 | // in `print.c` 2 | 3 | #include // printf 4 | #include // uint8_t 5 | 6 | void print_spaced(char *s) { 7 | // start at the beginning 8 | int i = 0; 9 | 10 | while (1) { 11 | // we're going to be shifting bytes around, 12 | // so treat them like unsigned 8-bit values 13 | uint8_t c = s[i]; 14 | if (c == 0) { 15 | // reached null terminator, stop printing 16 | break; 17 | } 18 | 19 | // length of the sequence, ie., number of bytes 20 | // that encode a single Unicode scalar value 21 | int len = 1; 22 | if (c >> 5 == 0b110) { 23 | len = 2; 24 | } else if (c >> 4 == 0b1110) { 25 | len = 3; 26 | } else if (c >> 3 == 0b11110) { 27 | len = 4; 28 | } 29 | 30 | // print the entire UTF-8-encoded Unicode scalar value 31 | for (; len > 0; len--) { 32 | printf("%c", s[i]); 33 | i++; 34 | } 35 | // print space separator 36 | printf(" "); 37 | } 38 | } 39 | 40 | int main(int argc, char **argv) { 41 | for (int i = 1; i < argc; i++) { 42 | print_spaced(argv[i]); 43 | printf("\n"); 44 | } 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /simple/string/print.js: -------------------------------------------------------------------------------- 1 | // in `print.js` 2 | 3 | const { argv, stdout } = process; 4 | 5 | // we have to skip *two* arguments: the path to node, 6 | // and the path to our script 7 | for (const arg of argv.slice(2)) { 8 | stdout.write(arg.toUpperCase()); 9 | stdout.write("\n"); 10 | } -------------------------------------------------------------------------------- /simple/string/rustre/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /simple/string/rustre/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rustre" 3 | version = "0.1.0" 4 | authors = ["lesterli "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /simple/string/rustre/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut upp = String::with_capacity(512); 3 | for arg in std::env::args().skip(1) { 4 | upp.clear(); 5 | uppercase(&arg, &mut upp); 6 | println!("upp = {}", upp); 7 | println!("arg = {}", arg); 8 | } 9 | } 10 | 11 | // was `mut dst: String` 12 | fn uppercase(src: &str, dst: &mut String) { 13 | for c in src.chars() { 14 | for c in c.to_uppercase() { 15 | dst.push(c); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /simple/string/upper.c: -------------------------------------------------------------------------------- 1 | // in `upper.c` 2 | 3 | #include // printf 4 | #include // uint8_t, uint32_t 5 | #include // exit 6 | 7 | void encode_utf8(uint32_t *src, char *dst) { 8 | int i = 0; 9 | int j = 0; 10 | 11 | while (1) { 12 | uint32_t scalar = src[i]; 13 | 14 | if (scalar == 0) { 15 | dst[j] = 0; // null terminator 16 | break; 17 | } 18 | 19 | if (scalar > 0b11111111111) { 20 | fprintf(stderr, "Can only encode codepoints <= 0x%x", 0b11111111111); 21 | exit(1); 22 | } 23 | 24 | if (scalar > 0b1111111) { // 7 bits 25 | // 2-byte sequence 26 | 27 | uint8_t b1 = 0b11000000 | ((uint8_t) ((scalar & 0b11111000000) >> 6)); 28 | // 2-byte marker first 5 of 11 bits 29 | 30 | uint8_t b2 = 0b10000000 | ((uint8_t) (scalar & 0b111111)); 31 | // continuation last 6 of 11 bits 32 | 33 | dst[j + 0] = b1; 34 | dst[j + 1] = b2; 35 | j += 2; 36 | } else { 37 | // 1-byte sequence 38 | dst[j] = (char) scalar; 39 | j++; 40 | } 41 | 42 | i++; 43 | } 44 | } 45 | 46 | void decode_utf8(char *src, uint32_t *dst) { 47 | int i = 0; 48 | int j = 0; 49 | 50 | while (1) { 51 | uint8_t c = src[i]; 52 | if (c == 0) { 53 | dst[j] = 0; 54 | break; // null terminator 55 | } 56 | 57 | uint32_t scalar; 58 | int len; 59 | 60 | if (c >> 3 == 0b11110) { 61 | fprintf(stderr, "decode_utf8: 4-byte sequences are not supported!\n"); 62 | exit(1); 63 | } if (c >> 4 == 0b1110) { 64 | fprintf(stderr, "decode_utf8: 3-byte sequences are not supported!\n"); 65 | exit(1); 66 | } else if (c >> 5 == 0b110) { 67 | // 2-byte sequence 68 | uint32_t b1 = (uint32_t) src[i]; 69 | uint32_t b2 = (uint32_t) src[i + 1]; 70 | uint32_t mask1 = 0b0000011111000000; 71 | uint32_t mask2 = 0b0000000000111111; 72 | 73 | scalar = ((b1 << 6) & mask1) | ((b2 << 0) & mask2); 74 | len = 2; 75 | } else { 76 | // 1-byte sequence 77 | scalar = (uint32_t) c; 78 | len = 1; 79 | } 80 | dst[j++] = scalar; 81 | i += len; 82 | } 83 | } 84 | 85 | #include // toupper 86 | 87 | int main(int argc, char **argv) { 88 | uint32_t scalars[1024]; // hopefully that's enough 89 | decode_utf8(argv[1], scalars); 90 | 91 | for (int i = 0;; i++) { 92 | if (scalars[i] == 0) { 93 | break; 94 | } 95 | printf("U+%04X ", scalars[i]); 96 | } 97 | printf("\n"); 98 | 99 | // this is the highest codepoint we can decode/encode successfully 100 | const size_t table_size = 0b11111111111; 101 | uint32_t lower_to_upper[table_size]; 102 | // initialize the table to just return the codepoint unchanged 103 | for (uint32_t cp = 0; cp < table_size; cp++) { 104 | lower_to_upper[cp] = cp; 105 | } 106 | // set a-z => A-Z 107 | for (int c = 97; c <= 122; c++) { // ha. 108 | lower_to_upper[(uint32_t) c] = (uint32_t) toupper(c); 109 | } 110 | 111 | // note: nested functions is a GNU extension! 112 | void set(char *lower, char *upper) { 113 | uint32_t lower_s[1024]; 114 | uint32_t upper_s[1024]; 115 | decode_utf8(lower, lower_s); 116 | decode_utf8(upper, upper_s); 117 | for (int i = 0;; i++) { 118 | if (lower_s[i] == 0) { 119 | break; 120 | } 121 | lower_to_upper[lower_s[i]] = upper_s[i]; 122 | } 123 | } 124 | // set a few more 125 | set( 126 | "éêèàâëüöïÿôîçæœ", 127 | "ÉÊÈÀÂËÜÖÏŸÔÎÇÆŒ" 128 | ); 129 | 130 | // now convert our scalars to upper-case 131 | for (int i = 0;; i++) { 132 | if (scalars[i] == 0) { 133 | break; 134 | } 135 | scalars[i] = lower_to_upper[scalars[i]]; 136 | } 137 | 138 | uint8_t result[1024]; // yolo 139 | encode_utf8(scalars, result); 140 | 141 | printf("%s\n", result); 142 | 143 | return 0; 144 | } -------------------------------------------------------------------------------- /simple/string/woops.c: -------------------------------------------------------------------------------- 1 | // in `woops.c` 2 | 3 | #include 4 | #include 5 | 6 | void uppercase(char *s) { 7 | // this is peak C right there 8 | do { 9 | *s = toupper(*s); 10 | } while (*s++); 11 | } 12 | 13 | int main(int argc, char **argv) { 14 | char *arg = argv[1]; 15 | 16 | char *upp = arg; 17 | uppercase(upp); 18 | 19 | printf("upp = %s\n", upp); 20 | } --------------------------------------------------------------------------------