diff --git a/README.md b/README.md index 87857b1..ccc0d36 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,12 @@ Exploration a Rust Programming Language - (33 concepts) ## TYPES -// Todo +1. [Struct](./Rust_Concepts/src/struct.rs) +2. [Enum](./Rust_Concepts/src/enum.rs) +3. Option // TODO +4. Result (later) +5. Vec (later) +6. HashMap (later) ## CONTROL diff --git a/Rust_Concepts/Cargo.toml b/Rust_Concepts/Cargo.toml index 3e6ad26..c1c42ce 100644 --- a/Rust_Concepts/Cargo.toml +++ b/Rust_Concepts/Cargo.toml @@ -34,4 +34,15 @@ path = "src/clone.rs" # path to the source file [[bin]] name = "StackVSHeap" # the name you’ll use with --bin path = "src/stack_vs_heap.rs" # path to the source file -# cargo run --bin StackVSHeap \ No newline at end of file +# cargo run --bin StackVSHeap + +[[bin]] +name = "Struct" # the name you’ll use with --bin +path = "src/struct.rs" # path to the source file +# cargo run --bin Struct + + +[[bin]] +name = "Enum" # the name you’ll use with --bin +path = "src/enum.rs" # path to the source file +# cargo run --bin Enum \ No newline at end of file diff --git a/Rust_Concepts/src/enum.rs b/Rust_Concepts/src/enum.rs new file mode 100644 index 0000000..b7e4d08 --- /dev/null +++ b/Rust_Concepts/src/enum.rs @@ -0,0 +1,365 @@ +/* Rust Concepts: https://sociocyber.site/rust_concepts_v2.html + Concept: Enum (Lives in Stack) + + Usage: Create a Type with named variants. Match this for control flow, That variants optionaly can carry data. + P.S. "Variant" means just a text name, like "Red", "Green", "Yellow", "Ok", "Something", "Ball", "Earth",. + + Description: + + enum Name { + Variant1, + Variant2, + Variant3(type) <- data types: i32, u32, String and etc,. + } + + let some = Name::Variant1 +*/ + +#[derive(Debug)] +#[allow(dead_code)] // - ingore all warings about unused enum fields +enum Apple { + Red(String), + Yellow, // warning: variants `Red` and `Yellow` are never constructed + Green, +} + + +#[derive(Debug)] +#[allow(dead_code)] +enum GnuLinux { + Arch, + Kali, + Debian, + Trisquel, + Guix, + Windows(Release) +} + +#[derive(Debug)] +#[allow(dead_code)] // - ingore all warings about unused enum fields +enum Release { + // _Eleven, // '_' means this field not used, or add #[allow(dead_code)] derictive + Ten, + Seven +} + +#[derive(Debug)] +#[allow(dead_code)] +enum Partion { + Root, + Home, + Hard(u8), // Hard(1), Hard(2),. +} + +#[derive(Debug)] +#[allow(dead_code)] +enum Signal { + Red, + Yellow, + Green(u32), // carries seconds remaining; index = (2) +} + +#[derive(Debug)] +#[allow(dead_code)] +enum NetworkStatus { + NotFound = 404, + Ok = 200, + Forbiden = 500 +} + +fn main() { + // Create enum type + let apple1 = Apple::Green; + println!("I eating an apple with color {:?}", apple1); + + /* + + STACK + ┌─────────────────────────────┐ + │ apple1 │ + │ ┌───────────────────────┐ │ + │ │ Tag: Green (variant) │ │ + │ │ (discriminant = 2) │ │ + │ └───────────────────────┘ │ + │ Size: 1 byte (depends on │ + │ number of variants) │ + └─────────────────────────────┘ + + HEAP + (unused - enums are stack-allocated) + */ + + + + + // Create enum type with heap-data + let apple2 = Apple::Red( String::from("Fuji") ); // Fuji - saved in HEAP + println!("I eating an apple with color {:?}", apple2); + + /* + + STACK + ┌──────────────────────┐ + │ apple1 │ + │ ┌────────────────┐ │ + │ │ Tag: Red (0) │ │ + │ │ ptr: 0x1000 ───────────┐ + │ │ len: 4 │ │ │ + │ │ capacity: 4 │ │ │ + │ └────────────────┘ │ │ + └──────────────────────┘ │ + │ + ▼ + HEAP (Memory Address 0x1000) + ┌──────────────────────────────┐ + │ [F][u][j][i] │ + │ 0x1000 │ + │ (4 bytes allocated) │ + │ (capacity: 4 bytes) │ + └──────────────────────────────┘ + + */ + + + let signal = Signal::Green(200); + describe(signal); + + /* + + STACK + ┌────────────────────────────────┐ + │ signal │ + │ ┌──────────────────────────┐ │ + │ │ Tag: Green (2) │ │ (2) - means variant[index] + │ │ Data: 200 (u32) │ │ + │ │ (4 bytes) │ │ + │ └──────────────────────────┘ │ + └────────────────────────────────┘ + + HEAP + (unused - no heap allocation needed) + + */ + + + + + let status = NetworkStatus::Ok; + println!("Network status: {}", status as i32); // Recommendation for typed values like i32,. Still use Struct instead of Enum. + + + let my_operating_system = GnuLinux::Arch; // Arch Linux, we call new stack frame as "my_operating_system", We save a Tag (This Enum Type saved in STACK Frame as Tag: "Enum Name", with additional fields: len,. ), + // let my_operating_system = GnuLinux::Windows(Release::Ten); // windows 10 + + // Just call functions and todo something, as use can see with enums code can be simple to read. + // P.S. '&' in '&variable' to indicate of the variable is a reference = read a value (Enum Type in this case), without holding it. + describe_os(&my_operating_system); // share Tag + install_base_packagers(&my_operating_system); // share Tag + + format_disk(Partion::Root); // Create here and Share Tag (not variable defined for enum type) + format_disk(Partion::Home); + format_disk(Partion::Hard(1)); // Create here and Share Tag + number in here number saved in STACK, NOT in HEAP + format_disk(Partion::Hard(2)); + + install_base_packagers(&GnuLinux::Kali); + install_base_packagers(&GnuLinux::Trisquel); +} + + + + + + +// Functions - not worry about "match",. we'll explore control flow in later lessons +fn describe(s: Signal) { + match s { + Signal::Red => println!("Stop!"), + Signal::Yellow => println!("Slow down"), + Signal::Green(n) => println!("Go! {}s left", n), + } +} + +fn format_disk(part: Partion) { + println!("Formating as ext4: {:?}", part); +} + +fn install_base_packagers(os: &GnuLinux) { + println!("Install for {:?}", &os); + + match os { + GnuLinux::Arch => { + println!("pacman -Syu wayland blender krita") + }, + GnuLinux::Kali | GnuLinux::Debian | GnuLinux::Trisquel => { + println!("apt update -y && apt upgrade -y xorg kicad arduinoide") + }, + _ => println!("Noting") + } +} + +fn describe_os(os: &GnuLinux) { + match os { + GnuLinux::Arch => println!("I use Arch btw!"), + GnuLinux::Kali => println!("Yea i can hack you computer"), + GnuLinux::Debian => println!("Super stable, good choice!"), + GnuLinux::Trisquel => println!("GNU/Linux, easy-peasy, interface like windows, no terminals, without linux kernel BLOBS, only libre software!"), + GnuLinux::Guix => println!("GNU/Linux! Guix! Not easy for beggener, but.. Not systemd, not blobs, custom system config, sheme language for describe what packages you want install.,"), + _ => println!("Oh! Damn! You are use a Windows? Oh no.. crap. Now you can trash you computer OR.. re-install your OS.") + } +} + + + +// More examples of enums + +// enum Protocol { +// Tcp, +// Udp, +// Http, +// Https, +// Dns, +// Ftp, +// Ssh, +// } + +// #[derive(Debug)] +// enum Planets { +// Earth_Water, // Eeath, but you know,. oceans so much more than earth _/(00)\_ +// Moon, +// Other +// } + +// enum DataCollector { +// Sensors, +// Production, +// Resources +// } + +// enum DataBase { +// Redis, +// SQLite, +// PostgreSQL +// } + +// enum Data { +// SensorData, +// ProductionData, +// ResourceData(Resource), // takes Resource enum +// } + + +// enum Resource { +// // Metals and Metallic Elements +// Metal(String), + +// // Precious and Semi-Precious Stones +// PreciousStone(String), + +// // Rare Earth Elements +// RareEarthElement(String), + +// // Fossil Fuels +// FossilFuel(String), + +// // Nuclear and Radioactive Materials +// RadioactiveMaterial(String), + +// // Non-metallic Minerals +// Mineral(String), + +// // Gases +// Gas(String), + +// // Liquids +// Liquid(String), + +// // Soil and Earth Materials +// Soil(String), + +// // Organic Materials (Non-Food) +// OrganicMaterial(String), + +// // FOOD RESOURCES - Generic Categories +// Grain(String), +// Vegetable(String), +// Fruit(String), +// Protein(String), +// Dairy(String), +// Oil(String), +// Spice(String), +// Herb(String), +// Legume(String), +// NutOrSeed(String), +// Fungus(String), +// Algae(String), +// Sweetener(String), +// Beverage(String), +// } + +// enum ResourceHubApi { +// Url(String), +// } + +// enum Status { +// Online, +// Loading, +// ErrorCode(u16), +// } + +// enum System { +// SystemOnline, // means it's OK +// SystemError, +// SystemMessage(String), +// } + +// enum VoiceMessage { +// Greeting, +// Alert, +// Notifycation, +// Time, +// TimeReminder, +// TaskStart, +// TaskEnd, +// Instruction, +// } + +// enum Phone { +// Model(String) +// } + + +// Window + // MainView + // SideBar + // Topic1 + // SubMenu + // Item1 + // Item2 + // Topic2 + // SubMenu + // Item1 + // Item2 + +// enum Window { +// MainView, +// SideBar(SideBar), +// DataBar, +// StatusBar, +// StatusLine +// } + +// enum SideBar { +// Topic(String, SubMenu), +// } + +// enum SubMenu { +// Item(ItemData) +// } + +// enum ItemData { +// Title, +// Description, +// PreviewUrls(Vec), +// VideoUrls(Vec), +// BooksUrls(Vec), +// } \ No newline at end of file diff --git a/Rust_Concepts/src/main.rs b/Rust_Concepts/src/main.rs index d66f458..a773f28 100644 --- a/Rust_Concepts/src/main.rs +++ b/Rust_Concepts/src/main.rs @@ -1,3 +1,14 @@ +/* Rust Concepts: https://sociocyber.site/rust_concepts_v2.html + Concept: + + Usage: + + Description: + + Stack/Heap shemes +*/ + + fn main() { // to run examples use // cargo run --bin [Something] diff --git a/Rust_Concepts/src/struct.rs b/Rust_Concepts/src/struct.rs new file mode 100644 index 0000000..27f7477 --- /dev/null +++ b/Rust_Concepts/src/struct.rs @@ -0,0 +1,224 @@ +/* Rust Concepts: https://sociocyber.site/rust_concepts_v2.html + Concept: Struct + Usage: Create new Data Type; + + + What struct means? + Group of data types, with one name.( Save data in one thing,. ) + + stuct Name { + field1: Type, (i32, u32, String, &[], ...) + field2: Type, + field3: Type, + field4: Type, + } + + + * Use String::from() for clarity (more common in structs) [Fast] + * Not use .to_string() for structs. + ** Use .to_string() when converting other types only: let number = "134".to_string() + + P.S. '_' in '_variable' means = hide compiler warnings: unused variable + + * later in lessons -> add methods for struct's data, add implimentation, constructor, impl traits, tuple structs, unit structs (no fields, used for traits) + nested structs, with generics, builder pattern +*/ + +#[derive(Debug)] // Don't worry about this compiler-derictive, In later lessons we'll explore what this means. +struct Book { + name: String, + count: u32, + price: u32, +} + +fn main() { + // How create? + let harry_poter = Book { + // name: "Harry Poter".to_string(), // not use .to_string() in structs can be slow! + name: String::from("Harry Poter"), + count: 10, + price: 200, + }; + + /* + + STACK (and his frames) [CPU] HEAP [MEM] + ───────────────────────────────────── ────────────────────────── + frame: main() ┌────────────────────────┐ + ┌───────────────────────────────────┐ │ "Harry Poter" │ + │ harry_potter : Book │ │ 12 bytes, UTF-8 │ + │ ┌─────────────────────────────┐ │ │ [H][a][r][r][y][ ]... │ + │ │ name : String │ │ owns │ [P][o][t][e][r] │ + │ │ ┌─────────────────────────┐ │ │ ────────► │ │ + │ │ │ ptr │ │ │ │ dropped when │ + │ │ │ len = 12 │ │ │ │ Book drops │ + │ │ │ cap = 12 │ │ │ └────────────────────────┘ + │ │ │ [ 3 × usize on stack ] │ │ │ + │ │ └─────────────────────────┘ │ │ + │ └─────────────────────────────┘ │ + │ │ + │ ┌─────────────────────────────┐ │ + │ │ count : u32 = 10 │ │ (no heap — u32 fits + │ └─────────────────────────────┘ │ directly on stack) + │ │ + │ ┌─────────────────────────────┐ │ + │ │ price : u32 = 200 │ │ + │ └─────────────────────────────┘ │ + └───────────────────────────────────┘ + + STACK — frame: main() + ─────────────────────────────────────────────── + address field bytes + ─────────────────────────────────────────────── + 0x00 name.ptr 8 (pointer to heap) + 0x08 name.len 8 + 0x10 name.cap 8 + 0x18 count 4 (u32) + 0x1C price 4 (u32) + ─────────────────────────────────────────────── + total: 32 bytes + + */ + + + let one_in_space = Book { + name: String::from("Disteller: One in Space"), + count: 1, + price: 250, + }; + // let books_in_shop: [Book; 2] = [Book{name: "Harry Poter".to_string(), count: 1, price: 200}, Book{name: "s".to_string(), count: 2, price: 300}]; + + // What if i need change a variables in struct when saved in array? + // Make array mutable ( add "mut" ) + let mut books_in_shop: [Book; 2] = [harry_poter, one_in_space]; + + /* + STACK (and his frames) [CPU] HEAP [MEM] + ────────────────────────────────────────── ────────────────────────── + frame: main() + ┌──────────────────────────────────────┐ + │ books_in_shop : [Book; 2] │ + │ │ + │ [0] harry_potter │ + │ ┌────────────────────────────────┐ │ ┌────────────────────────┐ + │ │ name : String │ │ │ "Harry Poter" │ + │ │ ┌──────────────────────────┐ │ │ owns │ 12 bytes, UTF-8 │ + │ │ │ ptr │ │ │ ──────────► │ [H][a][r][r][y][ ]... │ + │ │ │ len = 12 │ │ │ │ [P][o][t][e][r] │ + │ │ │ cap = 12 │ │ │ └────────────────────────┘ + │ │ └──────────────────────────┘ │ │ + │ └────────────────────────────────┘ │ + │ ┌────────────────────────────────┐ │ (separate heap alloc) + │ │ count : u32 = 10 │ │ + │ └────────────────────────────────┘ │ + │ ┌────────────────────────────────┐ │ + │ │ price : u32 = 200 │ │ + │ └────────────────────────────────┘ │ + │ │ + │ [1] one_in_space │ + │ ┌────────────────────────────────┐ │ ┌────────────────────────┐ + │ │ name : String │ │ │ "One in Space" │ + │ │ ┌──────────────────────────┐ │ │ owns │ 12 bytes, UTF-8 │ + │ │ │ ptr │ │ │ ──────────► │ [O][n][e][ ][i][n]... │ + │ │ │ len = 12 │ │ │ │ [S][p][a][c][e] │ + │ │ │ cap = 12 │ │ │ └────────────────────────┘ + │ │ └──────────────────────────┘ │ │ + │ └────────────────────────────────┘ │ + │ ┌────────────────────────────────┐ │ + │ │ count : u32 = 1 │ │ + │ └────────────────────────────────┘ │ + │ ┌────────────────────────────────┐ │ + │ │ price : u32 = 999 │ │ + │ └────────────────────────────────┘ │ + │ │ + │ [Book; 2] = 64 bytes flat on stack │ + │ 2 separate heap allocs for String │ + └──────────────────────────────────────┘ + + + + STACK — frame: main() + ───────────────────────────────────────────────── + address field bytes + ───────────────────────────────────────────────── + rbp - 64 books_in_shop[0].name.ptr 8 + rbp - 56 books_in_shop[0].name.len 8 + rbp - 48 books_in_shop[0].name.cap 8 + rbp - 40 books_in_shop[0].count 4 + rbp - 36 books_in_shop[0].price 4 + ───────────────────────────────────────────────── + rbp - 32 books_in_shop[1].name.ptr 8 + rbp - 24 books_in_shop[1].name.len 8 + rbp - 16 books_in_shop[1].name.cap 8 + rbp - 8 books_in_shop[1].count 4 + rbp - 4 books_in_shop[1].price 4 + ───────────────────────────────────────────────── + total: 64 bytes + + + what is max STACK size? + + Depends on OS and how the thread was created. + + OS / context default stack size + ────────────────────────────────────────────── + Linux 8 MB + Windows 1 MB + macOS 8 MB (main thread) + 512 KB (other threads) + ────────────────────────────────────────────── + Rust main thread inherits OS default + Rust spawned thread 2 MB (Rust sets this) + embedded / no_std you set it manually + often 4–64 KB + ────────────────────────────────────────────── + + If you exceed it → stack overflow → program crashes. + + let big: [u8; 10_000_000] = [0; 10_000_000]; // 10 MB → boom + + + // fix — put it on heap + let big: Vec = vec![0; 10_000_000]; // ok, all data saved in HEAP [MEM], in STACK save only pointer to data + + + You can change stack size for spawned threads: + std::thread::Builder::new() + .stack_size(16 * 1024 * 1024) // 16 MB + .spawn(|| { ... }); + + */ + + // How print? + println!("Book: {}", books_in_shop[0].name); + println!("Count: {}", books_in_shop[0].count); + println!("Price: {}", books_in_shop[0].price); + println!("------------------"); + println!("Book: {}", books_in_shop[1].name); + println!("Count: {}", books_in_shop[1].count); + println!("Price: {}", books_in_shop[1].price); + + println!("------------------"); + println!("UPDATE"); + + // How chage fields (variables) in struct? + books_in_shop[0].name = String::from("Genry Proper"); + books_in_shop[0].count = 3000; + books_in_shop[0].price = 50; + + println!("Book: {}", books_in_shop[0].name); + println!("Count: {}", books_in_shop[0].count); + println!("Price: {}", books_in_shop[0].price); + + + // What if i need change a variables in struct (when struct not in array)? + // Make struct mutable. + // Add "mut" + let mut mutable_book = Book { + name: String::from("Harry You are."), + count: 1, + price: 250, + }; + mutable_book.name = String::from("Genry Potato"); + println!("Mutable Book: {}", mutable_book.name); +} \ No newline at end of file