├── 27-bevy_snake ├── .gitignore ├── .cargo │ └── config.toml ├── snake01_beginning │ ├── src │ │ └── main.rs │ └── Cargo.toml ├── README.md ├── snake02_window │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake04_snakemove │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake06_grid │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake09_foodspawning │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake03_snakehead │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake05_snakecontrol │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake07_moveongrid │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake08_configwindow │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake10_foodtimer │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake11_headadvance │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake12_segments │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake13_attachtail │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── snake14_eatandgrow │ ├── Cargo.toml │ └── src │ │ └── main.rs └── snake15_hitting │ └── Cargo.toml ├── 30-ffi ├── bigint-pyo3 │ ├── .gitignore │ ├── fib_rust.py │ ├── Cargo.toml │ ├── fib.py │ ├── pyproject.toml │ ├── src │ │ └── lib.rs │ └── Cargo.lock ├── c_call_rust │ ├── run_c.sh │ ├── compile_c.sh │ ├── call_rust │ ├── src │ │ └── lib.rs │ ├── call_rust.c │ ├── Cargo.lock │ └── Cargo.toml ├── word-count │ ├── MANIFEST.in │ ├── cargo-generate.toml │ ├── __pycache__ │ │ └── noxfile.cpython-310.pyc │ ├── tests │ │ ├── __pycache__ │ │ │ └── test_word_count.cpython-310-pytest-7.4.3.pyc │ │ └── test_word_count.py │ ├── .template │ │ ├── pre-script.rhai │ │ ├── pyproject.toml │ │ └── Cargo.toml │ ├── Cargo.toml │ ├── noxfile.py │ ├── word_count │ │ └── __init__.py │ ├── pyproject.toml │ ├── README.md │ ├── src │ │ └── lib.rs │ └── Cargo.lock └── rust_call_c │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ └── main.rs ├── .gitignore ├── 2122-axumapp_stepbystep ├── axumapp03_addlog │ ├── .gitignore │ ├── assets │ │ ├── index.html │ │ ├── script.js │ │ └── ferris.png │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── axumapp04_query │ ├── .gitignore │ ├── start.sh │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── axumapp05_form │ ├── .gitignore │ ├── start.sh │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── axumapp10_db │ ├── .gitignore │ ├── start.sh │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── axumapp11_todo │ ├── .gitignore │ ├── start.sh │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── axumapp01_helloworld │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── axumapp02_staticfile │ ├── .gitignore │ ├── assets │ │ ├── index.html │ │ ├── script.js │ │ └── ferris.png │ ├── assets2 │ │ ├── index.html │ │ ├── script.js │ │ └── ferris2.png │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── axumapp06_jsoninput │ ├── .gitignore │ ├── assets │ │ ├── index.html │ │ ├── script.js │ │ └── ferris.png │ ├── start.sh │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── axumapp07_jsonres │ ├── .gitignore │ ├── start.sh │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── axumapp08_global404 │ ├── .gitignore │ ├── start.sh │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── axumapp09_template │ ├── .gitignore │ ├── templates │ │ └── hello.html │ ├── start.sh │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── .cargo │ └── config.toml └── .rustc_info.json ├── 28-nom ├── .cargo │ └── config.toml ├── color │ ├── Cargo.toml │ ├── Cargo.lock │ └── src │ │ └── main.rs ├── coordination │ ├── Cargo.toml │ ├── Cargo.lock │ └── src │ │ └── main.rs ├── num0_parser │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ └── Cargo.lock └── num1_parser │ ├── Cargo.toml │ ├── src │ └── main.rs │ └── Cargo.lock ├── 25-slint-chatbot-demo ├── build.rs ├── assets │ └── screenshot.png ├── .gitignore ├── Cargo.toml ├── LICENSE ├── ui │ └── appwindow.slint ├── README.md └── src │ ├── main.rs │ ├── token_output_stream.rs │ └── llmengin.rs ├── 26-slint-yolov8-demo ├── build.rs ├── football.jpg ├── .vscode │ ├── settings.json │ ├── extensions.json │ └── launch.json ├── assets │ ├── poses.png │ └── objects.png ├── src │ ├── yolov8engine │ │ ├── roboto-mono-stripped.ttf │ │ └── coco_classes.rs │ └── main.rs ├── Cargo.toml ├── LICENSE ├── README.md └── ui │ └── appwindow.slint ├── 24-candle_yolov8 ├── assets │ ├── bike.jpg │ ├── cats.jpg │ └── football.jpg ├── src │ ├── roboto-mono-stripped.ttf │ └── coco_classes.rs ├── Cargo.toml └── README.md ├── 23-candle_chat ├── Cargo.toml ├── README.md └── src │ ├── token_output_stream.rs │ ├── simple.rs │ └── cli.rs ├── 16-channel ├── Cargo.toml └── src │ ├── main_e.rs │ ├── main_f.rs │ ├── main_c.rs │ ├── main_a.rs │ ├── main_b.rs │ └── main_d.rs └── 14-getinfo ├── Cargo.toml └── src ├── client_framed.rs ├── client.rs ├── server_framed.rs └── server.rs /27-bevy_snake/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /30-ffi/bigint-pyo3/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/target 2 | **/debug 3 | **/.env/ 4 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp03_addlog/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp04_query/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp05_form/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp10_db/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp11_todo/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp01_helloworld/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp02_staticfile/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp06_jsoninput/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp07_jsonres/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp08_global404/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp09_template/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /27-bevy_snake/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target-dir="target" 3 | -------------------------------------------------------------------------------- /28-nom/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target-dir="target" 3 | 4 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target-dir="target" 3 | -------------------------------------------------------------------------------- /30-ffi/c_call_rust/run_c.sh: -------------------------------------------------------------------------------- 1 | LD_LIBRARY_PATH=./target/debug ./call_rust 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp03_addlog/assets/index.html: -------------------------------------------------------------------------------- 1 | Hi from index.html 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp02_staticfile/assets/index.html: -------------------------------------------------------------------------------- 1 | Hi from index.html 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp06_jsoninput/assets/index.html: -------------------------------------------------------------------------------- 1 | Hi from index.html 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp03_addlog/assets/script.js: -------------------------------------------------------------------------------- 1 | console.log("Hello, World!"); 2 | -------------------------------------------------------------------------------- /30-ffi/bigint-pyo3/fib_rust.py: -------------------------------------------------------------------------------- 1 | import rust_fib 2 | 3 | rust_fib.calc_fib(2000000) 4 | 5 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp02_staticfile/assets/script.js: -------------------------------------------------------------------------------- 1 | console.log("Hello, World!"); 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp02_staticfile/assets2/index.html: -------------------------------------------------------------------------------- 1 | Hi from assets2/index.html 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp02_staticfile/assets2/script.js: -------------------------------------------------------------------------------- 1 | console.log("Hello, World2!"); 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp06_jsoninput/assets/script.js: -------------------------------------------------------------------------------- 1 | console.log("Hello, World!"); 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp09_template/templates/hello.html: -------------------------------------------------------------------------------- 1 |

Hello, {{ name }}!

