├── .gitignore ├── LICENSE ├── README.md ├── async ├── .gitignore └── Readme.md ├── async_std ├── .gitignore └── how_to_ref_self │ ├── .gitignore │ ├── README.md │ ├── by_arc │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── by_block_on │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── by_life_time │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── by_pin │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ └── by_static │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── atomic_memory_order ├── .gitignore └── Readme.md ├── bit_operations ├── .gitignore ├── README.md ├── base_bit │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── bitflags │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── enumflags2 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── cpp_placement_new ├── .gitignore └── Readme.md ├── data_cmp ├── .gitignore └── Readme.md ├── destructor_in_rust ├── .gitignore ├── Readme.md └── destructor_sequence │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── enum_rust ├── .gitignore ├── README.md ├── alias_enum │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── alist │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── define_enum │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── like_c │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── use_declare │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── fn_overload ├── .gitignore ├── Readme.md ├── add_trait │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── macro_for_variadic │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── overload_1 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── overload_2 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── global_data_usage ├── .gitignore └── Readme.md ├── mathmatics ├── .gitignore ├── endecode │ ├── .gitignore │ └── base58_bs58 │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ └── main.rs ├── hash_learn │ ├── .gitignore │ ├── hash256_t │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ ├── ripemd160_t │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ ├── secp256k1_k256 │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ └── secp256k1_secp256k1 │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ └── main.rs └── ndarray_learn │ ├── .gitignore │ └── matrix │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── mio ├── .gitignore ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── README.md ├── mio_1 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── mio_2 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── mio_oneshot_test │ ├── .gitignore │ ├── mio_server │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── tcp_client_block │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs │ └── tcp_client_noneblock │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── mmqrcode1654076680683.png ├── mut_diveinto ├── .gitignore ├── .vscode │ └── launch.json ├── Cargo.toml └── src │ └── main.rs ├── orphan_rule ├── .gitignore ├── base │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── generic │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── wrapper │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── os_signal_handling_in_rust ├── .gitignore ├── Cargo.toml ├── README.md ├── ctrlc_1 │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── ctrlc_channel │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── signal_hook │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── signal_hook2 │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── signal_hook_cross_beam_channel │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── signal_hook_tokio │ ├── .Cargo.toml.swp │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ └── main.rs ├── others ├── .gitignore └── Readme.md ├── panic_in_rust ├── .gitignore ├── Cargo.toml ├── README.md ├── mutex_poisoned │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── panic-1 │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── panic-assert-unwind-safe │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── panic-catch-recover │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── panic-handle │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── panic-rethrow │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── panic-set-hook │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── panic-take-hook │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── panic-unwind-safe-test │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── panic-write-to-log │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── peer_socket_dead_check ├── .gitignore ├── README.md ├── libc_socket_server │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── tcp_client_block │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── tcp_client_noneblock │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── tcp_client_tokio │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── pin_unpin ├── .gitignore ├── Readme.md ├── pin_to_heap │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── pin_to_stack │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── self_ref_struct │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── rust_embeded ├── .gitignore └── Readme.md ├── rust_iter ├── .gitignore ├── README.md ├── create_intoiterator │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── create_intoiterator2 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── create_intoiterator3 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── create_intoiterator4 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── create_intoiterator5 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── iter_method │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── rust_mod_study ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── exp │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ ├── consumer │ │ ├── cons.rs │ │ └── mod.rs │ │ ├── main.rs │ │ ├── producer │ │ ├── mod.rs │ │ └── pror.rs │ │ ├── switcher.rs │ │ └── switcher │ │ └── sw.rs ├── lip │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── lip1 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ ├── caller.rs │ │ ├── lib.rs │ │ └── worker.rs ├── lip2 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ ├── caller.rs │ │ ├── lib.rs │ │ └── worker │ │ ├── mod.rs │ │ ├── worker1.rs │ │ ├── worker2.rs │ │ └── worker3.rs └── lip3 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ ├── caller.rs │ ├── caller │ └── callerin.rs │ └── lib.rs ├── rust_my_error ├── .gitignore ├── README.md ├── anyhow_t │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── my_enum_error │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ ├── error.rs │ │ └── main.rs ├── my_struct_error │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ ├── .gitignore │ │ ├── error.rs │ │ └── main.rs └── thiserror_t │ ├── .gitignore │ ├── Cargo.toml │ └── src │ ├── count.rs │ ├── error.rs │ └── lib.rs ├── rust_result_option ├── .gitignore ├── README.md ├── error_propagation_byquestion_mark │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── error_propagation_primitive │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── rust_primitive │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── tokio ├── .gitignore ├── hello_world │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── select_macro │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs └── tokio_check_result_error │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── toml_parser ├── .gitignore ├── README.md ├── toml_1 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs └── toml_2 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ ├── .gitignore │ └── main.rs ├── too_many_lists ├── .gitignore ├── Readme.md ├── lists │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ ├── first.rs │ │ ├── lib.rs │ │ ├── second.rs │ │ └── third.rs └── splitting_borrows │ ├── .gitignore │ └── mut_ref_to_struct_subfield │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs └── unsafe_collect ├── .gitignore ├── ffi ├── .gitignore ├── README.md ├── Rust FFI (C vs Rust)学习杂记.pdf ├── c2rust │ ├── .gitignore │ ├── README.md │ ├── box_t │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── c_call_rust.c │ │ │ └── lib.rs │ ├── closure_as_callback │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── build.rs │ │ └── src │ │ │ ├── closure.c │ │ │ ├── closure.rs │ │ │ └── main.rs │ └── simple │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── build.rs │ │ └── src │ │ ├── main.rs │ │ ├── simple.c │ │ └── simple.rs └── rust2c │ ├── .gitignore │ ├── README.md │ ├── build_c_lib_by_gcc │ ├── .gitignore │ ├── Cargo.toml │ ├── build.rs │ └── src │ │ ├── hello.c │ │ └── main.rs │ ├── cc_auto_build_c_lib │ ├── .gitignore │ ├── Cargo.toml │ ├── build.rs │ └── src │ │ ├── hello.c │ │ └── main.rs │ ├── code_generate │ ├── .gitignore │ ├── Cargo.toml │ ├── build.rs │ └── src │ │ └── main.rs │ ├── conditional_compilation │ ├── .gitignore │ ├── Cargo.toml │ ├── build.rs │ └── src │ │ └── main.rs │ ├── manual_build_1 │ ├── .gitignore │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ └── test.c │ └── write_c_in_rust │ ├── .gitignore │ ├── Cargo.toml │ ├── build.rs │ └── src │ └── main.rs └── variance └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rust 铁粉 --- 寻找Rust职位中! 2 | 3 | C++老码农,从业经历丰富,如:服务端、客户端、`苹果App`、手机游戏、分布式、云计算等领域皆有所涉猎!虽未成大器,但刻苦求索,敏而好学,不耻下问,孜孜不倦! 4 | 5 | >------------------------ 6 | C++语言入行,多年磨炼,经验还是有的!之前于项目中接触`golang`,遂学习之,简洁高效甚是令我喜爱,然C++之癖好难改,甚是难以彻底接受`GC`类语言,故此始终不冷不热,直到遇到Rust后, 令我倾心叹服!故而打算全身心投入钻研之,一心一意!是故所著代码行文虽粗鄙,仍不改初心,奉与诸君,以求指正! 7 | 8 | >------------------------ 9 | 感叹人生好似陀螺,拼命地旋转着,总期望着未来也许可以稳定下来!但是 不断的鞭挞令你无从喘息! 10 | 11 | 那年同学少年,而今两鬓霜花!多少事已成空!罢罢罢!江湖一去无踪影, 归来依旧少年郎! 12 | 13 | >------------------------ 14 | RUST学习随笔,水平有限,难免谬误,请多指教。 15 | 16 | * 作者: 于金良 17 | * 邮箱: 285779289@qq.com 18 | * 微信: lingshanxingzhe-pure 19 | * csdn: https://blog.csdn.net/htyu_0203_39 20 | * zhihu: https://www.zhihu.com/people/yujinliang-pure 21 | 22 | -------------------------------------------------------------------------------- /async/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /async/Readme.md: -------------------------------------------------------------------------------- 1 | # Rust异步编程杂记 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | - 异步编程大敌阻塞 12 | 13 | > `https://blog.hwc.io/posts/rust-futures-threadsleep-and-blocking-calls-inside-async-fn/` 14 | > 15 | > `https://stjepang.github.io/2019/12/04/blocking-inside-async-code.html` 16 | > 17 | > `https://rickyhan.com/jekyll/update/2019/12/22/convert-to-async-rust.html` 18 | > 19 | > `https://async.rs/blog/stop-worrying-about-blocking-the-new-async-std-runtime/` 20 | > 21 | > --- 22 | > 23 | > 对于异步编程, 我认为async runtime应该自动检测blocking发生, 一旦达到时间阀值, 自动为async task executor 创建新的执行线程, 从而避免队列中其他aysnc task因为没有线程来分配而不能运行!从而无缝地将同步阻塞和异步编程很好地合二为一!这样两个世界变为一个世界!这样,我们就可以很自然地使用diesel/rayon等计算密集型的库来真正解决问题。比较彻底地解决了异步编程只适合IO密集型项目的缺点! 24 | > 25 | > 其实一切的焦点在于效率: golang goroutine采用抢占式调度了,所以阻塞不再是问题!而Rust 协程是协作式调度, 一旦发生阻塞,则协作无法完成,大家都无法再继续执行下去!前者可以彻底避免阻塞的危害!但是抢占是有代价的!牺牲一定的性能! 而后者没有各种检测和抢占代码效率损耗,执行效率可能会更优!但是无法克服阻塞的问题! 26 | 27 | 28 | 29 | - 对于不能直接借用本地栈变量的克服方法: 30 | 31 | > 1. move 闭包, 且clone要借用的变量。 32 | > 33 | > 2. 不要borrow, 而是move ownship. 34 | > 3. Task::scop. 35 | > 4. Task::Block_on 36 | > 5. Arc. 37 | > 6. Pin 38 | > 7. static variable 39 | > 8. impl Future 40 | > 41 | > 具体例子请看:`https://github.com/yujinliang/rust_learn/tree/master/async_std/how_to_ref_self` 42 | 43 | 44 | 45 | 46 | 47 | - 协作式调度 vs 抢占式调度(preemptive - cooperative) 48 | 49 | > `https://www.zhihu.com/question/271657274/answer/376416028` 50 | > 51 | > 【抢占方法】 52 | > 53 | > (1). os signal 54 | > 55 | > 这个提案要实现的,如字面意思,就是强行让一个 goroutine 让出 CPU,不管该 goroutine 在做什么,不需要 goroutine 的“协作”,就能抢占该 goroutine 的 CPU 时间。go 现在的调度器,如果想从外部让一个 goroutine 让出 CPU 时间,只能在函数的入口处做一些手脚,让该 goroutine 在调用函数之前,发现它应该让出 CPU,这就是协作式的,因为需要 goroutine 执行到那一个路径,外部只能等待它执行到那里,或者其他一些触发到调度的代码路径。 56 | > 57 | > 这个提案的方案是,直接用信号让执行 goroutine 的系统线程切换到信号处理器,从而实现 goroutine 的打断。 58 | > 59 | > (2). 在每个函数调用入口加入调度代码,判断是否抢占! 不彻底,因为一旦进入函数再阻塞, 则无法抢占!而且效率代价大! 60 | 61 | 62 | 63 | 64 | 65 | - Author 66 | 67 | > 学习随笔,如有谬误,望请海涵雅正,谢谢。 68 | > 69 | > 作者:心尘了 70 | > 71 | > email: [285779289@qq.com](mailto:285779289@qq.com) 72 | > 73 | > git: https://github.com/yujinliang 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | - Reference 82 | 83 | > `https://blog.logrocket.com/a-practical-guide-to-async-in-rust/` 84 | > 85 | > `https://alastairreid.github.io/rust-verification-tools/` 86 | > 87 | > `https://github.com/rust-lang/async-book` 88 | > 89 | > `http://xion.io/tag/async.html` 90 | > 91 | > `https://omarabid.com/async-rust` 92 | > 93 | > `https://async.rs/` 94 | > 95 | > `https://areweasyncyet.rs/` 96 | > 97 | > `https://zhuanlan.zhihu.com/p/37209852` 98 | > 99 | > `https://blog.rust-lang.org/2019/11/07/Async-await-stable.html` 100 | > 101 | > `https://rust-lang.github.io/async-book/03_async_await/01_chapter.html` 102 | > 103 | > `https://www.philipdaniels.com/blog/2019/async-std-demo1/` 104 | > 105 | > `https://book.async.rs/concepts/tasks.html` 106 | > 107 | > `https://rust-lang.github.io/async-book/` 108 | 109 | -------------------------------------------------------------------------------- /async_std/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /async_std/how_to_ref_self/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_arc/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_arc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "by_arc" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | async-std="1.5" -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_arc/src/main.rs: -------------------------------------------------------------------------------- 1 | use async_std::task; 2 | use async_std::sync::Arc; 3 | 4 | struct Circle { 5 | radius:f64 6 | } 7 | impl Circle { 8 | async fn area(self:Arc) -> f64 { 9 | let self_divide = self.clone(); 10 | let join_handle = task::spawn(async move { 11 | 2.0*3.1415*self_divide.radius 12 | }); 13 | join_handle.await 14 | } 15 | 16 | } 17 | fn main() { 18 | task::block_on(async { 19 | let by_arc = Arc::new(Circle{radius:30.5}); 20 | println!("{}", by_arc.area().await); 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_block_on/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_block_on/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "by_block_on" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | async-std="1.5" -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_block_on/src/main.rs: -------------------------------------------------------------------------------- 1 | use async_std::task; 2 | 3 | struct Circle { 4 | radius:f64 5 | } 6 | impl Circle { 7 | async fn area(&self) -> f64 { 8 | task::block_on(async { 9 | 2.0*3.1415*self.radius 10 | }) 11 | } 12 | 13 | } 14 | fn main() { 15 | task::block_on(async { 16 | let by_blockon = Circle{radius:30.5}; 17 | println!("{}", by_blockon.area().await); 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_life_time/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_life_time/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "by_life_time" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | async-std="1.5" 11 | futures = "0.3.4" -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_life_time/src/main.rs: -------------------------------------------------------------------------------- 1 | use async_std::task; 2 | //use async_std::task::JoinHandle; 3 | use futures::{future, Future,FutureExt}; 4 | use std::error::Error; 5 | 6 | struct Circle { 7 | radius:f64 8 | } 9 | 10 | impl Circle { 11 | async fn make_a_future<'a>(&'a self) -> impl Future +'a { 12 | //below code compilation failed, coz ref self, unless add move for async block. 13 | async move { 14 | 2.0*3.1415*self.radius 15 | } 16 | } 17 | 18 | async fn make_b_future<'a>(&'a self) -> impl Future +'a { 19 | future::ok(self).map(|pa:Result<&'a Self, Box>| {2.0*3.1415*pa.unwrap().radius}) 20 | } 21 | 22 | } 23 | fn main() { 24 | task::block_on(async { 25 | let by_life = Circle{radius:30.5}; 26 | //1.for task::spawn 27 | //compilation failed with task::spawn. 28 | //let r = task::spawn(by_life.make_a_future()).await; 29 | 30 | //2.for async block 31 | let ra = by_life.make_a_future().await; 32 | println!("{:?}", ra.await); 33 | 34 | //3.for future 35 | let rb = by_life.make_b_future().await; 36 | println!("{:?}", rb.await); 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_pin/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_pin/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "by_pin" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | async-std = "1.6.2" 11 | -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_pin/src/main.rs: -------------------------------------------------------------------------------- 1 | use async_std::task; 2 | use std::pin::Pin; 3 | 4 | struct Circle { 5 | radius:f64 6 | } 7 | impl Circle { 8 | async fn area(self : Pin>) -> f64 { 9 | let join_handle = task::spawn(async move { 10 | 2.0*3.1415*self.radius //spawn need : self is required to live as long as `'static` here 11 | }); 12 | join_handle.await 13 | } 14 | 15 | } 16 | fn main() { 17 | task::block_on(async { 18 | let by_arc = Box::pin(Circle{radius:30.5}); 19 | println!("{}", by_arc.area().await); 20 | }) 21 | } -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_static/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_static/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "by_static" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | async-std="1.5" -------------------------------------------------------------------------------- /async_std/how_to_ref_self/by_static/src/main.rs: -------------------------------------------------------------------------------- 1 | use async_std::task; 2 | 3 | struct Circle { 4 | radius:f64 5 | } 6 | impl Circle { 7 | async fn area(&'static self) -> f64 { 8 | let j_handle = task::spawn(async move { 9 | 2.0*3.1415*self.radius 10 | }) ; 11 | j_handle.await 12 | } 13 | 14 | } 15 | fn main() { 16 | task::block_on(async { 17 | static BY_STATIC:Circle = Circle{radius:30.5}; 18 | println!("{}", BY_STATIC.area().await); 19 | println!("{}", BY_STATIC.area().await); 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /atomic_memory_order/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /bit_operations/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /bit_operations/base_bit/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /bit_operations/base_bit/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "base_bit" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /bit_operations/base_bit/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut byte: u8 = 0b0000_0000; 3 | println!("0b{:08b}", byte); 4 | 5 | byte |= 0b0000_1000; // Set a bit 6 | println!("0b{:08b}", byte); 7 | 8 | byte &= 0b1111_0111; // Unset a bit 9 | println!("0b{:08b}", byte); 10 | 11 | byte ^= 0b0000_1000; // Toggle a bit 12 | println!("0b{:08b}", byte); 13 | 14 | byte = !byte; // Flip all bits 15 | println!("0b{:08b}", byte); 16 | 17 | byte <<= 1; // shift left one bit 18 | println!("0b{:08b}", byte); 19 | 20 | byte >>= 1; // shift right one bit 21 | println!("0b{:08b}", byte); 22 | 23 | //https://doc.rust-lang.org/std/primitive.u8.html 24 | let mut rbyte: u8 = 0b1000_0000; 25 | rbyte = rbyte.rotate_left(1); // rotate left one bit 26 | println!("0b{:08b}", byte); 27 | //https://doc.rust-lang.org/std/#primitives 28 | rbyte = rbyte.rotate_right(1); // rotate right one bit 29 | println!("0b{:08b}", rbyte); 30 | 31 | bit_twiddling(0, 3); 32 | bit_twiddling(8, 3); 33 | 34 | //test bitwise operation macros 35 | assert_eq!(eq1!(0b0000_1111, 0), true); 36 | assert_eq!(eq0!(0b0000_1111, 4), true); 37 | assert_eq!(set!(0b0000_1111, 0), 0x0f); 38 | assert_eq!(clr!(0b0000_1111, 0), 0x0e); 39 | } 40 | 41 | fn bit_twiddling(original: u8, bit: u8) { 42 | let mask = 1 << bit; 43 | 44 | println!( 45 | "Original: {:b}, Set: {:b}, Cleared: {:b}, Toggled: {:b}", 46 | original, 47 | original | mask, 48 | original & !mask, 49 | original ^ mask 50 | ); 51 | } 52 | 53 | //define rust macro for bitwise operations 54 | #[macro_export] 55 | macro_rules! eq1 { 56 | ($n:expr, $b:expr) => { 57 | $n & (1 << $b) != 0 58 | }; 59 | } 60 | 61 | #[macro_export] 62 | macro_rules! eq0 { 63 | ($n:expr, $b:expr) => { 64 | $n & (1 << $b) == 0 65 | }; 66 | } 67 | 68 | #[macro_export] 69 | macro_rules! set { 70 | ($n:expr, $b:expr) => { 71 | $n | (1 << $b) 72 | }; 73 | } 74 | 75 | #[macro_export] 76 | macro_rules! clr { 77 | ($n:expr, $b:expr) => { 78 | $n & !(1 << $b) 79 | }; 80 | } -------------------------------------------------------------------------------- /bit_operations/bitflags/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /bit_operations/bitflags/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bitflags" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | bitflags = "1.2.1" 11 | -------------------------------------------------------------------------------- /bit_operations/bitflags/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | #[macro_use] 4 | extern crate bitflags; 5 | 6 | bitflags! { 7 | pub struct Flags: u32 {//模块可见性: private默认本模块可见, pub模块外也可见。 8 | const A = 0b00000001; 9 | const B = 0b00000010; 10 | const C = 0b00000100; 11 | const ABC = Self::A.bits | Self::B.bits | Self::C.bits; 12 | } 13 | } 14 | 15 | impl Flags { 16 | pub fn clear(&mut self) { 17 | self.bits = 0; // The `bits` field can be accessed from within the 18 | // same module where the `bitflags!` macro was invoked. 19 | } 20 | } 21 | 22 | impl fmt::Display for Flags { 23 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 24 | write!(f, "hi!") 25 | } 26 | } 27 | 28 | fn main() { 29 | //example1 30 | let e1 = Flags::A | Flags::C; 31 | let e2 = Flags::B | Flags::C; 32 | assert_eq!((e1 | e2), Flags::ABC); // union 33 | assert_eq!((e1 & e2), Flags::C); // intersection 34 | assert_eq!((e1 - e2), Flags::A); // set difference 35 | assert_eq!(!e2, Flags::A); // set complement 36 | assert!(e1.contains(Flags::A)); 37 | //example2 38 | let mut flags = Flags::A | Flags::B; 39 | flags.clear(); 40 | assert!(flags.is_empty()); 41 | assert_eq!(format!("{}", flags), "hi!"); 42 | assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B"); 43 | assert_eq!(format!("{:?}", Flags::B), "B"); 44 | } -------------------------------------------------------------------------------- /bit_operations/enumflags2/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /bit_operations/enumflags2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "enumflags2" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | enumflags2 = "0.6.4" -------------------------------------------------------------------------------- /bit_operations/enumflags2/src/main.rs: -------------------------------------------------------------------------------- 1 | use enumflags2::BitFlags; 2 | 3 | #[derive(BitFlags, Copy, Clone, Debug, PartialEq)] 4 | #[repr(u8)] 5 | enum Test { 6 | A = 0b0001, 7 | B = 0b0010, 8 | C = 0b0100, 9 | D = 0b1000, 10 | } 11 | 12 | fn main() { 13 | 14 | let a_b = Test::A | Test::B; // BitFlags 15 | let a_c = Test::A | Test::C; 16 | let b_c_d = Test::C | Test::B | Test::D; 17 | 18 | // BitFlags(0b11, [A, B]) 19 | println!("{:?}", a_b); 20 | 21 | // BitFlags(0b1, [A]) 22 | println!("{:?}", a_b & a_c); 23 | 24 | // Iterate over the flags like a normal set! 25 | assert_eq!(a_b.iter().collect::>(), &[Test::A, Test::B]); 26 | 27 | assert!(a_b.contains(Test::A)); 28 | assert!(b_c_d.contains(Test::B | Test::C)); 29 | assert!(!(b_c_d.contains(a_b))); 30 | 31 | assert!(a_b.intersects(a_c)); 32 | assert!(!(a_b.intersects(Test::C | Test::D))); 33 | } 34 | -------------------------------------------------------------------------------- /cpp_placement_new/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /cpp_placement_new/Readme.md: -------------------------------------------------------------------------------- 1 | # `C++ Placement new in Rust Tracking ` 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | - 相关资料收集杂记 10 | 11 | > 12 | > 13 | > 14 | > Rust中的堆分配现在是如何工作的??? 15 | > 16 | > 堆分配隐藏在Rust stable中的Box类型后面。当您在一个Box类型中实例化数据时,您将把数据放入堆中,并且Box类型存储一个指向该堆分配数据的内部指针。 17 | > 18 | > 而且堆内存的分配和释放完全由Rust 编译器负责!隐藏在Rust 编译器背后! 19 | > 20 | > 现在Rust stable 还不支持C++ placement new , 相关的讨论争论还在继续! 我认为Rust安全的基石在于对内存的严格控制! 如果贸然在围墙上开一个洞, 我看还需谨慎考虑和缜密设计!任何新语言特性的加入都不允许危害Rust的安全基石! 21 | > 22 | > 相关的讨论和设计,请看: 23 | > 24 | > http://blakesmith.me/2018/12/31/what-is-placement-new-in-rust.html 25 | > 26 | > https://github.com/rust-lang/rust/issues/27779 27 | > https://github.com/rust-lang/rust/pull/48333 28 | > https://internals.rust-lang.org/t/removal-of-all-unstable-placement-features/7223 29 | 30 | 31 | 32 | > Rust每一新的语言特性的加入都要经过旷日持久的讨论和争论, 即使已经加入的语言特性若发现严重问题,也可能砍去!这正是Rust高质量高效率的基石, 33 | > 34 | > 所以C++ placement new还在讨论完善之中, 我会持续关注更新。 35 | 36 | 37 | 38 | - Author 39 | 40 | > 学习随笔,如有谬误,望请海涵雅正,谢谢。 41 | > 42 | > 作者:心尘了 43 | > 44 | > email: [285779289@qq.com](mailto:285779289@qq.com) 45 | > 46 | > git: https://github.com/yujinliang -------------------------------------------------------------------------------- /data_cmp/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /destructor_in_rust/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /destructor_in_rust/destructor_sequence/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /destructor_in_rust/destructor_sequence/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "destructor_sequence" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /destructor_in_rust/destructor_sequence/src/main.rs: -------------------------------------------------------------------------------- 1 | 2 | #[derive(Debug)] 3 | struct SubField(u8); 4 | 5 | impl Drop for SubField { 6 | fn drop(&mut self) { 7 | println!("{:?}", self); 8 | } 9 | } 10 | 11 | #[derive(Debug)] 12 | struct HasDrop 13 | { 14 | a: SubField, 15 | b:SubField, 16 | c:SubField, 17 | d:SubField, 18 | } //你的自定义类型。 19 | 20 | impl Drop for HasDrop { 21 | fn drop(&mut self) { 22 | println!("HasDrop!"); 23 | } 24 | } 25 | 26 | fn main() { 27 | let _x = HasDrop{a:SubField(1), b:SubField(2), c:SubField(3), d:SubField(4)}; 28 | } -------------------------------------------------------------------------------- /enum_rust/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /enum_rust/alias_enum/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /enum_rust/alias_enum/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "alias_enum" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /enum_rust/alias_enum/src/main.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | enum VeryVerboseEnumOfThingsToDoWithNumbers { 3 | Add, 4 | Subtract, 5 | } 6 | 7 | // 为上面的enum创建一个类型别名。 8 | type Operations = VeryVerboseEnumOfThingsToDoWithNumbers; 9 | 10 | impl VeryVerboseEnumOfThingsToDoWithNumbers { 11 | fn run(&self, x: i32, y: i32) -> i32 { 12 | //注意Self 也是上面enum的类型别名。 13 | match self { 14 | Self::Add => x + y, 15 | Self::Subtract => x - y, 16 | } 17 | } 18 | } 19 | 20 | fn main() { 21 | //我们可以通过它的别名来引用每个变体,而不是冗长和不方便的名字。 22 | let x = Operations::Add; 23 | let y = Operations::Subtract; 24 | println!("{:?}: {}",x, x.run(3, 4)); 25 | println!("{:?}: {}",y, y.run(3, 4)); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /enum_rust/alist/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /enum_rust/alist/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "alist" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /enum_rust/alist/src/main.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, PartialEq, Eq)] 2 | pub enum List { 3 | // Cons: Tuple struct that wraps an element and a pointer to the next node 4 | Nodes(u32, Box), 5 | // Nil: A node that signifies the end of the linked list 6 | Nil, 7 | } 8 | 9 | // Methods can be attached to an enum 10 | impl List { 11 | // Create an empty list 12 | fn new() -> List { 13 | // `Nil` has type `List` 14 | Self::Nil 15 | } 16 | 17 | // Consume a list, and return the same list with a new element at its front 18 | fn push_front(self, elem: u32) -> List { 19 | // `Node` also has type List 20 | Self::Nodes(elem, Box::new(self)) 21 | } 22 | 23 | // Return the length of the list 24 | fn len(&self) -> u32 { 25 | // `self` has to be matched, because the behavior of this method 26 | // depends on the variant of `self` 27 | // `self` has type `&List`, and `*self` has type `List`, matching on a 28 | // concrete type `T` is preferred over a match on a reference `&T` 29 | match *self { 30 | // Can't take ownership of the tail, because `self` is borrowed; 31 | // instead take a reference to the tail 32 | Self::Nodes(_, ref tail) => 1 + tail.len(), 33 | // Base Case: An empty list has zero length 34 | Self::Nil => 0 35 | } 36 | } 37 | 38 | // Return representation of the list as a (heap allocated) string 39 | fn stringify(&self) -> String { 40 | match *self { 41 | Self::Nodes(head, ref tail) => { 42 | // `format!` is similar to `print!`, but returns a heap 43 | // allocated string instead of printing to the console 44 | format!("{}, {}", head, tail.stringify()) 45 | }, 46 | Self::Nil => { 47 | format!("Nil") 48 | }, 49 | } 50 | } 51 | } 52 | 53 | fn main() { 54 | // Create an empty linked list 55 | let mut list = List::new(); 56 | 57 | // Prepend some elements 58 | list = list.push_front(1); 59 | list = list.push_front(2); 60 | list = list.push_front(3); 61 | 62 | // Show the final state of the list 63 | println!("linked list has length: {}", list.len()); 64 | println!("{}", list.stringify()); 65 | } -------------------------------------------------------------------------------- /enum_rust/define_enum/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /enum_rust/define_enum/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "define_enum" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /enum_rust/define_enum/src/main.rs: -------------------------------------------------------------------------------- 1 | enum WebEvent { 2 | // An `enum` may either be `unit-like`, 3 | PageLoad, 4 | PageUnload, 5 | // like tuple structs, 6 | KeyPress(char), 7 | Paste(String), 8 | // or c-like structures. 9 | Click { x: i64, y: i64 }, 10 | } 11 | 12 | // A function which takes a `WebEvent` enum as an argument and 13 | // returns nothing. 14 | fn inspect(event: WebEvent) { 15 | match event { 16 | WebEvent::PageLoad => println!("page loaded"), 17 | WebEvent::PageUnload => println!("page unloaded"), 18 | // Destructure `c` from inside the `enum`. 19 | WebEvent::KeyPress(c) => println!("pressed '{}'.", c), 20 | WebEvent::Paste(s) => println!("pasted \"{}\".", s), 21 | // Destructure `Click` into `x` and `y`. 22 | WebEvent::Click { x, y } => { 23 | println!("clicked at x={}, y={}.", x, y); 24 | }, 25 | } 26 | } 27 | 28 | fn main() { 29 | let pressed = WebEvent::KeyPress('x'); 30 | // `to_owned()` creates an owned `String` from a string slice. 31 | let pasted = WebEvent::Paste("my text".to_owned()); 32 | let click = WebEvent::Click { x: 20, y: 80 }; 33 | let load = WebEvent::PageLoad; 34 | let unload = WebEvent::PageUnload; 35 | 36 | inspect(pressed); 37 | inspect(pasted); 38 | inspect(click); 39 | inspect(load); 40 | inspect(unload); 41 | } -------------------------------------------------------------------------------- /enum_rust/like_c/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /enum_rust/like_c/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "like_c" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /enum_rust/like_c/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | //https://doc.rust-lang.org/nomicon/other-reprs.html 4 | //#[repr(C)] 5 | #[repr(u8)] 6 | enum Number { 7 | Zero, //默认从0开始。 8 | One = 22, 9 | Two, 10 | } 11 | 12 | // enum with explicit discriminator 13 | #[repr(C)] 14 | #[derive(Debug, PartialEq, Eq)] 15 | enum Color { 16 | Red = 0xff0000, 17 | Green = 0x00ff00, 18 | Blue = 0x0000ff, 19 | } 20 | 21 | fn main() { 22 | // `enums` can be cast as integers. 23 | println!("zero is {}", Number::Zero as u8); 24 | println!("one is {}", Number::One as u8); 25 | println!("one is {}", Number::Two as u8); 26 | 27 | println!("roses are #{:06x}", Color::Red as i32); 28 | println!("violets are #{:06x}", Color::Blue as i32); 29 | 30 | let color = Color::Blue; 31 | if color == Color::Blue { //must implement PartialEq trait. 32 | println!("{:?}", color); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /enum_rust/use_declare/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /enum_rust/use_declare/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "use_declare" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /enum_rust/use_declare/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | enum Status { 4 | Rich, 5 | Poor, 6 | } 7 | 8 | enum Work { 9 | Civilian, 10 | Soldier, 11 | } 12 | 13 | fn main() { 14 | // Explicitly `use` each name so they are available without 15 | // manual scoping. 16 | use crate::Status::{Poor, Rich}; 17 | // Automatically `use` each name inside `Work`. 18 | use crate::Work::*; 19 | 20 | // Equivalent to `Status::Poor`. 21 | let status = Poor; 22 | // Equivalent to `Work::Civilian`. 23 | let work = Civilian; 24 | 25 | match status { 26 | // Note the lack of scoping because of the explicit `use` above. 27 | Rich => println!("The rich have lots of money!"), 28 | Poor => println!("The poor have no money..."), 29 | } 30 | 31 | match work { 32 | // Note again the lack of scoping. 33 | Civilian => println!("Civilians work!"), 34 | Soldier => println!("Soldiers fight!"), 35 | } 36 | } -------------------------------------------------------------------------------- /fn_overload/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /fn_overload/add_trait/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /fn_overload/add_trait/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "add_trait" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /fn_overload/add_trait/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Add; 2 | 3 | #[derive(Debug,Clone,Copy, PartialEq, Eq)] 4 | struct Complex { 5 | real : i32, 6 | imag: i32, 7 | } 8 | 9 | impl Add for Complex { 10 | type Output = Complex; 11 | 12 | fn add(self, other: Complex) -> Complex { 13 | Complex { 14 | real: self.real + other.real, 15 | imag: self.imag + other.imag, 16 | } 17 | } 18 | } 19 | fn main() { 20 | let c1 = Complex{ real: 3, imag:7}; 21 | let c2 = Complex{ real: 4, imag:6}; 22 | println!("{:?}", c1 +c2); 23 | } 24 | -------------------------------------------------------------------------------- /fn_overload/macro_for_variadic/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /fn_overload/macro_for_variadic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "macro_for_variadic" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /fn_overload/macro_for_variadic/src/main.rs: -------------------------------------------------------------------------------- 1 | macro_rules! sum { 2 | ($($args:expr),*) => {{ 3 | let result = 0; 4 | $( 5 | let result = result + $args; 6 | )* 7 | result 8 | }} 9 | } 10 | 11 | macro_rules! print_all { 12 | ($($args:expr),*) => {{ 13 | $( 14 | println!("{}", $args); 15 | )* 16 | }} 17 | } 18 | 19 | fn main() { 20 | assert_eq!(sum!(1, 2, 3), 6); 21 | print_all!(1, 2, "Hello"); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /fn_overload/overload_1/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /fn_overload/overload_1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "overload_1" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /fn_overload/overload_1/src/main.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | enum IntOrFloat { 3 | Int(i32), 4 | Float(f32), 5 | } 6 | 7 | trait IntOrFloatTrait { 8 | fn to_int_or_float(&self) -> IntOrFloat; 9 | } 10 | 11 | impl IntOrFloatTrait for i32 { 12 | fn to_int_or_float(&self) -> IntOrFloat { 13 | IntOrFloat::Int(*self) 14 | } 15 | } 16 | 17 | impl IntOrFloatTrait for f32 { 18 | fn to_int_or_float(&self) -> IntOrFloat { 19 | IntOrFloat::Float(*self) 20 | } 21 | } 22 | 23 | fn attempt_4(x: T) { 24 | let v = x.to_int_or_float(); 25 | println!("{:?}", v); 26 | } 27 | 28 | fn main() { 29 | let i: i32 = 1; 30 | let f: f32 = 3.0; 31 | 32 | attempt_4(i); 33 | attempt_4(f); 34 | } -------------------------------------------------------------------------------- /fn_overload/overload_2/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /fn_overload/overload_2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "overload_2" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /fn_overload/overload_2/src/main.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | struct Foo { 3 | value:u64 4 | } 5 | 6 | trait HasUIntValue { 7 | fn as_u64(self) -> u64; 8 | } 9 | 10 | impl Foo { 11 | fn add(&mut self, value:T) { 12 | self.value += value.as_u64(); 13 | } 14 | } 15 | 16 | impl HasUIntValue for i64 { 17 | fn as_u64(self) -> u64 { 18 | return self as u64; 19 | } 20 | } 21 | 22 | impl HasUIntValue for f64 { 23 | fn as_u64(self) -> u64 { 24 | return self as u64; 25 | } 26 | } 27 | 28 | fn test_add_with_int() 29 | { 30 | let mut x = Foo { value: 10 }; 31 | x.add(10i64); 32 | assert!(x.value == 20); 33 | println!("{:?}", x); 34 | } 35 | 36 | fn test_add_with_float() 37 | { 38 | let mut x = Foo { value: 10 }; 39 | x.add(10.0f64); 40 | assert!(x.value == 20); 41 | println!("{:?}", x); 42 | } 43 | 44 | 45 | fn main() { 46 | test_add_with_int(); 47 | test_add_with_float(); 48 | } 49 | -------------------------------------------------------------------------------- /global_data_usage/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /global_data_usage/Readme.md: -------------------------------------------------------------------------------- 1 | # `A Guide to Global Data in Rust`-学习笔记 2 | 3 | - 为什么需要Global Data 4 | 5 | > (1) 应用程序的配置。 6 | > 7 | > (2) 例如全局变量,不需要一层层函数传参。 8 | > 9 | > (3) 数据库链接,连接池以及其他网络资源。 10 | > 11 | > (4) 日志。 12 | > 13 | > (5) 例如在`build.rs`中生成Rust代码,如:date/time/git commit rev. 14 | 15 | 16 | 17 | - 权衡取舍 18 | 19 | > (1) 编译时/运行时 load global data value. 20 | > 21 | > (2) 只读/可写。 22 | > 23 | > (3) 生命周期 : 要'static , 还是局部一点。 24 | > 25 | > (4) 创建到栈上, 还是堆上。 26 | > 27 | > (5) 并发读写否。 28 | 29 | 30 | 31 | - 多种方案比较 32 | 33 | > (1) rust let关键字,在`fn main()`中定义,然后通过函数参数传递。缺点:就是麻烦,需要层层函数传参。 34 | > 35 | > (2) `rust const`关键字,其生命周期为'static。 缺点:不可变, 而且限制为编译器常量和`const fn `. 36 | > 37 | > (3) `lazy_static`crate and `once_cell` crate, 缺点:数据对象必须满足Sync trait, 以及进程退出时,数据对象的析构函数不被执行,所以不要指望通过其析构函数清理资源。 38 | > 39 | > (4)`arc-swap`crate 解决并发读写Global Data的问题。 40 | > 41 | > (5) `std::include!`、`std::include_str!`、`std::include_bytes!`, 将一段Rust源码复制拼接到你的Rust源码文件中。 42 | > 43 | > 更多详情请看:`https://github.com/paulkernfeld/global-data-in-rust` , 我就不再传话了。 44 | 45 | 46 | 47 | - 后记 48 | 49 | 任何程序,任何编程语言, 对于`Global Data`的用法都是一个非常重要的关切点!一方面关乎语言哲学, 另一方面关乎实际工程代码的耦合度!所以恰当使用`Global Data`是极其重要的!代码过度耦合则难于管理/扩展/维护!所以非常有必要反复强调!这篇笔记只是抛砖引玉,希望您能阅读原文, 深入学习`Global Data`的使用指导。`https://github.com/paulkernfeld/global-data-in-rust` 50 | 51 | > 程序开发需要始终贯彻`依赖倒置原则`, 封装隔离变化, 抽象出稳定接口!即抽象接口,具化实现!而耦合代表依赖,依赖稳定的抽象层,如此代码耦合才能适度。 52 | 53 | 54 | 55 | - Author 56 | 57 | > 作者:心尘了 58 | > 59 | > email: [285779289@qq.com](mailto:285779289@qq.com) 60 | > 61 | > git:https://github.com/yujinliang/rust_learn 62 | > 63 | > `水平有限,笔记草乱,如有谬误,尽请指正!` 64 | 65 | 66 | 67 | - Reference 68 | 69 | > `https://github.com/paulkernfeld/global-data-in-rust` -------------------------------------------------------------------------------- /mathmatics/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mathmatics/endecode/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mathmatics/endecode/base58_bs58/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mathmatics/endecode/base58_bs58/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "base58_bs58" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | bs58 = "0.3.1" 11 | -------------------------------------------------------------------------------- /mathmatics/endecode/base58_bs58/src/main.rs: -------------------------------------------------------------------------------- 1 | //bs58 = "0.3.1" 2 | //https://docs.rs/bs58/0.3.1/bs58/ 3 | //https://github.com/mycorrhiza/bs58-rs 4 | use std::io::{self, Read,Write}; 5 | 6 | 7 | fn main() { 8 | //encode 9 | let mut input = Vec::::new(); 10 | io::stdin().read_to_end(&mut input).unwrap(); 11 | let enc = bs58::encode(input).into_string(); 12 | println!("{}", enc); 13 | 14 | //decode 15 | match bs58::decode(enc).into_vec() { 16 | Ok(vec) => io::stdout().write_all(&*vec).unwrap(), 17 | Err(err) => eprintln!("{}", err), 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/hash256_t/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/hash256_t/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hash256_t" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | sha2 = "0.8.1" 11 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/hash256_t/src/main.rs: -------------------------------------------------------------------------------- 1 | //https://github.com/RustCrypto 2 | //https://docs.rs/sha2/0.8.1/sha2/ 3 | //https://github.com/RustCrypto/hashes/tree/master/sha2 4 | use sha2::{Sha256, Sha512, Digest}; 5 | 6 | fn main() { 7 | 8 | // create a Sha256 object 9 | let mut hasher = Sha256::new(); 10 | // write input message 11 | hasher.input(b"hello world"); 12 | // read hash digest and consume hasher 13 | let result = hasher.result(); 14 | println!("Result: {:x}", result); 15 | 16 | // same for Sha512 17 | let mut hasher = Sha512::new(); 18 | hasher.input(b"hello world"); 19 | let result = hasher.result(); 20 | println!("Result: {:x}", result); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/ripemd160_t/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/ripemd160_t/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ripemd160_t" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | ripemd160 = "0.8.0" 11 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/ripemd160_t/src/main.rs: -------------------------------------------------------------------------------- 1 | //ripemd160 2 | //https://docs.rs/ripemd160/0.8.0/ripemd160/ 3 | //https://github.com/RustCrypto/hashes 4 | use ripemd160::{Ripemd160, Digest}; 5 | 6 | fn main() { 7 | // create a RIPEMD-160 hasher instance 8 | let mut hasher = Ripemd160::new(); 9 | // process input message 10 | hasher.input(b"Hello world!"); 11 | // acquire hash digest in the form of GenericArray, 12 | // which in this case is equivalent to [u8; 20] 13 | let result = hasher.result(); 14 | println!("{:x}", result); 15 | } 16 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/secp256k1_k256/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/secp256k1_k256/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "secp256k1_k256" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | k256 = "0.2.0" 11 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/secp256k1_k256/src/main.rs: -------------------------------------------------------------------------------- 1 | //secp256k1 2 | //https://crates.io/crates/k256 3 | //https://github.com/RustCrypto/elliptic-curves/tree/master/k256 4 | //https://github.com/RustCrypto/elliptic-curves 5 | 6 | 7 | 8 | fn main() { 9 | println!("Hello, world!"); 10 | } 11 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/secp256k1_secp256k1/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/secp256k1_secp256k1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "secp256k1_secp256k1" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | secp256k1 = "0.17.2" 11 | -------------------------------------------------------------------------------- /mathmatics/hash_learn/secp256k1_secp256k1/src/main.rs: -------------------------------------------------------------------------------- 1 | //secp256k1 2 | //https://docs.rs/secp256k1/0.17.2/secp256k1/ 3 | extern crate secp256k1; 4 | use self::secp256k1::{Secp256k1, Message, SecretKey, PublicKey}; 5 | 6 | fn main() { 7 | 8 | let secp = Secp256k1::new(); 9 | let secret_key = SecretKey::from_slice(&[0xcd; 32]).expect("32 bytes, within curve order"); 10 | let public_key = PublicKey::from_secret_key(&secp, &secret_key); 11 | let message = Message::from_slice(&[0xab; 32]).expect("32 bytes"); 12 | 13 | let sig = secp.sign(&message, &secret_key); 14 | assert!(secp.verify(&message, &sig, &public_key).is_ok()); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /mathmatics/ndarray_learn/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mathmatics/ndarray_learn/matrix/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mathmatics/ndarray_learn/matrix/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "matrix" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | ndarray = "0.13.1" 11 | #ndarray-linalg = "0.12.0" 12 | -------------------------------------------------------------------------------- /mathmatics/ndarray_learn/matrix/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate ndarray; 2 | //extern crate ndarray_linalg; 3 | 4 | use ndarray::*; 5 | //use ndarray_linalg::*; 6 | 7 | fn main() { 8 | 9 | //2d 3x3矩阵相加 10 | let a = arr2(&[[1, 2, 3], 11 | [4, 5, 6], 12 | [7,8,9]]); 13 | 14 | let b = arr2(&[[9, 8, 7], 15 | [6, 5, 4], 16 | [3,2,1]]); 17 | //element-wise operation 18 | let sum = &a + &b; 19 | 20 | println!("\nmatrix add: \n{}\n + \n{}\n = \n{}\n", a, b, sum); 21 | 22 | //2d 3x3 矩阵相减 23 | //element-wise operation 24 | let sub = &a - &b; 25 | println!("\nmatrix sub: \n{}\n + \n{}\n = \n{}\n", a, b, sub); 26 | 27 | //2d 3x3 matrix product 当a and b 是2d矩阵时, dot执行“矩阵积”,即结果是一个矩阵。 28 | let dot_result_matrix = &a.dot(&b); 29 | println!("\nmatrix product: \n{}",dot_result_matrix ); 30 | //element-wise operation 31 | let dot_result_matrix = &a * &b; 32 | println!("\nmatrix element-wise multiplication: \n{}",dot_result_matrix ); 33 | 34 | //1d 矩阵,即是一个向量,具有大小和方向 35 | //dot product 36 | let b_v: Array1 = arr1(&[1,2,3]); 37 | let a_v: Array1 = arr1(&[4,5,6]); 38 | //点积(内积,数量积) 39 | let dot_product = a_v.dot(&b_v); 40 | println!("\nmatrix dot product: \n{}",dot_product ); 41 | //叉积(外积,向量积) 42 | //let outer_product = a_v.outer(&b_v); 43 | //println!("\nmatrix outer product: \n{}",outer_product ); 44 | 45 | //element-wise operation 46 | let product = &a_v * &b_v; 47 | println!("\nmatrix element-wise multiplication: \n{}",product ); 48 | //element-wise operation 49 | let div = &a_v / &b_v; 50 | println!("\nmatrix element-wise div: \n{}",div ); 51 | } 52 | -------------------------------------------------------------------------------- /mio/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mio/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yujinliang/rust_learn/e641dd6925cf0ba4cd8fd6edc8dcb20e4b18e956/mio/1.png -------------------------------------------------------------------------------- /mio/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yujinliang/rust_learn/e641dd6925cf0ba4cd8fd6edc8dcb20e4b18e956/mio/2.png -------------------------------------------------------------------------------- /mio/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yujinliang/rust_learn/e641dd6925cf0ba4cd8fd6edc8dcb20e4b18e956/mio/3.png -------------------------------------------------------------------------------- /mio/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yujinliang/rust_learn/e641dd6925cf0ba4cd8fd6edc8dcb20e4b18e956/mio/4.png -------------------------------------------------------------------------------- /mio/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yujinliang/rust_learn/e641dd6925cf0ba4cd8fd6edc8dcb20e4b18e956/mio/5.png -------------------------------------------------------------------------------- /mio/mio_1/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mio/mio_1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mio_1" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | mio = "0.6.21" -------------------------------------------------------------------------------- /mio/mio_1/src/main.rs: -------------------------------------------------------------------------------- 1 | use mio::*; 2 | use mio::net::{TcpListener, TcpStream}; 3 | 4 | fn main() { 5 | 6 | 7 | // Setup some tokens to allow us to identify which event is 8 | // for which socket. 9 | const SERVER: Token = Token(0); 10 | const CLIENT: Token = Token(1); 11 | 12 | let addr = "127.0.0.1:13265".parse().unwrap(); 13 | 14 | // Setup the server socket 15 | let server = TcpListener::bind(&addr).unwrap(); 16 | 17 | // Create a poll instance 18 | let poll = Poll::new().unwrap(); 19 | 20 | // Start listening for incoming connections 21 | poll.register(&server, SERVER, Ready::readable(), 22 | PollOpt::edge()).unwrap(); 23 | 24 | // Setup the client socket 25 | let sock = TcpStream::connect(&addr).unwrap(); 26 | 27 | // Register the socket 28 | poll.register(&sock, CLIENT, Ready::readable(), 29 | PollOpt::edge()).unwrap(); 30 | 31 | // Create storage for events 32 | let mut events = Events::with_capacity(1024); 33 | 34 | loop { 35 | poll.poll(&mut events, None).unwrap(); 36 | 37 | for event in events.iter() { 38 | match event.token() { 39 | SERVER => { 40 | // Accept and drop the socket immediately, this will close 41 | // the socket and notify the client of the EOF. 42 | let _ = server.accept(); 43 | println!("server accepted"); 44 | } 45 | CLIENT => { 46 | // The server just shuts down the socket, let's just exit 47 | // from our event loop. 48 | println!("client done"); 49 | return; 50 | } 51 | _ => unreachable!(), 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /mio/mio_2/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mio/mio_2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mio_2" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | mio = "0.6.21" 11 | -------------------------------------------------------------------------------- /mio/mio_2/src/main.rs: -------------------------------------------------------------------------------- 1 | use mio::net::UdpSocket; 2 | use mio::{Events, Ready, Poll, PollOpt, Token}; 3 | use std::time::Duration; 4 | 5 | fn main() -> Result<(), Box> { 6 | 7 | 8 | 9 | const SENDER: Token = Token(0); 10 | const ECHOER: Token = Token(1); 11 | 12 | // This operation will fail if the address is in use, so we select different ports for each 13 | // socket. 14 | let sender_socket = UdpSocket::bind(&"127.0.0.1:0".parse()?)?; 15 | let echoer_socket = UdpSocket::bind(&"127.0.0.1:0".parse()?)?; 16 | 17 | // If we do not use connect here, SENDER and ECHOER would need to call send_to and recv_from 18 | // respectively. 19 | sender_socket.connect(echoer_socket.local_addr().unwrap())?; 20 | 21 | // We need a Poll to check if SENDER is ready to be written into, and if ECHOER is ready to be 22 | // read from. 23 | let poll = Poll::new()?; 24 | 25 | // We register our sockets here so that we can check if they are ready to be written/read. 26 | poll.register(&sender_socket, SENDER, Ready::writable(), PollOpt::edge())?; 27 | poll.register(&echoer_socket, ECHOER, Ready::readable(), PollOpt::edge())?; 28 | 29 | let msg_to_send = [9; 9]; 30 | let mut buffer = [0; 9]; 31 | 32 | let mut events = Events::with_capacity(128); 33 | loop { 34 | poll.poll(&mut events, Some(Duration::from_millis(100)))?; 35 | for event in events.iter() { 36 | match event.token() { 37 | // Our SENDER is ready to be written into. 38 | SENDER => { 39 | let bytes_sent = sender_socket.send(&msg_to_send)?; 40 | assert_eq!(bytes_sent, 9); 41 | println!("sent {:?} -> {:?} bytes", msg_to_send, bytes_sent); 42 | }, 43 | // Our ECHOER is ready to be read from. 44 | ECHOER => { 45 | let num_recv = echoer_socket.recv(&mut buffer)?; 46 | println!("echo {:?} -> {:?}", buffer, num_recv); 47 | buffer = [0; 9]; 48 | } 49 | _ => unreachable!() 50 | } 51 | } 52 | } //loop end. 53 | } 54 | -------------------------------------------------------------------------------- /mio/mio_oneshot_test/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mio/mio_oneshot_test/mio_server/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mio/mio_oneshot_test/mio_server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mio_3" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | mio = "0.6" 11 | -------------------------------------------------------------------------------- /mio/mio_oneshot_test/tcp_client_block/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mio/mio_oneshot_test/tcp_client_block/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "syn_tcp_client" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /mio/mio_oneshot_test/tcp_client_block/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::net::TcpStream; 2 | use std::io::{ Write, Read}; 3 | 4 | fn main() -> std::io::Result<()> { 5 | let mut stream = TcpStream::connect("127.0.0.1:8080")?; 6 | let mut buf = [0u8; 8]; 7 | 8 | loop { 9 | println!("prepare send" ); 10 | stream.write(&[1])?; 11 | //----- 12 | stream.read(&mut buf)?; 13 | println!("server back {:?}" , String::from_utf8_lossy(&buf)); 14 | } 15 | 16 | } // the stream is closed here 17 | -------------------------------------------------------------------------------- /mio/mio_oneshot_test/tcp_client_noneblock/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /mio/mio_oneshot_test/tcp_client_noneblock/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test_code" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | mio = "0.6.21" 11 | -------------------------------------------------------------------------------- /mio/mio_oneshot_test/tcp_client_noneblock/src/main.rs: -------------------------------------------------------------------------------- 1 | use mio::{Events, Ready, Poll, PollOpt, Token}; 2 | use mio::net::TcpStream; 3 | use std::time::Duration; 4 | use std::io::{Read, Write}; 5 | 6 | fn main() -> Result<(), Box> { 7 | 8 | let mut buffer = [0 as u8; 1024]; 9 | let mut stream = TcpStream::connect(&"127.0.0.1:8080".parse()?)?; 10 | 11 | let poll = Poll::new()?; 12 | let mut events = Events::with_capacity(128); 13 | 14 | // Register the socket with `Poll` 15 | poll.register(&stream, Token(0), Ready::writable() | Ready::readable(), 16 | PollOpt::edge())?; 17 | 18 | loop{ 19 | poll.poll(&mut events, Some(Duration::from_millis(100)))?; 20 | for event in &events { 21 | match event.token() { 22 | Token(0) => { 23 | 24 | if event.readiness().is_readable() { 25 | let read = stream.read(&mut buffer); 26 | match read { 27 | Ok(0) => { 28 | println!("server socket closed", ); 29 | break 30 | }, 31 | Ok(_n) => { 32 | println!("{}",std::str::from_utf8(&buffer)?); 33 | }, 34 | Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => 35 | break, 36 | Err(_) => break 37 | } 38 | 39 | } 40 | 41 | if event.readiness().is_writable() { 42 | stream.write_all("i am client".as_bytes()).unwrap(); 43 | 44 | } 45 | }, 46 | 47 | _ => unreachable!() 48 | } //match end. 49 | } //for end. 50 | 51 | }//loop end. 52 | 53 | } 54 | -------------------------------------------------------------------------------- /mmqrcode1654076680683.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yujinliang/rust_learn/e641dd6925cf0ba4cd8fd6edc8dcb20e4b18e956/mmqrcode1654076680683.png -------------------------------------------------------------------------------- /mut_diveinto/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /mut_diveinto/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 了解相关属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug", 11 | "program": "${workspaceFolder}/target/debug/mut_diveinto", 12 | "args": [], 13 | "cwd": "${workspaceFolder}" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /mut_diveinto/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mut_diveinto" 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 | -------------------------------------------------------------------------------- /mut_diveinto/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | /* 4 | * 由于个人水平和精力有限,难免有谬误,望请大家海涵指正。 5 | *不要觉得知识点浅显就小看它,有些东西必须深挖搞懂,如此方可写出清晰严谨的代码! 6 | * 本文就是要深挖不同位置上mut的明确含义。 7 | */ 8 | //Case1: 9 | println!("Case1:--------------------------------------"); 10 | //owner是所有者,变量名owner左边的mut表示:(1)owner变量本身可变,即可以再次被赋予其他值。 (2)owner所拥有的String对象(内存区域)本身是可变的,即可以被修改。 11 | let mut owner = String::from("hello"); 12 | 13 | //看, sowner所拥有的String对象可以被修改吧,比如加入其他字符串。 14 | owner.push_str("world"); 15 | println!("{}",owner); 16 | 17 | //看,owner 变量被重新赋值,现在拥有一个新的String对象,这都是owner变量左侧的mut赋予它的权力。 18 | owner = String::from("a other string object"); 19 | println!("{}",owner); 20 | 21 | //一个对象(内存区域)是否可变,即可被修改, 完全由其“所有者”决定! 22 | let mut xa: [i32;5] = [1,2,3,4,5]; 23 | let ya: [i32;5] = [6,7,8,9,10]; 24 | 25 | xa[0] = 11; 26 | println!("{:?}", xa); 27 | 28 | //ya[0] = 12; 报错:因为ya不可变。 29 | 30 | //注意看下面: ya将自己所拥有的数组对象的所有权转移给了xa, 31 | xa = ya; 32 | 33 | //注意只有所有者才能决定其所拥有的对象(内存区域)是否可变,即是否可修改!即变量名左侧的mut是关键。 34 | xa[0] = 20; 35 | println!("{:?}", xa); 36 | 37 | //Case2: 38 | println!("Case2:--------------------------------------"); 39 | //v是所有者,它和Case1一样,具备同样权力。 40 | let mut v:[i32;3] = [1,2,3]; 41 | { 42 | 43 | let mut borrower:&mut [i32;3] = &mut v; //v 左侧的mut是不是感觉多余呢?因为borrower的类型定义已经很清楚了,何必画蛇添足? 44 | //其实不然,对于稍微大一些的项目而言, 变量和函数的定义未必就在你的眼前, 所以赋值和传参时的冗余信息就非常有必要了,令你不必跳来跳去就可以清楚参数类型和意图。 45 | 46 | //注意:此时的borrower只是一个引用(相当于c的一个数组指针而已),而非slice(胖指针), 47 | //只是在函数调用传参数时,rust帮我们自动转换成slice而已。 48 | mut_slice(borrower); 49 | println!("{:?}", borrower); 50 | 51 | //borrower右侧的mut说明其借来(指向)的对象本身是可变的,即允许修改。 52 | borrower[0] = 11; 53 | println!("{:?}", borrower); 54 | 55 | //borrower左侧的mut说明其可以被再次赋予其他值, 即可变。 56 | let mut vv: [i32;3] = [4,5,6]; 57 | borrower = &mut vv; 58 | println!("{:?}", borrower); 59 | } 60 | 61 | mut_slice(&mut v); //v左侧的mut明确表达这是可变参数,而不必查阅函数定义。 62 | 63 | 64 | } 65 | 66 | //接受一个slice(胖指针)作为参数 67 | fn mut_slice(a: &mut [i32]){ 68 | a[2]=5; 69 | } 70 | 71 | /* 72 | * 补充知识点: 73 | * 1. 对数组的借用可以产生一个数组切片, 比如上面的: &mut v 74 | * 2. 数组切片slice只是对数组的借用,没有所有权,切记。 75 | * 3. 数组切片slice是”胖指针“,包括: 数组头元素指针和slice长度。 76 | * 4. 数组是编译期大小确定的类型. 77 | * 5. 把数组作为参数传给函数,这个数组不会退化为一个指针,而是会完整复制这个数组,所以函数体内对实参数组的修改,不会影响到外边的数组!切记这和c/c++不同。 78 | * 6. 数组索引类型: usize 79 | * 7. 现在rust编译器规定:对于局部变量/函数参数和返回值等处的类型大小必须为编译期已知量,所以对于”动态大小类型“,即DST , 一般不允许直接创建, 必须通过指针间接创建和操作,比如:&, Box等。 80 | * 8. 元素类型 和数组长度都相同,才是相同类型的数组。 81 | * 9. rust规定严格, 不同类型通常禁止隐士自动转换, 必须手动显示转换。 82 | * 10. 调试时,想知道某个变量,参数等的实际类型, 可以令rust编译器报错给出,比如类型不匹配时, rust编译器会告诉你期望的类型和实际的类型。 83 | */ -------------------------------------------------------------------------------- /orphan_rule/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /orphan_rule/base/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /orphan_rule/base/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "base" 3 | version = "0.1.0" 4 | authors = ["htyu"] 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 | -------------------------------------------------------------------------------- /orphan_rule/base/src/main.rs: -------------------------------------------------------------------------------- 1 | //base/src/main.rs 2 | //or base/src/lib.rs 3 | //那么base目录就是一个完整独立的crate,里面包括很多子目录。 4 | //每一个crate下,比如base下,都会有一个Cargo.toml用于编译这个crate. 5 | 6 | 7 | pub trait A { 8 | fn summarize(&self) -> String; 9 | } 10 | pub struct B { 11 | pub headline: String, 12 | pub location: String, 13 | pub author: String, 14 | pub content: String, 15 | } 16 | 17 | //注意impl需要满足rust的orphan rule(孤儿规则), 即A或者B两者至少有一个必须和impl块定义在同一个本地(当前)crate中,否则禁止impl块. 18 | //很明显,当前的A和B都和impl块定义在同一个crate中, 所以合法,也就是说A和B里至少有一个必须是自己亲生的孩子,否则无权调教。 19 | //举个反例, 比如:trait Display和Vec都是rust标准库crate中定义好的,所以你的impl块就违反孤儿规则。 20 | //总的原则 : 自己的孩子自己管,别人的孩子你管不着。 21 | impl A for B { 22 | fn summarize(&self) -> String { 23 | format!("{}, by {} ({})", self.headline, self.author, self.location) 24 | } 25 | } 26 | 27 | 28 | fn main() { 29 | let b = B{ headline: "headline".to_string(), location: "location".to_string(), author: "author".to_string(), content: "content".to_string()}; 30 | println!("# {}",b.summarize()); 31 | } 32 | -------------------------------------------------------------------------------- /orphan_rule/generic/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /orphan_rule/generic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "generic" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /orphan_rule/generic/src/main.rs: -------------------------------------------------------------------------------- 1 | /*https://blog.rust-lang.org/2020/01/30/Rust-1.41.0.html 2 | *rust orphan rule孤儿规则对于泛型做出了适当的放松限制,形如: 3 | *impl ForeignTrait for ForeignType { 4 | * // ... 5 | * } 6 | *这样的形式在rust1.41之前是非法的,不满足孤儿规则,虽然ForeignTrait中, 7 | *以一个本地crate自定义LocalType实例化后,就相当于变成了一个本地localTrait了, 8 | *但是旧版本的孤儿规则不允许,分明就是误伤,不过rust1.41之后就允许了。 9 | *这样极大的增强了泛型表达和扩展能力! 10 | *https://doc.rust-lang.org/std/convert/trait.Into.html#implementing-into-for-conversions-to-external-types-in-old-versions-of-rust 11 | *https://blog.rust-lang.org/2020/01/30/Rust-1.41.0.html 12 | */ 13 | 14 | struct Wrapper(Vec); 15 | 16 | 17 | impl From> for Vec { 18 | 19 | fn from(w: Wrapper) -> Vec { 20 | w.0 21 | } 22 | } 23 | 24 | 25 | fn main() { 26 | println!("Hello, world!"); 27 | } 28 | -------------------------------------------------------------------------------- /orphan_rule/wrapper/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /orphan_rule/wrapper/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wrapper" 3 | version = "0.1.0" 4 | authors = ["htyu"] 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 | -------------------------------------------------------------------------------- /orphan_rule/wrapper/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | //有的时候我们想对别人生的孩子稍加改造,但是rust的orphan rule孤儿规则不允许。 4 | //所以我们必须自己生一个, 虽然他只是个wrapper包装器,可毕竟是自己亲生的,满足孤儿规则。 5 | //比如下面的trait Display和Vec都是rust标准库crate中预定义的, 也就是说别人的孩子我们动不得。 6 | //现在我们自己生一个wrapper类用于包装一下Vec , 然后再应用impl块就合法了。 7 | //也许有人会质疑,我原本打算给Vec添加一个借口(新功能)而已,现在新接口实现了,但是Vec 8 | //原先的接口就不能直接调用了,难道让Wrapper再重新实现吗? 9 | //解决这个问题用不着这么笨的方法, 学学rust里各种智能指针(胖指针)的实现方法就好, 10 | //只要你的自定义类型impl了trait Deref就搞定了, rust帮你自动解引用。 11 | //详情请看:https://doc.rust-lang.org/book/ch15-02-deref.html 12 | 13 | struct Wrapper(Vec); 14 | 15 | impl fmt::Display for Wrapper { 16 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 17 | write!(f, "[{}]", self.0.join(", ")) 18 | } 19 | } 20 | 21 | fn main() { 22 | let w = Wrapper(vec![String::from("hello"), String::from("world")]); 23 | println!("w = {}", w); 24 | } 25 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["ctrlc_1", "ctrlc_channel", "signal_hook", "signal_hook2", "signal_hook_tokio", "signal_hook_cross_beam_channel"] 3 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/ctrlc_1/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/ctrlc_1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ctrlc_1" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | ctrlc = "3.1.3" 11 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/ctrlc_1/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate ctrlc; 2 | use std::sync::atomic::{ AtomicBool, Ordering}; 3 | use std::sync::Arc; 4 | 5 | fn main() { 6 | 7 | let running = Arc::new(AtomicBool::new(true)); 8 | let r = running.clone(); 9 | 10 | ctrlc::set_handler(move ||{ 11 | r.store(false, Ordering::SeqCst); 12 | }).expect("Error setting Ctrl-C handler."); 13 | 14 | println!("Waiting for Ctrl-C..."); 15 | while running.load(Ordering::SeqCst) { 16 | 17 | println!("."); 18 | } 19 | println!("Got the Ctrl-C signal, now Exitting..."); 20 | } 21 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/ctrlc_channel/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/ctrlc_channel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ctrlc_channel" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | ctrlc = "3.1.3" 11 | crossbeam-channel = "0.3" 12 | 13 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/ctrlc_channel/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | use std::error::Error; 3 | use crossbeam_channel::{bounded, tick, Receiver, select}; 4 | 5 | fn ctrl_channel() ->Result, ctrlc::Error> { 6 | 7 | let (sender, receiver) = bounded(100); 8 | ctrlc::set_handler(move || { 9 | 10 | let _ = sender.send(()); 11 | 12 | })?; 13 | 14 | Ok(receiver) 15 | } 16 | fn main() -> Result<(), Box> { 17 | 18 | let ctrl_c_events = ctrl_channel()?; 19 | let ticks = tick(Duration::from_secs(1)); 20 | 21 | loop { 22 | 23 | select!{ 24 | 25 | recv(ticks) -> _ => { 26 | println!("working!"); 27 | } 28 | 29 | recv(ctrl_c_events)-> _ => { 30 | println!("Got the CtrlC Signal"); 31 | println!("goodbye!"); 32 | break; 33 | } 34 | } 35 | } 36 | 37 | Ok(()) 38 | } 39 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "arc-swap" 5 | version = "0.4.3" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | 8 | [[package]] 9 | name = "libc" 10 | version = "0.2.65" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | 13 | [[package]] 14 | name = "signal-hook" 15 | version = "0.1.11" 16 | source = "registry+https://github.com/rust-lang/crates.io-index" 17 | dependencies = [ 18 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 19 | "signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 20 | ] 21 | 22 | [[package]] 23 | name = "signal-hook-registry" 24 | version = "1.1.1" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | dependencies = [ 27 | "arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 28 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 29 | ] 30 | 31 | [[package]] 32 | name = "signal_hook" 33 | version = "0.1.0" 34 | dependencies = [ 35 | "signal-hook 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", 36 | ] 37 | 38 | [metadata] 39 | "checksum arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a1eca3195b729bbd64e292ef2f5fff6b1c28504fed762ce2b1013dde4d8e92" 40 | "checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" 41 | "checksum signal-hook 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cb543aecec4ba8b867f41284729ddfdb7e8fcd70ec3d7d37fca3007a4b53675f" 42 | "checksum signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1797d48f38f91643908bb14e35e79928f9f4b3cefb2420a564dde0991b4358dc" 43 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "signal_hook" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | signal-hook = "0.1.11" 11 | 12 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::{error::Error, thread}; 2 | use signal_hook::{iterator::Signals, SIGINT}; 3 | 4 | 5 | fn main() -> Result<(), Box< dyn Error> > { 6 | 7 | let signals = Signals::new(&[SIGINT])?; 8 | 9 | thread::spawn(move||{ 10 | 11 | for sig in signals.forever() { 12 | 13 | println!("Received signal {:?}", sig); 14 | break; 15 | } 16 | }).join().unwrap(); 17 | 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook2/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook2/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "arc-swap" 5 | version = "0.4.3" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | 8 | [[package]] 9 | name = "libc" 10 | version = "0.2.65" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | 13 | [[package]] 14 | name = "signal-hook" 15 | version = "0.1.11" 16 | source = "registry+https://github.com/rust-lang/crates.io-index" 17 | dependencies = [ 18 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 19 | "signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 20 | ] 21 | 22 | [[package]] 23 | name = "signal-hook-registry" 24 | version = "1.1.1" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | dependencies = [ 27 | "arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 28 | "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 29 | ] 30 | 31 | [[package]] 32 | name = "signal_hook2" 33 | version = "0.1.0" 34 | dependencies = [ 35 | "signal-hook 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", 36 | ] 37 | 38 | [metadata] 39 | "checksum arc-swap 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a1eca3195b729bbd64e292ef2f5fff6b1c28504fed762ce2b1013dde4d8e92" 40 | "checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" 41 | "checksum signal-hook 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cb543aecec4ba8b867f41284729ddfdb7e8fcd70ec3d7d37fca3007a4b53675f" 42 | "checksum signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1797d48f38f91643908bb14e35e79928f9f4b3cefb2420a564dde0991b4358dc" 43 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "signal_hook2" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | signal-hook = "0.1.11" 11 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook2/src/main.rs: -------------------------------------------------------------------------------- 1 | use signal_hook::iterator::Signals; 2 | use std::{thread, error::Error}; 3 | 4 | fn main() -> Result<(), Box> { 5 | 6 | let signals = Signals::new(&[signal_hook::SIGINT, signal_hook::SIGUSR1])?; 7 | 8 | thread::spawn(move || { 9 | 10 | for sig in &signals { 11 | 12 | match sig { 13 | 14 | signal_hook::SIGINT => { 15 | 16 | println!("SIGINT ->: {:?}", sig); 17 | break; 18 | 19 | }, 20 | signal_hook::SIGUSR1 => { 21 | println!("SIGUSR1 -> : {:?}", sig); 22 | break; 23 | 24 | }, 25 | _ => unreachable!(), 26 | } 27 | } 28 | }).join().unwrap(); 29 | 30 | Ok(()) 31 | } 32 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook_cross_beam_channel/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook_cross_beam_channel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "signal_hook_cross_beam_channel" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | crossbeam-channel = "0.3.9" 11 | signal-hook = "0.1.11" 12 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook_cross_beam_channel/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate crossbeam_channel as channel; 2 | extern crate signal_hook; 3 | 4 | use std::{thread,os::raw::c_int, error::Error}; 5 | 6 | fn notify(signals: &[c_int]) -> Result, Box > { 7 | 8 | let (s, r) = channel::bounded(100); 9 | let signals = signal_hook::iterator::Signals::new(signals)?; 10 | thread::spawn(move || { 11 | 12 | for signal in signals.forever() { 13 | s.send(signal).unwrap(); 14 | } 15 | }); 16 | Ok(r) 17 | } 18 | 19 | fn main() { 20 | 21 | let r = notify(&[signal_hook::SIGINT]).unwrap(); 22 | 23 | println!("catch the signal : {:?}", r.recv().unwrap()); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook_tokio/.Cargo.toml.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yujinliang/rust_learn/e641dd6925cf0ba4cd8fd6edc8dcb20e4b18e956/os_signal_handling_in_rust/signal_hook_tokio/.Cargo.toml.swp -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook_tokio/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook_tokio/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "signal_hook_tokio" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | signal-hook = {version = "0.1.11", features=["tokio-support"]} 11 | tokio = "0.1.22" 12 | libc = "0.2.65" 13 | -------------------------------------------------------------------------------- /os_signal_handling_in_rust/signal_hook_tokio/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::Error; 2 | use signal_hook::iterator::Signals; 3 | use tokio::prelude::*; 4 | 5 | 6 | fn main() -> Result<(), Error> { 7 | 8 | let wait_signal = Signals::new(&[signal_hook::SIGUSR1])? 9 | .into_async()? 10 | .into_future() 11 | .map(|sig|{println!("game over: {}", sig.0.unwrap());}) 12 | .map_err(|e| panic!("{}", e.0)); 13 | 14 | unsafe{ libc::kill(libc::getpid(), signal_hook::SIGUSR1);}; 15 | tokio::run(wait_signal); 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /others/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /others/Readme.md: -------------------------------------------------------------------------------- 1 | # 未归类知识杂记 2 | 3 | > Rust 短字符串性能分析:`https://fasterthanli.me/articles/small-strings-in-rust` 4 | 5 | -------------------------------------------------------------------------------- /panic_in_rust/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /panic_in_rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["panic-1", "panic-catch-recover", "panic-handle", "panic-rethrow", "panic-set-hook", "panic-take-hook", "panic-write-to-log", "panic-unwind-safe-test","mutex_poisoned", "panic-assert-unwind-safe"] 3 | -------------------------------------------------------------------------------- /panic_in_rust/mutex_poisoned/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /panic_in_rust/mutex_poisoned/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mutex_poisoned" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /panic_in_rust/mutex_poisoned/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::sync::{Arc, Mutex}; 2 | use std::thread; 3 | 4 | fn main() { 5 | 6 | let lock = Arc::new(Mutex::new(0_u32)); 7 | let lock2 = lock.clone(); 8 | 9 | let _ = thread::spawn(move || -> () { 10 | // This thread will acquire the mutex first, unwrapping the result of 11 | // `lock` because the lock has not been poisoned. 12 | let _guard = lock2.lock().unwrap(); 13 | 14 | // This panic while holding the lock (`_guard` is in scope) will poison 15 | // the mutex. 16 | panic!(); 17 | }).join(); 18 | 19 | // The lock is poisoned by this point, but the returned result can be 20 | // pattern matched on to return the underlying guard on both branches. 21 | let mut guard = match lock.lock() { 22 | Ok(guard) => guard, 23 | Err(poisoned) => poisoned.into_inner(), 24 | }; 25 | 26 | println!("{}", *guard ); 27 | *guard += 1; 28 | println!("{}", *guard ); 29 | 30 | assert_eq!(lock.is_poisoned(), true); 31 | println!("poisoned: {}",lock.is_poisoned() ); 32 | } 33 | -------------------------------------------------------------------------------- /panic_in_rust/panic-1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "panic-1" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /panic_in_rust/panic-1/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | use std::panic; 3 | 4 | fn main() { 5 | 6 | let r = thread::spawn(move || { 7 | 8 | panic!("panic occured in child thread."); 9 | //println!("child is Ok", ); //unreachable statement 10 | 11 | }).join(); 12 | 13 | println!("{:?}",r ); 14 | println!("althought some panic occurred in child, but the panic cannot sent back to and break the main thread."); 15 | 16 | //------ 17 | println!("----------------------------------------------------------------" ); 18 | let r = thread::spawn(move || { 19 | 20 | let r = thread::spawn(move || { 21 | 22 | panic!("thead2 panic!"); 23 | //println!("thread2 is Ok", ); //unreachable statement 24 | 25 | }).join(); 26 | println!("the thread1 is ok" ); 27 | return r; 28 | 29 | }).join(); 30 | 31 | println!("{:?}",r ); 32 | println!("main thread is ok"); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /panic_in_rust/panic-assert-unwind-safe/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /panic_in_rust/panic-assert-unwind-safe/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "panic-assert-unwind-safe" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /panic_in_rust/panic-assert-unwind-safe/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::panic::{self, AssertUnwindSafe}; 2 | 3 | fn main() { 4 | 5 | 6 | let mut variable = 4; 7 | println!("{}",variable ); 8 | // This code will not compile because the closure captures `&mut variable` 9 | // which is not considered unwind safe by default. 10 | 11 | // panic::catch_unwind(|| { 12 | // variable += 3; 13 | // }); 14 | 15 | // This, however, will compile due to the `AssertUnwindSafe` wrapper 16 | let result = panic::catch_unwind(AssertUnwindSafe(|| { 17 | variable += 3; 18 | })); 19 | 20 | println!("{}",variable ); 21 | println!("{:?}",result ); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /panic_in_rust/panic-catch-recover/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "panic-catch-recover" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /panic_in_rust/panic-catch-recover/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::panic; 2 | 3 | fn main() { 4 | 5 | 6 | let result = panic::catch_unwind(|| { 7 | println!("no panics , all is ok!"); 8 | }); 9 | debug_assert!(result.is_ok()); 10 | 11 | let result = panic::catch_unwind(|| { 12 | panic!("oh panic occured !"); 13 | }); 14 | debug_assert!(result.is_err()); 15 | 16 | println!("main thread is ok" ); 17 | } 18 | -------------------------------------------------------------------------------- /panic_in_rust/panic-handle/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "panic-handle" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /panic_in_rust/panic-handle/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | use std::panic; 3 | use std::time; 4 | use std::any::Any; 5 | 6 | fn main() { 7 | 8 | println!("Entering main!"); 9 | 10 | let h = thread::spawn(|| { 11 | 12 | let dur_millis = time::Duration::from_millis(500); 13 | thread::sleep(dur_millis); 14 | panic!("boom"); 15 | 16 | }); 17 | 18 | let r = h.join(); 19 | handle(r); 20 | 21 | let r = panic::catch_unwind(|| { 22 | 23 | let dur_millis = time::Duration::from_millis(500); 24 | thread::sleep(dur_millis); 25 | panic!(String::from("boom again!")); 26 | 27 | }); 28 | 29 | handle(r); 30 | 31 | println!("Exiting main!"); 32 | 33 | } 34 | 35 | //both of the panic::catch_unwind and thread::spawn is to return Err(Any) 36 | //fn handle(r: thread::Result<()>) { 37 | fn handle( r: Result>) { 38 | 39 | println!("{:?}", r ); 40 | match r { 41 | 42 | Ok(r) => println!("All is well! {:?}", r), 43 | Err(e) => { 44 | if let Some(e) = e.downcast_ref::<&'static str>() { 45 | println!("Got an error: {}", e); 46 | } 47 | else if let Some(e) = e.downcast_ref::() { 48 | 49 | println!("Got an error: {}", e); 50 | } 51 | else { 52 | println!("Got an unknown error: {:?}", e); 53 | } 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /panic_in_rust/panic-rethrow/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "panic-rethrow" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /panic_in_rust/panic-rethrow/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::panic; 2 | 3 | fn main() { 4 | 5 | let result = panic::catch_unwind(|| { 6 | panic!("oh no!, panic occured!"); 7 | }); 8 | 9 | println!("I am ok 1st", ); 10 | 11 | if let Err(err) = result { 12 | println!("I am ok 2nd", ); 13 | panic::resume_unwind(err); 14 | //println!("unreachable here", ); 15 | } 16 | 17 | println!("unreachable here", ); 18 | } 19 | -------------------------------------------------------------------------------- /panic_in_rust/panic-set-hook/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "panic-hook" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /panic_in_rust/panic-set-hook/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::panic; 2 | 3 | fn main() { 4 | 5 | panic::set_hook(Box::new(|info| { 6 | println!("Custom panic hook: {:?}", info); 7 | })); 8 | 9 | panic!("Normal panic"); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /panic_in_rust/panic-take-hook/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "panic-tabke-hook" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /panic_in_rust/panic-take-hook/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::panic; 2 | 3 | fn main() { 4 | 5 | panic::set_hook(Box::new(|_| { 6 | println!("Custom panic hook"); 7 | })); 8 | 9 | let _ = panic::take_hook(); 10 | 11 | panic!("Normal panic"); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /panic_in_rust/panic-unwind-safe-test/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /panic_in_rust/panic-unwind-safe-test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "panic-unwind-safe-test" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /panic_in_rust/panic-unwind-safe-test/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::sync::Mutex; 3 | //do ask rust compiler what types are unwindsafe. 4 | fn implements() {} 5 | 6 | fn main() { 7 | 8 | //可变不共享,共享不可变! 9 | //包括内部可变性! 10 | //对于可变且共享的元素,可否证明安全? 11 | 12 | //below all is UnwindSafe. 13 | implements::>(); 14 | implements::<&Option>(); 15 | implements::<&Mutex>(); 16 | 17 | //below all is not UnwindSafe. 18 | //implements::<&mut i32>(); 19 | //implements::<&RefCell>(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /panic_in_rust/panic-write-to-log/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /panic_in_rust/panic-write-to-log/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "panic-write-to-log" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /panic_in_rust/panic-write-to-log/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::panic; 2 | use std::ops::Deref; 3 | 4 | fn main() { 5 | 6 | panic::set_hook(Box::new(|panic_info| { 7 | 8 | let (filename, line) = panic_info.location() 9 | .map(|loc| (loc.file(), loc.line())) 10 | .unwrap_or(("", 0)); 11 | 12 | let cause = panic_info.payload() 13 | .downcast_ref::() 14 | .map(String::deref); 15 | 16 | let cause = cause.unwrap_or_else(|| { 17 | 18 | panic_info.payload() 19 | .downcast_ref::<&str>().map(|s| *s) 20 | .unwrap_or("") 21 | 22 | }); 23 | 24 | println!("Test A panic occurred at {}:{}: {}", filename, line, cause); //write to log here. 25 | 26 | })); 27 | 28 | panic!("oh panic!"); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /peer_socket_dead_check/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /peer_socket_dead_check/libc_socket_server/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /peer_socket_dead_check/libc_socket_server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "libc_socket_server" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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.66" 11 | rayon = "1.3.0" 12 | -------------------------------------------------------------------------------- /peer_socket_dead_check/tcp_client_block/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /peer_socket_dead_check/tcp_client_block/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "syn_tcp_client" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /peer_socket_dead_check/tcp_client_block/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::net::{TcpStream, Shutdown}; 2 | use std::io::{ Write, Read, Result, ErrorKind, Error}; 3 | 4 | fn main() -> std::io::Result<()> { 5 | 6 | let mut stream = TcpStream::connect("127.0.0.1:8080")?; 7 | let mut buf = [0u8; 8]; 8 | 9 | loop { 10 | //stream.write(&[1])?; 11 | //hit BrokenPipe error , then close the peer socket. 12 | let ret = rio_writen(&mut stream, &[1,1,1,1,1,1,1]).unwrap(); 13 | println!("write: {:?}", ret); 14 | 15 | //----- 16 | let rc = stream.read(&mut buf); 17 | println!("read: {:?}", rc); 18 | //check error to make decision to close the peer socket. 19 | match rc { 20 | Ok(n) => { 21 | println!("read, n: {}, server back {:?}" ,n, String::from_utf8_lossy(&buf)); 22 | //read return with Ok(0) that means peer socket is dead in common case. 23 | //of course, we also check both Ok(0) and Error::last_os_error().ErrorKind , such as: ErrorKind::NotConnected. 24 | //to avoid false alarm. 25 | if n == 0 { 26 | stream.shutdown(Shutdown::Both).unwrap_or_default(); 27 | println!("peer socket closed {:?}", stream); 28 | return Err(Error::last_os_error()); 29 | } 30 | } 31 | Err(e) => { 32 | match e.kind() { 33 | ErrorKind::ConnectionAborted | 34 | ErrorKind::ConnectionRefused | 35 | ErrorKind::ConnectionReset | 36 | ErrorKind::NotConnected | 37 | ErrorKind::BrokenPipe => { 38 | //should close the socket 39 | stream.shutdown(Shutdown::Both).unwrap_or_default(); 40 | println!("peer socket closed {:?}", stream); 41 | return Err(e); 42 | }, 43 | ErrorKind::TimedOut => { 44 | //tow choice : first , close the peer socket now. 45 | //second send heart beat packet to peer for checking its alive. 46 | }, 47 | 48 | //just for noneblocking mode. 49 | //ErrorKind::WouldBlock => {continue;}, 50 | 51 | _ => { continue;} 52 | } 53 | } 54 | } 55 | 56 | } 57 | 58 | } // the stream is closed here 59 | 60 | fn rio_writen(stream :&mut TcpStream, buf: &[u8]) -> Result { 61 | 62 | let mut nleft = buf.len(); 63 | let mut bufp = buf; 64 | while nleft > 0 { 65 | //attention: nwritten hit Ok(0), that means maybe some wrong or nothing, but always retry to write again and agian , until errors occureed(-1) or all Ok. 66 | match stream.write(bufp) { 67 | Ok(n) => { 68 | nleft -= n ; 69 | if nleft > 0 { 70 | bufp = &bufp[n..]; 71 | } 72 | } 73 | e => { 74 | return e; 75 | } 76 | } 77 | } 78 | return Ok(buf.len()); 79 | } 80 | -------------------------------------------------------------------------------- /peer_socket_dead_check/tcp_client_noneblock/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /peer_socket_dead_check/tcp_client_noneblock/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test_code" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | mio = "0.6.21" 11 | -------------------------------------------------------------------------------- /peer_socket_dead_check/tcp_client_tokio/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /peer_socket_dead_check/tcp_client_tokio/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tcp_client_tokio" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | tokio = { version = "0.2.6", features = ["full"] } 11 | -------------------------------------------------------------------------------- /peer_socket_dead_check/tcp_client_tokio/src/main.rs: -------------------------------------------------------------------------------- 1 | use tokio::net::{TcpStream}; 2 | use tokio::prelude::*; 3 | use std::io::{ErrorKind}; 4 | use std::net::{Shutdown}; 5 | 6 | #[tokio::main] 7 | async fn main() -> Result<(), Box> { 8 | // Connect to a peer 9 | let mut stream = TcpStream::connect("127.0.0.1:8080").await?; 10 | let mut buf = [1u8; 10]; 11 | loop { 12 | // Write some data. 13 | match stream.write_all(&buf).await { 14 | Err(e) => { 15 | println!("w: {:?}", e); 16 | if e.kind() == ErrorKind::ConnectionAborted { 17 | stream.shutdown(Shutdown::Both)?; 18 | break; 19 | } 20 | else if e.kind() == ErrorKind::ConnectionRefused { 21 | stream.shutdown(Shutdown::Both)?; 22 | break; 23 | } 24 | else if e.kind() == ErrorKind::ConnectionReset { 25 | stream.shutdown(Shutdown::Both)?; 26 | break; 27 | } 28 | else if e.kind() == ErrorKind::BrokenPipe { 29 | stream.shutdown(Shutdown::Both)?; 30 | break; 31 | } 32 | else {// if e.kind() == ErrorKind::Interrupted { 33 | // if e.kind() == ErrorKind::WriteZero { 34 | continue; 35 | } 36 | }, 37 | _ => {}, 38 | } 39 | 40 | //--- 41 | match stream.read(&mut buf).await { 42 | Err(e) => { 43 | println!("r: {:?}", e); 44 | if e.kind() == ErrorKind::ConnectionAborted { 45 | stream.shutdown(Shutdown::Both)?; 46 | break; 47 | } 48 | else if e.kind() == ErrorKind::ConnectionRefused { 49 | stream.shutdown(Shutdown::Both)?; 50 | break; 51 | } 52 | else if e.kind() == ErrorKind::ConnectionReset { 53 | stream.shutdown(Shutdown::Both)?; 54 | break; 55 | } 56 | else if e.kind() == ErrorKind::NotConnected { 57 | stream.shutdown(Shutdown::Both)?; 58 | break; 59 | } 60 | else { 61 | continue; 62 | } 63 | 64 | } 65 | Ok(n) => { 66 | println!("r:{:?}", n); 67 | if n == 0 { 68 | //peer socket is dead 69 | stream.shutdown(Shutdown::Both)?; 70 | break; 71 | } 72 | } 73 | } 74 | println!("{:?}", String::from_utf8_lossy(&buf)); 75 | 76 | } 77 | Ok(()) 78 | } 79 | -------------------------------------------------------------------------------- /pin_unpin/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /pin_unpin/pin_to_heap/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /pin_unpin/pin_to_heap/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pin_to_heap" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /pin_unpin/pin_to_heap/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | use std::marker::PhantomPinned; 3 | 4 | #[derive(Debug)] 5 | struct Test { 6 | a: String, 7 | b: *const String, 8 | _marker: PhantomPinned, 9 | } 10 | 11 | impl Test { 12 | fn new(txt: &str) -> Pin> { 13 | let t = Test { 14 | a: String::from(txt), 15 | b: std::ptr::null(), 16 | _marker: PhantomPinned, 17 | }; 18 | let mut boxed = Box::pin(t); 19 | let self_ptr: *const String = &boxed.as_ref().a; 20 | unsafe { boxed.as_mut().get_unchecked_mut().b = self_ptr }; 21 | 22 | boxed 23 | } 24 | 25 | fn a<'a>(self: Pin<&'a Self>) -> &'a str { 26 | &self.get_ref().a 27 | } 28 | 29 | fn b<'a>(self: Pin<&'a Self>) -> &'a String { 30 | unsafe { &*(self.b) } 31 | } 32 | } 33 | 34 | pub fn main() { 35 | let mut test1 = Test::new("test1"); 36 | let mut test2 = Test::new("test2"); 37 | 38 | println!("a: {}, b: {}",test1.as_ref().a(), test1.as_ref().b()); 39 | std::mem::swap(&mut test1, &mut test2); //???????????? 40 | println!("a: {}, b: {}",test2.as_ref().a(), test2.as_ref().b()); //从程序output看test2.as_ref().b()指向正确的位置! 41 | //我发现pin to stack例子中swap就会编译报错,不允许,或者说禁止获得&mut Test; 42 | //但是本例pin to heap 的swap编译通过,运行正确,test1和test2被移动成功, 而且 test2.b指向正确!? 43 | /* 44 | Pin> 代表将分配在堆上的T类型对象钉在原地不动,从而保持固定的内存位置!切记是T被分配到堆上,并且被钉在原地不许移动!即内存位置固定! 可并不是钉住Box<>这个胖指针不让Move! 45 | 46 | 但是即使不采用Pin , 当对象创建在堆上时, 即使他是!UnPin类型, 同样可以一直保持固定的内存位置!所以分配到堆上的对象天生就有固定性稳定性!!! 47 | 此处特别容易令人迷惑, 特别是C++guys对于下面代码可能会疑惑: 48 | 49 | std::mem::swap(&mut test1, &mut test2); //它按位交换的只是两个胖指针自身, 对其所指堆上对象没有影响! 50 | 51 | 此行代码命名已经按bitcopy and swap这两个堆对象了,你怎么可以说他们的内存位置不定不变呢??????? 52 | 53 | 莫急, 听我分说, 首先Rust语言默认就是Move语义, 传递所有权,除非类型实现了Copy Trait; 其二Rust的堆对象都是通过`胖指针`, 如Box来创建的! , 形如: let mut boxed = Box::new(t); 54 | boxed只一个栈变量, 一个胖指针, 而其所指的数据对象在堆上! test1 和test2即是如此, 所以通过swap, =赋值等操作, 只是按位复制交换了栈变量test1和test2, 相当于两者交换了所有权, 交换了指向! 而堆上的数据对象不受影响! 55 | 所以说move的只是这两个胖指针而已!交换了所有权而已, 其所指对象还在堆上内存位置固定没变! 完全符合Pin>的语义要求。 56 | */ 57 | } -------------------------------------------------------------------------------- /pin_unpin/pin_to_stack/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /pin_unpin/pin_to_stack/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pin_to_stack" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /pin_unpin/pin_to_stack/src/main.rs: -------------------------------------------------------------------------------- 1 | //https://cfsamson.github.io/books-futures-explained/4_pin.html#pinning-and-self-referential-structs 2 | use std::pin::Pin; 3 | use std::marker::PhantomPinned; 4 | 5 | #[derive(Debug)] 6 | struct Test { 7 | a: String, 8 | b: *const String, 9 | _marker: PhantomPinned, //此struct被标记为: !UnPin , 就是禁止Move的标志。 10 | } 11 | 12 | 13 | impl Test { 14 | fn new(txt: &str) -> Self { 15 | //直接在stack上create Test struct. 16 | //注意:不论C/C++/Rust等, 栈(变量)对象的生命周期小于等于当前所在函数调用栈帧的生命周期, 17 | //故此指针指向栈对象, 必须慎重考虑其生命长短,避免出现`悬指针`。 18 | Test { 19 | a: String::from(txt), 20 | b: std::ptr::null(), 21 | _marker: PhantomPinned, // This makes our type `!Unpin` 22 | } 23 | } 24 | fn init<'a>(self: Pin<&'a mut Self>) { 25 | let self_ptr: *const String = &self.a; 26 | let this = unsafe { self.get_unchecked_mut() }; 27 | this.b = self_ptr; 28 | } 29 | 30 | fn a<'a>(self: Pin<&'a Self>) -> &'a str { 31 | &self.get_ref().a 32 | } 33 | 34 | fn b<'a>(self: Pin<&'a Self>) -> &'a String { 35 | unsafe { &*(self.b) } 36 | } 37 | } 38 | 39 | fn main() { 40 | // test1 is safe to move before we initialize it 41 | let mut test1 = Test::new("test1"); 42 | // Notice how we shadow `test1` to prevent it from being accessed again 43 | //同名的新指针变量屏蔽了原来的test1, 以此确保只能通过Pin来访问到Test. 44 | //这样确保不可能再访问到旧test1指针! 45 | let mut test1 = unsafe { Pin::new_unchecked(&mut test1) }; 46 | Test::init(test1.as_mut()); 47 | 48 | let mut test2 = Test::new("test2"); 49 | let mut test2 = unsafe { Pin::new_unchecked(&mut test2) }; 50 | Test::init(test2.as_mut()); 51 | 52 | println!("a: {}, b: {}", Test::a(test1.as_ref()), Test::b(test1.as_ref())); 53 | //swap导致编译错误, 因为Pin实质上就是禁止获得&mut T引用(指针) , 54 | //无法获得&mut T指针,则无法Move , 比如:swap等。 55 | //之所以用Pin 包裹原来的裸指针,目的就是禁止获取到:&mut T. 56 | //好比游子的父母就是不搬离老房子, 这样归来的游子才能找到家门。 57 | // std::mem::swap(test1.get_mut(), test2.get_mut()); 58 | println!("a: {}, b: {}", Test::a(test2.as_ref()), Test::b(test2.as_ref())); 59 | } 60 | 61 | /*fn main() { 62 | let mut test1 = Test::new("test1"); 63 | let mut test1_pin = unsafe { Pin::new_unchecked(&mut test1) }; 64 | Test::init(test1_pin.as_mut()); 65 | drop(test1_pin); //Pin指针被提前drop , 因为test1未被遮蔽, 后面代码仍然可以访问到, 但是test1已被析构 66 | 67 | let mut test2 = Test::new("test2"); 68 | mem::swap(&mut test1, &mut test2); 69 | println!("Not self referential anymore: {:?}", test1.b); //test1.b == 0x00 , Pin析构时析构了test1 所指的Test Struct, 其内部指针归0, 70 | //所以说不再是自引用。 71 | }*/ -------------------------------------------------------------------------------- /pin_unpin/self_ref_struct/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /pin_unpin/self_ref_struct/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "self_ref_struct" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /pin_unpin/self_ref_struct/src/main.rs: -------------------------------------------------------------------------------- 1 | 2 | #[derive(Debug)] 3 | struct Test { 4 | a: String, 5 | b: *const String, 6 | } 7 | 8 | impl Test { 9 | fn new(txt: &str) -> Self { 10 | Test { 11 | a: String::from(txt), 12 | b: std::ptr::null(), 13 | } 14 | } 15 | 16 | fn init(&mut self) { 17 | let self_ref: *const String = &self.a; 18 | self.b = self_ref; 19 | } 20 | 21 | fn a(&self) -> &str { 22 | &self.a 23 | } 24 | 25 | fn b(&self) -> &String { 26 | unsafe {&*(self.b)} 27 | } 28 | } 29 | 30 | //这个代码例子充分说明了`self-referential structs` 引发的严重bug. 31 | //其实在c/c++中也是一样的, 结构体中一个指针field却指向本结构体中的某个其他field,表面看没什么问题, 32 | //但是一旦此结构体被move到其他内存位置,如下面代码中的swap, 这种按位copy的方式不能将结构体中的指针更新为新内存位置! 33 | //这也就是为什么C++提供移动构造函数等语言特性!而Rust语言默认语义是Move, 而且是按位copy方式, 所以出现上面的问题, 34 | //身在曹营心在汉!其实我觉得C++也只是和稀泥,未能彻底解决!对于变量赋值,对象构造可以用移动构造函数和赋值运算符解决; 35 | //对于底层bit copy/swap这一层面仍然是个漏洞,越过围墙,导致移动构造函数和赋值运算符等语言特性成了稻草人! 36 | //当然C++的语言哲学是:后果自负,作死活该!所以有坑有洞自己看着点!而Rust的语言哲学是:见洞就堵,见坑就填,作死就滚! 37 | //如何优雅高效彻底解决`self-referential structs` , Rust语言还在反复不断探讨!旷日持久! 38 | //这正式我热爱Rust的地方, 对于每一个语言特性都要千锤百炼,绝不滥竽充数, 而且对于发现潜在问题的语言特性零容忍,坚决砍去! 39 | //所以彻底完整的解决方法还在讨论, 为了实现poll a future, 搞个Pin /UnPin就够用了! 40 | //Pin的意思就是像钉子那样钉在那里不准移动!这样`self-referential structs`的指针问题就没有啦! 41 | //当然对于`非self-referential structs`的类型标记为UnPin , 即使被Pin也无影响,照样Move, 因为不存在自引用,完全安全呀! 42 | fn main() { 43 | let mut test1 = Test::new("test1"); 44 | test1.init(); 45 | let mut test2 = Test::new("test2"); 46 | test2.init(); 47 | 48 | println!("a: {}, b: {}", test1.a(), test1.b()); 49 | std::mem::swap(&mut test1, &mut test2); 50 | test1.a = "I've totally changed now!".to_string(); 51 | println!("a: {}, b: {}", test2.a(), test2.b()); //证明指针test2.b仍然指向test1.a位置,但是他应该指向test2.a才对的!!! 52 | 53 | } -------------------------------------------------------------------------------- /rust_embeded/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_embeded/Readme.md: -------------------------------------------------------------------------------- 1 | # `Rust Embeded` 优质学习资料 2 | 3 | - [`rust embeded权威资料`] 4 | 5 | > `https://docs.rust-embedded.org/discovery/` 入门 6 | > `https://docs.rust-embedded.org/book/` 中级 7 | > `https://docs.rust-embedded.org/embedonomicon/` 高级 8 | > `https://docs.rust-embedded.org/faq.html` 提问&回答 9 | > `https://docs.rust-embedded.org/` 总入口 10 | > 11 | > `https://docs.rust-embedded.org/embedonomicon/ `最适合入门!首先学习它!言简意赅,虽然是高级教程,确实通俗易懂小巧全面。 12 | > 13 | > `https://www.rust-lang.org/learn` 14 | 15 | > `本来我想自己写一篇关于rust embeded文章, 在不断收集资料和深入学习过程中,我发现rust 官方资料已经足够全面清晰简洁易读易懂!所以我没有必要再啰嗦了!官方文档中的英文不多,也很好看懂!` 16 | 17 | 18 | 19 | - [附加资料] 20 | 21 | > `https://doc.rust-lang.org/unstable-book/language-features/lang-items.html` 22 | > 23 | > `https://doc.rust-lang.org/book/` 24 | > `https://doc.rust-lang.org/reference/index.html` 25 | > `https://doc.rust-lang.org/nomicon/index.html` 26 | > `https://doc.rust-lang.org/nightly/unstable-book/index.html` 27 | > 28 | > `https://dev.to/verkkokauppacom/creating-an-ffi-compatible-c-abi-library-in-rust-5dji` 29 | > 30 | > `https://gankra.github.io/blah/rust-layouts-and-abis/` 31 | > 32 | > `https://github.com/rust-lang/rfcs/blob/master/text/0131-target-specification.md` 33 | > 34 | > `https://www.collabora.com/news-and-blog/blog/2020/06/23/cross-building-rust-gstreamer-plugins-for-the-raspberry-pi/` 35 | > 36 | > `https://github.com/rust-lang/rfcs/pull/2873` 37 | > 38 | > `https://ferrous-systems.com/blog/embedded-concurrency-patterns/` 39 | > 40 | > `https://micouy.github.io/posts/low-level-pt-1/` 41 | > 42 | > `https://avr-rust.com/` for compiling `arduino` 43 | 44 | 45 | 46 | - [特别推荐] 47 | 48 | > `https://fasterthanli.me/blog/2020/whats-in-a-linux-executable/` 49 | > 50 | > `https://fasterthanli.me/blog/2020/a-no-std-rust-binary/` 51 | 52 | 53 | 54 | - 创建新Target 55 | 56 | > `https://rust-embedded.github.io/embedonomicon/custom-target.html` 57 | 58 | 59 | 60 | - [`Rust ABI`] 61 | 62 | > `https://doc.rust-lang.org/stable/reference/abi.html` 63 | > 64 | > `https://doc.rust-lang.org/stable/reference/items/external-blocks.html#abi` 65 | > 66 | > `https://doc.rust-lang.org/stable/reference/items/functions.html#extern-function-qualifier` 67 | > 68 | > `https://doc.rust-lang.org/stable/reference/attributes.html#meta-item-attribute-syntax` 69 | > 70 | > `https://doc.rust-lang.org/nomicon/other-reprs.html#reprc` 71 | 72 | 73 | 74 | - [`Rust ASM inline assembly`] 75 | 76 | > ​ `https://blog.rust-lang.org/inside-rust/2020/06/08/new-inline-asm.html` 77 | > 78 | > Rust 实现了兼容`C ABI` ,从而实现了`C and Rust`互操作!现在又通过更加强大清晰的新语法支持内嵌汇编语言代码! 79 | > 80 | > 这样Rust在嵌入式,操作系统开发领域就妥妥地站稳脚跟!也就是说系统级开发语言圈:汇编语言、C、C++ 中,现在必须加上Rust。 81 | > 82 | > 而`Rust自身 ABI`的定义却不那么紧迫了!因为对于一门快速迭代成长的新兴系统级编程语言而言,过早地限定其`ABI`反而阻碍其进化优化! 83 | 84 | 85 | 86 | 87 | 88 | - [rust 国内源] 89 | 90 | > `https://huangjj27.gitlab.io/posts/rust-mirror/` 91 | > `https://mirrors.sjtug.sjtu.edu.cn/#/` 92 | > `https://mirrors.tuna.tsinghua.edu.cn/` 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /rust_iter/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "create_intoiterator" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator/src/main.rs: -------------------------------------------------------------------------------- 1 | //reference: https://stackoverflow.com/questions/30218886/how-to-implement-iterator-and-intoiterator-for-a-simple-struct 2 | struct Pixel { 3 | r: i8, 4 | g: i8, 5 | b: i8, 6 | } 7 | 8 | impl IntoIterator for Pixel { 9 | type Item = i8; 10 | type IntoIter = PixelIntoIterator; 11 | 12 | fn into_iter(self) -> Self::IntoIter { 13 | PixelIntoIterator { 14 | pixel: self, 15 | index: 0, 16 | } 17 | } 18 | } 19 | 20 | struct PixelIntoIterator { 21 | pixel: Pixel, 22 | index: usize, 23 | } 24 | 25 | impl Iterator for PixelIntoIterator { 26 | type Item = i8; 27 | fn next(&mut self) -> Option { 28 | let result = match self.index { 29 | 0 => self.pixel.r, 30 | 1 => self.pixel.g, 31 | 2 => self.pixel.b, 32 | _ => return None, 33 | }; 34 | self.index += 1; 35 | Some(result) 36 | } 37 | } 38 | 39 | fn main() { 40 | let p = Pixel { 41 | r: 54, 42 | g: 23, 43 | b: 74, 44 | }; 45 | for component in p {//for 自动调用into_iter获得迭代器, 同时p的所有权也被move进PixelIntoIterator了。 46 | println!("{}", component); 47 | } 48 | //后面代码不能再访问p了,因为它已经丧失所有权,失效了。 49 | } -------------------------------------------------------------------------------- /rust_iter/create_intoiterator2/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "create_intoiterator2" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator3/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator3/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "create_intoiterator3" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator3/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_variables, non_snake_case)] 2 | 3 | #[derive(Debug)] 4 | pub struct StatusRegister { 5 | CarryFlag: bool, 6 | ZeroFlag: bool, 7 | OverflowFlag: bool, 8 | } 9 | 10 | impl StatusRegister { 11 | fn new() -> Self { 12 | StatusRegister { 13 | CarryFlag: true, 14 | ZeroFlag: false, 15 | OverflowFlag: true, 16 | } 17 | } 18 | 19 | fn iter_mut(&mut self) -> StatusRegisterIterMut { 20 | StatusRegisterIterMut { 21 | status: self, 22 | index: 0, 23 | } 24 | } 25 | } 26 | 27 | impl<'a> IntoIterator for &'a mut StatusRegister { 28 | type IntoIter = StatusRegisterIterMut<'a>; 29 | type Item = &'a mut bool; 30 | 31 | fn into_iter(self) -> Self::IntoIter { 32 | self.iter_mut() 33 | } 34 | } 35 | 36 | pub struct StatusRegisterIterMut<'a> { 37 | status: &'a mut StatusRegister, 38 | index: usize, 39 | } 40 | 41 | impl<'a> Iterator for StatusRegisterIterMut<'a> { 42 | type Item = &'a mut bool; 43 | 44 | // Invariant to keep: index is 0, 1, 2 or 3 45 | // Every call, this increments by one, capped at 3 46 | // index should never be 0 on two different calls 47 | // and similarly for 1 and 2. 48 | fn next(&mut self) -> Option { 49 | let result = unsafe { 50 | match self.index { 51 | // Safety: Since each of these three branches are 52 | // executed exactly once, we hand out no more than one mutable reference 53 | // to each part of self.status 54 | // Since self.status is valid for 'a 55 | // Each partial borrow is also valid for 'a 56 | 0 => &mut *(&mut self.status.CarryFlag as *mut _), 57 | 1 => &mut *(&mut self.status.ZeroFlag as *mut _), 58 | 2 => &mut *(&mut self.status.OverflowFlag as *mut _), 59 | _ => return None, 60 | } 61 | }; 62 | // If self.index isn't 0, 1 or 2, we'll have already returned 63 | // So this bumps us up to 1, 2 or 3. 64 | self.index += 1; 65 | Some(result) 66 | } 67 | } 68 | 69 | pub struct CPU { 70 | pub memory: [u8; 0xffff], 71 | pub status: StatusRegister, 72 | } 73 | 74 | impl CPU { 75 | pub fn new() -> CPU { 76 | let memory = [0; 0xFFFF]; 77 | CPU { 78 | memory, 79 | status: StatusRegister::new(), 80 | } 81 | } 82 | 83 | fn execute(&mut self) { 84 | let mut shifter = 0b1000_0000; 85 | println!("Before: {:?}", self.status); 86 | for status in self.status.iter_mut() { 87 | // mut status here! 88 | *status = !*status; 89 | println!("{}", status); 90 | shifter <<= 1; 91 | } 92 | println!("After: {:?}", self.status); 93 | } 94 | } 95 | 96 | fn main() { 97 | let mut cpu = CPU::new(); 98 | cpu.execute(); 99 | } 100 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator4/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator4/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "create_intoiterator4" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator4/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_variables, non_snake_case)] 2 | 3 | #[derive(Debug)] 4 | pub struct StatusRegister { 5 | CarryFlag: bool, 6 | ZeroFlag: bool, 7 | OverflowFlag: bool, 8 | } 9 | 10 | impl StatusRegister { 11 | fn new() -> Self { 12 | StatusRegister { 13 | CarryFlag: true, 14 | ZeroFlag: false, 15 | OverflowFlag: true, 16 | } 17 | } 18 | 19 | fn iter_mut(&mut self) -> impl Iterator { 20 | use std::iter::once; 21 | once(&mut self.CarryFlag) 22 | .chain(once(&mut self.ZeroFlag)) 23 | .chain(once(&mut self.OverflowFlag)) 24 | } 25 | } 26 | 27 | pub struct CPU { 28 | pub memory: [u8; 0xffff], 29 | pub status: StatusRegister, 30 | } 31 | 32 | impl CPU { 33 | pub fn new() -> CPU { 34 | let memory = [0; 0xFFFF]; 35 | CPU { 36 | memory, 37 | status: StatusRegister::new(), 38 | } 39 | } 40 | 41 | fn execute(&mut self) { 42 | let mut shifter = 0b1000_0000; 43 | println!("Before: {:?}", self.status); 44 | for status in self.status.iter_mut() { 45 | // mut status here! 46 | *status = !*status; 47 | println!("{}", status); 48 | shifter <<= 1; 49 | } 50 | println!("After: {:?}", self.status); 51 | } 52 | } 53 | 54 | fn main() { 55 | let mut cpu = CPU::new(); 56 | cpu.execute(); 57 | } 58 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator5/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator5/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "create_intoiterator5" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_iter/create_intoiterator5/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_variables, non_snake_case)] 2 | 3 | #[derive(Debug)] 4 | pub struct StatusRegister { 5 | CarryFlag: bool, 6 | ZeroFlag: bool, 7 | OverflowFlag: bool, 8 | } 9 | 10 | impl StatusRegister { 11 | fn new() -> Self { 12 | StatusRegister { 13 | CarryFlag: true, 14 | ZeroFlag: false, 15 | OverflowFlag: true, 16 | } 17 | } 18 | 19 | fn iter_mut(&mut self) -> std::vec::IntoIter<&mut bool> { 20 | vec![ 21 | &mut self.CarryFlag, 22 | &mut self.ZeroFlag, 23 | &mut self.OverflowFlag, 24 | ] 25 | .into_iter() 26 | } 27 | } 28 | 29 | pub struct CPU { 30 | pub memory: [u8; 0xffff], 31 | pub status: StatusRegister, 32 | } 33 | 34 | impl CPU { 35 | pub fn new() -> CPU { 36 | let memory = [0; 0xFFFF]; 37 | CPU { 38 | memory, 39 | status: StatusRegister::new(), 40 | } 41 | } 42 | 43 | fn execute(&mut self) { 44 | let mut shifter = 0b1000_0000; 45 | println!("Before: {:?}", self.status); 46 | for status in self.status.iter_mut() { 47 | // mut status here! 48 | *status = !*status; 49 | println!("{}", status); 50 | shifter <<= 1; 51 | } 52 | println!("After: {:?}", self.status); 53 | } 54 | } 55 | 56 | fn main() { 57 | let mut cpu = CPU::new(); 58 | cpu.execute(); 59 | } 60 | -------------------------------------------------------------------------------- /rust_iter/iter_method/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_iter/iter_method/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iter_method" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_iter/iter_method/src/main.rs: -------------------------------------------------------------------------------- 1 | 2 | 3 | fn main() { 4 | 5 | //几个Iterator常用的方法,背熟用好,非常有利于写出简洁代码。 6 | let v = vec![1,2,3,4,5,6]; 7 | let it = v.iter().filter(|&x|{ x % 2 == 0}); 8 | for x in it { 9 | println!("{}", x); 10 | } 11 | //----------------------------- 12 | let collect: Vec = v.iter().map( |&x|{ x*2}).collect(); 13 | for x in collect { 14 | println!("{}", x); 15 | } 16 | //------------------------------- 17 | let sum = v.iter().fold(0, | acc, &x|{ acc +x }); 18 | println!("{}", sum ); 19 | //-------------------------------- 20 | let v2 = vec![7,8,9,10]; 21 | let all_it = v.iter().chain(v2.iter()); 22 | for x in all_it { 23 | println!("{}", x); 24 | } 25 | //-------------------------------- 26 | let mut idx_value_pair = v.iter().enumerate(); 27 | println!("{:?}", idx_value_pair.next()); 28 | //----------------------------- 29 | println!("{}", v.iter().count()); 30 | //------------------------------ 31 | let sum: i32 = v.iter().sum(); 32 | println!("{}", sum); 33 | //------------------------------- 34 | let data = vec![vec![1, 2, 3, 4], vec![5, 6]]; 35 | let flattened = data.into_iter().flatten().collect::>(); 36 | for x in flattened { 37 | println!("{}", x); 38 | } 39 | //-------------------------------- 40 | v.iter().for_each(|x|{ println!("{}",x);}); 41 | //------------------------------- 42 | let the_item= v.iter().nth(1); 43 | println!("{:?}", the_item); 44 | //------------------------------ 45 | let rev_it = v.iter().rev(); 46 | for x in rev_it { 47 | println!("{}",x); 48 | } 49 | //-------------------------------- 50 | let a = [0, 1, 2, 3, 4, 5]; 51 | let step_it = a.iter().step_by(2); 52 | for x in step_it { 53 | println!("{}", x); 54 | } 55 | //------------------------------- 56 | 57 | } 58 | -------------------------------------------------------------------------------- /rust_mod_study/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_mod_study/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "exp" 5 | version = "0.1.0" 6 | dependencies = [ 7 | "lip 0.1.0", 8 | "lip1 0.1.0", 9 | "lip2 0.1.0", 10 | "lip3 0.1.0", 11 | ] 12 | 13 | [[package]] 14 | name = "lip" 15 | version = "0.1.0" 16 | 17 | [[package]] 18 | name = "lip1" 19 | version = "0.1.0" 20 | 21 | [[package]] 22 | name = "lip2" 23 | version = "0.1.0" 24 | 25 | [[package]] 26 | name = "lip3" 27 | version = "0.1.0" 28 | 29 | -------------------------------------------------------------------------------- /rust_mod_study/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["exp", "lip", "lip1", "lip2", "lip3"] 3 | -------------------------------------------------------------------------------- /rust_mod_study/README.md: -------------------------------------------------------------------------------- 1 | # RUST模块的理解 2 | 3 | *** 4 | 5 | 6 | 7 | * 每一个crate就是一个根模块。如:`exp, lip, lip1, lip2, lip3`。 8 | 9 | * 独立的一个文件就是一个mod,文件名就是mod名;但是main.rs, lib.rs, mod.rs除外,mod.rs的模块名就是其所在目录的名字; 而main.rs, lib.rs 的目录结构,如:` exp/src/main.rs `或 `lip/src/lib.rs` ;两者的mod名分别是exp和lip。 10 | 11 | * 文件和文件夹内的mod 及其内部定义的函数默认都是private的,除非pub声明公开。 12 | 13 | * 一个文件夹直接包含mod.rs ,如: ` rust_mod_study/lip2/src/worker/mod.rs ;`则 worker就是模块名; 并且mod.rs为此模块的入口文件,此文件夹内的其他子模块都要在mod.rs中 `pub mod 模块名`,声明后,外部方可看到。 14 | 15 | * 如果一个元素是私有的,那么只有本模块内的元素以及它的子模块可以访问。 16 | 17 | * 如果一个元素是公开的,那么它上一层的模块就有权访问它。 18 | 19 | * 如果存在与文件同名的目录, 则在该目录下定义的模块都是该文件的子模块.(`2018 edition有效`)如:`rust_mod_study/lip3/src/caller.rs ;` `rust_mod_study/lip3/src/caller/callerin.rs;` 20 | 21 | ​ 特别注意,callerin这个mod必须在caller.rs中以`pub mod callerin;`形式声明,否则外部看不到; 最终模块路径为:`lip3::caller::callerin::call();` 22 | 23 | * `rust 2018 edition` 不再需要在根模块中使用extern crate xxx;语法导入第三方包。如在文件`main.rs , lib.rs`中不再需要extern crate xxx语法导入第三方包, 如:` rust_mod_study/exp/src/main.rs` 中的extern crate xxx可以去掉了。只需在Cargo.toml中配置好, 然后在代码中以模块路径访问即可,如:modx::mody::modz::fnx(); 也可以use一下,缩短路径。 24 | 25 | * rust 如何引用未发布的本地crate, 特别之处在`exp/Cargo.toml`中, 如: 26 | 27 | ```tom 28 | [package] 29 | name = "exp" 30 | version = "0.1.0" 31 | authors = ["yujinliang <285779289@qq.com>"] 32 | edition = "2018" 33 | 34 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 35 | [dependencies] 36 | lip = {path= "../lip" } 37 | lip1 = {path= "../lip1" } 38 | lip2 = {path= "../lip2" } 39 | lip3 = {path= "../lip3" } 40 | 41 | ``` 42 | 43 | - 目录结构:` Cargo.lock Cargo.toml exp lip lip1 lip2 lip3 target `在同一个父目录`rust_mod_study`中;其中`exp/src/main.rs`引用lip开头的所有模块。 44 | 45 | 46 | 47 | - 配置`rust workspace`, 在`rust_mod_study/Cargo.toml`中加入以下配置即可,如: 48 | 49 | ``` 50 | [workspace] 51 | members = ["exp", "lip", "lip1", "lip2", "lip3"] 52 | ``` 53 | 54 | * 在rust_mod_study/exp中给出一个例子用于说明:在同一个crate下各个子mod间的可见性和引用方法 55 | 56 | 1. 首先各个子mod都需要在main.rs(属于crate顶级mod)中声明自己, 如: mod producer; mod consumer; mod switcher;等 ,只有这样各个子mod才能看到彼此,才能引用。 57 | 2. 每一个子mod可以用use crate::xxx形式引用在1.中声明的mod, 如:use crate::producer;等。 58 | 3. 每一个子mod自身默认都是自私的,除非以pub , pub use等打开为公用。 59 | 4. 对于pub struct 其field默认仍然是private的,需要pub声明为公用。 60 | 61 | 总结: 父mod可以引用其子mod, 但是在父模块中仍然需要声明后方可应用子模块,如:`mod 子模块名` ;而每一个子模块,只可以看到在其父模块中声明过的子mod, 但是仍需`use crate::子模块名` 来引用一下后方可用。 62 | 63 | 我是在rust 1.39中做的实验, 时间急促,水平有限,如有谬误,欢迎指正,感谢啦! 64 | 65 | 66 | 67 | * 所有的例子代码都在rust_mod_study目录中 ` 68 | 69 | 70 | 71 | - 追加好资料 72 | 73 | > `http://www.sheshbabu.com/posts/rust-module-system/` 74 | 75 | 76 | 77 | [^footnote]: 本文只是随笔,所以不求面面俱到,只针对容易误解的点。 78 | 79 | 80 | 81 | > RUST学习随笔,如有谬误,尽请指正,谢谢。 82 | > 83 | > 作者:心尘了 84 | > 85 | > email: 285779289@qq.com 86 | > 87 | > 微信:justice_forever_123 88 | > 89 | 90 | 91 | 92 | #### Reference List 93 | 94 | * 深入浅出Rust, 范长春著, 机械工业出版社. 95 | * Rust编程之道, 张汉东著, 电子工业出版社. 96 | 97 | 98 | 99 | #### Thanks All 100 | 101 | #### 信息资料繁多,网络信息资源更是浩如烟海,故此难以全部列出引用参考出处,在此一并感谢!如有缺漏,十分抱歉,最后感谢所有前辈的付出和心血。 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /rust_mod_study/exp/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /rust_mod_study/exp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "exp" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | lip = {path= "../lip" } 11 | lip1 = {path= "../lip1" } 12 | lip2 = {path= "../lip2" } 13 | lip3 = {path= "../lip3" } 14 | -------------------------------------------------------------------------------- /rust_mod_study/exp/src/consumer/cons.rs: -------------------------------------------------------------------------------- 1 | use crate::producer; 2 | use crate::switcher; 3 | 4 | #[derive(Debug)] 5 | pub struct Consumer { 6 | pub id: String, 7 | } 8 | 9 | 10 | impl Consumer { 11 | 12 | pub fn pr(&self) { 13 | println!("{:#?}", self); 14 | } 15 | 16 | pub fn call_other_mod() { 17 | 18 | let p = producer::Producer{id: "I am producer from consumer".to_string()}; 19 | p.pr(); 20 | switcher::sw::exchange(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /rust_mod_study/exp/src/consumer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod cons; 2 | -------------------------------------------------------------------------------- /rust_mod_study/exp/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate lip; 2 | extern crate lip1; 3 | extern crate lip2; 4 | //extern crate lip3; //for rust 2018 edition 5 | 6 | mod consumer; 7 | mod producer; 8 | mod switcher; 9 | 10 | fn main() { 11 | println!("exp mod:"); 12 | 13 | println!("lip mod"); 14 | lip::caller::call(); 15 | lip::worker::work1(); 16 | 17 | println!("lip1 mod"); 18 | lip1::caller::call(); 19 | lip1::worker::work1(); 20 | 21 | println!("lip2 mod"); 22 | lip2::caller::callerx::call(); 23 | lip2::worker::worker1::work1(); 24 | lip2::worker::worker2::work2(); 25 | lip2::worker::worker3::work3(); 26 | lip2::worker::workx(); 27 | 28 | println!("lip3 mod"); 29 | lip3::caller::callerin::call(); 30 | 31 | println!("exp mod"); 32 | consumer::cons::Consumer::call_other_mod(); 33 | producer::Producer::call_other_mod(); 34 | } 35 | -------------------------------------------------------------------------------- /rust_mod_study/exp/src/producer/mod.rs: -------------------------------------------------------------------------------- 1 | mod pror; 2 | pub use pror::Producer; -------------------------------------------------------------------------------- /rust_mod_study/exp/src/producer/pror.rs: -------------------------------------------------------------------------------- 1 | use crate::consumer; 2 | 3 | #[derive(Debug)] 4 | pub struct Producer { 5 | pub id: String, 6 | } 7 | 8 | 9 | impl Producer { 10 | 11 | pub fn pr(&self) { 12 | println!("{:#?}", self); 13 | } 14 | 15 | pub fn call_other_mod() { 16 | 17 | let p = consumer::cons::Consumer{id: "I am consumer from producer".to_string()}; 18 | p.pr(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /rust_mod_study/exp/src/switcher.rs: -------------------------------------------------------------------------------- 1 | pub mod sw; -------------------------------------------------------------------------------- /rust_mod_study/exp/src/switcher/sw.rs: -------------------------------------------------------------------------------- 1 | 2 | pub fn exchange() { 3 | 4 | println!("switcher is ok"); 5 | } -------------------------------------------------------------------------------- /rust_mod_study/lip/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /rust_mod_study/lip/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lip" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_mod_study/lip/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() { 5 | assert_eq!(2 + 2, 4); 6 | } 7 | } 8 | 9 | pub mod caller { 10 | 11 | pub fn call(){ 12 | 13 | println!("lip::caller::call()"); 14 | } 15 | 16 | } 17 | 18 | pub mod worker { 19 | 20 | pub fn work1() { 21 | 22 | println!("lip::worker::work1()"); 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /rust_mod_study/lip1/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /rust_mod_study/lip1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lip1" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_mod_study/lip1/src/caller.rs: -------------------------------------------------------------------------------- 1 | pub fn call() { 2 | 3 | println!("lip1::caller::call()"); 4 | } 5 | -------------------------------------------------------------------------------- /rust_mod_study/lip1/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() { 5 | assert_eq!(2 + 2, 4); 6 | } 7 | } 8 | 9 | pub mod caller; 10 | pub mod worker; 11 | -------------------------------------------------------------------------------- /rust_mod_study/lip1/src/worker.rs: -------------------------------------------------------------------------------- 1 | pub fn work1() { 2 | 3 | println!("lip1::worker::work1()"); 4 | } 5 | -------------------------------------------------------------------------------- /rust_mod_study/lip2/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /rust_mod_study/lip2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lip2" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_mod_study/lip2/src/caller.rs: -------------------------------------------------------------------------------- 1 | pub mod callerx { 2 | 3 | pub fn call() { 4 | 5 | println!("lip2::caller::callerx::call()"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /rust_mod_study/lip2/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() { 5 | assert_eq!(2 + 2, 4); 6 | } 7 | } 8 | 9 | pub mod caller; 10 | pub mod worker; 11 | -------------------------------------------------------------------------------- /rust_mod_study/lip2/src/worker/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod worker1; 2 | pub mod worker2; 3 | pub mod worker3; 4 | 5 | 6 | pub fn workx() { 7 | 8 | println!("lip2::worker::workx()"); 9 | } 10 | -------------------------------------------------------------------------------- /rust_mod_study/lip2/src/worker/worker1.rs: -------------------------------------------------------------------------------- 1 | pub fn work1() { 2 | 3 | println!("lip2::worker::work1()"); 4 | } 5 | -------------------------------------------------------------------------------- /rust_mod_study/lip2/src/worker/worker2.rs: -------------------------------------------------------------------------------- 1 | pub fn work2() { 2 | 3 | println!("lip2::worker::work2()"); 4 | } 5 | -------------------------------------------------------------------------------- /rust_mod_study/lip2/src/worker/worker3.rs: -------------------------------------------------------------------------------- 1 | pub fn work3() { 2 | 3 | println!("lip2::worker::work3()"); 4 | } 5 | -------------------------------------------------------------------------------- /rust_mod_study/lip3/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /rust_mod_study/lip3/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lip3" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_mod_study/lip3/src/caller.rs: -------------------------------------------------------------------------------- 1 | pub mod callerin; 2 | -------------------------------------------------------------------------------- /rust_mod_study/lip3/src/caller/callerin.rs: -------------------------------------------------------------------------------- 1 | pub fn call() { 2 | 3 | println!("lip3::caller::callerin::call()"); 4 | 5 | } 6 | -------------------------------------------------------------------------------- /rust_mod_study/lip3/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() { 5 | assert_eq!(2 + 2, 4); 6 | } 7 | } 8 | 9 | pub mod caller; 10 | -------------------------------------------------------------------------------- /rust_my_error/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_my_error/README.md: -------------------------------------------------------------------------------- 1 | # 自定义Error in Rust 2 | 3 | 我参考了`std::io::Error`的实现代码,写了两个代码小例子,我尽可能简化之,只保留必须实现的Trait. 4 | 5 | 对于Rust的错误处理, Option可以表达`有和无`, Result进而表达`对和错`, 很多时候,知道出现错误了,就够了! 但是有时候我们必须针对每一种具体错误类型做出更加有针对性的处理逻辑!所以第三个要求:光知道出错还不够,还要知道具体发生了什么种类错误!特别是对于crate库的实现者,对于返回给caller的Result::Err必须给出具体明确的错误类型,这样可以令caller可以针对性处理。 6 | 7 | C语言大家基本都学过, C函数返回不同的有符号整数,用于表示不同的错误种类!`Unix/Linux`的 `errno` 也是如此! 8 | 9 | 很朴素,很直接,但是可读性不高!对于Rust而言,直接在Result::Err(错误码)包含有符号整数错误码当然很简单!但是Rust Style呢?通常是自定义Error,关键点: 10 | 11 | * `pub enum MyError { ...}` 或`pub struct MyError{}` 12 | * `impl trait Debug,Display for MyError` 13 | * `impl trait std::error::Error for MyError` 14 | * `impl trait From<> for MyError` 15 | 16 | > 提示: trait From用于将不同模块或crate的Error转化为我的自定义Error; 而且Rust 要求`自定义Error`必须实现`std::error::Error`trait , 且这个`trait` 中,只有`fn source`必须要实现, `fn description` 只要你实现了`trait Display` 就没必要实现了,`fn cause`淘汰了,我在`rust 1.39`中实验如此。 17 | > 18 | > 具体还是看代码例子吧。 19 | > 20 | > 在实现过程中,必须注意的问题: 21 | > 22 | > 1. 各种元素:Sized, 即必须是大小固定可知的, 编译期常量。 23 | > 2. 满足 Trait Send , Sync限定,因为可能在线程间传递共享。 24 | > 25 | 26 | `以上个人理解恐有谬误,尽请指正!` 27 | 28 | ------ 29 | 30 | # [Rust: Structuring and handling errors in 2020](https://nick.groenen.me/posts/rust-error-handling/)- 学习笔记 31 | 32 | `直接上菜, 首先介绍两个新的Crate用于Rust Error处理,anyhow 和thiserror, 其代表Rust Error处理的最新探索成果! anyhow面向Application应用程序开发, thiserror面向Library开发, 为什么一个Rust Error处理需要分成两个Crate来处理呢?!` 理由如下: 33 | 34 | > (1) 库应专注于生成有意义的结构化错误类型/变体。这允许应用程序轻松区分各种错误情况。 35 | > 36 | > (2) 应用程序主要消化错误。 37 | > 38 | > (3) 库需要将错误从一种类型转换为另一种类型。比如:将底层IO错误封装进本库提供的高级错误,这样调用者才能区分此底层IO错误具体来自于那个库。 39 | > 40 | > (4) 库在更改错误或创建新错误时必须小心,因为这些错误很容易为调用者引入破坏性更改。所以要求库可以更容易地更改和新建错误,同时尽可能避免祸及调用者。 41 | > 42 | > (5) 库返回错误,而应用程序需要决定这些错误是否格式化以及如何显示给人。 43 | > 44 | > (6) 应用程序可能还希望分析和检查错误,例如将错误转发到异常跟踪系统,或者在认为安全时重试操作。 45 | > 46 | > (7) 库的`pub API`应该始终使用std::Result和自定义Error 类型(并且它impl了std::error::Error Trait) ,而failure::Fail这类Rust Error处理Crate没有能与Rust原生的Error处理很好地融合, 独自创造了一套,也难以很好的和用户代码相融合, 增加了用户学习负担。 47 | > 48 | > 总结: 基于以上理由, 将错误处理分为两个crate就非常必要了!同时提炼出优质Rust Error处理crate的特性: A. 可以与Rust原生Error处理很好融合。B. 可以与用户代码很好地融合,最好是不漏踪迹,不污染用户代码。 C. 极大地降低学习和使用负担,最好零负担。 D. 非常容易更改和新建错误,不会导致调用者破坏性修改代码。 E. 可以backtrace, 清晰表达错误类型、源头和传播路径。 F. 可以给每个错误以人性化的可读信息。G. 灵活有效的错误分析、检查、转发、重试机制。 49 | > 50 | > 【详细内容请看】:`https://nick.groenen.me/posts/rust-error-handling/` 51 | 52 | 53 | 54 | > 参照原文,我整理调试出两个代码例子, `thiserror_t 和anyhow_t `, 放到了`https://github.com/yujinliang/rust_learn/tree/master/rust_my_error` , 有兴趣可以看看。 55 | 56 | 57 | 58 | - Author 59 | 60 | 61 | > RUST学习随笔,如有谬误,尽请指正,谢谢。 62 | > 63 | > 作者:心尘了 64 | > 65 | > email: [285779289@qq.com](mailto:285779289@qq.com) 66 | 67 | 68 | 69 | - Reference: 70 | 71 | `https://nick.groenen.me/posts/rust-error-handling/` 72 | 73 | `https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html` 74 | 75 | `https://mozillazg.com/2017/10/rust-cargo-use-local-crate-package.html` 76 | 77 | `https://doc.rust-lang.org/rust-by-example/cargo/deps.html` -------------------------------------------------------------------------------- /rust_my_error/anyhow_t/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_my_error/anyhow_t/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "anyhow_t" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | #`https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html` 9 | [dependencies] 10 | thiserror_t = { path = "../thiserror_t"} #如果thiserror_t crate在其Cargo.toml中[lib]下定义的name与其package name不符,则报错,找不到thiserror_t! 11 | anyhow = "1.0.31" 12 | -------------------------------------------------------------------------------- /rust_my_error/anyhow_t/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate thiserror_t; 2 | use anyhow::{Context, Result}; 3 | use std::fs::File; 4 | use std::env; 5 | use thiserror_t::count_words; 6 | 7 | fn main() -> Result<()> { 8 | for filename in env::args().skip(1).collect::>() { 9 | let mut reader = File::open(&filename).context(format!("unable to open '{}'", filename))?; 10 | let wordcount = 11 | count_words(&mut reader).context(format!("unable to count words in '{}'", filename))?; 12 | println!("{} {}", wordcount, filename); 13 | } 14 | Ok(()) 15 | } 16 | 17 | //深入学习请看:`https://nick.groenen.me/posts/rust-error-handling/` 18 | //anyhow crate的好处: 19 | //1. 明显简化了main()函数的返回值类型声明。 20 | //2. 通过context可以对相应错误进行更加详细的注释描述。 21 | //3. 通过此命令行:RUST_BACKTRACE=1 cargo run some_options 列出错误源头和传播路径。 22 | //4. 可格式化错误输出显示格式。 23 | //总结: Rust的错误处理方案始终是争论比较激烈的地方, 一直在激烈快速进化,结合几十年丰厚的软件工程实践经验, 24 | //不断探索改进最优雅高效的Rust错误处理方案!最终尘埃落定之前,必然百家争鸣百花齐放! 25 | //所以failure之类已经过时, 现在推荐thiserror 和anyhow crates。 26 | //从示例代码可知, 使用thiserror和anyhow crate极为简单,无痛零负担,好似百步神拳无影掌。 27 | //之前的failure crate有点喧宾夺主的感觉,另立一套,融入性差,使用负担重。 -------------------------------------------------------------------------------- /rust_my_error/my_enum_error/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_my_error/my_enum_error/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "my_enum_error" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_my_error/my_enum_error/src/error.rs: -------------------------------------------------------------------------------- 1 | 2 | #[derive(Debug)] 3 | pub enum MyError{ 4 | 5 | Test1, 6 | Test2(char), 7 | Test3(i32), 8 | Test4(&'static str), 9 | Test5(String), 10 | Io(std::io::Error), 11 | Other(Box), 12 | } 13 | 14 | impl std::convert::From for MyError { 15 | 16 | fn from(e: std::io::Error) -> Self { 17 | MyError::Io(e) 18 | } 19 | } 20 | 21 | impl std::fmt::Display for MyError { 22 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 23 | 24 | match self { 25 | 26 | MyError::Test1 => write!(f, "MyError::Test1"), 27 | MyError::Test2(c) => write!(f, "MyError::Test2: {}", c), 28 | MyError::Test3(n) => write!(f, "MyError::Test3: {}", n), 29 | MyError::Test4(ref s) => write!(f, "MyError::Test4: {}", s), 30 | MyError::Test5(ref s) => write!(f, "MyError::Test5: {}", s), 31 | MyError::Io(e) => e.fmt(f), 32 | MyError::Other(e) => e.fmt(f), 33 | } 34 | } 35 | } 36 | 37 | impl std::error::Error for MyError { 38 | 39 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 40 | match self { 41 | MyError::Test1 => None, 42 | MyError::Test2(..) => None, 43 | MyError::Test3(..) => None, 44 | MyError::Test4(..) => None, 45 | MyError::Test5(..) => None, 46 | MyError::Io(e) => e.source(), 47 | MyError::Other(e) => e.source(), 48 | 49 | } 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /rust_my_error/my_enum_error/src/main.rs: -------------------------------------------------------------------------------- 1 | mod error; 2 | 3 | 4 | fn main() { 5 | 6 | println!("{}", error::MyError::Test1); 7 | println!("{}", error::MyError::Test2('c')); 8 | println!("{}", error::MyError::Test3(8)); 9 | println!("{}", error::MyError::Test4("test errror &str")); 10 | println!("{}", error::MyError::Test5("test error string".to_string())); 11 | 12 | if let error::MyError::Other(e) = error::MyError::Other(Box::new(std::io::Error::new(std::io::ErrorKind::Other, error::MyError::Test1))){ 13 | println!("{}", e); 14 | assert!(e.is::()); 15 | assert!(e.downcast::().unwrap().get_ref().unwrap().is::()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rust_my_error/my_struct_error/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_my_error/my_struct_error/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "my_struct_error" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_my_error/my_struct_error/src/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_my_error/my_struct_error/src/error.rs: -------------------------------------------------------------------------------- 1 | use std::convert::From; 2 | use std::fmt::{Debug, Display,Formatter}; 3 | 4 | //只是对std::io::Error实现的简化,以利说明。 5 | #[derive(Debug)] 6 | pub struct MyStructError { 7 | repr: Repr, 8 | } 9 | 10 | impl MyStructError { 11 | 12 | pub fn kind(&self) -> ErrorKind { 13 | match self.repr { 14 | Repr::Os(..) => ErrorKind::Os, //此处应获取OS的enum error kind, 如: Repr::Os(code) => sys::decode_error_kind(code), 15 | Repr::Custom(ref c) => c.kind, 16 | Repr::Simple(kind) => kind, 17 | } 18 | } 19 | } 20 | 21 | #[derive(Debug)] 22 | enum Repr { 23 | Os(i32), //用于包含底层OS返回的错误码. 24 | Simple(ErrorKind), //用于包含自己定义的具体错误case. 25 | Custom(Box), //用于包含其他crate实现的各种Error。 26 | } 27 | 28 | #[derive(Debug)] 29 | struct Custom { 30 | kind: ErrorKind, //用于标定其他crate的Error 31 | error: Box, //用于指向其他crate实现的Error类型。 32 | } 33 | 34 | //定义错误具体种类。 35 | #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] 36 | pub enum ErrorKind { 37 | 38 | NotFound, 39 | Os, 40 | Other, 41 | } 42 | 43 | impl ErrorKind { 44 | 45 | pub(crate) fn as_str(&self) -> &'static str { 46 | match *self { 47 | ErrorKind::NotFound => "entity not found", 48 | ErrorKind::Os => "os error", 49 | ErrorKind::Other => "other os error", 50 | } 51 | } 52 | } 53 | 54 | impl From for MyStructError { 55 | #[inline] 56 | fn from(kind: ErrorKind) -> MyStructError { 57 | MyStructError { 58 | repr: Repr::Simple(kind) 59 | } 60 | } 61 | } 62 | 63 | //此处只是举一个其他crate的Error向我们自定义错误转化的例子。 64 | //other crate `s Error to MyStructError conversion 65 | impl From for MyStructError { 66 | #[inline] 67 | fn from(o: std::io::Error) -> MyStructError { 68 | MyStructError { 69 | repr: Repr::Custom(Box::new(Custom{kind: ErrorKind::Other, error:Box::new(o)})), 70 | } 71 | } 72 | } 73 | 74 | impl Display for MyStructError { 75 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 76 | match self.repr { 77 | Repr::Os(code) => {write!(f, "os error code : {}", code)} 78 | Repr::Custom(ref c) => Debug::fmt(&c, f), 79 | Repr::Simple(kind) => write!(f, "{}", kind.as_str()), 80 | } 81 | } 82 | } 83 | 84 | //自定义错误,不管是enum,还是struct实现,最终都要统一继承实现std::error::Error,这样rust 所有的Error都有一个父亲, 85 | //好处是一个父类型指针就可以指向所有错误类型实现,方便统一管理. 86 | impl std::error::Error for MyStructError { 87 | 88 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 89 | match self.repr { 90 | Repr::Os(..) => None, 91 | Repr::Simple(..) => None, 92 | Repr::Custom(ref c) => c.error.source(), 93 | } 94 | } 95 | 96 | } 97 | 98 | pub fn test() { 99 | 100 | let e1 = MyStructError{repr: Repr::Os(-1)}; 101 | println!("{}",e1); 102 | println!("{}", MyStructError{repr: Repr::Simple(ErrorKind::NotFound)}); 103 | 104 | let other = std::io::Error::new(std::io::ErrorKind::Other, e1); 105 | let e2 = MyStructError { repr: Repr::Custom(Box::new(Custom{kind: ErrorKind::Other, error:Box::new(other)})),}; 106 | println!("{}", e2); 107 | 108 | } 109 | 110 | pub fn get_a_e () -> MyStructError { 111 | 112 | MyStructError{repr: Repr::Os(-1)} 113 | } -------------------------------------------------------------------------------- /rust_my_error/my_struct_error/src/main.rs: -------------------------------------------------------------------------------- 1 | mod error; 2 | 3 | fn main() { 4 | 5 | error::test(); 6 | 7 | if error::ErrorKind::Os == error::get_a_e().kind() { 8 | 9 | println!("os error number: {}", error::get_a_e()); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /rust_my_error/thiserror_t/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_my_error/thiserror_t/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "thiserror_t" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | #特别提醒,如果此处lib name与package的name不一致, 则会导致其他crate引用本crate时失败,找不到! 9 | #crate: anyhow_t`s Cargo.toml 引用本crate的dependencies: thiserror_t = { path = "../thiserror_t"} 10 | #[lib] 11 | #name="tt" 12 | #crate-type=["rlib", "dylib"] 13 | 14 | [dependencies] 15 | thiserror = "1.0.19" 16 | -------------------------------------------------------------------------------- /rust_my_error/thiserror_t/src/count.rs: -------------------------------------------------------------------------------- 1 | use std::io::prelude::*; 2 | use std::io::BufReader; 3 | use crate::error::WordCountError; 4 | 5 | pub fn count_words(input: &mut R) -> Result { 6 | let reader = BufReader::new(input); 7 | let mut wordcount = 0; 8 | for line in reader.lines() { 9 | let line = line.map_err(|source| WordCountError::ReadError { source })?; 10 | //下面注释掉的语句表示,所有其他std::io::Error默认都封装为IOError,除非如上句,自己手动封装为指定高级错误类型。 11 | //for _word in line?.split_whitespace() { //for #[error(transparent)] IOError(#[from] std::io::Error) 12 | for _word in line.split_whitespace() { 13 | wordcount += 1; 14 | } 15 | } 16 | if wordcount == 0 { 17 | return Err(WordCountError::EmptySource); 18 | } 19 | Ok(wordcount) 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /rust_my_error/thiserror_t/src/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | /// WordCountError enumerates all possible errors returned by this library. 4 | #[derive(Error, Debug)] 5 | pub enum WordCountError { 6 | /// Represents an empty source. For example, an empty text file being given 7 | /// as input to `count_words()`. 8 | #[error("Source contains no data")] 9 | EmptySource, 10 | 11 | /// Represents a failure to read from input. 12 | #[error("Read error")] 13 | ReadError { source: std::io::Error }, 14 | 15 | /// Represents all other cases of `std::io::Error`. 16 | #[error(transparent)] 17 | IOError(#[from] std::io::Error), 18 | } 19 | 20 | //对于库的外部使用者只暴露统一的WordCountError, 任何库底层爆出的错误,如:std::io::Error等都会被封装成 21 | //WordCountError中定义的相应高级错误Case。 这样库的用户就可明确地区分出错误出自那个库。 -------------------------------------------------------------------------------- /rust_my_error/thiserror_t/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod error; 2 | mod count; 3 | pub use error::WordCountError; 4 | pub use count::count_words; 5 | 6 | #[cfg(test)] 7 | mod tests { 8 | use crate::count::count_words; 9 | 10 | #[test] 11 | fn count_words_t() { 12 | let mut b = "This string will be read".as_bytes(); 13 | let r = count_words(& mut b); 14 | assert!(r.is_ok()); 15 | assert!(r.unwrap() == 5); 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /rust_result_option/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_result_option/error_propagation_byquestion_mark/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_result_option/error_propagation_byquestion_mark/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "error_propagation_byquestion_mark" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_result_option/error_propagation_byquestion_mark/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::io::Read; 3 | use std::fs::File; 4 | 5 | fn read_username_from_file() -> Result { 6 | 7 | let mut s = String::new(); 8 | File::open("hello.txt")?.read_to_string(&mut s)?; 9 | 10 | Ok(s) 11 | } 12 | 13 | fn main() { 14 | 15 | let r = read_username_from_file(); 16 | println!("{:?}",r ); 17 | } 18 | -------------------------------------------------------------------------------- /rust_result_option/error_propagation_primitive/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /rust_result_option/error_propagation_primitive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "error_propagation" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_result_option/error_propagation_primitive/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::io::Read; 3 | use std::fs::File; 4 | 5 | fn read_username_from_file() -> Result { 6 | 7 | let f = File::open("hello.txt"); 8 | 9 | let mut f = match f { 10 | Ok(file) => file, 11 | Err(e) => return Err(e), 12 | }; 13 | 14 | let mut s = String::new(); 15 | 16 | match f.read_to_string(&mut s) { 17 | Ok(_) => Ok(s), 18 | Err(e) => Err(e), 19 | } 20 | } 21 | 22 | 23 | fn main() { 24 | 25 | let r = read_username_from_file(); 26 | println!("{:?}",r ); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /rust_result_option/rust_primitive/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | 13 | hello.txt 14 | 15 | -------------------------------------------------------------------------------- /rust_result_option/rust_primitive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_primitive" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /rust_result_option/rust_primitive/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::ErrorKind; 3 | 4 | //pub fn open>(path: P) -> Result 5 | 6 | fn main() { 7 | 8 | let f = File::open("hello.txt"); 9 | 10 | let _f = match f { 11 | 12 | Ok(file) => file, 13 | Err(error) => match error.kind() { 14 | 15 | ErrorKind::NotFound => match File::create("hello.txt") { 16 | Ok(fc) => fc, 17 | Err(e) => panic!("Problem creating the file: {:?}", e), 18 | }, 19 | _ => panic!("Problem opening the file: {:?}", error), 20 | }, 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /tokio/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /tokio/hello_world/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /tokio/hello_world/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello_world" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | tokio = { version = "0.2.4", features = ["full"] } -------------------------------------------------------------------------------- /tokio/hello_world/src/main.rs: -------------------------------------------------------------------------------- 1 | use tokio::net::TcpListener; 2 | use tokio::prelude::*; 3 | 4 | #[tokio::main] 5 | async fn main() -> Result<(), Box> { 6 | let mut listener = TcpListener::bind("127.0.0.1:8080").await?; 7 | 8 | loop { 9 | let (mut socket, _) = listener.accept().await?; 10 | 11 | tokio::spawn(async move { 12 | let mut buf = [0; 1024]; 13 | 14 | // In a loop, read data from the socket and write the data back. 15 | loop { 16 | let n = match socket.read(&mut buf).await { 17 | // socket closed 18 | Ok(n) if n == 0 => return, 19 | Ok(n) => n, 20 | Err(e) => { 21 | eprintln!("failed to read from socket; err = {:?}", e); 22 | return; 23 | } 24 | }; 25 | 26 | // Write the data back 27 | if let Err(e) = socket.write_all(&buf[0..n]).await { 28 | eprintln!("failed to write to socket; err = {:?}", e); 29 | return; 30 | } 31 | } 32 | }); 33 | } 34 | } 35 | 36 | //test command on linux : nc localhost 8080 37 | -------------------------------------------------------------------------------- /tokio/select_macro/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /tokio/select_macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "select_macro" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | tokio = { version = "0.2.13", features = ["full"] } -------------------------------------------------------------------------------- /tokio/select_macro/src/main.rs: -------------------------------------------------------------------------------- 1 | use tokio::time::{self, Duration,delay_for,timeout}; 2 | use tokio::stream::{self, StreamExt}; 3 | use tokio::sync::{oneshot,mpsc,broadcast}; 4 | use tokio::task; 5 | 6 | async fn some_computation(input: u32) -> String { 7 | format!("the result of computation {}", input) 8 | } 9 | 10 | async fn some_async_work() { 11 | // do work 12 | delay_for(Duration::from_millis(1)).await; 13 | 14 | } 15 | 16 | #[tokio::main] 17 | async fn main() { 18 | //time::delay 19 | let mut delay = time::delay_for(Duration::from_millis(5)); 20 | //stream 21 | let mut stream1 = stream::iter(vec![1, 2, 3]); 22 | //oneshot 23 | let (tx1, mut rx1) = oneshot::channel(); 24 | tokio::spawn(async move { 25 | tx1.send("first").unwrap(); 26 | }); 27 | let mut a = None; 28 | //mpsc 29 | let (mut tx2, mut rx2) = mpsc::channel(100); 30 | tokio::spawn(async move { 31 | for i in 0..10 { 32 | let res = some_computation(i).await; 33 | tx2.send(res).await.unwrap(); 34 | } 35 | }); 36 | let mut done = false; 37 | //broadcast 38 | let (tx3, mut rx3) = broadcast::channel(16); 39 | let mut rx4 = tx3.subscribe(); 40 | tx3.send(10).unwrap(); 41 | tx3.send(20).unwrap(); 42 | tokio::spawn(async move { 43 | assert_eq!(rx4.recv().await.unwrap(), 10); 44 | assert_eq!(rx4.recv().await.unwrap(), 20); 45 | }); 46 | //time::interval 47 | let mut interval = time::interval(Duration::from_millis(2)); 48 | //join handle 49 | let mut join_done = false; 50 | let mut join_handle: task::JoinHandle = task::spawn(async { 51 | // some work here 52 | delay_for(Duration::from_millis(1)).await; 53 | 88 54 | }); 55 | //time::timeout 56 | //let mut to = timeout(Duration::from_millis(5), some_async_work()); 57 | 58 | loop { 59 | tokio::select! { 60 | _ = &mut delay => { 61 | println!("delay reached"); 62 | break; 63 | }, 64 | /* _ = &mut to => { 65 | println!("operation timed out"); 66 | break; 67 | },*/ 68 | ret_code=&mut join_handle ,if !join_done => { 69 | join_done = true; 70 | println!("join handle case: {:?}", ret_code); 71 | }, 72 | _= interval.tick() => { 73 | println!("operation interval"); 74 | }, 75 | _ = some_async_work() => { 76 | println!("operation completed"); 77 | //delay_for(Duration::from_millis(100000)).await; 78 | }, 79 | Some(v) = stream1.next() => { println!("stream: {}", v);}, 80 | v1 = (&mut rx1), if a.is_none() => { 81 | println!("oneshot : {:?}", v1);a = v1.ok(); 82 | }, 83 | v2 = rx2.recv(), if !done => { 84 | println!("mpsc: {:?}", v2); 85 | if v2.is_none() { done = true; } 86 | }, 87 | v3 = rx3.recv() => { 88 | println!("broadcast: {:?}", v3); 89 | }, 90 | else => { 91 | println!("not match"); 92 | }, 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /tokio/tokio_check_result_error/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /tokio/tokio_check_result_error/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tokio_hello_world" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | tokio = { version = "0.2.6", features = ["full"] } 11 | -------------------------------------------------------------------------------- /tokio/tokio_check_result_error/src/main.rs: -------------------------------------------------------------------------------- 1 | use tokio::net::TcpListener; 2 | use tokio::prelude::*; 3 | 4 | #[tokio::main] 5 | async fn main() -> Result<(), Box> { 6 | 7 | let mut listener = TcpListener::bind("127.0.0.1:8080").await?; 8 | 9 | loop { 10 | let (mut socket, _) = listener.accept().await?; 11 | 12 | tokio::spawn(async move { 13 | let mut buf = [0; 1024]; 14 | 15 | // In a loop, read data from the socket and write the data back. 16 | loop { 17 | let n = match socket.read(&mut buf).await { 18 | // socket closed 19 | Ok(n) if n == 0 => return, 20 | Ok(n) => n, 21 | Err(e) => { 22 | eprintln!("failed to read from socket; err = {:?}", e); 23 | return; 24 | } 25 | }; 26 | 27 | // Write the data back 28 | if let Err(e) = socket.write_all(&buf[0..n]).await { 29 | eprintln!("failed to write to socket; err = {:?}", e); 30 | return; 31 | } 32 | } 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /toml_parser/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /toml_parser/README.md: -------------------------------------------------------------------------------- 1 | # TOML配置文件格式Rust解析代码 2 | 3 | * Rust Example Code 4 | 5 | > [Reference] 6 | > 7 | > `https://github.com/alexcrichton/toml-rs` 8 | > 9 | > `https://serde.rs/derive.html` 10 | > 11 | > `https://crates.io/crates/serde` 12 | > 13 | > > 第一个链接是一个Rust Crate to parser toml。没什么可说的, 哈哈, 直接来两个example code. 14 | > > 15 | > > 代码不复杂,看一看就好,容易上手!对于更加复杂的用法,请阅读上面链接中的代码和文章,我就不再啰嗦了!为什么不深入分析一下呢!因为例子中涉及到的用法case够用了,其他用法,比如:toml to json, parser rust enum 等,toml-rs crate也已经给出了简明的代码例子!所以我就不再多说了。我的想法,配置文件要尽可能地简单明了,千万别整得很复杂!简单易用,直截了当,别有太多弯弯绕!最好能自说明自描述!这样运维的兄弟能好过些! 16 | > > 17 | > > serde 是rust序列化反序列化crate, 有兴趣可以深入研究一下。 18 | 19 | 20 | 21 | * About Me 22 | 23 | > RUST学习随笔,如有谬误,尽请指正,谢谢。 24 | 25 | > 作者:心尘了 26 | 27 | > email: [285779289@qq.com](mailto:285779289@qq.com) 28 | 29 | > 微信:justice_forever_123 30 | 31 | -------------------------------------------------------------------------------- /toml_parser/toml_1/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /toml_parser/toml_1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "toml_1" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | toml = "0.5" 11 | serde = { version = "1.0.102", features = ["derive"] } 12 | -------------------------------------------------------------------------------- /toml_parser/toml_1/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | use serde::{ Deserialize}; 4 | 5 | /// This is what we're going to decode into. Each field is optional, meaning 6 | /// that it doesn't have to be present in TOML. 7 | #[derive(Debug, Deserialize)] 8 | struct Config { 9 | global_string: Option, 10 | global_integer: Option, 11 | server: Option, 12 | peers: Option>, 13 | } 14 | 15 | /// Sub-structs are decoded from tables, so this will decode from the `[server]` 16 | /// table. 17 | /// 18 | /// Again, each field is optional, meaning they don't have to be present. 19 | #[derive(Debug, Deserialize)] 20 | struct ServerConfig { 21 | ip: Option, 22 | port: Option, 23 | } 24 | 25 | #[derive(Debug, Deserialize)] 26 | struct PeerConfig { 27 | ip: Option, 28 | port: Option, 29 | } 30 | 31 | fn main() { 32 | let toml_str = r#" 33 | global_string = "test" 34 | global_integer = 5 35 | [server] 36 | ip = "127.0.0.1" 37 | port = 80 38 | [[peers]] 39 | ip = "127.0.0.1" 40 | port = 8080 41 | [[peers]] 42 | ip = "127.0.0.1" 43 | "#; 44 | 45 | let decoded: Config = toml::de::from_str(toml_str).unwrap(); 46 | println!("{:#?}", decoded); 47 | } 48 | -------------------------------------------------------------------------------- /toml_parser/toml_2/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /toml_parser/toml_2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "toml_2" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | toml = "0.5" 11 | serde = { version = "1.0.102", features = ["derive"] } 12 | -------------------------------------------------------------------------------- /toml_parser/toml_2/src/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /too_many_lists/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /too_many_lists/Readme.md: -------------------------------------------------------------------------------- 1 | # Too -many-lists学习摘要 2 | 3 | - IterMute实现要点难点 4 | 5 | ```rust 6 | ... 7 | pub struct List { 8 | head: Link, 9 | } 10 | 11 | type Link = Option>>; 12 | 13 | struct Node { 14 | elem: T, 15 | next: Link, 16 | } 17 | ... 18 | ... 19 | ... 20 | pub struct IterMut<'a, T> { 21 | next: Option<&'a mut Node>, 22 | } 23 | 24 | //https://rust-unofficial.github.io/too-many-lists/second-iter-mut.html 25 | //IterMut之所以可以工作, 原文给出了2个理由: 26 | //1. 通过take确实保证了&mut型引用的唯一排他性。 27 | //2. https://doc.rust-lang.org/nomicon/borrow-splitting.html 28 | impl List { 29 | pub fn iter_mut(&mut self) -> IterMut<'_, T> { 30 | //this works coz: Rust understands that it's ok to shard a mutable reference into the subfields of the pointed-to struct, 31 | //because there's no way to "go back up", and they're definitely disjoint. 32 | IterMut { next: self.head.as_mut().map(|node| &mut **node) } 33 | } 34 | } 35 | 36 | impl<'a, T> Iterator for IterMut<'a, T> { 37 | type Item = &'a mut T; 38 | 39 | fn next(&mut self) -> Option { 40 | self.next.take().map(|node| {//此处next被take收割了, 保证了map外部无法再访问到!从而确保&mut引用排他性。 41 | //this works coz: Rust understands that it's ok to shard a mutable reference into the subfields of the pointed-to struct, 42 | // because there's no way to "go back up", and they're definitely disjoint. 43 | //We take the Option<&mut> so we have exclusive access to the mutable reference. 44 | //No need to worry about someone looking at it again. 45 | self.next = node.next.as_mut().map(|node| &mut **node); 46 | &mut node.elem 47 | }) 48 | } 49 | ... 50 | ... 51 | ``` 52 | 53 | > 上面的IterMute代码之所以可以工作,too-many-lists作者给出两点理由: 54 | > 55 | > 1. 通过take确实保证了&mut型引用的唯一排他性。 56 | > 2. Rust知道可以同时借用结构的不相交字段,如下面代码例子。 57 | 58 | 59 | 60 | ```rust 61 | //https://doc.rust-lang.org/nomicon/borrow-splitting.html 62 | //https://rust-unofficial.github.io/too-many-lists/second-iter-mut.html 63 | 64 | #[derive(Debug)] 65 | struct Foo { 66 | a: i32, 67 | b: i32, 68 | c: i32, 69 | } 70 | 71 | fn main() { 72 | let mut x = Foo {a: 0, b: 0, c: 0}; 73 | let xx =&mut x; 74 | let a = &mut x.a; 75 | let b = &mut x.b; 76 | let c = &x.c; 77 | *b += 1; 78 | let c2 = &x.c; 79 | *a += 10; 80 | println!("{} {} {} {}", a, b, c, c2); 81 | //println!("whole struct: {:?}", xx); 82 | //Rust 编译器很聪明,允许你分别持有指向结构体子成员的可变引用,因为Rust编译器知道他们彼此没有交集,是安全的。 83 | //但是`引用xx`与后续声明的其他引用有交集,很明显struct整体当然包含其子成员!Rust铁律:允许多只读,排他写!所以不安全! 84 | //但是Rust编译器很聪明,只要`引用xx`无处使用就是安全的!所以注释掉println!就OK, 否则报错:` cannot borrow `x.a` as mutable more than once at a time` 85 | 86 | } 87 | ``` 88 | 89 | > too-many-lists中亮点很多,非常值得学习的Rust著作, 而IterMute的实现方法更是创意非凡!不用unsafe也可有这么好的trick! 绝对让人眼前一亮!灵光一闪!值得反复学习。例子代码位置:`https://github.com/yujinliang/rust_learn/tree/master/too_many_lists` 90 | 91 | 92 | 93 | 94 | 95 | - Author 96 | 97 | > 作者:心尘了 98 | > 99 | > email: [285779289@qq.com](mailto:285779289@qq.com) 100 | > 101 | > git: https://github.com/yujinliang 102 | > 103 | > `水平有限,万望海涵,指导` 104 | 105 | 106 | 107 | 108 | 109 | - Reference 110 | 111 | `https://doc.rust-lang.org/nomicon/borrow-splitting.html` 112 | 113 | `https://rust-unofficial.github.io/too-many-lists/second-iter-mut.html` 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /too_many_lists/lists/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /too_many_lists/lists/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lists" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /too_many_lists/lists/src/first.rs: -------------------------------------------------------------------------------- 1 | use std::mem; 2 | 3 | pub struct List { 4 | head: Link, 5 | } 6 | 7 | enum Link { 8 | Empty, 9 | More(Box), 10 | } 11 | 12 | struct Node { 13 | elem: i32, 14 | next: Link, 15 | } 16 | 17 | impl List { 18 | pub fn new() -> Self { 19 | List { head: Link::Empty } 20 | } 21 | 22 | pub fn push(&mut self, elem: i32) { 23 | let new_node = Node { 24 | elem: elem, 25 | next: mem::replace(&mut self.head, Link::Empty), 26 | }; 27 | self.head = Link::More(Box::new(new_node)); 28 | } 29 | 30 | pub fn pop(&mut self) -> Option { 31 | match mem::replace(&mut self.head, Link::Empty) { 32 | Link::Empty => None, 33 | Link::More(node) => { 34 | self.head = node.next; 35 | Some(node.elem) 36 | } 37 | } 38 | } 39 | } 40 | 41 | impl Drop for List { 42 | fn drop(&mut self) { 43 | let mut cur_link = mem::replace(&mut self.head, Link::Empty); 44 | 45 | while let Link::More(mut boxed_node) = cur_link { 46 | cur_link = mem::replace(&mut boxed_node.next, Link::Empty); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /too_many_lists/lists/src/third.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | pub struct List { 4 | head: Link, 5 | } 6 | 7 | type Link = Option>>; 8 | 9 | struct Node { 10 | elem: T, 11 | next: Link, 12 | } 13 | 14 | impl List { 15 | pub fn new() -> Self { 16 | List { head: None } 17 | } 18 | 19 | pub fn append(&self, elem: T) -> List { 20 | List { head: Some(Arc::new(Node { 21 | elem: elem, 22 | next: self.head.clone(), 23 | }))} 24 | } 25 | 26 | pub fn tail(&self) -> List { 27 | List { head: self.head.as_ref().and_then(|node| node.next.clone()) } 28 | } 29 | 30 | pub fn head(&self) -> Option<&T> { 31 | self.head.as_ref().map(|node| &node.elem ) 32 | } 33 | 34 | } 35 | 36 | pub struct Iter<'a, T> { 37 | next: Option<&'a Node>, 38 | } 39 | 40 | impl List { 41 | pub fn iter(&self) -> Iter<'_, T> { 42 | Iter { next: self.head.as_ref().map(|node| &**node) } 43 | } 44 | } 45 | 46 | impl<'a, T> Iterator for Iter<'a, T> { 47 | type Item = &'a T; 48 | 49 | fn next(&mut self) -> Option { 50 | self.next.map(|node| { 51 | self.next = node.next.as_ref().map(|node| &**node); 52 | &node.elem 53 | }) 54 | } 55 | } 56 | //???? 57 | impl Drop for List { 58 | fn drop(&mut self) { 59 | let mut head = self.head.take(); 60 | while let Some(node) = head { 61 | if let Ok(mut node) = Arc::try_unwrap(node) { 62 | head = node.next.take(); 63 | } else { 64 | break; 65 | } 66 | } 67 | } 68 | } 69 | //A type is Send if it's safe to move to another thread. A type is Sync if it's safe to share between multiple threads. 70 | -------------------------------------------------------------------------------- /too_many_lists/splitting_borrows/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /too_many_lists/splitting_borrows/mut_ref_to_struct_subfield/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /too_many_lists/splitting_borrows/mut_ref_to_struct_subfield/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mut_ref_to_struct_subfield" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 | -------------------------------------------------------------------------------- /too_many_lists/splitting_borrows/mut_ref_to_struct_subfield/src/main.rs: -------------------------------------------------------------------------------- 1 | //https://doc.rust-lang.org/nomicon/borrow-splitting.html 2 | //https://rust-unofficial.github.io/too-many-lists/second-iter-mut.html 3 | 4 | #[derive(Debug)] 5 | struct Foo { 6 | a: i32, 7 | b: i32, 8 | c: i32, 9 | } 10 | 11 | fn main() { 12 | let mut x = Foo {a: 0, b: 0, c: 0}; 13 | let xx =&mut x; 14 | let a = &mut x.a; 15 | let b = &mut x.b; 16 | let c = &x.c; 17 | *b += 1; 18 | let c2 = &x.c; 19 | *a += 10; 20 | println!("{} {} {} {}", a, b, c, c2); 21 | //println!("whole struct: {:?}", xx); 22 | //Rust 编译器很聪明,允许你分别持有指向结构体子成员的可变引用,因为Rust编译器知道他们彼此没有交集,是安全的。 23 | //但是`引用xx`与后续声明的其他引用有交集,很明显struct整体当然包含其子成员!Rust铁律:允许多只读,排他写!所以不安全! 24 | //但是Rust编译器很聪明,只要`引用xx`无处使用就是安全的!所以注释掉println!就OK, 否则报错:` cannot borrow `x.a` as mutable more than once at a time` 25 | 26 | } 27 | -------------------------------------------------------------------------------- /unsafe_collect/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/README.md: -------------------------------------------------------------------------------- 1 | # `Rust FFI (C vs Rust)学习杂记` 2 | 3 | 正文请看: 4 | 5 | 文档:Rust FFI (C vs Rust)学习杂记.note 6 | 链接:https://note.youdao.com/s/5zE9TlxF 7 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/Rust FFI (C vs Rust)学习杂记.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yujinliang/rust_learn/e641dd6925cf0ba4cd8fd6edc8dcb20e4b18e956/unsafe_collect/ffi/Rust FFI (C vs Rust)学习杂记.pdf -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yujinliang/rust_learn/e641dd6925cf0ba4cd8fd6edc8dcb20e4b18e956/unsafe_collect/ffi/c2rust/README.md -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/box_t/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/box_t/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "box_t" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 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 = "box" 11 | crate-type = ["cdylib", "staticlib"] 12 | 13 | 14 | [build-dependencies] 15 | 16 | 17 | 18 | [dependencies] 19 | 20 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/box_t/src/c_call_rust.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Returns ownership to the caller. 4 | struct Foo* foo_new(void); 5 | 6 | // Returns ownership to the caller. 7 | struct Foo* foo_new_option(void); 8 | 9 | // Takes ownership from the caller; no-op when invoked with NULL. 10 | void foo_delete(struct Foo*); 11 | 12 | int main() { 13 | foo_delete(foo_new()); 14 | foo_delete(NULL); 15 | foo_delete(foo_new_option()); 16 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/box_t/src/lib.rs: -------------------------------------------------------------------------------- 1 | 2 | #[repr(C)] 3 | #[derive(Debug)] 4 | pub struct Foo; 5 | 6 | #[no_mangle] 7 | pub extern "C" fn foo_new() -> Box { 8 | Box::new(Foo) 9 | } 10 | 11 | #[no_mangle] 12 | pub extern "C" fn foo_new_option() -> Option> { 13 | Some(Box::new(Foo)) 14 | } 15 | 16 | // C`s NULL pointer is equeal to Option::None. 17 | #[no_mangle] 18 | pub extern "C" fn foo_delete(f: Option>) { 19 | println!("{:?}",f ); 20 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/closure_as_callback/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/closure_as_callback/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "closure_as_callback" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 5 | edition = "2018" 6 | build="build.rs" 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | 11 | [build-dependencies] 12 | cc = "1.0.54" -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/closure_as_callback/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | cc::Build::new() 3 | .file("src/closure.c") 4 | .compile("closure"); 5 | println!("cargo:rerun-if-changed=src/closure.c"); 6 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/closure_as_callback/src/closure.c: -------------------------------------------------------------------------------- 1 | typedef void (*AddCallback)(int result, void *user_data); 2 | 3 | void better_add_two_numbers(int a, int b, AddCallback cb, void *user_data) 4 | { 5 | int result = a + b; 6 | cb(result, user_data); 7 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/closure_as_callback/src/closure.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::{c_int, c_void}; 2 | 3 | pub type AddCallback = unsafe extern "C" fn(c_int, *mut c_void); 4 | 5 | extern "C" { 6 | fn better_add_two_numbers( 7 | a: c_int, 8 | b: c_int, 9 | cb: AddCallback, 10 | user_data: *mut c_void, 11 | ); 12 | } 13 | 14 | pub fn add_two_numbers(a: i32, b: i32, on_result_calculated: F) 15 | where 16 | F: FnMut(i32), 17 | { 18 | unsafe { 19 | let mut closure = on_result_calculated; 20 | let cb = get_trampoline(&closure); 21 | 22 | better_add_two_numbers(a, b, cb, &mut closure as *mut _ as *mut c_void); 23 | } 24 | } 25 | //C语言只认识函数指针, 而Rust语言的闭包只是个语法糖,即一个匿名结构体实现了Fn/FnMut/FnOnce,从而实现函数调用。 26 | // trampoline中文蹦床的意思,很是贴切!首先从Rust传递回调函数指针给C, C代码运行相应逻辑后调用回调函数, 从C返回Rust! 27 | //核心思想: 从C回到Rust语言环境, Rust语言当然认识自己的闭包啦!所以可以直接调用。 28 | //注意: 闭包被当做user_data来回传递, 且闭包的声明与FnMut(c_int)必须相同。 29 | //所以FFI的核心原则:求同存异!各找各妈! 30 | unsafe extern "C" fn trampoline(result: c_int, user_data: *mut c_void) 31 | where 32 | F: FnMut(c_int), 33 | { 34 | let user_data = &mut *(user_data as *mut F); //此处并未对user_data做类型检查,直接转换为F, 若是类型不匹配则panic。 35 | user_data(result); //所以要求闭包声明必须和F一致。 36 | } 37 | 38 | //下面这个getter的使命就是帮助Rust编译器实例化fn trampoline。 39 | //因为fn trampoline自己的函数参数都没有用到F泛型参数, 故此Rust没有足够的信息推导出F的具体类型, 40 | //所以下面的getter提供了F的具体类型信息。 41 | fn get_trampoline(_closure: &F) -> AddCallback 42 | where 43 | F: FnMut(c_int), 44 | { 45 | trampoline:: 46 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/closure_as_callback/src/main.rs: -------------------------------------------------------------------------------- 1 | //reference: http://adventures.michaelfbryan.com/posts/rust-closures-in-ffi/?utm_source=reddit&utm_medium=social&utm_campaign=rust-closures-in-ffi 2 | use std::os::raw::{c_int}; 3 | mod closure; 4 | use closure::add_two_numbers; 5 | 6 | fn main() { 7 | let mut got = 0; 8 | let closure = |result: c_int| { 9 | got = result; 10 | println!("cb: {}", result); 11 | }; 12 | add_two_numbers(1, 2, closure); 13 | println!("got: {}", got); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/simple/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/simple/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simple" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 5 | edition = "2018" 6 | build = "build.rs" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | 12 | 13 | [build-dependencies] 14 | cc = "1.0.54" -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/simple/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | cc::Build::new() 3 | .file("src/simple.c") 4 | .compile("simple"); 5 | println!("cargo:rerun-if-changed=src/simple.c"); 6 | 7 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/simple/src/main.rs: -------------------------------------------------------------------------------- 1 | // src/main.rs 2 | //reference: https://github.com/Michael-F-Bryan/rust-closures-and-ffi 3 | //reference:http://adventures.michaelfbryan.com/posts/rust-closures-in-ffi/?utm_source=reddit&utm_medium=social&utm_campaign=rust-closures-in-ffi 4 | 5 | mod simple; 6 | use simple::{ simple_add_two_numbers, two_numbers_added_cb}; 7 | 8 | fn main() { 9 | let a = 1; 10 | let b = 2; 11 | 12 | println!("Adding {} and {}", a, b); 13 | 14 | unsafe { 15 | simple_add_two_numbers(1, 2, two_numbers_added_cb); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/simple/src/simple.c: -------------------------------------------------------------------------------- 1 | // src/simple.c 2 | 3 | typedef void (*AddCallback)(int result); 4 | 5 | void simple_add_two_numbers(int a, int b, AddCallback cb) 6 | { 7 | int result = a + b; 8 | cb(result); 9 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/c2rust/simple/src/simple.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::c_int; 2 | 3 | pub type AddCallback = unsafe extern "C" fn(c_int); 4 | 5 | extern "C" { 6 | pub fn simple_add_two_numbers(a: c_int, b: c_int, cb: AddCallback); 7 | } 8 | 9 | 10 | pub unsafe extern "C" fn two_numbers_added_cb(result: c_int) { 11 | println!("Got {}!", result); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yujinliang/rust_learn/e641dd6925cf0ba4cd8fd6edc8dcb20e4b18e956/unsafe_collect/ffi/rust2c/README.md -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/build_c_lib_by_gcc/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/build_c_lib_by_gcc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "build_c_lib_by_gcc" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 5 | edition = "2018" 6 | build="build.rs" #关键点,启用构建脚本build.rs。 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/build_c_lib_by_gcc/build.rs: -------------------------------------------------------------------------------- 1 | // build.rs 2 | 3 | use std::process::Command; 4 | use std::env; 5 | use std::path::Path; 6 | 7 | fn main() { 8 | let out_dir = env::var("OUT_DIR").unwrap(); 9 | 10 | //下面直接调用gcc生成C库,并未考虑跨平台问题,切切! 11 | Command::new("gcc").args(&["src/hello.c", "-c", "-fPIC", "-o"]) 12 | .arg(&format!("{}/hello.o", out_dir)) 13 | .status().unwrap(); 14 | Command::new("ar").args(&["crus", "libhello.a", "hello.o"]) 15 | .current_dir(&Path::new(&out_dir)) 16 | .status().unwrap(); 17 | //上面的代码很直观,就是编译C 代码,构建静态库的命令行, 生成的C库存放到"OUT_DIR"环境变量指定的目录。 18 | //其实您完全可以举一反三, 通过编写build.rs构建脚本,可以调用诸如gcc, ar, make,cmake等C/C++构建工具为Rust工程提前生成C库。 19 | //我想您能想到, build.rs肯定是在开始构建编译Rust工程之前执行的!用于预处理。 20 | 21 | //下面很关键,配置cargo的官方指定方法之一 ! 22 | println!("cargo:rustc-link-search=native={}", out_dir); //配置C库的搜索路径,相当于rustc -L 23 | println!("cargo:rustc-link-lib=static=hello"); //配置需要链接的C库名, 相当于rustc -l 24 | println!("cargo:rerun-if-changed=src/hello.c"); //告诉cargo工具,只有当“src/hello.c”这个文件发生变化时,才重新执行build.rs脚本。 25 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/build_c_lib_by_gcc/src/hello.c: -------------------------------------------------------------------------------- 1 | // src/hello.c 2 | 3 | #include 4 | 5 | void hello() { 6 | printf("Hello, World!\n"); 7 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/build_c_lib_by_gcc/src/main.rs: -------------------------------------------------------------------------------- 1 | //注意:此处没有使用#[link]属性指定需要链接的C库, 因为我们在build.rs构建脚本中已经设定好了, 2 | //rust cargo 知道该去链接那个C库。 3 | extern "C" { fn hello(); } 4 | 5 | fn main() { 6 | unsafe { hello(); } 7 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/cc_auto_build_c_lib/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/cc_auto_build_c_lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cc_auto_build_c_lib" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 5 | edition = "2018" 6 | build="build.rs" 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [build-dependencies] 10 | cc = "1.0.53" 11 | 12 | [dependencies] 13 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/cc_auto_build_c_lib/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | //the cc crate专门自动构建编译C/C++ code, 3 | //如:自动检测:系统平台, 硬件架构, 自动选择相应编译器,设定各种编译参数, 4 | //自动设定相关环境变量, 如:cargo相关环境变量, 自动将编译好的C库保存到“OUT_DIR” 5 | //所以cc可以自动帮你搞定诸如:交叉编译, 跨平台。 6 | //cargo build -vv 可以看到已经自动设定的各种构建参数。 7 | //详情请参考:`https://docs.rs/cc/1.0.53/cc/` 8 | cc::Build::new() 9 | .file("src/hello.c") 10 | .compile("hello"); 11 | println!("cargo:rerun-if-changed=src/hello.c"); //告诉cargo 只有当src/hello.c发生变化时,才重新执行build.rs脚本。 12 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/cc_auto_build_c_lib/src/hello.c: -------------------------------------------------------------------------------- 1 | // src/hello.c 2 | 3 | #include 4 | 5 | void hello() { 6 | printf("Hello, World!\n"); 7 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/cc_auto_build_c_lib/src/main.rs: -------------------------------------------------------------------------------- 1 | //注意:此处没有使用#[link]属性指定需要链接的C库, 因为我们在build.rs构建脚本中已经设定好了, 2 | //rust cargo 知道该去链接那个C库。 3 | extern "C" { fn hello(); } 4 | 5 | fn main() { 6 | unsafe { hello(); } 7 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/code_generate/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/code_generate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "code_generate" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 5 | edition = "2018" 6 | build="build.rs" # 关键点,启用构建脚本。 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/code_generate/build.rs: -------------------------------------------------------------------------------- 1 | // build.rs 2 | 3 | use std::env; 4 | use std::fs; 5 | use std::path::Path; 6 | 7 | fn main() { 8 | //"OUT_DIR" 告诉cargo 此build脚本的output应该存放到什么位置。 9 | let out_dir = env::var_os("OUT_DIR").unwrap(); 10 | let dest_path = Path::new(&out_dir).join("hello.rs"); 11 | fs::write( 12 | &dest_path, 13 | "pub fn message() -> &'static str { 14 | \"Hello, World!\" 15 | } 16 | " 17 | ).unwrap(); 18 | 19 | //注意哟:这不是普通的print呀, 这是配置cargo的一种官方方法。 20 | //“rerun-if-changed”是cargo 指令,下面代码的意思是:只有当build.rs脚本文件发生变化时,才重新执行build.rs, 21 | //否则默认只要package里的文件发生变化,就re-run build.rs。 22 | println!("cargo:rerun-if-changed=build.rs"); 23 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/code_generate/src/main.rs: -------------------------------------------------------------------------------- 1 | //关键点:此行宏代码将build.rs生成的代码文件包含进来加入编译。 2 | include!(concat!(env!("OUT_DIR"), "/hello.rs")); 3 | 4 | fn main() { 5 | println!("{}", message()); 6 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/conditional_compilation/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/conditional_compilation/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "conditional_compilation" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 5 | edition = "2018" 6 | build="build.rs" 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | 10 | [features] 11 | default = ["foo_1"] # cargo build /run 默认开启的feature。 12 | foo_1 = [] #定义一个feature。 13 | foo_2 = [] 14 | foo_3 = [] # 方括号中列出此feature依赖的其他feature, 逗号分割。 15 | 16 | #cargo build/run --features "foo_2" 17 | #cargo build/run #默认开启default feature 18 | #cargo run --features "foo_2 foo_3" 19 | 20 | [dependencies] 21 | 22 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/conditional_compilation/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rustc-cfg=os2"); 3 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/conditional_compilation/src/main.rs: -------------------------------------------------------------------------------- 1 | #[cfg(os1)] 2 | fn hello() { 3 | println!("os1 hello"); 4 | } 5 | 6 | #[cfg(os2)] 7 | fn hello() { 8 | println!("os2 hello"); 9 | } 10 | 11 | #[cfg(os3)] 12 | fn hello() { 13 | println!("o3 hello"); 14 | } 15 | 16 | #[cfg(feature = "foo_1")] 17 | fn foo_1() { 18 | println!("foo_1"); 19 | } 20 | 21 | #[cfg(feature = "foo_2")] 22 | fn foo_2() { 23 | println!("foo_2"); 24 | } 25 | 26 | #[cfg(feature = "foo_3")] 27 | fn foo_3() { 28 | println!("foo_3"); 29 | } 30 | 31 | fn foo() { 32 | if cfg!(feature = "foo_1") { 33 | println!("foo_1"); 34 | } 35 | if cfg!(feature = "foo_2") { 36 | println!("foo_2"); 37 | } 38 | if cfg!(feature = "foo_3") { 39 | println!("foo_3"); 40 | } 41 | } 42 | 43 | fn main() { 44 | hello(); 45 | //注意宏cfg!(predicate) , 在编译时评估predicate的真假, 即true/false, 然后返回结果。 46 | let machine_kind = if cfg!(unix) { 47 | "unix" 48 | } else if cfg!(windows) { 49 | "windows" 50 | } else { 51 | "unknown" 52 | }; 53 | 54 | println!("I'm running on a {} machine!", machine_kind); 55 | 56 | foo(); 57 | } 58 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/manual_build_1/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/manual_build_1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "manual_build_1" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | #RUSTFLAGS='-L .' cargo run 9 | 10 | 11 | [dependencies] 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/manual_build_1/src/main.rs: -------------------------------------------------------------------------------- 1 | //RUSTFLAGS='-L .' cargo run 2 | //-L 用于告诉rustc 库位置。 3 | 4 | use std::os::raw::c_int; //(1) 必须使用rust and c都认识的数据类型。 5 | 6 | //(2) 这个rust属性用于按名指定链接库,默认链接动态库,除非kind设定static指定链接静态库。 7 | #[link(name="test")] 8 | //#[link(name = "test", kind = "static")] 9 | 10 | //(3) 申明外部函数遵守C语言函数调用规约。 11 | extern "C" { 12 | fn add(a: c_int, b: c_int) -> c_int; 13 | } 14 | 15 | fn main() { 16 | //(4) Rust 规定,只允许在unsafe块中调用FFI extern fn. 17 | let r = unsafe{add(2, 3)}; 18 | println!("{}", r); 19 | } 20 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/manual_build_1/test.c: -------------------------------------------------------------------------------- 1 | // gcc -c -Wall -Werror -fpic test.c //for dynamic library 2 | //gcc -c test.c //for static library. 3 | //ar rcs libtest.a test.o //for static library 4 | 5 | int add(int a, int b) { 6 | return a +b; 7 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/write_c_in_rust/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | 3 | Cargo.lock 4 | 5 | test/test 6 | 7 | sparrow.test 8 | 9 | prof.cpu 10 | 11 | callgrap.pdf 12 | -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/write_c_in_rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "write_c_in_rust" 3 | version = "0.1.0" 4 | authors = ["yujinliang <285779289@qq.com>"] 5 | edition = "2018" 6 | build = "build.rs" 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | cpp = "0.5.4" 11 | 12 | 13 | [build-dependencies] 14 | cpp_build = "0.5.4" -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/write_c_in_rust/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | cpp_build::build("src/main.rs"); 3 | } -------------------------------------------------------------------------------- /unsafe_collect/ffi/rust2c/write_c_in_rust/src/main.rs: -------------------------------------------------------------------------------- 1 | use cpp::*; 2 | 3 | cpp!{{ 4 | #include 5 | }} 6 | 7 | fn add(a: i32, b: i32) -> i32 { 8 | unsafe { 9 | cpp!([a as "int32_t", b as "int32_t"] -> i32 as "int32_t" { 10 | printf("adding %d and %d\n", a, b); 11 | return a + b; 12 | }) 13 | } 14 | } 15 | 16 | fn main() { 17 | println!("{}", add(1, 7)); 18 | } 19 | --------------------------------------------------------------------------------