├── S25_streams ├── profile_man.png ├── profile_woman.png ├── Cargo.toml ├── index.html └── src │ ├── main.rs │ ├── echo_server.rs │ ├── low_level_server.rs │ ├── ping_server.rs │ ├── file_server.rs │ ├── kv_server.rs │ └── basics.rs ├── S14_modules ├── src │ ├── repository.rs │ ├── borrow_system.rs │ ├── membership │ │ ├── member_management.rs │ │ └── mod.rs │ └── lib.rs └── Cargo.toml ├── meth-leb ├── .gitignore ├── www │ ├── dist │ │ ├── 85e05c94123b4ab615ea.wasm │ │ └── index.html │ ├── package.json │ ├── webpack.config.js │ ├── index.js │ └── index.html ├── .github │ └── dependabot.yml ├── tests │ └── web.rs ├── .appveyor.yml ├── src │ ├── utils.rs │ └── lib.rs ├── Cargo.toml ├── LICENSE_MIT ├── README.md ├── .travis.yml └── LICENSE_APACHE ├── s27-hello-wasm ├── .gitignore ├── package.json ├── .github │ └── dependabot.yml ├── src │ ├── lib.rs │ └── utils.rs ├── tests │ └── web.rs ├── .appveyor.yml ├── Cargo.toml ├── LICENSE_MIT ├── README.md └── .travis.yml ├── S00_hello_world ├── src │ └── main.rs └── Cargo.toml ├── S02_vectors ├── Cargo.toml └── src │ └── main.rs ├── S03_strings ├── Cargo.toml └── src │ └── main.rs ├── S07_structs ├── Cargo.toml └── src │ └── main.rs ├── S12_traits ├── Cargo.toml └── src │ └── main.rs ├── S16_testing ├── Cargo.toml └── src │ ├── lib.rs │ ├── accounting.rs │ └── membership.rs ├── S19_threads ├── Cargo.toml └── src │ ├── main.rs │ ├── basic.rs │ └── arc_and_mutex.rs ├── S01_variables ├── Cargo.toml └── src │ └── main.rs ├── S04_functions ├── Cargo.toml └── src │ └── main.rs ├── S06_ownership ├── Cargo.toml └── src │ └── main.rs ├── S08_lifetimes ├── Cargo.toml └── src │ └── main.rs ├── S11_generics ├── Cargo.toml └── src │ └── main.rs ├── S17_closures ├── Cargo.toml └── src │ ├── main.rs │ ├── repository.rs │ └── scenario.rs ├── S18_smart_pointers ├── Cargo.toml └── src │ ├── main.rs │ ├── boxing.rs │ └── rc_scenario.rs ├── S26_unsafe_coding ├── Cargo.toml └── src │ ├── simple_ffi.rs │ ├── main.rs │ └── advanced.rs ├── S13_built_in_traits ├── Cargo.toml └── src │ └── main.rs ├── S22_parallelism ├── Cargo.toml └── src │ └── main.rs ├── S05_control_flows ├── Cargo.toml └── src │ └── main.rs ├── S09_enums ├── Cargo.toml └── src │ └── main.rs ├── S10_pattern_matching ├── Cargo.toml └── src │ └── main.rs ├── S15_error_handling ├── Cargo.toml └── src │ └── main.rs ├── S20_channels ├── Cargo.toml └── src │ ├── main.rs │ ├── basic.rs │ ├── scenarios.rs │ └── problems.rs ├── S24_file_io ├── Cargo.toml └── src │ ├── main.rs │ ├── model.rs │ ├── basics.rs │ ├── advanced.rs │ └── data_generator.rs ├── S21_macros ├── Cargo.toml └── src │ ├── without_macro.rs │ ├── model.rs │ ├── samples.rs │ ├── with_macro.rs │ └── main.rs ├── proc_macros ├── Cargo.toml └── src │ └── lib.rs ├── S23_asynchronous_programming ├── Cargo.toml └── src │ ├── iot_sample.rs │ ├── main.rs │ ├── api_sample.rs │ └── metric_sample.rs ├── .github └── workflows │ └── rust.yml ├── .gitignore ├── Cargo.toml └── LICENSE /S25_streams/profile_man.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /S14_modules/src/repository.rs: -------------------------------------------------------------------------------- 1 | pub fn add() {} 2 | pub fn remove() {} 3 | pub fn list() {} 4 | -------------------------------------------------------------------------------- /meth-leb/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | bin/ 5 | pkg/ 6 | wasm-pack.log 7 | -------------------------------------------------------------------------------- /s27-hello-wasm/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | bin/ 5 | pkg/ 6 | wasm-pack.log 7 | -------------------------------------------------------------------------------- /S14_modules/src/borrow_system.rs: -------------------------------------------------------------------------------- 1 | pub fn borrow() {} 2 | pub fn giving_back() {} 3 | pub fn is_borrowable() {} 4 | -------------------------------------------------------------------------------- /S14_modules/src/membership/member_management.rs: -------------------------------------------------------------------------------- 1 | pub fn subscribe() {} 2 | pub fn unsubscribe() {} 3 | fn list() {} 4 | -------------------------------------------------------------------------------- /S25_streams/profile_woman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/rust-training/HEAD/S25_streams/profile_woman.png -------------------------------------------------------------------------------- /s27-hello-wasm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "g": "^2.0.1", 4 | "npm": "^11.0.0" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /S00_hello_world/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let name = "Burak Selim Senyurt"; 3 | println!("Hello, {name}!"); 4 | } 5 | -------------------------------------------------------------------------------- /S02_vectors/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S02_vectors" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S03_strings/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S03_strings" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S07_structs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S07_structs" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S12_traits/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S12_traits" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S14_modules/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S14_modules" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S16_testing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S16_testing" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S19_threads/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S19_threads" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S25_streams/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S25_streams" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S01_variables/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S01_variables" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S04_functions/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S04_functions" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S06_ownership/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S06_ownership" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S08_lifetimes/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S08_lifetimes" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S11_generics/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S11_generics" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S17_closures/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S17_closures" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S00_hello_world/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "SOO_hello_world" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S18_smart_pointers/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S18_smart_pointers" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S26_unsafe_coding/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S26_unsafe_coding" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /S13_built_in_traits/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S13_built_in_traits" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /meth-leb/www/dist/85e05c94123b4ab615ea.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buraksenyurt/rust-training/HEAD/meth-leb/www/dist/85e05c94123b4ab615ea.wasm -------------------------------------------------------------------------------- /S22_parallelism/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S22_parallelism" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | rayon = "1.10.0" 8 | -------------------------------------------------------------------------------- /S25_streams/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Sample Index Page 4 | 5 | 6 |

Rust is a system programming language