2 | -------------------------------------------------------------------------------- /30-ffi/c_call_rust/compile_c.sh: -------------------------------------------------------------------------------- 1 | gcc call_rust.c -o call_rust -lc_call_rust -L./target/debug 2 | -------------------------------------------------------------------------------- /30-ffi/word-count/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include pyproject.toml Cargo.toml 2 | recursive-include src * 3 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp05_form/start.sh: -------------------------------------------------------------------------------- 1 | RUST_LOG=tower_http=debug,axumapp05=debug cargo run 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp10_db/start.sh: -------------------------------------------------------------------------------- 1 | RUST_LOG=tower_http=debug,axumapp10=debug cargo run 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp11_todo/start.sh: -------------------------------------------------------------------------------- 1 | RUST_LOG=tower_http=debug,axumapp11=debug cargo run 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp04_query/start.sh: -------------------------------------------------------------------------------- 1 | RUST_LOG=tower_http=debug,axumapp04=debug cargo run 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp06_jsoninput/start.sh: -------------------------------------------------------------------------------- 1 | RUST_LOG=tower_http=debug,axumapp06=debug cargo run 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp07_jsonres/start.sh: -------------------------------------------------------------------------------- 1 | RUST_LOG=tower_http=debug,axumapp07=debug cargo run 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp08_global404/start.sh: -------------------------------------------------------------------------------- 1 | RUST_LOG=tower_http=debug,axumapp08=debug cargo run 2 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp09_template/start.sh: -------------------------------------------------------------------------------- 1 | RUST_LOG=tower_http=debug,axumapp09=debug cargo run 2 | -------------------------------------------------------------------------------- /25-slint-chatbot-demo/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | slint_build::compile("ui/appwindow.slint").unwrap(); 3 | } 4 | -------------------------------------------------------------------------------- /26-slint-yolov8-demo/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | slint_build::compile("ui/appwindow.slint").unwrap(); 3 | } 4 | -------------------------------------------------------------------------------- /30-ffi/c_call_rust/call_rust: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/30-ffi/c_call_rust/call_rust -------------------------------------------------------------------------------- /24-candle_yolov8/assets/bike.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/24-candle_yolov8/assets/bike.jpg -------------------------------------------------------------------------------- /24-candle_yolov8/assets/cats.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/24-candle_yolov8/assets/cats.jpg -------------------------------------------------------------------------------- /27-bevy_snake/snake01_beginning/src/main.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | fn main() { 4 | App::new().run(); 5 | } 6 | -------------------------------------------------------------------------------- /26-slint-yolov8-demo/football.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/26-slint-yolov8-demo/football.jpg -------------------------------------------------------------------------------- /24-candle_yolov8/assets/football.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/24-candle_yolov8/assets/football.jpg -------------------------------------------------------------------------------- /26-slint-yolov8-demo/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.linkedProjects": [ 3 | ".\\Cargo.toml" 4 | ] 5 | } -------------------------------------------------------------------------------- /26-slint-yolov8-demo/assets/poses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/26-slint-yolov8-demo/assets/poses.png -------------------------------------------------------------------------------- /30-ffi/c_call_rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[no_mangle] 2 | pub extern "C" fn hello_from_rust() { 3 | println!("Hello from Rust!"); 4 | } 5 | -------------------------------------------------------------------------------- /30-ffi/word-count/cargo-generate.toml: -------------------------------------------------------------------------------- 1 | [template] 2 | ignore = [".nox"] 3 | 4 | [hooks] 5 | pre = [".template/pre-script.rhai"] 6 | -------------------------------------------------------------------------------- /26-slint-yolov8-demo/assets/objects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/26-slint-yolov8-demo/assets/objects.png -------------------------------------------------------------------------------- /24-candle_yolov8/src/roboto-mono-stripped.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/24-candle_yolov8/src/roboto-mono-stripped.ttf -------------------------------------------------------------------------------- /25-slint-chatbot-demo/assets/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/25-slint-chatbot-demo/assets/screenshot.png -------------------------------------------------------------------------------- /30-ffi/c_call_rust/call_rust.c: -------------------------------------------------------------------------------- 1 | extern void hello_from_rust(); 2 | 3 | int main(void) { 4 | hello_from_rust(); 5 | return 0; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /30-ffi/word-count/__pycache__/noxfile.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/30-ffi/word-count/__pycache__/noxfile.cpython-310.pyc -------------------------------------------------------------------------------- /27-bevy_snake/README.md: -------------------------------------------------------------------------------- 1 | # bevy_snake 2 | 3 | 4 | Clone of the snake game, with Bevy. Updated to Bevy v0.12. 5 | 6 | https://mbuffett.com/posts/bevy-snake-tutorial/ 7 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp03_addlog/assets/ferris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/2122-axumapp_stepbystep/axumapp03_addlog/assets/ferris.png -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp02_staticfile/assets/ferris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/2122-axumapp_stepbystep/axumapp02_staticfile/assets/ferris.png -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp06_jsoninput/assets/ferris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/2122-axumapp_stepbystep/axumapp06_jsoninput/assets/ferris.png -------------------------------------------------------------------------------- /26-slint-yolov8-demo/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "rust-lang.rust-analyzer", 4 | "vadimcn.vscode-lldb", 5 | "Slint.slint" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /26-slint-yolov8-demo/src/yolov8engine/roboto-mono-stripped.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/26-slint-yolov8-demo/src/yolov8engine/roboto-mono-stripped.ttf -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp02_staticfile/assets2/ferris2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/2122-axumapp_stepbystep/axumapp02_staticfile/assets2/ferris2.png -------------------------------------------------------------------------------- /30-ffi/c_call_rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "c_call_rust" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /30-ffi/rust_call_c/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "rust_call_c" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /30-ffi/word-count/tests/__pycache__/test_word_count.cpython-310-pytest-7.4.3.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketang84/jikeshijian/HEAD/30-ffi/word-count/tests/__pycache__/test_word_count.cpython-310-pytest-7.4.3.pyc -------------------------------------------------------------------------------- /25-slint-chatbot-demo/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # These are backup files generated by rustfmt 6 | **/*.rs.bk 7 | 8 | *.gguf 9 | *.json 10 | -------------------------------------------------------------------------------- /30-ffi/rust_call_c/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_call_c" 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 | -------------------------------------------------------------------------------- /30-ffi/word-count/.template/pre-script.rhai: -------------------------------------------------------------------------------- 1 | variable::set("PYO3_VERSION", "0.20.0"); 2 | file::rename(".template/Cargo.toml", "Cargo.toml"); 3 | file::rename(".template/pyproject.toml", "pyproject.toml"); 4 | file::delete(".template"); 5 | -------------------------------------------------------------------------------- /28-nom/color/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "color" 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 | nom = "7.1.3" 10 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp01_helloworld/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axumapp01" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "0.7" 9 | tokio = { version = "1.0", features = ["full"] } 10 | -------------------------------------------------------------------------------- /28-nom/coordination/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "coordination" 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 | nom = "7.1.3" 10 | -------------------------------------------------------------------------------- /28-nom/num0_parser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "num0_parser" 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 | nom = "7.1.3" 10 | -------------------------------------------------------------------------------- /28-nom/num1_parser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "num1_parser" 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 | nom = "7.1.3" 10 | -------------------------------------------------------------------------------- /27-bevy_snake/snake02_window/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake02" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | -------------------------------------------------------------------------------- /27-bevy_snake/snake04_snakemove/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake04" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" -------------------------------------------------------------------------------- /27-bevy_snake/snake06_grid/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake06" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | -------------------------------------------------------------------------------- /27-bevy_snake/snake09_foodspawning/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake09" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" -------------------------------------------------------------------------------- /27-bevy_snake/snake01_beginning/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake01" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | -------------------------------------------------------------------------------- /27-bevy_snake/snake03_snakehead/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake03" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | -------------------------------------------------------------------------------- /27-bevy_snake/snake05_snakecontrol/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake05" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | -------------------------------------------------------------------------------- /27-bevy_snake/snake07_moveongrid/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake07" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | -------------------------------------------------------------------------------- /27-bevy_snake/snake08_configwindow/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake08" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | -------------------------------------------------------------------------------- /27-bevy_snake/snake10_foodtimer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake10" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | 12 | -------------------------------------------------------------------------------- /27-bevy_snake/snake11_headadvance/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake11" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | 12 | -------------------------------------------------------------------------------- /27-bevy_snake/snake12_segments/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake12" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | 12 | -------------------------------------------------------------------------------- /27-bevy_snake/snake13_attachtail/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake13" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | 12 | -------------------------------------------------------------------------------- /27-bevy_snake/snake14_eatandgrow/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake14" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | 12 | -------------------------------------------------------------------------------- /27-bevy_snake/snake15_hitting/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snake15" 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 | bevy = "0.12.1" 10 | rand = "0.8.5" 11 | 12 | -------------------------------------------------------------------------------- /30-ffi/c_call_rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "c_call_rust" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | 9 | [lib] 10 | crate-type = ["cdylib"] 11 | 12 | 13 | [dependencies] 14 | -------------------------------------------------------------------------------- /30-ffi/word-count/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "word-count" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | name = "word_count" 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | pyo3 = { version = "0.20", features = ["extension-module"] } 12 | rayon = "1.0.2" 13 | 14 | [workspace] 15 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp02_staticfile/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axumapp02" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "0.7.2" 9 | tokio = { version = "1.0", features = ["full"] } 10 | tower-http = { version = "0.5.0", features = ["fs", "trace"] } 11 | -------------------------------------------------------------------------------- /27-bevy_snake/snake02_window/src/main.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | fn main() { 4 | App::new() 5 | .add_plugins(DefaultPlugins) 6 | .add_systems(Startup, setup_camera) 7 | .run(); 8 | } 9 | 10 | fn setup_camera(mut commands: Commands) { 11 | commands.spawn(Camera2dBundle::default()); 12 | } 13 | -------------------------------------------------------------------------------- /30-ffi/word-count/.template/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["maturin>=1,<2"] 3 | build-backend = "maturin" 4 | 5 | [project] 6 | name = "{{project-name}}" 7 | version = "0.1.0" 8 | 9 | [project.optional-dependencies] 10 | dev = ["pytest"] 11 | 12 | [tool.pytest.ini_options] 13 | addopts = "--benchmark-disable" 14 | -------------------------------------------------------------------------------- /30-ffi/word-count/.template/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["{{authors}}"] 3 | name = "{{project-name}}" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [lib] 8 | name = "word_count" 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | pyo3 = { version = "{{PYO3_VERSION}}", features = ["extension-module"] } 13 | rayon = "1.0.2" 14 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp03_addlog/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axumapp03" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "0.7" 9 | tokio = { version = "1.0", features = ["full"] } 10 | tower-http = { version = "0.5.0", features = ["fs", "trace"] } 11 | tracing = "0.1.40" 12 | tracing-subscriber = "0.3.18" 13 | -------------------------------------------------------------------------------- /30-ffi/bigint-pyo3/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bigint" 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 | [lib] 9 | name = "rust_fib" 10 | crate-type = ["cdylib"] 11 | 12 | [dependencies] 13 | num-bigint = "0.4.4" 14 | num-traits = "0.2.17" 15 | pyo3 = "0.20" 16 | 17 | -------------------------------------------------------------------------------- /30-ffi/bigint-pyo3/fib.py: -------------------------------------------------------------------------------- 1 | def fibonacci(n): 2 | if n <= 0: 3 | return "输入的数字必须大于0" 4 | elif n == 1: 5 | return 0 6 | elif n == 2: 7 | return 1 8 | else: 9 | a, b = 0, 1 10 | for _ in range(n - 2): 11 | a, b = b, a + b 12 | return b 13 | 14 | # 测试函数 15 | # print(fibonacci(100000)) 16 | fibonacci(2000000) 17 | 18 | -------------------------------------------------------------------------------- /28-nom/num0_parser/src/main.rs: -------------------------------------------------------------------------------- 1 | use nom::IResult; 2 | use std::error::Error; 3 | 4 | pub fn do_nothing_parser(input: &str) -> IResult<&str, &str> { 5 | Ok((input, "")) 6 | } 7 | fn main() -> Result<(), Box> { 8 | let (remaining_input, output) = do_nothing_parser("abcdefg")?; 9 | assert_eq!(remaining_input, "abcdefg"); 10 | assert_eq!(output, ""); 11 | Ok(()) 12 | } 13 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp05_form/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axumapp05" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "0.7" 9 | tokio = { version = "1.0", features = ["full"] } 10 | tower-http = { version = "0.5", features = ["fs", "trace"] } 11 | tracing = "0.1" 12 | tracing-subscriber = "0.3" 13 | serde = { version = "1.0", features = ["derive"] } 14 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp04_query/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axumapp04" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "0.7" 9 | tokio = { version = "1.0", features = ["full"] } 10 | tower-http = { version = "0.5", features = ["fs", "trace"] } 11 | tracing = "0.1" 12 | tracing-subscriber = "0.3" 13 | serde = { version = "1.0", features = ["derive"] } 14 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp06_jsoninput/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axumapp06" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "0.7" 9 | tokio = { version = "1.0", features = ["full"] } 10 | tower-http = { version = "0.5", features = ["fs", "trace"] } 11 | tracing = "0.1" 12 | tracing-subscriber = "0.3" 13 | serde = { version = "1.0", features = ["derive"] } 14 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp07_jsonres/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axumapp07" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "0.7" 9 | tokio = { version = "1.0", features = ["full"] } 10 | tower-http = { version = "0.5", features = ["fs", "trace"] } 11 | tracing = "0.1" 12 | tracing-subscriber = "0.3" 13 | serde = { version = "1.0", features = ["derive"] } 14 | serde_json = "1.0" 15 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp08_global404/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axumapp08" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "0.7" 9 | tokio = { version = "1.0", features = ["full"] } 10 | tower-http = { version = "0.5", features = ["fs", "trace"] } 11 | tracing = "0.1" 12 | tracing-subscriber = "0.3" 13 | serde = { version = "1.0", features = ["derive"] } 14 | serde_json = "1.0" 15 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp09_template/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axumapp09" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "0.7" 9 | tokio = { version = "1.0", features = ["full"] } 10 | tower-http = { version = "0.5", features = ["fs", "trace"] } 11 | tracing = "0.1" 12 | tracing-subscriber = "0.3" 13 | serde = { version = "1.0", features = ["derive"] } 14 | serde_json = "1.0" 15 | askama = "0.12" 16 | -------------------------------------------------------------------------------- /30-ffi/word-count/noxfile.py: -------------------------------------------------------------------------------- 1 | import nox 2 | 3 | nox.options.sessions = ["test"] 4 | 5 | 6 | @nox.session 7 | def test(session: nox.Session): 8 | session.env["MATURIN_PEP517_ARGS"] = "--profile=dev" 9 | session.install(".[dev]") 10 | session.run("pytest") 11 | 12 | 13 | @nox.session 14 | def bench(session: nox.Session): 15 | session.env["MATURIN_PEP517_ARGS"] = "--profile=dev" 16 | session.install(".[dev]") 17 | session.run("pytest", "--benchmark-enable") 18 | -------------------------------------------------------------------------------- /28-nom/num1_parser/src/main.rs: -------------------------------------------------------------------------------- 1 | pub use nom::bytes::complete::tag; 2 | pub use nom::IResult; 3 | use std::error::Error; 4 | 5 | fn parse_input(input: &str) -> IResult<&str, &str> { 6 | tag("abc")(input) 7 | } 8 | 9 | fn main() -> Result<(), Box> { 10 | let (leftover_input, output) = parse_input("abcWorld")?; 11 | assert_eq!(leftover_input, "World"); 12 | assert_eq!(output, "abc"); 13 | 14 | assert!(parse_input("defWorld").is_err()); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /30-ffi/bigint-pyo3/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["maturin>=1.4,<2.0"] 3 | build-backend = "maturin" 4 | 5 | [project] 6 | name = "bigint-pyo3" 7 | requires-python = ">=3.8" 8 | classifiers = [ 9 | "Programming Language :: Rust", 10 | "Programming Language :: Python :: Implementation :: CPython", 11 | "Programming Language :: Python :: Implementation :: PyPy", 12 | ] 13 | dynamic = ["version"] 14 | 15 | [tool.maturin] 16 | features = ["pyo3/extension-module"] 17 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp10_db/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axumapp10" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "0.7" 9 | tokio = { version = "1.0", features = ["full"] } 10 | tower-http = { version = "0.5", features = ["fs", "trace"] } 11 | tracing = "0.1" 12 | tracing-subscriber = "0.3" 13 | serde = { version = "1.0", features = ["derive"] } 14 | serde_json = "1.0" 15 | bb8 = "0.7" 16 | bb8-postgres = "0.7" 17 | tokio-postgres = "0.7" 18 | -------------------------------------------------------------------------------- /30-ffi/word-count/word_count/__init__.py: -------------------------------------------------------------------------------- 1 | from .word_count import search, search_sequential, search_sequential_allow_threads 2 | 3 | __all__ = [ 4 | "search_py", 5 | "search", 6 | "search_sequential", 7 | "search_sequential_allow_threads", 8 | ] 9 | 10 | 11 | def search_py(contents: str, needle: str) -> int: 12 | total = 0 13 | for line in contents.splitlines(): 14 | for word in line.split(" "): 15 | if word == needle: 16 | total += 1 17 | return total 18 | -------------------------------------------------------------------------------- /25-slint-chatbot-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "slint-chatbot-demo" 3 | version = "0.1.0" 4 | authors = ["daoga"] 5 | edition = "2021" 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 | slint = "1.3" 12 | anyhow = "1.0.75" 13 | candle-core = { version = "0.3.1" } 14 | candle-transformers = { version = "0.3.1" } 15 | clap = "4.4.10" 16 | hf-hub = "0.3.2" 17 | tokenizers = "0.15.0" 18 | 19 | [build-dependencies] 20 | slint-build = "1.3" 21 | -------------------------------------------------------------------------------- /23-candle_chat/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "candle_demo_openchat_35" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | anyhow = "1.0.75" 10 | candle-core = { version = "0.3.1" } 11 | candle-transformers = "0.3.1" 12 | clap = "4.4.10" 13 | hf-hub = "0.3.2" 14 | tokenizers = "0.15.0" 15 | 16 | [[bin]] 17 | name = "simple" 18 | path = "src/simple.rs" 19 | 20 | 21 | [[bin]] 22 | name = "cli" 23 | path = "src/cli.rs" 24 | 25 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp11_todo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axumapp11" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | axum = "0.7" 9 | tokio = { version = "1.0", features = ["full"] } 10 | tower-http = { version = "0.5", features = ["fs", "trace"] } 11 | tracing = "0.1" 12 | tracing-subscriber = "0.3" 13 | serde = { version = "1.0", features = ["derive"] } 14 | serde_json = "1.0" 15 | bb8 = "0.7" 16 | bb8-postgres = "0.7" 17 | tokio-postgres = "0.7" 18 | uuid = { version = "1.0", features = ["serde", "v4"] } 19 | 20 | -------------------------------------------------------------------------------- /24-candle_yolov8/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "candle_demo_yolov8" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | anyhow = "1.0.75" 10 | candle-core = "0.3.1" 11 | candle-nn = "0.3.1" 12 | candle-transformers = "0.3.1" 13 | clap = "4.4.10" 14 | hf-hub = "0.3.2" 15 | image = "0.24.7" 16 | imageproc = "0.23.0" 17 | rusttype = "0.9.3" 18 | tokenizers = "0.15.0" 19 | tracing = "0.1.40" 20 | tracing-chrome = "0.7.1" 21 | tracing-subscriber = "0.3.18" 22 | 23 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp01_helloworld/src/main.rs: -------------------------------------------------------------------------------- 1 | use axum::{response::Html, routing::get, Router}; 2 | 3 | #[tokio::main] 4 | async fn main() { 5 | // build our application with a route 6 | let app = Router::new().route("/", get(handler)); 7 | 8 | // run it 9 | let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") 10 | .await 11 | .unwrap(); 12 | println!("listening on {}", listener.local_addr().unwrap()); 13 | axum::serve(listener, app).await.unwrap(); 14 | } 15 | 16 | async fn handler() -> Html<&'static str> { 17 | Html("

Hello, World!

") 18 | } 19 | -------------------------------------------------------------------------------- /30-ffi/word-count/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["maturin>=1,<2"] 3 | build-backend = "maturin" 4 | 5 | [project] 6 | name = "word-count" 7 | version = "0.1.0" 8 | classifiers = [ 9 | "License :: OSI Approved :: MIT License", 10 | "Development Status :: 3 - Alpha", 11 | "Intended Audience :: Developers", 12 | "Programming Language :: Python", 13 | "Programming Language :: Rust", 14 | "Operating System :: POSIX", 15 | "Operating System :: MacOS :: MacOS X", 16 | ] 17 | 18 | [project.optional-dependencies] 19 | dev = ["pytest", "pytest-benchmark"] 20 | 21 | [tool.pytest.ini_options] 22 | addopts = "--benchmark-disable" 23 | -------------------------------------------------------------------------------- /16-channel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "channel" 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 | tokio = { version = "1.33.0", features = ["full"] } 10 | 11 | [[bin]] 12 | name = "main_a" 13 | path = "src/main_a.rs" 14 | 15 | [[bin]] 16 | name = "main_b" 17 | path = "src/main_b.rs" 18 | 19 | [[bin]] 20 | name = "main_c" 21 | path = "src/main_c.rs" 22 | 23 | [[bin]] 24 | name = "main_d" 25 | path = "src/main_d.rs" 26 | 27 | [[bin]] 28 | name = "main_e" 29 | path = "src/main_e.rs" 30 | 31 | [[bin]] 32 | name = "main_f" 33 | path = "src/main_f.rs" 34 | -------------------------------------------------------------------------------- /16-channel/src/main_e.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | use tokio::task; 3 | use tokio::time; 4 | 5 | #[tokio::main] 6 | async fn main() { 7 | let task_a = task::spawn(async move { 8 | println!("in task_a"); 9 | time::sleep(Duration::from_secs(3)).await; // 等待3s 10 | 1 11 | }); 12 | let task_b = task::spawn(async move { 13 | println!("in task_b"); 14 | 2 15 | }); 16 | let task_c = task::spawn(async move { 17 | println!("in task_c"); 18 | 3 19 | }); 20 | 21 | let (r1, r2, r3) = tokio::join!(task_a, task_b, task_c); 22 | 23 | println!("{}, {}, {}", r1.unwrap(), r2.unwrap(), r3.unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /30-ffi/bigint-pyo3/src/lib.rs: -------------------------------------------------------------------------------- 1 | use num_bigint::BigUint; 2 | use num_traits::{One, Zero}; 3 | use pyo3::prelude::*; 4 | 5 | // Calculate large fibonacci numbers. 6 | fn fib(n: usize) -> BigUint { 7 | let mut f0: BigUint = Zero::zero(); 8 | let mut f1: BigUint = One::one(); 9 | for _ in 0..n { 10 | let f2 = f0 + &f1; 11 | f0 = f1; 12 | f1 = f2; 13 | } 14 | f0 15 | } 16 | 17 | #[pyfunction] 18 | fn calc_fib(n: usize) -> PyResult<()> { 19 | let _ = fib(n); 20 | Ok(()) 21 | } 22 | 23 | #[pymodule] 24 | fn rust_fib(_py: Python<'_>, m: &PyModule) -> PyResult<()> { 25 | m.add_function(wrap_pyfunction!(calc_fib, m)?)?; 26 | Ok(()) 27 | } 28 | -------------------------------------------------------------------------------- /14-getinfo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "getinfo" 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 | bytes = "1.5.0" 10 | futures = "0.3.29" 11 | tokio = { version = "1.33.0", features = ["full"] } 12 | tokio-util = { version = "0.7.10", features = ["full"] } 13 | 14 | 15 | [[bin]] 16 | name = "server" 17 | path = "src/server.rs" 18 | 19 | [[bin]] 20 | name = "client" 21 | path = "src/client.rs" 22 | 23 | [[bin]] 24 | name = "server_framed" 25 | path = "src/server_framed.rs" 26 | 27 | [[bin]] 28 | name = "client_framed" 29 | path = "src/client_framed.rs" 30 | 31 | -------------------------------------------------------------------------------- /16-channel/src/main_f.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | use tokio::task; 3 | use tokio::time; 4 | 5 | #[tokio::main] 6 | async fn main() { 7 | let task_a = task::spawn(async move { 8 | println!("in task_a"); 9 | time::sleep(Duration::from_secs(3)).await; // 等待3s 10 | 1 11 | }); 12 | let task_b = task::spawn(async move { 13 | println!("in task_b"); 14 | 2 15 | }); 16 | let task_c = task::spawn(async move { 17 | println!("in task_c"); 18 | 3 19 | }); 20 | 21 | let ret = tokio::select! { 22 | r = task_a => r.unwrap(), 23 | r = task_b => r.unwrap(), 24 | r = task_c => r.unwrap(), 25 | }; 26 | 27 | println!("{}", ret); 28 | } 29 | -------------------------------------------------------------------------------- /26-slint-yolov8-demo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "slint-yolov8-demo" 3 | version = "0.1.0" 4 | authors = ["Daogang Tang "] 5 | edition = "2021" 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 | native-dialog = "0.7.0" 12 | slint = "1.3" 13 | 14 | anyhow = "1.0.75" 15 | candle-core = "0.3.1" 16 | candle-nn = "0.3.1" 17 | candle-transformers = "0.3.1" 18 | #clap = "4.4.10" 19 | hf-hub = "0.3.2" 20 | image = "0.24.7" 21 | imageproc = "0.23.0" 22 | rusttype = "0.9.3" 23 | tokenizers = "0.15.0" 24 | tracing = "0.1.40" 25 | tracing-chrome = "0.7.1" 26 | tracing-subscriber = "0.3.18" 27 | 28 | 29 | [build-dependencies] 30 | slint-build = "1.3" 31 | -------------------------------------------------------------------------------- /16-channel/src/main_c.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | use tokio::task; 3 | use tokio::time; 4 | 5 | #[tokio::main] 6 | async fn main() { 7 | let task_a = task::spawn(async move { 8 | println!("in task_a"); 9 | time::sleep(Duration::from_secs(3)).await; // 等待3s 10 | 1 11 | }); 12 | let task_b = task::spawn(async move { 13 | println!("in task_b"); 14 | 2 15 | }); 16 | let task_c = task::spawn(async move { 17 | println!("in task_c"); 18 | 3 19 | }); 20 | 21 | let mut tasks = Vec::with_capacity(3); 22 | tasks.push(task_a); 23 | tasks.push(task_b); 24 | tasks.push(task_c); 25 | 26 | let mut outputs = Vec::with_capacity(tasks.len()); 27 | for task in tasks { 28 | println!("iterate task result.."); 29 | // 在这里依次等待任务完成 30 | outputs.push(task.await.unwrap()); 31 | } 32 | println!("{:?}", outputs); 33 | } 34 | -------------------------------------------------------------------------------- /27-bevy_snake/snake03_snakehead/src/main.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | const SNAKE_HEAD_COLOR: Color = Color::rgb(0.7, 0.7, 0.7); 4 | 5 | #[derive(Component)] 6 | struct SnakeHead; 7 | 8 | fn main() { 9 | App::new() 10 | .add_plugins(DefaultPlugins) 11 | .add_systems(Startup, (setup_camera, spawn_snake)) 12 | .run(); 13 | 14 | } 15 | 16 | fn setup_camera(mut commands: Commands) { 17 | commands.spawn(Camera2dBundle::default()); 18 | } 19 | 20 | fn spawn_snake(mut commands: Commands) { 21 | commands 22 | .spawn(SpriteBundle { 23 | sprite: Sprite { 24 | color: SNAKE_HEAD_COLOR, 25 | ..default() 26 | }, 27 | transform: Transform { 28 | scale: Vec3::new(10.0, 10.0, 10.0), 29 | ..default() 30 | }, 31 | ..default() 32 | }) 33 | .insert(SnakeHead); 34 | } 35 | -------------------------------------------------------------------------------- /28-nom/color/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "color" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "nom", 10 | ] 11 | 12 | [[package]] 13 | name = "memchr" 14 | version = "2.6.4" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" 17 | 18 | [[package]] 19 | name = "minimal-lexical" 20 | version = "0.2.1" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 23 | 24 | [[package]] 25 | name = "nom" 26 | version = "7.1.3" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 29 | dependencies = [ 30 | "memchr", 31 | "minimal-lexical", 32 | ] 33 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp02_staticfile/src/main.rs: -------------------------------------------------------------------------------- 1 | use axum::{response::Html, routing::get, Router}; 2 | use tower_http::services::{ServeDir, ServeFile}; 3 | 4 | #[tokio::main] 5 | async fn main() { 6 | let serve_dir = 7 | ServeDir::new("assets2").not_found_service(ServeFile::new("assets2/index.html")); 8 | // build our application with a route 9 | let app = Router::new() 10 | .route("/foo", get(handler)) 11 | .nest_service("/assets", ServeDir::new("assets")) 12 | .nest_service("/assets2", serve_dir.clone()) 13 | .fallback_service(serve_dir); 14 | 15 | // run it 16 | let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") 17 | .await 18 | .unwrap(); 19 | println!("listening on {}", listener.local_addr().unwrap()); 20 | axum::serve(listener, app).await.unwrap(); 21 | } 22 | 23 | async fn handler() -> Html<&'static str> { 24 | Html("

