Introduction
Welcome to my little notes page for random notes.
This is just a mdbook of random notes that I may update if needed, for now it is intentionally minimal. (Credit to mdBook folks for awesome tool!)
Thanks for visiting, and please dont forget to support your community and donate to organizations like pancan (to help those sick with pancreatic cancer).
Thanks kindly!
Misc (How to edit the mdbook!)
- Run command:
cargo install mdbook && mdbook serveto generate ./book HTMLs. - Edit/Add Notes into Markdown Files in ./src ONLY WHILE
mdbook serveIS RUNNING!!!!! - Then re-order left side links, via SUMMARY.md or book.toml, and it will update left menu bar in real time, and create new md files in the menu bar.
- Now, mdbook serve, should have updated the searchindex.js based on your markdown edits etc, so ctrl+c to close mdbook, and git commit em up!
Keyboard Shortcuts ⌨️
Anyone who knows me, knows I love webapps that fully support keyboard shortcuts. This book does so! Try typing the / character for example :P
| Shortcut | Action | Notes |
|---|---|---|
| ← (Arrow Left) | Go to previous chapter/page | Fast navigation |
| → (Arrow Right) | Go to next chapter/page | Fast navigation |
| S or / | Open search bar | Instantly search chapters |
| ? | Open shortcuts/help menu | Shows all shortcuts |
| Esc | Close help/search/menus | Quick exit from overlays |
| Ctrl + Enter | Run code block (if focused on interactive sample) | For interactive Rust playgrounds |
🕸️ webdev
Here are some of my favorite go-to websites for learning, referencing, and improving at modern web development.
I've added notes so I remember what each is best for.
📚 Learning & Documentation
-
MDN Web Docs — The holy grail of web dev references!!!!!!!!!! ALWAYS USE THI, i just type mdn.io in the browser too and it works well just like docs.rs essentially as a BROWSER URL. Official specs, browser compatibility tables, and detailed documentation for HTML, CSS, JS, APIs, and more.
-
The Modern JavaScript Tutorial — Start from scratch and master JavaScript, from fundamentals to advanced concepts like OOP, the DOM, and events.
🎨 Design & Assets
-
Favicon.io — Generate favicons from text, images, or emojis for your projects. Fast and free.
-
CSS-Tricks — Articles, tips, and guides covering everything from layout techniques to animations.
-
Frontend Mentor — Practice front-end skills by building real projects from design files.
🛠️ Tools & Playgrounds
-
CodePen — Live HTML, CSS, JS sandbox for quick prototyping and sharing.
-
JSFiddle — Another quick JS/CSS/HTML test environment.
-
Can I use — Check browser support for web features.
💡 Tip: Bookmark these, and keep your toolbox handy — having quick access to docs and tools saves hours every week. Really helpful DEFINITELY!
Google Fonts (Regular Best Way)
To use Google Fonts is...
- navigate to fonts.google.com
- pick a font
- click get code
- copy the header code into the
<head> - apply the
classto the html attribute you want, and look at the url to match the name as a font-family.
Google Fonts Helper Webpage (Alternative, easier)
To use the non-official "Google Webfonts Helper" webpage for self-hosting Google Fonts, follow these steps:
- Visit the unofficial helper at
gwfh.mranftl.com - Search for the Google Font you want.
- Choose the character sets (Latin, Cyrillic, etc.) and select the font weights/styles you need (such as regular, bold, italic).
- After choosing your styles and browser support level, click “Download” to get a ZIP of the font files (WOFF2, WOFF, etc.).
- Extract and upload these font files to your web host or server, just as you would with other site assets (images, CSS, etc.).
- Copy the CSS generated by the tool (provided on the website after you select your fonts).
- Adjust the
url()paths in the@font-facestatements to match your file locations. - Paste this code in a CSS file that is loaded by your site.
- Use standard CSS to apply your font, e.g.:
body { font-family: 'Your Font Name', sans-serif; }
I think thats about it!
🦀 rustdev 🦀
These are little cool things I found on my Rust journey. Imho these are best-in-class tutorials, frameworks, and community-curated guides.
BEST COMMAND TO LEARN: rustup doc --book
🎓 Rust Language Learning
- The Rust Programming Language ("The Book")
- Actix Web This is cool, pair it with Tera... you got yourself a flask+jinja thing.
- Axum Made by Tokio... looks cool
- Leptos
Minimalist and intuitive – good for beginners or hobby projects wanting a quick start. Seems Reactish, really cool. But still need to study Typescript regardless.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@
From this course:
rust_my_notes.md Using my rust Udemy Course: Master the rust programmlanguage A-Z https://lmrms.udemy.com/course/learn-to-code-with-rust/learn/lecture/46619855#overview
Import another func from a file (from inside main.rs, with ./poop.rs in samedir)
mod poop; // from inside main.rs, tell rust about other mod use poop::Poop; // Import my other pub Poop "type" or "struct"
Type Alias
Type Alias in Rust means just a alias:
#![allow(unused)] fn main() { type Bits = u32; let myI32 : Bits = 32; let myf64 : Bits = 64; }
Compiler DirectivesD
Compiler Directive applies to A SINGLE LINE or block:
#[allow(unused_variables)] fn blah () {} #![allow(unused_variables)] fn main(){} fn blah(){} etc... // #![] is for the whole file
isize/usize = are nicknames for built in types depending on computer
To basically let it pick a u8 or u16 if you have big compooter... let x: u64 = 15_000_000; // Btw, _'s are ignored, this is 15 million. let y: usize = 15_000_000; // See how it is usize? the compoooter will pik it.
rust raw string to ignore all backslashes
lets x = r"blah blah C:\blah no new line \n haha!";
println format specifier
Customize the printed representation of the interpolated value. let x: i32 = 50.13515212; pln("{x:.2}"); // only 2 decidimal places
cast a i32 to i8
let my32: i32 = 50; let my8: i8 = my32 as i8; // "as i8" is the cast! BTW, can overflow to 255.
basic_rust_notes.md
Random notes...
cargo doc --open ---- this will open only the manpages of your current git project
Ownership BTW ONLY 0 MUTABLE REF to mem is allowed.md
Ownership Transfer to Functions for Heap stuff like string, but not ints.rs
reference is like a pointer but always guaranteed to point to valid memory
SemVer means Semantic versioning like rand -1.8.5.txt
unwrap() is same as expect() but wo msg
02_borrow_only_once.md
fn main() { let mut s = String::from("hello"); let r0 = &s; // no problem let r1 = &s; // no problem println!("{r0} and {r2}"); println!("{r0} and {r2}"); // Variables r0 and r2 will not be used after this point. let r2 = &mut s; // no problem println!("{r2}"); let r3 = &s; // no problem println!("{r3}"); println!("{r0} and {r2}"); //CANT USE BECAUSE ONCE YOU MAKE A MUT REF, IT CLOSD THE SCOPE OF ALL //PREVIOUS REFS SO NOW YOU NEED TO MAKE A NEW REF MOVING FORWARD!!!!! }
celc_to_fahr.rs
use rand::Rng; fn main() { println!("enter celcius..."); let mut target = String::new(); std::io::stdin().read_line(&mut target).expect("io error"); let target: f32 = target.trim().parse().expect("cant convert to FARENHEIGHT!"); let faren = (target * 9.0 / 5.0) + 32.0; println!("Ok in FARENHEIGHT it is... {faren}"); }
encode_a_msg.rs
#![allow(unused)] fn main() { // This was a cool example from https://doc.rust-lang.org/std/iter/trait.Iterator.html let chars = ['g', 'd', 'k', 'k', 'n']; let hello: String = chars.into_iter() .map(|x| x as u8) .map(|x| (x + 1) as char) .collect(); assert_eq!("hello", hello); }
if_let.rs
In rust you can do if condition
fn main() { let condition = true; let condition = false; let condition = 12414214 + 2412; // Bad b/c IFLET needs a BOOL! let number = if condition { 5 } else { 6 }; println!("The value of number is: {number}"); }
Or...
fn main() { let letter: Option<i32> = None; if let Some(i) = letter { println!("Matched {:?}!", i); } else { println!("No number, using letter instead!"); // This runs } }
Or with a ENUM!!!!!!
#[derive(Debug)] enum Foo { Bar, Baz, Qux(u32), } fn main() { let c = Foo::Qux(100); if let Foo::Qux(value) = c { println!("c is {}", value); // Outputs: c is 100 } }
hashmap_to_count_word_occurences.rs
NOTE The bottom of this file has a really good hashmap with vector in it example!!!
Basically a hashmap is a key and value hash table.
The keys are unique, and the rust stdlib is pretty aweseome!!!
Check out this simple prompter app, you give it a sentence and it counts the words... (randomly each time, b/c the HashMap is using Quadratic Probing and SIMD lookup stuff). Really cool stdlib source code! See: https://doc.rust-lang.org/std/collections/struct.HashMap.html.
Here is my example, really good practice with my favorite std::io::stdin()
fn main() { println!("give me a sentence, ill count the words"); let mut buf = String::new(); std::io::stdin().read_line(&mut buf).expect("read error"); let mut hash01 = std::collections::HashMap::new(); for word in buf.split_whitespace() { // check this out, its cool. * is basically a C++ pointer! *hash01.entry(word).or_insert(0) += 1; } println!("ok word count is... {:#?}", hash01); }
For fun, in python this woulda beeen...
sentence = "apple banana apple cherry banana apple"
word_counts = {}
for word in sentence.split():
word_counts[word] = word_counts.get(word, 0) + 1
IMPORTANT: The book had this excersize at the end of chapter 8, and its really good to do over and over to practice...
Using a hash map and vectors, create a text interface to allow a user to add employee names to a department in a company; for example, “Add Sally to Engineering” or “Add Amir to Sales.” Then, let the user retrieve a list of all people in a department or all people in the company by department, sorted alphabetically.
Example code that needs to be refactored, but at least works:
#[allow(unused_variables)] use std::collections::HashMap; fn main() { println!("This app will create a hashmap... Get ready!"); let mut hashmap01 : HashMap<String, Vec<String>> = HashMap::new(); let mut buf = String::new(); loop { println!( r#" Main Menu: 1. Add Employee to a Department 2. Print the Hash 3. Print empl in a specific dept... 4. Exit "# ); std::io::stdin().read_line(&mut buf).expect("read errorrr"); let choice: u8 = buf.trim().parse().expect("parse errrorr.."); match choice { 1 => { add_to_hashmap(&mut hashmap01) }, 2 => { dbg!(&hashmap01); }, 3 => { print_emp_from_selected_dept(&mut hashmap01); }, _ => { println!("try again... ")}, } buf.clear(); } } fn print_emp_from_selected_dept(hashmap01 : &mut HashMap<String,Vec<String>>) { let mut buf = String::new(); println!("Enter a department..."); std::io::stdin().read_line(&mut buf).expect("coudlnt read dept.."); let dept = buf.trim(); match hashmap01.get(dept) { Some(names) => { println!("found these people..."); println!("{names:?}"); }, None => { println!("no people found"); } } } fn add_to_hashmap (hashmap01 : &mut HashMap<String,Vec<String>> ) { let mut buf = String::new(); println!("enter dept..."); std::io::stdin().read_line(&mut buf).expect("couldnt read dept"); let dept = buf.clone(); buf.clear(); println!("enter name..."); std::io::stdin().read_line(&mut buf).expect("couldnt read name"); let name = buf.clone().trim().to_string(); match hashmap01.get(&dept.trim().to_string()) { Some(names) => { let mut new_names = names.clone(); new_names.push(name); hashmap01.insert(dept.trim().to_string(), new_names); } None => { let mut new_names = Vec::new(); new_names.push(name); hashmap01.insert(dept.trim().to_string(), new_names); }, } }
This comment can be uncommented to get both the slice or heap String version!
fn main() { println!("Enter a sentence, and ill tell you longest word..."); let mut io_buf = String::new(); std::io::stdin().read_line(&mut io_buf).expect("io error"); //let test = "ka jdslgkjas dglkja skgdj alskjg aksjhdglkasjhdg"; // <-- a str slice let test = io_buf; // <-- a String let mut buf_slice = ""; for i in test.split_whitespace() { if buf_slice.len() < i.len() { buf_slice = i; } } println!("ok longest word was... {}", buf_slice); }
This is how you concatenate 2 string slices...
#[allow(unused_variables)] fn main() { let s1 = "this is a &str 1..."; let s2 = "this is a &str 2..."; // Both of these ways are ok... let s3 = s1.to_lowercase() + s2; let s4 = s1.to_string() + s2; // But... this is another way too.. let s5 = format!("{s1}{s2}"); dbg!(s5); }
Use Closures instead of matches
With closure:
use std::fs::File; use std::io::ErrorKind; fn main() { let greeting_file = File::open("hello.txt").unwrap_or_else(|error| { if error.kind() == ErrorKind::NotFound { File::create("hello.txt").unwrap_or_else(|error| { panic!("Problem creating the file: {error:?}"); }) } else { panic!("Problem opening the file: {error:?}"); } }); }
... which is way better then just nested matches!
use std::io::ErrorKind; fn main() { let file_result = std::fs::File::open("test.txt"); // Yuck! Nested Matches!!! let file = match file_result { Ok(file) => { println!("ok we got a file opend yay"); file }, Err(error) => { match error.kind() { ErrorKind::NotFound => { println!("ok file waz not there"); panic!("waa1!");}, _ => { println!("ok some other err was there"); panic!("waa!");}, } } }; dbg!(file); }
This is a function which is GENERIC over type T which MUST IMPLEMENT PARTIALORD
fn main() { let list01 = [1, 2, 4, 6, 3, 77, 3]; let largest = find_largest(&list01); let list02 = ['w', 'u', 't']; let largest2 = find_largest(&list02); dbg!(largest); dbg!(largest2); } /* We read this definition as... “The function largest is generic over some type T.” This function has one parameter named list, which is a slice of values of type T. The largest function will return a reference to a value of the same type T. */ fn find_largest<T: std::cmp::PartialOrd>(numlist: &[T]) -> &T { let mut largest = &numlist[0]; for i in numlist { if largest < i { largest = i; } } largest }
So, basically:
This chapter from The Rust Book was hard (10.2) (I.e. kinda like those Cpp interfaces)
-
Trait = The functionality a type has, and can share with other types.
-
Trait Bound = A generic Type of anything, can have shared behaviour.
We make them like:
pub trait Summary { fn blah (&self) -> blah {blah blah} }
- We can use trait as a param too via:
pub fn notify(item: &impl Summary) {}
which is a trait bound syntax for:
pub fn notify<T: Summary>(item: &T) {}
or... if multiple traits and hard to read, we use the "while":
fn blah<T, U> (t: &T, u: &U) -> i32 where T: Display + Clone U: Clone + Debug { blah blah ; }
- We can return a type that implements a trait
fn return_summarizable() -> impl Summary { Summary{blah: blah} // return me }
THIS IS FROM THE RUST BOOK ORIGINALLY, GOOD TO STUDY AND MEMORIZE
BASICALLY THAT where keyword I spotted was a trait bound...
Multiple Trait Bounds with the + Syntax
We can also specify more than one trait bound. Say we wanted notify to use display formatting as well as summarize on item: We specify in the notify definition that item must implement both Display and Summary. We can do so using the + syntax:
#![allow(unused)] fn main() { pub fn notify(item: &(impl Summary + Display)) { }
The + syntax is also valid with trait bounds on generic types:
#![allow(unused)] fn main() { pub fn notify<T: Summary + Display>(item: &T) { }
With the two trait bounds specified, the body of notify can call summarize and use {} to format item.
THE WHERE KEYWORD IS HERE////
Clearer Trait Bounds with where Clauses
Using too many trait bounds has its downsides. Each generic has its own trait bounds, so functions with multiple generic type parameters can contain lots of trait bound information between the function’s name and its parameter list, making the function signature hard to read. For this reason, Rust has alternate syntax for specifying trait bounds inside a where clause after the function signature. So, instead of writing this:
#![allow(unused)] fn main() { fn some_function<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32 { }
we can use a where clause, like this:
#![allow(unused)] fn main() { fn some_function<T, U>(t: &T, u: &U) -> i32 where T: Display + Clone, U: Clone + Debug, { }
This function’s signature is less cluttered: The function name, parameter list, and return type are close together, similar to a function without lots of trait bounds.
Here is a simple app where the func guarantees that the RETURN REF will be VALID AS LONG AS BOTH PARAMETERS ARE VALID
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } } fn main() { println!("The returned reference will be valid as long as both of the parameters are valid."); let x = "The returned reference will be valid as long as both of the parameters are valid."; let y = "roba ga takaai koucha toka dezaato skon toka ne"; let i = longest(x, y); dbg!(i); }