7 | 8 | -------------------------------------------------------------------------------- /S05_control_flows/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S05_control_flows" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | rand = "0.9.0-alpha.2" 8 | -------------------------------------------------------------------------------- /S09_enums/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S09_enums" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | rand = "0.9.0-alpha.2" 8 | chrono = "0.4.38" 9 | -------------------------------------------------------------------------------- /S10_pattern_matching/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S10_pattern_matching" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | rand = "0.9.0-alpha.2" 8 | -------------------------------------------------------------------------------- /S15_error_handling/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S15_error_handling" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | rand = "0.9.0-alpha.2" 8 | -------------------------------------------------------------------------------- /S20_channels/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S20_channels" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | rand = "0.8.5" 8 | tokio = { version = "1.41.1", features = ["full"] } 9 | -------------------------------------------------------------------------------- /meth-leb/.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "08:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /S24_file_io/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S24_file_io" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | rand = "0.9.0-beta.1" 8 | chrono = "0.4.39" 9 | crossterm = "0.28.1" 10 | -------------------------------------------------------------------------------- /s27-hello-wasm/.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "08:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /S21_macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S21_macros" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | proc_macros = { path = "../proc_macros" } 8 | log = "0.4.22" 9 | env_logger = "0.11.5" 10 | -------------------------------------------------------------------------------- /proc_macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "proc_macros" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | proc-macro = true 8 | 9 | [dependencies] 10 | quote = "1.0.37" 11 | syn = { version = "2.0.90", features = ["full"] } 12 | -------------------------------------------------------------------------------- /S23_asynchronous_programming/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "S23_async_await" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | reqwest = "0.12.9" 8 | tokio = { version = "1.42.0", features = ["full"] } 9 | rand = "0.9.0-beta.1" 10 | -------------------------------------------------------------------------------- /s27-hello-wasm/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod utils; 2 | 3 | use wasm_bindgen::prelude::*; 4 | 5 | #[wasm_bindgen] 6 | extern "C" { 7 | fn alert(s: &str); 8 | } 9 | 10 | #[wasm_bindgen] 11 | pub fn greet() { 12 | alert("Hello from the WASM World!"); 13 | } 14 | -------------------------------------------------------------------------------- /meth-leb/tests/web.rs: -------------------------------------------------------------------------------- 1 | //! Test suite for the Web and headless browsers. 2 | 3 | #![cfg(target_arch = "wasm32")] 4 | 5 | extern crate wasm_bindgen_test; 6 | use wasm_bindgen_test::*; 7 | 8 | wasm_bindgen_test_configure!(run_in_browser); 9 | 10 | #[wasm_bindgen_test] 11 | fn pass() { 12 | assert_eq!(1 + 1, 2); 13 | } 14 | -------------------------------------------------------------------------------- /s27-hello-wasm/tests/web.rs: -------------------------------------------------------------------------------- 1 | //! Test suite for the Web and headless browsers. 2 | 3 | #![cfg(target_arch = "wasm32")] 4 | 5 | extern crate wasm_bindgen_test; 6 | use wasm_bindgen_test::*; 7 | 8 | wasm_bindgen_test_configure!(run_in_browser); 9 | 10 | #[wasm_bindgen_test] 11 | fn pass() { 12 | assert_eq!(1 + 1, 2); 13 | } 14 | -------------------------------------------------------------------------------- /S14_modules/src/membership/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod member_management; 2 | 3 | struct Member { 4 | id: u32, 5 | full_name: String, 6 | level: u8, 7 | } 8 | 9 | impl Member { 10 | pub fn new(id: u32, full_name: String, level: u8) -> Self { 11 | Member { 12 | id, 13 | full_name, 14 | level, 15 | } 16 | } 17 | fn get_bonus() {} 18 | } 19 | -------------------------------------------------------------------------------- /meth-leb/.appveyor.yml: -------------------------------------------------------------------------------- 1 | install: 2 | - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe 3 | - if not defined RUSTFLAGS rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly 4 | - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin 5 | - rustc -V 6 | - cargo -V 7 | 8 | build: false 9 | 10 | test_script: 11 | - cargo test --locked 12 | -------------------------------------------------------------------------------- /s27-hello-wasm/.appveyor.yml: -------------------------------------------------------------------------------- 1 | install: 2 | - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe 3 | - if not defined RUSTFLAGS rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly 4 | - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin 5 | - rustc -V 6 | - cargo -V 7 | 8 | build: false 9 | 10 | test_script: 11 | - cargo test --locked 12 | -------------------------------------------------------------------------------- /S25_streams/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | mod basics; 4 | mod echo_server; 5 | mod file_server; 6 | mod kv_server; 7 | mod low_level_server; 8 | mod ping_server; 9 | 10 | fn main() -> io::Result<()> { 11 | // basics::run()?; 12 | // low_level_server::run()?; 13 | // ping_server::run(); 14 | // echo_server::run()?; 15 | // file_server::run()?; 16 | kv_server::run()?; 17 | Ok(()) 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Build 20 | run: cargo build --verbose 21 | - name: Run tests 22 | run: cargo test --verbose 23 | -------------------------------------------------------------------------------- /meth-leb/src/utils.rs: -------------------------------------------------------------------------------- 1 | pub fn set_panic_hook() { 2 | // When the `console_error_panic_hook` feature is enabled, we can call the 3 | // `set_panic_hook` function at least once during initialization, and then 4 | // we will get better error messages if our code ever panics. 5 | // 6 | // For more details see 7 | // https://github.com/rustwasm/console_error_panic_hook#readme 8 | #[cfg(feature = "console_error_panic_hook")] 9 | console_error_panic_hook::set_once(); 10 | } 11 | -------------------------------------------------------------------------------- /s27-hello-wasm/src/utils.rs: -------------------------------------------------------------------------------- 1 | pub fn set_panic_hook() { 2 | // When the `console_error_panic_hook` feature is enabled, we can call the 3 | // `set_panic_hook` function at least once during initialization, and then 4 | // we will get better error messages if our code ever panics. 5 | // 6 | // For more details see 7 | // https://github.com/rustwasm/console_error_panic_hook#readme 8 | #[cfg(feature = "console_error_panic_hook")] 9 | console_error_panic_hook::set_once(); 10 | } 11 | -------------------------------------------------------------------------------- /S24_file_io/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | mod advanced; 4 | mod basics; 5 | mod data_generator; 6 | mod model; 7 | /* 8 | Pek çok programlama dilinde olduğu gibi Rust tarafında da kullanışlı File I/O 9 | modüller ve fonksiyonellikleri vardır. Bu bölümde fiziki dosyalar ile ilgili Input/Output 10 | işlemlerine ait temel seviyede örneklere yer verilmektedir. 11 | */ 12 | fn main() -> io::Result<()> { 13 | // basics::run()?; 14 | data_generator::run()?; 15 | advanced::run()?; 16 | 17 | Ok(()) 18 | } 19 | -------------------------------------------------------------------------------- /meth-leb/www/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parabol-example", 3 | "version": "1.0.0", 4 | "description": "Rust + WASM ile parabol çizimi örneği", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "webpack serve --open", 8 | "build": "webpack" 9 | }, 10 | "author": "Burak Selim Senyurt", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "webpack": "^5.97.1", 14 | "webpack-cli": "^5.0.1", 15 | "webpack-dev-server": "^5.2.0" 16 | }, 17 | "dependencies": { 18 | "copy-webpack-plugin": "^12.0.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /S19_threads/src/main.rs: -------------------------------------------------------------------------------- 1 | use arc_and_mutex::*; 2 | // use basic::*; 3 | // use std::thread; 4 | 5 | mod arc_and_mutex; 6 | mod basic; 7 | 8 | fn main() { 9 | // Case #1 10 | // start_a_simple_thread(); 11 | // println!("After the thread calling"); 12 | 13 | // Case #2 14 | // move_keyword_error(); 15 | // move_keyword_success(); 16 | // multiple_threads_sample(); 17 | 18 | // run_with_error(); 19 | run_correctly(); 20 | // run_inconsistent(); 21 | // run_safely(); 22 | // run_mutex(); 23 | 24 | println!("After the thread calling"); 25 | } 26 | -------------------------------------------------------------------------------- /S21_macros/src/without_macro.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Aşağıdaki senaryoda iki sayıdan hangisi büyükse o geriye dönüyor. 3 | Ancak üç sayı kıyaslamak istediğimiz bir durum olursa ne yaparız? 4 | Bu durumda Vec parametre alan bir versiyon yazabiliriz ya da 5 | bunu bir makro ile çözebiliriz. 6 | */ 7 | pub fn max_of_two(a: i32, b: i32) -> i32 { 8 | if a >= b { 9 | return a; 10 | } 11 | b 12 | } 13 | 14 | #[cfg(test)] 15 | mod tests { 16 | use super::*; 17 | 18 | #[test] 19 | fn test_max_of_two() { 20 | assert_eq!(max_of_two(10, 20), 20); 21 | assert_eq!(max_of_two(30, 20), 30); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | 16 | .idea/ 17 | .vscode/* 18 | node_modules 19 | *.o 20 | *.d 21 | *.bin 22 | *.dat 23 | *.cargo-lock 24 | *.logs 25 | *.txt 26 | workspace.xml 27 | 28 | bin/* 29 | obj/* 30 | -------------------------------------------------------------------------------- /meth-leb/www/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const CopyWebpackPlugin = require("copy-webpack-plugin"); 3 | 4 | module.exports = { 5 | entry: "./index.js", 6 | output: { 7 | path: path.resolve(__dirname, "dist"), 8 | filename: "bundle.js", 9 | }, 10 | mode: "development", 11 | plugins: [ 12 | new CopyWebpackPlugin({ 13 | patterns: [{from: "index.html", to: "index.html"}], 14 | }), 15 | ], 16 | devServer: { 17 | static: "./dist", 18 | port: 5555, 19 | open: true, 20 | }, 21 | experiments: { 22 | asyncWebAssembly: true, 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "S00_hello_world", 4 | "S01_variables", 5 | "S02_vectors", 6 | "S03_strings", 7 | "S04_functions", 8 | "S05_control_flows", 9 | "S06_ownership", 10 | "S07_structs", 11 | "S08_lifetimes", 12 | "S09_enums", 13 | "S10_pattern_matching", 14 | "S11_generics", 15 | "S12_traits", 16 | "S13_built_in_traits", 17 | "S14_modules", 18 | "S15_error_handling", 19 | "S16_testing", 20 | "S17_closures", 21 | "S18_smart_pointers", 22 | "S19_threads", 23 | "S20_channels", 24 | "S21_macros", 25 | "S22_parallelism", 26 | "S23_asynchronous_programming", 27 | "S24_file_io", 28 | "S25_streams", 29 | "S26_unsafe_coding", 30 | "proc_macros", 31 | "s27-hello-wasm", 32 | "meth-leb" 33 | ] 34 | resolver = "2" 35 | -------------------------------------------------------------------------------- /meth-leb/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "meth-leb" 3 | version = "0.1.0" 4 | authors = ["buraksenyurt "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.84" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.7", optional = true } 21 | 22 | [dev-dependencies] 23 | wasm-bindgen-test = "0.3.34" 24 | 25 | [profile.release] 26 | # Tell `rustc` to optimize for small code size. 27 | opt-level = "s" 28 | -------------------------------------------------------------------------------- /S24_file_io/src/model.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{Display, Formatter}; 2 | 3 | #[derive(Debug)] 4 | pub struct Game<'a> { 5 | pub id: u32, 6 | pub name: &'a str, 7 | pub release_year: u16, 8 | pub category: &'a str, 9 | pub score: f32, 10 | } 11 | 12 | impl<'a> Game<'a> { 13 | pub fn new(id: u32, name: &'a str, release_year: u16, category: &'a str, score: f32) -> Self { 14 | Game { 15 | id, 16 | name, 17 | release_year, 18 | category, 19 | score, 20 | } 21 | } 22 | } 23 | 24 | impl<'a> Display for Game<'a> { 25 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 26 | write!( 27 | f, 28 | "{},{},{},{},{}", 29 | self.id, self.name, self.release_year, self.category, self.score 30 | ) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /s27-hello-wasm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "s27-hello-wasm" 3 | version = "0.1.0" 4 | authors = ["buraksenyurt "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.84" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.7", optional = true } 21 | 22 | [dev-dependencies] 23 | wasm-bindgen-test = "0.3.34" 24 | 25 | [profile.release] 26 | # Tell `rustc` to optimize for small code size. 27 | opt-level = "s" 28 | -------------------------------------------------------------------------------- /S23_asynchronous_programming/src/iot_sample.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | use tokio::task; 3 | use tokio::time::sleep; 4 | 5 | pub async fn run() { 6 | let i_robot = task::spawn(fetch_sensor_data(12456, 1)); 7 | let ai = task::spawn(fetch_sensor_data(11101, 3)); 8 | let optimus_prime = task::spawn(fetch_sensor_data(19023, 2)); 9 | 10 | let _ = tokio::join!(i_robot, ai, optimus_prime); 11 | } 12 | 13 | async fn fetch_sensor_data(sensor_id: u32, interval: u64) { 14 | for i in 1..=10 { 15 | println!( 16 | "Sensor ID: {}. Fetching data...{}. Result is {}", 17 | sensor_id, 18 | i, 19 | simulate_sensor_reading() 20 | ); 21 | sleep(Duration::from_secs(interval)).await; 22 | } 23 | } 24 | 25 | fn simulate_sensor_reading() -> f64 { 26 | rand::random::() * 10.0 27 | } 28 | -------------------------------------------------------------------------------- /S26_unsafe_coding/src/simple_ffi.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Burada örnek bir FFI (Foreign Function Interface) kullanımı söz konusudur. 3 | Bu kullanımlarda unsafe kod blokları ele alınır. 4 | Örnekte Rust ortamından bir C fonksiyon çağrısı yapılır. 5 | */ 6 | extern "C" { 7 | fn strlen(s: *const i8) -> usize; 8 | fn sin(x: f64) -> f64; 9 | fn cos(x: f64) -> f64; 10 | } 11 | 12 | pub fn run() { 13 | let c_string = std::ffi::CString::new("Rust programming language with Ferris").unwrap(); 14 | let ptr = c_string.as_ptr(); 15 | 16 | unsafe { 17 | println!("String length: {}", strlen(ptr)); 18 | } 19 | 20 | let angle = 60.0_f64.to_radians(); 21 | 22 | unsafe { 23 | let sin_value = sin(angle); 24 | let cos_value = cos(angle); 25 | 26 | println!("sin(60°): {}", sin_value); 27 | println!("cos(60°): {}", cos_value); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /S23_asynchronous_programming/src/main.rs: -------------------------------------------------------------------------------- 1 | mod api_sample; 2 | mod iot_sample; 3 | mod metric_sample; 4 | /* 5 | Asenkron programlamada async, await, future ve task gibi kavramlar öne çıkar. 6 | async kullanımı thread kullanımı ile benzerlik gösterir ancak async ile çalışılan yapılar 7 | thread'lere nazaran daha az kaynak tüketir. 8 | 9 | Burada future:Future trait'ine bakmakta yarar vardır. 10 | Future trait asenkron çalışan bir operasyon için ileri zamanlı hesaplama desteği sağlar. 11 | Basit bir polling mantığı ile başlatılan asenkron işin tamamlanıp tamamlanmadığı kontrol 12 | edilir. Eğeri iş tamamlanmışsa hesaplama sonucu çekilebilir. 13 | 14 | use std::future; 15 | future::Future::poll(); 16 | */ 17 | 18 | #[tokio::main] 19 | async fn main() { 20 | println!("Starting..."); 21 | 22 | api_sample::run().await; 23 | iot_sample::run().await; 24 | metric_sample::run().await; 25 | 26 | println!("Done!"); 27 | } 28 | -------------------------------------------------------------------------------- /meth-leb/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod utils; 2 | 3 | use wasm_bindgen::prelude::*; 4 | 5 | #[wasm_bindgen] 6 | extern "C" { 7 | fn alert(s: &str); 8 | } 9 | 10 | #[wasm_bindgen] 11 | pub fn greet() { 12 | alert("Hello, meth-leb!"); 13 | } 14 | /* 15 | Aşağıdaki fonksiyon belirli bir x aralığındaki y değerlerini hesaplamaktadır. 16 | Tipik bir parabol denklemi aslında. 17 | Parametreleri bu projede index.html sayfasından alacağız. 18 | 19 | */ 20 | 21 | #[wasm_bindgen] 22 | pub fn calculate_parabola( 23 | a: f64, 24 | b: f64, 25 | c: f64, 26 | x_min: f64, 27 | x_max: f64, 28 | steps: usize, 29 | ) -> Vec { 30 | let mut points = Vec::new(); 31 | let step_size = (x_max - x_min) / steps as f64; 32 | let mut x = x_min; 33 | 34 | for _ in 0..=steps { 35 | let y = a * x * x + b * x + c; 36 | points.push(x); 37 | points.push(y); 38 | x += step_size; 39 | } 40 | 41 | points 42 | } 43 | -------------------------------------------------------------------------------- /S23_asynchronous_programming/src/api_sample.rs: -------------------------------------------------------------------------------- 1 | use tokio::task; 2 | 3 | pub async fn run() { 4 | let task_a = task::spawn(fetch_data_async( 5 | "https://jsonplaceholder.typicode.com/posts/1", 6 | )); 7 | let task_b = task::spawn(fetch_data_async( 8 | "https://jsonplaceholder.typicode.com/posts/2", 9 | )); 10 | let task_c = task::spawn(fetch_data_async( 11 | "https://jsonplaceholder.typicode.com/posts/3", 12 | )); 13 | 14 | let (res_a, res_b, res_c) = tokio::join!(task_a, task_b, task_c); 15 | 16 | match (res_a, res_b, res_c) { 17 | (Ok(a), Ok(b), Ok(c)) => { 18 | println!("{:?}", a); 19 | println!("{:?}", b); 20 | println!("{:?}", c); 21 | } 22 | _ => println!("Failed to fetch data"), 23 | } 24 | } 25 | 26 | async fn fetch_data_async(url: &str) -> Result { 27 | let response = reqwest::get(url).await?; 28 | response.text().await 29 | } 30 | -------------------------------------------------------------------------------- /S21_macros/src/model.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Programda aşağıdaki gibi entity nesnelerimiz olduğunu düşünelim. 3 | Bu türler için basit CRUD operasyonlarına ihtiyacımız olacaktır. 4 | Yeni modeller ekledikçe benzer metotları ilave etmemiz gerekir. 5 | Buradaki yeniden kullanılabilir kodu makrolar ile oluşturabiliriz. 6 | */ 7 | pub struct Player { 8 | pub id: i32, 9 | pub name: String, 10 | pub rating: f32, 11 | } 12 | 13 | // impl Player { 14 | // fn create(id: i32, name: String, rating: f32) -> Self { 15 | // Player { id, name, rating } 16 | // } 17 | // } 18 | 19 | pub struct Game { 20 | pub id: i32, 21 | pub title: String, 22 | pub studio: String, 23 | pub year: u8, 24 | } 25 | 26 | // impl Game { 27 | // fn create(id: i32, title: String, studio: String, year: u8) -> Self { 28 | // Game { 29 | // id, 30 | // title, 31 | // studio, 32 | // year, 33 | // } 34 | // } 35 | // } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Burak Selim Senyurt 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 | -------------------------------------------------------------------------------- /S25_streams/src/echo_server.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Read, Write}; 2 | use std::net::TcpListener; 3 | 4 | /* 5 | Aşağıdaki örnek basit bir echo server. Client server arasında kurulan bağlantıda, 6 | client'ın gönderdiği mesaj sunucu tarafından client'a geri gönderilir veya sunucu 7 | client'tan gelen mesaja karşılık ECHO diye yanıt döner. 8 | 9 | Çalıştığım Windows 11 sisteminde bunu denemek için netcat programından yararlandım. 10 | 11 | echo "Hello world" | nc localhost 7001 12 | 13 | ile deneyebiliriz. 14 | */ 15 | pub fn run() -> std::io::Result<()> { 16 | let address = "0.0.0.0:7001"; 17 | let listener = TcpListener::bind(address)?; 18 | println!("Listening on {address}"); 19 | 20 | for stream in listener.incoming() { 21 | let mut stream = stream?; 22 | let mut buffer = [0; 1024]; 23 | let bytes_read = stream.read(&mut buffer)?; 24 | let message = String::from_utf8_lossy(&buffer[..bytes_read]) 25 | .trim() 26 | .to_owned(); 27 | println!("{bytes_read} bytes received: {message} "); 28 | stream.write_all(&buffer[..bytes_read])?; 29 | } 30 | 31 | Ok(()) 32 | } 33 | -------------------------------------------------------------------------------- /meth-leb/LICENSE_MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 buraksenyurt 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /s27-hello-wasm/LICENSE_MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 buraksenyurt 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /S16_testing/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Test modüllerini çalıştırmak için 3 | 4 | cargo test 5 | 6 | komutunu kullanabiliriz. Eğer belli bir testi çalıştırmak istersek aynı komutu aşağıdaki gibi 7 | kullanabiliriz. 8 | 9 | cargo test two_plus_two_is_four 10 | 11 | Örneğin sadece membership modülündeki membership_tests testlerini koşmak için aşağıdaki 12 | komutu kullanabiliriz. 13 | 14 | cargo test membership_tests 15 | 16 | Testleri paralel çalıştırmak da isteyebiliriz. Bazı durumlarda test metotları uzun süreli 17 | iş parçacıkları içerebilirler. Bunun için thread sayısı belirtebiliriz. Aşağıdaki komutu 18 | kullanarak testleri 4 thread'e bölüp koşturmaktayız. 19 | 20 | cargo test -- --test-threads=4 # =4 bitişik yazılmalı yoksa komut anlaşılmaz 21 | 22 | Diğer kullanım komutları ile ilgili bilgi almak için; 23 | 24 | cargo test --help 25 | */ 26 | mod accounting; 27 | mod membership; 28 | 29 | pub fn add(left: u64, right: u64) -> u64 { 30 | left + right 31 | } 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | use super::*; 36 | 37 | #[test] 38 | fn two_plus_two_is_four() { 39 | let result = add(2, 2); 40 | assert_eq!(result, 4); 41 | } 42 | 43 | #[test] 44 | #[ignore] 45 | fn just_fails() { 46 | panic!("Failing..."); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /S23_asynchronous_programming/src/metric_sample.rs: -------------------------------------------------------------------------------- 1 | use rand::Rng; 2 | use std::time::Duration; 3 | use tokio::sync::mpsc; 4 | use tokio::task; 5 | use tokio::time::sleep; 6 | 7 | pub async fn run() { 8 | let (log_transmitter, mut log_receiver) = mpsc::channel(100); 9 | 10 | let cpu_task = task::spawn(fetch_metrics("CPU Service", log_transmitter.clone())); 11 | let memory_task = task::spawn(fetch_metrics("Memory Service", log_transmitter.clone())); 12 | let disk_task = task::spawn(fetch_metrics("Disk Service", log_transmitter)); 13 | 14 | let logger_task = task::spawn(async move { 15 | while let Some(metric) = log_receiver.recv().await { 16 | println!("LOG: {}", metric); 17 | } 18 | }); 19 | 20 | let _ = tokio::join!(cpu_task, memory_task, disk_task, logger_task); 21 | } 22 | 23 | async fn fetch_metrics(service_name: &str, tx: mpsc::Sender) { 24 | let interval = Duration::from_secs(5); 25 | for i in 1..=10 { 26 | let metric = format!("{} - Metric {}: {}", service_name, i, get_metric()); 27 | if tx.send(metric).await.is_err() { 28 | println!("{}: Channel isn't active!", service_name); 29 | break; 30 | } 31 | sleep(interval).await; 32 | } 33 | } 34 | 35 | fn get_metric() -> f64 { 36 | let mut rng = rand::rng(); 37 | rng.random_range(50.0..100.0) 38 | } 39 | -------------------------------------------------------------------------------- /S03_strings/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let hero_name = "Can Cloud Van Dam".to_string(); 3 | println!("{}", hero_name); 4 | let position = String::from("Quarter back"); 5 | println!("{}", position); 6 | let short_name = hero_name.replace("Can Cloud Van Dam", "CCVD"); 7 | println!("{}", &short_name); 8 | 9 | // &str (string slice) bir string değerin belli bir kısmını refeans edebilir ya da 10 | // string slice (&str) için heap üzerine yer ayrılmaz(String veri türünün aksine) 11 | // Boyutu bellidir. 12 | // Genellikle fonksiyonlara argüman taşırken &str daha uygundur (lifetime'a dikkat) 13 | let greetings = "Greetings dear young and crazy brains".to_string(); 14 | let first_word = greetings.get(0..10).unwrap(); 15 | println!("{}", first_word); 16 | 17 | let first_words = "hello there"; //doğrudan &str 18 | println!("{}", first_words); 19 | 20 | let word_aloha = "Aloha!"; 21 | let word = word_aloha.to_string(); 22 | let word_ref = &word; 23 | println!("{}", word_aloha); 24 | println!("{}", word); 25 | println!("{}", word_ref); 26 | 27 | println!("Words is equal, {}", word_aloha.to_lowercase() == "aloha!"); 28 | 29 | // Elimizde geçerli UTF-8/UNICODE karakterleri olmadığında strings literals kullanılabilir. 30 | let konnichiwa = "\u{3053}\u{3093}\u{306B}\u{3061}\u{306F}"; 31 | println!("{}", konnichiwa); 32 | } 33 | -------------------------------------------------------------------------------- /S20_channels/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Thread'ler arasında veri aktarımı yapmak için kanallardan(channels) yararlanılabilir. 3 | Kanallar ownership ve borrowing kuralları ile uyumlu olacak şekilde thread-safe ve verimli 4 | bir haberleşme imkanı sunar. 5 | 6 | Genelde multi-producer, single-consumer modelinde işlenirler. Yani birden fazla veri üreten 7 | thread(producers) söz konusu iken bu üretilen verileri dinleyen ya da kullananan sadece tek bir 8 | tüketetici(consumer) thread vardır. 9 | 10 | Kanallar içerisinde sadece belirlenen veri türleri kullanılır bu da tip güvenliğinin 11 | sağlanması anlamına gelir. Burada yine defacto olarak ifade edebileceğim tokio kütüphanesi 12 | sayesinden kanalların asenkron çalıştırılması da sağlanabilir. 13 | */ 14 | use crate::basic::*; 15 | use crate::problems::*; 16 | use crate::scenarios::*; 17 | 18 | mod basic; 19 | mod problems; 20 | mod scenarios; 21 | fn main() { 22 | // hello_channels(); 23 | // multi_producer(); 24 | // multi_producer_2(); 25 | // process_reports(); 26 | // deadlock_case(); 27 | // deadlock_case_banking(); 28 | // poisoning_case(); 29 | poisoning_case_logging(); 30 | } 31 | 32 | // #[tokio::main] 33 | // async fn main() { 34 | // println!("Standard mpsc scenario"); 35 | // do_with_standard(); 36 | // println!("async scenario with tokio"); 37 | // do_with_tokio().await 38 | // } 39 | -------------------------------------------------------------------------------- /S21_macros/src/samples.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Bu macro blok olarak girilen kodun çalışma zamanını ölçer. 3 | */ 4 | macro_rules! wt { 5 | ($block:block) => {{ 6 | let start = std::time::Instant::now(); 7 | let result = $block; 8 | let duration = start.elapsed(); 9 | println!("Total execution time: {:?}", duration); 10 | result 11 | }}; 12 | } 13 | 14 | /* 15 | Aşağıdaki macro ise { } bloğu içerisindeki veri modelini alıp XML şekline dönüştürür. 16 | */ 17 | macro_rules! xml { 18 | ($tag:ident { $($key:ident : $value:expr),* }) => { 19 | format!( 20 | "<{tag} {attributes} />", 21 | tag = stringify!($tag), 22 | attributes = vec![$(format!("{}=\"{}\"", stringify!($key), $value)),*].join(" ") 23 | ) 24 | }; 25 | } 26 | 27 | // cargo test -- --nocapture 28 | #[cfg(test)] 29 | mod sample_tests { 30 | #[test] 31 | fn wt_test() { 32 | let sum = wt!({ 33 | let mut total = 0; 34 | for i in 1..100 { 35 | total += i; 36 | } 37 | total 38 | }); 39 | assert_eq!(sum, 4950); 40 | } 41 | 42 | #[test] 43 | fn xml_test() { 44 | let data = xml! { 45 | game { 46 | id:1, 47 | title:"Pacman 1983", 48 | rate:9.6 49 | } 50 | }; 51 | assert_eq!( 52 | data, 53 | "".to_string() 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /S02_vectors/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | /* 3 | Vector türü heap üstünden yer allocate etmeye izin verir ve dinamik olarak büyüyebilir. 4 | Diziler gibi sabit elemanlı değillerdir. 5 | Dizilerde olduğu gibi aynı türden verileri taşıyabilirler. 6 | */ 7 | 8 | let mut points = vec![3.14, 2.67, 1.24, 9.80]; 9 | points.push(7.5); 10 | println!("{:?}", points); 11 | println!("First point is {}", points[0]); 12 | 13 | let last_in = points.pop(); 14 | println!("{:?}", last_in); 15 | println!("Current vector elements {:#?}", points); 16 | 17 | let mut names = Vec::new(); 18 | names.push(String::from("Bob")); 19 | names.push(String::from("Frank")); 20 | names.push(String::from("Orange")); 21 | names.push(String::from("Mary")); 22 | names.reverse(); 23 | println!("Players vector capacity is {:?}", names.capacity()); 24 | println!("Players :\n {:#?}", names); 25 | 26 | let codes: Vec = (50..=60).collect(); 27 | println!("Looking codes are, {:?}", codes); 28 | 29 | /* 30 | Vector/Array türlerinin işaret ettiği veri kümelerinden dilimler alabiliriz. 31 | Yani tüm veri kümesini almak yerine sadece belli bir dilimi ile çalışma yapmak istediğimizde, 32 | bu dilime ait bir referans ile çalışmak tercih edilir. 33 | Slice olarak geçen bir kavram aslında bir veri dilimini referans eden bir değişkendir. 34 | */ 35 | let codes: Vec = (0..100).collect(); 36 | let first_ten = &codes[0..=10]; 37 | println!("First ten: {:#?}", first_ten); 38 | } 39 | -------------------------------------------------------------------------------- /S24_file_io/src/basics.rs: -------------------------------------------------------------------------------- 1 | use crate::model::Game; 2 | use std::fs::{File, OpenOptions}; 3 | use std::io::{Read, Write}; 4 | use std::{fs, io}; 5 | 6 | /* 7 | Aşağıdaki metot games.dat isimli bir dosya oluşturur. Sistemde varsa append modda açar ve 8 | gelen içeriği sonuna ekleyerek devam eder. 9 | */ 10 | fn append_game(game: &Game) -> io::Result<()> { 11 | let mut file = OpenOptions::new() 12 | .create(true) 13 | .append(true) 14 | .open("games.dat")?; 15 | writeln!(file, "{}", game)?; 16 | Ok(()) 17 | } 18 | 19 | /* 20 | Bu fonksiyon ise path ile gelen dosya içeriğini okuyup geriye döndürür. 21 | Metin tabanlı dosyalar için ele alınan bir yöntemdir. 22 | */ 23 | fn read(path: &str) -> io::Result { 24 | // if !fs::metadata(path).is_ok() { 25 | // panic!("File does not exist: {}", path); 26 | // } 27 | let mut file = File::open(path)?; 28 | let mut contents = String::new(); 29 | file.read_to_string(&mut contents)?; 30 | Ok(contents) 31 | } 32 | 33 | pub fn run() -> io::Result<()> { 34 | if fs::metadata("games.dat").is_ok() { 35 | fs::remove_file("games.dat")?; 36 | } 37 | let games = vec![ 38 | Game::new(1, "Starcraft", 1996, "Strategy", 8.7), 39 | Game::new(2, "Generals Zero Hour", 2004, "Strategy", 8.3), 40 | Game::new(3, "Prince of Persia", 1983, "RPG", 9.2), 41 | ]; 42 | games.iter().for_each(|g| append_game(g).unwrap()); 43 | 44 | let content = read("games.dat")?; 45 | println!("Popular Games List\n{}", content); 46 | Ok(()) 47 | } 48 | -------------------------------------------------------------------------------- /S04_functions/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | print_greetings(); 3 | let name = "Can Cloud Van Dam"; 4 | greet(name); 5 | println!("4 + 5 = {}", sum(4, 5)); 6 | 7 | let numbers = vec![1, 4, 6, 2, 8, 10, 3, 7, 27, 9, 144, 1024, 5]; 8 | let evens = get_evens(&numbers); 9 | println!("{:?}", evens); 10 | let odds = get_odds(&numbers); 11 | println!("{:?}", odds); 12 | 13 | let (x, y) = move_position(10.0, 5.0, 1.0); 14 | println!("{:?}:{:?}", x, y); 15 | 16 | let names = vec!["caN", "clOUD", "vAn", "DaM"]; 17 | print_all_to_upper(names); 18 | } 19 | 20 | fn print_greetings() { 21 | println!("Welcome to my new world!"); 22 | } 23 | 24 | fn greet(name: &str) { 25 | println!("Hello {}! How are you?", name); 26 | } 27 | 28 | fn print_all_to_upper(names: Vec<&str>) { 29 | for name in names { 30 | println!("{}", name.to_uppercase()); 31 | } 32 | } 33 | 34 | fn sum(value_1: i32, value_2: i32) -> i32 { 35 | value_1 + value_2 36 | } 37 | 38 | fn double_it(value: i32) -> i32 { 39 | value * 2 40 | } 41 | 42 | fn move_position(mut x: f32, mut y: f32, acceleration: f32) -> (f32, f32) { 43 | x += acceleration; 44 | y += acceleration; 45 | (x, y) 46 | } 47 | 48 | fn get_evens(numbers: &Vec) -> Vec { 49 | let mut evens: Vec = Vec::new(); 50 | for number in numbers { 51 | if *number % 2 == 0 { 52 | evens.push(*number); 53 | } 54 | } 55 | evens 56 | } 57 | 58 | fn get_odds(numbers: &[i32]) -> Vec { 59 | numbers 60 | .iter() 61 | .filter(|&&i| i % 3 == 0) 62 | .cloned() 63 | .collect::>() 64 | } 65 | -------------------------------------------------------------------------------- /S14_modules/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Rust projelerinde organizasyonu Crate, Module ve Package kavramları ile sağlarız. 3 | 4 | Crate'ler projeler arasında metotların iş kurallarının paylaşımının sağlanması için kullanılır. 5 | Module türleri ise içinde bulunduğu library veya executable için ortak fonksiyonellikler sağlar. 6 | 7 | crates.io, rust ile yazılmış crate'lerin resmi olarak toplandığı yerdir. 8 | 9 | Bir library'deki modül ve içeriğinin organizasyonel olarak görünümünü öğrenmek için 10 | cargo-modules aracı kullanılabilir. 11 | 12 | Mesela bulunduğumuz workspace için şöyle bir komut işletilebilir ve S14_modules içeriği 13 | gözlemlenebilir 14 | cargo modules structure --package S14_modules 15 | 16 | pub(self) tanımını private erişim belirleyici olarak düşünebiliriz. 17 | */ 18 | mod borrow_system; 19 | mod membership; 20 | mod repository; 21 | 22 | // mod library { 23 | // // pub struct Book { 24 | // // pub title: String, 25 | // // pub author: String, 26 | // // pub can_be_borrowed: bool, 27 | // // } 28 | // 29 | // // mod book_repository { 30 | // // pub fn add() {} 31 | // // pub fn remove() {} 32 | // // pub fn list() {} 33 | // // } 34 | // 35 | // // mod borrow_system { 36 | // // pub fn borrow() {} 37 | // // pub fn giving_back() {} 38 | // // pub fn is_borrowable() {} 39 | // // } 40 | // 41 | // // mod member_management { 42 | // // pub fn subscribe() {} 43 | // // pub fn unsubscribe() {} 44 | // // fn list() {} 45 | // // } 46 | // } 47 | 48 | pub struct Book { 49 | pub title: String, 50 | pub author: String, 51 | pub can_be_borrowed: bool, 52 | } 53 | -------------------------------------------------------------------------------- /S24_file_io/src/advanced.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Bu seferki senaryoda bir log dosyası içerisinde yer alan bilgileri thread sayısına göre 3 | parçalayıp her blok içerisindeki Error loglarının 4 | kanal(channel) üzerinden bir dinleyiciye(receiver) gönderilmesini sağlıyoruz. 5 | 6 | Yani bir dosya içeriğini 7 | */ 8 | use std::fs::File; 9 | use std::io::{self, BufRead, BufReader}; 10 | use std::sync::{mpsc, Arc, Mutex}; 11 | use std::thread; 12 | 13 | fn analyze_logs(file_path: &str, num_threads: usize) -> io::Result<()> { 14 | let file = File::open(file_path)?; 15 | let reader = BufReader::new(file); 16 | 17 | let (tx, rx) = mpsc::channel(); 18 | let lines = Arc::new(Mutex::new(reader.lines())); 19 | 20 | let mut handles = Vec::new(); 21 | 22 | for _ in 0..num_threads { 23 | let tx = tx.clone(); 24 | let lines = Arc::clone(&lines); 25 | 26 | let handle = thread::spawn(move || { 27 | while let Ok(mut guard) = lines.lock() { 28 | if let Some(Ok(line)) = guard.next() { 29 | drop(guard); 30 | if line.contains("ERROR") { 31 | tx.send(line).unwrap(); 32 | } 33 | } else { 34 | break; 35 | } 36 | } 37 | }); 38 | 39 | handles.push(handle); 40 | } 41 | 42 | drop(tx); 43 | let mut error_count = 0; 44 | for received in rx { 45 | error_count += 1; 46 | println!("Founded error log: {}", received); 47 | } 48 | println!("TOTAL ERROR COUNT: {}", error_count); 49 | 50 | for handle in handles { 51 | handle.join().unwrap(); 52 | } 53 | 54 | Ok(()) 55 | } 56 | pub fn run() -> io::Result<()> { 57 | analyze_logs("sys.logs", 4)?; 58 | Ok(()) 59 | } 60 | -------------------------------------------------------------------------------- /S26_unsafe_coding/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Rust, bellek güvenliğini sağlama ve eşzamanlılık garantilerini sunmak üzere tasarlanmış bir 3 | bellek yönetim sistemini benimser. Ancak bazı hallerde bu güvenli alanın dışına çıkılması 4 | gerekebilir. Bu genellikle unsafe kod blokları ile gerçekleştirilir. 5 | 6 | Unsafe bloklarda dilin standart güvnelik mekanizmaları göz ardı edilir. Unsafe kod tarafına 7 | çıkmayı gerektiren durumlar kısaca şöyle özetlenebilir. 8 | 9 | - Performans iyileştirmeleri: Rust'un kontrol mekanizmaları performans üzerinde yük oluşturabilir. 10 | Mesela raw pointer'lar ile çalışmak çok hızlıdır. Bellek erişiminde bu hızlara çıkmak istediğimiz 11 | durumlarda ele alabiliriz. 12 | - C/C++ gibi rust dışındaki dillerle FFI(Foreign Function Interface) etkileşim kurmak istediğimiz 13 | hallerde tercih edilir. 14 | - Bellek bloklarını doğrudan manupile etmek istediğimiz hallerde. 15 | - Rust'ın normal veri yapılarından daha büyük boyutlardaki (union yapılar gerektiren haller) 16 | ihtiyaçlarda bit seviyesinde işlemler gerektiğinde 17 | - Yazılan kodun mantıksal olarak güvenli olduğu hallerde kullanılan built-in fonksiyonellikleri 18 | sağlayan api'ler için güvenlik kontrollerini atlamak istediğimizde 19 | 20 | Unsafe kod kullanımında sorumluluk daha çok geliştiriciye kalır. Diğer yandan unsafe kod blokları 21 | gerekli olduğu yerlerde kullanılır ve kalan kod parçaları rust'ın güvenlik kriterlerine tabi 22 | olmaya devam eder. 23 | 24 | Unsafe kodlama bellek güvenliği kriterlerinden feragat etmek anlamına gelse de, doğru şekilde 25 | ve yerlerde kullanıldığında sistem seviyesinde kontrol ve yüksek performans sağlar. 26 | */ 27 | mod advanced; 28 | mod simple_ffi; 29 | 30 | fn main() { 31 | simple_ffi::run(); 32 | advanced::run(); 33 | } 34 | -------------------------------------------------------------------------------- /S25_streams/src/low_level_server.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::io::BufRead; 3 | use std::io::Write; 4 | 5 | /* 6 | Aşağıdaki kod parçasında stdin ve stdout kullanılarak çok düşük seviyede bir http server 7 | fonksiyonelliği ele alınmaktadır. Bu tabii çok düşük seviye bir kodlamadır ve açıkçası çok 8 | pratik değildir. Bu tip bir web sunucusu hizmeti için std::net modülündeki TcpListener ve 9 | TcpStream türleri kullanılabilir. 10 | 11 | Terminalden denemek için; 12 | 13 | Linux tarafında aşağıdaki şekilde ilerleyebilir. 14 | 15 | echo -e "GET /ping HTTP/1.1\r\n" | cargo run 16 | 17 | Windows tarafında ise 18 | 19 | cargo run ile projeyi çalıştırdıktan sonra 20 | terminale 21 | GET /ping HTTP/1.1 22 | yazılıp ilerlenebilir. 23 | */ 24 | pub fn run() -> io::Result<()> { 25 | let stdin = io::stdin(); 26 | let stdout = io::stdout(); 27 | 28 | let mut reader = stdin.lock(); 29 | let mut writer = stdout.lock(); 30 | 31 | let mut request_line = String::new(); 32 | reader.read_line(&mut request_line)?; 33 | 34 | let mut parts = request_line.split_whitespace(); 35 | let method = parts.next().unwrap_or(""); 36 | let path = parts.next().unwrap_or(""); 37 | println!("{:?} {:?}", method, path); 38 | 39 | if method == "GET" && path == "/ping" { 40 | writeln!(writer, "HTTP/1.1 200 OK")?; 41 | writeln!(writer, "Content-Type: application/json")?; 42 | writeln!(writer, "Content-Length: 6")?; 43 | writeln!(writer, "")?; 44 | writeln!(writer, "Pong!")?; 45 | } else { 46 | writeln!(writer, "HTTP/1.1 404 Not Found")?; 47 | writeln!(writer, "Content-Type: application/json")?; 48 | writeln!(writer, "Content-Length: 9")?; 49 | writeln!(writer, "")?; 50 | writeln!(writer, "Not Found")?; 51 | } 52 | 53 | Ok(()) 54 | } 55 | -------------------------------------------------------------------------------- /S05_control_flows/src/main.rs: -------------------------------------------------------------------------------- 1 | use rand::Rng; 2 | 3 | fn main() { 4 | let mut rnd = rand::thread_rng(); 5 | let some_number = rnd.gen_range(1..1_000); 6 | 7 | println!("{}", some_number); 8 | 9 | if some_number % 2 == 0 { 10 | println!("{} is even.", some_number); 11 | } else if some_number % 3 == 0 { 12 | println!("{} is odd", some_number); 13 | } 14 | 15 | loop { 16 | let number = rnd.gen_range(1..101); 17 | println!("{}", number); 18 | if number % 23 == 0 { 19 | println!("I have got you {}", number); 20 | break; 21 | } else { 22 | continue; 23 | } 24 | } 25 | 26 | let mut try_count = 0; 27 | while try_count < 100 { 28 | let number = rnd.gen_range(1..101); 29 | if number % 23 == 0 { 30 | println!("I found the number {} in {} try", number, try_count); 31 | break; 32 | } 33 | try_count += 1; 34 | } 35 | 36 | let data = get_random_numbers(10); 37 | for (index, value) in data.iter().enumerate() { 38 | println!("{index}\t {value}"); 39 | } 40 | 41 | check_exam_score(rnd.gen_range(0..=100)); 42 | } 43 | 44 | fn get_random_numbers(max_limit: u8) -> Vec { 45 | let mut rnd = rand::thread_rng(); 46 | let mut numbers = Vec::new(); 47 | for _ in 0..max_limit { 48 | let n = rnd.gen_range(1..101); 49 | if numbers.contains(&n) { 50 | continue; 51 | } 52 | numbers.push(n); 53 | } 54 | numbers 55 | } 56 | 57 | fn check_exam_score(point: i32) { 58 | if point == 0 { 59 | println!("Blank paper! Fails"); 60 | } else if point > 70 { 61 | println!("{point} is enough for pass."); 62 | } else if point < 50 { 63 | println!("{point} is not enough for pass."); 64 | } else if point > 50 && point < 70 { 65 | println!("{point} is greater than 50 but less than 70. Come in September!"); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /meth-leb/www/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Parabola Drawer 4 | 18 | 19 | 20 |

Parabola Drawer

21 |

Fun with math :) Select a predefined parabola or use your values to draw your own parabola.

22 | 23 |
24 | 25 | 36 |