Hello, World!

") 25 | } 26 | -------------------------------------------------------------------------------- /28-nom/num0_parser/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "memchr" 7 | version = "2.6.4" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" 10 | 11 | [[package]] 12 | name = "minimal-lexical" 13 | version = "0.2.1" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 16 | 17 | [[package]] 18 | name = "nom" 19 | version = "7.1.3" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 22 | dependencies = [ 23 | "memchr", 24 | "minimal-lexical", 25 | ] 26 | 27 | [[package]] 28 | name = "num0_parser" 29 | version = "0.1.0" 30 | dependencies = [ 31 | "nom", 32 | ] 33 | -------------------------------------------------------------------------------- /28-nom/num1_parser/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "memchr" 7 | version = "2.6.4" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" 10 | 11 | [[package]] 12 | name = "minimal-lexical" 13 | version = "0.2.1" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 16 | 17 | [[package]] 18 | name = "nom" 19 | version = "7.1.3" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 22 | dependencies = [ 23 | "memchr", 24 | "minimal-lexical", 25 | ] 26 | 27 | [[package]] 28 | name = "num1_parser" 29 | version = "0.1.0" 30 | dependencies = [ 31 | "nom", 32 | ] 33 | -------------------------------------------------------------------------------- /28-nom/coordination/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "coordination" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "nom", 10 | ] 11 | 12 | [[package]] 13 | name = "memchr" 14 | version = "2.6.4" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" 17 | 18 | [[package]] 19 | name = "minimal-lexical" 20 | version = "0.2.1" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 23 | 24 | [[package]] 25 | name = "nom" 26 | version = "7.1.3" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 29 | dependencies = [ 30 | "memchr", 31 | "minimal-lexical", 32 | ] 33 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/.rustc_info.json: -------------------------------------------------------------------------------- 1 | {"rustc_fingerprint":729461393880023121,"outputs":{"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.73.0 (cc66ad468 2023-10-03)\nbinary: rustc\ncommit-hash: cc66ad468955717ab92600c770da8c1601a4ff33\ncommit-date: 2023-10-03\nhost: x86_64-unknown-linux-gnu\nrelease: 1.73.0\nLLVM version: 17.0.2\n","stderr":""},"15729799797837862367":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/mike/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}} -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp03_addlog/src/main.rs: -------------------------------------------------------------------------------- 1 | use axum::{response::Html, routing::get, Router}; 2 | use tower_http::{ 3 | services::{ServeDir, ServeFile}, 4 | trace::TraceLayer, 5 | }; 6 | 7 | #[tokio::main] 8 | async fn main() { 9 | tracing_subscriber::fmt::init(); 10 | 11 | let serve_dir = ServeDir::new("assets").not_found_service(ServeFile::new("assets/index.html")); 12 | // build our application with a route 13 | let app = Router::new() 14 | .route("/foo", get(handler)) 15 | .nest_service("/assets", serve_dir.clone()) 16 | .fallback_service(serve_dir) 17 | .layer(TraceLayer::new_for_http()); 18 | 19 | // run it 20 | let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") 21 | .await 22 | .unwrap(); 23 | tracing::debug!("listening on {}", listener.local_addr().unwrap()); 24 | axum::serve(listener, app).await.unwrap(); 25 | } 26 | 27 | async fn handler() -> Html<&'static str> { 28 | Html("

Hello, World!

") 29 | } 30 | -------------------------------------------------------------------------------- /14-getinfo/src/client_framed.rs: -------------------------------------------------------------------------------- 1 | use bytes::Bytes; 2 | use futures::{SinkExt, StreamExt}; 3 | use std::env; 4 | use tokio::net::TcpStream; 5 | use tokio_util::codec::{Framed, LengthDelimitedCodec}; 6 | 7 | #[tokio::main] 8 | async fn main() -> Result<(), Box> { 9 | let addr = env::args() 10 | .nth(1) 11 | .unwrap_or_else(|| "127.0.0.1:8888".to_string()); 12 | // 连接到服务端 13 | let stream = TcpStream::connect(&addr).await?; 14 | // 包裹成 Frame stream 15 | let mut framed_stream = Framed::new(stream, LengthDelimitedCodec::new()); 16 | 17 | // 发送指令 18 | framed_stream.send(Bytes::from("gettime")).await?; 19 | 20 | // 读取返回数据,这里只读一次 21 | if let Some(msg) = framed_stream.next().await { 22 | match msg { 23 | Ok(msg) => { 24 | let timeinfo = String::from_utf8(msg.to_vec())?; 25 | println!("{}", timeinfo); 26 | } 27 | Err(e) => return Err(e.into()), 28 | } 29 | } 30 | 31 | Ok(()) 32 | } 33 | -------------------------------------------------------------------------------- /30-ffi/word-count/README.md: -------------------------------------------------------------------------------- 1 | # word-count 2 | 3 | Demonstrates searching for a file in plain python, with rust singlethreaded and with rust multithreaded. 4 | 5 | ## Build 6 | 7 | ```shell 8 | pip install . 9 | ``` 10 | 11 | ## Usage 12 | 13 | ```python 14 | from word_count import search_py, search, search_sequential 15 | 16 | search_py("foo bar", "foo") 17 | search("foo bar", "foo") 18 | search_sequential("foo bar", "foo") 19 | ``` 20 | 21 | ## Testing 22 | 23 | To test install nox globally and run 24 | 25 | ```shell 26 | nox 27 | ``` 28 | 29 | ## Benchmark 30 | 31 | To test install nox globally and run 32 | 33 | ```shell 34 | nox -s bench 35 | ``` 36 | 37 | ## Copying this example 38 | 39 | Use [`cargo-generate`](https://crates.io/crates/cargo-generate): 40 | 41 | ```bash 42 | $ cargo install cargo-generate 43 | $ cargo generate --git https://github.com/PyO3/pyo3 examples/word-count 44 | ``` 45 | 46 | (`cargo generate` will take a little while to clone the PyO3 repo first; be patient when waiting for the command to run.) 47 | -------------------------------------------------------------------------------- /16-channel/src/main_a.rs: -------------------------------------------------------------------------------- 1 | use tokio::sync::mpsc; 2 | 3 | #[tokio::main] 4 | async fn main() { 5 | let mut db: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 6 | let (tx, mut rx) = mpsc::channel::(100); 7 | 8 | let tx1 = tx.clone(); 9 | let tx2 = tx.clone(); 10 | 11 | let task_a = tokio::task::spawn(async move { 12 | if let Err(_) = tx1.send(50).await { 13 | println!("receiver dropped"); 14 | return; 15 | } 16 | }); 17 | let task_b = tokio::task::spawn(async move { 18 | if let Err(_) = tx2.send(100).await { 19 | println!("receiver dropped"); 20 | return; 21 | } 22 | }); 23 | 24 | let task_c = tokio::task::spawn(async move { 25 | while let Some(i) = rx.recv().await { 26 | println!("got = {}", i); 27 | db[4] = i; 28 | println!("{:?}", db); 29 | } 30 | }); 31 | _ = task_a.await.unwrap(); 32 | _ = task_b.await.unwrap(); 33 | _ = task_c.await.unwrap(); 34 | } 35 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp09_template/src/main.rs: -------------------------------------------------------------------------------- 1 | use askama::Template; 2 | use axum::{ 3 | extract::Path, 4 | http::StatusCode, 5 | response::IntoResponse, 6 | routing::get, 7 | Router, 8 | }; 9 | use tower_http::trace::TraceLayer; 10 | 11 | #[tokio::main] 12 | async fn main() { 13 | tracing_subscriber::fmt::init(); 14 | 15 | let app = Router::new() 16 | .route("/greet/:name", get(greet)) 17 | .layer(TraceLayer::new_for_http()) 18 | .fallback(handler_404); 19 | 20 | // run it 21 | let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") 22 | .await 23 | .unwrap(); 24 | tracing::debug!("listening on {}", listener.local_addr().unwrap()); 25 | axum::serve(listener, app).await.unwrap(); 26 | } 27 | 28 | #[derive(Template)] 29 | #[template(path = "hello.html")] 30 | struct HelloTemplate { 31 | name: String, 32 | } 33 | 34 | async fn greet(Path(name): Path) -> impl IntoResponse { 35 | HelloTemplate { name } .to_string() 36 | } 37 | 38 | async fn handler_404() -> impl IntoResponse { 39 | (StatusCode::NOT_FOUND, "nothing to see here") 40 | } 41 | -------------------------------------------------------------------------------- /25-slint-chatbot-demo/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /26-slint-yolov8-demo/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /27-bevy_snake/snake04_snakemove/src/main.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | const SNAKE_HEAD_COLOR: Color = Color::rgb(0.7, 0.7, 0.7); 4 | 5 | #[derive(Component)] 6 | struct SnakeHead; 7 | 8 | fn main() { 9 | App::new() 10 | .add_plugins(DefaultPlugins) 11 | .add_systems(Startup, (setup_camera, spawn_snake)) 12 | .add_systems(Update, snake_movement) 13 | .run(); 14 | } 15 | 16 | fn setup_camera(mut commands: Commands) { 17 | commands.spawn(Camera2dBundle::default()); 18 | } 19 | 20 | fn spawn_snake(mut commands: Commands) { 21 | commands 22 | .spawn(SpriteBundle { 23 | sprite: Sprite { 24 | color: SNAKE_HEAD_COLOR, 25 | ..default() 26 | }, 27 | transform: Transform { 28 | scale: Vec3::new(10.0, 10.0, 10.0), 29 | ..default() 30 | }, 31 | ..default() 32 | }) 33 | .insert(SnakeHead); 34 | } 35 | 36 | fn snake_movement(mut head_positions: Query<(&SnakeHead, &mut Transform)>) { 37 | for (_head, mut transform) in head_positions.iter_mut() { 38 | transform.translation.y += 2.; 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /28-nom/color/src/main.rs: -------------------------------------------------------------------------------- 1 | use nom::{ 2 | bytes::complete::{tag, take_while_m_n}, 3 | combinator::map_res, 4 | sequence::Tuple, 5 | IResult, 6 | }; 7 | 8 | #[derive(Debug, PartialEq)] 9 | pub struct Color { 10 | pub red: u8, 11 | pub green: u8, 12 | pub blue: u8, 13 | } 14 | 15 | fn from_hex(input: &str) -> Result { 16 | u8::from_str_radix(input, 16) 17 | } 18 | 19 | fn is_hex_digit(c: char) -> bool { 20 | c.is_digit(16) 21 | } 22 | 23 | fn hex_primary(input: &str) -> IResult<&str, u8> { 24 | map_res(take_while_m_n(2, 2, is_hex_digit), from_hex)(input) 25 | } 26 | 27 | fn hex_color(input: &str) -> IResult<&str, Color> { 28 | let (input, _) = tag("#")(input)?; 29 | let (input, (red, green, blue)) = (hex_primary, hex_primary, hex_primary).parse(input)?; 30 | Ok((input, Color { red, green, blue })) 31 | } 32 | 33 | #[test] 34 | fn parse_color() { 35 | assert_eq!( 36 | hex_color("#2F14DF"), 37 | Ok(( 38 | "", 39 | Color { 40 | red: 47, 41 | green: 20, 42 | blue: 223, 43 | } 44 | )) 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp04_query/src/main.rs: -------------------------------------------------------------------------------- 1 | use axum::{extract::Query, response::{Html, IntoResponse}, routing::get, Router}; 2 | use serde::Deserialize; 3 | use tower_http::trace::TraceLayer; 4 | 5 | #[derive(Debug, Deserialize)] 6 | #[allow(dead_code)] 7 | struct Params { 8 | foo: i32, 9 | bar: String, 10 | aa: Option, 11 | } 12 | 13 | #[tokio::main] 14 | async fn main() { 15 | tracing_subscriber::fmt::init(); 16 | 17 | // build our application with a route 18 | let app = Router::new() 19 | .route("/", get(handler)) 20 | .route("/query", get(query)) 21 | .layer(TraceLayer::new_for_http()); 22 | 23 | // run it 24 | let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") 25 | .await 26 | .unwrap(); 27 | println!("listening on {}", listener.local_addr().unwrap()); 28 | axum::serve(listener, app).await.unwrap(); 29 | } 30 | 31 | async fn handler() -> Html<&'static str> { 32 | Html("

Hello, World!

") 33 | } 34 | 35 | async fn query(Query(params): Query) -> impl IntoResponse { 36 | tracing::debug!("query params {:?}", params); 37 | Html("

Test query

