From cea5051c23cc84b053f63f392bba20568f1d55b2 Mon Sep 17 00:00:00 2001 From: SocioCyber Date: Sat, 4 Apr 2026 08:00:20 -0700 Subject: [PATCH] first commit --- README.md | 4 + Rust_Concepts/.gitignore | 1 + Rust_Concepts/Cargo.lock | 7 ++ Rust_Concepts/Cargo.toml | 22 +++++ Rust_Concepts/src/borrowing.rs | 129 ++++++++++++++++++++++++++++ Rust_Concepts/src/main.rs | 3 + Rust_Concepts/src/mutable_borrow.rs | 98 +++++++++++++++++++++ Rust_Concepts/src/ownership.rs | 82 ++++++++++++++++++ 8 files changed, 346 insertions(+) create mode 100644 README.md create mode 100644 Rust_Concepts/.gitignore create mode 100644 Rust_Concepts/Cargo.lock create mode 100644 Rust_Concepts/Cargo.toml create mode 100644 Rust_Concepts/src/borrowing.rs create mode 100644 Rust_Concepts/src/main.rs create mode 100644 Rust_Concepts/src/mutable_borrow.rs create mode 100644 Rust_Concepts/src/ownership.rs diff --git a/README.md b/README.md new file mode 100644 index 0000000..ee7ac53 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# Learning + +Exploration a Rust Programming Language - (33 concepts) +And ETC. \ No newline at end of file diff --git a/Rust_Concepts/.gitignore b/Rust_Concepts/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/Rust_Concepts/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Rust_Concepts/Cargo.lock b/Rust_Concepts/Cargo.lock new file mode 100644 index 0000000..13817d5 --- /dev/null +++ b/Rust_Concepts/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "Concepts" +version = "0.1.0" diff --git a/Rust_Concepts/Cargo.toml b/Rust_Concepts/Cargo.toml new file mode 100644 index 0000000..8a4da07 --- /dev/null +++ b/Rust_Concepts/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "Concepts" +version = "0.1.0" +edition = "2024" + +[dependencies] + +[[bin]] +name = "Ownership" # the name you’ll use with --bin +path = "src/ownership.rs" # path to the source file +# cargo run --bin Ownership + +[[bin]] +name = "Borrowing" # the name you’ll use with --bin +path = "src/borrowing.rs" # path to the source file +# cargo run --bin Borrowing + + +[[bin]] +name = "MutBorrowing" # the name you’ll use with --bin +path = "src/mutable_borrow.rs" # path to the source file +# cargo run --bin MutBorrowing \ No newline at end of file diff --git a/Rust_Concepts/src/borrowing.rs b/Rust_Concepts/src/borrowing.rs new file mode 100644 index 0000000..af82f88 --- /dev/null +++ b/Rust_Concepts/src/borrowing.rs @@ -0,0 +1,129 @@ +/* Rust Concepts: https://sociocyber.site/rust_concepts_v2.html + Concept: Borrowing (shared &) + Usage: read a value, without holding it. + + --- + We call the action of creating a reference borrowing. + As in real life, if a person owns something, + you can borrow it from them. When you’re done, + you have to give it back. You don’t own it. + + Ampersands '&' represent references, + and they allow you to refer to some value + without taking ownership of it. + + & to indicate of the parameter X is a reference. + --- + + + Owner1 in this context means who (stack frame) hold a data in heap [MEM area] + + Value can be shared to someone. + & (reference) means = i want share this variable-value to someone + + We can reference to a variable for get,read his value. + One variable can have many who want get his value. + + MANY readers and ONE value. + Many & (references) to somethings. + (many &refs allowed simultaneously) + + We can NOT change reference. + We can NOT change value when want to read this. + & (reference) = not changeble, only readable + + &owner1 means = reference to a variable for get his value. + + STACK (and his frames) [CPU] HEAP [MEM] + ────────────────────────────────── ────────────────────── + frame: main() ┌────────────────────┐ + ┌──────────────────────────────┐ │ "Borrowing Value" │ + │ owner1 : String │ owns │ 15 bytes, UTF-8 │ + │ ┌──────────────────────────┐ │ ─────────► │ [B][o][r][r][o]... │ + │ │ ptr │ │ └────────────────────┘ + │ │ len = 15 │ │ + │ │ cap = 15 │ │ + │ └──────────────────────────┘ │ + └──────────────────────────────┘ + + frame: print_len( &owner1 ) + ┌──────────────────────────────┐ + │ s : &String (borrow) │ + │ ┌──────────────────────────┐ │ + │ │ ptr ──► owner1 │ │ (read-only, no copy) + │ └──────────────────────────┘ │ + └──────────────────────────────┘ + │ + └─► borrow ends when print_len() returns + + frame: println!("{}", owner1) + ┌──────────────────────────────┐ + │ owner1 still valid │ + │ println! auto-borrows &owner1│ + │ no & needed in code │ + └──────────────────────────────┘ +*/ + + +/* Arguments in functions creates a new stack frame + with pointer2 --> pointer1 --> Heap first address of "v a l u e" + + Like it: add_word(arg1: &String) + &arg1 - new ptr -> ptr -> value +*/ +fn print_len(string: &String) { // borrows + println!("{}", string.len()); // Read reference (de-reference for get value) ptr2(&owner1) => get ptr1 (owner1) => read heap +} + +fn main() { + let owner1 = String::from("Borrowing Value"); + // change_value(&owner1); // Not allowed! We can't change value only READ. + + print_len(&owner1); // borrowing, not ownership. Not change address in stack-slot for ptr (-> heap), make new ptr in stack (in new frame [ptr ──► owner1]) + // ptr2 (reference1) -> ptr1 (owner1) -> heap ["Borrowing Value"] + // ptr2 (reference2) -> ptr1 (owner1) -> heap ["Borrowing Value"] + // ptr2 (reference3) -> ptr1 (owner1) -> heap ["Borrowing Value"] + // ptr2 (&owner1) -> ptr1 (owner1) -> heap ["Borrowing Value"] + + println!("(Borrowing) {}", owner1); // not need reference. Why? + /* + STACK HEAP + ────────────────────────────────── ────────────────────── + frame: main() ┌────────────────────┐ + ┌──────────────────────────────┐ │ "Borrowing Value" │ + │ owner1 : String │ owns │ 15 bytes, UTF-8 │ + │ ┌──────────────────────────┐ │ ─────────► │ [B][o][r][r][o]... │ + │ │ ptr │ │ └────────────────────┘ + │ │ len = 15 │ │ + │ │ cap = 15 │ │ + │ └──────────────────────────┘ │ + │ │ + │ reference1 : &String │ + │ ┌──────────────────────────┐ │ + │ │ ptr ──► owner1 (above) │ │ <── new slot in same frame + │ └──────────────────────────┘ │ + └──────────────────────────────┘ + + frame: print_len( reference1 ) + ┌──────────────────────────────┐ + │ s : &String (borrow) │ + │ ┌──────────────────────────┐ │ + │ │ ptr ──► reference1 │ │ (copy of the pointer, same address) + │ └──────────────────────────┘ │ + └──────────────────────────────┘ + │ + └─► borrow ends when print_len() returns + reference1 still valid in main() + owner1 still valid in main() + + */ + + let reference1 = &owner1; // save in new stack's slot in main frame a ptr to owner1 + // let reference2 = &owner1; + // let reference3 = &owner1; + + print_len(reference1); + // print_len(reference2); + // print_len(reference3); + +} \ No newline at end of file diff --git a/Rust_Concepts/src/main.rs b/Rust_Concepts/src/main.rs new file mode 100644 index 0000000..2a778e4 --- /dev/null +++ b/Rust_Concepts/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + +} diff --git a/Rust_Concepts/src/mutable_borrow.rs b/Rust_Concepts/src/mutable_borrow.rs new file mode 100644 index 0000000..2a72844 --- /dev/null +++ b/Rust_Concepts/src/mutable_borrow.rs @@ -0,0 +1,98 @@ +/* Rust Concepts: https://sociocyber.site/rust_concepts_v2.html + Concept: Mutable Borrow (&mut) + Usage: change a value, without holding it. + + --- + We call the action of creating a reference borrowing. + As in real life, if a person owns something, + you can borrow it from them. When you’re done, + you have to give it back. You don’t own it. + + Ampersands '&' represent references, + and they allow you to refer to some value + without taking ownership of it. + + & to indicate of the parameter X is a reference. + --- + + For short: + [Only one Reference] (&mut) --> (mut) [varaiable] + ONLY Reference1 can modify mutable-variable1, not others refrences-N. + ONLY ONE MUTABLE reference1 (&mut) ---> heap + + + What this means? + We can define mutable variable. + And.. ONLY ONE reference for this mutable variable. + Not two, not three, etc, ONLY ONE reference for ONE mut variable + + We use this one reference to modify a varible value + For this we need: + 1. Mutable variable - let mut var_name = value + 2. Reference to mutable variable - type: &mut + + So, How to crate a reference for mutable variable? + + 1. Use type "mut" for variable. + + ### let mut variable = String::from("Value"); + + 2. In expressions(in function calls, when save into new variable) + + ### Use a type "&mut". + + This means a reference for mutable variable => i can change a value. + let reference = &mut variable; <-- use "&mut [variable_name]". + + + P.S. Never write a "mut &variable" => uncorrect! compile errors! + + For function calls as argument: + - add_word(&mut var_name); + + If we want describe reference type of mutable variable + in variables definitions, function calls,. + + Then use this syntax: + + 1. let reference: &mut [TYPE] * let model: &mut String = ... ... ; + 2. function(argument1: &mut [TYPE]) * do_some_thing_with_value(&mut value); + +*/ + + + +/* Arguments in functions creates a new stack frame with + pointer2 --> pointer1 --> Heap first address of "v a l u e" + + Like it: add_word(arg1: &String) + &arg1 - new ptr -> ptr -> value +*/ + +fn add_word(first_word: &mut String, second_word: &mut String) { + first_word.push_str(" "); + first_word.push_str(second_word); +} + +fn main() { + let mut arg1 = String::from("Notebook"); // mutable variable, holds a value in heap + let mut arg2 = String::from("Model"); + let mut arg3 = String::from("1012"); + + // symbol '_' in '_reference1' means = disable compiler warnings for unusable variables now + let _reference1: &mut String = &mut arg1; // Mutable Borrowing + let _reference2: &mut String = &mut arg2; // Reference to mutable variable + + // We can create reference for mutable (mut) variable and put into functions + // add_word(reference1, reference2); + + // We can use this syntax too. + // "&mut arg1",. means a reference for mutable (mut) variable + add_word(&mut arg1, &mut arg2); + add_word(&mut arg1, &mut arg3); + + // let _reference3: &mut String = &arg1; // ❌ can't borrow immutably while mut borrow active (but if type not setted, compile automaticaly set _reference3 as &mut) + // println!("{}", _reference3); // expected mutable reference `&mut String` but found reference `&String` + + println!("{}", arg1); // "Notebook Model 1012" +} \ No newline at end of file diff --git a/Rust_Concepts/src/ownership.rs b/Rust_Concepts/src/ownership.rs new file mode 100644 index 0000000..b7be688 --- /dev/null +++ b/Rust_Concepts/src/ownership.rs @@ -0,0 +1,82 @@ +/* Rust Concepts: https://sociocyber.site/rust_concepts_v2.html + Concept: Ownership + + One value = One owner + owner means -> who have something + + Ownership means moves ptr1's address into ptr2 (this happens in stack) + Moving structs from [stack-slots1] into [stack-slots2] + + ptr - pointer (similar to pointer in C/C++) + + Variable(owner) saved in scope, when runtime out of scope, + then the value is freed automaticly from MEM. (no garbage collector) + In rust garbage collector is not used. Borrwing & prevent + +┌─────────────────────┐ ┌─────────────────────┐ +│ Stack – owner1 │ │ Stack – owner2 │ +│ (before move) │ │ (after move) │ +│ │ │ │ +│ +----------------+ │ │ +----------------+ │ +│ | ptr → heap "V" | │ move → │ | ptr → heap "V" | │ +│ | len = 5 | │ │ | len = 5 | │ +│ | cap = 5 | │ │ | cap = 5 | │ +│ +----------------+ │ │ +----------------+ │ +└─────────────────────┘ └─────────────────────┘ + +Heap (single allocation) +┌───────────────────────────────────────┐ +│ 0xABCDEF00: V a l u e … │ +└───────────────────────────────────────┘ + + + +Scope ends → drop(owner2) → memory freed + +Heap (single allocation - out of scope) +┌───────────────────────────────────────┐ +│ 0xABCDEF00: … │ +└───────────────────────────────────────┘ +*/ + + +fn main() { + let owner1 = String::from("Value"); // ? save "Value" in heap, stack (owner1) → ptr → heap "hello" + /* + stack-slots1 + +-------------------+ ← lower address (stack grows down) + | ptr → heap "hello"| ← 8 bytes + | len = 5 | ← 8 bytes + | cap = 5 | ← 8 bytes + +-------------------+ ← higher address + + heap address (ptr) → [ 'h' 'e' 'l' 'l' 'o' ] + */ + + let owner2 = owner1; // owershipped! owner1 moves (ship) his value into owner1. stack (owner2) → ptr (getted from owner1) → heap "hello" + + /* + stack slot (owner2) ──► ptr → heap "hello" + stack slot (owner1) ──► ptr // not can be used, + + stack-slots2 stack-slots1 + owner2 (on stack) owner1 (on stack) + +-------------------+ +-----------------------+ + | ptr → heap "hello"| | | + | len = 5 | + + + | cap = 5 | | | + +-------------------+ +-----------------------+ + + heap address (ptr) → None (not valid) + */ + + // println!("{}", owner1); // owner1 no longer valid, not ptr. (Compiler thinks this about as 'None') + // Not actual address for heap, where value + + println!("(Ownership) owner1 -> owner2; owner2 = {}", owner2); +} // owner2 Out of the scope, drops owner2 for free a heap + + +// When owner2 and owner1 go out of scope, they will both try to free the same memory. This is known as a double free error and is one of the memory safety bugs we mentioned previously. Freeing memory twice can lead to memory corruption, which can potentially lead to security vulnerabilities. +// To ensure memory safety, after the line let owner2 = owner1;, Rust considers owner1 as no longer valid. +// Therefore, Rust doesn’t need to free anything when owner1 goes out of scope. \ No newline at end of file