37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 |
52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /S21_macros/src/with_macro.rs: -------------------------------------------------------------------------------- 1 | macro_rules! max_of { 2 | ($x:expr) => { 3 | $x 4 | }; 5 | ($x:expr,$y:expr) => { 6 | if $x > $y { 7 | $x 8 | } else { 9 | $y 10 | } 11 | }; 12 | ($x:expr,$($y:expr),+) => { 13 | max_of!($x,max_of!($($y),+)) 14 | } 15 | } 16 | 17 | /* 18 | Aşağıdaki makro tanımında da crud operasyonlarını(şimdilik create) üreten bir kod 19 | parçası yer alıyor. Buradaki ident, ty gibi ifadeler "metasyntactic variables" 20 | olarak geçer ve özel anlamları vardır. Örneğin ident, identifier olarak ifade edilebilir 21 | ve bir tanımlayıcıyı temsil eder. ty f32, String, Option vb türleri temsil eder. 22 | */ 23 | macro_rules! crud { 24 | ($struct_name:ident, $($field_name:ident: $field_type:ty),*) => { 25 | #[derive(Debug)] 26 | struct $struct_name { 27 | $( 28 | $field_name: $field_type, 29 | )* 30 | } 31 | 32 | impl $struct_name { 33 | fn new($($field_name: $field_type),*) -> $struct_name { 34 | $struct_name { $($field_name),* } 35 | } 36 | } 37 | }; 38 | } 39 | 40 | crud!(Product, id: i32,title: String,list_price:f32,category: String); 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use super::*; 45 | 46 | #[test] 47 | fn test_max_macro() { 48 | assert_eq!(max_of!(1), 1); 49 | assert_eq!(max_of!(2, 7), 7); 50 | assert_eq!(max_of!(10, 0, 6, 19, 20, 3, 2, 7), 20); 51 | assert_eq!(max_of!(-8, -5, -3, -99), -3); 52 | } 53 | 54 | #[test] 55 | fn test_crud_macro() { 56 | let c64 = Product::new( 57 | 1, 58 | "C64 monitor 14.1inch".to_string(), 59 | 999.99, 60 | "Retro Computer".to_string(), 61 | ); 62 | assert_eq!(c64.id, 1); 63 | assert_eq!(c64.title, "C64 monitor 14.1inch".to_string()); 64 | assert_eq!(c64.list_price, 999.99); 65 | assert_eq!(c64.category, "Retro Computer".to_string()); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /S21_macros/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Makrolar meta programlamanın temel unsurlarındadır. Meta programlama kod yazan kodlar 3 | oluşturulmasını benimseyen bir konsepttir. Makroları kullanarak kod tekrarını azaltan 4 | kurguları işletebiliriz. 5 | 6 | println! write! gibi sonu ! ile biten enstrümanlar aslında birer makrodur. Makroları 7 | Declarative ve Procedural olmak üzere iki ana kategoriye ayırabiliriz. 8 | 9 | Bu projedeki test metotlarında declarative macro örnekleri yer almaktadır. 10 | Aynı zamanda wtime isimli bir procedural macro kullanım örneği de mevcuttur. 11 | */ 12 | use log::info; 13 | use proc_macros::{log_execution, work_time_effort, work_time_effort_log}; 14 | 15 | mod model; 16 | mod samples; 17 | mod with_macro; 18 | mod without_macro; 19 | 20 | #[work_time_effort] 21 | fn find_total() { 22 | let mut total = 0; 23 | for i in 0..1000 { 24 | total += i; 25 | } 26 | println!("Result: {}", total); 27 | } 28 | 29 | /* 30 | Attribute türevli procedural makrolara parametre de geçilebilir. 31 | Argümanlar, macrodaki ilk parametredeki TokenStream üzerinden yakalanır. 32 | */ 33 | #[work_time_effort_log("info")] 34 | fn find_another_total() { 35 | let mut total = 0; 36 | for i in 0..1_000 { 37 | total += i; 38 | } 39 | println!("Result: {}", total); 40 | } 41 | 42 | struct Logger; 43 | 44 | impl Logger { 45 | pub fn log(&self, msg: &str) { 46 | info!("{}", msg); 47 | } 48 | } 49 | 50 | #[log_execution(Logger)] 51 | fn sum() { 52 | let mut total = 0; 53 | for i in 0..1_000 { 54 | total += i; 55 | } 56 | println!("Result: {}", total); 57 | } 58 | 59 | /* 60 | Log çıktılarını görmek için uygulamayı linux platformunda 61 | 62 | RUST_LOG=info cargo run 63 | 64 | ile, 65 | Windows platformunda Powershell' de ise 66 | 67 | set RUST_LOG=info && cargo run 68 | 69 | ile çalıştırabiliriz. 70 | */ 71 | fn main() { 72 | env_logger::init(); 73 | 74 | let _total = find_total(); 75 | let _another_total = find_another_total(); 76 | let _sum = sum(); 77 | } 78 | -------------------------------------------------------------------------------- /S16_testing/src/accounting.rs: -------------------------------------------------------------------------------- 1 | fn get_discount_amount(unit_price: f64, rate: f64) -> Result { 2 | if unit_price < 0.0 { 3 | return Err(AccountingError::InvalidUnitPrice( 4 | "Unit price cannot be negative.", 5 | )); 6 | } 7 | if rate < 0.0 || rate > 1.0 { 8 | return Err(AccountingError::InvalidRate( 9 | "Discount rate must be between 0.0 and 1.0.", 10 | )); 11 | } 12 | Ok(unit_price * (1.0 - rate)) 13 | } 14 | 15 | #[derive(Debug, PartialEq)] 16 | enum AccountingError { 17 | InvalidUnitPrice(&'static str), 18 | InvalidRate(&'static str), 19 | } 20 | 21 | #[cfg(test)] 22 | mod accounting_tests { 23 | use super::*; 24 | use crate::accounting::AccountingError::{InvalidRate, InvalidUnitPrice}; 25 | 26 | #[test] 27 | fn test_no_discount() { 28 | let result = get_discount_amount(100.0, 0.0); 29 | assert_eq!(result.unwrap(), 100.0); 30 | } 31 | #[test] 32 | fn test_two_percent_discount() { 33 | let result = get_discount_amount(100.0, 0.2); 34 | assert_eq!(result.unwrap(), 80.0); 35 | } 36 | #[test] 37 | fn test_full_discount() { 38 | let result = get_discount_amount(100.0, 1.0); 39 | assert_eq!(result.unwrap(), 0.0); 40 | } 41 | #[test] 42 | fn test_negative_price() { 43 | let result = get_discount_amount(-50.0, 0.2); 44 | assert_eq!( 45 | result, 46 | Err(InvalidUnitPrice("Unit price cannot be negative.")) 47 | ); 48 | } 49 | #[test] 50 | fn test_invalid_discount_greater_than_one() { 51 | let result = get_discount_amount(100.0, 1.5); 52 | assert_eq!( 53 | result, 54 | Err(InvalidRate("Discount rate must be between 0.0 and 1.0.")) 55 | ); 56 | } 57 | #[test] 58 | fn test_invalid_discount_negative() { 59 | let result = get_discount_amount(100.0, -0.3); 60 | assert_eq!( 61 | result, 62 | Err(InvalidRate("Discount rate must be between 0.0 and 1.0.")) 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /S17_closures/src/main.rs: -------------------------------------------------------------------------------- 1 | use crate::repository::Game; 2 | 3 | mod repository; 4 | mod scenario; 5 | /* 6 | Closure' lar anonim fonksiyonlar olarak düşünülebilirler. Özellikle fonksiyonel dillerin 7 | önemli enstrümanlarındandırlar. Bir closure bir değişkene atanıp kullanılabilir dolayısıyla 8 | fonksiyonlara parametre olarak kod bloğu içeren ifadeler göndermenin yolunu da açar. 9 | 10 | Rust standart kütüphanesinde Fn, FnMut, FnOnce gibi trait'ler ile Closure' ların çalışma 11 | davranışları belirlenir. 12 | 13 | Fn: Closure değişkenlere salt okunur olarak erişir. 14 | FnMut: Closure değişkenleri değiştirebilir. 15 | FnOnce: Closure değişkenleri sahiplenir ve sadece bir defa çalıştırılabilir. 16 | */ 17 | 18 | // Klasik bir yöntemler oyunların yıllarına göre sıralanması işlevini ele alalım 19 | fn year_sorter(game: &Game) -> u16 { 20 | game.year 21 | } 22 | 23 | fn main() { 24 | let mut games = repository::load_games(); 25 | // println!("Games List {:#?}", games); 26 | // /* 27 | // sort_by_key parametre olarak FnMut traitini uygulayan bir fonksiyon kullanır. 28 | // Örneğin yıla göre sıralama yapmak için bu bilgiyi geriye döndüren year_sorter fonksiyonu 29 | // sort_by_key'e parametre olarak geçebiliriz. Sort By Key bunu ascending sırada yapar. 30 | // */ 31 | // games.sort_by_key(year_sorter); 32 | // println!("Games List(Sorted by Year) {:#?}", games); 33 | // // Ancak closure'lar aşağıdaki örneklerde olduğu gibi daha efektif kullanılabilirler. 34 | 35 | // games.sort_by(|g1, g2| g1.year.cmp(&g2.year)); 36 | // println!("Games by year ascending order"); 37 | // print_games(&games); 38 | // 39 | // games.sort_by(|g1, g2| g2.year.cmp(&g1.year)); 40 | // println!("\nGames by year descending order"); 41 | // print_games(&games); 42 | 43 | let popular_games: Vec = games.into_iter().filter(|g| g.popularity > 2.0).collect(); 44 | print_games(&popular_games); 45 | 46 | scenario::run(); 47 | } 48 | 49 | fn print_games(games: &Vec) { 50 | for game in games { 51 | println!("{}, {}", game.year, game.title); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /S07_structs/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Rust dilinde 3 tür struct vardır. 3 | Named Field base. Player struct'ı bu türdendir 4 | Tuple based. Position struct'ı bu türdendir. 5 | Unit based. 6 | 7 | */ 8 | fn main() { 9 | let marlon = Player { 10 | name: String::from("Marlon Singer"), 11 | is_active: false, 12 | level: 100, 13 | position: Position(1.0, 0.0), 14 | }; 15 | println!("{} level is {}", marlon.name, marlon.level); 16 | 17 | let durden = spawn_random_user(String::from("Tyler Durden")); 18 | println!( 19 | "{}({}) on ({}:{})", 20 | durden.name, durden.is_active, durden.position.0, durden.position.1 21 | ); 22 | 23 | let position = Position(9.0, 12.0); 24 | println!( 25 | "Some position at the galaxy ({}:{})", 26 | position.0, position.1 27 | ); 28 | 29 | let mut rectangle = Rectangle::new(10.0, 20.0); 30 | println!("Area is {}", rectangle.area()); 31 | println!("Perimeter is {}", rectangle.perimeter()); 32 | rectangle.resize(10.0, 10.0); 33 | println!("Area is {}", rectangle.area()); 34 | println!("Perimeter is {}", rectangle.perimeter()); 35 | } 36 | 37 | fn spawn_random_user(name: String) -> Player { 38 | Player { 39 | name, 40 | is_active: true, 41 | level: 100, 42 | position: Position(10.0, 20.40), 43 | } 44 | } 45 | 46 | // Field base struct 47 | struct Player { 48 | name: String, 49 | is_active: bool, 50 | level: u8, 51 | position: Position, 52 | } 53 | 54 | struct Position(f32, f32); // Tuple based struct 55 | 56 | struct Rectangle { 57 | width: f32, 58 | height: f32, 59 | } 60 | 61 | impl Rectangle { 62 | fn new(width: f32, height: f32) -> Self { 63 | Rectangle { width, height } 64 | } 65 | fn area(&self) -> f32 { 66 | self.width * self.height 67 | } 68 | fn perimeter(&self) -> f32 { 69 | (self.width + self.height) * 2.0 70 | } 71 | fn resize(&mut self, width: f32, height: f32) { 72 | self.width = width; 73 | self.height = height; 74 | } 75 | } 76 | 77 | struct Entity; // Unit based struct (ECS tarafında sık gördüğümüz bir kavram) 78 | -------------------------------------------------------------------------------- /meth-leb/www/index.js: -------------------------------------------------------------------------------- 1 | import init, {calculate_parabola} from "../pkg/meth_leb.js"; 2 | 3 | async function main() { 4 | 5 | await init(); 6 | 7 | const form = document.getElementById("form"); 8 | const canvas = document.getElementById("canvas"); 9 | const context = canvas.getContext("2d"); 10 | const dropdown = document.getElementById("examples"); 11 | 12 | function drawAxes() { 13 | context.beginPath(); 14 | context.strokeStyle = "gray"; 15 | context.lineWidth = 1; 16 | 17 | context.moveTo(0, 300); 18 | context.lineTo(800, 300); 19 | 20 | context.moveTo(400, 0); 21 | context.lineTo(400, 600); 22 | 23 | context.stroke(); 24 | context.closePath(); 25 | } 26 | 27 | drawAxes(); 28 | 29 | function draw(a, b, c, x_min, x_max, steps) { 30 | 31 | const points = calculate_parabola(a, b, c, x_min, x_max, steps); 32 | 33 | context.clearRect(0, 0, canvas.width, canvas.height); 34 | drawAxes(); 35 | context.beginPath(); 36 | context.moveTo((points[0] - x_min) * 50, 300 - points[1] * 50); 37 | 38 | for (let i = 2; i < points.length; i += 2) { 39 | const x = (points[i] - x_min) * 50; 40 | const y = 300 - points[i + 1] * 50; 41 | context.lineTo(x, y); 42 | } 43 | 44 | context.stroke(); 45 | } 46 | 47 | dropdown.addEventListener("change", (event) => { 48 | const [a, b, c, x_min, x_max, steps] = event.target.value.split(",").map(Number); 49 | draw(a, b, c, x_min, x_max, steps); 50 | }); 51 | 52 | form.addEventListener("submit", (event) => { 53 | event.preventDefault(); 54 | 55 | const a = parseFloat(document.getElementById("a").value); 56 | const b = parseFloat(document.getElementById("b").value); 57 | const c = parseFloat(document.getElementById("c").value); 58 | const x_min = parseFloat(document.getElementById("x_min").value); 59 | const x_max = parseFloat(document.getElementById("x_max").value); 60 | const steps = parseInt(document.getElementById("steps").value); 61 | 62 | draw(a, b, c, x_min, x_max, steps); 63 | }); 64 | } 65 | 66 | main().catch((error) => console.error("Error on loading wasm module.", error)); 67 | -------------------------------------------------------------------------------- /S18_smart_pointers/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Pointer 3 | - Bellek üzerindeki bir veri içeriğini işaret eden adres bilgisini taşıyan 4 | değişken olarak düşünülebilir. 5 | - Farkında olmadan şu ana kadar kullandığımız bir pointer vardır (&) 6 | ve datayı referans etmekte kullanılır. 7 | 8 | Smart Pointer 9 | - Pointer adreslerine ek metadata bilgileri veya kabiliyetler içerirler. 10 | - Rust diline özel bir kavram değildir esasında C++ orijinlidir. 11 | - Referanslar veriyi işaret ederken Smart Pointer’ lar genellikle sahipliğini de alır 12 | (Sürpriz! String ve Vec türleri smart pointer olarak da geçer zira belli bir bellek 13 | adresindeki verinin sahipliğini alırlar ve onu manipüle etmemize izin verirler) 14 | - Deref ve Drop trait’lerini implemente eden struct türleri olarak tasarlanabilirler 15 | (Yani kendi Smart Pointer modellerimizi tasarlayabiliriz) 16 | 17 | Hangisi ne zaman? 18 | 19 | Box ve RefCell birden fazla sahipliği tek bir veri üzerinde sağlarken, 20 | Rc aynı veri üzerinden birden fazla sahiplik sunar. 21 | 22 | Box immutable veya mutable ödünç alma (borrowing) için derleme zamanında kontrol sağlar. 23 | Rc sadece immutable borrowing için derleme zamanında kontrol sağlar. 24 | RefCell immutable veya mutable ödünç alma için runtime'da kontrol sağlar. 25 | */ 26 | mod boxing; 27 | mod rc_scenario; 28 | 29 | use crate::boxing::*; 30 | use crate::rc_scenario::*; 31 | 32 | fn main() { 33 | simple_boxing(); 34 | //recursive_data_model_with_error(); 35 | recursive_sample(); 36 | hello_rc(); 37 | // run_rc_with_error(); 38 | // run_rc_with_error_2(); 39 | 40 | /* 41 | Alttaki senaryoda aslında farklı kullanım şekilleri de söz konusu olabilir. 42 | 43 | - Sadece bir vektör üzerinde çalışma yapıyorsak RefCell> kullanımı yeterlidir. 44 | - Vektörün paylaşımı söz konusu ise Rc>> daha uygun olabilir. 45 | - Hem vektörü hem de içindeki elemanları paylaşmamız gerekirse Rc>> 46 | daha iyi bir çözüm olabilir. 47 | 48 | Tabii şunu uutmamamak lazım ki hem Rc hem de RefCell kullanımı nedeniyle 49 | runtime maliyeti daha yüksektir (Zira burada referans sayımı ve mutasyon kontrolleri yapılır) 50 | */ 51 | run_rc(); 52 | } 53 | -------------------------------------------------------------------------------- /proc_macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate proc_macro; 2 | use proc_macro::TokenStream; 3 | use quote::quote; 4 | use syn::{parse_macro_input, Expr, ItemFn, LitStr}; 5 | 6 | #[proc_macro_attribute] 7 | pub fn work_time_effort(_attr: TokenStream, item: TokenStream) -> TokenStream { 8 | let input = parse_macro_input!(item as ItemFn); 9 | let fn_name = &input.sig.ident; 10 | let fn_block = &input.block; 11 | 12 | let expanded = quote! { 13 | fn #fn_name() { 14 | let start = std::time::Instant::now(); 15 | #fn_block 16 | let duration = start.elapsed(); 17 | println!("Total execution time {}: {:?}", stringify!(#fn_name), duration); 18 | } 19 | }; 20 | 21 | expanded.into() 22 | } 23 | 24 | #[proc_macro_attribute] 25 | pub fn work_time_effort_log(attr: TokenStream, item: TokenStream) -> TokenStream { 26 | let log_level = parse_macro_input!(attr as LitStr).value(); 27 | 28 | let input = parse_macro_input!(item as ItemFn); 29 | let fn_name = &input.sig.ident; 30 | let fn_block = &input.block; 31 | 32 | let expanded = quote! { 33 | fn #fn_name() { 34 | let start = std::time::Instant::now(); 35 | #fn_block 36 | let duration = start.elapsed(); 37 | match #log_level { 38 | "info" => println!("[INFO] Total execution time {}: {:?}", stringify!(#fn_name), duration), 39 | "debug" => println!("[DEBUG] Total execution time {}: {:?}", stringify!(#fn_name), duration), 40 | "error" => eprintln!("[ERROR] Total execution time {}: {:?}", stringify!(#fn_name), duration), 41 | _ => println!("Unknown log level: {}", #log_level), 42 | } 43 | } 44 | }; 45 | 46 | expanded.into() 47 | } 48 | 49 | #[proc_macro_attribute] 50 | pub fn log_execution(attr: TokenStream, item: TokenStream) -> TokenStream { 51 | let logger_expr = parse_macro_input!(attr as Expr); 52 | 53 | let input = parse_macro_input!(item as ItemFn); 54 | let fn_name = &input.sig.ident; 55 | let fn_block = &input.block; 56 | 57 | let expanded = quote! { 58 | fn #fn_name() { 59 | let start = std::time::Instant::now(); 60 | #fn_block 61 | let duration = start.elapsed(); 62 | #logger_expr.log(&format!("Execution time for {}: {:?}", stringify!(#fn_name), duration)); 63 | } 64 | }; 65 | 66 | expanded.into() 67 | } 68 | -------------------------------------------------------------------------------- /S17_closures/src/repository.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | pub struct Game { 3 | pub title: String, 4 | pub year: u16, 5 | pub popularity: f32, 6 | } 7 | 8 | pub fn load_games() -> Vec { 9 | vec![ 10 | Game { 11 | title: String::from("The Legend of Zelda: Breath of the Wild"), 12 | year: 2017, 13 | popularity: 1.5, 14 | }, 15 | Game { 16 | title: String::from("Half-Life 2"), 17 | year: 2004, 18 | popularity: 1.6, 19 | }, 20 | Game { 21 | title: String::from("The Witcher 3: Wild Hunt"), 22 | year: 2015, 23 | popularity: 1.8, 24 | }, 25 | Game { 26 | title: String::from("Dark Souls"), 27 | year: 2011, 28 | popularity: 1.1, 29 | }, 30 | Game { 31 | title: String::from("God of War"), 32 | year: 2018, 33 | popularity: 1.25, 34 | }, 35 | Game { 36 | title: String::from("Super Mario Odyssey"), 37 | year: 2017, 38 | popularity: 1.9, 39 | }, 40 | Game { 41 | title: String::from("Hades"), 42 | year: 2020, 43 | popularity: 2.8, 44 | }, 45 | Game { 46 | title: String::from("Resident Evil 4"), 47 | year: 2005, 48 | popularity: 0.9, 49 | }, 50 | Game { 51 | title: String::from("Minecraft"), 52 | year: 2009, 53 | popularity: 2.73, 54 | }, 55 | Game { 56 | title: String::from("Overwatch"), 57 | year: 2016, 58 | popularity: 1.25, 59 | }, 60 | Game { 61 | title: String::from("Grand Theft Auto V"), 62 | year: 2013, 63 | popularity: 1.1, 64 | }, 65 | Game { 66 | title: String::from("Animal Crossing: New Horizons"), 67 | year: 2020, 68 | popularity: 1.4, 69 | }, 70 | Game { 71 | title: String::from("Elden Ring"), 72 | year: 2022, 73 | popularity: 2.98, 74 | }, 75 | Game { 76 | title: String::from("Bloodborne"), 77 | year: 2015, 78 | popularity: 1.12, 79 | }, 80 | Game { 81 | title: String::from("Sekiro: Shadows Die Twice"), 82 | year: 2019, 83 | popularity: 0.78, 84 | }, 85 | Game { 86 | title: String::from("Mass Effect 2"), 87 | year: 2010, 88 | popularity: 1.98, 89 | }, 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /S18_smart_pointers/src/boxing.rs: -------------------------------------------------------------------------------- 1 | pub fn simple_boxing() { 2 | // Örnek bir Boxing işlemi 3 | let value = 23; // Normalde stack' de saklanır 4 | let boxed_value = Box::new(value); // Şimdi heap'e alındı ama boxed_value hala stack'te zira adres göstermekte 5 | println!("Boxed value is {}", boxed_value); 6 | 7 | let identity = ("John Smith", 23, true); // tuple veriyi stack'ta saklar 8 | let boxed_identity = Box::new(identity); // Şimdi heap' te 9 | println!("Boxed identity is {:?}", boxed_identity); 10 | } 11 | 12 | /* 13 | Aşağıdaki kullanım build aşamasında 14 | error[E0072]: recursive type `Tree` has infinite size 15 | hatasını verir. Bu tip recursive veri modellerinde datanın ne kadar yer kaplayacağı bilinemez. 16 | Zira Rust derleme zamanında nesnelerin ne kadar yer kaplayacağını bilmek ister. 17 | Bir düğüm kendisine referans verdikçe bu sonsuz bir boyutlamaya gider. 18 | Bu nedenle ilgili senaryoda Box kullanılarak esasında Heap bazlı bir kullanıma gidilir. 19 | */ 20 | // enum Tree { 21 | // Node(i32, Tree, Tree), 22 | // Empty, 23 | // } 24 | 25 | //pub fn recursive_data_model_with_error() { 26 | // let left_child = Tree::Node(1, Tree::Empty, Tree::Empty); 27 | // let right_child = Tree::Node(3, Tree::Empty, Tree::Empty); 28 | // let root = Tree::Node(2, left_child, right_child); 29 | // } 30 | 31 | use std::fmt::{Display, Formatter}; 32 | 33 | enum Server { 34 | Node(String, Box, Box), 35 | Empty, 36 | } 37 | impl Display for Server { 38 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 39 | match self { 40 | Server::Node(name, primary, backup) => { 41 | write!( 42 | f, 43 | "Server: {}\n Primary: {}\n Backup: {}", 44 | name, primary, backup 45 | ) 46 | } 47 | Server::Empty => write!(f, "None"), 48 | } 49 | } 50 | } 51 | 52 | pub fn recursive_sample() { 53 | let backup_server_blue = Server::Node( 54 | String::from("Backup Server Blue"), 55 | Box::new(Server::Empty), 56 | Box::new(Server::Empty), 57 | ); 58 | 59 | let primary_server_green = Server::Node( 60 | String::from("Primary Server Green"), 61 | Box::new(Server::Empty), 62 | Box::new(backup_server_blue), 63 | ); 64 | 65 | let root_server = Server::Node( 66 | String::from("Root Server"), 67 | Box::new(primary_server_green), 68 | Box::new(Server::Node( 69 | String::from("Backup Root"), 70 | Box::new(Server::Empty), 71 | Box::new(Server::Empty), 72 | )), 73 | ); 74 | 75 | println!("{}", root_server); 76 | } 77 | -------------------------------------------------------------------------------- /S25_streams/src/ping_server.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | use std::io::{Read, Write}; 3 | use std::net::{TcpListener, TcpStream}; 4 | 5 | /* 6 | Bu örnekte TcpStream ve TcpListener kullanılarak ilkel bir web server işletiliyor. 7 | İstemciler http://localhost:5001/ping adresine bir talepte bulunduklarında JSON formatında 8 | Pong! isimli bir cevap alıyorlar. Eğer başka bir route talep edilirse de Not Found cevabı 9 | alıyorlar. 10 | 11 | TcpStream ve TcpListener kullanılarak low-level'da bir HTTP Server yazmak daha mantıklı elbette. 12 | Bu ikili kullanılarak farklı server'lar da yazılabilir. 13 | 14 | İstemciden gelen veriyi geriye döndüren echo server, 15 | File Server, 16 | Chat uygulaması, 17 | Redis benzeri key-value store 18 | */ 19 | fn handle_ping(mut stream: TcpStream) { 20 | let mut buffer = [0; 512]; 21 | stream.read(&mut buffer).unwrap(); 22 | 23 | let request = String::from_utf8_lossy(&buffer); 24 | let mut parts = request.split_whitespace(); 25 | let method = parts.next().unwrap_or(""); 26 | let path = parts.next().unwrap_or(""); 27 | 28 | let response = if method == HttpMethod::Get.to_string() && path == "/ping" { 29 | let body = r#"{"message": "Pong!"}"#; 30 | format!( 31 | "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{}", 32 | body.len(), 33 | body 34 | ) 35 | } else { 36 | let body = r#"{"error": "Not Found"}"#; 37 | format!( 38 | "HTTP/1.1 404 Not Found\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{}", 39 | body.len(), 40 | body 41 | ) 42 | }; 43 | 44 | stream.write_all(response.as_bytes()).unwrap(); 45 | stream.flush().unwrap(); 46 | } 47 | 48 | pub fn run() { 49 | /* 50 | localhost:5001 portu sürekli dinleniyor ve data stream handle_ping metoduna 51 | gönderilerek değerlendiriliyor. 52 | */ 53 | let listener = TcpListener::bind("127.0.0.1:5001").unwrap(); 54 | println!("Listening on 127.0.0.1:5001..."); 55 | 56 | for stream in listener.incoming() { 57 | handle_ping(stream.unwrap()); 58 | } 59 | } 60 | 61 | enum HttpMethod { 62 | Post, 63 | Get, 64 | Delete, 65 | Patch, 66 | Put, 67 | } 68 | impl Display for HttpMethod { 69 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 70 | let str = match self { 71 | HttpMethod::Post => "POST".to_string(), 72 | HttpMethod::Get => "GET".to_string(), 73 | HttpMethod::Delete => "DELETE".to_string(), 74 | HttpMethod::Patch => "PATCH".to_string(), 75 | HttpMethod::Put => "PUT".to_string(), 76 | }; 77 | write!(f, "{}", str) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /S25_streams/src/file_server.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | use std::io::{Read, Write}; 3 | use std::net::{TcpListener, TcpStream}; 4 | use std::path::Path; 5 | /* 6 | Bu örnek kod parçasında ise ilkel bir file server yer almaktadır. 7 | Örnek png, jpg, gif gibi resim formatları ile html ve txt gibi metinsel olanları ele alır. 8 | 9 | Test etmek için 10 | 11 | localhost:5003 adresine HTTP Get talebi göndermek yeterli. Örneğin; 12 | 13 | http://localhost:5003/profile_woman.png 14 | http://localhost:5003/profile_man.png 15 | http://localhost:5003/index.html 16 | 17 | curl ile test etmek içinse aşağıdaki gibi ilerleyebiliriz. 18 | 19 | curl -v http://localhost:5003/profile_woman.png --output woman.png 20 | 21 | gibi 22 | */ 23 | 24 | fn handle_request(mut stream: TcpStream) { 25 | let mut buffer = [0; 512]; 26 | if let Err(err) = stream.read(&mut buffer) { 27 | eprintln!("Error reading stream: {}", err); 28 | return; 29 | } 30 | 31 | let request = String::from_utf8_lossy(&buffer); 32 | let mut parts = request.split_whitespace(); 33 | let method = parts.next().unwrap_or(""); 34 | let path = parts.next().unwrap_or(""); 35 | 36 | println!("Request: {} {}", method, path); 37 | 38 | if method == "GET" && path != "/favicon.ico" { 39 | let filename = &path[1..]; 40 | println!("Serving file: {}", filename); 41 | 42 | if let Ok(contents) = fs::read(filename) { 43 | let content_type = match Path::new(filename).extension().and_then(|ext| ext.to_str()) { 44 | Some("png") => "image/png", 45 | Some("jpg") | Some("jpeg") => "image/jpeg", 46 | Some("gif") => "image/gif", 47 | Some("html") => "text/html", 48 | Some("txt") => "text/plain", 49 | _ => "application/octet-stream", 50 | }; 51 | 52 | let response = format!( 53 | "HTTP/1.1 200 OK\r\nContent-Type: {}\r\nContent-Length: {}\r\nConnection: close\r\n\r\n", 54 | content_type, 55 | contents.len() 56 | ); 57 | 58 | stream.write_all(response.as_bytes()).unwrap(); 59 | stream.write_all(&contents).unwrap(); 60 | stream.flush().unwrap(); 61 | } else { 62 | let response = 63 | "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"; 64 | stream.write_all(response.as_bytes()).unwrap(); 65 | } 66 | } 67 | } 68 | 69 | pub fn run() -> std::io::Result<()> { 70 | let address = "127.0.0.1:5003"; 71 | let listener = TcpListener::bind(address)?; 72 | println!("File server is ready on {address}"); 73 | 74 | for stream in listener.incoming() { 75 | if let Ok(stream) = stream { 76 | handle_request(stream); 77 | } else { 78 | eprintln!("Failed to accept connection"); 79 | } 80 | } 81 | 82 | Ok(()) 83 | } 84 | -------------------------------------------------------------------------------- /S16_testing/src/membership.rs: -------------------------------------------------------------------------------- 1 | struct MembershipManager; 2 | 3 | impl MembershipManager { 4 | fn validate_nickname(&self, nick_name: &str) -> Result<(), UserError> { 5 | if nick_name.len() < 5 { 6 | return Err(UserError::InvalidNickname(String::from( 7 | "Nickname is too short", 8 | ))); 9 | } 10 | if nick_name.len() > 15 { 11 | return Err(UserError::InvalidNickname(String::from( 12 | "Nickname is too long", 13 | ))); 14 | } 15 | if nick_name.contains(' ') { 16 | return Err(UserError::InvalidNickname(String::from( 17 | "Nickname contains space", 18 | ))); 19 | } 20 | if nick_name.chars().any(|c| !c.is_alphanumeric()) { 21 | return Err(UserError::InvalidNickname(String::from( 22 | "Nickname contains alphanumeric", 23 | ))); 24 | } 25 | Ok(()) 26 | } 27 | } 28 | 29 | #[derive(Debug, PartialEq)] 30 | enum UserError { 31 | InvalidNickname(String), 32 | WrongPassword, 33 | } 34 | 35 | #[cfg(test)] 36 | mod membership_tests { 37 | use super::*; 38 | 39 | #[test] 40 | fn test_valid_nick_name() { 41 | let membership_manager = MembershipManager; 42 | assert!(membership_manager.validate_nickname("rustropic").is_ok()); 43 | } 44 | 45 | #[test] 46 | fn test_short_nick_name() { 47 | let membership_manager = MembershipManager; 48 | let result = membership_manager.validate_nickname("none"); 49 | assert_eq!( 50 | result, 51 | Err(UserError::InvalidNickname( 52 | "Nickname is too short".to_string() 53 | )) 54 | ); 55 | } 56 | 57 | #[test] 58 | fn test_long_nick_name() { 59 | let membership_manager = MembershipManager; 60 | let result = membership_manager.validate_nickname("ToooooLonnnnnnnnngggggggggggNickkkk"); 61 | assert_eq!( 62 | result, 63 | Err(UserError::InvalidNickname( 64 | "Nickname is too long".to_string() 65 | )) 66 | ); 67 | } 68 | 69 | #[test] 70 | fn test_nick_name_with_space() { 71 | let membership_manager = MembershipManager; 72 | let result = membership_manager.validate_nickname("The Red Barron"); 73 | assert_eq!( 74 | result, 75 | Err(UserError::InvalidNickname( 76 | "Nickname contains space".to_string() 77 | )) 78 | ); 79 | } 80 | 81 | #[test] 82 | fn test_nick_name_with_special_chars() { 83 | let membership_manager = MembershipManager; 84 | let result = membership_manager.validate_nickname("Rust@Nickname!"); 85 | assert_eq!( 86 | result, 87 | Err(UserError::InvalidNickname( 88 | "Nickname contains alphanumeric".to_string() 89 | )) 90 | ); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /meth-leb/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

wasm-pack-template

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

8 | Build Status 9 |

10 | 11 |

12 | Tutorial 13 | | 14 | Chat 15 |

16 | 17 | Built with 🦀🕸 by The Rust and WebAssembly Working Group 18 |
19 | 20 | ## About 21 | 22 | [**📚 Read this template tutorial! 📚**][template-docs] 23 | 24 | This template is designed for compiling Rust libraries into WebAssembly and 25 | publishing the resulting package to NPM. 26 | 27 | Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other 28 | templates and usages of `wasm-pack`. 29 | 30 | [tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html 31 | [template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html 32 | 33 | ## 🚴 Usage 34 | 35 | ### 🐑 Use `cargo generate` to Clone this Template 36 | 37 | [Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate) 38 | 39 | ``` 40 | cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project 41 | cd my-project 42 | ``` 43 | 44 | ### 🛠️ Build with `wasm-pack build` 45 | 46 | ``` 47 | wasm-pack build 48 | ``` 49 | 50 | ### 🔬 Test in Headless Browsers with `wasm-pack test` 51 | 52 | ``` 53 | wasm-pack test --headless --firefox 54 | ``` 55 | 56 | ### 🎁 Publish to NPM with `wasm-pack publish` 57 | 58 | ``` 59 | wasm-pack publish 60 | ``` 61 | 62 | ## 🔋 Batteries Included 63 | 64 | * [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating 65 | between WebAssembly and JavaScript. 66 | * [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook) 67 | for logging panic messages to the developer console. 68 | * `LICENSE-APACHE` and `LICENSE-MIT`: most Rust projects are licensed this way, so these are included for you 69 | 70 | ## License 71 | 72 | Licensed under either of 73 | 74 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 75 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 76 | 77 | at your option. 78 | 79 | ### Contribution 80 | 81 | Unless you explicitly state otherwise, any contribution intentionally 82 | submitted for inclusion in the work by you, as defined in the Apache-2.0 83 | license, shall be dual licensed as above, without any additional terms or 84 | conditions. 85 | -------------------------------------------------------------------------------- /s27-hello-wasm/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

wasm-pack-template

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

8 | Build Status 9 |

10 | 11 |

12 | Tutorial 13 | | 14 | Chat 15 |

16 | 17 | Built with 🦀🕸 by The Rust and WebAssembly Working Group 18 |
19 | 20 | ## About 21 | 22 | [**📚 Read this template tutorial! 📚**][template-docs] 23 | 24 | This template is designed for compiling Rust libraries into WebAssembly and 25 | publishing the resulting package to NPM. 26 | 27 | Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other 28 | templates and usages of `wasm-pack`. 29 | 30 | [tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html 31 | [template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html 32 | 33 | ## 🚴 Usage 34 | 35 | ### 🐑 Use `cargo generate` to Clone this Template 36 | 37 | [Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate) 38 | 39 | ``` 40 | cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project 41 | cd my-project 42 | ``` 43 | 44 | ### 🛠️ Build with `wasm-pack build` 45 | 46 | ``` 47 | wasm-pack build 48 | ``` 49 | 50 | ### 🔬 Test in Headless Browsers with `wasm-pack test` 51 | 52 | ``` 53 | wasm-pack test --headless --firefox 54 | ``` 55 | 56 | ### 🎁 Publish to NPM with `wasm-pack publish` 57 | 58 | ``` 59 | wasm-pack publish 60 | ``` 61 | 62 | ## 🔋 Batteries Included 63 | 64 | * [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating 65 | between WebAssembly and JavaScript. 66 | * [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook) 67 | for logging panic messages to the developer console. 68 | * `LICENSE-APACHE` and `LICENSE-MIT`: most Rust projects are licensed this way, so these are included for you 69 | 70 | ## License 71 | 72 | Licensed under either of 73 | 74 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 75 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 76 | 77 | at your option. 78 | 79 | ### Contribution 80 | 81 | Unless you explicitly state otherwise, any contribution intentionally 82 | submitted for inclusion in the work by you, as defined in the Apache-2.0 83 | license, shall be dual licensed as above, without any additional terms or 84 | conditions. 85 | -------------------------------------------------------------------------------- /meth-leb/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Parabola Drawer 4 | 5 | 16 | 17 | 18 |

Parabola Drawer

19 |

y = ax² + bx + c

20 |

Fun with math :) Select a predefined parabola or use your values to draw your own parabola.

21 | 22 |
23 |
24 | 25 | 37 |
38 | 39 |
40 |
41 | 42 | 43 |
44 |
45 | 46 | 47 |
48 |
49 | 50 | 51 |
52 |
53 | 54 |
55 |
56 | 57 | 58 |
59 |
60 | 61 | 62 |
63 |
64 | 65 | 66 |
67 |
68 | 69 | 70 |
71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /S11_generics/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Generic türler ile tipler üzerinden genel soyutlamalar yapmak mümkün olur. 3 | Aynı fonksiyonu veya veri yapısını farklı türler için ayrı ayrı tasarlamak yerine 4 | generic alt yapısından yararlanılabilir. 5 | 6 | Generic kavramı C# ve Go gibi dillerde de yaygın olarak kullanılır. 7 | 8 | */ 9 | use std::fmt::{Debug, Display}; 10 | use std::ops::Add; 11 | 12 | fn main() { 13 | log_any(3.14f32); 14 | log_any("TCP connection established"); 15 | log_any(State::InProgress); 16 | log_any(false); 17 | 18 | let game_point = Point::::new(10, 20, 10); 19 | println!("{}", game_point.info()); 20 | 21 | let vehicle_position: Point = Point::new(5.5, 3.14, 2.20); 22 | println!("Vehicle Position {}", vehicle_position.info()); 23 | 24 | let vehicle_new_position: Point = vehicle_position.add(Point::new(1.0, 1.0, 2.0)); 25 | println!("New position after move {}", vehicle_new_position.info()); 26 | } 27 | 28 | #[derive(Debug)] 29 | enum State { 30 | InProgress, 31 | Done, 32 | Error, 33 | } 34 | 35 | /* 36 | Örnek bir generic fonksiyon. 37 | parametre olarak gelen object değişkeni T türünden olabilir. 38 | T için herhangibir kısıt belirtilmediğinden herhangibir türü alabilir. 39 | 40 | Tabii burada henüz işlenmeyen iki trait kullanımı söz konusu. 41 | log_any fonksiyonu içerisindeki println! metodunda {:?} formasyonu kullanılmıştır. 42 | Bu formasyon ilgili türün Debug Trait'ini uygulamış olduğunu varsasyar. 43 | Buna göre gelen T türünün println! fonksiyonunda {:?} formasyonunda kullanılabilmesi 44 | için T'nin Debug trait'ini uygulamak zorunda olduğu belirtilmelidir. 45 | T:Debug bu amaçla yazılmıştır. 46 | */ 47 | fn log_any(object: T) { 48 | println!("Logged value ise '{:?}'", object); 49 | } 50 | 51 | /* 52 | Kendi generic veri modellerimizi de tanımlayabiliriz. 53 | Yaygın kullanılan örneklerden birisi koordinat bilgisi veya kompleks sayılardır. 54 | 55 | Aşağıdaki 3D koordinat sistemi için bir veri modeli tanımı söz konusudur. 56 | 57 | Sadece T kullanmak veri yapısını bozabilir. Nitekim her tür buraya gelebilir. 58 | Bu nedenle generic constraint kullanmak mantıklıdır. 59 | Mesela Point yapısının sadece i32, u8, i16, f32 gibi sayısal türler ile çalışması için 60 | T'nin farklı bir şekilde kısıtlanması gerekir. 61 | 62 | Bu kısım belki eğitim için biraz zorlayıcı olabilir. 63 | 64 | Copy ve Add traitleri sayısal ifadeler için kullanılan davranışları tanımlar. 65 | Ayrıca T türünün {:?} formasyonu ile kullanılabilmesi için Debug trait'inin uygulanması gerekir. 66 | */ 67 | struct Point> { 68 | x: T, 69 | y: T, 70 | z: T, 71 | } 72 | 73 | impl> Point { 74 | fn new(x: T, y: T, z: T) -> Self { 75 | Point { x, y, z } 76 | } 77 | fn info(&self) -> String { 78 | format!("({:?}, {:?}, {:?})", self.x, self.y, self.z) 79 | } 80 | fn add(self, other: Point) -> Point { 81 | Point { 82 | x: self.x + other.x, 83 | y: self.y + other.y, 84 | z: self.z + other.z, 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /meth-leb/.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | sudo: false 3 | 4 | cache: cargo 5 | 6 | matrix: 7 | include: 8 | 9 | # Builds with wasm-pack. 10 | - rust: beta 11 | env: RUST_BACKTRACE=1 12 | addons: 13 | firefox: latest 14 | chrome: stable 15 | before_script: 16 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 17 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 18 | - cargo install-update -a 19 | - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f 20 | script: 21 | - cargo generate --git . --name testing 22 | # Having a broken Cargo.toml (in that it has curlies in fields) anywhere 23 | # in any of our parent dirs is problematic. 24 | - mv Cargo.toml Cargo.toml.tmpl 25 | - cd testing 26 | - wasm-pack build 27 | - wasm-pack test --chrome --firefox --headless 28 | 29 | # Builds on nightly. 30 | - rust: nightly 31 | env: RUST_BACKTRACE=1 32 | before_script: 33 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 34 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 35 | - cargo install-update -a 36 | - rustup target add wasm32-unknown-unknown 37 | script: 38 | - cargo generate --git . --name testing 39 | - mv Cargo.toml Cargo.toml.tmpl 40 | - cd testing 41 | - cargo check 42 | - cargo check --target wasm32-unknown-unknown 43 | - cargo check --no-default-features 44 | - cargo check --target wasm32-unknown-unknown --no-default-features 45 | - cargo check --no-default-features --features console_error_panic_hook 46 | - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook 47 | - cargo check --no-default-features --features "console_error_panic_hook wee_alloc" 48 | - cargo check --target wasm32-unknown-unknown --no-default-features --features "console_error_panic_hook wee_alloc" 49 | 50 | # Builds on beta. 51 | - rust: beta 52 | env: RUST_BACKTRACE=1 53 | before_script: 54 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 55 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 56 | - cargo install-update -a 57 | - rustup target add wasm32-unknown-unknown 58 | script: 59 | - cargo generate --git . --name testing 60 | - mv Cargo.toml Cargo.toml.tmpl 61 | - cd testing 62 | - cargo check 63 | - cargo check --target wasm32-unknown-unknown 64 | - cargo check --no-default-features 65 | - cargo check --target wasm32-unknown-unknown --no-default-features 66 | - cargo check --no-default-features --features console_error_panic_hook 67 | - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook 68 | # Note: no enabling the `wee_alloc` feature here because it requires 69 | # nightly for now. 70 | -------------------------------------------------------------------------------- /s27-hello-wasm/.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | sudo: false 3 | 4 | cache: cargo 5 | 6 | matrix: 7 | include: 8 | 9 | # Builds with wasm-pack. 10 | - rust: beta 11 | env: RUST_BACKTRACE=1 12 | addons: 13 | firefox: latest 14 | chrome: stable 15 | before_script: 16 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 17 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 18 | - cargo install-update -a 19 | - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f 20 | script: 21 | - cargo generate --git . --name testing 22 | # Having a broken Cargo.toml (in that it has curlies in fields) anywhere 23 | # in any of our parent dirs is problematic. 24 | - mv Cargo.toml Cargo.toml.tmpl 25 | - cd testing 26 | - wasm-pack build 27 | - wasm-pack test --chrome --firefox --headless 28 | 29 | # Builds on nightly. 30 | - rust: nightly 31 | env: RUST_BACKTRACE=1 32 | before_script: 33 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 34 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 35 | - cargo install-update -a 36 | - rustup target add wasm32-unknown-unknown 37 | script: 38 | - cargo generate --git . --name testing 39 | - mv Cargo.toml Cargo.toml.tmpl 40 | - cd testing 41 | - cargo check 42 | - cargo check --target wasm32-unknown-unknown 43 | - cargo check --no-default-features 44 | - cargo check --target wasm32-unknown-unknown --no-default-features 45 | - cargo check --no-default-features --features console_error_panic_hook 46 | - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook 47 | - cargo check --no-default-features --features "console_error_panic_hook wee_alloc" 48 | - cargo check --target wasm32-unknown-unknown --no-default-features --features "console_error_panic_hook wee_alloc" 49 | 50 | # Builds on beta. 51 | - rust: beta 52 | env: RUST_BACKTRACE=1 53 | before_script: 54 | - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) 55 | - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) 56 | - cargo install-update -a 57 | - rustup target add wasm32-unknown-unknown 58 | script: 59 | - cargo generate --git . --name testing 60 | - mv Cargo.toml Cargo.toml.tmpl 61 | - cd testing 62 | - cargo check 63 | - cargo check --target wasm32-unknown-unknown 64 | - cargo check --no-default-features 65 | - cargo check --target wasm32-unknown-unknown --no-default-features 66 | - cargo check --no-default-features --features console_error_panic_hook 67 | - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook 68 | # Note: no enabling the `wee_alloc` feature here because it requires 69 | # nightly for now. 70 | -------------------------------------------------------------------------------- /S25_streams/src/kv_server.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::io::{Read, Write}; 3 | use std::net::{TcpListener, TcpStream}; 4 | use std::sync::{Arc, Mutex}; 5 | use std::thread; 6 | 7 | /* 8 | Bu örnekte ise basit bir key-value store'un stream üzerinden host edilmesi ele alınır. 9 | Gelen talepler için ayrı birer thread başlatılır. 10 | Test etmek için yine ncat aracından aşağıdaki gibi yararlanabiliriz. 11 | 12 | echo SET isActive true | ncat localhost 5002 13 | echo GET isActive" | ncat localhost 5002 14 | 15 | echo SET connectionString datasource=localhost;database=Northwind | ncat localhost 5002 16 | echo GET connectionString | ncat localhost 5002 17 | 18 | echo LIST | ncat localhost 5002 19 | 20 | Pek tabii bu tip bir sunucuya karşılık gelecek bir istemci de yazılabilir. 21 | */ 22 | 23 | fn handle_request(mut stream: TcpStream, value_store: Arc>>) { 24 | let mut buffer = [0; 1024]; 25 | while let Ok(bytes_read) = stream.read(&mut buffer) { 26 | if bytes_read == 0 { 27 | break; 28 | } 29 | let request = String::from_utf8_lossy(&buffer[..bytes_read]); 30 | println!("Request: {}", request); 31 | let mut parts = request.split_whitespace(); 32 | 33 | let command = parts.next().unwrap_or(""); 34 | let key = parts.next().unwrap_or(""); 35 | let value = parts.next().unwrap_or(""); 36 | println!("Command: {}\nKey:{}\nValue:{}\n", command, key, value); 37 | 38 | let response = match command { 39 | "SET" => { 40 | let mut vs_guard = value_store.lock().unwrap(); 41 | vs_guard.insert(key.to_string(), value.to_string()); 42 | "OK\n".to_string() 43 | } 44 | "GET" => { 45 | let vs_guard = value_store.lock().unwrap(); 46 | vs_guard 47 | .get(key) 48 | .cloned() 49 | .unwrap_or("NOT FOUND\n".to_string()) 50 | } 51 | "DEL" => { 52 | let mut vs_guard = value_store.lock().unwrap(); 53 | if vs_guard.remove(key).is_some() { 54 | "DELETED\n".to_string() 55 | } else { 56 | "NOT FOUND\n".to_string() 57 | } 58 | } 59 | "LIST" => { 60 | let vs_guard = value_store.lock().unwrap(); 61 | let keys: Vec = vs_guard.keys().cloned().collect(); 62 | keys.join("\n") 63 | } 64 | _ => "ERROR: Unknown command\n".to_string(), 65 | }; 66 | 67 | stream.write_all(response.as_bytes()).unwrap(); 68 | } 69 | } 70 | 71 | pub fn run() -> std::io::Result<()> { 72 | let address = "127.0.0.1:5002"; 73 | let listener = TcpListener::bind(address)?; 74 | let value_store = Arc::new(Mutex::new(HashMap::new())); 75 | 76 | println!("KV Store is ready on {address}"); 77 | 78 | for stream in listener.incoming() { 79 | let stream = stream?; 80 | let value_store_clone = Arc::clone(&value_store); 81 | 82 | thread::spawn(move || handle_request(stream, value_store_clone)); 83 | } 84 | 85 | Ok(()) 86 | } 87 | -------------------------------------------------------------------------------- /S01_variables/src/main.rs: -------------------------------------------------------------------------------- 1 | // Referans doküman https://doc.rust-lang.org/beta/book/ch03-02-data-types.html 2 | 3 | fn main() { 4 | let last_score = 90; 5 | println!("Last score is {}", last_score); 6 | // last_score=80; // Default immutable olduğundan çalışmaz. 7 | 8 | let mut last_score = 80; 9 | println!("Last score is {}", last_score); 10 | last_score = 60; 11 | println!("Last score is {}", last_score); 12 | 13 | let _delta_time = 1.25; // default f64 14 | let _delta_time = 1.25_f32; 15 | let delta_time: f32 = 1.25; 16 | println!("Delta time is {}", delta_time); 17 | 18 | let _total_values = 1 + 2 + 3; 19 | let total_values: u8 = 1 + 2 + 3; 20 | println!("Total values is {}", total_values); 21 | 22 | /* 23 | Genellikle renk değerlerini temsil etmek veya bellek adreslerini ifade etmek için kullanılır. 24 | 16'lık sistem, ikilik sisteme (binary) göre daha büyük bir aralık sunar ve sayıları daha 25 | kısa formatta ifade edebilir. 26 | */ 27 | let color_in_hex = 0xFF0032; 28 | println!("Color is {color_in_hex} or {:x}", color_in_hex); 29 | 30 | /* 31 | Octal(8lik sistem), genellikle dosya izinlerini ve diğer POSIX sistemlerinde kullanılan izinleri göstermek için kullanılır. 32 | Unix ve Linux tabanlı sistemlerde dosya izinleri,Örneğin, chmod 755 komutu, dosya izinlerini 8'lik sistemde ayarlayan bir komuttur 33 | */ 34 | let file_permission: u32 = 0o755; 35 | println!( 36 | "File permission is {file_permission} or {:o}", 37 | file_permission 38 | ); 39 | 40 | /* 41 | Düşük seviye programlama ve bit manipülasyonunda kullanılabilir. 42 | Örneğin bit seviyesinden flag'leri kontrol etmek, belli bitleri açık kapamak gibi 43 | */ 44 | let some_flags: u8 = 0b1010_0110; 45 | println!("Flags is {some_flags} or {:b}", some_flags); 46 | 47 | let is_valid = true; 48 | println!("Is valid? {}", is_valid); 49 | 50 | let is_even = 10 % 2 == 0; 51 | println!("Is even? {}", is_even); 52 | 53 | let up_button = 'w'; 54 | println!("Button is {:}", up_button); 55 | 56 | println!("Max Height is {MAX_HEIGHT}"); 57 | println!("Background color is {:?}", BACKGROUND_COLOR); 58 | 59 | // Tuple, compound type olarak bilinen türlerndendir. 60 | // Farklı tür değerlerini tek bir çatı altında toplayan türler Compound Type olarak adlandırılır 61 | let arguments = (640, 480, String::from("Game Title"), false); 62 | println!("Arguments is {:#?}", arguments); 63 | println!("Screen width and height {}x{}", arguments.0, arguments.1); 64 | 65 | let (title, is_active) = (arguments.1, arguments.2); 66 | println!("Title is {}", title); 67 | println!("Is active? {}", is_active); 68 | 69 | // Array türü sadece aynı türden verileri taşır 70 | let points = [9.0, 8.5, 7.2, 8.4, 9.1]; 71 | println!("Points is {:#?}", points); 72 | println!("First value is {}", points[0]); 73 | println!("Second value is {}", points[1]); 74 | // Aşağıdaki satırda ısrar etsek bile derleme zamanında hata alırız. 75 | // println!("None value is {}", points[999]); //Index out of bounds: array length is 5 but the index is 999 76 | 77 | let mut numbers = [1, 2, 3, 4, 5]; 78 | numbers[2] = 8; 79 | println!("Mutated second value is {}", numbers[2]); 80 | } 81 | 82 | const MAX_HEIGHT: u16 = 1280; 83 | const BACKGROUND_COLOR: (u8, u8, u8) = (255, 255, 0); 84 | -------------------------------------------------------------------------------- /S20_channels/src/basic.rs: -------------------------------------------------------------------------------- 1 | use std::sync::mpsc::channel; 2 | use std::thread; 3 | use std::time::Duration; 4 | 5 | pub fn hello_channels() { 6 | let (transmitter, reciever) = channel(); 7 | let message = String::from("Sample content"); 8 | // let number = 3.14; 9 | thread::spawn(move || { 10 | // message değişkeninin sahipliği send metoduna geçer ve sonrasında ilgili veri drop olur 11 | transmitter.send(message).unwrap(); 12 | // transmitter.send(number).unwrap(); 13 | }); 14 | 15 | let data = reciever.recv().unwrap(); 16 | /* 17 | Örneğimizde String türünü kullandığımızdan message değerini 18 | aşağıdaki gibi kullanmak istersek ownership ihlali oluşmasına sebep oluruz. 19 | Bu compile-time ile tespit edilir. 20 | error[E0382]: borrow of moved value: `message` 21 | 22 | 10 | transmitter.send(message).unwrap(); 23 | | ------- variable moved due to use in closure 24 | 25 | Ancak örneğin Copy trait implementasyonu yapmış bir değer kullansak bu hataya takılmayız. 26 | Shallow ve Deep Copy davranışlarını hatırlayalım. 27 | */ 28 | // println!("{}", message); 29 | // println!("{}", number); 30 | println!("{}", data); 31 | } 32 | 33 | /* 34 | Aşağıdaki örnekte birden fazla producer kullanımı denenmektedir. 35 | Bu kodun ilginç yanı ikinci for döngüsünde transmitter'lardan gelen tüm mesajlar yakalansa 36 | dahi döngünün devam ediyor olmasıdır. Zira transmitter_clone'ları halen daha yaşamaktadır 37 | ve tamamı drop edilene kadar for döngüsü devam eder. 38 | 39 | Buradaki basit çözüm yöntemlerinden birisi ana göndericiyi, yani diğer klonların referans 40 | aldığı göndericiyi drop etmektir. 41 | */ 42 | pub fn multi_producer() { 43 | let (transmitter, receiver) = channel(); 44 | 45 | for i in 0..10 { 46 | let transmitter_clone = transmitter.clone(); 47 | thread::spawn(move || { 48 | transmitter_clone 49 | .send(format!("Sending message is {}", i)) 50 | .unwrap(); 51 | thread::sleep(Duration::from_secs(2)); 52 | }); 53 | } 54 | 55 | // İlk denemede aşağıdaki gibi transmitter'ı drop etmeden deneyelim. 56 | // drop(transmitter); 57 | 58 | for received in receiver { 59 | println!("Incoming message is '{}'", received); 60 | } 61 | 62 | println!("End of program"); 63 | } 64 | 65 | /* 66 | Aşağıdaki örnek ile yukardaki arasındaki en önemli fark transmitter nesnelerinin 67 | yaşam ömürler. for döngüsü olan örnekte transmitter nesnesinin clone referansları oluşuyor. 68 | main fonksiyonunda son satıra gelindiğinde bunlardan hiçbiri drop olmamışsa 69 | receiver dinlemede kalıyor. 70 | 71 | Ancak aşağıdaki örnekte ilk thread ana transmitter nesnesi baz alarak çalışıyor ve ikinci 72 | thread'de onun clone referansını kullanıyor. Dolayısıyla ilk transmitter nesnesi 73 | ilk closure sonunda drop edileceğinden kalan klonuda işlemini bitirdiyse receiver sonlanabiliyor. 74 | */ 75 | 76 | pub fn multi_producer_2() { 77 | let (transmitter, receiver) = channel(); 78 | let transmitter_clone = transmitter.clone(); 79 | thread::spawn(move || { 80 | transmitter.send(String::from("Hello there!")).unwrap(); 81 | thread::sleep(Duration::from_secs(2)); 82 | }); 83 | 84 | thread::spawn(move || { 85 | transmitter_clone 86 | .send(String::from("Why are you so serious!")) 87 | .unwrap(); 88 | }); 89 | 90 | for received in receiver { 91 | println!("Incoming message: {}", received); 92 | } 93 | 94 | println!("End of program"); 95 | } 96 | -------------------------------------------------------------------------------- /S17_closures/src/scenario.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | 3 | #[derive(Debug)] 4 | struct Player { 5 | id: u32, 6 | position: (f32, f32), 7 | velocity: (f32, f32), 8 | score: u32, 9 | } 10 | 11 | #[derive(Debug)] 12 | struct GameWorld { 13 | players: Vec, 14 | } 15 | 16 | /* 17 | update fonksiyonunda kullanılan f değişkeni generic bir tür olarak belirtilmiştir ve 18 | Fn trait'ini uygulaması beklenmektedir. Kısaca f yerine Fn trait'ine uygun bir closure 19 | ifadesi gelebilir. Örneğin apply_gravity fonksiyonu gibi ya da anonim şekilde belirtilerek. 20 | */ 21 | 22 | fn update_players_system(world: &mut GameWorld, mut f: F) 23 | where 24 | F: Fn(&mut Player), 25 | { 26 | for p in &mut world.players { 27 | f(p); 28 | } 29 | } 30 | 31 | fn update_score_system(world: &GameWorld, mut f: F) 32 | where 33 | F: FnMut(&Player), 34 | /* 35 | Burada FnMut yerine Fn kullanıp oluşan hata mesajını inceleyebiliriz. 36 | 37 | error[E0594]: cannot assign to `total_team_score`, as it is a captured variable in a `Fn` closure 38 | change this to accept `FnMut` instead of `Fn` 39 | */ 40 | { 41 | for p in &world.players { 42 | f(p); 43 | } 44 | } 45 | 46 | pub fn run() { 47 | let mut world = GameWorld { 48 | players: vec![ 49 | Player { 50 | id: 1, 51 | position: (0.0, 0.0), 52 | velocity: (2.0, 0.0), 53 | score: 0, 54 | }, 55 | Player { 56 | id: 2, 57 | position: (100.0, 0.0), 58 | velocity: (8.0, 0.0), 59 | score: 0, 60 | }, 61 | ], 62 | }; 63 | 64 | let apply_gravity = |entity: &mut Player| { 65 | entity.position.0 += entity.velocity.0 * 0.9; 66 | entity.position.1 += entity.velocity.1 * 0.9; 67 | }; 68 | 69 | println!("Before Update: {:?}", world.players); 70 | update_players_system(&mut world, apply_gravity); 71 | // update_players_system(&mut world, |entity| { 72 | // entity.position.0 += entity.velocity.0 * 0.9; 73 | // entity.position.1 += entity.velocity.1 * 0.9; 74 | // }); 75 | println!("After Update: {:?}", world.players); 76 | 77 | // FnMut kullanımı ile ilgili bir örnek 78 | let mut total_team_score = 0; 79 | 80 | println!("Total score before update: {}", total_team_score); 81 | update_players_system(&mut world, |p| p.score += 2); 82 | update_score_system(&world, |p: &Player| { 83 | total_team_score += p.score; 84 | }); 85 | println!("Total score after update: {}", total_team_score); 86 | 87 | // FnOnce Örneği 88 | let message = Some(String::from("You have unlocked a new level!")); 89 | let show_message = || { 90 | if let Some(msg) = message { 91 | println!("{}", msg); 92 | } else { 93 | println!("Message already shown."); 94 | } 95 | }; 96 | 97 | show_message(); 98 | // show_message(); // Burada 'value used here after move' hatası oluşur 99 | /* 100 | Henüz erken olsa da thread açmak FnOnce kullanımı için iyi bir örnek olabilir. 101 | thread::spawn yeni bir thread başlatırken FnOnce türünden bir closure alır. Dışarıdan 102 | değerler closure içerisine taşınır ve thread sonlanana kadar closure sahip olduğu tüm 103 | değerleri tüketir. Bu tek sefer çalıştırılması gereken bir closure olarak düşünülebilir. 104 | */ 105 | let message = String::from("Inside a thread!"); 106 | let handle = thread::spawn(move || { 107 | println!("{}", message); 108 | }); 109 | // println!("{}", message); // value borrowed here after move 110 | handle.join().unwrap(); 111 | } 112 | -------------------------------------------------------------------------------- /S24_file_io/src/data_generator.rs: -------------------------------------------------------------------------------- 1 | use chrono::Utc; 2 | use crossterm::event::{read, Event, KeyCode}; 3 | use rand::prelude::IndexedRandom; 4 | use std::fs::File; 5 | use std::io; 6 | use std::io::{BufRead, BufReader, Write}; 7 | /* 8 | Aşağıdaki fonksiyonun amacı basitçe büyük miktarda veri içeren bir log dosyası üretmektir. 9 | Senaryo gereği messages isimli vektörden rastgele içerikler çekip parametre olarak 10 | verilen dosya içerisine yazar. 11 | */ 12 | fn generate_random_file(file_path: &str, line_numbers: usize) -> io::Result<()> { 13 | let messages = [ 14 | "[INFO] Incoming service request for \\games HTTP Get", 15 | "[ERROR] Security breach detected!", 16 | "[INFO] User logged in.", 17 | "[WARNING] Disk space running low.", 18 | "[ERROR] Connection to database failed.", 19 | "[WARNING] Unexpected message 'Why so serious'.", 20 | "[ERROR] Configuration file not found.", 21 | "[INFO] Resilience strategy has been installed", 22 | "[INFO] User profile updated.", 23 | "[ERROR] Failed to load module.", 24 | ]; 25 | 26 | let mut rng = rand::rng(); 27 | let mut file = File::create(file_path)?; 28 | 29 | for _ in 0..line_numbers { 30 | let message = messages.choose(&mut rng).unwrap(); 31 | writeln!(file, "{}: {}", Utc::now(), message)?; 32 | } 33 | 34 | Ok(()) 35 | } 36 | 37 | /* 38 | Fiziki I/O işlemleri disk veya usb gibi ortamları kullandıklarından büyük boyutlu dosyalarla 39 | çalışmak problem olabilir. Bu durumda veriyi memory'de buffer'layarak okumak daha iyi bir 40 | performans sergiler. Aşağıdaki örnekte dosya içeriği satır bazlı okunurken BufReader türünden 41 | yararlanılır. 42 | */ 43 | fn read_lines(file_path: &str) -> io::Result<()> { 44 | let file = File::open(file_path)?; 45 | // let reader = BufReader::new(file); 46 | // Buffer açarken istersek kapasiteyi de belirtebiliriz. Örnekte 8 Kb'lık bloklar kullanılıyor 47 | let reader = BufReader::with_capacity(8 * 1024, file); 48 | 49 | for (idx, line) in reader.lines().enumerate() { 50 | println!("{}- {}", idx + 1, line?); 51 | } 52 | 53 | Ok(()) 54 | } 55 | 56 | /* 57 | Aşağıdaki fonksiyon dosya içeriğini sayfa sayfa okumak için kullanılır. 58 | Dosya içeriği yine bir buffer üzerinden ele alınır ancak page_size değerine göre 59 | bölümlenerek işlenir. Terminalden basılan tuşu algılamak içinse crossterm crate'inden 60 | yararlanılmaktadır. 61 | */ 62 | fn read_lines_with_pause(file_path: &str, page_size: usize) -> io::Result<()> { 63 | let file = File::open(file_path)?; 64 | let reader = BufReader::with_capacity(8 * 1024, file); 65 | 66 | let mut line_count = 0; 67 | 68 | for (idx, line) in reader.lines().enumerate() { 69 | println!("{}- {}", idx + 1, line?); 70 | line_count += 1; 71 | 72 | if line_count % page_size == 0 { 73 | println!("Press SPACE for continue, or press E for exit..."); 74 | 75 | loop { 76 | if let Event::Key(event) = read()? { 77 | match event.code { 78 | KeyCode::Char(' ') => break, 79 | KeyCode::Char('e') | KeyCode::Char('E') => return Ok(()), 80 | _ => { 81 | println!( 82 | "Invalid input. Press SPACE for continue, or press E for exit... " 83 | ); 84 | } 85 | } 86 | } 87 | } 88 | } 89 | } 90 | 91 | Ok(()) 92 | } 93 | 94 | pub fn run() -> io::Result<()> { 95 | let file_path = "sys.logs"; 96 | let line_numbers = 1000; 97 | 98 | generate_random_file(file_path, line_numbers)?; 99 | println!("'{file_path}' with {line_numbers} lines has been generated."); 100 | 101 | // read_lines(file_path)?; 102 | read_lines_with_pause(file_path, 50)?; 103 | Ok(()) 104 | } 105 | -------------------------------------------------------------------------------- /S20_channels/src/scenarios.rs: -------------------------------------------------------------------------------- 1 | use rand::Rng; 2 | use std::sync::mpsc::channel; 3 | use std::thread; 4 | use std::time::Duration; 5 | use tokio::sync::mpsc; 6 | 7 | /* 8 | Bu senaryoda sistemdeki n sayıda dosyanın n thread ile işlenmesi söz konusudur. 9 | Her thread dosyayı işlediğinde ve işlemi bitirdiğinde kanala bilgi bırakır. 10 | En sonunda tüm bu bilgiler receiver üzerinden toplanır. 11 | */ 12 | pub fn process_reports() { 13 | let (transmitter, receiver) = channel(); 14 | 15 | let reports = [ 16 | "salary.json", 17 | "invoices.json", 18 | "summary.json", 19 | "personnel.json", 20 | ]; 21 | 22 | for report in reports { 23 | let transmitter = transmitter.clone(); 24 | thread::spawn(move || { 25 | let mut rng = rand::thread_rng(); 26 | let sleep_time = rng.gen_range(2..=5); 27 | transmitter 28 | .send(format!("Processing '{}' report...", report)) 29 | .unwrap(); 30 | 31 | // Rapor dosyalarının işlendiği bazı business'lar çağırdığımızı düşünelim 32 | 33 | thread::sleep(Duration::from_secs(sleep_time)); 34 | 35 | transmitter 36 | .send(format!( 37 | "Finished processing '{}' in {} seconds", 38 | report, sleep_time 39 | )) 40 | .unwrap(); 41 | }); 42 | } 43 | 44 | drop(transmitter); 45 | println!("Started the processing reports"); 46 | for result in receiver { 47 | println!("Status {}", result); 48 | } 49 | println!("Completed the processing reports"); 50 | } 51 | 52 | /* 53 | Aşağıdaki örneklerde rust'ın standart mpsc modeli ile tokio karşılaştırılmakta. 54 | Standart kütüphanedeki mpsc'in esasında gerçek anlamda bir asenkronluk sunmadığı belirtilmekte. 55 | Mesaj gönderimleri senkron olsa bile receiver tarafında bloklanma söz konusu olabilir ve 56 | burası aslında senkron çalışır. Bu nedenle mpsc çoklu dinleme yapılan senaryolar için pek 57 | uygun değil. 58 | */ 59 | 60 | pub fn do_with_standard() { 61 | let (transmitter, receiver) = channel(); 62 | 63 | for i in 1..=5 { 64 | let tx_clone = transmitter.clone(); 65 | thread::spawn(move || { 66 | thread::sleep(Duration::from_secs(5)); 67 | tx_clone.send(format!("Task {} completed", i)).unwrap(); 68 | }); 69 | } 70 | 71 | drop(transmitter); 72 | 73 | println!("Waiting for all tasks..."); 74 | 75 | // Aşağıdaki döngü main thread üzerine çalışıp buradaki akışı bloklamaya neden olacak 76 | for i in 0..10 { 77 | thread::sleep(Duration::from_secs(1)); 78 | println!("Main task is working...Counting {}", i); 79 | } 80 | 81 | while let Ok(message) = receiver.recv() { 82 | println!("{}", message); 83 | } 84 | 85 | println!("All tasks completed!"); 86 | } 87 | 88 | pub async fn do_with_tokio() { 89 | let (transmitter, mut receiver) = mpsc::channel(10); 90 | 91 | for i in 1..=5 { 92 | let tx_clone = transmitter.clone(); 93 | tokio::spawn(async move { 94 | tokio::time::sleep(Duration::from_secs(5)).await; 95 | tx_clone 96 | .send(format!("Task {} completed", i)) 97 | .await 98 | .unwrap(); 99 | }); 100 | } 101 | 102 | drop(transmitter); 103 | 104 | println!("Waiting for all tasks..."); 105 | 106 | /* 107 | Standart mpsc örneğinden farklı olarak burada ana thread bloklanmadan 108 | döngünün asenkron olarak çalıştırılması sağlanır. 109 | */ 110 | tokio::spawn(async { 111 | for i in 0..10 { 112 | tokio::time::sleep(Duration::from_secs(1)).await; 113 | println!("Main task is working...Counting {}", i); 114 | } 115 | }); 116 | 117 | while let Some(message) = receiver.recv().await { 118 | println!("{}", message); 119 | } 120 | 121 | println!("All tasks completed!"); 122 | } 123 | -------------------------------------------------------------------------------- /S15_error_handling/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Rust dilinde hatalar recoverable ve unrecoverable olmak üzere 3 | iki ana kategoriye ayrılır. 4 | 5 | Recoverable Error için Result türü ele alınırken, 6 | Unrecoverable Error durumlarında panic! makrosu ön plana çıkar. 7 | 8 | */ 9 | use rand::Rng; 10 | use std::fmt; 11 | use std::fmt::{Display, Formatter}; 12 | use std::fs::File; 13 | use std::io::ErrorKind; 14 | 15 | fn main() { 16 | /* 17 | Unrecoverable Errors 18 | 19 | panic! makrosu çalışmakta olan thread'i bir hata mesajı ile sonlandırır 20 | 21 | Örneğin out of bounds durumunu ele alalım. 22 | Runtime'da aşağıdaki kod parçası için 'index out of bounds' hatası üretilir. 23 | Burada istersek Backtrace içeriğine de bakabiliriz. Bunun için terminalden, 24 | $env:RUST_BACKTRACE = 1 25 | şeklinde komut çalıştırmak yeterlidir. 26 | 27 | unwinding vs abort ???s 28 | */ 29 | let numbers = vec![1, 4, 7, 0, 9]; 30 | // let some_number= numbers[99]; 31 | /* 32 | Recoverable Errors, 33 | 34 | Burada hatalar Result türü ile kolaylıkla ele alınabilir. 35 | */ 36 | // let f = File::open("there_is_no_spoon.dat"); 37 | // let file = match f { 38 | // Ok(file) => file, 39 | // Err(e) => panic!("{:?}", e), 40 | // }; 41 | 42 | // let file = f.unwrap_or_else(|e| match e.kind() { 43 | // std::io::ErrorKind::NotFound => match File::create("there_is_no_spoon.dat") { 44 | // Ok(file_created) => file_created, 45 | // Err(e) => panic!("{:?}", e), 46 | // }, 47 | // _ => panic!("{:?}", e), 48 | // }); 49 | 50 | /* 51 | unwrap metodu eğer işlem sonucunda problem varsa bir panik oluşturur 52 | expect ile bu hata hakkında ekstra bilgi verebiliriz. 53 | */ 54 | // let file = File::open("there_is_no_spoon.dat").unwrap(); 55 | // let file = 56 | // File::open("there_is_no_spoon.dat").expect("Are you sure? There is no file I think."); 57 | 58 | // Error propagation 59 | 60 | match approve_application("10001") { 61 | Ok(_) => println!("Application approved."), 62 | Err(e) => println!("Error occurred: {}", e), 63 | } 64 | } 65 | 66 | /* 67 | Error Propagation 68 | 69 | Oluşan bir hatanın üst katmanlara(fonksiyonlara) taşınması olarak düşünülebilir. 70 | 71 | Kendi hata nesnelerimizi kullanabiliriz. Örneğin kredi başruvu sürecinde kredi 72 | skoru hesaplaması yapılırken oluşabilecek bazı durumların birer Error olarak 73 | ele alınmasını sağlayabiliriz. 74 | */ 75 | 76 | #[derive(Debug)] 77 | enum CreditScoreError { 78 | NotFound(String), 79 | ServiceUnavailable, 80 | LowScore(i32), 81 | } 82 | 83 | impl Display for CreditScoreError { 84 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { 85 | match *self { 86 | CreditScoreError::NotFound(ref account_id) => { 87 | write!(f, "Credit score not found. Account Id {}", account_id) 88 | } 89 | CreditScoreError::ServiceUnavailable => { 90 | write!(f, "Credit service is currently unavailable") 91 | } 92 | CreditScoreError::LowScore(score) => write!(f, "Low credit score. Score is {}", score), 93 | } 94 | } 95 | } 96 | 97 | fn fetch_credit_score(account_owner: &str) -> Result { 98 | let mut generator = rand::thread_rng(); 99 | let simulation_number = generator.gen_range(0..=3); 100 | let score = generator.gen_range(300..=700); 101 | match simulation_number { 102 | 0 => Ok(score), 103 | 1 => Err(CreditScoreError::NotFound(String::from(account_owner))), 104 | _ => Err(CreditScoreError::ServiceUnavailable), 105 | } 106 | } 107 | 108 | fn approve_application(account_owner: &str) -> Result<(), CreditScoreError> { 109 | let score = fetch_credit_score(account_owner)?; 110 | if score < ELIGIBLE_CREDIT_SCORE { 111 | Err(CreditScoreError::LowScore(score)) 112 | } else { 113 | Ok(()) 114 | } 115 | } 116 | 117 | const ELIGIBLE_CREDIT_SCORE: i32 = 600; 118 | -------------------------------------------------------------------------------- /S22_parallelism/src/main.rs: -------------------------------------------------------------------------------- 1 | use rayon::current_num_threads; 2 | use rayon::prelude::*; 3 | use std::sync::{Arc, Mutex}; 4 | use std::thread; 5 | use std::time::Instant; 6 | 7 | fn main() { 8 | print_thread_count(); 9 | // find_total_scenario(); 10 | find_primes_scenario(); 11 | } 12 | 13 | fn print_thread_count() { 14 | let num_threads = current_num_threads(); 15 | println!("Rayon bu sistemde {} iş parçacığı kullanacak.", num_threads); 16 | } 17 | 18 | fn find_total_scenario() { 19 | let numbers: Vec = (1..=1_000_000).collect(); 20 | 21 | let start = Instant::now(); 22 | let serial_sum: u64 = numbers.iter().sum(); 23 | let serial_duration = start.elapsed(); 24 | println!("Seri toplama süresi: {:?}", serial_duration); 25 | 26 | let start = Instant::now(); 27 | let parallel_sum: u64 = numbers.par_iter().sum(); 28 | let parallel_duration = start.elapsed(); 29 | println!("Paralel toplama süresi: {:?}", parallel_duration); 30 | 31 | assert_eq!(serial_sum, parallel_sum); 32 | } 33 | 34 | // Sayının asal olup olmadığını kontrol eden fonksiyon 35 | fn is_prime(n: u64) -> bool { 36 | if n < 2 { 37 | return false; 38 | } 39 | for i in 2..=((n as f64).sqrt() as u64) { 40 | if n % i == 0 { 41 | return false; 42 | } 43 | } 44 | true 45 | } 46 | 47 | fn parallel_find_primes(numbers: Vec, num_threads: usize) -> Vec { 48 | let chunk_size = numbers.len() / num_threads; 49 | let numbers = Arc::new(numbers); 50 | let results = Arc::new(Mutex::new(Vec::new())); 51 | 52 | let mut handles = vec![]; 53 | 54 | for i in 0..num_threads { 55 | let numbers = Arc::clone(&numbers); 56 | let results = Arc::clone(&results); 57 | 58 | let handle = thread::spawn(move || { 59 | let start = i * chunk_size; 60 | let end = if i == num_threads - 1 { 61 | numbers.len() 62 | } else { 63 | start + chunk_size 64 | }; 65 | 66 | let local_primes: Vec = numbers[start..end] 67 | .iter() 68 | .cloned() 69 | .filter(|&n| is_prime(n)) 70 | .collect(); 71 | 72 | let mut results = results.lock().unwrap(); 73 | results.extend(local_primes); 74 | }); 75 | 76 | handles.push(handle); 77 | } 78 | 79 | for handle in handles { 80 | handle.join().unwrap(); 81 | } 82 | 83 | let results = Arc::try_unwrap(results).unwrap().into_inner().unwrap(); 84 | results 85 | } 86 | 87 | /* 88 | Kendi sistemimde seri hesaplama yani tek thread ile asal sayı bulma operasyonu 89 | 4 dakika 41 saniye kadar sürdü. 90 | 91 | Thread'leri kendimiz manuel açarsak bu süre 92 | 93 | 94 | Rayon kullananılan durumda 12 çekirdekli sistem bunu yaklaşık olarak 95 | 1 dakika 36 saniyede gerçekleştirdi. 96 | */ 97 | fn find_primes_scenario() { 98 | let numbers: Vec = (1..=100_000_000).collect(); 99 | 100 | let start = Instant::now(); 101 | let s_primes: Vec = numbers.iter().filter(|&&n| is_prime(n)).cloned().collect(); 102 | let serial_duration = start.elapsed(); 103 | println!("Seri asal sayılar hesaplama süresi: {:?}", serial_duration); 104 | 105 | let start = Instant::now(); 106 | let t_primes = parallel_find_primes(numbers.clone(), 12); 107 | let parallel_duration = start.elapsed(); 108 | println!( 109 | "Thread'ler ile paralel asal sayılar hesaplama süresi: {:?}", 110 | parallel_duration 111 | ); 112 | assert_eq!(s_primes.len(), t_primes.len()); 113 | 114 | let start = Instant::now(); 115 | let p_primes: Vec = numbers 116 | .par_iter() 117 | .filter(|&&n| is_prime(n)) 118 | .cloned() 119 | .collect(); 120 | let parallel_duration = start.elapsed(); 121 | println!( 122 | "Paralel asal sayılar hesaplama süresi: {:?}", 123 | parallel_duration 124 | ); 125 | 126 | assert_eq!(s_primes, p_primes); 127 | println!("Sonuçlar eşleşiyor! Seri ve paralel hesaplamalar aynı."); 128 | } 129 | -------------------------------------------------------------------------------- /S26_unsafe_coding/src/advanced.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Aynı türden nesneleri çok sık oluşturup(create) kaldırdığımız(drop) bir durum olduğunu ve bunu 3 | kısıtlı bellek kapasitesine sahip bir gömülü sistem üzerinde işletmemiz gerektiğini düşünelim. 4 | Böyle bir durumda kendi bellek havuzumu oluşturup yönetebiliriz ama bunun için unsafe alana 5 | çıkmamız gerekir. Aşağıdaki kodlarda bu kullanima ait bir örnek yer alıyor. 6 | 7 | Olası hataları ise şöyle ifade edebiliriz. 8 | 9 | User After Free: Serbest kalan bellek bloğuna erişmeye çalışmak 10 | Double Free : Aynı bellek bloğunu birden fazla kez serbest bırakılmaya çalışılması 11 | */ 12 | use std::alloc::{alloc, dealloc, Layout}; 13 | use std::ptr; 14 | 15 | // const X64_ALIGN: usize = 8; 16 | 17 | /* 18 | Sistemin 32 veya 64 bit olmasına göre gerekli olan byte hizalama değerini aldığımı fonksiyon 19 | */ 20 | fn get_alignment() -> usize { 21 | if cfg!(target_pointer_width = "32") { 22 | 4 // 32-bit alignment 23 | } else { 24 | 8 // 64-bit alignment 25 | } 26 | } 27 | 28 | struct RapidMemoryPool { 29 | total_size: usize, 30 | usage: usize, 31 | ref_pointer: *mut u8, //raw memory pointer 32 | } 33 | 34 | impl RapidMemoryPool { 35 | fn new(total_size: usize) -> Self { 36 | println!("Rapid Memory Pool initiating"); 37 | 38 | unsafe { 39 | let layout = Layout::from_size_align(total_size, get_alignment()).unwrap(); 40 | println!("{layout:?}"); 41 | let ref_pointer = alloc(layout); 42 | if ref_pointer.is_null() { 43 | panic!("Could not allocate memory"); 44 | } 45 | Self { 46 | total_size, 47 | usage: 0, 48 | ref_pointer, 49 | } 50 | } 51 | } 52 | 53 | /* 54 | Bu fonksiyon bir bellek bölgesini ayırır ve başlangıç adresini 55 | raw pointer olarak döner. Buradaki raw pointer mutable'dır. 56 | */ 57 | fn allocate(&mut self, amount: usize) -> *mut u8 { 58 | unsafe { 59 | if self.usage + amount > self.total_size { 60 | panic!("Out of memory"); 61 | } 62 | let alloc_ptr = self.ref_pointer.add(self.usage); 63 | self.usage += amount; 64 | alloc_ptr 65 | } 66 | } 67 | 68 | fn free(&mut self) { 69 | unsafe { 70 | let layout = Layout::from_size_align(self.total_size, get_alignment()).unwrap(); 71 | dealloc(self.ref_pointer, layout); 72 | self.ref_pointer = ptr::null_mut(); 73 | self.total_size = 0; 74 | self.usage = 0; 75 | } 76 | } 77 | } 78 | 79 | impl Drop for RapidMemoryPool { 80 | fn drop(&mut self) { 81 | if !self.ref_pointer.is_null() { 82 | self.free(); 83 | println!("Dropping memory pool"); 84 | } 85 | } 86 | } 87 | 88 | pub fn run() { 89 | let mut pool = RapidMemoryPool::new(1024); 90 | 91 | /* 92 | Bu tip kullanımlarda bellek taşma hatalarına dikkat etmek gerekir tabii. 93 | Ayrılan alandan daha büyük bir veri yazmaya çalışmak ya da belleği serbest bıraktıktan 94 | sonra erişmeye çalışmak bazı hatalara sebebiyet verir.Use After Free gibi. 95 | */ 96 | unsafe { 97 | let block_red = pool.allocate(256); // 256 byte yer ayırır 98 | println!("Block Red allocated at: {:?}", block_red); 99 | *block_red = 100; 100 | *block_red.add(1) = 200; // İkinci byte 101 | 102 | let position = block_red as *mut Vector; 103 | (*position).x = 10; 104 | (*position).y = 16; 105 | 106 | println!("Position {}:{}", (*position).x, (*position).y); 107 | 108 | let block_blue = pool.allocate(512); // 512 byte yer ayırır 109 | println!("Block Blue allocated at: {:?}", block_blue); 110 | 111 | // block_blue'dan 256 byte'lık bir slice al 112 | let slice = std::slice::from_raw_parts_mut(block_blue, 256); 113 | slice[0] = 100; // İlk byte 114 | slice[1] = 200; // İkinci byte 115 | slice[5] = 35; 116 | println!("Slice values: {:?}", &slice[0..10]); 117 | } 118 | } // Drop trait implementasyonu nedeniyle buradan bellek otomatik serbest kalır 119 | 120 | #[repr(C)] 121 | struct Vector { 122 | x: u16, 123 | y: u16, 124 | } 125 | -------------------------------------------------------------------------------- /S19_threads/src/basic.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | use std::time::Duration; 3 | 4 | pub fn start_a_simple_thread() { 5 | let handle = thread::spawn(move || { 6 | println!("Starting thread..."); 7 | thread::sleep(Duration::new(3, 0)); 8 | println!("Thread stopped..."); 9 | }); 10 | // handle.join().unwrap(); 11 | /* 12 | İlk önce bu olmadan deneyelim. 13 | Eğer kullanmazsa main thread buradaki işlemin tamamlanmasını beklemeden yoluna devam eder. 14 | */ 15 | } 16 | 17 | // pub fn move_keyword_error() { 18 | // let student_points = vec![30.50, 49.90, 65.55, 90.00, 81.00]; 19 | // /* 20 | // Aşağıdaki durum biraz daha dikkatli ele alınmalı. 21 | // main thread içinde tanımlı student_points vektörünü yeni başlatılan bir thread içinde 22 | // ele almak istiyoruz. println! ile doğrudan yazdırmak istediğimizde eğer move keyword 23 | // kullanılmamışsa şu hatayı alırız; 24 | // 25 | // error[E0373]: closure may outlive the current function 26 | // , but it borrows `student_points`, which is owned by the current function 27 | // 28 | // Ancak student_points içeriğini örneğin bir döngüde kullanır ve elemanları tek tek 29 | // f32 olarak ele alırsak move anahtarını kullanmasak bile problem olmaz. 30 | // 31 | // Bunu açıklamaya çalışalım; 32 | // 33 | // vektör türü ile ifade edilen veriler bilindiği üzere heap üzerinde durmakta. 34 | // main thread içinde başlatılan ikinci thread'de bu vektörün sahipliği(ownership) alınmak isteniyor. 35 | // Ancak ikinci thread ki closure ile bir kod bloğu açıyor, 36 | // main thread'den daha uzun süre çalışabilir ve bu memory safe bir davranış değildir. 37 | // Bu yüzden rust move kullanılmasını ve bu sayede vektör sahipliğinin closure'a taşınmasını istiyor. 38 | // 39 | // Esasında Rust thread safe bir ortam sağlamaya çalışıyor. 40 | // Birden fazla thread üzerinde aynı bellek adresine işaret eden bir yapı varsa, 41 | // Rust buna izin vermez zira bu data race durumunun oluşmasına yol açabilir. 42 | // 43 | // move kullanıldığında closure, student_points vektörünün tamamının sahipliğini alır. 44 | // Vektörün sahipliği artık ana thread'e değil, closure bloğuna aittir. 45 | // Rust thread’ler arası sahiplik sorununu bu şekilde çözer. 46 | // 47 | // O zaman tek tek içeriği dolaştığımızda move kullanılmaması neden bir probleme sebebiyet 48 | // vermiyor? Bu durumda closure, vektörün kendisini değil elemanlarını kullanmış oluyor. 49 | // Zira bu örnekte vektör elemanları f32 türündendir dolayısıyla kopyalanarak taşınabilirler. 50 | // closure bu kopyalar üzerinde çalışır. Dolayısıyla orjinal vektörün sahiplenilmesi veya 51 | // borç olara alınması söz konusu değildir. 52 | // */ 53 | // let handle = thread::spawn(|| { 54 | // println!("Thread is starting..."); 55 | // println!("{:?}", student_points); // Bu kullanımla aşağıdaki farklı 56 | // // for point in student_points { 57 | // // println!("Processing for point {}", point); 58 | // // } 59 | // println!("Thread completed"); 60 | // }); 61 | // handle.join().unwrap(); 62 | // } 63 | 64 | pub fn move_keyword_success() { 65 | let student_points = vec![30.50, 49.90, 65.55, 90.00, 81.00]; 66 | let handle = thread::spawn(move || { 67 | println!("Thread is starting..."); 68 | println!("{:?}", student_points); 69 | println!("Thread completed"); 70 | }); 71 | handle.join().unwrap(); 72 | } 73 | 74 | fn calc_factorial(n: u64) -> u64 { 75 | (1..=n).product() 76 | } 77 | pub fn multiple_threads_sample() { 78 | let numbers = vec![10, 3, 5, 13, 8, 9, 1, 2, 17, 11, 7, 6]; 79 | let threads_count = 4; 80 | let mut handles = vec![]; 81 | let chunk_size = numbers.len() / threads_count; 82 | 83 | for i in 0..threads_count { 84 | let chunk = numbers[i * chunk_size..(i + 1) * chunk_size].to_vec(); 85 | handles.push(thread::spawn(move || { 86 | let mut results = vec![]; 87 | for num in chunk { 88 | println!("Thread {} processing for {}", i, num); 89 | results.push((num, calc_factorial(num))); 90 | } 91 | results 92 | })); 93 | } 94 | 95 | let mut final_results = vec![]; 96 | 97 | for handle in handles { 98 | final_results.push(handle.join().unwrap()); 99 | } 100 | 101 | println!("{:?}", final_results); 102 | } 103 | -------------------------------------------------------------------------------- /S25_streams/src/basics.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, BufRead, Write}; 2 | 3 | /* 4 | stdin, stdout ve hatta stderr UNIX tabanlı sistemlerden beri gelen birer standardı ifade eder. 5 | stdin temelde kullanıcıdan veya başka bir programdan veri almak, 6 | stdout programın normal çıktısını kullanıcıya veya başka bir programa iletmek, 7 | stderr ise hata mesajlarını ayırmak maksadıyla geliştirilmiş standartlardır. 8 | 9 | Bu noktada |(pipe) ve >(redirect) sıklıkla karşılaşılan terminal operatörleridir. 10 | |, stdout çıktısını başka bir programın stdin girişine yönlendirmek için kullanılır. 11 | 12 | Örneğin, 13 | ls | grep ".rs" 14 | gibi. 15 | 16 | > ise bir komutun stdout çıktısını bir dosyaya yönlendirmek için kullanılır. 17 | Örneğin, 18 | ls > files.txt 19 | gibi. 20 | 21 | Birde >>(Append) vardır. > gibi yönlendirme yapar ama mevcut dosyasının üzerine yazmak yerine 22 | sonuna ekleme yapar. 23 | Örneğin, 24 | echo "Some thoughts about you" >> memories.txt 25 | 26 | stdin ve stdout ile stream'ler üzerinden veri yazmak veya okumak mümkündür. 27 | Örneğin bir dosyaya stdin ile veriyi write_to_file metodundaki gibi yazabiliriz. 28 | Ya da terminalden gelen verileri okumak için stdin().read_line metodu kullanılabilir (sum örneği) 29 | 30 | Kullanıcı terminalden bilgi girdikçe de işlenmesini sağlayabiliriz. Bir stdin açıp 31 | satır satır okumak yeterlidir(read metodu) 32 | 33 | Hatta pipe üzerinden gelen bir stream' de ele alınabilir. (read_from_pipe metodu) 34 | 35 | Rust'ta stdout başka bir programın girdisine stdin üzerinden bağlanarak veri aktarabilir. 36 | Örneğin bir programın çalışma zamanı çıktısını başka bir dosyaya yazarken stdout kullanılabilir. 37 | 38 | */ 39 | fn write_to_file() -> io::Result<()> { 40 | let mut input = String::new(); 41 | println!("Please enter some text:"); 42 | 43 | io::stdin().read_line(&mut input)?; 44 | println!("Your text is: {}", input.trim()); 45 | 46 | Ok(()) 47 | } 48 | 49 | fn sum() -> io::Result { 50 | let mut input1 = String::new(); 51 | let mut input2 = String::new(); 52 | 53 | println!("Please enter the first number:"); 54 | io::stdin().read_line(&mut input1)?; 55 | 56 | println!("Second number:"); 57 | io::stdin().read_line(&mut input2)?; 58 | 59 | let x: i32 = input1.trim().parse().expect("Please enter a number!"); 60 | let y: i32 = input2.trim().parse().expect("Please enter a number!"); 61 | 62 | Ok(x + y) 63 | } 64 | 65 | fn read() -> io::Result<()> { 66 | let stdin = io::stdin(); 67 | let reader = stdin.lock(); 68 | 69 | println!("Please enter some text (Ctrl+Z for exit):"); 70 | for line in reader.lines() { 71 | let line = line?; 72 | println!("Input: {}", line); 73 | } 74 | 75 | Ok(()) 76 | } 77 | 78 | /* 79 | 80 | Aşağıdaki metod için terminalden şu komut verilebilir. 81 | 82 | cat logs.dat | cargo run 83 | */ 84 | 85 | fn read_from_pipe() -> io::Result<()> { 86 | let stdin = io::stdin(); 87 | let reader = stdin.lock(); 88 | 89 | println!("Data is retrieving..."); 90 | for line in reader.lines() { 91 | let line = line?; 92 | println!("Data: {}", line); 93 | } 94 | 95 | Ok(()) 96 | } 97 | 98 | /* 99 | Aşağıdaki metodu işletmek için programı şu şekilde işletebiliriz. 100 | 101 | cargo run > logs.txt 102 | 103 | Burada kullanılan > operatörü, programdaki stdout'u logs.txt dosyasına doğru yönlendirir. 104 | */ 105 | fn write_log() -> io::Result<()> { 106 | let stdout = io::stdout(); 107 | let mut handle = stdout.lock(); 108 | 109 | writeln!(handle, "This will be written to a file.")?; 110 | 111 | Ok(()) 112 | } 113 | 114 | /* 115 | Aşağıdaki metod verilen teriman komutuna göre şöyle çalışır. 116 | logs.dat dosyası cat uygulaması ile açılır, bu uygulama dosyanın içeriğini okur ve 117 | pipe vasıtasıyla bu programın stdin girdisine aktarılır. Bu programda gelen içeriği alır 118 | ve onu output_logs.txt dosyasının içeriğine doğru yönlendirir. 119 | 120 | cat logs.dat | cargo run > output_logs.txt 121 | 122 | */ 123 | fn double_usage() -> io::Result<()> { 124 | let stdin = io::stdin(); 125 | let stdout = io::stdout(); 126 | 127 | let reader = stdin.lock(); 128 | let mut writer = stdout.lock(); 129 | 130 | for line in reader.lines() { 131 | let line = line?; 132 | writeln!(writer, "Data received {}", line)?; 133 | } 134 | Ok(()) 135 | } 136 | 137 | pub fn run() -> io::Result<()> { 138 | // write_to_file()?; 139 | // 140 | // let total = sum()?; 141 | // println!("Total: {}", total); 142 | // 143 | // read()?; 144 | 145 | // read_from_pipe()?; 146 | 147 | // write_log()?; 148 | 149 | double_usage()?; 150 | 151 | Ok(()) 152 | } 153 | -------------------------------------------------------------------------------- /S08_lifetimes/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Her referansın bir yaşam ömrü vardır(lifetime). 3 | Çoğunlukla implicit olarak var olurlar ve bazı durumlarda açıkça belirtmek gerekir. 4 | lifetimes, daha çok Dangling References durumunun oluşmasını engellemek içindir. 5 | */ 6 | fn main() { 7 | /* 8 | Öncelikle basit bir danling reference durumu oluşturalım. 9 | Bunun için aşağıdaki kod parçasını göz önüne alalım. 10 | 11 | value değişkenine scope içerisinde yaşayabilen point isimli değişkenin referansı veriliyor. 12 | Kasıtlı olarak açtığımız blok kapatıldığında ise point değişkeni bellekten drop ediliyor. 13 | Dolayısıyla value değişkeni artık var olmayan bir değere referans etmeye çalışıyor. 14 | Rust bu durumu algılar ve kodu derlemez. 15 | Çalışma zamanı çıktısı aşağıdaki gibi olacaktır. 16 | 17 | error[E0597]: `point` does not live long enough 18 | --> S08_lifetimes\src/main.rs:13:17 19 | | 20 | 12 | let point = 2.25; 21 | | ----- binding `point` declared here 22 | 13 | value = &point; 23 | | ^^^^^^ borrowed value does not live long enough 24 | 14 | } 25 | | - `point` dropped here while still borrowed 26 | 15 | println!("{}", value); 27 | | ----- borrow later used here 28 | 29 | For more information about this error, try `rustc --explain E0597`. 30 | 31 | 32 | */ 33 | // let value; 34 | // { 35 | // let point = 2.25; 36 | // value = &point; 37 | // } // point değişkeni scope sonlandığı için drop edilir 38 | // println!("{}", value); // value artık olmayan bir değeri referans etmeye çalışıyordur. 39 | 40 | /* 41 | Bazı durumlarda referansların yaşam ömürlerinin açıkça belirtilmesi gerekir. 42 | Bunun için lifetime annotation özelliği kullanılır. 43 | Örneğin referans içeren struct'lar da bu açıkça belirtilmelidir. 44 | 45 | Aşağıdaki örneği ele alalım. 46 | 47 | Account veri yapısında customer_name isimli bir string literal kullanımı söz konusudur. 48 | Bu bir referanstır. 49 | Aşağıdaki kod parçasında da name isimli String bir değişken oluşturulur ve 50 | van_dam_account nesnesi örneklenirken customer_name alanına name referansı eklenir. 51 | Eğer, herhangi bir sebeple name değişkeni van_dam_account değişkeninden daha az yaşarsa, 52 | (yani daha önceden bir şekilde drop olursa), van_dam_account isimli değişkendeki customer_name, 53 | olmayan bir referansı taşımaya çalışacaktır. Bu da Dangling Pointer durumu olarak bilinir. 54 | Bu nedenle Account struct tanımında &str şeklinde bir kullanıma derleyici izin vermez. 55 | Lifetime annotation kullanılmazsa şöyle bir derleme zamanı hatası oluşur. 56 | 57 | error[E0106]: missing lifetime specifier 58 | --> S08_lifetimes\src/main.rs:66:20 59 | | 60 | 66 | customer_name: &str, 61 | | ^ expected named lifetime parameter 62 | | 63 | help: consider introducing a named lifetime parameter 64 | | 65 | 65 ~ struct Account<'a> { 66 | 66 ~ customer_name: &'a str, 67 | | 68 | */ 69 | 70 | let name = String::from("Jan Klot Van Dam"); 71 | /* 72 | Bulunduğumuz scope'da name değişkeninin implicit lifetime değeri, 73 | Account nesne örneğine de aktarılır ve customer_name'in aynı süre yaşaması garanti edilir. 74 | */ 75 | let van_dam_account = Account { 76 | customer_name: &name, 77 | balance: 1000f32, 78 | }; 79 | println!( 80 | "{} has a {} coin", 81 | van_dam_account.customer_name, van_dam_account.balance 82 | ); 83 | 84 | /* 85 | Bütün string literal referansları static lifetime bilgisine sahiptir ancak açıkça yazılmazlar 86 | Tüm program döngüsü boyunca çalışacak lifetime bildirimleri için 'static kullanılabilir ancak önerilmez 87 | Mümkün mertebe nesnelerin ömürlerini gerektiği kadar sürelerde tutmak optimizasyon açısından daha doğrudur. 88 | */ 89 | let settings = get_app_settings(); 90 | println!("Server address is {}", settings.server_address); 91 | println!("Connection string is {}", settings.connection_string); 92 | } 93 | 94 | struct Account<'a> { 95 | customer_name: &'a str, // customer_name için lifetime annotation bildirimi 96 | balance: f32, 97 | } 98 | 99 | /* 100 | Aşağıdaki örnekte yer alan ApplicationSettings isimli struct 101 | lifetime annotation kullanıyor. 102 | Bunu tip bir yapıyı programın çalışma zamanı boyunca tutacağı bazı ayarlar 103 | için kullanabiliriz. Sunucu adresi, veritabanı bilgisi gibi. 104 | 105 | get_app_settings fonksiyonun ApplicationSettings örneğini dönerken dikkat edileceği üzere 106 | <'static> bildirimini ele almıştır. 107 | */ 108 | struct ApplicationSettings<'a> { 109 | server_address: &'a str, 110 | connection_string: &'a str, 111 | } 112 | 113 | fn get_app_settings() -> ApplicationSettings<'static> { 114 | ApplicationSettings { 115 | server_address: "localhost", 116 | connection_string: "data source=Northwind;server:127.0.0.1;", 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /S18_smart_pointers/src/rc_scenario.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Heap üzerindeki alokasyonlar Multiple Ownership gerektiği durumlarda Rc kullanılabilir. 3 | RC referansları sayan bir kabiliyete sahiptir. 4 | Birde Arc vardır yani Atomic Referans Counting. Bunu daha çok paylaşımın thread'ler arasında 5 | güvenli şekilde sağlanmasını istediğimiz durumlarda ele alırız. 6 | */ 7 | use std::cell::{Ref, RefCell}; 8 | use std::rc::Rc; 9 | 10 | pub fn hello_rc() { 11 | /* 12 | p1, p2 ve p3 aynı veriyi işaret eden ve stack' de duran pointer'lardır. 13 | */ 14 | let p1 = Rc::new(String::from("Some values on the heap")); 15 | let p2 = p1.clone(); 16 | let p3 = p2.clone(); 17 | 18 | println!("p1={:?}", p1); 19 | println!("p2={:?}", p2); 20 | println!("p3={:?}", p3); 21 | } 22 | 23 | /* 24 | İlk olarak aşağıdaki senaryoyu göz önüne alalım. 25 | Burada Player veri modeli yine kendi türünden bir vektör kullanarak arkadaş listesini tutuyor. 26 | */ 27 | // #[derive(Debug)] 28 | // struct Player { 29 | // id: u32, 30 | // name: String, 31 | // friends: Vec, 32 | // } 33 | // 34 | // impl Player { 35 | // fn new(id: u32, name: &str) -> Self { 36 | // Player { 37 | // id, 38 | // name: name.to_string(), 39 | // friends: Vec::new(), 40 | // } 41 | // } 42 | // 43 | // fn add_friend(&mut self, friend: Player) { 44 | // self.friends.push(friend); 45 | // } 46 | // 47 | // fn print(&self) { 48 | // println!("{}'s friends:", self.name); 49 | // for friend in &self.friends { 50 | // println!(" {} (ID: {})", friend.name, friend.id); 51 | // } 52 | // } 53 | // } 54 | // 55 | // pub fn run_rc_with_error() { 56 | // let mut steve = Player::new(1, "Stivi Vondır"); 57 | // let lord = Player::new(2, "Lord veyda"); 58 | // let anakin = Player::new(3, "Anakin"); 59 | // 60 | // steve.add_friend(lord); // lord' un sahipliği add_friend sonrası steve' e taşındı 61 | // steve.add_friend(anakin); 62 | // 63 | // steve.print(); 64 | // 65 | // println!("Lord veyda's ID: {}", lord.id); // Dolayısıyla burada value moved here hatası alınır 66 | // } 67 | 68 | /* 69 | İkinci olarak Rc kullandığımız senaryoya bakalım ama bu seferde kendimiz 70 | error[E0596]: cannot borrow data in an `Rc` as mutable 71 | hatasına götüreceğiz. 72 | */ 73 | // #[derive(Debug)] 74 | // struct Player { 75 | // id: u32, 76 | // name: String, 77 | // friends: Vec>, 78 | // } 79 | // 80 | // impl Player { 81 | // fn new(id: u32, name: &str) -> Rc { 82 | // Rc::new(Player { 83 | // id, 84 | // name: name.to_string(), 85 | // friends: Vec::new(), 86 | // }) 87 | // } 88 | // 89 | // fn add_friend(self: &Rc, friend: Rc) { 90 | // self.friends.push(friend); 91 | // } 92 | // 93 | // fn print(&self) { 94 | // println!("{}'s friends:", self.name); 95 | // for friend in self.friends.iter() { 96 | // println!(" {} (ID: {})", friend.name, friend.id); 97 | // } 98 | // } 99 | // } 100 | // 101 | // pub fn run_rc_with_error_2() { 102 | // let steve = Player::new(1, "Stivi Vondır"); 103 | // let lord = Player::new(2, "Lord veyda"); 104 | // let anakin = Player::new(3, "Anakin"); 105 | // 106 | // steve.add_friend(Rc::clone(&lord)); 107 | // steve.add_friend(Rc::clone(&anakin)); 108 | // 109 | // steve.print(); 110 | // 111 | // println!("Lord Veyda's ID: {}", lord.id); 112 | // } 113 | 114 | /* 115 | Yukarıdaki senaryoda bir Player'ın kendisini tutan bir Vector nesnesine ihtiyacı olmuştur. 116 | Bunun için Vec'ün Rc kullanılması yolu tercih edilmiştir. Ancak bu 117 | özellikle add_friends metodunda vektör içeriğine mutable erişmeyi gerektirir. Bu nedenle 118 | vektöre referansının da mutable olarak ele alınabilmesi gerekir. Normalde birden fazla sahip 119 | varken mutable olma hali derleme hatasına yol açabilir. RefCell kullanımı ile bunu runtime'a 120 | taşırız. Yani ownership kontrolünü runtime tarafında işleriz. 121 | 122 | Bu kullanımda borrow_mut ve borrow metot çağrımları söz konusudur. Bu çağrımlar esasında 123 | RefCell türevli Ref ve RefMut trait'lerini kullanır. 124 | */ 125 | 126 | #[derive(Debug)] 127 | struct Player { 128 | id: u32, 129 | name: String, 130 | friends: RefCell>>, 131 | } 132 | 133 | impl Player { 134 | fn new(id: u32, name: &str) -> Rc { 135 | Rc::new(Player { 136 | id, 137 | name: name.to_string(), 138 | friends: RefCell::new(Vec::new()), 139 | }) 140 | } 141 | 142 | fn add_friend(self: &Rc, friend: Rc) { 143 | self.friends.borrow_mut().push(friend); 144 | } 145 | 146 | fn print(&self) { 147 | println!("{}'s friends:", self.name); 148 | for friend in self.friends.borrow().iter() { 149 | println!(" {} (ID: {})", friend.name, friend.id); 150 | } 151 | } 152 | } 153 | 154 | pub fn run_rc() { 155 | let steve = Player::new(1, "Stivi Vondır"); 156 | let lord = Player::new(2, "Lord veyda"); 157 | let anakin = Player::new(3, "Anakin"); 158 | 159 | steve.add_friend(Rc::clone(&lord)); 160 | steve.add_friend(Rc::clone(&anakin)); 161 | 162 | steve.print(); 163 | 164 | println!("Lord Veyda's ID: {}", lord.id); 165 | } 166 | -------------------------------------------------------------------------------- /S12_traits/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Trait'ler Rust'ın en önemli enstrümanlarından birisidir. 3 | Özellikle generic olma kabiliyeti ile birlikte ele alınır. 4 | Bu örneğe kadar çok detaya girmeden gazı trait'leri kullandık. 5 | Debug, Copy, Clone, Add vb 6 | 7 | Bir trait aslında bir davranış tanımlar. Herhangibir veri modeli bu davranışı 8 | kendisine alabilir. Böylece sistem içerisinde aynı davranışlara sahip fonksiyonellikleri 9 | bulmak ve organize etmek kolaylaşır. 10 | 11 | C# tarafında interface tipinin kullanım amacı ile benzetilebilir. 12 | */ 13 | fn main() { 14 | let mut redis_instance = Redis; 15 | let mut doctor = HealthCheck { is_online: false }; 16 | 17 | start_sample(&mut redis_instance); 18 | start_sample(&mut doctor); 19 | start_sample2(&mut redis_instance); 20 | 21 | // default trait kullanımı için örnek 22 | let debit_payment = DebitCard; 23 | let company_payment = CompanyAccount; 24 | let card_payment = CreditCard; 25 | 26 | debit_payment.pay(100.0); 27 | card_payment.pay(100.0); 28 | company_payment.pay(100.0); 29 | 30 | // Trait Object kullanımı 31 | let red_ball = Circle; 32 | let blue_ball = Circle; 33 | let wall = Square; 34 | let warrior = Player; 35 | let level_1: Vec<&dyn Draw> = vec![&red_ball, &blue_ball, &wall, &warrior]; 36 | draw_shapes(&level_1); 37 | } 38 | 39 | /* 40 | Aşağıdaki fonksiyon parametre olarak Service trait' ini 41 | uygulayan değişkenler ile çalışabilmektedir. 42 | */ 43 | fn start_sample(service: &mut impl Service) { 44 | service.activate(); 45 | println!("{:?}", service.status()); 46 | service.deactivate(); 47 | println!("{:?}", service.status()); 48 | } 49 | // Bazı durumlarda Trait bildirimi generic tanımlama üzerinden de yapılabilir 50 | fn start_sample2(service: &mut T) { 51 | service.activate(); 52 | println!("{:?}", service.status()); 53 | service.deactivate(); 54 | println!("{:?}", service.status()); 55 | } 56 | 57 | /* 58 | # Bir trait nasıl tanımlanır, nasıl uygulanır? 59 | 60 | Service isimli trait activate ve deactivate isimli iki fonksiyon tanımlar. 61 | Devam eden kob bloğunda yer alan Redis ve HealthCheck isimli veri yapıları 62 | bu davranışları kendilerine göre özelleştirir. 63 | */ 64 | trait Service { 65 | fn activate(&mut self); 66 | fn deactivate(&mut self); 67 | fn status(&self) { 68 | println!("Service status"); 69 | } 70 | } 71 | 72 | struct Redis; 73 | struct HealthCheck { 74 | is_online: bool, 75 | } 76 | /* 77 | Service davranışları Redis veri modeli için aşağıdaki gibi uygulanabilir. 78 | Bir Trait bir veri yapısı ile ilişkilendirildiğinde tanımlı tüm trait'ler uygulanmalıdır. 79 | Sadece Default trait için farklı bir durum söz konusudur. 80 | Örneğin status isimli fonksiyon Service trait'i içerisinde bir kod fonksiyonuna sahiptir. 81 | Yani Service trait'inin uygulandığı veri yapısında ezilmek zorunda değildir. 82 | */ 83 | impl Service for Redis { 84 | fn activate(&mut self) { 85 | println!("Activating Redis"); 86 | } 87 | fn deactivate(&mut self) { 88 | println!("Deactivating Redis"); 89 | } 90 | } 91 | 92 | impl Service for HealthCheck { 93 | fn activate(&mut self) { 94 | self.is_online = true; 95 | println!("Activating HealthCheck"); 96 | } 97 | fn deactivate(&mut self) { 98 | println!("Deactivating HealthCheck"); 99 | } 100 | fn status(&self) { 101 | println!("Service status {}", self.is_online); 102 | } 103 | } 104 | 105 | /* 106 | varsayılan trait kullanımı için bir başka örneği de şöyle yazabiliriz. 107 | Bir ödeme davranışımız var. Varsayılan olarak tutar ne ise onu kullanır. 108 | Ancak örneğin kredi kartı ödemesinde ek komisyon söz konusudur. 109 | Diğer ödeme biçimlerinden farklı bir davranışın uygulanması gerekir. 110 | */ 111 | trait Payment { 112 | fn pay(&self, amount: f64) { 113 | println!("Paid amount {:.2} with cash.", amount); 114 | } 115 | } 116 | struct DebitCard; 117 | impl Payment for DebitCard {} 118 | struct CompanyAccount; 119 | impl Payment for CompanyAccount {} 120 | struct CreditCard; 121 | impl Payment for CreditCard { 122 | fn pay(&self, amount: f64) { 123 | let amount_with_commision = amount * 1.1; 124 | println!("Paid {:.2} with credit card.", amount_with_commision); 125 | } 126 | } 127 | 128 | /* 129 | Aşağıdaki örnekte ise Trait Object kullanımı söz konusudur. 130 | Bazı durumlarda belli bir Trait'in uygulayıcılarını nesne olarak fonksiyonlara almak isteyebiliriz. 131 | Burada sıkıntı Trait implemente eden tipin bellekte ne kadar yer kaplayacağını kestirememektir. 132 | Kullanım formasyonlarından birisi dinamik nesne tanımlamasıdır. 133 | dyn Trait 134 | */ 135 | // Standart bir grafik kütüphanesinde veya oyun motorunda draw davranışı olduğunu varsayalım 136 | trait Draw { 137 | fn draw(&self); 138 | } 139 | 140 | struct Circle; 141 | struct Square; 142 | struct Player; 143 | 144 | impl Draw for Circle { 145 | fn draw(&self) { 146 | println!("Drawing a circle"); 147 | } 148 | } 149 | 150 | impl Draw for Square { 151 | fn draw(&self) { 152 | println!("Drawing a square"); 153 | } 154 | } 155 | 156 | impl Draw for Player { 157 | fn draw(&self) { 158 | println!("Drawing a player"); 159 | } 160 | } 161 | 162 | /* 163 | draw_shape fonksiyonu dikkat edileceği üzre &dyn Draw türünden bir parametre almaktadır. 164 | Buna göre bu fonksiyona Draw trait'ini implemente eden herhangibir nesneyi gönderebilir 165 | ve bu değişken üzerinen draw metodunu işlettirebiliriz. 166 | */ 167 | fn draw_shapes(shapes: &Vec<&dyn Draw>) { 168 | for shape in shapes.iter() { 169 | shape.draw(); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /S19_threads/src/arc_and_mutex.rs: -------------------------------------------------------------------------------- 1 | use std::sync::{Arc, Mutex}; 2 | use std::thread; 3 | use std::time::Duration; 4 | 5 | // pub fn run_with_error() { 6 | // let data = vec![ 7 | // "Service Red: Task A", 8 | // "Service Blue: Task B", 9 | // "Service Green: Task C", 10 | // "Service Alpha: Task D", 11 | // ]; 12 | // 13 | // let mut handles = vec![]; 14 | // 15 | // /* 16 | // Bu kullanımda thread'ler data isimli vektör içeriğini ortaklaşa kullanmak ister. 17 | // Ancak burada data içeriği closure tarafından sahiplenilir ve doğal olarak diğer 18 | // bir thread'in erişmesi mümkün olmaz. Çözüm için Atomcially Reference Counted (Arc) 19 | // smart pointer'ı kullanılabilir. 20 | // */ 21 | // for i in 0..2 { 22 | // let handle = thread::spawn(move || { 23 | // for task in &data { 24 | // println!("Thread '{}' is processing '{}'", i, task); 25 | // } 26 | // }); 27 | // 28 | // handles.push(handle); 29 | // } 30 | // 31 | // for handle in handles { 32 | // handle.join().unwrap(); 33 | // } 34 | // } 35 | 36 | pub fn run_correctly() { 37 | let data = Arc::new(vec![ 38 | "Service Red: Task A", 39 | "Service Blue: Task B", 40 | "Service Green: Task C", 41 | "Service Alpha: Task D", 42 | ]); 43 | 44 | let mut handles = vec![]; 45 | 46 | /* 47 | Yukarıda moved hatası nedeniyle hatalı çalışan senaryoda Arc kullanılarak gerekli 48 | çözüm sağlanabilir. 49 | */ 50 | for i in 0..2 { 51 | let data_clone = Arc::clone(&data); 52 | let handle = thread::spawn(move || { 53 | for task in data_clone.iter() { 54 | println!("Thread '{}' is processing '{}'", i, task); 55 | } 56 | }); 57 | 58 | handles.push(handle); 59 | } 60 | 61 | for handle in handles { 62 | handle.join().unwrap(); 63 | } 64 | } 65 | 66 | /* 67 | Arc kullanılarak thread'lerin veriye güvenli bir şekilde erişmesi sağlanabilir 68 | ancak burada veri tutarlılığının bozulma ihtimali de olabilir. 69 | */ 70 | // pub fn run_inconsistent() { 71 | // let data = Arc::new(vec![0; 10]); 72 | // let mut handles = vec![]; 73 | // 74 | // for i in 0..4 { 75 | // /* 76 | // Thread'ler için verinin referansını Arc ile klonluyoruz. 77 | // Böylece thread'ler ilgili veriye erişebilirler. 78 | // */ 79 | // 80 | // let data_clone = Arc::clone(&data); 81 | // 82 | // let handle = thread::spawn(move || { 83 | // for j in 0..data_clone.len() { 84 | // /* 85 | // Aşağıda ise veri üzerinde bir güncelleme yapmaktayız. 86 | // Bu güncelleme işlemi derleme zamanında 87 | // 88 | // error[E0596]: cannot borrow data in an `Arc` as mutable 89 | // 90 | // hatasının oluşmasına sebep olur. Zira Arc ile veriye eş zamanlı erişmek 91 | // mümkünken güvenli bir şekilde değiştirmek söz konusu değildir. 92 | // 93 | // istisna olarak unsafe bir yaklaşım ile bu durum ihlal edilebilir. 94 | // Ancak ideal olanı Mutex kullanmak ve threadler arasındaki ortak veriyi 95 | // değiştirirken güvenli bir erişim sağlamaktır. Birisi veriyi değiştirirken 96 | // başka thread o veriyi değiştiremez. 97 | // 98 | // Böylece thread'ler veriyi ortaklaşa okuyabilir ve güvenli şekilde değiştirebilir. 99 | // */ 100 | // data_clone[j] += 2; 101 | // println!("Thread {} updating index {}", i, j); 102 | // } 103 | // }); 104 | // 105 | // handles.push(handle); 106 | // } 107 | // 108 | // for handle in handles { 109 | // handle.join().unwrap(); 110 | // } 111 | // 112 | // println!("{:?}", *data); 113 | // } 114 | 115 | /* 116 | Bu metot data'ya ortaklaşa erişen ve onu güvenli şekilde değiştiren 117 | çoklu thread kullanımını örneklemektedir. 118 | */ 119 | pub fn run_safely() { 120 | // Datayı mutex ile güvenlik altına alırken, Arc ile de thread safe referans sayımı yapıyoruz. 121 | let data = Arc::new(Mutex::new(0)); 122 | let mut handles = vec![]; 123 | 124 | for _ in 0..5 { 125 | // Her thread için kullanılacak smart pointer nesnesini oluşturuyoruz 126 | let data_clone = Arc::clone(&data); 127 | 128 | let handle = thread::spawn(move || { 129 | // Veriyi kullanmak için thread içerisinde önce kilidi açmamız lazım 130 | let mut num = data_clone.lock().unwrap(); 131 | *num += 1; 132 | }); // Lock burada serbest bırakılır 133 | 134 | handles.push(handle); 135 | } 136 | 137 | for handle in handles { 138 | handle.join().unwrap(); 139 | } 140 | 141 | println!("Final value: {}", *data.lock().unwrap()); 142 | } 143 | 144 | /* 145 | Mutex veriyi kullandırırken kilit mekanizmasını işletir. 146 | Bunu görmek için aşağıdaki örneğe bakabiliriz. 147 | */ 148 | pub fn run_mutex() { 149 | // Ortak olarak kullanılacak veri 150 | let data = Arc::new(Mutex::new(0)); 151 | 152 | let data_clone_one = Arc::clone(&data); 153 | let t1 = thread::spawn(move || { 154 | let mut num = data_clone_one.lock().unwrap(); 155 | *num += 3; 156 | println!("Thread 1 has locked the data."); 157 | thread::sleep(Duration::from_secs(3)); // Kasıtlı olarak bekletme yapıyoruz 158 | println!("After 3 seconds...\nThread 1 is unlocking the data."); 159 | }); 160 | 161 | let data_clone_two = Arc::clone(&data); 162 | let t2 = thread::spawn(move || { 163 | println!("Thread 2 is trying to lock the data."); 164 | let mut num = data_clone_two.lock().unwrap(); 165 | *num += 5; 166 | println!("Thread 2 has locked and updated the data."); 167 | }); 168 | 169 | t1.join().unwrap(); 170 | t2.join().unwrap(); 171 | 172 | println!("Final value: {}", *data.lock().unwrap()); 173 | } 174 | -------------------------------------------------------------------------------- /S09_enums/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Rust tarafında veriyi ifade etme şeklinin bir yolu da Enum kullanmaktır. 3 | Enum veri yapısı oldukça zengindir. 4 | İşte kullanıma ilişkin birkaç örnek. 5 | */ 6 | // Örnekte User enum değişkeninde aktivasyon tarihi için de yardımcı bir crate kullanıldı 7 | use chrono::{DateTime, Utc}; 8 | // Bu örnekte rastgelelik gerektiren bir durum olduğu için bu crate eklendi 9 | use rand::Rng; 10 | 11 | enum Status { 12 | Success, 13 | InProgress, 14 | Error(String), 15 | } 16 | 17 | // Enum'lara da metotlar uygulanabilir 18 | impl Status { 19 | fn get_info(&self) -> &str { 20 | match self { 21 | Status::Success => "Success", 22 | Status::InProgress => "InProgress", 23 | Status::Error(detail) => detail, 24 | } 25 | } 26 | } 27 | 28 | fn create_report(title: String) -> Status { 29 | if title.is_empty() { 30 | return Status::Error("Title cannot be empty".to_string()); 31 | } 32 | 33 | // Sembolik olarak 3 ile bölünme durumuna göre geriye InProgress durumu döndürmekteyiz. 34 | let mut randomizer = rand::thread_rng(); 35 | let value = randomizer.gen_range(0..=3); 36 | 37 | if value % 3 == 0 { 38 | return Status::InProgress; 39 | } 40 | 41 | Status::Success 42 | } 43 | 44 | /* 45 | Pek tabi enum türleri başka bir tipin verisinde de anlam kazanır. 46 | Örneğin bir oyuncunun seviyesi enum türü ile ifade edilebilir. 47 | 48 | Debug trait implementasyonuna şimdilik takılmayalım ancak Player için bu direktif uygulandığında, 49 | Level için de uygulanması gerekir, nitekim Player veri modeli Level'ı da kullanır. 50 | Debug trait, uygulandığı tür için {:?} veya {:#?} gibi kullanımlarda kolaylık sağlar. 51 | */ 52 | #[derive(Debug)] 53 | enum Level { 54 | Rookie, 55 | Pro, 56 | Elit(f32), 57 | } 58 | 59 | #[derive(Debug)] 60 | struct Player { 61 | title: String, 62 | level: Level, 63 | is_active: bool, 64 | } 65 | 66 | impl Player { 67 | fn new(title: String, level: Level) -> Self { 68 | Player { 69 | title, 70 | level, 71 | is_active: false, 72 | } 73 | } 74 | fn change_level(&mut self, level: Level) { 75 | self.level = level; 76 | } 77 | fn activate(&mut self) { 78 | self.is_active = true; 79 | } 80 | fn deactivate(&mut self) { 81 | self.is_active = false; 82 | } 83 | } 84 | 85 | fn main() { 86 | let result = create_report(String::new()); 87 | println!("{}", result.get_info()); 88 | 89 | let result = create_report(String::from("Last Sales")); 90 | println!("{}", result.get_info()); 91 | 92 | let mut mario = Player::new(String::from("mario"), Level::Rookie); 93 | println!("{:?}", mario); 94 | mario.activate(); 95 | mario.change_level(Level::Pro); 96 | println!("{:?}", mario); 97 | mario.change_level(Level::Elit(300.59)); 98 | /* 99 | Enum veri yapısının güzel yanlarından birisi de pattern matching bloklarında ele alınabilmesidir. 100 | Aşağıda mario isimli Player değişkeninin Elit olma hali değerlendirilir. 101 | 102 | Bir enum değişkeni pattern match bloğuna dahil edildiğin olası tüm değerleri ele alınmalıdır. 103 | */ 104 | match mario.level { 105 | // Elit değeri f32 türünden birde parametre barındırabiliyor 106 | Level::Elit(coin) => { 107 | println!("Now Mario is on elit league with {coin} coin",); 108 | } 109 | _ => {} // Diğer durumları ele almak istemiyoruz 110 | } 111 | mario.deactivate(); 112 | println!("{:?}", mario); 113 | 114 | let mario = User::Inactive { 115 | name: "Can Cey Mario".to_string(), 116 | }; 117 | println!("{:#?}", mario); 118 | 119 | /* 120 | Built-in gelen Option enum'ı generic bir türdür(Generic kavramı burada kafa karıştırabilir. Çok kısaca değinmek lazım) 121 | Eğer bir değer söz konusu ise onu temsil eder(örneğin User enum değeri). 122 | Eğer ortada bir değer yoksa None döner 123 | */ 124 | if let Some(m) = mario.activate(Utc::now()) { 125 | println!("Mario etkinleştirildi"); 126 | println!("{:#?}", m); 127 | } 128 | } 129 | 130 | /* 131 | Rust enum veri yapısının zenginliğini gösteren bir diğer örneği aşağıdaki gibi ele alabiliriz. 132 | 133 | Sistemdeki bir kullanıcı akfit veya pasif olma durumuna göre kullanılmak istenir. 134 | Klasik bir OOP stilinde User isimli bir sınıf yazıp aktif olup olmama durumunu bir bool özellik ile ele alabiliriz. 135 | Aşağıdaki kurguda ise kullanıcının Inactive veya Active olma halleri bir veri modeli olarak ifade edilmektedir. 136 | Kullanıcı inactive ise sadece adını taşıyan bir enum durumu söz konusudur. 137 | Active olması ise adı haricinde, aktiv olduğu tarih gibi bilgileri de içerir. 138 | */ 139 | #[derive(Debug)] 140 | enum User { 141 | Inactive { 142 | name: String, 143 | }, 144 | Active { 145 | name: String, 146 | active: bool, 147 | activation_date: DateTime, 148 | }, 149 | } 150 | impl User { 151 | /* 152 | activate metodu dönüş türü olarak da built-in Option enum'ını kullanır. 153 | Bazı diller null değer olmasın halini karşılamak için Options pattern'i ele alır, 154 | ya da olası Exception durumlarında bilgilendirme de dönebilmek için Resut pattern kullanır. 155 | Rust, bu iki durumu built-in karşılar. Option ve Result enum'ları bunun içindir. 156 | */ 157 | fn activate(&self, activation_date: DateTime) -> Option { 158 | match self { 159 | // Inactive bir kullanıcı söz konusu ise kullanıcı ile ilgili bazı bilgiler barındıran Active değişkeni döner 160 | User::Inactive { name } => { 161 | let created = User::Active { 162 | name: name.clone(), 163 | active: true, 164 | activation_date, 165 | }; 166 | // Oluşturulan kullanıcı örneğin veri tabanına log olarak bırakılır 167 | Some(created) 168 | } 169 | User::Active { .. } => None, // Kullanıcı zaten aktivse None dönebiliriz 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /S10_pattern_matching/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Pattern Matching kabiliyeti rust tarafında da sıklıkla kullanılır. 3 | Option , Result gibi built-in gelen veya kendi tasarladığım Enum yapılarında karar yapılarını 4 | inşa etmek için ideal ve temiz bir kod pratiği sunar. 5 | */ 6 | use rand::Rng; 7 | 8 | fn main() { 9 | check_status(); 10 | 11 | check_exam(Student { 12 | id: 1, 13 | full_name: String::from("Burak De La Fuante Dos Selimos"), 14 | grade: 44, 15 | }); 16 | 17 | let mut balance = 1000.0; 18 | process_transaction(&mut balance, CustomerTransaction::Deposit(400.0)); 19 | process_transaction(&mut balance, CustomerTransaction::Withdraw(50.0)); 20 | 21 | let klyde = User::new(19, String::from("Jhony Klyde"), None); 22 | println!("{}", klyde.info()); // İlerde info yerinde Display Trait implementasyonu kullanılır 23 | let zee = User::new( 24 | 23, 25 | String::from("Zee"), 26 | Some(String::from("zee@somewhere.abc")), 27 | ); 28 | println!("{}", zee.info()); 29 | 30 | let accounts = load_accounts(); 31 | let result = find_account(&accounts, 1003); 32 | match result { 33 | Some(account) => println!( 34 | "Account for '{}' found: {} with balance ${}", 35 | account.id, account.holder_name, account.balance 36 | ), 37 | None => println!("Account not found."), 38 | } 39 | // Bazen yukarıdaki gibi bir match ifadesi yerine 'if let' söz dizimi de kullanılabilir 40 | if let Some(account) = find_account(&accounts, 1002) { 41 | println!( 42 | "Account for '{}' found: {} with balance ${}", 43 | account.id, account.holder_name, account.balance 44 | ); 45 | } 46 | } 47 | fn check_status() { 48 | /* 49 | ping, parametre olarak gelen servis adresini için bir health check yapıyor diye düşünelim. 50 | dönen HttpStatus enum değerine göre ekrana bilgilendirme yapılmakta 51 | */ 52 | let call_response = ping("http://localhost:3456/ping"); 53 | match call_response { 54 | HttpStatus::Ok => { 55 | println!("Http Status is OK(200)"); 56 | } 57 | HttpStatus::Accepted => { 58 | println!("Http Status is ACCEPTED(201)"); 59 | } 60 | HttpStatus::NotFound => { 61 | println!("Http Status is NOT FOUND(404)"); 62 | } 63 | HttpStatus::BadRequest => { 64 | println!("Http Status is BAD REQUEST(400)"); 65 | } 66 | HttpStatus::InternalServerError => { 67 | println!("Http Status INTERNAL ERROR(500)"); 68 | } 69 | } 70 | } 71 | // Sembolik olarak bir servise gidipte rastgele HttpStatus bilgisi döndüren fonksiyon 72 | fn ping(service_address: &str) -> HttpStatus { 73 | let mut generator = rand::thread_rng(); 74 | let lucy_number = generator.gen_range(0..=10); 75 | println!("Pinging the {service_address}"); 76 | // luck_number değerine göre bir Status değeri üretilir 77 | match lucy_number { 78 | 1 => HttpStatus::Ok, // 1 ise 79 | 2..=4 => HttpStatus::Accepted, // 2, 3 ve 4 dahil ise 80 | 5 => HttpStatus::BadRequest, // 5 ise 81 | 8 | 10 => HttpStatus::NotFound, // 8 veya 10 ise 82 | _ => HttpStatus::InternalServerError, // 1,2,3,4 dışındaki tüm durumlar için 83 | } 84 | } 85 | enum HttpStatus { 86 | Ok, 87 | Accepted, 88 | NotFound, 89 | BadRequest, 90 | InternalServerError, 91 | } 92 | 93 | struct Student { 94 | id: u32, 95 | full_name: String, 96 | grade: u8, 97 | } 98 | 99 | fn check_exam(student: Student) { 100 | // pattner mathcing'de aşağıdaki gibi değer aralıkları da kullanılabilir 101 | match student.grade { 102 | 0..=49 => println!("[{}]{} failed.", student.id, student.full_name), 103 | 50..=79 => println!("[{}]{} passed.", student.id, student.full_name), 104 | 80..=100 => println!( 105 | "[{}]{} passed with congrats.", 106 | student.id, student.full_name 107 | ), 108 | _ => println!("Invalid grade score"), 109 | } 110 | } 111 | 112 | enum CustomerTransaction { 113 | Deposit(f64), 114 | Withdraw(f64), 115 | } 116 | 117 | fn process_transaction(balance: &mut f64, transaction: CustomerTransaction) { 118 | match transaction { 119 | CustomerTransaction::Deposit(amount) => { 120 | *balance += amount; 121 | println!("Deposited ${}\nNew balance: ${}.", amount, balance); 122 | } 123 | CustomerTransaction::Withdraw(amount) => { 124 | if *balance >= amount { 125 | *balance -= amount; 126 | println!("Withdraw ${}\nNew balance: ${}.", amount, balance); 127 | } else { 128 | println!("Insufficient funds."); 129 | } 130 | } 131 | } 132 | } 133 | 134 | struct User { 135 | id: u32, 136 | title: String, 137 | email: Option, // Some(String) veya None değerlerinden birisini alabilir 138 | // Yani User için bir email adresi atama zorunluluğu olmadığı varsayılmaktadır 139 | } 140 | 141 | impl User { 142 | fn new(id: u32, title: String, email: Option) -> Self { 143 | User { id, title, email } 144 | } 145 | 146 | fn info(&self) -> String { 147 | /* 148 | User bilgisini string olarak dönerken email bilgisine sahip olup olmamasına 149 | göre farklı bir içerik oluşturmak için pattern matching'den yararlanabiliriz 150 | */ 151 | match self.email { 152 | Some(ref em) => format!("{}-{} ({})", self.id, self.title, em), 153 | None => format!("{} ({})", self.id, self.title), 154 | } 155 | } 156 | } 157 | 158 | struct Account { 159 | id: u32, 160 | holder_name: String, 161 | balance: f64, 162 | } 163 | /* 164 | Referans olarak gelen vektör içerisinde id bilgisine sahip Account değişkenini arayan 165 | bu fonksiyon Option<&T> dönmektedir. 166 | Metodun kullanıldığı yerde pattern matching'den yararlanılır. 167 | */ 168 | fn find_account(accounts: &Vec, id: u32) -> Option<&Account> { 169 | accounts.iter().find(|acc| acc.id == id) 170 | } 171 | 172 | fn load_accounts() -> Vec { 173 | vec![ 174 | Account { 175 | id: 1001, 176 | holder_name: "Nora Min".to_string(), 177 | balance: 1000.0, 178 | }, 179 | Account { 180 | id: 1002, 181 | holder_name: "Agnis Yang".to_string(), 182 | balance: 750.0, 183 | }, 184 | Account { 185 | id: 1003, 186 | holder_name: "Valeri Mora".to_string(), 187 | balance: 850.0, 188 | }, 189 | Account { 190 | id: 1004, 191 | holder_name: "Monti Konti".to_string(), 192 | balance: 275.0, 193 | }, 194 | ] 195 | } 196 | -------------------------------------------------------------------------------- /S20_channels/src/problems.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Her ne kadar rust dili thread-safe bir ortam sağlamak için bazı kuralları devreye alsa da 3 | deadlock veya mutex poisoning gibi durumlardan kaçılamayabilir. Aşağıdaki örnek kodlarda 4 | bu durumlar ele alınmaktadır. 5 | 6 | Kilit mekanizmalarının hatalı kullanımları deadlock oluşmasına sebep olabilir. 7 | Diğer yandan bir kilit söz konusu iken bulunulan thread'de panic oluşması da sorun yaratır ve 8 | bu durum Thread Poisoning olarak adlandırılır. 9 | */ 10 | use std::fs::File; 11 | use std::io::Write; 12 | use std::sync::{Arc, Mutex}; 13 | use std::thread; 14 | 15 | pub fn deadlock_case() { 16 | let number = Arc::new(Mutex::new(1)); 17 | let mut handles = vec![]; 18 | 19 | for i in 0..10 { 20 | let number = Arc::clone(&number); 21 | let handle = thread::spawn(move || { 22 | println!("For counter is {}", i); 23 | let mut num = number.lock().unwrap(); 24 | /* 25 | Aşağıdaki satırda number birkez daha kilitlenmeye çalışılır. 26 | Bu thread'lerin birbirini beklemesine sebep olacak bir deadlock oluşması anlamına gelir. 27 | Dolayısıyla program bir türlü sonlanmaz. 28 | */ 29 | let mut another_num = number.lock().unwrap(); 30 | *num += 1; 31 | }); 32 | handles.push(handle); 33 | } 34 | 35 | for handle in handles { 36 | println!("Joining handle"); 37 | handle.join().unwrap(); 38 | } 39 | 40 | println!("{:?}", number.lock().unwrap()); 41 | } 42 | 43 | struct Account { 44 | owner: String, 45 | balance: f32, 46 | } 47 | /* 48 | Aşağıdaki senaryoda da bir deadlock durumu oluşmaktadır. 49 | Hesap bilgileri Mutex'ler ile korunu ve arka arkaya açılan iki thread bu mutex'ler ile 50 | işlem yapmaya çalışır. Thread'ler içerisindeki kilit açma sıralarında karşılıklı Mutex'lerin 51 | ele alınmaya çalışılıyor olması bunun en büyük nedenidir. 52 | */ 53 | pub fn deadlock_case_banking() { 54 | let my_account = Arc::new(Mutex::new(Account { 55 | owner: "John Doe".to_string(), 56 | balance: 100.0, 57 | })); 58 | let other_account = Arc::new(Mutex::new(Account { 59 | owner: "Merry Jane".to_string(), 60 | balance: 200.0, 61 | })); 62 | 63 | let my_account_clone = Arc::clone(&my_account); 64 | let other_account_clone = Arc::clone(&other_account); 65 | 66 | let handle1 = thread::spawn(move || { 67 | let mut source_account = my_account_clone.lock().unwrap(); 68 | println!("Thread 1: Locked by source account"); 69 | thread::sleep(std::time::Duration::from_secs(1)); 70 | let mut target_account = other_account_clone.lock().unwrap(); 71 | println!("Thread 1: Locked by target account"); 72 | 73 | source_account.balance -= 50.0; 74 | target_account.balance += 50.0; 75 | }); 76 | 77 | let my_account_clone = Arc::clone(&my_account); 78 | let other_account_clone = Arc::clone(&other_account); 79 | 80 | let handle2 = thread::spawn(move || { 81 | let mut acc2 = other_account_clone.lock().unwrap(); 82 | println!("Thread 2: Locked by target account"); 83 | thread::sleep(std::time::Duration::from_secs(1)); 84 | let mut acc1 = my_account_clone.lock().unwrap(); 85 | println!("Thread 2: Locked by source account"); 86 | 87 | acc2.balance -= 25.0; 88 | acc1.balance += 25.0; 89 | }); 90 | 91 | handle1.join().unwrap(); 92 | handle2.join().unwrap(); 93 | 94 | println!( 95 | "Final balances: My Account : {}, Other Account: {}", 96 | my_account.lock().unwrap().balance, 97 | other_account.lock().unwrap().balance 98 | ); 99 | } 100 | 101 | /* 102 | Bu fonksiyonda thread poisoning durumu ele alınmaktadır. 103 | thread açıldığında Mutex'ten bir kilit alınır ancak hemen arkasından kasıtlı olarak panic 104 | durumu oluşturulur. Bu nokta thread'in zehirlendiği kısımdır. 105 | 106 | Bu nedenle guard değişkeni unwrap_or_else metodu ile ele alınmıştır. Panic oluşması halinde 107 | into_iter ile kurtarılması sağlanabilir. 108 | */ 109 | pub fn poisoning_case() { 110 | let first_lock = Arc::new(Mutex::new(100)); 111 | let second_lock = Arc::clone(&first_lock); 112 | 113 | let _ = thread::spawn(move || { 114 | let mut inner_guard = second_lock.lock().unwrap(); 115 | *inner_guard += 1; 116 | panic!("Thread is poisoning..."); 117 | }) 118 | .join(); 119 | 120 | let mut guard = first_lock 121 | .lock() 122 | .unwrap_or_else(|poisoned| poisoned.into_inner()); 123 | 124 | *guard += 10; 125 | println!("Thread guard: {:?}", guard); 126 | } 127 | 128 | /* 129 | Aşağıdaki senaryoda da Thread Poisoning durumu söz konusudur ancak biraz daha gerçekçi bir 130 | durum ele alınmaktadır. Birden fazla thread'in bir log dosyasına kayıt attığını düşünelim. 131 | Disk dolabilir farklı bir I/O hatası olabilir ve yazan thread içinden panic üretimi mümkün 132 | hale gelebilir. Böyle bir durumda thread zehirlenmesi meydana gelir. 133 | Aşağıdaki örnekte ilk thread içerisinde kasıtlı olarak bir panic durumu oluşturulur. 134 | Uygulamanın ilk versiyonunda bu durum diğer thread tarafından ele alınmaz ve program istem dışı 135 | şekilde sonlanır. 136 | Ancak ikinci uygulamada unwrap_or_else ile mutex'in zehirli olup olmama durumuna göre bir kontrol 137 | söz konusudur. 138 | */ 139 | pub fn poisoning_case_logging() { 140 | let log_file = Arc::new(Mutex::new( 141 | File::create("system.log").expect("Unable to create log file"), 142 | )); 143 | let log_file_clone = Arc::clone(&log_file); 144 | 145 | let handle = thread::spawn(move || { 146 | let mut file = log_file_clone.lock().unwrap(); 147 | writeln!(file, "Thread 1: Writing the system health status").unwrap(); 148 | panic!("Errors occurred while writing to the log file!"); 149 | }); 150 | 151 | // let log_file_clone = Arc::clone(&log_file); 152 | // let handle_2 = thread::spawn(move || { 153 | // let mut file = log_file_clone.lock().unwrap(); 154 | // thread::sleep(std::time::Duration::from_secs(3)); 155 | // writeln!(file, "Thread 2: Attempting to write").unwrap(); 156 | // }); 157 | 158 | // Üstteki durum değerlendirildikten sonra aşağıdaki kod parçası incelenir 159 | let log_file_clone = Arc::clone(&log_file); 160 | let recovery_handle = thread::spawn(move || { 161 | let mut file = log_file_clone 162 | .lock() 163 | .unwrap_or_else(|poisoned| poisoned.into_inner()); 164 | thread::sleep(std::time::Duration::from_secs(3)); 165 | writeln!(file, "Thread 2: Recovering from poisoned state").unwrap(); 166 | }); 167 | 168 | let _ = handle.join(); 169 | // let _ = handle_2.join(); 170 | let _ = recovery_handle.join(); 171 | 172 | println!("Log file operations completed"); 173 | } 174 | -------------------------------------------------------------------------------- /S06_ownership/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | { 3 | // Kasıtlı bir scope başlangıcı 4 | let player_score = 90; 5 | println!("Player Score is {}", player_score); 6 | let _title = String::from("Programming with Rust"); 7 | let _size = (640_f32, 480_f32); 8 | } // Scope sonu 9 | 10 | // println!("Player Score is {}",player_score); // Scope dışından owner_score'a erişilemez(dropped) 11 | 12 | move_rule(); 13 | move_rule_with_clone(); 14 | 15 | /* 16 | i32 gibi türler Copy trait'ini uygularlar. Bu tip boyutça küçük veri türleri 17 | kopyalama ile taşındıklarından bir move ihlali söz konusu olmaz. 18 | Copy ve Clone aslında birer Trait' tir ve belli veri türlerine uygulanır. 19 | Clone, deep copy işlemi uyguladığından Copy operasyonuna göre maliyetlidir. 20 | */ 21 | let number = 32u8; 22 | let other_number = number; 23 | println!("Number is {}", number); 24 | println!("Other number is {}", other_number); 25 | 26 | /* 27 | Örneğin String türü otomatik bir kopyalama işlemi yapmaz. Açıkça klonlamak gerekir. 28 | String veri türünün Rust tarafındaki implementasyonuna bakmakta yarar var. 29 | Clone trait'ini uyguladığını açıkça görebiliriz. 30 | 31 | Eğer first_name'i full_name'i oluşturmak için kullanırken clone'larsak move sorunu giderilir. 32 | Yine de Clone operasyonunun maliyetli olduğunu unutmamamlıyız. 33 | */ 34 | let first_name = String::from("Burak"); 35 | let full_name = first_name + " Selim Şenyurt"; 36 | println!("Full name is {}", full_name); 37 | // println!("First name is {}", first_name); // Value used after being moved [E0382] 38 | 39 | let book_title = String::from("Programming with Rust"); 40 | search_book(book_title); // sahiplik(ownership) metota geçer 41 | // Bu nedenle aşağıdaki satırda artık book_title kullanılamaz. 42 | // println!("Book title is {}", book_title); // Value used after being moved [E0382] 43 | 44 | /* 45 | Aşağıdak örnekte de, bir String değişken check_department fonksiyonuna gönderilmekte. 46 | Fonksiyon söz konusu String değişkenin sahipliğini alıp bazı operasyonlar gerçekleştirdikten 47 | sonra aynen geriye dönebilir. 48 | */ 49 | let department = String::from("IT"); 50 | let department = check_department(department); // Sahiplik fonksiyondan geri alınıyor 51 | println!("The department is {}", department); 52 | 53 | /* 54 | Birde Shallo Copy'yi baz alan değer türlerine bakalım. 55 | f32'de stack bazlı bir veri türüdür ve Deep Copy yerine basit veri kopyalamasını kullanır (Copy) 56 | Bu nedenle metoda geçen değer otomatik olarak kopyalanarak gider. 57 | Dönüşünde tekrardan kullanılabilir. Özetle move ihlali olmaz. 58 | */ 59 | let amount = 955.50f32; 60 | send_money(amount); 61 | println!("{} coin sent", amount); 62 | 63 | /* 64 | Aşağıdaki kod örneğinde String veri türünün referans yolu ile bir metoda parametre olarak 65 | geçilmesi söz konusudur. & ile level_name referansı taşındığından bir sonraki satırda 66 | move ihlali söz konusu olmayacaktır. 67 | */ 68 | let level_name = String::from("Casino Royal"); 69 | load_level(&level_name); 70 | println!("Now game at level {}", level_name); 71 | 72 | /* 73 | Aşağıdaki kullanım da mümkündür. 74 | some_words değişkeninin sahipliği mutable referans olarak trim_last metoduna taşınır. 75 | */ 76 | let mut some_words = String::from("Some words !."); 77 | trim_last(&mut some_words); 78 | println!("{}", some_words); 79 | trim_last(&mut some_words); 80 | println!("{}", some_words); 81 | 82 | /* 83 | Ownership kurallarına göre bir veri aynı anda yalnızca bir mutable referansa sahip olabilir 84 | ya da aynı anda birden fazla shared referansa mümkündür. 85 | */ 86 | let mut motto = String::from("It's a Beautiful Day !."); 87 | let upper_counts = get_upper_counts(&motto); 88 | load_level(&motto); 89 | trim_last(&mut motto); 90 | println!("Upper Letter counts: {}", upper_counts); 91 | 92 | only_one_mutable(); 93 | } 94 | 95 | fn get_upper_counts(context: &String) -> usize { 96 | let mut count = 0; 97 | for c in context.chars() { 98 | if c.is_ascii_uppercase() { 99 | count += 1; 100 | } 101 | } 102 | count 103 | } 104 | 105 | fn load_level(name: &String) { 106 | println!("Loading level {}", name); 107 | } 108 | 109 | fn trim_last(context: &mut String) { 110 | context.pop(); 111 | } 112 | 113 | fn send_money(money: f32) { 114 | println!("{} coin is sending...", money); 115 | } 116 | 117 | fn check_department(department: String) -> String { 118 | println!("Calculating defects for '{}' department", department); 119 | department 120 | } 121 | 122 | /* 123 | Bu fonksiyon parametre olarak gelen title değişkeninin sahipliğini de alır (ownership) 124 | Dolayısıyla metottan çıkılırken scope kuralı gereği title değişkeni bellekten düşürülür. 125 | */ 126 | fn search_book(title: String) { 127 | println!("Starting search for '{}'", title); 128 | } 129 | 130 | fn move_rule() { 131 | // Ownership yasasında move ihlali için Vec tabanlı örnek 132 | let names = vec![ 133 | "John".to_string(), 134 | "Beatrice".to_string(), 135 | "Zee".to_string(), 136 | ]; 137 | let _names_again = names; // names vektör sahipliği names_again'e geçti. names artık yok. 138 | // println!("{:?}", names); // Value used after being moved [E0382] 139 | } 140 | 141 | fn move_rule_with_clone() { 142 | /* 143 | Ownership yasasında move ihlali clone operasyonu ile aşılabilir ancak; 144 | Aşağıdaki gibi String türden veri içeren büyük bir vektör için clone operasyonunun 145 | büyük bir maliyeti vardır. 146 | */ 147 | let names = vec![ 148 | "John".to_string(), 149 | "Beatrice".to_string(), 150 | "Zee".to_string(), 151 | ]; 152 | let names_again = names.clone(); // names vektörünün bir klonu oluşturulur ve bunun sahipliği names_again değişkenine verilir 153 | println!("{:?}", names); // Bu durumda names halen kullanılabilirdir. 154 | println!("{:?}", names_again); 155 | } 156 | 157 | fn only_one_mutable() { 158 | let mut greetings = String::from("Hello HAL! How are you doing?"); 159 | 160 | let ref_1 = &greetings; // Immutable referans 161 | let ref_2 = &greetings; // Diğer immutable referansımız 162 | 163 | // let mut_ref = &mut greetings; // Mutable referans oluşturmaya çalışıyoruz 164 | 165 | /* 166 | Hem immutable hem de mutable referansı 167 | aynı anda kullanmaya çalışmak hataya neden olacaktır. 168 | 169 | error[E0502]: cannot borrow `greetings` as mutable because it is also borrowed as immutable 170 | --> S06_ownership\src/main.rs:163:19 171 | | 172 | 160 | let ref_1 = &greetings; // Immutable referans 173 | | ---------- immutable borrow occurs here 174 | ... 175 | 163 | let mut_ref = &mut greetings; // Mutable referans oluşturmaya çalışıyoruz 176 | | ^^^^^^^^^^^^^^ mutable borrow occurs here 177 | ... 178 | 169 | println!("{}, {}", ref_1, ref_2); 179 | | ----- immutable borrow later used here 180 | 181 | */ 182 | println!("{}, {}", ref_1, ref_2); 183 | // println!("{}", mut_ref); 184 | } 185 | -------------------------------------------------------------------------------- /S13_built_in_traits/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Rust standart kütüphanesi bir dizi hazır trait sunar. 3 | Debug, Copy, Clone, Default, PartialEq, Drop gibi bir çok tür vardır. 4 | Aşağıdaki kod parçalarında bu trait'lerin kullanımlarına ait örnekler yer alıyor 5 | */ 6 | use std::fmt::{Display, Formatter}; 7 | use std::num::ParseIntError; 8 | use std::str::FromStr; 9 | 10 | fn main() { 11 | let max_payne = Player { 12 | name: String::from("Max Payne"), 13 | level: 80, 14 | last_score: 167.58, 15 | }; 16 | // Debug trait'ini uygulamazsak 17 | // `Player` does not implement `Debug` (required by `{:#?}`): E0277 18 | println!("{:#?}", max_payne); 19 | 20 | // Aşağıdaki kullanım ise Display trait'ini uygulamayı gerektirir 21 | println!("{}", max_payne); 22 | 23 | // Clone trait uygulaması 24 | let mut red_one = max_payne.clone(); 25 | red_one.name = String::from("Red Leader One"); 26 | println!("{:#?}", red_one); 27 | 28 | // PartialEq ve Copy, Clone örnekleri 29 | let my_speed = Velocity { x: 10.0, y: 0.0 }; 30 | let your_speed = Velocity { x: 10.0, y: 0.0 }; 31 | if my_speed == your_speed { 32 | println!("{my_speed:?} is equal to {your_speed:?}") 33 | } 34 | accelerate(your_speed); 35 | // Eğer Velocity için Copy trait kullanmazsak 36 | // Value used after being moved [E0382] derleme hatası oluşur 37 | if my_speed == your_speed { 38 | println!("{my_speed:?} is equal to {your_speed:?}") 39 | } else { 40 | println!("{my_speed:?} is not equal to {your_speed:?}") 41 | } 42 | 43 | // PartialEq örneği 44 | let log_1 = LogStamp { 45 | id: 1234, 46 | time: String::from("2024-10-20T09:56-PM"), 47 | content: String::from("Check with ping"), 48 | }; 49 | let log_2 = LogStamp { 50 | id: 1234, 51 | time: String::from("2024-10-20T09:58-PM"), 52 | content: String::from("Check with ping"), 53 | }; 54 | if log_1 == log_2 { 55 | println!("Same logs\n{log_1:?}\n{log_2:?}"); 56 | } 57 | 58 | // Default trait örneği 59 | let my_game = Game::default(); 60 | println!("{:#?}", my_game); 61 | println!("{}", my_game); 62 | 63 | // FromStr kullanımı 64 | let valid_color = "125:100:100".parse::(); 65 | match valid_color { 66 | Ok(color) => println!("Parsed color: {:?}", color), 67 | Err(e) => println!("Error parsing color: {:?}", e), 68 | } 69 | 70 | let invalid_color = "red:100:100".parse::(); 71 | match invalid_color { 72 | Ok(color) => println!("Parsed color: {:?}", color), 73 | Err(e) => println!("Error parsing color: {:?}", e), 74 | } 75 | 76 | // Drop trait kullanım örneği 77 | { 78 | let author_service = Service { 79 | title: String::from("Author service"), 80 | address: String::from("https://azon/services/author"), 81 | }; 82 | println!("{:#?} is ready.", author_service); 83 | author_service.call(); 84 | } // Drop trait tetiklenir 85 | } 86 | 87 | fn accelerate(mut speed: Velocity) { 88 | speed.x += 1.0; 89 | speed.y += 1.0; 90 | println!("Accelerating a little bit. {:#?}", speed); 91 | println!("Normalizing"); 92 | } 93 | 94 | /* 95 | Bir player değişkeni Debug trait sayesinde {:?} veya 96 | {:#?} gösterimlerini doğrudan destekler. 97 | Çıktı otomatik olarak JSON formatına döndürülür. 98 | 99 | Player veri yapısı aynı zamanda Clone trait'ini devralır. 100 | Buna göre klonlanarak (shallow copy) taşıma işlemlerine dahil edilebilir. 101 | */ 102 | #[derive(Debug, Clone)] 103 | struct Player { 104 | name: String, 105 | level: u8, 106 | last_score: f32, 107 | } 108 | 109 | /* 110 | Display trait uygulandığı veri modelinin bir Formatter bileşeni 111 | ile çalışabilmesini sağlar. 112 | fmt fonksiyonundan write makrosu ile döndürülen içerik, 113 | örneğin println! makrosunda {} formasyonunda kullanılabilir. 114 | */ 115 | impl Display for Player { 116 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 117 | write!( 118 | f, 119 | "{}({}) last score is {}", 120 | self.name, self.level, self.last_score 121 | ) 122 | } 123 | } 124 | 125 | /* 126 | Aşağıdaki örnekte ise Velocity türünden değişkenlerin 127 | eşitlik operatörü ile kontrol edilebilmeleri için PartialEq 128 | trait'ini devralması söz konusudur. 129 | 130 | Velocity tamamen f32 değerlerinden oluştuğundan move yerine kopyalanarak 131 | taşıma özelliği de sağlayabilir. Bunun için Copy trait'ini devralması yeterlidir. 132 | */ 133 | #[derive(Debug, PartialEq, Copy, Clone)] 134 | struct Velocity { 135 | x: f32, 136 | y: f32, 137 | } 138 | 139 | // impl PartialEq for Velocity { 140 | // fn eq(&self, other: &Self) -> bool { 141 | // self.x == other.x && self.y == other.y 142 | // } 143 | //} 144 | 145 | /* 146 | Bazı durumlarda eşitlik kontrolü için veri modelinin tüm üyelerine bakılmaz. 147 | Bu gibi bir durumda PartialEq trait açıkça uygulanabilir. 148 | */ 149 | #[derive(Debug)] 150 | struct LogStamp { 151 | id: i32, 152 | time: String, 153 | content: String, 154 | } 155 | impl PartialEq for LogStamp { 156 | fn eq(&self, other: &Self) -> bool { 157 | self.id == other.id 158 | } 159 | } 160 | 161 | /* 162 | Bir veri yapısının default değerleri ile oluşturmak için 163 | Default trait kullanılabilir. derive edilebileceği gibi açıkça yazılabilir de. 164 | */ 165 | #[derive(Debug)] 166 | struct Game { 167 | fps: u8, 168 | title: String, 169 | screen_width: u32, 170 | screen_height: u32, 171 | } 172 | 173 | impl Default for Game { 174 | fn default() -> Self { 175 | Game { 176 | fps: 30, 177 | title: String::from("A Simple Game"), 178 | screen_width: 1280, 179 | screen_height: 960, 180 | } 181 | } 182 | } 183 | 184 | impl Display for Game { 185 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 186 | write!( 187 | f, 188 | "{}({}x{}) at {} fps", 189 | self.title, self.screen_width, self.screen_height, self.fps 190 | ) 191 | } 192 | } 193 | 194 | /* 195 | Popüler trait'lerden birisi de FromStr'dır. 196 | Bir String ifadeden dönüşütürme işlemini tariflememizi sağlar. 197 | 198 | FromStr trait Result dönen bir fonksiyon sağlar. Dolayısıyla Result 199 | değişkeninin Err tipi de programcı tarafından sağlanır. 200 | Aşağıdaki örnekte 125:100:100 gibi bir metinsel bir içerik geldiğinde 201 | Red Green Blue değerlerinin çekilmesi için bir uyarlama yapılmıştır. 202 | */ 203 | #[derive(Debug, Copy, Clone)] 204 | struct SystemColor { 205 | r: u8, 206 | g: u8, 207 | b: u8, 208 | } 209 | 210 | #[derive(Debug)] 211 | enum ColorParseError { 212 | WrongArgumentCount, 213 | ParseError(ParseIntError), 214 | } 215 | 216 | impl FromStr for SystemColor { 217 | type Err = ColorParseError; 218 | 219 | fn from_str(s: &str) -> Result { 220 | let parts: Vec<&str> = s.split(':').collect(); 221 | if parts.len() != 3 { 222 | return Err(ColorParseError::WrongArgumentCount); 223 | } 224 | 225 | let r = parts[0] 226 | .parse::() 227 | .map_err(ColorParseError::ParseError)?; 228 | let g = parts[1] 229 | .parse::() 230 | .map_err(ColorParseError::ParseError)?; 231 | let b = parts[2] 232 | .parse::() 233 | .map_err(ColorParseError::ParseError)?; 234 | 235 | Ok(SystemColor { r, g, b }) 236 | } 237 | } 238 | 239 | /* 240 | Drop trait. 241 | Bu trait bir değişken drop edileceği sırada yapılması istenenlerin 242 | gerçekleştirilebileceği bir fonksiyonellik sağlar. 243 | */ 244 | #[derive(Debug)] 245 | struct Service { 246 | title: String, 247 | address: String, 248 | } 249 | 250 | impl Service { 251 | fn call(&self) { 252 | println!("Service call"); 253 | } 254 | } 255 | 256 | impl Drop for Service { 257 | fn drop(&mut self) { 258 | println!("Closing temp connections and releasing resources."); 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /meth-leb/LICENSE_APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------