") 38 | } 39 | -------------------------------------------------------------------------------- /16-channel/src/main_b.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | use tokio::sync::mpsc; 3 | use tokio::task; 4 | use tokio::time; 5 | 6 | #[tokio::main] 7 | async fn main() { 8 | let mut db: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 9 | let (tx, mut rx) = mpsc::channel::(100); 10 | 11 | let tx1 = tx.clone(); 12 | let tx2 = tx.clone(); 13 | 14 | let task_a = task::spawn(async move { 15 | println!("in task_a 1"); 16 | time::sleep(Duration::from_secs(3)).await; 17 | println!("in task_a 2"); 18 | if let Err(_) = tx1.send(50).await { 19 | println!("receiver dropped"); 20 | return; 21 | } 22 | }); 23 | let task_b = task::spawn(async move { 24 | println!("in task_b"); 25 | if let Err(_) = tx2.send(100).await { 26 | println!("receiver dropped"); 27 | return; 28 | } 29 | }); 30 | 31 | let task_c = task::spawn(async move { 32 | while let Some(i) = rx.recv().await { 33 | println!("got = {}", i); 34 | db[4] = i; 35 | println!("{:?}", db); 36 | } 37 | }); 38 | 39 | _ = task_c.await.unwrap(); 40 | _ = task_a.await.unwrap(); 41 | _ = task_b.await.unwrap(); 42 | } 43 | -------------------------------------------------------------------------------- /28-nom/coordination/src/main.rs: -------------------------------------------------------------------------------- 1 | use nom::bytes::complete::tag; 2 | use nom::sequence::{delimited, separated_pair}; 3 | use nom::IResult; 4 | use std::error::Error; 5 | 6 | #[derive(Debug, PartialEq)] 7 | pub struct Coordinate { 8 | pub x: i32, 9 | pub y: i32, 10 | } 11 | 12 | use nom::character::complete::i32; 13 | 14 | fn parse_integer_pair(input: &str) -> IResult<&str, (i32, i32)> { 15 | separated_pair(i32, tag(", "), i32)(input) 16 | } 17 | 18 | fn parse_coordinate(input: &str) -> IResult<&str, Coordinate> { 19 | let (remaining, (x, y)) = delimited(tag("("), parse_integer_pair, tag(")"))(input)?; 20 | 21 | Ok((remaining, Coordinate { x, y })) 22 | } 23 | 24 | fn main() -> Result<(), Box> { 25 | let (_, parsed) = parse_coordinate("(3, 5)")?; 26 | assert_eq!(parsed, Coordinate { x: 3, y: 5 }); 27 | 28 | let (_, parsed) = parse_coordinate("(2, -4)")?; 29 | assert_eq!(parsed, Coordinate { x: 2, y: -4 }); 30 | 31 | let parsing_error = parse_coordinate("(3,)"); 32 | assert!(parsing_error.is_err()); 33 | 34 | let parsing_error = parse_coordinate("(,3)"); 35 | assert!(parsing_error.is_err()); 36 | 37 | let parsing_error = parse_coordinate("Ferris"); 38 | assert!(parsing_error.is_err()); 39 | 40 | Ok(()) 41 | } 42 | -------------------------------------------------------------------------------- /14-getinfo/src/client.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use tokio::io::{AsyncReadExt, AsyncWriteExt}; 3 | use tokio::net::TcpStream; 4 | 5 | #[tokio::main] 6 | async fn main() -> Result<(), Box> { 7 | let addr = env::args() 8 | .nth(1) 9 | .unwrap_or_else(|| "127.0.0.1:8888".to_string()); 10 | // 连接到服务端 11 | let mut stream = TcpStream::connect(&addr).await?; 12 | 13 | // 写入指令数据,这是一种最简单的协议. 14 | stream.write_all(b"gettime").await?; 15 | 16 | // 等待tcp server的回复,读取内容 17 | // 这里用动态数组来存储从服务端返回的内容 18 | let mut buf: Vec = Vec::with_capacity(8128); 19 | // 读取的缓冲区 20 | let mut resp = [0u8; 2048]; 21 | loop { 22 | // 尝试一次读,返回读到的字节数 23 | let n = stream.read(&mut resp).await?; 24 | // 将读到的字节合并到buf中去 25 | buf.extend_from_slice(&resp[0..n]); 26 | if n == 0 { 27 | // 流断掉了 28 | panic!("Unexpected EOF"); 29 | } else if buf.len() >= 28 { 30 | // like: "Tue Oct 31 14:56:27 CST 2023" 31 | // buf 已经填充了足够的内容 32 | break; 33 | } else { 34 | // buf 中还没有足够多的内容,继续填充... 35 | continue; 36 | } 37 | } 38 | 39 | // 转换并打印返回的信息 40 | let timeinfo = String::from_utf8(buf)?; 41 | println!("{}", timeinfo); 42 | 43 | Ok(()) 44 | } 45 | -------------------------------------------------------------------------------- /30-ffi/word-count/src/lib.rs: -------------------------------------------------------------------------------- 1 | use pyo3::prelude::*; 2 | use rayon::prelude::*; 3 | 4 | /// Searches for the word, parallelized by rayon 5 | #[pyfunction] 6 | fn search(contents: &str, needle: &str) -> usize { 7 | contents 8 | .par_lines() 9 | .map(|line| count_line(line, needle)) 10 | .sum() 11 | } 12 | 13 | /// Searches for a word in a classic sequential fashion 14 | #[pyfunction] 15 | fn search_sequential(contents: &str, needle: &str) -> usize { 16 | contents.lines().map(|line| count_line(line, needle)).sum() 17 | } 18 | 19 | #[pyfunction] 20 | fn search_sequential_allow_threads(py: Python<'_>, contents: &str, needle: &str) -> usize { 21 | py.allow_threads(|| search_sequential(contents, needle)) 22 | } 23 | 24 | /// Count the occurrences of needle in line, case insensitive 25 | fn count_line(line: &str, needle: &str) -> usize { 26 | let mut total = 0; 27 | for word in line.split(' ') { 28 | if word == needle { 29 | total += 1; 30 | } 31 | } 32 | total 33 | } 34 | 35 | #[pymodule] 36 | fn word_count(_py: Python<'_>, m: &PyModule) -> PyResult<()> { 37 | m.add_function(wrap_pyfunction!(search, m)?)?; 38 | m.add_function(wrap_pyfunction!(search_sequential, m)?)?; 39 | m.add_function(wrap_pyfunction!(search_sequential_allow_threads, m)?)?; 40 | 41 | Ok(()) 42 | } 43 | -------------------------------------------------------------------------------- /30-ffi/rust_call_c/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | // this extern block links to the libm library 4 | #[link(name = "m")] 5 | extern "C" { 6 | // this is a foreign function 7 | // that computes the square root of a single precision complex number 8 | fn csqrtf(z: Complex) -> Complex; 9 | 10 | fn ccosf(z: Complex) -> Complex; 11 | } 12 | 13 | // Since calling foreign functions is considered unsafe, 14 | // it's common to write safe wrappers around them. 15 | fn cos(z: Complex) -> Complex { 16 | unsafe { ccosf(z) } 17 | } 18 | 19 | fn main() { 20 | // z = -1 + 0i 21 | let z = Complex { re: -1., im: 0. }; 22 | 23 | // calling a foreign function is an unsafe operation 24 | let z_sqrt = unsafe { csqrtf(z) }; 25 | 26 | println!("the square root of {:?} is {:?}", z, z_sqrt); 27 | 28 | // calling safe API wrapped around unsafe operation 29 | println!("cos({:?}) = {:?}", z, cos(z)); 30 | } 31 | 32 | // Minimal implementation of single precision complex numbers 33 | #[repr(C)] 34 | #[derive(Clone, Copy)] 35 | struct Complex { 36 | re: f32, 37 | im: f32, 38 | } 39 | 40 | impl fmt::Debug for Complex { 41 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 42 | if self.im < 0. { 43 | write!(f, "{}-{}i", self.re, -self.im) 44 | } else { 45 | write!(f, "{}+{}i", self.re, self.im) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /25-slint-chatbot-demo/ui/appwindow.slint: -------------------------------------------------------------------------------- 1 | import { Button, VerticalBox, TextEdit } from "std-widgets.slint"; 2 | 3 | export component AppWindow inherits Window { 4 | title: "OpenChat Bot"; 5 | width: 500px; 6 | height: 550px; 7 | forward-focus: ed2; 8 | // in-out property counter: 42; 9 | in-out property dialog; 10 | in-out property input-ask; 11 | 12 | // callback request-increase-value(); 13 | callback send-ask-content(string); 14 | 15 | VerticalBox { 16 | Text { 17 | // text: "Model: openchat_3.5.Q8_0.gguf"; 18 | text: "Model: openchat_3.5.Q4_K_M.gguf"; 19 | } 20 | ed1 := TextEdit { 21 | font-size: 15px; 22 | width: parent.width - 20px; 23 | // height: parent.height - 200px; 24 | vertical-stretch: 1; 25 | read-only: true; 26 | text: root.dialog; 27 | } 28 | ed2 := TextEdit { 29 | font-size: 15px; 30 | width: parent.width - 20px; 31 | height: 100px; 32 | text <=> root.input-ask; 33 | } 34 | Button { 35 | text: "Send"; 36 | clicked => { 37 | // root.request-increase-value(); 38 | root.send-ask-content(root.input-ask); 39 | ed2.text = ""; 40 | // root.update-dialog-content("test "); 41 | // root.dialog = root.dialog + "test "; 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /25-slint-chatbot-demo/README.md: -------------------------------------------------------------------------------- 1 | # Slint Chatbot Demo 2 | 3 | This is a demo of Rust + Slint + Candle + OpenChat LLM, it looks like this: 4 | 5 | ![](./assets/screenshot.png) 6 | 7 | ## Do it by yourself 8 | 9 | Make sure you have downloaded `openchat_3.5.Q4_K_M.gguf` and `tokenizer.json` by: 10 | 11 | ``` 12 | HF_HUB_ENABLE_HF_TRANSFER=1 HF_ENDPOINT=https://hf-mirror.com huggingface-cli download TheBloke/openchat_3.5-GGUF openchat_3.5.Q4_K_M.gguf 13 | HF_HUB_ENABLE_HF_TRANSFER=1 HF_ENDPOINT=https://hf-mirror.com huggingface-cli download openchat/openchat_3.5 tokenizer.json 14 | ``` 15 | The downloads locate at `~/.cache/huggingface/hub/`. 16 | 17 | Copy them to the root of the current project directory, like the following: 18 | 19 | ``` 20 | $ ls -lh 21 | total 12G 22 | -rw-r--r-- 1 daoga 197609 71 12月 6 12:34 build.rs 23 | -rw-r--r-- 1 daoga 197609 141K 12月 7 17:37 Cargo.lock 24 | -rw-r--r-- 1 daoga 197609 436 12月 7 17:36 Cargo.toml 25 | -rw-r--r-- 1 daoga 197609 1.1K 12月 6 12:34 LICENSE 26 | -rw-r--r-- 1 daoga 197609 4.1G 12月 7 15:31 openchat_3.5.Q4_K_M.gguf 27 | -rw-r--r-- 1 daoga 197609 7.2G 12月 7 15:53 openchat_3.5.Q8_0.gguf 28 | -rw-r--r-- 1 daoga 197609 468 12月 7 17:39 README.md 29 | drwxr-xr-x 1 daoga 197609 0 12月 7 15:07 src/ 30 | drwxr-xr-x 1 daoga 197609 0 12月 6 16:49 target/ 31 | -rw-r--r-- 1 daoga 197609 1.8M 12月 7 15:30 tokenizer.json 32 | drwxr-xr-x 1 daoga 197609 0 12月 6 12:34 ui/ 33 | ``` 34 | 35 | and then 36 | 37 | ``` 38 | cargo run --release 39 | ``` 40 | 41 | You will look at a GUI app poped up, good luck! 42 | -------------------------------------------------------------------------------- /26-slint-yolov8-demo/README.md: -------------------------------------------------------------------------------- 1 | # Slint Chatbot Demo 2 | 3 | This is a demo of Rust + Slint + Candle + Yolov8, it looks like this: 4 | 5 | ![](./assets/objects.png) 6 | ![](./assets/poses.png) 7 | 8 | ## Do it by yourself 9 | 10 | Make sure you have downloaded `yolov8m.safetensors` and `yolov8m-pose.safetensors` by: 11 | 12 | ``` 13 | HF_HUB_ENABLE_HF_TRANSFER=1 HF_ENDPOINT=https://hf-mirror.com huggingface-cli download lmz/candle-yolo-v8 yolov8m.safetensors 14 | HF_HUB_ENABLE_HF_TRANSFER=1 HF_ENDPOINT=https://hf-mirror.com huggingface-cli download lmz/candle-yolo-v8 yolov8m-pose.safetensors 15 | ``` 16 | The downloads locate at `~/.cache/huggingface/hub/`. 17 | 18 | Copy them to the root of the current project directory, like follows: 19 | 20 | ``` 21 | $ ls -lh 22 | total 101M 23 | -rwxr-xr-x 1 mike mike 150K Dec 9 14:58 Cargo.lock 24 | -rwxr-xr-x 1 mike mike 615 Dec 9 14:58 Cargo.toml 25 | -rwxr-xr-x 1 mike mike 1.1K Dec 9 14:58 LICENSE 26 | -rwxr-xr-x 1 mike mike 747 Dec 9 18:29 README.md 27 | drwxr-xr-x 2 mike mike 4.0K Dec 9 18:27 assets 28 | -rwxr-xr-x 1 mike mike 71 Dec 9 14:58 build.rs 29 | -rwxr-xr-x 1 mike mike 168K Dec 9 14:58 football.jpg 30 | drwxr-xr-x 3 mike mike 4.0K Dec 9 14:58 src 31 | drwxr-xr-x 4 mike mike 4.0K Dec 9 15:03 target 32 | drwxr-xr-x 2 mike mike 4.0K Dec 9 14:58 ui 33 | -rw-r--r-- 1 mike mike 51M Dec 9 17:45 yolov8m-pose.safetensors 34 | -rw-r--r-- 1 mike mike 50M Dec 9 17:45 yolov8m.safetensors 35 | ``` 36 | 37 | and then 38 | 39 | ``` 40 | cargo run --release 41 | ``` 42 | 43 | You will look at a GUI app popped up, good luck! 44 | -------------------------------------------------------------------------------- /24-candle_yolov8/src/coco_classes.rs: -------------------------------------------------------------------------------- 1 | pub const NAMES: [&str; 80] = [ 2 | "person", 3 | "bicycle", 4 | "car", 5 | "motorbike", 6 | "aeroplane", 7 | "bus", 8 | "train", 9 | "truck", 10 | "boat", 11 | "traffic light", 12 | "fire hydrant", 13 | "stop sign", 14 | "parking meter", 15 | "bench", 16 | "bird", 17 | "cat", 18 | "dog", 19 | "horse", 20 | "sheep", 21 | "cow", 22 | "elephant", 23 | "bear", 24 | "zebra", 25 | "giraffe", 26 | "backpack", 27 | "umbrella", 28 | "handbag", 29 | "tie", 30 | "suitcase", 31 | "frisbee", 32 | "skis", 33 | "snowboard", 34 | "sports ball", 35 | "kite", 36 | "baseball bat", 37 | "baseball glove", 38 | "skateboard", 39 | "surfboard", 40 | "tennis racket", 41 | "bottle", 42 | "wine glass", 43 | "cup", 44 | "fork", 45 | "knife", 46 | "spoon", 47 | "bowl", 48 | "banana", 49 | "apple", 50 | "sandwich", 51 | "orange", 52 | "broccoli", 53 | "carrot", 54 | "hot dog", 55 | "pizza", 56 | "donut", 57 | "cake", 58 | "chair", 59 | "sofa", 60 | "pottedplant", 61 | "bed", 62 | "diningtable", 63 | "toilet", 64 | "tvmonitor", 65 | "laptop", 66 | "mouse", 67 | "remote", 68 | "keyboard", 69 | "cell phone", 70 | "microwave", 71 | "oven", 72 | "toaster", 73 | "sink", 74 | "refrigerator", 75 | "book", 76 | "clock", 77 | "vase", 78 | "scissors", 79 | "teddy bear", 80 | "hair drier", 81 | "toothbrush", 82 | ]; 83 | -------------------------------------------------------------------------------- /26-slint-yolov8-demo/src/yolov8engine/coco_classes.rs: -------------------------------------------------------------------------------- 1 | pub const NAMES: [&str; 80] = [ 2 | "person", 3 | "bicycle", 4 | "car", 5 | "motorbike", 6 | "aeroplane", 7 | "bus", 8 | "train", 9 | "truck", 10 | "boat", 11 | "traffic light", 12 | "fire hydrant", 13 | "stop sign", 14 | "parking meter", 15 | "bench", 16 | "bird", 17 | "cat", 18 | "dog", 19 | "horse", 20 | "sheep", 21 | "cow", 22 | "elephant", 23 | "bear", 24 | "zebra", 25 | "giraffe", 26 | "backpack", 27 | "umbrella", 28 | "handbag", 29 | "tie", 30 | "suitcase", 31 | "frisbee", 32 | "skis", 33 | "snowboard", 34 | "sports ball", 35 | "kite", 36 | "baseball bat", 37 | "baseball glove", 38 | "skateboard", 39 | "surfboard", 40 | "tennis racket", 41 | "bottle", 42 | "wine glass", 43 | "cup", 44 | "fork", 45 | "knife", 46 | "spoon", 47 | "bowl", 48 | "banana", 49 | "apple", 50 | "sandwich", 51 | "orange", 52 | "broccoli", 53 | "carrot", 54 | "hot dog", 55 | "pizza", 56 | "donut", 57 | "cake", 58 | "chair", 59 | "sofa", 60 | "pottedplant", 61 | "bed", 62 | "diningtable", 63 | "toilet", 64 | "tvmonitor", 65 | "laptop", 66 | "mouse", 67 | "remote", 68 | "keyboard", 69 | "cell phone", 70 | "microwave", 71 | "oven", 72 | "toaster", 73 | "sink", 74 | "refrigerator", 75 | "book", 76 | "clock", 77 | "vase", 78 | "scissors", 79 | "teddy bear", 80 | "hair drier", 81 | "toothbrush", 82 | ]; 83 | -------------------------------------------------------------------------------- /26-slint-yolov8-demo/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug executable 'slint-yolov8-demo'", 11 | "cargo": { 12 | "args": [ 13 | "build", 14 | "--bin=slint-yolov8-demo", 15 | "--package=slint-yolov8-demo" 16 | ], 17 | "filter": { 18 | "name": "slint-yolov8-demo", 19 | "kind": "bin" 20 | } 21 | }, 22 | "args": [], 23 | "cwd": "${workspaceFolder}" 24 | }, 25 | { 26 | "type": "lldb", 27 | "request": "launch", 28 | "name": "Debug unit tests in executable 'slint-yolov8-demo'", 29 | "cargo": { 30 | "args": [ 31 | "test", 32 | "--no-run", 33 | "--bin=slint-yolov8-demo", 34 | "--package=slint-yolov8-demo" 35 | ], 36 | "filter": { 37 | "name": "slint-yolov8-demo", 38 | "kind": "bin" 39 | } 40 | }, 41 | "args": [], 42 | "cwd": "${workspaceFolder}" 43 | } 44 | ] 45 | } -------------------------------------------------------------------------------- /25-slint-chatbot-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | 3 | use std::sync::mpsc::channel; 4 | 5 | mod token_output_stream; 6 | mod llmengin; 7 | 8 | slint::include_modules!(); 9 | 10 | fn main() -> Result<(), slint::PlatformError> { 11 | let ui = AppWindow::new()?; 12 | 13 | let ui_handle = ui.as_weak(); 14 | let (sender, receiver) = channel::(); 15 | let sender1 = sender.clone(); 16 | 17 | let _thread = std::thread::spawn(move || { 18 | 19 | if let Err(_) = llmengin::start_engine(ui_handle, receiver) { 20 | // process before exit. 21 | } 22 | }); 23 | 24 | let ui_handle = ui.as_weak(); 25 | ui.on_send_ask_content(move |content| { 26 | update_dialog(ui_handle.clone(), content.to_string()); 27 | sender.send(content.to_string()).unwrap(); 28 | }); 29 | 30 | ui.window().on_close_requested(move || { 31 | sender1.send("_exit_".to_string()).unwrap(); 32 | slint::CloseRequestResponse::HideWindow 33 | }); 34 | 35 | ui.run() 36 | } 37 | 38 | fn update_dialog(ui_handle: slint::Weak, msg: String) { 39 | _ = slint::invoke_from_event_loop(move || { 40 | let ui_handle = ui_handle.unwrap(); 41 | let old_content = ui_handle.get_dialog(); 42 | ui_handle.set_dialog(old_content + &msg + "\n"); 43 | }); 44 | } 45 | 46 | fn update_dialog_without_ln(ui_handle: slint::Weak, msg: String) { 47 | _ = slint::invoke_from_event_loop(move || { 48 | let ui_handle = ui_handle.unwrap(); 49 | let old_content = ui_handle.get_dialog(); 50 | ui_handle.set_dialog(old_content + &msg); 51 | }); 52 | } -------------------------------------------------------------------------------- /27-bevy_snake/snake05_snakecontrol/src/main.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | const SNAKE_HEAD_COLOR: Color = Color::rgb(0.7, 0.7, 0.7); 4 | 5 | #[derive(Component)] 6 | struct SnakeHead; 7 | 8 | fn main() { 9 | App::new() 10 | .add_plugins(DefaultPlugins) 11 | .add_systems(Startup, (setup_camera, spawn_snake)) 12 | .add_systems(Update, snake_movement) 13 | .run(); 14 | } 15 | 16 | fn setup_camera(mut commands: Commands) { 17 | commands.spawn(Camera2dBundle::default()); 18 | } 19 | 20 | fn spawn_snake(mut commands: Commands) { 21 | commands 22 | .spawn(SpriteBundle { 23 | sprite: Sprite { 24 | color: SNAKE_HEAD_COLOR, 25 | ..default() 26 | }, 27 | transform: Transform { 28 | scale: Vec3::new(10.0, 10.0, 10.0), 29 | ..default() 30 | }, 31 | ..default() 32 | }) 33 | .insert(SnakeHead); 34 | } 35 | 36 | fn snake_movement( 37 | keyboard_input: Res>, 38 | mut head_positions: Query<&mut Transform, With>, 39 | ) { 40 | for mut transform in head_positions.iter_mut() { 41 | if keyboard_input.pressed(KeyCode::Left) { 42 | transform.translation.x -= 2.; 43 | } 44 | if keyboard_input.pressed(KeyCode::Right) { 45 | transform.translation.x += 2.; 46 | } 47 | if keyboard_input.pressed(KeyCode::Down) { 48 | transform.translation.y -= 2.; 49 | } 50 | if keyboard_input.pressed(KeyCode::Up) { 51 | transform.translation.y += 2.; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /26-slint-yolov8-demo/ui/appwindow.slint: -------------------------------------------------------------------------------- 1 | import { Button, VerticalBox , HorizontalBox} from "std-widgets.slint"; 2 | 3 | export component AppWindow inherits Window { 4 | width: 900px; 5 | height: 480px; 6 | 7 | in-out property orig-image; 8 | in-out property orig-image-path; 9 | 10 | in-out property generated-image; 11 | 12 | callback select-orig-pic(); 13 | callback probe-objects(); 14 | callback probe-poses(); 15 | 16 | VerticalBox { 17 | width: 100%; 18 | vertical-stretch: 1; 19 | Text { 20 | text: "Model Size: Medium"; 21 | } 22 | HorizontalBox { 23 | width: 98%; 24 | vertical-stretch: 1; 25 | Image { 26 | width: 49%; 27 | source: root.orig-image; 28 | 29 | } 30 | Rectangle { 31 | width: 1px; 32 | background: gray; 33 | } 34 | Image { 35 | width: 49%; 36 | source: root.generated-image; 37 | } 38 | } 39 | HorizontalBox { 40 | alignment: start; 41 | height: 50px; 42 | Button { 43 | text: "Select Picture.."; 44 | clicked => { 45 | root.select-orig-pic(); 46 | } 47 | } 48 | Button { 49 | text: "Detect Objects"; 50 | clicked => { 51 | root.probe-objects(); 52 | } 53 | } 54 | Button { 55 | text: "Detect Poses"; 56 | clicked => { 57 | root.probe-poses(); 58 | } 59 | } 60 | } 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /16-channel/src/main_d.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | use tokio::sync::{mpsc, oneshot}; 3 | use tokio::task; 4 | use tokio::time; 5 | 6 | #[tokio::main] 7 | async fn main() { 8 | let mut db: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 9 | let (tx, mut rx) = mpsc::channel::<(u32, oneshot::Sender)>(100); 10 | 11 | let tx1 = tx.clone(); 12 | let tx2 = tx.clone(); 13 | 14 | let task_a = task::spawn(async move { 15 | time::sleep(Duration::from_secs(3)).await; 16 | let (resp_tx, resp_rx) = oneshot::channel(); 17 | if let Err(_) = tx1.send((50, resp_tx)).await { 18 | println!("receiver dropped"); 19 | return; 20 | } 21 | if let Ok(ret) = resp_rx.await { 22 | if ret { 23 | println!("task_a finished with success."); 24 | } else { 25 | println!("task_a finished with failure."); 26 | } 27 | } else { 28 | println!("oneshot sender dropped"); 29 | return; 30 | } 31 | }); 32 | let task_b = task::spawn(async move { 33 | let (resp_tx, resp_rx) = oneshot::channel(); 34 | if let Err(_) = tx2.send((100, resp_tx)).await { 35 | println!("receiver dropped"); 36 | return; 37 | } 38 | if let Ok(ret) = resp_rx.await { 39 | if ret { 40 | println!("task_b finished with success."); 41 | } else { 42 | println!("task_b finished with failure."); 43 | } 44 | } else { 45 | println!("oneshot sender dropped"); 46 | return; 47 | } 48 | }); 49 | 50 | let task_c = task::spawn(async move { 51 | while let Some((i, resp_tx)) = rx.recv().await { 52 | println!("got = {}", i); 53 | db[4] = i; 54 | println!("{:?}", db); 55 | resp_tx.send(true).unwrap(); 56 | } 57 | }); 58 | 59 | _ = task_a.await.unwrap(); 60 | _ = task_b.await.unwrap(); 61 | _ = task_c.await.unwrap(); 62 | } 63 | -------------------------------------------------------------------------------- /24-candle_yolov8/README.md: -------------------------------------------------------------------------------- 1 | 2 | # candle-yolo-v8 3 | 4 | ```bash 5 | cargo run --release -- assets/football.jpg 6 | # or 7 | cargo run --release -- assets/football.jpg --task pose 8 | ``` 9 | 10 | 11 | 12 | ## candle-yolo-v8: Object Detection and Pose Estimation 13 | 14 | This is a port of [Ultralytics 15 | YOLOv8](https://github.com/ultralytics/ultralytics). The implementation is based 16 | on the [tinygrad 17 | version](https://github.com/tinygrad/tinygrad/blob/master/examples/yolov8.py) 18 | and on the model architecture described in this 19 | [issue](https://github.com/ultralytics/ultralytics/issues/189). The supported 20 | tasks are object detection and pose estimation. 21 | 22 | You can try this model online on the [Candle YOLOv8 23 | Space](https://huggingface.co/spaces/lmz/candle-yolo). The model then fully runs 24 | in your browser using WebAssembly - if you use a custom image it will never 25 | leave your phone/computer! 26 | 27 | ## Running some example 28 | 29 | ### Object Detection 30 | ```bash 31 | cargo run --example yolo-v8 --release -- candle-examples/examples/yolo-v8/assets/bike.jpg 32 | ``` 33 | 34 | This prints details about the detected objects and generates a `bike.pp.jpg` file. 35 | 36 | ![Leading group, Giro d'Italia 2021](./assets/bike.jpg) 37 | 38 | Image source: 39 | [wikimedia](https://commons.wikimedia.org/wiki/File:Leading_group,_Giro_d%27Italia_2021,_Stage_15.jpg). 40 | 41 | ![Leading group, Giro d'Italia 2021](./assets/bike.od.jpg) 42 | 43 | ### Pose Estimation 44 | ```bash 45 | cargo run --example yolo-v8 --release -- \ 46 | candle-examples/examples/yolo-v8/assets/bike.jpg --task pose 47 | ``` 48 | 49 | ![Leading group, Giro d'Italia 2021](./assets/bike.pose.jpg) 50 | 51 | ### Command-line flags 52 | 53 | - `--which`: select the model variant to be used, `n`, `s` , `m`, `l`, or `x` by 54 | increasing size and quality. 55 | - `--task`: `detect` for object detection and `pose` for pose estimation. 56 | - `--legend-size`: the size of the characters to print. 57 | - `--model`: use a local model file rather than downloading it from the hub. 58 | 59 | -------------------------------------------------------------------------------- /14-getinfo/src/server_framed.rs: -------------------------------------------------------------------------------- 1 | use bytes::Bytes; 2 | use futures::{SinkExt, StreamExt}; 3 | use std::env; 4 | use tokio::net::TcpListener; 5 | use tokio::process::Command; 6 | use tokio_util::codec::{Framed, LengthDelimitedCodec}; 7 | 8 | #[tokio::main] 9 | async fn main() -> Result<(), Box> { 10 | let addr = env::args() 11 | .nth(1) 12 | .unwrap_or_else(|| "127.0.0.1:8888".to_string()); 13 | println!("Listening on: {}", addr); 14 | let listener = TcpListener::bind(&addr).await?; 15 | 16 | // 注意这里是一个无条件循环,表明始终处于服务状态 17 | loop { 18 | // 等待客户端请求连上来 19 | let (stream, _) = listener.accept().await?; 20 | // 包裹成一个Frame stream 21 | let mut framed_stream = Framed::new(stream, LengthDelimitedCodec::new()); 22 | 23 | // 创建子task执行任务 24 | tokio::spawn(async move { 25 | // 等待读取一个一个msg,如果返回None,会退出这个循环 26 | while let Some(msg) = framed_stream.next().await { 27 | match msg { 28 | Ok(msg) => { 29 | // 解析指令,执行任务 30 | let directive = String::from_utf8(msg.to_vec()) 31 | .expect("error when converting to string directive."); 32 | println!("{directive}"); 33 | let output = process(&directive).await; 34 | println!("{output}"); 35 | 36 | // 返回执行结果 37 | _ = framed_stream.send(Bytes::from(output)).await; 38 | } 39 | Err(e) => { 40 | println!("{e:?}"); 41 | } 42 | } 43 | } 44 | }); 45 | } 46 | } 47 | 48 | async fn process(directive: &str) -> String { 49 | if directive == "gettime" { 50 | // 这里我们用了unwrap()是因为我们一般确信执行date命令不会失败 51 | // 更可靠的作法是对返回的Result作处理 52 | let output = Command::new("date").output().await.unwrap(); 53 | String::from_utf8(output.stdout).unwrap() 54 | } else { 55 | // 如果是其它指令,我们目前返回 无效指令 56 | "invalid command".to_owned() 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp10_db/src/main.rs: -------------------------------------------------------------------------------- 1 | use axum::{ 2 | extract::State, 3 | http::StatusCode, 4 | response::{Html, IntoResponse}, 5 | routing::get, 6 | Router, 7 | }; 8 | use bb8::Pool; 9 | use bb8_postgres::PostgresConnectionManager; 10 | use tokio_postgres::NoTls; 11 | use tower_http::trace::TraceLayer; 12 | 13 | type ConnectionPool = Pool>; 14 | 15 | 16 | #[tokio::main] 17 | async fn main() { 18 | tracing_subscriber::fmt::init(); 19 | 20 | let manager = PostgresConnectionManager::new_from_stringlike( 21 | "host=localhost user=postgres dbname=postgres password=123456", 22 | NoTls, 23 | ) 24 | .unwrap(); 25 | 26 | let pool = Pool::builder().build(manager).await.unwrap(); 27 | 28 | let app = Router::new() 29 | .route("/", get(handler)) 30 | .route("/query_from_db", get(query_from_db)) 31 | .layer(TraceLayer::new_for_http()) 32 | .fallback(handler_404) 33 | .with_state(pool); 34 | 35 | // run it 36 | let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") 37 | .await 38 | .unwrap(); 39 | tracing::debug!("listening on {}", listener.local_addr().unwrap()); 40 | axum::serve(listener, app).await.unwrap(); 41 | } 42 | 43 | async fn handler() -> Html<&'static str> { 44 | Html("

Hello, World!

") 45 | } 46 | 47 | async fn handler_404() -> impl IntoResponse { 48 | (StatusCode::NOT_FOUND, "nothing to see here") 49 | } 50 | 51 | async fn query_from_db(State(pool): State) -> Result { 52 | tracing::debug!("get db conn {:?}", pool); 53 | let conn = pool.get().await.map_err(internal_error)?; 54 | 55 | tracing::debug!("query_from_db: 1"); 56 | let row = conn 57 | .query_one("select 1 + 1", &[]) 58 | .await 59 | .map_err(internal_error)?; 60 | tracing::debug!("query_from_db: 2"); 61 | 62 | let two: i32 = row.try_get(0).map_err(internal_error)?; 63 | tracing::debug!("query_from_db: 3"); 64 | tracing::debug!("calc_result {:?}", two); 65 | 66 | Ok(two.to_string()) 67 | } 68 | 69 | fn internal_error(err: E) -> (StatusCode, String) 70 | where 71 | E: std::error::Error, 72 | { 73 | (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) 74 | } 75 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp05_form/src/main.rs: -------------------------------------------------------------------------------- 1 | use axum::{ 2 | extract::{Form, Query}, 3 | response::Html, 4 | routing::get, 5 | Router, 6 | }; 7 | use serde::Deserialize; 8 | use tower_http::trace::TraceLayer; 9 | 10 | #[allow(dead_code)] 11 | #[derive(Debug, Deserialize)] 12 | struct Params { 13 | foo: Option, 14 | bar: Option, 15 | } 16 | 17 | #[tokio::main] 18 | async fn main() { 19 | tracing_subscriber::fmt::init(); 20 | 21 | let app = Router::new() 22 | .route("/", get(handler)) 23 | .route("/query", get(query)) 24 | .route("/form", get(show_form).post(accept_form)) 25 | .layer(TraceLayer::new_for_http()); 26 | 27 | // run it 28 | let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") 29 | .await 30 | .unwrap(); 31 | tracing::debug!("listening on {}", listener.local_addr().unwrap()); 32 | axum::serve(listener, app).await.unwrap(); 33 | } 34 | 35 | async fn handler() -> Html<&'static str> { 36 | Html("

Hello, World!

") 37 | } 38 | 39 | async fn query(Query(params): Query) -> Html<&'static str> { 40 | tracing::debug!("query params {:?}", params); 41 | Html("

Test query

") 42 | } 43 | 44 | async fn show_form() -> Html<&'static str> { 45 | Html( 46 | r#" 47 | 48 | 49 | 50 | 51 |
52 | 56 | 57 | 61 | 62 | 63 |
64 | 65 | 66 | "#, 67 | ) 68 | } 69 | 70 | #[allow(dead_code)] 71 | #[derive(Deserialize, Debug)] 72 | struct Input { 73 | name: String, 74 | email: String, 75 | } 76 | 77 | async fn accept_form(Form(input): Form) -> Html<&'static str> { 78 | tracing::debug!("form params {:?}", input); 79 | 80 | Html("

Form posted

") 81 | } 82 | 83 | -------------------------------------------------------------------------------- /30-ffi/word-count/tests/test_word_count.py: -------------------------------------------------------------------------------- 1 | from concurrent.futures import ThreadPoolExecutor 2 | 3 | import pytest 4 | import word_count 5 | 6 | NT = 10 7 | 8 | @pytest.fixture(scope="session") 9 | def contents() -> str: 10 | text = """ 11 | The Zen of Python, by Tim Peters 12 | 13 | Beautiful is better than ugly. 14 | Explicit is better than implicit. 15 | Simple is better than complex. 16 | Complex is better than complicated. 17 | Flat is better than nested. 18 | Sparse is better than dense. 19 | Readability counts. 20 | Special cases aren't special enough to break the rules. 21 | Although practicality beats purity. 22 | Errors should never pass silently. 23 | Unless explicitly silenced. 24 | In the face of ambiguity, refuse the temptation to guess. 25 | There should be one-- and preferably only one --obvious way to do it. 26 | Although that way may not be obvious at first unless you're Dutch. 27 | Now is better than never. 28 | Although never is often better than *right* now. 29 | If the implementation is hard to explain, it's a bad idea. 30 | If the implementation is easy to explain, it may be a good idea. 31 | Namespaces are one honking great idea -- let's do more of those! 32 | """ 33 | return text * 1000 * NT 34 | 35 | 36 | def test_word_count_rust_parallel(benchmark, contents): 37 | count = benchmark(word_count.search, contents, "is") 38 | assert count == 10000 * NT 39 | 40 | 41 | def test_word_count_rust_sequential(benchmark, contents): 42 | count = benchmark(word_count.search_sequential, contents, "is") 43 | assert count == 10000 * NT 44 | 45 | 46 | def test_word_count_python_sequential(benchmark, contents): 47 | count = benchmark(word_count.search_py, contents, "is") 48 | assert count == 10000 * NT 49 | 50 | 51 | def run_rust_sequential_twice( 52 | executor: ThreadPoolExecutor, contents: str, needle: str 53 | ) -> int: 54 | future_1 = executor.submit( 55 | word_count.search_sequential_allow_threads, contents, needle 56 | ) 57 | future_2 = executor.submit( 58 | word_count.search_sequential_allow_threads, contents, needle 59 | ) 60 | result_1 = future_1.result() 61 | result_2 = future_2.result() 62 | return result_1 + result_2 63 | 64 | 65 | def test_word_count_rust_sequential_twice_with_threads(benchmark, contents): 66 | executor = ThreadPoolExecutor(max_workers=2) 67 | count = benchmark(run_rust_sequential_twice, executor, contents, "is") 68 | assert count == 20000 * NT 69 | -------------------------------------------------------------------------------- /23-candle_chat/README.md: -------------------------------------------------------------------------------- 1 | ## Rust Candle Demo 2 | 3 | An interactive command line tool to demonstrate how to use HuggingFace's rust [Candle ML framework](https://github.com/huggingface/candle) to execute LLM. 4 | 5 | This demo uses the quantized version of LLM openchat: https://huggingface.co/TheBloke/openchat_3.5-GGUF by default. 6 | 7 | 8 | ### Prepare 9 | 10 | Make sure you have installed the huggingface cli, if not, do it: 11 | 12 | ``` 13 | pip install -U "huggingface_hub[cli]" 14 | ``` 15 | 16 | And then you should download this model file associated with the original openchat `tokenizer.json` file: 17 | 18 | 19 | ``` 20 | mkdir hf_hub 21 | HF_HUB_ENABLE_HF_TRANSFER=1 HF_ENDPOINT=https://hf-mirror.com huggingface-cli download TheBloke/openchat_3.5-GGUF openchat_3.5.Q8_0.gguf --local-dir hf_hub 22 | HF_HUB_ENABLE_HF_TRANSFER=1 HF_ENDPOINT=https://hf-mirror.com huggingface-cli download openchat/openchat_3.5 tokenizer.json --local-dir hf_hub 23 | ``` 24 | 25 | ### Run 26 | 27 | There are two examples here: 28 | 29 | - **simple**: all parameters are hardcoded into code to make everything simplest, but you need to modify the model and tokenizer.json file by yourself, and run by: 30 | 31 | ``` 32 | cargo run --release --bin simple 33 | ``` 34 | 35 | - **cli**: you can use this cli program to pass parameters from command line. 36 | 37 | ``` 38 | cargo run --release --bin cli -- --model=xxxxxxx --tokenizer=xxxx 39 | ``` 40 | 41 | You can use `--help` to show what parameters could be configured. 42 | 43 | ``` 44 | $ cargo run --release --bin cli -- --help 45 | Finished release [optimized] target(s) in 0.04s 46 | Running `target/release/cli --help` 47 | avx: false, neon: false, simd128: false, f16c: false 48 | Usage: cli [OPTIONS] 49 | 50 | Options: 51 | --tokenizer [default: ../hf_hub/openchat_3.5_tokenizer.json] 52 | --model [default: ../hf_hub/openchat_3.5.Q8_0.gguf] 53 | -n, --sample-len [default: 1000] 54 | --temperature [default: 0.8] 55 | --seed [default: 299792458] 56 | --repeat-penalty [default: 1.1] 57 | --repeat-last-n [default: 64] 58 | --gqa [default: 8] 59 | -h, --help Print help 60 | -V, --version Print version 61 | ``` 62 | 63 | ### License 64 | 65 | None. 66 | 67 | ### Feedback 68 | 69 | Feel free to submit issues to this repository. 70 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp06_jsoninput/src/main.rs: -------------------------------------------------------------------------------- 1 | use axum::{ 2 | extract::{Form, Json, Query}, 3 | response::Html, 4 | routing::{get, post}, 5 | Router, 6 | }; 7 | use serde::Deserialize; 8 | use tower_http::trace::TraceLayer; 9 | 10 | #[allow(dead_code)] 11 | #[derive(Debug, Deserialize)] 12 | struct Params { 13 | foo: Option, 14 | bar: Option, 15 | } 16 | 17 | #[tokio::main] 18 | async fn main() { 19 | tracing_subscriber::fmt::init(); 20 | 21 | let app = Router::new() 22 | .route("/", get(handler)) 23 | .route("/query", get(query)) 24 | .route("/form", get(show_form).post(accept_form)) 25 | .route("/json", post(accept_json)) 26 | .layer(TraceLayer::new_for_http()); 27 | 28 | // run it 29 | let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") 30 | .await 31 | .unwrap(); 32 | tracing::debug!("listening on {}", listener.local_addr().unwrap()); 33 | axum::serve(listener, app).await.unwrap(); 34 | } 35 | 36 | async fn handler() -> Html<&'static str> { 37 | Html("

Hello, World!

") 38 | } 39 | 40 | async fn query(Query(params): Query) -> Html<&'static str> { 41 | tracing::debug!("query params {:?}", params); 42 | Html("

Test query

") 43 | } 44 | 45 | async fn show_form() -> Html<&'static str> { 46 | Html( 47 | r#" 48 | 49 | 50 | 51 | 52 |
53 | 57 | 58 | 62 | 63 | 64 |
65 | 66 | 67 | "#, 68 | ) 69 | } 70 | 71 | #[allow(dead_code)] 72 | #[derive(Deserialize, Debug)] 73 | struct Input { 74 | name: String, 75 | email: String, 76 | } 77 | 78 | async fn accept_form(Form(input): Form) -> Html<&'static str> { 79 | tracing::debug!("form params {:?}", input); 80 | 81 | Html("

Form posted

") 82 | } 83 | 84 | async fn accept_json(Json(input): Json) -> Html<&'static str> { 85 | tracing::debug!("json params {:?}", input); 86 | Html("

Json posted

") 87 | } 88 | -------------------------------------------------------------------------------- /14-getinfo/src/server.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use tokio::io::{AsyncReadExt, AsyncWriteExt}; 3 | use tokio::net::TcpListener; 4 | use tokio::process::Command; 5 | 6 | #[tokio::main] 7 | async fn main() -> Result<(), Box> { 8 | let addr = env::args() 9 | .nth(1) 10 | .unwrap_or_else(|| "127.0.0.1:8888".to_string()); 11 | println!("Listening on: {}", addr); 12 | let listener = TcpListener::bind(&addr).await?; 13 | 14 | // 注意这里是一个无条件循环,表明始终处于服务状态 15 | loop { 16 | // 等待客户端请求连上来 17 | let (mut socket, _) = listener.accept().await?; 18 | 19 | // 来一个客户端连接,创建一个对应的新任务 20 | tokio::spawn(async move { 21 | // 分配一个缓冲存 22 | let mut buf = [0; 1024]; 23 | let mut offset = 0; 24 | // 循环读,因为不能确保一次能从网络线路上读完数据 25 | loop { 26 | // 读操作,返回的n表示读了多少个字节 27 | // 正常情况下,读到数据才会返回,如果没有读到,就会等待 28 | let n = socket 29 | .read(&mut buf[offset..]) 30 | .await 31 | .expect("failed to read data from socket"); 32 | 33 | // n返回0的情况,是碰到了EOF,表明远端的写操作已断开,这个一定要判断 34 | if n == 0 { 35 | // 碰到了EOF就直接返回结束此任务,因为后面的操作没了意义 36 | return; 37 | } 38 | 39 | println!("offset: {offset}, n: {n}"); 40 | let end = offset + n; 41 | // 转换指令为字符串 42 | if let Ok(directive) = std::str::from_utf8(&buf[..end]) { 43 | println!("{directive}"); 44 | // 执行指令对应的工作 45 | let output = process(directive).await; 46 | println!("{output}"); 47 | // 向客户端返回处理结果 48 | socket 49 | .write_all(&output.as_bytes()) 50 | .await 51 | .expect("failed to write data to socket"); 52 | } else { 53 | // 判断是否转换失败,如果失败,就有可能是网络上的数据还没读完 54 | // 要继续loop读下一波数据 55 | offset = end; 56 | } 57 | } 58 | }); 59 | } 60 | } 61 | 62 | async fn process(directive: &str) -> String { 63 | if directive == "gettime" { 64 | // 这里我们用了unwrap()是因为我们一般确信执行date命令不会失败 65 | // 更可靠的作法是对返回的Result作处理 66 | let output = Command::new("date").output().await.unwrap(); 67 | String::from_utf8(output.stdout).unwrap() 68 | } else { 69 | // 如果是其它指令,我们目前返回 无效指令 70 | "invalid command".to_owned() 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /23-candle_chat/src/token_output_stream.rs: -------------------------------------------------------------------------------- 1 | use candle_core::Result; 2 | 3 | /// This is a wrapper around a tokenizer to ensure that tokens can be returned to the user in a 4 | /// streaming way rather than having to wait for the full decoding. 5 | pub struct TokenOutputStream { 6 | tokenizer: tokenizers::Tokenizer, 7 | tokens: Vec, 8 | prev_index: usize, 9 | current_index: usize, 10 | } 11 | 12 | impl TokenOutputStream { 13 | pub fn new(tokenizer: tokenizers::Tokenizer) -> Self { 14 | Self { 15 | tokenizer, 16 | tokens: Vec::new(), 17 | prev_index: 0, 18 | current_index: 0, 19 | } 20 | } 21 | 22 | pub fn into_inner(self) -> tokenizers::Tokenizer { 23 | self.tokenizer 24 | } 25 | 26 | fn decode(&self, tokens: &[u32]) -> Result { 27 | match self.tokenizer.decode(tokens, true) { 28 | Ok(str) => Ok(str), 29 | Err(err) => candle_core::bail!("cannot decode: {err}"), 30 | } 31 | } 32 | 33 | // https://github.com/huggingface/text-generation-inference/blob/5ba53d44a18983a4de32d122f4cb46f4a17d9ef6/server/text_generation_server/models/model.py#L68 34 | pub fn next_token(&mut self, token: u32) -> Result> { 35 | let prev_text = if self.tokens.is_empty() { 36 | String::new() 37 | } else { 38 | let tokens = &self.tokens[self.prev_index..self.current_index]; 39 | self.decode(tokens)? 40 | }; 41 | self.tokens.push(token); 42 | let text = self.decode(&self.tokens[self.prev_index..])?; 43 | if text.len() > prev_text.len() && text.chars().last().unwrap().is_ascii() { 44 | let text = text.split_at(prev_text.len()); 45 | self.prev_index = self.current_index; 46 | self.current_index = self.tokens.len(); 47 | Ok(Some(text.1.to_string())) 48 | } else { 49 | Ok(None) 50 | } 51 | } 52 | 53 | pub fn decode_rest(&self) -> Result> { 54 | let prev_text = if self.tokens.is_empty() { 55 | String::new() 56 | } else { 57 | let tokens = &self.tokens[self.prev_index..self.current_index]; 58 | self.decode(tokens)? 59 | }; 60 | let text = self.decode(&self.tokens[self.prev_index..])?; 61 | if text.len() > prev_text.len() { 62 | let text = text.split_at(prev_text.len()); 63 | Ok(Some(text.1.to_string())) 64 | } else { 65 | Ok(None) 66 | } 67 | } 68 | 69 | pub fn decode_all(&self) -> Result { 70 | self.decode(&self.tokens) 71 | } 72 | 73 | pub fn get_token(&self, token_s: &str) -> Option { 74 | self.tokenizer.get_vocab(true).get(token_s).copied() 75 | } 76 | 77 | pub fn tokenizer(&self) -> &tokenizers::Tokenizer { 78 | &self.tokenizer 79 | } 80 | 81 | pub fn clear(&mut self) { 82 | self.tokens.clear(); 83 | self.prev_index = 0; 84 | self.current_index = 0; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /25-slint-chatbot-demo/src/token_output_stream.rs: -------------------------------------------------------------------------------- 1 | use candle_core::Result; 2 | 3 | /// This is a wrapper around a tokenizer to ensure that tokens can be returned to the user in a 4 | /// streaming way rather than having to wait for the full decoding. 5 | pub struct TokenOutputStream { 6 | tokenizer: tokenizers::Tokenizer, 7 | tokens: Vec, 8 | prev_index: usize, 9 | current_index: usize, 10 | } 11 | 12 | impl TokenOutputStream { 13 | pub fn new(tokenizer: tokenizers::Tokenizer) -> Self { 14 | Self { 15 | tokenizer, 16 | tokens: Vec::new(), 17 | prev_index: 0, 18 | current_index: 0, 19 | } 20 | } 21 | 22 | pub fn into_inner(self) -> tokenizers::Tokenizer { 23 | self.tokenizer 24 | } 25 | 26 | fn decode(&self, tokens: &[u32]) -> Result { 27 | match self.tokenizer.decode(tokens, true) { 28 | Ok(str) => Ok(str), 29 | Err(err) => candle_core::bail!("cannot decode: {err}"), 30 | } 31 | } 32 | 33 | // https://github.com/huggingface/text-generation-inference/blob/5ba53d44a18983a4de32d122f4cb46f4a17d9ef6/server/text_generation_server/models/model.py#L68 34 | pub fn next_token(&mut self, token: u32) -> Result> { 35 | let prev_text = if self.tokens.is_empty() { 36 | String::new() 37 | } else { 38 | let tokens = &self.tokens[self.prev_index..self.current_index]; 39 | self.decode(tokens)? 40 | }; 41 | self.tokens.push(token); 42 | let text = self.decode(&self.tokens[self.prev_index..])?; 43 | if text.len() > prev_text.len() && text.chars().last().unwrap().is_ascii() { 44 | let text = text.split_at(prev_text.len()); 45 | self.prev_index = self.current_index; 46 | self.current_index = self.tokens.len(); 47 | Ok(Some(text.1.to_string())) 48 | } else { 49 | Ok(None) 50 | } 51 | } 52 | 53 | pub fn decode_rest(&self) -> Result> { 54 | let prev_text = if self.tokens.is_empty() { 55 | String::new() 56 | } else { 57 | let tokens = &self.tokens[self.prev_index..self.current_index]; 58 | self.decode(tokens)? 59 | }; 60 | let text = self.decode(&self.tokens[self.prev_index..])?; 61 | if text.len() > prev_text.len() { 62 | let text = text.split_at(prev_text.len()); 63 | Ok(Some(text.1.to_string())) 64 | } else { 65 | Ok(None) 66 | } 67 | } 68 | 69 | pub fn decode_all(&self) -> Result { 70 | self.decode(&self.tokens) 71 | } 72 | 73 | pub fn get_token(&self, token_s: &str) -> Option { 74 | self.tokenizer.get_vocab(true).get(token_s).copied() 75 | } 76 | 77 | pub fn tokenizer(&self) -> &tokenizers::Tokenizer { 78 | &self.tokenizer 79 | } 80 | 81 | pub fn clear(&mut self) { 82 | self.tokens.clear(); 83 | self.prev_index = 0; 84 | self.current_index = 0; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp07_jsonres/src/main.rs: -------------------------------------------------------------------------------- 1 | use axum::{ 2 | extract::{Form, Json, Query}, 3 | response::{Html, IntoResponse}, 4 | routing::{get, post}, 5 | Router, 6 | }; 7 | use serde::{Serialize, Deserialize}; 8 | use serde_json::json; 9 | use tower_http::trace::TraceLayer; 10 | 11 | #[allow(dead_code)] 12 | #[derive(Debug, Deserialize)] 13 | struct Params { 14 | foo: Option, 15 | bar: Option, 16 | } 17 | 18 | #[tokio::main] 19 | async fn main() { 20 | tracing_subscriber::fmt::init(); 21 | 22 | let app = Router::new() 23 | .route("/", get(handler)) 24 | .route("/query", get(query)) 25 | .route("/form", get(show_form).post(accept_form)) 26 | .route("/json", post(accept_json)) 27 | .route("/resjson", post(res_json)) 28 | .route("/resjson2", post(res_json2)) 29 | .layer(TraceLayer::new_for_http()); 30 | 31 | // run it 32 | let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") 33 | .await 34 | .unwrap(); 35 | tracing::debug!("listening on {}", listener.local_addr().unwrap()); 36 | axum::serve(listener, app).await.unwrap(); 37 | } 38 | 39 | async fn handler() -> Html<&'static str> { 40 | Html("

Hello, World!

") 41 | } 42 | 43 | async fn query(Query(params): Query) -> Html<&'static str> { 44 | tracing::debug!("query params {:?}", params); 45 | Html("

Test query

") 46 | } 47 | 48 | async fn show_form() -> Html<&'static str> { 49 | Html( 50 | r#" 51 | 52 | 53 | 54 | 55 |
56 | 60 | 61 | 65 | 66 | 67 |
68 | 69 | 70 | "#, 71 | ) 72 | } 73 | 74 | #[allow(dead_code)] 75 | #[derive(Deserialize, Debug)] 76 | struct Input { 77 | name: String, 78 | email: String, 79 | } 80 | 81 | async fn accept_form(Form(input): Form) -> Html<&'static str> { 82 | tracing::debug!("form params {:?}", input); 83 | 84 | Html("

Form posted

") 85 | } 86 | 87 | async fn accept_json(Json(input): Json) -> Html<&'static str> { 88 | tracing::debug!("json params {:?}", input); 89 | Html("

Json posted

") 90 | } 91 | 92 | async fn res_json(Json(input): Json) -> impl IntoResponse { 93 | tracing::debug!("json params {:?}", input); 94 | Json(json!({ 95 | "result": "ok", 96 | "number": 1, 97 | })) 98 | } 99 | 100 | #[allow(dead_code)] 101 | #[derive(Serialize, Debug)] 102 | struct Output { 103 | name: String, 104 | age: u32, 105 | } 106 | 107 | async fn res_json2(Json(input): Json) -> impl IntoResponse { 108 | tracing::debug!("json params {:?}", input); 109 | 110 | let a = Output { 111 | name: "mike".to_string(), 112 | age: 20, 113 | }; 114 | Json(serde_json::to_value(a).unwrap()) 115 | } 116 | -------------------------------------------------------------------------------- /27-bevy_snake/snake07_moveongrid/src/main.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | const SNAKE_HEAD_COLOR: Color = Color::rgb(0.7, 0.7, 0.7); 4 | const SNAKE_SEGMENT_COLOR: Color = Color::rgb(0.3, 0.3, 0.3); 5 | const ARENA_WIDTH: u32 = 10; 6 | const ARENA_HEIGHT: u32 = 10; 7 | 8 | 9 | #[derive(Component)] 10 | struct SnakeHead; 11 | 12 | #[derive(Component, Clone, Copy, PartialEq, Eq)] 13 | struct Position { 14 | x: i32, 15 | y: i32, 16 | } 17 | 18 | #[derive(Component)] 19 | struct Size { 20 | width: f32, 21 | height: f32, 22 | } 23 | 24 | impl Size { 25 | pub fn square(x: f32) -> Self { 26 | Self { 27 | width: x, 28 | height: x, 29 | } 30 | } 31 | } 32 | 33 | 34 | 35 | fn main() { 36 | App::new() 37 | .add_plugins(DefaultPlugins) 38 | .add_systems(Startup, (setup_camera, spawn_snake)) 39 | .add_systems(Update, (snake_movement, size_scaling, position_translation)) 40 | .run(); 41 | } 42 | 43 | fn setup_camera(mut commands: Commands) { 44 | commands.spawn(Camera2dBundle::default()); 45 | } 46 | 47 | fn spawn_snake(mut commands: Commands) { 48 | commands 49 | .spawn(SpriteBundle { 50 | sprite: Sprite { 51 | color: SNAKE_HEAD_COLOR, 52 | ..default() 53 | }, 54 | transform: Transform { 55 | scale: Vec3::new(10.0, 10.0, 10.0), 56 | ..default() 57 | }, 58 | ..default() 59 | }) 60 | .insert(SnakeHead) 61 | .insert(Position { x: 3, y: 3 }) 62 | .insert(Size::square(0.8)); 63 | } 64 | 65 | fn snake_movement( 66 | keyboard_input: Res>, 67 | mut head_positions: Query<&mut Position, With>, 68 | ) { 69 | for mut pos in head_positions.iter_mut() { 70 | if keyboard_input.pressed(KeyCode::Left) { 71 | pos.x -= 1; 72 | } 73 | if keyboard_input.pressed(KeyCode::Right) { 74 | pos.x += 1; 75 | } 76 | if keyboard_input.pressed(KeyCode::Down) { 77 | pos.y -= 1; 78 | } 79 | if keyboard_input.pressed(KeyCode::Up) { 80 | pos.y += 1; 81 | } 82 | } 83 | } 84 | 85 | fn size_scaling(primary_query: Query<&Window, With>, mut q: Query<(&Size, &mut Transform)>) { 86 | let window = primary_query.get_single().unwrap(); 87 | for (sprite_size, mut transform) in q.iter_mut() { 88 | transform.scale = Vec3::new( 89 | sprite_size.width / ARENA_WIDTH as f32 * window.width() as f32, 90 | sprite_size.height / ARENA_HEIGHT as f32 * window.height() as f32, 91 | 1.0, 92 | ); 93 | } 94 | } 95 | 96 | fn position_translation(primary_query: Query<&Window, With>, mut q: Query<(&Position, &mut Transform)>) { 97 | fn convert(pos: f32, bound_window: f32, bound_game: f32) -> f32 { 98 | let tile_size = bound_window / bound_game; 99 | pos / bound_game * bound_window - (bound_window / 2.) + (tile_size / 2.) 100 | } 101 | let window = primary_query.get_single().unwrap(); 102 | for (pos, mut transform) in q.iter_mut() { 103 | transform.translation = Vec3::new( 104 | convert(pos.x as f32, window.width() as f32, ARENA_WIDTH as f32), 105 | convert(pos.y as f32, window.height() as f32, ARENA_HEIGHT as f32), 106 | 0.0, 107 | ); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /2122-axumapp_stepbystep/axumapp08_global404/src/main.rs: -------------------------------------------------------------------------------- 1 | use axum::{ 2 | extract::{Form, Json, Query}, 3 | http::StatusCode, 4 | response::{Html, IntoResponse}, 5 | routing::{get, post}, 6 | Router, 7 | }; 8 | use serde::{Serialize, Deserialize}; 9 | use serde_json::json; 10 | use tower_http::trace::TraceLayer; 11 | 12 | #[allow(dead_code)] 13 | #[derive(Debug, Deserialize)] 14 | struct Params { 15 | foo: Option, 16 | bar: Option, 17 | } 18 | 19 | #[tokio::main] 20 | async fn main() { 21 | tracing_subscriber::fmt::init(); 22 | 23 | let app = Router::new() 24 | .route("/", get(handler)) 25 | .route("/query", get(query)) 26 | .route("/form", get(show_form).post(accept_form)) 27 | .route("/json", post(accept_json)) 28 | .route("/resjson", post(res_json)) 29 | .route("/resjson2", post(res_json2)) 30 | .layer(TraceLayer::new_for_http()) 31 | .fallback(handler_404); 32 | 33 | // run it 34 | let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") 35 | .await 36 | .unwrap(); 37 | tracing::debug!("listening on {}", listener.local_addr().unwrap()); 38 | axum::serve(listener, app).await.unwrap(); 39 | } 40 | 41 | async fn handler() -> Html<&'static str> { 42 | Html("

Hello, World!

") 43 | } 44 | 45 | async fn query(Query(params): Query) -> Html<&'static str> { 46 | tracing::debug!("query params {:?}", params); 47 | Html("

Test query

") 48 | } 49 | 50 | async fn show_form() -> Html<&'static str> { 51 | Html( 52 | r#" 53 | 54 | 55 | 56 | 57 |
58 | 62 | 63 | 67 | 68 | 69 |
70 | 71 | 72 | "#, 73 | ) 74 | } 75 | 76 | #[allow(dead_code)] 77 | #[derive(Deserialize, Debug)] 78 | struct Input { 79 | name: String, 80 | email: String, 81 | } 82 | 83 | async fn accept_form(Form(input): Form) -> Html<&'static str> { 84 | tracing::debug!("form params {:?}", input); 85 | 86 | Html("

Form posted

") 87 | } 88 | 89 | async fn accept_json(Json(input): Json) -> Html<&'static str> { 90 | tracing::debug!("json params {:?}", input); 91 | Html("

Json posted

") 92 | } 93 | 94 | async fn res_json(Json(input): Json) -> impl IntoResponse { 95 | tracing::debug!("json params {:?}", input); 96 | Json(json!({ 97 | "result": "ok", 98 | "number": 1, 99 | })) 100 | } 101 | 102 | #[allow(dead_code)] 103 | #[derive(Serialize, Debug)] 104 | struct Output { 105 | name: String, 106 | age: u32, 107 | } 108 | 109 | async fn res_json2(Json(input): Json) -> impl IntoResponse { 110 | tracing::debug!("json params {:?}", input); 111 | 112 | let a = Output { 113 | name: "mike".to_string(), 114 | age: 20, 115 | }; 116 | Json(serde_json::to_value(a).unwrap()) 117 | } 118 | 119 | async fn handler_404() -> impl IntoResponse { 120 | (StatusCode::NOT_FOUND, "nothing to see here") 121 | } 122 | -------------------------------------------------------------------------------- /27-bevy_snake/snake06_grid/src/main.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | const SNAKE_HEAD_COLOR: Color = Color::rgb(0.7, 0.7, 0.7); 4 | const SNAKE_SEGMENT_COLOR: Color = Color::rgb(0.3, 0.3, 0.3); 5 | const ARENA_WIDTH: u32 = 10; 6 | const ARENA_HEIGHT: u32 = 10; 7 | 8 | 9 | #[derive(Component)] 10 | struct SnakeHead; 11 | 12 | #[derive(Component, Clone, Copy, PartialEq, Eq)] 13 | struct Position { 14 | x: i32, 15 | y: i32, 16 | } 17 | 18 | #[derive(Component)] 19 | struct Size { 20 | width: f32, 21 | height: f32, 22 | } 23 | 24 | impl Size { 25 | pub fn square(x: f32) -> Self { 26 | Self { 27 | width: x, 28 | height: x, 29 | } 30 | } 31 | } 32 | 33 | 34 | 35 | fn main() { 36 | App::new() 37 | .add_plugins(DefaultPlugins) 38 | .add_systems(Startup, (setup_camera, spawn_snake)) 39 | .add_systems(Update, (snake_movement, size_scaling, position_translation)) 40 | .run(); 41 | } 42 | 43 | fn setup_camera(mut commands: Commands) { 44 | commands.spawn(Camera2dBundle::default()); 45 | } 46 | 47 | fn spawn_snake(mut commands: Commands) { 48 | commands 49 | .spawn(SpriteBundle { 50 | sprite: Sprite { 51 | color: SNAKE_HEAD_COLOR, 52 | ..default() 53 | }, 54 | transform: Transform { 55 | scale: Vec3::new(10.0, 10.0, 10.0), 56 | ..default() 57 | }, 58 | ..default() 59 | }) 60 | .insert(SnakeHead) 61 | .insert(Position { x: 3, y: 3 }) 62 | .insert(Size::square(0.8)); 63 | } 64 | 65 | fn snake_movement( 66 | keyboard_input: Res>, 67 | mut head_positions: Query<&mut Transform, With>, 68 | ) { 69 | for mut transform in head_positions.iter_mut() { 70 | if keyboard_input.pressed(KeyCode::Left) { 71 | transform.translation.x -= 2.; 72 | } 73 | if keyboard_input.pressed(KeyCode::Right) { 74 | transform.translation.x += 2.; 75 | } 76 | if keyboard_input.pressed(KeyCode::Down) { 77 | transform.translation.y -= 2.; 78 | } 79 | if keyboard_input.pressed(KeyCode::Up) { 80 | transform.translation.y += 2.; 81 | } 82 | } 83 | } 84 | 85 | fn size_scaling(primary_query: Query<&Window, With>, mut q: Query<(&Size, &mut Transform)>) { 86 | let window = primary_query.get_single().unwrap(); 87 | for (sprite_size, mut transform) in q.iter_mut() { 88 | transform.scale = Vec3::new( 89 | sprite_size.width / ARENA_WIDTH as f32 * window.width() as f32, 90 | sprite_size.height / ARENA_HEIGHT as f32 * window.height() as f32, 91 | 1.0, 92 | ); 93 | } 94 | } 95 | 96 | fn position_translation(primary_query: Query<&Window, With>, mut q: Query<(&Position, &mut Transform)>) { 97 | fn convert(pos: f32, bound_window: f32, bound_game: f32) -> f32 { 98 | let tile_size = bound_window / bound_game; 99 | pos / bound_game * bound_window - (bound_window / 2.) + (tile_size / 2.) 100 | } 101 | 102 | let window = primary_query.get_single().unwrap(); 103 | for (pos, mut transform) in q.iter_mut() { 104 | transform.translation = Vec3::new( 105 | convert(pos.x as f32, window.width() as f32, ARENA_WIDTH as f32), 106 | convert(pos.y as f32, window.height() as f32, ARENA_HEIGHT as f32), 107 | 0.0, 108 | ); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /26-slint-yolov8-demo/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::{path::PathBuf, sync::mpsc::channel}; 2 | 3 | use native_dialog::FileDialog; 4 | use slint::{Image, Rgba8Pixel, SharedPixelBuffer}; 5 | 6 | slint::include_modules!(); 7 | 8 | mod yolov8engine; 9 | 10 | fn main() -> Result<(), slint::PlatformError> { 11 | let ui = AppWindow::new()?; 12 | 13 | let ui_handle = ui.as_weak(); 14 | ui.on_select_orig_pic(move || { 15 | let ui = ui_handle.unwrap(); 16 | 17 | let path = FileDialog::new() 18 | .set_location("~") 19 | .add_filter("Pics", &["png", "jpg", "jpeg"]) 20 | .show_open_single_file() 21 | .unwrap(); 22 | 23 | // if selected pic file 24 | if let Some(path) = path { 25 | ui.set_orig_image_path(path.to_string_lossy().to_string().into()); 26 | ui.set_orig_image(load_image(path)); 27 | } 28 | }); 29 | 30 | let (sender, receiver) = channel::<(String, String)>(); 31 | let sender1 = sender.clone(); 32 | let sender2 = sender.clone(); 33 | 34 | let ui_handle = ui.as_weak(); 35 | let _thread = std::thread::spawn(move || { 36 | loop { 37 | let ui_handle = ui_handle.clone(); 38 | let (task, img_path) = receiver.recv().unwrap(); 39 | if task.as_str() == "_exit_" { 40 | // end of this thread 41 | return; 42 | } 43 | 44 | let (task, model) = if task.as_str() == "detect" { 45 | ( 46 | yolov8engine::YoloTask::Detect, 47 | Some("yolov8m.safetensors".to_string()), 48 | ) 49 | } else { 50 | ( 51 | yolov8engine::YoloTask::Pose, 52 | Some("yolov8m-pose.safetensors".to_string()), 53 | ) 54 | }; 55 | 56 | if let Ok(path) = yolov8engine::start_engine(task, model, img_path) { 57 | _ = slint::invoke_from_event_loop(move || { 58 | let ui = ui_handle.unwrap(); 59 | ui.set_generated_image(load_image(PathBuf::from(path))); 60 | }); 61 | // ui.set_generated_image(load_image(PathBuf::from(path))); 62 | } else { 63 | } 64 | } 65 | }); 66 | 67 | let ui_handle = ui.as_weak(); 68 | ui.on_probe_objects(move || { 69 | let ui = ui_handle.unwrap(); 70 | let img_path = ui.get_orig_image_path().to_string(); 71 | println!("{}", img_path); 72 | _ = sender.send(("detect".to_string(), img_path)); 73 | }); 74 | 75 | let ui_handle = ui.as_weak(); 76 | ui.on_probe_poses(move || { 77 | let ui = ui_handle.unwrap(); 78 | let img_path = ui.get_orig_image_path().to_string(); 79 | println!("{}", img_path); 80 | _ = sender1.send(("pose".to_string(), img_path)); 81 | }); 82 | 83 | ui.window().on_close_requested(move || { 84 | sender2 85 | .send(("_exit_".to_string(), "".to_string())) 86 | .unwrap(); 87 | slint::CloseRequestResponse::HideWindow 88 | }); 89 | 90 | ui.run() 91 | } 92 | 93 | fn load_image(path: std::path::PathBuf) -> slint::Image { 94 | let mut a_image = image::open(path).expect("Error loading image").into_rgba8(); 95 | 96 | image::imageops::colorops::brighten_in_place(&mut a_image, 20); 97 | 98 | let buffer = SharedPixelBuffer::::clone_from_slice( 99 | a_image.as_raw(), 100 | a_image.width(), 101 | a_image.height(), 102 | ); 103 | let image = Image::from_rgba8(buffer); 104 | 105 | image 106 | } 107 | -------------------------------------------------------------------------------- /27-bevy_snake/snake08_configwindow/src/main.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | const SNAKE_HEAD_COLOR: Color = Color::rgb(0.7, 0.7, 0.7); 4 | const SNAKE_SEGMENT_COLOR: Color = Color::rgb(0.3, 0.3, 0.3); 5 | const ARENA_WIDTH: u32 = 25; 6 | const ARENA_HEIGHT: u32 = 25; 7 | 8 | 9 | #[derive(Component)] 10 | struct SnakeHead; 11 | 12 | #[derive(Component, Clone, Copy, PartialEq, Eq)] 13 | struct Position { 14 | x: i32, 15 | y: i32, 16 | } 17 | 18 | #[derive(Component)] 19 | struct Size { 20 | width: f32, 21 | height: f32, 22 | } 23 | 24 | impl Size { 25 | pub fn square(x: f32) -> Self { 26 | Self { 27 | width: x, 28 | height: x, 29 | } 30 | } 31 | } 32 | 33 | 34 | 35 | fn main() { 36 | App::new() 37 | // .add_plugins(DefaultPlugins) 38 | .add_plugins(DefaultPlugins.set(WindowPlugin { 39 | primary_window: Some( Window { 40 | title: "Snake!".to_string(), 41 | resolution: bevy::window::WindowResolution::new( 500.0, 500.0 ), 42 | ..default() 43 | }), 44 | ..default() 45 | }) 46 | ) 47 | .insert_resource(ClearColor(Color::rgb(0.04, 0.04, 0.04))) 48 | .add_systems(Startup, (setup_camera, spawn_snake)) 49 | .add_systems(Update, (snake_movement, size_scaling, position_translation)) 50 | .run(); 51 | } 52 | 53 | fn setup_camera(mut commands: Commands) { 54 | commands.spawn(Camera2dBundle::default()); 55 | } 56 | 57 | fn spawn_snake(mut commands: Commands) { 58 | commands 59 | .spawn(SpriteBundle { 60 | sprite: Sprite { 61 | color: SNAKE_HEAD_COLOR, 62 | ..default() 63 | }, 64 | transform: Transform { 65 | scale: Vec3::new(10.0, 10.0, 10.0), 66 | ..default() 67 | }, 68 | ..default() 69 | }) 70 | .insert(SnakeHead) 71 | .insert(Position { x: 3, y: 3 }) 72 | .insert(Size::square(0.8)); 73 | } 74 | 75 | fn snake_movement( 76 | keyboard_input: Res>, 77 | mut head_positions: Query<&mut Position, With>, 78 | ) { 79 | for mut pos in head_positions.iter_mut() { 80 | if keyboard_input.just_pressed(KeyCode::Left) { 81 | pos.x -= 1; 82 | } 83 | if keyboard_input.just_pressed(KeyCode::Right) { 84 | pos.x += 1; 85 | } 86 | if keyboard_input.just_pressed(KeyCode::Down) { 87 | pos.y -= 1; 88 | } 89 | if keyboard_input.just_pressed(KeyCode::Up) { 90 | pos.y += 1; 91 | } 92 | } 93 | } 94 | 95 | fn size_scaling(primary_query: Query<&Window, With>, mut q: Query<(&Size, &mut Transform)>) { 96 | let window = primary_query.get_single().unwrap(); 97 | for (sprite_size, mut transform) in q.iter_mut() { 98 | transform.scale = Vec3::new( 99 | sprite_size.width / ARENA_WIDTH as f32 * window.width() as f32, 100 | sprite_size.height / ARENA_HEIGHT as f32 * window.height() as f32, 101 | 1.0, 102 | ); 103 | } 104 | } 105 | 106 | fn position_translation(primary_query: Query<&Window, With>, mut q: Query<(&Position, &mut Transform)>) { 107 | fn convert(pos: f32, bound_window: f32, bound_game: f32) -> f32 { 108 | let tile_size = bound_window / bound_game; 109 | pos / bound_game * bound_window - (bound_window / 2.) + (tile_size / 2.) 110 | } 111 | let window = primary_query.get_single().unwrap(); 112 | for (pos, mut transform) in q.iter_mut() { 113 | transform.translation = Vec3::new( 114 | convert(pos.x as f32, window.width() as f32, ARENA_WIDTH as f32), 115 | convert(pos.y as f32, window.height() as f32, ARENA_HEIGHT as f32), 116 | 0.0, 117 | ); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /27-bevy_snake/snake09_foodspawning/src/main.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use rand::prelude::random; 3 | 4 | 5 | const SNAKE_HEAD_COLOR: Color = Color::rgb(0.7, 0.7, 0.7); 6 | const SNAKE_SEGMENT_COLOR: Color = Color::rgb(0.3, 0.3, 0.3); 7 | const FOOD_COLOR: Color = Color::rgb(1.0, 0.0, 1.0); 8 | const ARENA_WIDTH: u32 = 20; 9 | const ARENA_HEIGHT: u32 = 20; 10 | 11 | 12 | #[derive(Component)] 13 | struct SnakeHead; 14 | 15 | #[derive(Component)] 16 | struct Food; 17 | 18 | 19 | 20 | #[derive(Component, Clone, Copy, PartialEq, Eq)] 21 | struct Position { 22 | x: i32, 23 | y: i32, 24 | } 25 | 26 | #[derive(Component)] 27 | struct Size { 28 | width: f32, 29 | height: f32, 30 | } 31 | 32 | impl Size { 33 | pub fn square(x: f32) -> Self { 34 | Self { 35 | width: x, 36 | height: x, 37 | } 38 | } 39 | } 40 | 41 | 42 | 43 | fn main() { 44 | App::new() 45 | // .add_plugins(DefaultPlugins) 46 | .add_plugins(DefaultPlugins.set(WindowPlugin { 47 | primary_window: Some( Window { 48 | title: "Snake!".to_string(), 49 | resolution: bevy::window::WindowResolution::new( 500.0, 500.0 ), 50 | ..default() 51 | }), 52 | ..default() 53 | }) 54 | ) 55 | .insert_resource(ClearColor(Color::rgb(0.04, 0.04, 0.04))) 56 | .add_systems(Startup, (setup_camera, spawn_snake)) 57 | .add_systems(Update, (snake_movement, size_scaling, position_translation)) 58 | .add_systems(Update, food_spawner) 59 | .run(); 60 | } 61 | 62 | fn setup_camera(mut commands: Commands) { 63 | commands.spawn(Camera2dBundle::default()); 64 | } 65 | 66 | fn spawn_snake(mut commands: Commands) { 67 | commands 68 | .spawn(SpriteBundle { 69 | sprite: Sprite { 70 | color: SNAKE_HEAD_COLOR, 71 | ..default() 72 | }, 73 | transform: Transform { 74 | scale: Vec3::new(10.0, 10.0, 10.0), 75 | ..default() 76 | }, 77 | ..default() 78 | }) 79 | .insert(SnakeHead) 80 | .insert(Position { x: 3, y: 3 }) 81 | .insert(Size::square(0.8)); 82 | } 83 | 84 | fn snake_movement( 85 | keyboard_input: Res>, 86 | mut head_positions: Query<&mut Position, With>, 87 | ) { 88 | for mut pos in head_positions.iter_mut() { 89 | if keyboard_input.just_pressed(KeyCode::Left) { 90 | pos.x -= 1; 91 | } 92 | if keyboard_input.just_pressed(KeyCode::Right) { 93 | pos.x += 1; 94 | } 95 | if keyboard_input.just_pressed(KeyCode::Down) { 96 | pos.y -= 1; 97 | } 98 | if keyboard_input.just_pressed(KeyCode::Up) { 99 | pos.y += 1; 100 | } 101 | } 102 | } 103 | 104 | fn size_scaling(primary_query: Query<&Window, With>, mut q: Query<(&Size, &mut Transform)>) { 105 | let window = primary_query.get_single().unwrap(); 106 | for (sprite_size, mut transform) in q.iter_mut() { 107 | transform.scale = Vec3::new( 108 | sprite_size.width / ARENA_WIDTH as f32 * window.width() as f32, 109 | sprite_size.height / ARENA_HEIGHT as f32 * window.height() as f32, 110 | 1.0, 111 | ); 112 | } 113 | } 114 | 115 | fn position_translation(primary_query: Query<&Window, With>, mut q: Query<(&Position, &mut Transform)>) { 116 | fn convert(pos: f32, bound_window: f32, bound_game: f32) -> f32 { 117 | let tile_size = bound_window / bound_game; 118 | pos / bound_game * bound_window - (bound_window / 2.) + (tile_size / 2.) 119 | } 120 | let window = primary_query.get_single().unwrap(); 121 | for (pos, mut transform) in q.iter_mut() { 122 | transform.translation = Vec3::new( 123 | convert(pos.x as f32, window.width() as f32, ARENA_WIDTH as f32), 124 | convert(pos.y as f32, window.height() as f32, ARENA_HEIGHT as f32), 125 | 0.0, 126 | ); 127 | } 128 | } 129 | 130 | fn food_spawner(mut commands: Commands) { 131 | commands 132 | .spawn(SpriteBundle { 133 | sprite: Sprite { 134 | color: FOOD_COLOR, 135 | ..default() 136 | }, 137 | ..default() 138 | }) 139 | .insert(Food) 140 | .insert(Position { 141 | x: (random::() * ARENA_WIDTH as f32) as i32, 142 | y: (random::() * ARENA_HEIGHT as f32) as i32, 143 | }) 144 | .insert(Size::square(0.8)); 145 | } 146 | -------------------------------------------------------------------------------- /27-bevy_snake/snake10_foodtimer/src/main.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use rand::prelude::random; 3 | 4 | 5 | const SNAKE_HEAD_COLOR: Color = Color::rgb(0.7, 0.7, 0.7); 6 | // const SNAKE_SEGMENT_COLOR: Color = Color::rgb(0.3, 0.3, 0.3); 7 | const FOOD_COLOR: Color = Color::rgb(1.0, 0.0, 1.0); 8 | const ARENA_WIDTH: u32 = 20; 9 | const ARENA_HEIGHT: u32 = 20; 10 | 11 | 12 | #[derive(Resource)] 13 | struct FoodSpawnTimer(Timer); 14 | 15 | 16 | #[derive(Component)] 17 | struct SnakeHead; 18 | 19 | #[derive(Component)] 20 | struct Food; 21 | 22 | #[derive(Component, Clone, Copy, PartialEq, Eq)] 23 | struct Position { 24 | x: i32, 25 | y: i32, 26 | } 27 | 28 | #[derive(Component)] 29 | struct Size { 30 | width: f32, 31 | height: f32, 32 | } 33 | 34 | impl Size { 35 | pub fn square(x: f32) -> Self { 36 | Self { 37 | width: x, 38 | height: x, 39 | } 40 | } 41 | } 42 | 43 | 44 | 45 | fn main() { 46 | App::new() 47 | // .add_plugins(DefaultPlugins) 48 | .add_plugins(DefaultPlugins.set(WindowPlugin { 49 | primary_window: Some( Window { 50 | title: "Snake!".to_string(), 51 | resolution: bevy::window::WindowResolution::new( 500.0, 500.0 ), 52 | ..default() 53 | }), 54 | ..default() 55 | }) 56 | ) 57 | .insert_resource(ClearColor(Color::rgb(0.04, 0.04, 0.04))) 58 | .insert_resource(FoodSpawnTimer(Timer::from_seconds( 59 | 1.0, 60 | TimerMode::Repeating, 61 | ))) 62 | .add_systems(Startup, (setup_camera, spawn_snake)) 63 | .add_systems(Update, (snake_movement, size_scaling, position_translation)) 64 | .add_systems(Update, food_spawner) 65 | .run(); 66 | } 67 | 68 | fn setup_camera(mut commands: Commands) { 69 | commands.spawn(Camera2dBundle::default()); 70 | } 71 | 72 | fn spawn_snake(mut commands: Commands) { 73 | commands 74 | .spawn(SpriteBundle { 75 | sprite: Sprite { 76 | color: SNAKE_HEAD_COLOR, 77 | ..default() 78 | }, 79 | transform: Transform { 80 | scale: Vec3::new(10.0, 10.0, 10.0), 81 | ..default() 82 | }, 83 | ..default() 84 | }) 85 | .insert(SnakeHead) 86 | .insert(Position { x: 3, y: 3 }) 87 | .insert(Size::square(0.8)); 88 | } 89 | 90 | fn snake_movement( 91 | keyboard_input: Res>, 92 | mut head_positions: Query<&mut Position, With>, 93 | ) { 94 | for mut pos in head_positions.iter_mut() { 95 | if keyboard_input.just_pressed(KeyCode::Left) { 96 | pos.x -= 1; 97 | } 98 | if keyboard_input.just_pressed(KeyCode::Right) { 99 | pos.x += 1; 100 | } 101 | if keyboard_input.just_pressed(KeyCode::Down) { 102 | pos.y -= 1; 103 | } 104 | if keyboard_input.just_pressed(KeyCode::Up) { 105 | pos.y += 1; 106 | } 107 | } 108 | } 109 | 110 | fn size_scaling(primary_query: Query<&Window, With>, mut q: Query<(&Size, &mut Transform)>) { 111 | let window = primary_query.get_single().unwrap(); 112 | for (sprite_size, mut transform) in q.iter_mut() { 113 | transform.scale = Vec3::new( 114 | sprite_size.width / ARENA_WIDTH as f32 * window.width() as f32, 115 | sprite_size.height / ARENA_HEIGHT as f32 * window.height() as f32, 116 | 1.0, 117 | ); 118 | } 119 | } 120 | 121 | fn position_translation(primary_query: Query<&Window, With>, mut q: Query<(&Position, &mut Transform)>) { 122 | fn convert(pos: f32, bound_window: f32, bound_game: f32) -> f32 { 123 | let tile_size = bound_window / bound_game; 124 | pos / bound_game * bound_window - (bound_window / 2.) + (tile_size / 2.) 125 | } 126 | let window = primary_query.get_single().unwrap(); 127 | for (pos, mut transform) in q.iter_mut() { 128 | transform.translation = Vec3::new( 129 | convert(pos.x as f32, window.width() as f32, ARENA_WIDTH as f32), 130 | convert(pos.y as f32, window.height() as f32, ARENA_HEIGHT as f32), 131 | 0.0, 132 | ); 133 | } 134 | } 135 | 136 | fn food_spawner( 137 | mut commands: Commands, 138 | time: Res