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 |
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 |
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 |
--------------------------------------------------------------------------------