first commit

This commit is contained in:
SocioCyber
2026-04-04 08:00:20 -07:00
commit cea5051c23
8 changed files with 346 additions and 0 deletions

1
Rust_Concepts/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

7
Rust_Concepts/Cargo.lock generated Normal file
View File

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

22
Rust_Concepts/Cargo.toml Normal file
View File

@@ -0,0 +1,22 @@
[package]
name = "Concepts"
version = "0.1.0"
edition = "2024"
[dependencies]
[[bin]]
name = "Ownership" # the name youll use with --bin
path = "src/ownership.rs" # path to the source file
# cargo run --bin Ownership
[[bin]]
name = "Borrowing" # the name youll use with --bin
path = "src/borrowing.rs" # path to the source file
# cargo run --bin Borrowing
[[bin]]
name = "MutBorrowing" # the name youll use with --bin
path = "src/mutable_borrow.rs" # path to the source file
# cargo run --bin MutBorrowing

View File

@@ -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 youre done,
you have to give it back. You dont 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);
}

View File

@@ -0,0 +1,3 @@
fn main() {
}

View File

@@ -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 youre done,
you have to give it back. You dont 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"
}

View File

@@ -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 <moved> // not can be used,
stack-slots2 stack-slots1
owner2 (on stack) owner1 (on stack)
+-------------------+ +-----------------------+
| ptr → heap "hello"| | <ptr moved / invalid> |
| len = 5 | + <len moved / invalid> +
| cap = 5 | | <cap moved / invalid> |
+-------------------+ +-----------------------+
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 doesnt need to free anything when owner1 goes out of scope.