In real life applications, most of the times we have to pass variable bindings to other functions or assign them to other variable bindings. In this case, we are referencing the original binding; borrow the data of it.
What is Borrowing?
Borrow (verb) To receive something with the promise of returning it.
Shared & Mutable borrowings
⭐️ There are two types of Borrowing,
Shared Borrowing(&T)
A piece of data can be borrowed by a single or multiple users, but data should not be altered.
Mutable Borrowing(&mut T)
A piece of data can be borrowed and altered by a single user, but the data should not be accessible for any other users at that time.
Rules for borrowings
There are very important rules regarding borrowing,
One piece of data can be borrowed either as a shared borrow or as a mutable borrow at a given time. But not both at the same time.
Borrowing applies for both copy types and move types.
The concept of Liveness ↴
fnmain(){
+letmuta=vec![1,2,3];
+letb=&muta;// &mut borrow of `a` starts here
+// ⁝
+// some code // ⁝
+// some code // ⁝
+}// &mut borrow of `a` ends here
+
+
+fnmain(){
+letmuta=vec![1,2,3];
+letb=&muta;// &mut borrow of `a` starts here
+// some code
+
+println!("{:?}",a);// trying to access `a` as a shared borrow, so giving an error
+}// &mut borrow of `a` ends here
+
+
+fnmain(){
+letmuta=vec![1,2,3];
+{
+letb=&muta;// &mut borrow of `a` starts here
+// any other code
+}// &mut borrow of `a` ends here
+
+println!("{:?}",a);// allow borrowing `a` as a shared borrow
+}
+
💡 Let’s see how to use shared and mutable borrowings in examples.
\ No newline at end of file
diff --git a/docs/docs/borrowing/og.jpg b/docs/docs/borrowing/og.jpg
new file mode 100644
index 00000000..7616cba3
Binary files /dev/null and b/docs/docs/borrowing/og.jpg differ
diff --git a/docs/docs/cargo-crates-and-basic-project-structure/index.html b/docs/docs/cargo-crates-and-basic-project-structure/index.html
new file mode 100644
index 00000000..056bc9b1
--- /dev/null
+++ b/docs/docs/cargo-crates-and-basic-project-structure/index.html
@@ -0,0 +1,44 @@
+Cargo, Crates and Basic Project Structure · Learning Rust
Cargo is Rust’s built-in package manager and build system. It also supports the following actions,
Command
Action
cargo new
Create a new project
cargo init
Create a new project in an existing directory
cargo check
Verify the project compiles without errors
cargo build
Build the executable
cargo run
Build the executable and run
cargo clean
Remove the build system directories/ target directory
💡 The cargo check command verifies that the project compiles without errors, without producing an executable.
+Thus, it is often faster than cargo build.
💡 Cargo places executables compiled with cargo build or cargo run in the target/debug/ directory.
+But, while those built with cargo build --release for release purposes are stored in target/release/ directory.
+Release builds use more optimizations and remove some runtime safety checks to increase performance, although this comes at the cost of longer compile time.
Command
Action
cargo add
Add a dependency crate to the project
cargo remove
Remove a dependency crate from the project
cargo fetch
Download the dependencies specified in Cargo.lock
cargo update
Update project dependencies
💡 A crate is a package that can be shared via crates.io, Rust community’s crate registry.
+cargo add, cargo remove, cargo fetch, and cargo update commands manage project dependencies through the crate hosted on crates.io.
💡 The cargo add command includes a specified crate in the [dependencies] section of Cargo.toml, while cargo add --dev adds a crate to the [dev-dependencies] section. This indicates that the crate is only used for development purposes like testing and will not be included in the final compiled code.
Integration tests go in the tests directory (unit tests go in each file they’re testing).
Benchmarks go in the benches directory.
Examples go in the examples directory.
Rust Editions
Rust guarantees backward compatibility while introducing major updates to the language. To support this, the edition field was added to the Cargo.toml file in Rust 2018, marking the first major update to the language ecosystem three years after its initial release. Editions are opt-in, meaning existing crates will not experience these changes until they explicitly migrate to the new edition.
The major editions of Rust are:
Rust 2015: The initial edition, introduced with Rust 1.0. It established the core language features like ownership, borrowing, and lifetimes, laying the foundation for Rust’s safety and concurrency guarantees.
Rust 2018: The first major update, introduced the edition field in Cargo.toml, simplified the module system, stabilized async/await, improved error handling with the ? operator, and made several syntactic changes.
Rust 2021: Focused on improving ergonomics and removing inconsistencies, such as disjoint closure capture, IntoIterator for arrays, and the introduction of or-patterns in macros.
Rust 2024: The latest edition, includes enhancements like refined async features, more const generics, better diagnostics, and improved Cargo features.
For new projects created by cargo new, it will set edition = "2024" by default in the Cargo.toml file. For example,
The .cargo/bin directory of your home directory is the default location of Rust binaries. Not only the official binaries like rustc, cargo, rustup, rustfmt, rustdoc, rust-analyzer and also the binaries you can install via cargo install command, will be stored in this directory.
Even though the initial convention for naming crates and file names is using the snake_case, some crate developers are using kebab-case on both crates and file names. To make your code more consistent, use the initial convention snake_case; especially on file names.
Create,
an executable crate via cargo new command, run it via cargo run and examine the files and project structure.
a library crate via cargo new command, run cargo test and examine the files and project structure.
a multiple executables project and try to run each executable.
You can name executables in the Cargo.toml file.
[[bin]]
+name="app"
+path="src/bin/app/main.rs"
+
You can use the --bin flag to specify the executable, while running cargo commands. Ex. cargo build --bin app, cargo run --bin app
You can set default executable in the Cargo.toml file.
Run cargo build --release and check the files in the target folder.
\ No newline at end of file
diff --git a/docs/docs/cargo-crates-and-basic-project-structure/og.jpg b/docs/docs/cargo-crates-and-basic-project-structure/og.jpg
new file mode 100644
index 00000000..9d05f064
Binary files /dev/null and b/docs/docs/cargo-crates-and-basic-project-structure/og.jpg differ
diff --git a/docs/docs/combinators/index.html b/docs/docs/combinators/index.html
new file mode 100644
index 00000000..49ac7470
--- /dev/null
+++ b/docs/docs/combinators/index.html
@@ -0,0 +1,171 @@
+Combinators · Learning Rust
One meaning of “combinator” is a more informal sense referring to the combinator pattern, a style of organizing libraries centered around the idea of combining things. Usually there is some type T, some functions for constructing “primitive” values of type T, and some “combinators” which can combine values of type T in various ways to build up more complex values of type T. The other definition is “function with no free variables”.
+__ wiki.haskell.org
A combinator is a function which builds program fragments from program fragments; in a sense the programmer using combinators constructs much of the desired program automatically, rather that writing every detail by hand.
+__ John Hughes—Generalizing Monads to Arrows via Functional Programming Concepts
The exact definition of “combinators” in Rust ecosystem is bit unclear.
or(), and(), or_else(), and_then()
Combine two values of type T and return same type T.
xor() for Option types
Combine two values of type T and return same type T, only if exactly one value is T
filter() for Option types
Filter type T by using a closure as a conditional function
Return same type T
map(), map_err()
Convert type T by applying a closure.
The data type of the value inside T can be changed.
+ex. Some<&str> can be converted to Some<usize> or Err<&str> to Err<isize> and etc.
map_or(), map_or_else()
Transform type T by applying a closure & return the value inside type T.
For None and Err, a default value or another closure is applied.
ok_or(), ok_or_else() for Option types
Transform Option type into a Result type.
as_ref(), as_mut()
Transform type T into a reference or a mutable reference.
or() and and()
While combining two expressions, which return either Option/ Result
or(): If either one got Some or Ok, that value returns immediately.
and(): If both got Some or Ok, the value in the second expression returns. If either one got None or Err that value returns immediately.
With Option
lets1=Some("some1");
+lets2=Some("some2");
+letn: Option<&str>=None;
+
+assert_eq!(s1.or(s2),s1);// Some1 or Some2 = Some1
+assert_eq!(s1.or(n),s1);// Some or None = Some
+assert_eq!(n.or(s1),s1);// None or Some = Some
+assert_eq!(n.or(n),n);// None1 or None2 = None2
+
+assert_eq!(s1.and(s2),s2);// Some1 and Some2 = Some2
+assert_eq!(s1.and(n),n);// Some and None = None
+assert_eq!(n.and(s1),n);// None and Some = None
+assert_eq!(n.and(n),n);// None1 and None2 = None1
+
With Result
leto1: Result<&str,&str>=Ok("ok1");
+leto2: Result<&str,&str>=Ok("ok2");
+lete1: Result<&str,&str>=Err("error1");
+lete2: Result<&str,&str>=Err("error2");
+
+assert_eq!(o1.or(o2),o1);// Ok1 or Ok2 = Ok1
+assert_eq!(o1.or(e1),o1);// Ok or Err = Ok
+assert_eq!(e1.or(o1),o1);// Err or Ok = Ok
+assert_eq!(e1.or(e2),e2);// Err1 or Err2 = Err2
+
+assert_eq!(o1.and(o2),o2);// Ok1 and Ok2 = Ok2
+assert_eq!(o1.and(e1),e1);// Ok and Err = Err
+assert_eq!(e1.and(o1),e1);// Err and Ok = Err
+assert_eq!(e1.and(e2),e1);// Err1 and Err2 = Err1
+
xor()
While combining two Options, which return either Option, only if exactly one option is T.
The same Some type is returned, only if we pass only one Some value. None is returned, if both Some or None type. Rust support xor() only for Option types.
lets1=Some("some1");
+lets2=Some("some2");
+letn: Option<&str>=None;
+
+assert_eq!(s1.xor(s2),n);// Some1 xor Some2 = None
+assert_eq!(s1.xor(n),s1);// Some xor None = Some
+assert_eq!(n.xor(s1),s1);// None xor Some = Some
+assert_eq!(n.xor(n),n);// None1 xor None2 = None2
+
or_else()
Similar to or(). The only difference is, the second expression should be a closure which returns same type T.
With Option
lets1=Some("some1");
+lets2=Some("some2");
+letfn_some=||Some("some2");// similar to: let fn_some = || -> Option<&str> { Some("some2") };
+
+letn: Option<&str>=None;
+letfn_none=||None;
+
+assert_eq!(s1.or_else(fn_some),s1);// Some1 or_else Some2 = Some1
+assert_eq!(s1.or_else(fn_none),s1);// Some or_else None = Some
+assert_eq!(n.or_else(fn_some),s2);// None or_else Some = Some
+assert_eq!(n.or_else(fn_none),None);// None1 or_else None2 = None2
+
With Result
leto1: Result<&str,&str>=Ok("ok1");
+leto2: Result<&str,&str>=Ok("ok2");
+letfn_ok=|_|Ok("ok2");// similar to: let fn_ok = |_| -> Result<&str, &str> { Ok("ok2") };
+
+lete1: Result<&str,&str>=Err("error1");
+lete2: Result<&str,&str>=Err("error2");
+letfn_err=|_|Err("error2");
+
+assert_eq!(o1.or_else(fn_ok),o1);// Ok1 or_else Ok2 = Ok1
+assert_eq!(o1.or_else(fn_err),o1);// Ok or_else Err = Ok
+assert_eq!(e1.or_else(fn_ok),o2);// Err or_else Ok = Ok
+assert_eq!(e1.or_else(fn_err),e2);// Err1 or_else Err2 = Err2
+
and_then()
Similar to and(). The only difference is, the second expression should be a closure which returns same type T.
With Option
lets1=Some("some1");
+lets2=Some("some2");
+letfn_some=|_|Some("some2");// similar to: let fn_some = |_| -> Option<&str> { Some("some2") };
+
+letn: Option<&str>=None;
+letfn_none=|_|None;
+
+assert_eq!(s1.and_then(fn_some),s2);// Some1 and_then Some2 = Some2
+assert_eq!(s1.and_then(fn_none),n);// Some and_then None = None
+assert_eq!(n.and_then(fn_some),n);// None and_then Some = None
+assert_eq!(n.and_then(fn_none),n);// None1 and_then None2 = None1
+
With Result
leto1: Result<&str,&str>=Ok("ok1");
+leto2: Result<&str,&str>=Ok("ok2");
+letfn_ok=|_|Ok("ok2");// similar to: let fn_ok = |_| -> Result<&str, &str> { Ok("ok2") };
+
+lete1: Result<&str,&str>=Err("error1");
+lete2: Result<&str,&str>=Err("error2");
+letfn_err=|_|Err("error2");
+
+assert_eq!(o1.and_then(fn_ok),o2);// Ok1 and_then Ok2 = Ok2
+assert_eq!(o1.and_then(fn_err),e2);// Ok and_then Err = Err
+assert_eq!(e1.and_then(fn_ok),e1);// Err and_then Ok = Err
+assert_eq!(e1.and_then(fn_err),e1);// Err1 and_then Err2 = Err1
+
filter()
💡 Usually in programming languages filter functions are used with arrays or iterators to create a new array/ iterator by filtering own elements via a function/ closure. Rust also provides filter()as an iterator adaptor to apply a closure on each element of an iterator to transform it into another iterator. However in here we are talking about the functionality of filter() with Option types.
The same Some type is returned, only if we pass a Some value and the given closure returned true for it. None is returned, if None type passed or the closure returned false. The closure uses the value inside Some as an argument. Still Rust support filter() only for Option types.
lets1=Some(3);
+lets2=Some(6);
+letn=None;
+
+letfn_is_even=|x: &i8|x%2==0;
+
+assert_eq!(s1.filter(fn_is_even),n);// Some(3) -> 3 is not even -> None
+assert_eq!(s2.filter(fn_is_even),s2);// Some(6) -> 6 is even -> Some(6)
+assert_eq!(n.filter(fn_is_even),n);// None -> no value -> None
+
map() and map_err()
💡 Usually in programming languages map() functions are used with arrays or iterators, to apply a closure on each element of the array or iterator. Rust also provides map()as an iterator adaptor to apply a closure on each element of an iterator to transform it into another iterator. However in here we are talking about the functionality of map() with Option and Result types.
map() : Convert type T by applying a closure. The data type of Some or Ok blocks can be changed according to the return type of the closure. Convert Option<T> to Option<U>, Result<T, E> to Result<U, E>
⭐ Via map(), only Some and Ok values are getting changed. No affect to the values inside Err (None doesn’t contain any value at all).
map_err() for Result types : The data type of Err blocks can be changed according to the return type of the closure. Convert Result<T, E> to Result<T, F>.
⭐ Via map_err(), only Err values are getting changed. No affect to the values inside Ok.
Hope you remember the functionality of unwrap_or() and unwrap_or_else() functions. These functions also bit similar to them. But map_or() and map_or_else() apply a closure on Some and Ok values and return the value inside type T.
map_or() : Support only for Option types (not supporting Result). Apply the closure to the value inside Some and return the output according to the closure. The given default value is returned for None types.
map_or_else() : Support for both Option and Result types. Similar to map_or() but should provide another closure instead a default value for the first parameter.
⭐ None types doesn’t contain any value. So no need to pass anything to the closure as input with Option types. But Err types contain some value inside it. So default closure should able to read it as an input, while using this with Result types.
lets=Some(10);
+letn: Option<i8>=None;
+
+letfn_closure=|v: i8|v+2;
+letfn_default=||1;// None doesn't contain any value. So no need to pass anything to closure as input.
+
+assert_eq!(s.map_or_else(fn_default,fn_closure),12);
+assert_eq!(n.map_or_else(fn_default,fn_closure),1);
+
leto=Ok(10);
+lete=Err(5);
+
+letfn_closure=|v: i8|v+2;
+letfn_default_for_result=|v: i8|v+1;// Err contain some value inside it. So default closure should able to read it as input
+
+assert_eq!(o.map_or_else(fn_default_for_result,fn_closure),12);
+assert_eq!(e.map_or_else(fn_default_for_result,fn_closure),6);
+
ok_or() and ok_or_else()
As mentioned earlier, ok_or(), ok_or_else() transform Option type into Result type. Some to Ok and None to Err.
ok_or() : A default Err message should pass as argument.
🔎 As mentioned earlier, these functions are used to borrow type T as a reference or as a mutable reference.
as_ref() : Convert Option<T> to Option<&T> and Result<T, E> to Result<&T, &E>
as_mut() : Converts Option<T> to Option<&mut T> and Result<T, E> to Result<&mut T, &mut E>
\ No newline at end of file
diff --git a/docs/docs/combinators/og.jpg b/docs/docs/combinators/og.jpg
new file mode 100644
index 00000000..b6be4af0
Binary files /dev/null and b/docs/docs/combinators/og.jpg differ
diff --git a/docs/docs/comments-and-documenting-the-code/index.html b/docs/docs/comments-and-documenting-the-code/index.html
new file mode 100644
index 00000000..54769e2a
--- /dev/null
+++ b/docs/docs/comments-and-documenting-the-code/index.html
@@ -0,0 +1,42 @@
+Comments and Documenting the code · Learning Rust
💡 By convention, try to avoid using block comments. Use line comments instead.
Doc Comments
As we discussed, we can generate the project documentation via rustdoc by running the cargo doc command. It uses the doc comments to generate the documentation.
💡 Usually we are adding doc comments on library crates. Also, we can use Markdown notations inside the doc comments.
/// Line comments; document the next item
+/** Block comments; document the next item */
+
+//! Line comments; document the enclosing item
+/*! Block comments; document the enclosing item !*/
+
🔎 An attribute is a general, free-form metadatum that is interpreted according to the name, convention, language and compiler version. Any item declaration may have an attribute applied to it. Syntax:
Outer attribute: #[attr]
Inner attribute: #![attr]
👨🏫 Before going to the next…
Use //! only to write crate-level documentation, nothing else. When using mod blocks, use /// outside of the block. Check the usage of //! and /// doc comments of few popular crates on crates.io. For example, check serde/src/lib.rs and rand/src/lib.rs.
Run cargo new hello_lib --lib command to create a sample crate and replace its src/lib.rs file with the following code. Then run cd hello_lib && cargo doc --open to generate the documentation and open it from your web browser.
//! A Simple Hello World Crate
+
+/// This function returns the greeting; Hello, world!
+pubfnhello()-> String{
+("Hello, world!").to_string()
+}
+
+#[cfg(test)]
+modtests{
+usesuper::hello;
+
+#[test]
+fntest_hello(){
+assert_eq!(hello(),"Hello, world!");
+}
+}
+
\ No newline at end of file
diff --git a/docs/docs/comments-and-documenting-the-code/og.jpg b/docs/docs/comments-and-documenting-the-code/og.jpg
new file mode 100644
index 00000000..20658698
Binary files /dev/null and b/docs/docs/comments-and-documenting-the-code/og.jpg differ
diff --git a/docs/docs/control-flows/index.html b/docs/docs/control-flows/index.html
new file mode 100644
index 00000000..e583685a
--- /dev/null
+++ b/docs/docs/control-flows/index.html
@@ -0,0 +1,229 @@
+Control Flows · Learning Rust
letteam_size=7;
+
+ifteam_size<5{
+println!("Small");
+}elseifteam_size<10{
+println!("Medium");// The code prints this
+}else{
+println!("Large");
+}
+
ii. Let’s refactor the above code,
letteam_size=7;
+letteam_size_in_text;
+
+ifteam_size<5{
+team_size_in_text="Small";
+}elseifteam_size<10{
+team_size_in_text="Medium";
+}else{
+team_size_in_text="Large";
+}
+
+println!("Current team size : {}",team_size_in_text);// Current team size : Medium
+
iii. Let’s refactor further (variable shadowing),
letteam_size=7;
+letteam_size=ifteam_size<5{
+"Small"// ⭐️ no ;
+}elseifteam_size<10{
+"Medium"
+}else{
+"Large"
+};
+
+println!("Current team size : {}",team_size);// Current team size : Medium
+
⭐️ Return data type should be the same on each block when using this as an expression.
match
With Multiple Patterns
lettshirt_width=20;
+lettshirt_size=matchtshirt_width{
+13=>"XS",// check 13
+14|15=>"S",// check 14 and 15
+16..18=>"M",// check from 16 to 17 / 18 exclusive (16,17)
+18..=20=>"L",// check from 18 to 20 (18,19,20)
+
+xifx>20&&x<26=>"XL",// check 21 to 25 (21,22,23,24,25)
+// >,>=,<,<= via assigning the value to a variable (x) + if
+
+_=>"Not Available",// default behavior, if none of conditions matches
+};
+
+println!("{}",tshirt_size);// L
+
Without Default Behavior
letis_allowed=false;
+letlist_type=matchis_allowed{
+true=>"Full",
+false=>"Restricted"
+// no default/ _ condition can be skipped
+// Because data type of is_allowed is boolean and all possibilities checked on conditions
+};
+
+println!("{}",list_type);// Restricted
+
With Multiple Variable Matchings
letmarks_paper_a: u8=25;
+letmarks_paper_b: u8=30;
+
+letoutput=match(marks_paper_a,marks_paper_b){
+(50,50)=>"Full marks for both papers",
+(50,_)=>"Full marks for paper A",
+(_,50)=>"Full marks for paper B",
+(x,y)ifx>25&&y>25=>"Good",
+(_,_)=>"Work hard"
+};
+
+println!("{}",output);// Work hard
+
loop
Infinite loop
// ⚠️ This will run forever without terminating. Termininate manually (Ctrl+C)
+loop{
+println!("Loop forever!");
+}
+
With break and continue
letmuta=0;
+
+loop{
+ifa==0{
+println!("Skip Value : {}",a);
+a+=1;
+continue;
+}elseifa==2{
+println!("Break At : {}",a);
+break;
+}
+
+println!("Current Value : {}",a);
+a+=1;
+}
+
letmutb1=1;
+
+'outer: loop{// set label outer (or any other snake_case name)
+letmutb2=1;
+
+'inner: loop{// set label inner
+println!("Current Value : [{}][{}]",b1,b2);
+
+ifb1==2&&b2==2{
+break'outer;// kill outer loop
+}elseifb2==5{
+break;
+}
+
+b2+=1;
+}
+
+b1+=1;
+}
+
while
Infinite while
// ⚠️ This will run forever without terminating. Termininate manually (Ctrl+C)
+whiletrue{
+println!("While forever!");
+}
+
A simple while
letmuta=1;
+
+whilea<=10{
+println!("Current value : {}",a);
+a+=1;//no ++ or -- on Rust
+}
+
With break and continue
letmutb=0;
+
+whileb<5{
+ifb==0{
+println!("Skip value : {}",b);
+b+=1;
+continue;
+}elseifb==2{
+println!("Break At : {}",b);
+break;
+}
+
+println!("Current value : {}",b);
+b+=1;
+}
+
+// 💡 You can't break with a value in a while
+
Labeling and break the Outer while
letmutc1=1;
+
+'outer: whilec1<6{// set label outer (or any other snake_case name)
+letmutc2=1;
+
+'inner: whilec2<6{// set label inner
+println!("Current Value : [{}][{}]",c1,c2);
+
+ifc1==2&&c2==2{
+break'outer;// kill outer while
+}
+
+c2+=1;
+}
+
+c1+=1;
+}
+
for
A simple for
// 0 to 10 (10 exclusive); In other languages, `for(i = 0; i < 10; i++)`
+foriin0..10{
+println!("Current value : {}",i);
+}
+
// 1 to 10 (10 inclusive); In other languages, `for(i = 1; i <= 10; i++)`
+foriin1..=10{
+println!("Current value : {}",i);
+}
+
With break and continue
// 💡 You can't break with a value in a for
+forbin0..6{
+ifb==0{
+println!("Skip Value : {}",b);
+continue;
+}elseifb==2{
+println!("Break At : {}",b);
+break;
+}
+
+println!("Current value : {}",b);
+}
+
Labeling and break the Outer for
'outer: forc1in1..6{// set label outer (or any other snake_case name)
+
+'inner: forc2in1..6{// set label inner
+println!("Current Value : [{}][{}]",c1,c2);
+
+ifc1==2&&c2==2{
+break'outer;// kill outer for
+}
+}
+}
+
With Arrays and Vectors
letgroup: [&str;4]=["Mark","Larry","Bill","Steve"];
+
+// 👎 group.len() = 4 check on each iteration of the for loop
+fornin0..group.len(){
+println!("Current Person : {}",group[n]);
+}
+
+// 👍 group.iter() turn the array into a simple iterator
+forpersoningroup.iter(){
+println!("Current Person : {person}");
+}
+
+// 👍 group.iter().enumerate() helps to read both the current index (starting from zero) and the value
+for(index,person)ingroup.iter().enumerate(){
+println!("Person {index} : {person}");
+}
+
\ No newline at end of file
diff --git a/docs/docs/control-flows/og.jpg b/docs/docs/control-flows/og.jpg
new file mode 100644
index 00000000..aa79424c
Binary files /dev/null and b/docs/docs/control-flows/og.jpg differ
diff --git a/docs/docs/crates/index.html b/docs/docs/crates/index.html
new file mode 100644
index 00000000..56fc758a
--- /dev/null
+++ b/docs/docs/crates/index.html
@@ -0,0 +1,197 @@
+Crates · Learning Rust
💭 Crates are a bit similar to the packages in some other languages. Crates compile individually. If the crate has child file modules, those files will get merged with the crate file and compile as a single unit.
💭 A crate can produce an executable/ a binary or a library. src/main.rs is the crate root/ entry point for a binary crate and src/lib.rs is the entry point for a library crate.
01. lib.rs on executable crate
💡 When writing binary crates, we can move the main functionalities to src/lib.rs and use it as a library from src/main.rs. This pattern is quite common on executable crates.
💯 As I mentioned earlier, in here we use simplest examples to reduce the complexity of learning materials. But this is how we need to write greetings/src/lib.rs to make the code more testable.
// greetings/src/lib.rs
+pubfnhello()-> String{
+//! This returns `Hello, world!` String
+("Hello, world!").to_string()
+}
+
+// 01. Tests for `hello()`
+#[test]// Indicates that this is a test function
+fntest_hello(){
+assert_eq!(hello(),"Hello, world!");
+}
+
+// 02. Tests for `hello()`, Idiomatic way
+#[cfg(test)]// Only compiles when running tests
+modtests{// Separates tests from code
+usesuper::hello;// Import root `hello()` function
+
+#[test]
+fntest_hello(){
+assert_eq!(hello(),"Hello, world!");
+}
+}
+
📖 When importing a crate that has dashes in its name “like-this”, which is not a valid Rust identifier, it will be converted by changing the dashes to underscores, so you would write extern crate like_this;
lib.rs can link with multiple files.
// # Think we run,
+cargonewphrases
+touchphrases/src/lib.rs
+touchphrases/src/greetings.rs
+
+// # It generates,
+phrases
+├──Cargo.toml
+└──src
+├──greetings.rs
+├──lib.rs
+└──main.rs
+
+// # Think we modify following files,
+
+// 01. phrases/src/greetings.rs
+pubfnhello(){
+println!("Hello, world!");
+}
+
+// 02. phrases/src/main.rs
+fnmain(){
+phrases::greetings::hello();
+}
+
+// 03. phrases/src/lib.rs
+pubmodgreetings;// ⭐️ Import `greetings` module as a public module
+
02. Dependency crate on Cargo.toml
When the code in the lib.rs file is getting larger, we can move those into a separate library crate and use it as a dependency of the main crate. As we mentioned earlier, a dependency can be specified from a folder path, git repository or by crates.io.
a. Using folder path
Let’s see how to create a nested crate and use it as a dependency using folder path,
If you want to use a library crate on multiple projects, one way is moving crate code to a git repository and use it as a dependency when needed.
// -- Cargo.toml --
+[dependencies]
+
+// 01. Get the latest commit on the master branch
+rocket={git="https://github.com/SergioBenitez/Rocket"}
+
+// 02. Get the latest commit of a specific branch
+rocket={git="https://github.com/SergioBenitez/Rocket",branch="v0.3"}
+
+// 03. Get a specific tag
+rocket={git="https://github.com/SergioBenitez/Rocket",tag="v0.3.2"}
+
+// 04. Get a specific revision (on master or any branch, according to rev)
+rocket={git="https://github.com/SergioBenitez/Rocket",rev="8183f636305cef4adaa9525506c33cbea72d1745"}
+
c. Using crates.io
The other way is uploading it to crates.io and use it as a dependency when needed.
🚧 First, let’s create a simple “Hello world” crate and upload it to crates.io.
// # Think we run,
+cargonewtest_crate_hello_world--lib
+
+// # It generates,
+test_crate_hello_world
+├──Cargo.toml
+└──src
+└──lib.rs
+
+// # Think we modify following files,
+
+// 01. test_crate_hello_world/Cargo.toml
+[package]
+name="test_crate_hello_world"
+version="0.1.0"
+authors=["Dumindu Madunuwan"]
+
+description="A Simple Hello World Crate"
+repository="https://github.com/dumindu/test_crate_hello_world"
+keywords=["hello","world"]
+license="Apache-2.0"
+
+[dependencies]
+
+// 02. test_crate_hello_world/src/lib.rs
+//! A Simple Hello World Crate
+
+/// This function returns the greeting; `Hello, world!`
+pubfnhello()-> String{
+("Hello, world!").to_string()
+}
+
+#[cfg(test)]
+modtests{
+
+usesuper::hello;
+
+#[test]
+fntest_hello(){
+assert_eq!(hello(),"Hello, world!");
+}
+}
+
💭 //! doc comments are used to write crate and module-level documentation. On other places, we have to use /// outside of the block. And when uploading a crate to crates.io, cargo generates the documentation from these doc comments and host it on docs.rs.
💡 We have to add the description and license fields to Cargo.toml. Otherwise, we will get error: api errors: missing or empty metadata fields: description, license. Please see http://doc.crates.io/manifest.html
To upload this to crates.io,
We have to create an account on crates.io to acquire an API token
Then run cargo login <token> with that API token and cargo publish
You’ll need an account on crates.io to acquire an API token. To do so, visit the home page and log in via a GitHub account (required for now). After this, visit your Account Settings page and run the cargo login command specified.
+Ex. cargo login abcdefghijklmnopqrstuvwxyz012345
The next step is to package up your crate into a format that can be uploaded to crates.io. For this we’ll use the cargo package sub-command.
Now, it can be uploaded to crates.io with the cargo publish command.
If you’d like to skip the cargo package step, the cargo publish sub-command will automatically package up the local crate if a copy isn’t found already.
By default, Cargo looks dependencies on crates.io. So we have to add only the crate name and a version string to Cargo.toml and then run cargo build to fetch the dependencies and compile them.
\ No newline at end of file
diff --git a/docs/docs/crates/og.jpg b/docs/docs/crates/og.jpg
new file mode 100644
index 00000000..7846e6ab
Binary files /dev/null and b/docs/docs/crates/og.jpg differ
diff --git a/docs/docs/custom-error-types/index.html b/docs/docs/custom-error-types/index.html
new file mode 100644
index 00000000..4f969e10
--- /dev/null
+++ b/docs/docs/custom-error-types/index.html
@@ -0,0 +1,228 @@
+Custom Error Types · Learning Rust
Rust allow us to create our own Err types. We call them “Custom Error Types”.
Error trait
As you know traits define the functionality a type must provide. But we don’t always need to define new traits for common functionalities, because Rust standard library provides reusable traits which can be implemented on our own types. While creating custom error types the std::error::Error trait helps us to convert any type to an Err type.
As we discussed under traits inheritance, a trait can be inherited from another traits. trait Error: Debug + Display means Error trait inherits from fmt::Debug and fmt::Display traits.
How should the end user see this error as a message/ user-facing output.
Usually print via println!("{}") or eprintln!("{}")
Debug
How should display the Err while debugging/ programmer-facing output.
Usually print via println!("{:?}") or eprintln!("{:?}")
To pretty-print, println!("{:#?}") or eprintln!("{:#?}") can be used.
source()
The lower-level source of this error, if any.
Optional.
First, let’s see how to implement std::error::Error trait on a simplest custom error type.
usestd::fmt;
+
+// Custom error type; can be any type which defined in the current crate
+// 💡 In here, we use a simple "unit struct" to simplify the example
+structAppError;
+
+// Implement std::fmt::Display for AppError
+implfmt::DisplayforAppError{
+fnfmt(&self,f: &mutfmt::Formatter)-> fmt::Result{
+write!(f,"An Error Occurred, Please Try Again!")// user-facing output
+}
+}
+
+// Implement std::fmt::Debug for AppError
+implfmt::DebugforAppError{
+fnfmt(&self,f: &mutfmt::Formatter)-> fmt::Result{
+write!(f,"{{ file: {}, line: {} }}",file!(),line!())// programmer-facing output
+}
+}
+
+// A sample function to produce an AppError Err
+fnproduce_error()-> Result<(),AppError>{
+Err(AppError)
+}
+
+fnmain(){
+matchproduce_error(){
+Err(e)=>eprintln!("{}",e),// An Error Occurred, Please Try Again!
+_=>println!("No error"),
+}
+
+eprintln!("{:?}",produce_error());// Err({ file: src/main.rs, line: 17 })
+}
+
Hope you understood the main points. Now, let’s see a custom error type with an error code and an error message.
usestd::fmt;
+
+structAppError{
+code: usize,
+message: String,
+}
+
+// Different error messages according to AppError.code
+implfmt::DisplayforAppError{
+fnfmt(&self,f: &mutfmt::Formatter)-> fmt::Result{
+leterr_msg=matchself.code{
+404=>"Sorry, Can not find the Page!",
+_=>"Sorry, something is wrong! Please Try Again!",
+};
+
+write!(f,"{}",err_msg)
+}
+}
+
+// A unique format for dubugging output
+implfmt::DebugforAppError{
+fnfmt(&self,f: &mutfmt::Formatter)-> fmt::Result{
+write!(
+f,
+"AppError {{ code: {}, message: {} }}",
+self.code,self.message
+)
+}
+}
+
+fnproduce_error()-> Result<(),AppError>{
+Err(AppError{
+code: 404,
+message: String::from("Page not found"),
+})
+}
+
+fnmain(){
+matchproduce_error(){
+Err(e)=>eprintln!("{}",e),// Sorry, Can not find the Page!
+_=>println!("No error"),
+}
+
+eprintln!("{:?}",produce_error());// Err(AppError { code: 404, message: Page not found })
+
+eprintln!("{:#?}",produce_error());
+// Err(
+// AppError { code: 404, message: Page not found }
+// )
+}
+
⭐️ Rust standard library provides not only reusable traits and also it facilitates to magically generate implementations for few traits via #[derive] attribute. Rust support derivestd::fmt::Debug, to provide a default format for debug messages. So we can skip std::fmt::Debug implementation for custom error types and use #[derive(Debug)] before struct declaration.
For a struct #[derive(Debug)] prints, the name of the struct , { , comma-separated list of each field’s name and debug value and }.
usestd::fmt;
+
+#[derive(Debug)]// derive std::fmt::Debug on AppError
+structAppError{
+code: usize,
+message: String,
+}
+
+implfmt::DisplayforAppError{
+fnfmt(&self,f: &mutfmt::Formatter)-> fmt::Result{
+leterr_msg=matchself.code{
+404=>"Sorry, Can not find the Page!",
+_=>"Sorry, something is wrong! Please Try Again!",
+};
+
+write!(f,"{}",err_msg)
+}
+}
+
+fnproduce_error()-> Result<(),AppError>{
+Err(AppError{
+code: 404,
+message: String::from("Page not found"),
+})
+}
+
+fnmain(){
+matchproduce_error(){
+Err(e)=>eprintln!("{}",e),// Sorry, Can not find the Page!
+_=>println!("No error"),
+}
+
+eprintln!("{:?}",produce_error());// Err(AppError { code: 404, message: Page not found })
+
+eprintln!("{:#?}",produce_error());
+// Err(
+// AppError {
+// code: 404,
+// message: "Page not found"
+// }
+// )
+}
+
From trait
When writing real programs, we mostly have to deal with different modules, different std and third party crates at the same time. Each crate uses their own error types. However, if we are using our own error type, we should convert those errors into our error type. For these conversions, we can use the standardized trait std::convert::From.
💡 As you know, String::from() function is used to create a String from &str data type. Actually this also an implementation of std::convert::From trait.
Let’s see how to implement std::convert::From trait on a custom error type.
usestd::fs::File;
+usestd::io;
+
+#[derive(Debug)]
+structAppError{
+kind: String,// type of the error
+message: String,// error message
+}
+
+// Implement std::convert::From for AppError; from io::Error
+implFrom<io::Error>forAppError{
+fnfrom(error: io::Error)-> Self{
+AppError{
+kind: String::from("io"),
+message: error.to_string(),
+}
+}
+}
+
+fnmain()-> Result<(),AppError>{
+let_file=File::open("nonexistent_file.txt")?;// This generates an io::Error. But because of return type is Result<(), AppError>, it converts to AppError
+
+Ok(())
+}
+
+
+// --------------- Run time error ---------------
+Error: AppError{kind: "io",message: "No such file or directory (os error 2)"}
+
In the above example, File::open(“nonexistent.txt”)? produces std::io::Error. But because of the return type is Result<(), AppError>, it converts to an AppError. Because of we are propagating the error from main() function, it prints the Debug representation of the Err.
In the above example we deal with only one std error type, std::io::Error. Let’s see some example which handles multiple std error types.
usestd::fs::File;
+usestd::io::{self,Read};
+usestd::num;
+
+#[derive(Debug)]
+structAppError{
+kind: String,
+message: String,
+}
+
+// Implement std::convert::From for AppError; from io::Error
+implFrom<io::Error>forAppError{
+fnfrom(error: io::Error)-> Self{
+AppError{
+kind: String::from("io"),
+message: error.to_string(),
+}
+}
+}
+
+// Implement std::convert::From for AppError; from num::ParseIntError
+implFrom<num::ParseIntError>forAppError{
+fnfrom(error: num::ParseIntError)-> Self{
+AppError{
+kind: String::from("parse"),
+message: error.to_string(),
+}
+}
+}
+
+fnmain()-> Result<(),AppError>{
+letmutfile=File::open("hello_world.txt")?;// generates an io::Error, if can not open the file and converts to an AppError
+
+letmutcontent=String::new();
+file.read_to_string(&mutcontent)?;// generates an io::Error, if can not read file content and converts to an AppError
+
+let_number: usize;
+_number=content.parse()?;// generates num::ParseIntError, if can not convert file content to usize and converts to an AppError
+
+Ok(())
+}
+
+
+// --------------- Few possible run time errors ---------------
+
+// 01. If hello_world.txt is a nonexistent file
+Error: AppError{kind: "io",message: "No such file or directory (os error 2)"}
+
+// 02. If user doesn't have relevant permission to access hello_world.txt
+Error: AppError{kind: "io",message: "Permission denied (os error 13)"}
+
+// 03. If hello_world.txt contains non-numeric content. ex Hello, world!
+Error: AppError{kind: "parse",message: "invalid digit found in string"}
+
🔎 Search about the implementation of std::io::ErrorKind, to see how to organize error types further.
\ No newline at end of file
diff --git a/docs/docs/custom-error-types/og.jpg b/docs/docs/custom-error-types/og.jpg
new file mode 100644
index 00000000..d13db674
Binary files /dev/null and b/docs/docs/custom-error-types/og.jpg differ
diff --git a/docs/docs/enums/index.html b/docs/docs/enums/index.html
new file mode 100644
index 00000000..c76d3810
--- /dev/null
+++ b/docs/docs/enums/index.html
@@ -0,0 +1,144 @@
+Enums · Learning Rust
An enum is a single type that contains variants, which represent the possible values of the enum at any given time.
By convention, the enum name and its variants’ names should follow PascalCase.
Can access the variants using the :: notation and the variant name. ex. Day::Sunday
enumDay{
+Sunday,
+Monday,
+Tuesday,
+Wednesday,
+Thursday,
+Friday,
+Saturday,
+}
+
+// 💡 Day is the enum. Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday are its variants.
+
An enum variant can have either,
No data (a unit variant)
Unnamed ordered data (a tuple variant)
Named data/ fields (a struct variant)
enumFlashMessage{
+Success,// 💡 A unit variant (no data)
+Error(u8,String),// 💡 A tuple variant (one or more , separated data)
+Warning{field: String,message: String},// 💡 A struct variant (one or more , separated name: value data)
+}
+
+// 💡 FlashMessage is the emnum, Success, Error, Warning are its variants.
+
💡 In Rust, the term “instantiation” is used to describe the act of creating a concrete instance of a type (struct or enum).
💡 In Rust, the term “field” is used to describe a named component in a C-like struct & struct-like enum variant, and the term “element” is used to describe an unnamed component in a tuple struct & tuple-like enum variant. The term “member” is used to describe both.
#![allow(unused)]// 💡 skip unused warnings, as we don't read fields in the enums
+
+#[derive(Debug)]
+enumFlashMessage{// Definition
+Success,
+Error(u32,String),
+Warning{field: String,message: String},
+}
+
+fnmain(){
+// 1. Instantiation with separate variable declaration and assignment
+letx: FlashMessage;// Declaration with the data type
+x=FlashMessage::Success;
+println!("{x:?}");// Success
+
+// 2. Instantiation with a direct variable initialization
+leta=FlashMessage::Success;
+letb=FlashMessage::Error(401,"Unauthorized".to_string());
+letc=FlashMessage::Warning{field: "email".to_string(),message: "This is required".to_string()};
+
+println!("{a:?}");// Success
+println!("{b:?}");// Error(401, "Unauthorized")
+println!("{c:?}");// Warning { field: "email", message: "This is required" }
+}
+
// 3. Instantiation with a default variant
+#![allow(unused)]// 💡 skip unused warnings, as we don't use the all variants of the enum
+
+#[derive(Debug, Default)]
+enumHand{
+Left,
+#[default]// 💡Set Right as the default variant
+Right,
+}
+
+fnmain(){
+leta=Hand::default();// Instantiation with the default variant
+println!("{a:?}");// Right
+}
+
In Rust, the #[derive()] attribute is used to automatically generate an implementation of certain traits for a custom data structure (struct and enum), instead of you writing them by hand. The std::fmt::Debug trait allows us to format a value with {:?} or {:#?} in println! and similar macros. The std::default::Default trait allows us to create a new instance of a type with the Type::default() method.
Pattern Matching
With match
#![allow(unused)]// 💡 skip unused warnings, as we don't use the all variants of the enum
+
+enumSeason{
+Spring,
+Summer,
+Autumn,
+Winter,
+}
+
+fnmain(){
+leta=Season::Winter;
+letresult=matcha{
+Season::Spring=>"☀️",
+Season::Summer=>"🍁",
+Season::Autumn=>"🍂",
+Season::Winter=>"❄️",
+};
+
+println!("{result}");// ❄️
+}
+
With if let, else if let, else
if let is useful when we only care about handling one (or few) specific patterns and don’t need to explicitly match every possible case.
#![allow(unused)]// 💡 skip unused warnings, as we don't use the all variants of the enum
+
+enumSeason{
+Spring,
+Summer,
+Autumn,
+Winter,
+}
+
+fnmain(){
+leta=Season::Winter;
+letresult=ifletSeason::Spring=a{
+"☀️"
+}elseifletSeason::Summer=a{
+"🍁"
+}elseifletSeason::Autumn=a{
+"🍂"
+}elseifletSeason::Winter=a{
+"❄️"
+}else{
+unreachable!()
+};
+
+println!("{result}");// ❄️
+}
+
Destructuring & Accessing Variants’ Members
In Rust, directly accessing an enum variant’s fields without any form of pattern matching is not possible. We need to use pattern matching to access the fields by using a match expression or if let expression.
With match
#![allow(unused)]// 💡 skip unused warnings, as we don't use the all variants of the enum
+
+enumFlashMessage{
+Success,
+Error(u32,String),
+Warning{field: String,message: String},
+}
+
+fnmain(){
+leta=FlashMessage::Error(401,"Unauthorized".to_string());
+
+letresult=matcha{
+FlashMessage::Success=>"We'll get back to you.".to_string(),
+FlashMessage::Error(_,msg)=>msg,// 💡 Destructuring only the second element of the tuple variant.
+FlashMessage::Warning{message,..}=>message,// 💡 Destructuring only the second field of the struct variant.
+};
+
+println!("{result}");// Unauthorized
+}
+
With if let, else if let, else
if let is useful when we only care about handling one (or few) specific patterns and don’t need to explicitly match every possible case.
#![allow(dead_code)]// 💡 Remove dead_code warnings, as we don't access the all elements of variants.
+
+enumFlashMessage{
+Success,
+Error(u32,String),
+Warning{field: String,message: String},
+}
+
+fnmain(){
+leta=FlashMessage::Error(401,"Unauthorized".to_string());
+
+ifletFlashMessage::Error(_,msg)=a{
+println!("{msg}");// Unauthorized
+}elseifletFlashMessage::Warning{message,..}=a{
+println!("{message}");
+}else{
+println!("We'll get back to you.");
+}
+}
+
\ No newline at end of file
diff --git a/docs/docs/enums/og.jpg b/docs/docs/enums/og.jpg
new file mode 100644
index 00000000..689e982e
Binary files /dev/null and b/docs/docs/enums/og.jpg differ
diff --git a/docs/docs/error-and-none-propagation/index.html b/docs/docs/error-and-none-propagation/index.html
new file mode 100644
index 00000000..d02186bb
--- /dev/null
+++ b/docs/docs/error-and-none-propagation/index.html
@@ -0,0 +1,73 @@
+Error and None Propagation · Learning Rust
We should use panics like panic!(), unwrap(), expect() only if we can not handle the situation in a better way. Also if a function contains expressions which can produce either None or Err,
we can handle them inside the same function. Or,
we can return None and Err types immediately to the caller. So the caller can decide how to handle them.
💡 None types no need to handle by the caller of the function always. But Rusts’ convention to handle Err types is, return them immediately to the caller to give more control to the caller to decide how to handle them.
? Operator
If an Option type has Some value or a Result type has a Ok value, the value inside them passes to the next step.
If the Option type has None value or the Result type has Err value, return them immediately to the caller of the function.
Example with Option type,
fnmain(){
+ifcomplex_function().is_none(){
+println!("X not exists!");
+}
+}
+
+fncomplex_function()-> Option<&'staticstr>{
+letx=get_an_optional_value()?;// if None, returns immediately; if Some("abc"), set x to "abc"
+
+// some other code, ex
+println!("{}",x);// "abc" ; if you change line 19 `false` to `true`
+
+Some("")
+}
+
+fnget_an_optional_value()-> Option<&'staticstr>{
+
+//if the optional value is not empty
+iffalse{
+returnSome("abc");
+}
+
+//else
+None
+}
+
Example with Result Type,
fnmain(){
+// `main` function is the caller of `complex_function` function
+// So we handle errors of complex_function(), inside main()
+ifcomplex_function().is_err(){
+println!("Can not calculate X!");
+}
+}
+
+fncomplex_function()-> Result<u64,String>{
+letx=function_with_error()?;// if Err, returns immediately; if Ok(255), set x to 255
+
+// some other code, ex
+println!("{}",x);// 255 ; if you change line 20 `true` to `false`
+
+Ok(0)
+}
+
+fnfunction_with_error()-> Result<u64,String>{
+//if error happens
+iftrue{
+returnErr("some message".to_string());
+}
+
+// else, return valid output
+Ok(255)
+}
+
try!()
⭐ ? operator was added in Rust version 1.13. try!() macro is the old way to propagate errors before that. So we should avoid using this now.
If a Result type has Ok value, the value inside it passes to the next step. If it has Err value, returns it immediately to the caller of the function.
// using `?`
+letx=function_with_error()?;// if Err, returns immediately; if Ok(255), set x to 255
+
+// using `try!()`
+letx=try!(function_with_error());
+
Error propagation from main()
Before Rust version 1.26, we couldn’t propagate Result and Option types from the main() function. But now, we can propagate Result types from the main() function and it prints the Debug representation of the Err.
💡 We are going to discuss about Debug representations under Error trait section.
usestd::fs::File;
+
+fnmain()-> std::io::Result<()>{
+let_=File::open("not-existing-file.txt")?;
+
+Ok(())// Because of the default return value of Rust functions is an empty tuple/ ()
+}
+
+// Because of the program can not find not-existing-file.txt , it produces,
+// Err(Os { code: 2, kind: NotFound, message: "No such file or directory" })
+// While propagating error, the program prints,
+// Error: Os { code: 2, kind: NotFound, message: "No such file or directory" }
+
\ No newline at end of file
diff --git a/docs/docs/error-and-none-propagation/og.jpg b/docs/docs/error-and-none-propagation/og.jpg
new file mode 100644
index 00000000..9f70457d
Binary files /dev/null and b/docs/docs/error-and-none-propagation/og.jpg differ
diff --git a/docs/docs/functions/index.html b/docs/docs/functions/index.html
new file mode 100644
index 00000000..4d0025d7
--- /dev/null
+++ b/docs/docs/functions/index.html
@@ -0,0 +1,114 @@
+Functions · Learning Rust
When using arguments, we must declare the data types.
By default, functions return an empty tuple/ (). If you want to return a value, the return type must be specified after ->
Hello world
fnmain(){
+println!("Hello, world!");
+}
+
Passing Arguments
fnprint_sum(a: i8,b: i8){
+println!("sum is: {}",a+b);
+}
+
Returning Values
Without the return keyword. Only the last expression returns.
fnplus_one(a: i32)-> i32{
+a+1
+// There is no ending ; in the above line.
+// It means this is an expression which equals to `return a + 1;`.
+}
+
With the return keyword.
fnplus_two(a: i32)-> i32{
+returna+2;
+// Should use return keyword only on conditional/ early returns.
+// Using return keyword in the last expression is a bad practice.
+}
+
Function Pointers as a Data Type
fnmain(){
+letp1=plus_one;// Without type declarations
+leta=p1(5);// 6
+
+letp1: fn(i32)-> i32=plus_one;// With the type declarations
+letb=p1(5);// 6
+}
+
+fnplus_one(i: i32)-> i32{
+i+1
+}
+
Closures
Also known as anonymous functions or lambda functions.
The data types of arguments and returns are optional ⃰ⁱᵛ.
Example with a named function, before using closures.
fnmain(){
+letx=2;
+letsquare=|i: i32|-> i32{// Input parameters are passed inside | | and expression body is wrapped within { }
+i*i
+};
+println!("{}",square(x));
+}
+
Without Type Annotations
fnmain(){
+letx=2;
+letsquare=|i|i*i;// { } are optional for single-lined closures
+println!("{}",square(x));
+}
+
With Optional Type Annotations; Define and Call Together
fnmain(){
+letx=2;
+letx_square=|i: i32|-> i32{i*i}(x);// { } are mandatory while creating and calling same time.
+println!("{}",x_square);
+}
+
Without Type Annotations; Define and Call Together
fnmain(){
+letx=2;
+letx_square=|i|-> i32{i*i}(x);// ⭐️ The return type is mandatory.
+println!("{}",x_square);
+}
+
Test Functions
Start the function name with the test_ prefix.
Add with the #[test] attribute, inside a tests module with the #[cfg(test)] attribute.
fngreet()-> String{
+"Hello, world!".to_string()
+}
+
+#[cfg(test)]
+modtests{
+usesuper::greet;// 💡 Reimport the greet() function from the parent module.
+
+#[test]
+fntest_greet(){// The test function of greet()
+assert_eq!("Hello, world!",greet());
+}
+}
+
👨🏫 Before going to the next…
💯 Usage of :: and . to call functions in different modules,
💭 This is a quick reference about the usage of :: and . operators while calling functions. So, please don’t worry about structs, enums, traits, or impls for now. We will discuss them later.
Functions are standalone blocks of code, declare with the fn keyword.
Associated functions are functions that are associated with a particular data type such as structs, enums, or traits via an impl block.
Methods are associated functions with a receiver of self, &self, &mut self, self: Box<Self> etc.
⭐️ To call methods: use the . operator from an instance. ex. steve.intro_name()
⭐️ To call associated functions that are not methods: use the :: operator from the data type. ex. Person::new(), String::from()
structPerson{
+name: String,
+company_name: String,
+}
+
+implPerson{// 💡 impls are used to define functions in Rust structs, enums, etc.
+// 💡 The constructor (new` is a conventional name, not a keyword)
+fnnew(name: String,company_name: String)-> Person{// an associated function and not a method
+Person{name,company_name}
+}
+
+fnintro_name(&self)-> String{// 💡 a method
+format!("I'm {}",self.name)// 💡 access fields via `.` operator
+}
+
+fnintro_company(&self)-> String{// 💡 a method
+format!("I'm from {}",self.company_name)
+}
+}
+
+fnmain(){
+// 💡 calling associated functions with `::` operator
+letsteve=Person::new(String::from("Steve Jobs"),String::from("Apple"));
+
+// 💡 calling methods with `.` operator
+println!("{}. {}.",steve.intro_name(),steve.intro_company());// I'm Steve Jobs. I'm from Apple.
+
+// ⭐️ methods are also associated functions. So, we can call them with `::` operator as well but need to pass the instance as a parameter.
+println!("{}. {}.",Person::intro_name(&steve),Person::intro_company(&steve));// I'm Steve Jobs. I'm from Apple.
+}
+
Other than that, :: operator is used to call functions in different modules.
\ No newline at end of file
diff --git a/docs/docs/functions/og.jpg b/docs/docs/functions/og.jpg
new file mode 100644
index 00000000..85b584ed
Binary files /dev/null and b/docs/docs/functions/og.jpg differ
diff --git a/docs/docs/generics/index.html b/docs/docs/generics/index.html
new file mode 100644
index 00000000..0c4a654e
--- /dev/null
+++ b/docs/docs/generics/index.html
@@ -0,0 +1,96 @@
+Generics · Learning Rust
The core concept of generics is abstraction over types. They let us write one piece of code to operate with any data type without repeating ourselves to write separate versions for each type. At the compile time, Rust ensures the type safety and generates an optimized code for each concrete type used in the program.
Use an uppercase letter (T, U, …) or a PascalCase identifier for the data type.
Instead of x: u8 we use x: T.
Inform the compiler that T is a generic type by adding <T> at first.
On some occasions, the compiler cannot inter the type, and we have to specify the type when using the generic type. By the way, it’s good practice to specify the type on variables when using a generic implementation.
#[derive(Debug)]
+enumData<K,V>{
+Value(V),
+KeyValue(K,V),
+}
+
+fnmain(){
+leta: Data<(),bool>=Data::Value(true);// ⭐️ The compiler can not inter the type here. We have to specify the type.
+letb=Data::KeyValue(1,true);// The compiler can infer the type; i32, bool
+
+println!("{a:?}");// Value(true)
+println!("{b:?}");// KeyValue(1, true)
+}
+
👨🏫 Before going to the next…
Option and Result
💭 This is a quick reference to Option and Result as enums. Please don’t worry too much about them for now, as we will discuss them in detail later in Error Handling—Option & Result.
Many languages use null\ nil\ undefined types to represent empty outputs, and Exceptions to handle errors. Rust skips using both, especially to prevent issues like null pointer exceptions, sensitive data leakages through exceptions, etc. Option and Result types are two special generic enums defined in Rust’s standard library to deal with these cases.
// An output can have either Some value or no value/ None.
+enumOption<T>{// T is a generic and it can contain any type of value.
+Some(T),
+None,
+}
+
+// A result can represent either success/ Ok or failure/ Err.
+enumResult<T,E>{// T and E are generics. T can contain any type of value, E can be any error.
+Ok(T),
+Err(E),
+}
+
An optional value can have either Some value or no value/ None ⇒ possibility of absence
A result can represent either success/ Ok or failure/ Err ⇒ possibility of failure
Option
structTask{
+title: String,
+assignee: Option<Person>,// 💡 Instead of `assignee: Person`, we use `assignee: Option<Person>` as the assignee can be `None`.
+}
+
fnget_id_by_username(username: &str)-> Option<usize>{// 💡 Instead of setting return type as `usize`, set it `Option<usize>`
+// if username can be found in the system, return userId
+returnSome(userId);// 💡 Instead of return userId, return Some(userId)
+
+// else
+None// 💡 The last return statement no need `return` keyword and ending `;`
+}
+
+fnmain(){
+letusername="anonymous";
+matchget_id_by_username(username){// 💡 We can use pattern matching to catch the relevant return type (Some/None)
+None=>println!("User not found"),
+Some(i)=>println!("User Id: {}",i),
+}
+}
+
Result
fnget_word_count_from_file(file_name: &str)-> Result<u32,&str>{// 💡 Instead of setting return type as `u32`, set it `Result<u32, &str>`
+// if the file is not found on the system, return error
+returnErr("File can not be found!");// 💡 Instead panic/ break when the file can not be found; return Err(something)
+
+// else, count and return the word count
+Ok(word_count)// 💡 Instead of return `word_count`, return `Ok(word_count)`
+// 💡 The last return statement no need `return` keyword and ending `;`
+}
+
+fnmain(){
+letmutfile_name="file_a";
+matchget_word_count_from_file(file_name){// 💡 We can use pattern matching to catch the relevant return type (Ok/Err)
+Ok(i)=>println!("Word Count: {}",i),
+Err(e)=>println!("Error: {}",e)
+}
+}
+
\ No newline at end of file
diff --git a/docs/docs/generics/og.jpg b/docs/docs/generics/og.jpg
new file mode 100644
index 00000000..a6bf91b1
Binary files /dev/null and b/docs/docs/generics/og.jpg differ
diff --git a/docs/docs/hello-world/index.html b/docs/docs/hello-world/index.html
new file mode 100644
index 00000000..a155e6c0
--- /dev/null
+++ b/docs/docs/hello-world/index.html
@@ -0,0 +1,57 @@
+Hello World · Learning Rust
fn means function. The main function is the beginning of every Rust program.
+println!() prints text to the console and its ! indicates that it’s a macro rather than a function.
💡 Rust files should have .rs file extension and if you’re using more than one word for the file name, follow the snake_case convention.
Save the above code in file.rs , but it can be any name with .rs extension.
Compile it with rustc file.rs
Execute it with ./file on Linux and Mac or file.exe on Windows
These are the other usages of the println!() macro,
println!("{}, {}!","Hello","world");// Hello, world!
+
+println!("{0}, {1}!","Hello","world");// Hello, world!
+
+println!("{a}, {b}!",a="Hello",b="world");// Hello, world!
+
+let(a,b)=("Hello","world");// 💡 Two Variable bindings declare & initialize in one line.
+println!("{a}, {b}!");// Hello, world!
+
+println!();// A new line
+
// Debug print and pretty-print debug print format specifiers
+println!("{:?}",[1,2,3]);// [1, 2, 3]
+
+println!("{:#?}",[1,2,3]);
+/*
+ [
+ 1,
+ 2,
+ 3
+ ]
+*/
+
+// 💡 We can use the variable directly with the format specifier as well.
+leta=[1,2,3];
+
+println!("{a:?}");// similar to println!("{:?}", a);
+println!("{a:#?}");// similar to println!("{:#?}", a);
+
Rust has a print!() macro as well.
print!("Hello, world!\n");// With new line
+print!("Hello, world!");// Without new line
+
The format!() macro is used to store the formatted string.
println!("{}","Hello, world!".to_uppercase());// HELLO, WORLD!
+println!("{}","Hello, world!".to_lowercase());// hello, world!
+
+println!("{}","⭐️".repeat(3));// ⭐️⭐️⭐️
+
+println!("{}","Hello, world!".chars().count());// 13
+// 💡 For more accurate results, you should use a crate like unicode_segmentation that follows more accurate Unicode text segmentation standards.
+
Different format specifiers.
leta=255;
+println!("{a}");// 255
+
+println!("{a:b}");// Binary 💡 11111111
+println!("{a:o}");// Octal 💡 377
+println!("{a:x}");// LowerHex 💡 ff
+println!("{a:X}");// UpperHex 💡 FF
+
+println!("{a:0>5}");// Add leading zeros till character lengh 5 💡 00255
+println!("{a:0<5}");// Add tailing zeros till character lengh 5 💡 25500
+
For more rustc commands, check the rustc --help command.
\ No newline at end of file
diff --git a/docs/docs/hello-world/og.jpg b/docs/docs/hello-world/og.jpg
new file mode 100644
index 00000000..8a117961
Binary files /dev/null and b/docs/docs/hello-world/og.jpg differ
diff --git a/docs/docs/impls/index.html b/docs/docs/impls/index.html
new file mode 100644
index 00000000..a9db088b
--- /dev/null
+++ b/docs/docs/impls/index.html
@@ -0,0 +1,74 @@
+Impls · Learning Rust
Earlier, we discussed that structs and enums group related data, while impl blocks and traits add associated and shared behavior to the data.
Usage of Self vs self keywords:
Self: Refers to the type itself (the blueprint).
self: Refers to the instance of the type (the actual data).
💯 This can be any form of self, &self, &mut self, self: Box<Self>, self: Pin<&mut Self>, etc.
There are multiple ways to implement a behavior for a type. We discuss only about the impl blocks with this article. The patterns involving traits are discussed under Traits.
Inherent impls
Implement associated functions, methods, and constants directly for a type.
⭐️ The implementation must be in the same crate as the type.
impl Type
structPerson{
+name: String,
+}
+
+implPerson{
+constGREET: &str="Hello!";
+
+fngreet(&self)-> String{// &self` is shorthand for self: &Self
+format!("{} I am {}.",Self::GREET,self.name)// 💡Self to access type; self to access instance
+}
+}
+
+fnmain(){
+letsteve=Person{name: "Steve".to_string()};
+println!("{}",steve.greet())// Hello! I am Steve.
+}
+
Inside the impl block,
Constants belong to the type itself.
To access them, use the Self keyword or the type name.
Example: Self::GREET (preferred in Rust) or Person::GREET.
Methods (functions that access instance fields) must send the instance/ self as the first parameter.
This can be self, &self, &mut self, self: Box<Self>, self: Pin<&mut Self>, etc.) as the first parameter.
impl<T> Type<T>
structPoint<T>{
+x: T,
+y: T,
+}
+
+impl<T>Point<T>{
+fninto_tuple(self)-> (T,T){
+(self.x,self.y)
+}
+}
+
+fnmain(){
+leta=Point{x: 0,y: 1};// a: Point<i32>
+letb=a.into_tuple();// (0, 1)
+println!("{b:?}")
+}
+
+// 💡 into_tuple() take self (not &self) and consumes the self / instance.
+// 💡 we can pass &self (as a reference) and use as_ prefix to borrow the instance.
+// fn as_tuple(&self) -> (&T, &T) { (&self.x, &self.y) }
+
Associated Functions & Methods
Associated functions:
Functions that are associated with a particular data type via the impl block.
Can call from the type with :: operator.
Person::new(), Vec::new(), String::from()
Methods:
Associated functions with a receiver of self, &self, &mut self, self: Box<Self>, self: Pin<&mut Self>, etc.
Can call from the instance with . operator or from the type (as methods are also associated functions) with :: operator, but we need to pass the instance as the first parameter always.
steve.greet() or Person::greet(&steve)
"hello".to_string() or String::to_string("hello")
structPerson{
+name: String,
+company_name: String,
+}
+
+implPerson{
+// 💡 The constructor (new` is a conventional name, not a keyword)
+fnnew(name: String,company_name: String)-> Self{// an associated function and not a method
+Self{name,company_name}
+}
+
+fnintro_name(&self)-> String{// a method
+format!("I'm {}",self.name)
+}
+
+fnintro_company(&self)-> String{// a method
+format!("I'm from {}",self.company_name)
+}
+}
+
+fnmain(){
+// Call from the type with `::` operator
+letsteve=Person::new(String::from("Steve Jobs"),String::from("Apple"));
+
+// Call from the instance with `.` operator
+println!("{}. {}.",steve.intro_name(),steve.intro_company());// I'm Steve Jobs. I'm from Apple.
+
+// As methods are also associated functions; Call from the type with `::` operator and pass the instance as the first parameter
+println!("{}. {}.",Person::intro_name(&steve),Person::intro_company(&steve));// I'm Steve Jobs. I'm from Apple.
+}
+
We can use the type/ Person instead Self keyword in the new function. By the way, using the Self keyword is considered idiomatic in Rust.
Familiarize with the conventional prefixes and suffixes used in methods names.
Prefix
Postfix
self taken
self type
as_
none
&self or &mut self
any
from_
none
none
any
into_
none
self
any
is_
none
&mut self or &self or none
any
to_
_mut
&mut self
any
to_
not _mut
self
Copy
to_
not _mut
&self
not Copy
\ No newline at end of file
diff --git a/docs/docs/impls/og.jpg b/docs/docs/impls/og.jpg
new file mode 100644
index 00000000..dd52ce0d
Binary files /dev/null and b/docs/docs/impls/og.jpg differ
diff --git a/docs/docs/index.html b/docs/docs/index.html
new file mode 100644
index 00000000..d5acc52f
--- /dev/null
+++ b/docs/docs/index.html
@@ -0,0 +1 @@
+https://learning-rust.github.io/docs/overview/
\ No newline at end of file
diff --git a/docs/docs/index.xml b/docs/docs/index.xml
new file mode 100644
index 00000000..68f19aca
--- /dev/null
+++ b/docs/docs/index.xml
@@ -0,0 +1,453 @@
+Docs on Learning Rusthttps://learning-rust.github.io/docs/Recent content in Docs on Learning RustHugoen-USBorrowinghttps://learning-rust.github.io/docs/borrowing/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/borrowing/<p>In real life applications, most of the times we have to pass variable bindings to other functions or assign them to other variable bindings. In this case, we are <strong>referencing</strong> the original binding; <strong>borrow</strong> the data of it.</p>
+<h2 id="what-is-borrowing">What is Borrowing?</h2>
+<blockquote>
+<p><a href="https://github.com/nikomatsakis/rust-tutorials-keynote/blob/master/Ownership%20and%20Borrowing.pdf" target="_blank" >Borrow (verb)</a><br>
+To receive something with the promise of returning it.</p>
+</blockquote>
+<h2 id="shared--mutable-borrowings">Shared & Mutable borrowings</h2>
+<p>⭐️ There are two types of Borrowing,</p>
+<ol>
+<li>
+<p><strong>Shared Borrowing</strong> <code>(&T)</code></p>
+<ul>
+<li>A piece of data can be <strong>borrowed by a single or multiple users</strong>, but <strong>data should not be altered</strong>.</li>
+</ul>
+</li>
+<li>
+<p><strong>Mutable Borrowing</strong> <code>(&mut T)</code></p>Cargo, Crates and Basic Project Structurehttps://learning-rust.github.io/docs/cargo-crates-and-basic-project-structure/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/cargo-crates-and-basic-project-structure/<h2 id="cargo">Cargo</h2>
+<p>Cargo is Rust’s built-in package manager and build system. It also supports the following actions,</p>
+<table>
+ <thead>
+ <tr>
+ <th>Command</th>
+ <th>Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>cargo new</code></td>
+ <td>Create a new project</td>
+ </tr>
+ <tr>
+ <td><code>cargo init</code></td>
+ <td>Create a new project in an existing directory</td>
+ </tr>
+ <tr>
+ <td><code>cargo check</code></td>
+ <td>Verify the project compiles without errors</td>
+ </tr>
+ <tr>
+ <td><code>cargo build</code></td>
+ <td>Build the executable</td>
+ </tr>
+ <tr>
+ <td><code>cargo run</code></td>
+ <td>Build the executable and run</td>
+ </tr>
+ <tr>
+ <td><code>cargo clean</code></td>
+ <td>Remove the build system directories/ <code>target</code> directory</td>
+ </tr>
+ </tbody>
+</table>
+<blockquote>
+<p>💡 The <code>cargo check</code> command verifies that the project compiles without errors, without producing an executable.
+Thus, it is often faster than <code>cargo build</code>.</p>Combinatorshttps://learning-rust.github.io/docs/combinators/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/combinators/<h2 id="what-is-a-combinator">What is a combinator?</h2>
+<ul>
+<li>
+<p>One meaning of “combinator” is a more informal sense referring to the <strong>combinator pattern</strong>, a style of organizing libraries centered around the idea of combining things. Usually there is <strong>some type T</strong>, some <strong>functions for constructing “primitive” values of type T</strong>, and some “<strong>combinators</strong>” which can <strong>combine values of type T</strong> in various ways to <strong>build up more complex values of type T</strong>. The other definition is <strong>“function with no free variables”</strong>.
+__ <a href="https://wiki.haskell.org/Combinator" target="_blank" >wiki.haskell.org</a></p>Comments and Documenting the codehttps://learning-rust.github.io/docs/comments-and-documenting-the-code/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/comments-and-documenting-the-code/<h2 id="comments">Comments</h2>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">// Line comments
+</span></span></span><span class="line"><span class="cl"><span class="cm">/* Block comments */</span><span class="w">
+</span></span></span></code></pre></div><p>Nested block comments are supported.</p>
+<p>💡 <strong>By convention, try to avoid using block comments. Use line comments instead.</strong></p>
+<h2 id="doc-comments">Doc Comments</h2>
+<p><a href="https://learning-rust.github.io/docs/cargo-crates-and-basic-project-structure/#cargo" >As we discussed</a>, we can generate the project documentation via <a href="https://doc.rust-lang.org/stable/rustdoc/" target="_blank" >rustdoc</a> by running the <strong><code>cargo doc</code></strong> command. It uses the doc comments to generate the documentation.</p>
+<p>💡 Usually we are adding doc comments on library crates. Also, we can use <a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet" target="_blank" >Markdown notations</a> inside the doc comments.</p>Control Flowshttps://learning-rust.github.io/docs/control-flows/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/control-flows/<h2 id="if---else-if---else">if - else if - else</h2>
+<h3 id="if"><code>if</code></h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">age</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">13</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="w"> </span><span class="n">age</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">18</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, child!"</span><span class="p">);</span><span class="w"> </span><span class="c1">// The code prints this
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="if-else"><code>if</code> <code>else</code></h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">7</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Even"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Odd"</span><span class="p">);</span><span class="w"> </span><span class="c1">// The code prints this
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="with-let-statements">With <code>let</code> Statements</h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">age</span>: <span class="kt">u8</span> <span class="o">=</span><span class="w"> </span><span class="mi">13</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">is_below_eighteen</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">age</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">18</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kc">false</span><span class="w"> </span><span class="p">};</span><span class="w"> </span><span class="c1">// true
+</span></span></span></code></pre></div><h3 id="if-else-if-else"><code>if</code> <code>else if</code> <code>else</code></h3>
+<p>i. A simple example,</p>Crateshttps://learning-rust.github.io/docs/crates/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/crates/<p>💭 Crates are a bit similar to the packages in some other languages. Crates compile individually. If the crate has child file modules, those files will get merged with the crate file and compile as a single unit.</p>
+<p>💭 A crate can produce an executable/ a binary or a library. <code>src/main.rs</code> is the crate root/ entry point for a binary crate and <code>src/lib.rs</code> is the entry point for a library crate.</p>Custom Error Typeshttps://learning-rust.github.io/docs/custom-error-types/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/custom-error-types/<p>Rust allow us to create our own <code>Err</code> types. We call them “<em>Custom Error Types</em>”.</p>
+<h2 id="error-trait">Error trait</h2>
+<p>As you know <strong>traits define the functionality a type must provide</strong>. But we don’t always need to define new traits for common functionalities, because Rust <strong>standard library provides reusable traits</strong> which can be implemented on our own types. While creating custom error types the <a href="https://doc.rust-lang.org/std/error/trait.Error.html" target="_blank" ><code>std::error::Error</code> trait</a> helps us to convert any type to an <code>Err</code> type.</p>Enumshttps://learning-rust.github.io/docs/enums/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/enums/<ul>
+<li>An enum is a single type that contains variants, which represent the possible values of the enum at any given time.</li>
+<li>By convention, the enum name and its variants’ names should follow <a href="https://en.wikipedia.org/wiki/Camel_case" target="_blank" ><code>PascalCase</code></a>.</li>
+<li>Can access the variants using the <code>::</code> notation and the variant name. ex. Day::Sunday</li>
+</ul>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">enum</span> <span class="nc">Day</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Sunday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Monday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Tuesday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Wednesday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Thursday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Friday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Saturday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// 💡 Day is the enum. Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday are its variants.
+</span></span></span></code></pre></div><ul>
+<li>An enum variant can have either,
+<ul>
+<li>No data (a unit variant)</li>
+<li>Unnamed ordered data (a tuple variant)</li>
+<li>Named data/ fields (a struct variant)</li>
+</ul>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">enum</span> <span class="nc">FlashMessage</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Success</span><span class="p">,</span><span class="w"> </span><span class="c1">// 💡 A unit variant (no data)
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Error</span><span class="p">(</span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="nb">String</span><span class="p">),</span><span class="w"> </span><span class="c1">// 💡 A tuple variant (one or more , separated data)
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Warning</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">field</span>: <span class="nb">String</span><span class="p">,</span><span class="w"> </span><span class="n">message</span>: <span class="nb">String</span> <span class="p">},</span><span class="w"> </span><span class="c1">// 💡 A struct variant (one or more , separated name: value data)
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// 💡 FlashMessage is the emnum, Success, Error, Warning are its variants.
+</span></span></span></code></pre></div></li>
+</ul>
+<blockquote>
+<p>💡 In Rust, the term “instantiation” is used to describe the act of creating a concrete instance of a type (struct or enum).</p>Error and None Propagationhttps://learning-rust.github.io/docs/error-and-none-propagation/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/error-and-none-propagation/<p>We should use panics like <code>panic!()</code>, <code>unwrap()</code>, <code>expect()</code> only if we can not handle the situation in a better way. Also if a function contains expressions which can produce either <code>None</code> or <code>Err</code>,</p>
+<ul>
+<li>we can handle them inside the same function. Or,</li>
+<li>we can return <code>None</code> and <code>Err</code> types immediately to the caller. So the caller can decide how to handle them.</li>
+</ul>
+<p>💡 <code>None</code> types no need to handle by the caller of the function always. But Rusts’ convention to handle <strong><code>Err</code></strong> types is, <strong>return them immediately to the caller to give more control to the caller to decide how to handle them.</strong></p>Functionshttps://learning-rust.github.io/docs/functions/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/functions/<h2 id="named-functions">Named Functions</h2>
+<ul>
+<li>Named functions are declared with the keyword <strong><code>fn</code></strong></li>
+<li>When using <strong>arguments</strong>, we <strong>must declare the data types</strong>.</li>
+<li>By default, functions <strong>return an empty <a href="https://learning-rust.github.io/docs/primitive-data-types/#tuple" >tuple</a>/ <code>()</code></strong>. If you want to return a value, the <strong>return type must be specified</strong> after <strong><code>-></code></strong></li>
+</ul>
+<h3 id="hello-world">Hello world</h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="passing-arguments">Passing Arguments</h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">print_sum</span><span class="p">(</span><span class="n">a</span>: <span class="kt">i8</span><span class="p">,</span><span class="w"> </span><span class="n">b</span>: <span class="kt">i8</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"sum is: </span><span class="si">{}</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">b</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="returning-values">Returning Values</h3>
+<ul>
+<li>
+<p>Without the <code>return</code> keyword. Only the last expression returns.</p>Genericshttps://learning-rust.github.io/docs/generics/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/generics/<ul>
+<li>The core concept of generics is abstraction over types. They let us write one piece of code to operate with any data type without repeating ourselves to write separate versions for each type. At the compile time, Rust ensures the type safety and generates an optimized code for each concrete type used in the program.</li>
+<li>Use an uppercase letter (<code>T</code>, <code>U</code>, …) or a <a href="https://en.wikipedia.org/wiki/Camel_case" target="_blank" ><code>PascalCase</code></a> identifier for the data type.
+<ul>
+<li>Instead of <code>x: u8</code> we use <code>x: T</code>.</li>
+<li>Inform the compiler that <code>T</code> is a generic type by adding <code><T></code> at first.</li>
+</ul>
+</li>
+</ul>
+<h2 id="with-one-generic-type">With One Generic Type</h2>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Point</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">x</span>: <span class="nc">T</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">y</span>: <span class="nc">T</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">to_tuple</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">(</span><span class="n">x</span>: <span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="nc">T</span><span class="p">)</span><span class="w"> </span>-> <span class="p">(</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span>: <span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="mi">1</span><span class="w"> </span><span class="p">};</span><span class="w"> </span><span class="c1">// a: Point<i32>
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">to_tuple</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">y</span><span class="p">);</span><span class="w"> </span><span class="c1">// (i32, i32)
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{b:?}</span><span class="s">"</span><span class="p">);</span><span class="w"> </span><span class="c1">// (0, 1)
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span>: <span class="nc">false</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="nc">true</span><span class="w"> </span><span class="p">};</span><span class="w"> </span><span class="c1">// a: Point<bool>
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">to_tuple</span><span class="p">(</span><span class="n">c</span><span class="p">.</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="p">.</span><span class="n">y</span><span class="p">);</span><span class="w"> </span><span class="c1">// (bool, bool)
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{d:?}</span><span class="s">"</span><span class="p">);</span><span class="w"> </span><span class="c1">// (false, true)
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h2 id="with-multiple-generic-types">With Multiple Generic Types</h2>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Point</span><span class="o"><</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">U</span><span class="o">></span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">x</span>: <span class="nc">T</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">y</span>: <span class="nc">U</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">to_shuffled_tuple</span><span class="o"><</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">U</span><span class="o">></span><span class="p">(</span><span class="n">x</span>: <span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="nc">U</span><span class="p">)</span><span class="w"> </span>-> <span class="p">(</span><span class="n">U</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="p">,</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span>: <span class="mi">1</span><span class="k">u8</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="nc">true</span><span class="w"> </span><span class="p">};</span><span class="w"> </span><span class="c1">// a: Point<u8, bool>
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">to_shuffled_tuple</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">y</span><span class="p">);</span><span class="w"> </span><span class="c1">// (bool, u8)
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{b:?}</span><span class="s">"</span><span class="p">);</span><span class="w"> </span><span class="c1">// (true, 1)
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><p>On some occasions, the compiler cannot inter the type, and we have to specify the type when using the generic type. By the way, it’s good practice to specify the type on variables when using a generic implementation.</p>Hello Worldhttps://learning-rust.github.io/docs/hello-world/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/hello-world/<h2 id="hello-world">Hello, World!</h2>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><p><code>fn</code> means function. The <code>main</code> function is the beginning of every Rust program.
+<code>println!()</code> prints text to the console and its <code>!</code> indicates that it’s a <a href="https://doc.rust-lang.org/book/ch19-06-macros.html" target="_blank" >macro</a> rather than a function.</p>
+<blockquote>
+<p>💡 Rust files should have <code>.rs</code> file extension and if you’re using more than one word for the file name, follow the <a href="https://en.wikipedia.org/wiki/Snake_case" target="_blank" >snake_case</a> convention.</p>
+</blockquote>
+<ul>
+<li>Save the above code in <code>file.rs</code> , but it can be any name with <code>.rs</code> extension.</li>
+<li>Compile it with <code>rustc file.rs</code></li>
+<li>Execute it with <code>./file</code> on Linux and Mac or <code>file.exe</code> on Windows</li>
+</ul>
+<h2 id="rust-playground">Rust Playground</h2>
+<p><a href="https://play.rust-lang.org/" target="_blank" >Rust Playground</a> is a web interface for running Rust code.</p>Implshttps://learning-rust.github.io/docs/impls/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/impls/<ul>
+<li>Earlier, we discussed that structs and enums group related data, while impl blocks and traits add associated and shared behavior to the data.</li>
+<li>Usage of <code>Self</code> vs <code>self</code> keywords:
+<ul>
+<li><code>Self</code>: Refers to the type itself (the blueprint).</li>
+<li><code>self</code>: Refers to the instance of the type (the actual data).
+<ul>
+<li>💯 This can be any form of <code>self</code>, <code>&self</code>, <code>&mut self</code>, <code>self: Box<Self></code>, <code>self: Pin<&mut Self></code>, etc.</li>
+</ul>
+</li>
+</ul>
+</li>
+<li>There are multiple ways to implement a behavior for a type. We discuss only about the <code>impl</code> blocks with this article. The patterns involving traits are discussed under <a href="https://learning-rust.github.io/docs/traits" >Traits</a>.</li>
+</ul>
+<h2 id="inherent-impls">Inherent impls</h2>
+<p>Implement associated functions, methods, and constants directly for a type.</p>Installationhttps://learning-rust.github.io/docs/installation/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/installation/<h2 id="rustup">Rustup</h2>
+<p>There are many ways to install Rust on your system. For the moment the official way to install Rust is using <a href="https://rustup.rs/" target="_blank" >Rustup</a>.</p>
+<p><a href="https://rust-lang.github.io/rustup/index.html" target="_blank" >📖</a> Rustup installs The Rust Programming Language from the official release channels, enabling you to easily switch between <strong>stable, beta, and nightly</strong> compilers and keep them updated. It also makes cross-compiling simpler with binary builds of the standard library for common platforms.</p>
+<p><a href="https://rust-lang.github.io/rustup/installation/index.html" target="_blank" >📖</a> Rustup installs <code>rustc</code>, <code>cargo</code>, <code>rustup</code> and other standard tools to <strong>Cargo’s <code>bin</code> directory</strong>. On Unix it is located at <code>$HOME/.cargo/bin</code> and on Windows at <code>%USERPROFILE%\.cargo\bin</code>. This is the same directory that <code>cargo install</code> will install Rust programs and Cargo plugins.</p>Lifetimeshttps://learning-rust.github.io/docs/lifetimes/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/lifetimes/<p>When we are dealing with references, we have to make sure that the referencing data stay alive until we stop using the references.</p>
+<p>Think,</p>
+<ul>
+<li>We have a <strong>variable binding</strong>, <code>a</code>.</li>
+<li>We are <strong>referencing</strong> the value of <code>a</code>, <strong>from another variable binding</strong> <code>x</code>.
+We have to make sure that <strong><code>a</code> lives until we stop using <code>x</code></strong>.</li>
+</ul>
+<blockquote>
+<p>🔎 <strong>Memory management</strong> is a form of resource management applied to computer memory. Up until the mid-1990s, the majority of programming languages used <strong>Manual Memory Management</strong> which <strong>requires the programmer to give manual instructions</strong> to identify and deallocate unused objects/ garbage. Around 1959 John McCarthy invented <strong>Garbage collection</strong>(GC), a form of <strong>Automatic Memory Management</strong>(AMM). It determines what memory is no longer used and frees it automatically instead of relying on the programmer. However <strong>Objective-C and Swift</strong> provide similar functionality through <strong>Automatic Reference Counting</strong>(ARC).</p>Moduleshttps://learning-rust.github.io/docs/modules/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/modules/<h2 id="01-in-the-same-file">01. In the same file</h2>
+<p>Related code and data are grouped into a module and stored in the same file.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">greetings</span>::<span class="n">hello</span><span class="p">();</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">mod</span> <span class="nn">greetings</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c1">// ⭐️ By default, everything inside a module is private
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">hello</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// ⭐️ So function has to be public to access from outside
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><p>Modules can also be nested.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">phrases</span>::<span class="n">greetings</span>::<span class="n">hello</span><span class="p">();</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">mod</span> <span class="nn">phrases</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">mod</span> <span class="nn">greetings</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">hello</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><p>Private functions can be called from the same module or from a child module.</p>Operatorshttps://learning-rust.github.io/docs/operators/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/operators/<h2 id="arithmetic-operators">Arithmetic Operators</h2>
+<p><code>+ - * / %</code></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="c1">// 6
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="c1">// 4
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span><span class="w"> </span><span class="c1">// 10
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span><span class="w"> </span><span class="c1">// ⭐️ 2 not 2.5
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span><span class="w"> </span><span class="c1">// 1
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">5.0</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2.0</span><span class="p">;</span><span class="w"> </span><span class="c1">// 2.5
+</span></span></span></code></pre></div><h2 id="comparison-operators">Comparison Operators</h2>
+<p><code>== != < > <= >=</code></p>Option and Resulthttps://learning-rust.github.io/docs/option-and-result/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/option-and-result/<h2 id="why-option-and-result">Why Option and Result?</h2>
+<p>Many languages use <strong><code>null</code>\ <code>nil</code>\ <code>undefined</code> types</strong> to represent empty outputs, and <strong><code>Exceptions</code></strong> to handle errors. Rust skips using both, especially to prevent issues like <strong>null pointer exceptions, sensitive data leakages through exceptions</strong>, etc. Instead, Rust provides two special <strong>generic enums</strong>;<code>Option</code> and <code>Result</code> to deal with above cases.</p>
+<blockquote>
+<p>💭 In the previous sections, we have discussed about the basics of <a href="https://learning-rust.github.io/docs/enums" >enums</a>, <a href="https://learning-rust.github.io/docs/generics" >generics</a> and <a href="https://learning-rust.github.io/docs/generics/#generalizing-enums" ><code>Result</code> & <code>Option</code> types</a>.</p>Overviewhttps://learning-rust.github.io/docs/overview/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/overview/<h2 id="about-me">About me</h2>
+<blockquote>
+<p>🧑💻 I am an expat working in Singapore as a Go Backend and DevOps Engineer. Feel free to reach out if you find any mistakes or anything that needs to be changed, including spelling or grammar errors. Alternatively, you can create a pull request, open an issue, or <a href="https://gist.github.com/dumindu/00a0be2d175ed5ff3bc3c17bbf1ca5b6" target="_blank" >share your awesome ideas in this gist</a>. Good luck with learning Rust!</p>
+</blockquote>
+<p><a href="https://github.com/learning-rust/learning-rust.github.io" target="_blank" ><img src="https://img.shields.io/github/stars/learning-rust/learning-rust.github.io?style=for-the-badge&logo=rust&label=learning-rust.github.io&logoColor=333333&labelColor=f9f9f9&color=F46623" alt="learning-rust.github.io"></a>
+<a href="https://learning-cloud-native-go.github.io" target="_blank" ><img src="https://img.shields.io/github/stars/learning-cloud-native-go/learning-cloud-native-go.github.io?style=for-the-badge&logo=go&logoColor=333333&label=learning-cloud-native-go.github.io&labelColor=f9f9f9&color=00ADD8" alt="learning-cloud-native-go.github.io"></a></p>
+<p><a href="https://github.com/dumindu" target="_blank" ><img src="https://img.shields.io/badge/dumindu-866ee7?style=for-the-badge&logo=GitHub&logoColor=333333&labelColor=f9f9f9" alt="github.com"></a>
+<a href="https://www.buymeacoffee.com/dumindu" target="_blank" ><img src="https://img.shields.io/badge/Buy%20me%20a%20coffee-dumindu-FFDD00?style=for-the-badge&logo=buymeacoffee&logoColor=333333&labelColor=f9f9f9" alt="buymeacoffee"></a></p>
+<h2 id="overview">Overview</h2>
+<p>This publication has its origins in the posts I authored on Medium at <a href="https://medium.com/learning-rust" target="_blank" >https://medium.com/learning-rust</a>. However, please note that I have ceased updating the Medium posts. All current and future updates, new content, code, and grammar fixes will be exclusively maintained and released here, <a href="https://learning-rust.github.io" target="_blank" >https://learning-rust.github.io</a>.</p>Ownershiphttps://learning-rust.github.io/docs/ownership/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/ownership/<p>We discussed in the <a href="https://learning-rust.github.io/docs/traits/#derive-traits" >Derive Traits</a>, the usage of <a href="https://doc.rust-lang.org/std/marker/trait.Copy.html" target="_blank" ><code>Copy</code> marker trait</a> and <a href="https://doc.rust-lang.org/std/clone/index.html" target="_blank" ><code>.clone()</code></a> with the below code.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="cp">#[derive(Debug, Clone, Copy)]</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Point</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">x</span>: <span class="kt">i32</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">y</span>: <span class="kt">i32</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span>: <span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="mi">1</span><span class="w"> </span><span class="p">};</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{a:?}</span><span class="s">, </span><span class="si">{b:?}</span><span class="s">"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><p>If we try to remove <code>Copy</code> derive on <code>Point</code> and run, we will get the following error while compiling.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="n">error</span><span class="p">[</span><span class="n">E0382</span><span class="p">]</span>: <span class="nc">borrow</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">moved</span><span class="w"> </span><span class="n">value</span>: <span class="err">`</span><span class="n">a</span><span class="err">`</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">-</span>-> <span class="nc">src</span><span class="o">/</span><span class="n">main</span><span class="p">.</span><span class="n">rs</span>:<span class="mi">11</span>:<span class="mi">16</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span>: <span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="mi">1</span><span class="w"> </span><span class="p">};</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="k">move</span><span class="w"> </span><span class="n">occurs</span><span class="w"> </span><span class="n">because</span><span class="w"> </span><span class="err">`</span><span class="n">a</span><span class="err">`</span><span class="w"> </span><span class="n">has</span><span class="w"> </span><span class="k">type</span> <span class="err">`</span><span class="n">Point</span><span class="err">`</span><span class="p">,</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="n">does</span><span class="w"> </span><span class="n">not</span><span class="w"> </span><span class="n">implement</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="err">`</span><span class="nb">Copy</span><span class="err">`</span><span class="w"> </span><span class="k">trait</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="mi">9</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="n">moved</span><span class="w"> </span><span class="n">here</span><span class="w">
+</span></span></span></code></pre></div><p>This is because of Ownership, which is used to achieve Rust’s memory safety.</p>Panickinghttps://learning-rust.github.io/docs/panicking/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/panicking/<h2 id="panic">panic!()</h2>
+<ul>
+<li>In some cases, when an error occurs we can not do anything to handle it, <strong>if the error is something which should not have happened</strong>. In other words, if it’s an <strong>unrecoverable error</strong>.</li>
+<li>Also <strong>when we are not using a feature-rich debugger or proper logs</strong>, sometimes we need to <strong>debug the code by quitting the program from a specific line of code</strong> by printing out a specific message or a value of a variable binding to understand the current flow of the program.
+For above cases, we can use <code>panic!</code> macro.</li>
+</ul>
+<p>⭐ <code>panic!()</code> runs <strong>thread based</strong>. One thread can be panicked, while other threads are running.</p>Primitive Data Typeshttps://learning-rust.github.io/docs/primitive-data-types/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/primitive-data-types/<h2 id="bool">bool</h2>
+<p>true or false</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">b</span>: <span class="kt">bool</span> <span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// ⭐️ no TRUE, FALSE, 1, 0
+</span></span></span></code></pre></div><p>bool is a single byte(8 bits) in size.</p>
+<h2 id="char">char</h2>
+<p>A single Unicode scalar value</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sc">'x'</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">b</span>: <span class="kt">char</span> <span class="o">=</span><span class="w"> </span><span class="sc">'😎'</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// ⭐️ no "x", only single quotes
+</span></span></span></code></pre></div><p>Because of Unicode support, char is not a single byte, but four(32 bits).</p>
+<h2 id="i8-i16-i32-i64-i128">i8, i16, i32, i64, i128</h2>
+<p>8, 16, 32, 64 and 128 bit fixed sized signed(+/-) integer types</p>Smart Compilerhttps://learning-rust.github.io/docs/smart-compiler/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/smart-compiler/<h2 id="why-compiler">Why Compiler?</h2>
+<p>The Rust compiler does the most significant job to prevent errors in Rust programs. It <strong>analyzes the code at compile-time</strong> and issues warnings, if the code does not follow memory management rules or lifetime annotations correctly.</p>
+<p>For example,</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="cp">#[allow(unused_variables)]</span><span class="w"> </span><span class="c1">//💡 A lint attribute used to suppress the warning; unused variable: `b`
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">];</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{:?}</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// ------ Compile-time error ------
+</span></span></span><span class="line"><span class="cl"><span class="n">error</span><span class="p">[</span><span class="n">E0382</span><span class="p">]</span>: <span class="nc">use</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">moved</span><span class="w"> </span><span class="n">value</span>: <span class="err">`</span><span class="n">a</span><span class="err">`</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">-</span>-> <span class="nc">src</span><span class="o">/</span><span class="n">main</span><span class="p">.</span><span class="n">rs</span>:<span class="mi">6</span>:<span class="mi">22</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="mi">3</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="n">moved</span><span class="w"> </span><span class="n">here</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="mi">4</span><span class="w"> </span><span class="o">|</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="mi">5</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{:?}</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="n">used</span><span class="w"> </span><span class="n">here</span><span class="w"> </span><span class="n">after</span><span class="w"> </span><span class="k">move</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">note</span>: <span class="nc">move</span><span class="w"> </span><span class="n">occurs</span><span class="w"> </span><span class="n">because</span><span class="w"> </span><span class="err">`</span><span class="n">a</span><span class="err">`</span><span class="w"> </span><span class="n">has</span><span class="w"> </span><span class="k">type</span> <span class="err">`</span><span class="n">std</span>::<span class="n">vec</span>::<span class="nb">Vec</span><span class="o"><</span><span class="kt">i32</span><span class="o">></span><span class="err">`</span><span class="p">,</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="n">does</span><span class="w"> </span><span class="n">not</span><span class="w"> </span><span class="n">implement</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="err">`</span><span class="nb">Copy</span><span class="err">`</span><span class="w"> </span><span class="k">trait</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="n">error</span>: <span class="nc">aborting</span><span class="w"> </span><span class="n">due</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">previous</span><span class="w"> </span><span class="n">error</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="n">For</span><span class="w"> </span><span class="n">more</span><span class="w"> </span><span class="n">information</span><span class="w"> </span><span class="n">about</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">error</span><span class="p">,</span><span class="w"> </span><span class="kr">try</span><span class="w"> </span><span class="err">`</span><span class="n">rustc</span><span class="w"> </span><span class="o">--</span><span class="n">explain</span><span class="w"> </span><span class="n">E0382</span><span class="err">`</span><span class="p">.</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// ⭐ instead using #[allow(unused_variables)], consider using "let _b = a;" in line 4.
+</span></span></span><span class="line"><span class="cl"><span class="c1">// Also you can use "let _ =" to completely ignore return values
+</span></span></span></code></pre></div><blockquote>
+<p>💭 In the previous sections, we have discussed memory management concepts like <a href="https://learning-rust.github.io/docs/ownership" >ownership</a>, <a href="https://learning-rust.github.io/docs/borrowing" >borrowing</a>, <a href="https://learning-rust.github.io/docs/lifetimes" >lifetimes</a> and etc.</p>STD, Primitives and Preludeshttps://learning-rust.github.io/docs/std-primitives-and-preludes/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/std-primitives-and-preludes/<p>⭐️ In Rust, language elements are implemented by not only <strong><code>std</code> library</strong> crate but also <strong>compiler</strong> as well. Examples,</p>
+<ul>
+<li><strong><a href="https://doc.rust-lang.org/std/#primitives" target="_blank" >Primitives</a></strong>: Defined by the compiler and methods are implemented by <code>std</code> library directly on primitives.</li>
+<li><strong><a href="https://doc.rust-lang.org/std/#macros" target="_blank" >Standard Macros</a></strong>: Defined by both compiler and <code>std</code></li>
+</ul>
+<p>The <strong><code>std</code></strong> library has been divided into <strong><a href="https://doc.rust-lang.org/std/#modules" target="_blank" >modules</a></strong>, according to the main areas each covered.</p>
+<p>⭐️ While primitives are implemented by the <strong>compiler</strong>, the standard library implements the <strong>most useful methods</strong> directly on the primitive types. But some <strong>rarely useful language elements</strong> of some primitives are stored on relevant <strong><code>std</code> modules</strong>. This is why you can see <code>char</code>, <code>str</code> and integer types on both <a href="https://doc.rust-lang.org/std/#primitives" target="_blank" >primitives</a> and <a href="https://doc.rust-lang.org/std/#modules" target="_blank" ><code>std</code> modules</a>.</p>Structshttps://learning-rust.github.io/docs/structs/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/structs/<ul>
+<li>Used to <strong>encapsulate related properties into one unified data type</strong>.</li>
+<li>By convention, the name should follow <a href="https://en.wikipedia.org/wiki/Camel_case" target="_blank" ><code>PascalCase</code></a>.</li>
+<li>3 variants,
+<ul>
+<li>
+<p>C-like structs: One or more <code>,</code> separated <code>name: value pairs</code> enclosed in <code>{}</code></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Color</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">red</span>: <span class="kt">u8</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">green</span>: <span class="kt">u8</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">blue</span>: <span class="kt">u8</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div></li>
+<li>
+<p>Tuple structs: One or more <code>,</code> separated <code>values</code> enclosed in <code>()</code></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Color</span><span class="p">(</span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="kt">u8</span><span class="p">);</span><span class="w">
+</span></span></span></code></pre></div></li>
+<li>
+<p>Unit structs: A struct with no fields/ members</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Black</span><span class="p">;</span><span class="w">
+</span></span></span></code></pre></div></li>
+</ul>
+</li>
+</ul>
+<blockquote>
+<p>⭐️ In Rust, data (attributes) and behavior (associated functions and methods) are placed separately. Structs and Enums are used to group related data, and impls and traits are used to add associated and shared behavior to that data.</p>Traitshttps://learning-rust.github.io/docs/traits/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/traits/<p>A trait is a contract that defines a set of behaviors or properties that a type must implement. It can contain associated types, constants, function or method signatures, and overridable default implementations.</p>
+<h2 id="definition">Definition</h2>
+<h3 id="with-no-associates">With No Associates</h3>
+<p>💡 Mostly used to mark a type as having certain properties to allow in certain operations. Known as Marker Traits.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">pub</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="nb">Sized</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="with-the-declarations-of-associates">With the Declarations of Associates</h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">trait</span><span class="w"> </span><span class="n">Greet</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="no">PREFIX</span>: <span class="kp">&</span><span class="nb">'static</span> <span class="kt">str</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">type</span> <span class="nc">Item</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">fn</span> <span class="nf">greet</span><span class="p">(</span><span class="o">&</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">String</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="with-the-default-implementations-of-associates">With the Default Implementations of Associates</h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">trait</span><span class="w"> </span><span class="n">Greet</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="no">PREFIX</span>: <span class="kp">&</span><span class="nb">'static</span> <span class="kt">str</span> <span class="o">=</span><span class="w"> </span><span class="s">"Hello"</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">fn</span> <span class="nf">greet</span><span class="p">(</span><span class="o">&</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">String</span> <span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">format!</span><span class="p">(</span><span class="s">"</span><span class="si">{}</span><span class="s">!"</span><span class="p">,</span><span class="w"> </span><span class="nb">String</span>::<span class="n">from</span><span class="p">(</span><span class="bp">Self</span>::<span class="no">PREFIX</span><span class="p">))</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="with-supertraits">With Supertraits</h3>
+<p>A trait must have to be implemented first before implementing the current trait.</p>Unwrap and Expecthttps://learning-rust.github.io/docs/unwrap-and-expect/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/unwrap-and-expect/<h2 id="unwrap">unwrap()</h2>
+<ul>
+<li>If an <code>Option</code> type has <strong><code>Some</code></strong> value or a <code>Result</code> type has a <strong><code>Ok</code></strong> value, <strong>the value inside them</strong> passes to the next step.</li>
+<li>If the <code>Option</code> type has <strong><code>None</code></strong> value or the <code>Result</code> type has <strong><code>Err</code></strong> value, <strong>program panics</strong>; If <code>Err</code>, panics with the error message.</li>
+</ul>
+<p>The functionality is bit similar to the following codes, which are using <code>match</code> instead <code>unwrap()</code>.</p>
+<p>Example with <code>Option</code> and <code>match</code>, before using <code>unwrap()</code></p>Usehttps://learning-rust.github.io/docs/use/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/use/<p>Let’s see the main usages of the <code>use</code> keyword.</p>
+<h2 id="01-bind-a-full-path-to-a-new-name">01. Bind a full path to a new name</h2>
+<p>Mainly <code>use</code> keyword is used to bind a full path of an element to a new name. So the user doesn’t want to repeat the full path each time.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">// -- Initial code without the `use` keyword --
+</span></span></span><span class="line"><span class="cl"><span class="k">mod</span> <span class="nn">phrases</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">mod</span> <span class="nn">greetings</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">hello</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">phrases</span>::<span class="n">greetings</span>::<span class="n">hello</span><span class="p">();</span><span class="w"> </span><span class="c1">// Using full path
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// -- Usage of the `use` keyword --
+</span></span></span><span class="line"><span class="cl"><span class="c1">// 01. Create an alias for module
+</span></span></span><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">phrases</span>::<span class="n">greetings</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">greetings</span>::<span class="n">hello</span><span class="p">();</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// 02. Create an alias for module elements
+</span></span></span><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">phrases</span>::<span class="n">greetings</span>::<span class="n">hello</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">hello</span><span class="p">();</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// 03. Customize names with the `as` keyword
+</span></span></span><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">phrases</span>::<span class="n">greetings</span>::<span class="n">hello</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">greet</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">greet</span><span class="p">();</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h2 id="02-import-elements-to-scope">02. Import elements to scope</h2>
+<p>Another common usage of <code>use</code> is importing elements to scope. Remember that, this is also a bit similar to creating an alias and using it instead of using the full path.</p>Variable bindings, Constants & Staticshttps://learning-rust.github.io/docs/variable-bindings-constants-and-statics/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/variable-bindings-constants-and-statics/<ul>
+<li>Rust is a statically typed language; it checks data types at compile-time. But it doesn’t require you to actually type data types when declaring variable bindings. In that case, the compiler checks the usage and sets a better data type for it.</li>
+<li>⭐️ For <strong>constants and statics, we must annotate the data type</strong>.</li>
+<li>Types come after a <code>:</code> (colon) sign.</li>
+<li>The naming convention for the variable bindings is using the <a href="https://en.wikipedia.org/wiki/Snake_case" target="_blank" ><code>snake_case</code></a>. But, for constants and statics, we should follow the <a href="https://en.wikipedia.org/wiki/Snake_case" target="_blank" ><code>SCREAMING_SNAKE_CASE</code></a>.</li>
+</ul>
+<blockquote>
+<p>💭 In the following examples, we will use <a href="https://learning-rust.github.io/docs/primitive-data-types" >data types</a> like <code>bool</code>, <code>i32</code>, <code>i64</code> and <code>f64</code>. Don’t worry about them for now; they’ll be discussed later.</p>Vectorshttps://learning-rust.github.io/docs/vectors/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/vectors/<p>If you remember, the array is a fixed-size list of elements, of the same data type. Even with mut, its element count cannot be changed. A vector is <strong>kind of a re-sizable array</strong> but <strong>all elements must be in the same type</strong>.</p>
+<blockquote>
+<p>💡 <code>Vec<T></code>: capital “V” as <a href="https://doc.rust-lang.org/std/vec/struct.Vec.html" target="_blank" >it’s a struct</a>.</p>
+</blockquote>
+<p>It’s a generic type, written as <strong><code>Vec<T></code></strong>. T can have any type, ex. A vector of i32s is <code>Vec<i32></code>. Also, Vectors always allocate their data in a dynamically allocated heap.</p>Why Rust?https://learning-rust.github.io/docs/why-rust/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/why-rust/<h2 id="history-of-rust">History of Rust</h2>
+<p>Rust was initially designed and developed by former Mozilla employee <strong><a href="https://github.com/graydon" target="_blank" >Graydon Hoare</a></strong> as a personal project. Mozilla began sponsoring the project in 2009 and announced it in 2010. But the first stable release, Rust 1.0, was released on May 15, 2015.</p>
+<p>Since Rust 1.0, major updates have been released as <a href="https://learning-rust.github.io/docs/cargo-crates-and-basic-project-structure/#rust-editions" ><code>Editions</code></a> approximately every three years: Rust 2015 (with the release of Rust 1.0) , Rust 2018, Rust 2021, and Rust 2024, all maintaining backward compatibility.</p>Workspaceshttps://learning-rust.github.io/docs/workspaces/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/workspaces/<p>When the code base is getting larger, you might need to work with <strong>multiple crates on the same project</strong>. Rust supports this via Workspaces. You can <strong>analyze (<code>cargo check</code>), build, run tests or generate docs for all crates</strong> at once by running <code>cargo</code> commands from the project root.</p>
+<p>⭐️ When working on multiple crates same time, there is a higher possibility of having shared dependencies on crates. To prevent downloading and compiling the same dependency multiple times, Rust uses a <strong>shared build directory</strong> under the project root, while running <code>cargo build</code> from the project root.</p>
\ No newline at end of file
diff --git a/docs/docs/installation/index.html b/docs/docs/installation/index.html
new file mode 100644
index 00000000..3464f343
--- /dev/null
+++ b/docs/docs/installation/index.html
@@ -0,0 +1,6 @@
+Installation · Learning Rust
There are many ways to install Rust on your system. For the moment the official way to install Rust is using Rustup.
📖 Rustup installs The Rust Programming Language from the official release channels, enabling you to easily switch between stable, beta, and nightly compilers and keep them updated. It also makes cross-compiling simpler with binary builds of the standard library for common platforms.
📖 Rustup installs rustc, cargo, rustup and other standard tools to Cargo’s bin directory. On Unix it is located at $HOME/.cargo/bin and on Windows at %USERPROFILE%\.cargo\bin. This is the same directory that cargo install will install Rust programs and Cargo plugins.
🔎 The main tools Rustup installs to the Cargo’s bin directory,
rustc: The Rust compiler.
cargo: The Rust’s built-in package manager and the build system.
rustup: The Rust toolchain installer.
rustfmt: The Rust’s official tool of formatting Rust code according to style guidelines.
cargo-fmt: Helps to run rustfmt on whole Rust projects, including multi-crate workspaces.
cargo-clippy: A lint tool that provides extra checks for common mistakes and stylistic choices.
cargo-miri:An experimental Rust interpreter, which can be used for checking for undefined-behavior.
rustdoc: A local copy of the Rust documentation.
rust-analyzer: A language server that provides support for editors and IDEs.
rust-gdb and rust-lldb: Rust debuggers that wrap the GNU Debugger(GDB) and Low-Level Debugger(LLDB).
Installation
For Mac and Linux Users
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+
For Windows Users
Download rustup-init.exe from www.rustup.rs and run.
💡 You may need to install Visual C++ Build Tools 2019 or higher, which requires an additional 3–4 GBs.
👨🏫 Before going to the next…
To verify the current Rust version, use the rustc --version or shorter form rustc -V command.
Rust follows six week release cycles. Use the rustup update command to update the Rust ecosystem.
You can access Rust’s offline documentation via the rustup doc command.
For a full list of rustup commands, refer to the rustup --help command.
\ No newline at end of file
diff --git a/docs/docs/installation/og.jpg b/docs/docs/installation/og.jpg
new file mode 100644
index 00000000..79d39cd2
Binary files /dev/null and b/docs/docs/installation/og.jpg differ
diff --git a/docs/docs/learning_rust_medium.png b/docs/docs/learning_rust_medium.png
new file mode 100644
index 00000000..f2e7a465
Binary files /dev/null and b/docs/docs/learning_rust_medium.png differ
diff --git a/docs/docs/lifetimes/index.html b/docs/docs/lifetimes/index.html
new file mode 100644
index 00000000..628c5aa1
--- /dev/null
+++ b/docs/docs/lifetimes/index.html
@@ -0,0 +1,158 @@
+Lifetimes · Learning Rust
When we are dealing with references, we have to make sure that the referencing data stay alive until we stop using the references.
Think,
We have a variable binding, a.
We are referencing the value of a, from another variable bindingx.
+We have to make sure that a lives until we stop using x.
🔎 Memory management is a form of resource management applied to computer memory. Up until the mid-1990s, the majority of programming languages used Manual Memory Management which requires the programmer to give manual instructions to identify and deallocate unused objects/ garbage. Around 1959 John McCarthy invented Garbage collection(GC), a form of Automatic Memory Management(AMM). It determines what memory is no longer used and frees it automatically instead of relying on the programmer. However Objective-C and Swift provide similar functionality through Automatic Reference Counting(ARC).
What is Lifetime?
In Rust,
A resource can only have one owner at a time. When it goes out of the scope, Rust removes it from the Memory.
When we want to reuse the same resource, we are referencing it/ borrowing its content.
When dealing with references, we have to specify lifetime annotations to provide instructions for the compiler to set how long those referenced resources should be alive.
⭐ But because of lifetime annotations make the code more verbose, in order to make common patterns more ergonomic, Rust allows lifetimes to be elided/omitted in fn definitions. In this case, the compiler assigns lifetime annotations implicitly.
Lifetime annotations are checked at compile-time. The compiler checks when data is used for the first and the last times.
Unlike C and C++, usually, Rust doesn’t require explicitly dropping values at all.
Unlike GC, Rust doesn’t place deallocation calls where the data is no longer referenced.
Rust places deallocation calls where the data is about to go out of the scope and then enforces that no references to that resource exist after that point.
Usage
Lifetimes are denoted with an apostrophe. By convention, a lowercase letter is used for naming. Usually starts with'a and follows alphabetic order when we need to add multiple lifetime annotations.
When using references,
01. On Function Declaration
Input and output parameters with references should attach lifetimes after the & sign.
+ex. ..(x: &'a str) , ..(x: &'a mut str)
After the function name, we should mention that the given lifetimes are generic types.
+ex. fn foo<'a>(..) , fn foo<'a, 'b>(..)
// No inputs, return a reference
+fnfunction<'a>()-> &'astr{}
+
+// Single input
+fnfunction<'a>(x: &'astr){}
+
+// Single input and output, both have the same lifetime
+// The output should live at least as long as input exists
+fnfunction<'a>(x: &'astr)-> &'astr{}
+
+// Multiple inputs, only one input and the output share same lifetime
+// The output should live at least as long as y exists
+fnfunction<'a>(x: i32,y: &'astr)-> &'astr{}
+
+// Multiple inputs, both inputs and the output share same lifetime
+// The output should live at least as long as x and y exist
+fnfunction<'a>(x: &'astr,y: &'astr)-> &'astr{}
+
+// Multiple inputs, inputs can have different lifetimes 🔎
+// The output should live at least as long as x exists
+fnfunction<'a,'b>(x: &'astr,y: &'bstr)-> &'astr{}
+
02. On Struct or Enum Declaration
Elements with references should attach lifetimes after the & sign.
After the name of the struct or enum, we should mention that the given lifetimes are generic types.
// Single element
+// Data of x should live at least as long as Struct exists
+structStruct<'a>{
+x: &'astr
+}
+
+// Multiple elements
+// Data of x and y should live at least as long as Struct exists
+structStruct<'a>{
+x: &'astr,
+y: &'astr
+}
+
+
+// Variant with a single element
+// Data of the variant should live at least as long as Enum exists
+enumEnum<'a>{
+Variant(&'aType)
+}
+
03. With Impls and Traits
structStruct<'a>{
+x: &'astr
+}
+impl<'a>Struct<'a>{
+fnfunction<'a>(&self)-> &'astr{
+self.x
+}
+}
+
+
+structStruct<'a>{
+x: &'astr,
+y: &'astr
+}
+impl<'a>Struct<'a>{
+fnnew(x: &'astr,y: &'astr)-> Struct<'a>{// No need to specify <'a> after new; impl already has it
+Struct{
+x: x,
+y: y
+}
+}
+}
+
+
+// 🔎
+impl<'a>Trait<'a>forType
+impl<'a>TraitforType<'a>
+
As I mentioned earlier, in order to make common patterns more ergonomic, Rust allows lifetimes to be elided/omitted. This process is called Lifetime Elision.
💡 For the moment Rust supports Lifetime Elisions only on fn definitions. But in the future, it will support for impl headers as well.
Lifetime annotations of fn definitions can be elided if its parameter list has either,
only one input parameter passes by reference.
a parameter with either&selfor&mut self reference.
fntriple(x: &u64)-> u64{// Only one input parameter passes by reference
+x*3
+}
+
+
+fnfilter(x: u8,y: &str)-> &str{// Only one input parameter passes by reference
+ifx>5{y}else{"invalid inputs"}
+}
+
+
+structPlayer<'a>{
+id: u8,
+name: &'astr
+}
+
+impl<'a>Player<'a>{
+fnnew(id: u8,name: &str)-> Player<'_>{// Only one input parameter passes by reference
+Player{
+id: id,
+name: name
+}
+}
+
+fnheading_text(&self)-> String{// An fn definition with &self (or &mut self) reference
+format!("{}: {}",self.id,self.name)
+}
+}
+
+fnmain(){
+letplayer1=Player::new(1,"Serena Williams");
+letplayer1_heading_text=player1.heading_text();
+println!("{}",player1_heading_text);
+}
+
💡 In the Lifetime Elision process of fn definitions,
Each parameter passed by reference has got a distinct lifetime annotation.
+ex. ..(x: &str, y: &str) → ..<'a, 'b>(x: &'a str, y: &'b str)
If the parameter list only has one parameter passed by reference, that lifetime is assigned to all elided lifetimes in the return values of that function.
+ex. ..(x: i32, y: &str) -> &str → ..<'a>(x: i32, y: &'a str) -> &'a str
Even if it has multiple parameters passed by reference, if one of them has &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.
+ex. impl Impl{ fn function(&self, x: &str) -> &str {} } →
+impl<'a> Impl<'a>{ fn function(&'a self, x: &'b str) -> &'a str {} }
For all other cases, we have to write lifetime annotations manually.
'static Annotations
'static lifetime annotation is a reserved lifetime annotation. These references are valid for the entire program. They are saved in the data segment of the binary and the data referred to will never go out of scope.
staticN: i32=5;// A constant with 'static lifetime
+
+leta="Hello, world.";// a: &'static str
+
+
+fnindex()-> &'staticstr{// No need to mention <'static> ; fn index ̶<̶'̶s̶t̶a̶t̶i̶c̶>̶
+"Hello, world!"
+}
+
Few more examples about the usage of Rust lifetimes.
fngreeting<'a>()-> &'astr{
+"Hi!"
+}
+
+
+fnfullname<'a>(fname: &'astr,lname: &'astr)-> String{
+format!("{}{}",fname,lname)
+}
+
+
+structPerson<'a>{
+fname: &'astr,
+lname: &'astr
+}
+impl<'a>Person<'a>{
+fnnew(fname: &'astr,lname: &'astr)-> Person<'a>{// No need to specify <'a> after new; impl already has it
+Person{
+fname: fname,
+lname: lname
+}
+}
+
+fnfullname(&self)-> String{
+format!("{}{}",self.fname,self.lname)
+}
+}
+
+fnmain(){
+letplayer=Person::new("Serena","Williams");
+letplayer_fullname=player.fullname();
+
+println!("Player: {}",player_fullname);
+}
+
\ No newline at end of file
diff --git a/docs/docs/lifetimes/og.jpg b/docs/docs/lifetimes/og.jpg
new file mode 100644
index 00000000..dc02025c
Binary files /dev/null and b/docs/docs/lifetimes/og.jpg differ
diff --git a/docs/docs/modules/index.html b/docs/docs/modules/index.html
new file mode 100644
index 00000000..2c645b2d
--- /dev/null
+++ b/docs/docs/modules/index.html
@@ -0,0 +1,180 @@
+Modules · Learning Rust
Related code and data are grouped into a module and stored in the same file.
fnmain(){
+greetings::hello();
+}
+
+modgreetings{
+// ⭐️ By default, everything inside a module is private
+pubfnhello(){// ⭐️ So function has to be public to access from outside
+println!("Hello, world!");
+}
+}
+
Private functions can be called from the same module or from a child module.
// 01. Calling private functions of the same module
+fnmain(){
+phrases::greet();
+}
+
+modphrases{
+pubfngreet(){
+hello();// Or `self::hello();`
+}
+
+fnhello(){
+println!("Hello, world!");
+}
+}
+
+// 02. Calling private functions of the parent module
+fnmain(){
+phrases::greetings::hello();
+}
+
+modphrases{
+fnprivate_fn(){
+println!("Hello, world!");
+}
+
+pubmodgreetings{
+pubfnhello(){
+super::private_fn();
+}
+}
+}
+
💡 The self keyword is used to refer the same module, while the super keyword is used to refer parent module. Also, the super keyword can be used to access root functions from inside a module.
🔎 When writing tests it’s a good practice to write tests inside a test module because they compile only when running tests.
fngreet()-> String{
+"Hello, world!".to_string()
+}
+
+#[cfg(test)]// Only compiles when running tests
+modtests{
+usesuper::greet;// Import root greet function
+
+#[test]
+fntest_greet(){
+assert_eq!("Hello, world!",greet());
+}
+}
+
02. In a different file, same directory
// ↳ main.rs
+modgreetings;// Import greetings module
+
+fnmain(){
+greetings::hello();
+}
+
+// ↳ greetings.rs
+// ⭐️ No need to wrap the code with a mod declaration. The file itself acts as a module.
+pubfnhello(){// The function has to be public to access from outside
+println!("Hello, world!");
+}
+
If we wrap file content with a mod declaration, it will act as a nested module.
// ↳ main.rs
+modphrases;
+
+fnmain(){
+phrases::greetings::hello();
+}
+
+// ↳ phrases.rs
+pubmodgreetings{// ⭐️ The module has to be public to access from outside
+pubfnhello(){
+println!("Hello, world!");
+}
+}
+
03. In a different file, different directory
mod.rs in the directory module root is the entry point to the directory module. All other files in that directory root, act as sub-modules of the directory module.
// ↳ main.rs
+modgreetings;
+
+fnmain(){
+greetings::hello();
+}
+
+// ↳ greetings/mod.rs
+pubfnhello(){// ⭐️ The function has to be public to access from outside
+println!("Hello, world!");
+}
+
Again, If we wrap file content with a mod declaration, it will act as a nested module.
// ↳ main.rs
+modphrases;
+
+fnmain(){
+phrases::greetings::hello();
+}
+
+// ↳ phrases/mod.rs
+pubmodgreetings{// ⭐️ The module has to be public to access from outside
+pubfnhello(){
+println!("Hello, world!");
+}
+}
+
Other files in the directory module act as sub-modules for mod.rs.
🔎 It’s unable to import child file modules of directory modules to main.rs, so you can’t use mod phrases::greetings; from main.rs. But there is a way to import phrases::greetings::hello() to phrases module by re-exporting hello to phrases module. So you can call it directly as phrases::hello().
// ↳ phrases/greetings.rs
+pubfnhello(){
+println!("Hello, world!");
+}
+
+// ↳ phrases/mod.rs
+pubmodgreetings;
+
+pubuseself::greetings::hello;// Re-export `greetings::hello` to phrases
+
+// ↳ main.rs
+modphrases;
+
+fnmain(){
+phrases::hello();// You can call `hello()` directly from phrases
+}
+
This allows you to present an external interface that may not directly map to your internal code organization. If still it is not clear, don’t worry; We discuss the usages of use on an upcoming section in this post.
\ No newline at end of file
diff --git a/docs/docs/modules/og.jpg b/docs/docs/modules/og.jpg
new file mode 100644
index 00000000..d6639c26
Binary files /dev/null and b/docs/docs/modules/og.jpg differ
diff --git a/docs/docs/operators/index.html b/docs/docs/operators/index.html
new file mode 100644
index 00000000..c83768f4
--- /dev/null
+++ b/docs/docs/operators/index.html
@@ -0,0 +1,93 @@
+Operators · Learning Rust
leta=1;
+letb=2;
+
+letc=a&b;// 0 (01 && 10 -> 00)
+letd=a|b;// 3 (01 || 10 -> 11)
+lete=a^b;// 3 (01 != 10 -> 11)
+letf=a<<b;// 4 (Add b number of 0s to the end of a -> '01'+'00' -> 100)
+letg=a>>b;// 0 (Remove b number of bits from the end of a -> o̶1̶ -> 0)
+
Assignment and Compound Assignment Operators
The = operator is used to assign a name to a value or a function. Compound Assignment Operators are created by composing one of + - * / % & | ^ << >> operators with = operator.
🔎 The & or &mut operators are used for borrowing and * operator for dereferencing. For more information, refer Ownership, Borrowing & Lifetimes sections.
💯 Also, the :: operator is used to access modules, constants, structs, enums, functions (excluding methods) in std modules, crates or nested/ parent modules and to access variants of enums.
💯 Also, the . operator is used to access fields of tuples and structs and to call methods in datatypes.
usestd::collections::HashMap;// 💡load HashMap struct from the std::collections module
+
+fnmain(){
+// 💡 using `HashMap::from()` associated function to create a HashMap
+letbest_movies=HashMap::from([
+("01","The Shawshank Redemption"),
+("02","The Godfather"),
+("03","The Dark Knight"),
+]);
+
+println!("{:?}",best_movies);
+}
+
println!("{}",std::primitive::u8::MAX);// 💡 access MAX constant from the std::primitive::u8
+
letmuta=(1,"Steve");// 💡 a is a tuple
+
+// 💡 access fields via dot operator
+a.0=2;
+a.1="Tim";
+println!("{}{}",a.0,a.1);// 2 Tim
+
👨🏫 Before going to the next…
About string concatenation,
let(s1,s2)=("abc","123");// both &str
+// All bellow codes return abc123 (in String data type)
+
+// 1. via + operator
+lets=String::from(s1)+s2;// String + &str
+
+// 2. via push_str method
+letmuts=String::from(s1);
+s.push_str(s2);// String + &str
+
+// 3. via format! macro
+lets=format!("{s1}{s2}");// &str/String + &str/String
+
+// 4. via concat method
+lets=[s1,s2].concat();// &str or String array
+
\ No newline at end of file
diff --git a/docs/docs/operators/og.jpg b/docs/docs/operators/og.jpg
new file mode 100644
index 00000000..90c3b98a
Binary files /dev/null and b/docs/docs/operators/og.jpg differ
diff --git a/docs/docs/option-and-result/index.html b/docs/docs/option-and-result/index.html
new file mode 100644
index 00000000..30293d48
--- /dev/null
+++ b/docs/docs/option-and-result/index.html
@@ -0,0 +1,87 @@
+Option and Result · Learning Rust
Many languages use null\ nil\ undefined types to represent empty outputs, and Exceptions to handle errors. Rust skips using both, especially to prevent issues like null pointer exceptions, sensitive data leakages through exceptions, etc. Instead, Rust provides two special generic enums;Option and Result to deal with above cases.
An optional value can have either Some value or no value/ None.
A result can represent either success/ Ok or failure/ Err
// An output can have either Some value or no value/ None.
+enumOption<T>{// T is a generic and it can contain any type of value.
+Some(T),
+None,
+}
+
+// A result can represent either success/ Ok or failure/ Err.
+enumResult<T,E>{// T and E are generics. T can contain any type of value, E can be any error.
+Ok(T),
+Err(E),
+}
+
💭 Also as we discussed in preludes, not only Option and Result, and also their variants are in preludes. So, we can use them directly without using namespaces in the code.
Basic usages of Option
When writing a function or data type,
if an argument of the function is optional,
if the function is non-void and if the output it returns can be empty,
if the value of a property of the data type can be empty,
we have to use their data type as an Option type.
For example, if the function outputs a &str value and the output can be empty, the return type of the function should be set as Option<&str>.
fnget_an_optional_value()-> Option<&str>{
+
+//if the optional value is not empty
+returnSome("Some value");
+
+//else
+None
+}
+
In the same way, if the value of a property of a data type can be empty or optional like the middle_name of the Name data type in the following example, we should set its data type as an Option type.
structName{
+first_name: String,
+middle_name: Option<String>,// middle_name can be empty
+last_name: String,
+}
+
💭 As you know, we can use pattern matching to catch the relevant return type (Some/ None) via match. There is a function in std::env called home_dir() to get the current user’s home directory. However, not all users have a home directory in systems like Linux, so the home directory of a user can be optional. So it returns an Option type; Option<PathBuf>.
usestd::env;
+
+fnmain(){
+lethome_path=env::home_dir();
+matchhome_path{
+Some(p)=>println!("{:?}",p),// This prints "/root", if you run this in Rust playground
+None=>println!("Can not find the home directory!"),
+}
+}
+
⭐ However, when using optional arguments with functions, we have to pass None values for empty arguments while calling the function.
fnget_full_name(fname: &str,lname: &str,mname: Option<&str>)-> String{// middle name can be empty
+matchmname{
+Some(n)=>format!("{}{}{}",fname,n,lname),
+None=>format!("{}{}",fname,lname),
+}
+}
+
+fnmain(){
+println!("{}",get_full_name("Galileo","Galilei",None));
+println!("{}",get_full_name("Leonardo","Vinci",Some("Da")));
+}
+
+// 💡 Better create a struct as Person with fname, lname, mname fields and create a impl function as full_name()
+
🔎 Other than that, Option types are used with nullable pointers in Rust. Because there are no null pointers in Rust, the pointer types should point to a valid location. So if a pointer can be nullable, we have use Option<Box<T>> .
Basic usages of Result
If a function can produce an error, we have to use a Result type by combining the data type of the valid output and the data type of the error. For example, if the data type of the valid output is u64 and error type is String, the return type should be Result<u64, String>.
💭 As you know, we can use the pattern matching to catch the relevant return types (Ok/Err) via match. There is a function to fetch the value of any environment variable in std::env called var(). Its input is the environment variable name. This can produce an error if we pass a wrong environment variable or the program cannot extract the value of the environment variable while running. So, its return type is a Result type; Result<String, VarError>.
usestd::env;
+
+fnmain(){
+letkey="HOME";
+matchenv::var(key){
+Ok(v)=>println!("{}",v),// This prints "/root", if you run this in Rust playground
+Err(e)=>println!("{}",e),// This prints "environment variable not found", if you give a nonexistent environment variable
+}
+}
+
is_some(), is_none(), is_ok(), is_err()
Other than match expressions, Rust provides is_some() , is_none() and is_ok() , is_err() functions to identify the return type.
\ No newline at end of file
diff --git a/docs/docs/option-and-result/og.jpg b/docs/docs/option-and-result/og.jpg
new file mode 100644
index 00000000..d03b979c
Binary files /dev/null and b/docs/docs/option-and-result/og.jpg differ
diff --git a/docs/docs/overview/index.html b/docs/docs/overview/index.html
new file mode 100644
index 00000000..ce52ecb6
--- /dev/null
+++ b/docs/docs/overview/index.html
@@ -0,0 +1,7 @@
+Overview · Learning Rust
🧑💻 I am an expat working in Singapore as a Go Backend and DevOps Engineer. Feel free to reach out if you find any mistakes or anything that needs to be changed, including spelling or grammar errors. Alternatively, you can create a pull request, open an issue, or share your awesome ideas in this gist. Good luck with learning Rust!
+
+
Overview
This publication has its origins in the posts I authored on Medium at https://medium.com/learning-rust. However, please note that I have ceased updating the Medium posts. All current and future updates, new content, code, and grammar fixes will be exclusively maintained and released here, https://learning-rust.github.io.
\ No newline at end of file
diff --git a/docs/docs/overview/og.jpg b/docs/docs/overview/og.jpg
new file mode 100644
index 00000000..0b73116f
Binary files /dev/null and b/docs/docs/overview/og.jpg differ
diff --git a/docs/docs/ownership/index.html b/docs/docs/ownership/index.html
new file mode 100644
index 00000000..8e048343
--- /dev/null
+++ b/docs/docs/ownership/index.html
@@ -0,0 +1,139 @@
+Ownership · Learning Rust
This is because of Ownership, which is used to achieve Rust’s memory safety.
Ownership
In Rust,
Each piece of data has a single owner, and data is only scoped to its owner (💯 if it is not borrowed).
This means that when the owner of the data goes out of scope, the bound resource will be dropped/ released from memory.
There can only be one owner at a time. Assigning a variable to another variable or passing it to a function (if not passed by referencing) triggers one of the following behaviors:
Copy (for the types that implement the Copy trait):
The value is duplicated.
Both variables become independent owners of their own data and remain accessible.
Move (default behavior/ if not implemented Copy trait):
Ownership transfers to the new variable.
The original variable is invalidated and can no longer be used.
💡 In Rust, every assignment is technically a bitwise move (a memcpy). The difference is that if a type implements the Copy trait, the compiler simply doesn’t invalidate the original variable afterward.
Copy Types
Rust Standard Library has implemented the Copy trait inside std for primitive types and most simpler types mainly,
Due to the orphan rule, we are not allowed to implement std traits for std types.
To avoid needing to call the .clone() method each time when assigning data to a new variable or passing it to a function.
Also as we discussed, the Copy marker trait can be added to custom types via a derive macro. However, the Rust compiler will fail to compile if the type contains any non-Copy members.
#[derive(Debug, Clone, Copy)]
+structPerson{
+name: String,// 💡 String is not a Copy type. It's a Move type.
+}
+
+fnmain(){
+leta=Person{name: "Steve".to_string()};
+dbg!(a);
+}
+
fnmain(){
+letx: [i32;3];
+
+{
+leta=[1,2,3];
+x=a;
+println!("{:?}",a);// [1, 2, 3]
+
+// `a` is dropped here, but `x` holds its own independent copy
+}
+
+println!("{:?}",x);// [1, 2, 3]
+}
+
Move Types
By default, data in Rust follows move semantics unless the type implements the Copy marker trait.
Since Rust prohibits implementing Copy for types containing non-Copy members, we must manually call the .clone() method to duplicate the data.
Types like String, Vec<T>, and Box<T> in Rust store the unsized actual data on the heap and small, fixed-size metadata on the stack. When we assign these types to a new variable, only the stack metadata is copied, the original variable is invalidated, ownership of the heap data is transferred to the new variable, and only the new owner is responsible for freeing the heap memory.
However, when we call .clone() on these types, the heap data is duplicated (deep copy), unless types like Rc<T> and Arc<T>, which are specifically designed to be cloned efficiently by incrementing a reference count on the heap rather than duplicating the actual data in heap.
fnmain(){
+letx: String;
+
+{
+leta=String::from("Hello!");
+x=a;// Ownership is transferred to `x` and `a` is invalidated
+
+// At the end of this block, `a` goes out of scope.
+// However, no heap data is freed because ownership was moved to `x`
+}
+
+println!("{x}");// "Hello!"
+}
+
\ No newline at end of file
diff --git a/docs/docs/ownership/og.jpg b/docs/docs/ownership/og.jpg
new file mode 100644
index 00000000..61cc0600
Binary files /dev/null and b/docs/docs/ownership/og.jpg differ
diff --git a/docs/docs/panicking/index.html b/docs/docs/panicking/index.html
new file mode 100644
index 00000000..5eef29b4
--- /dev/null
+++ b/docs/docs/panicking/index.html
@@ -0,0 +1,147 @@
+Panicking · Learning Rust
In some cases, when an error occurs we can not do anything to handle it, if the error is something which should not have happened. In other words, if it’s an unrecoverable error.
Also when we are not using a feature-rich debugger or proper logs, sometimes we need to debug the code by quitting the program from a specific line of code by printing out a specific message or a value of a variable binding to understand the current flow of the program.
+For above cases, we can use panic! macro.
⭐ panic!() runs thread based. One thread can be panicked, while other threads are running.
01. Quit from a specific line.
fnmain(){
+// some code
+
+// if we need to debug in here
+panic!();
+}
+
+// -------------- Compile-time error --------------
+thread'main'panickedat'explicitpanic',src/main.rs:5:5
+
02. Quit with a custom error message.
#[allow(unused_mut)]// 💡 A lint attribute used to suppress the warning; username variable does not need to be mutable
+fnmain(){
+letmutusername=String::new();
+
+// some code to get the name
+
+ifusername.is_empty(){
+panic!("Username is empty!");
+}
+
+println!("{}",username);
+}
+
+// -------------- Compile-time error --------------
+thread'main'panickedat'Usernameisempty!',src/main.rs:8:9
+
03. Quit with the value of code elements.
#[derive(Debug)]// 💡 A lint attribute which use to implement `std::fmt::Debug` to Color
+structColor{
+r: u8,
+g: u8,
+b: u8,
+}
+
+#[allow(unreachable_code)]// 💡 A lint attribute used to suppress the warning; unreachable statement
+fnmain(){
+letsome_color: Color;
+
+// some code to get the color. ex
+some_color=Color{r: 255,g: 255,b: 0};
+
+// if we need to debug in here
+panic!("{:?}",some_color);
+
+println!(
+"The color = rgb({},{},{})",
+some_color.r,some_color.g,some_color.b
+);
+}
+
+// -------------- Compile-time error --------------
+thread'main'panickedat'Color{r: 255,g: 255,b: 0}',src/main.rs:16:5
+
As you can see in the above examples panic!() supports println!() type style arguments. By default, it prints the error message, file path and line & column numbers where the error happens.
unimplemented!()
💡 If your code is having unfinished code sections, there is a standardized macro as unimplemented!() to mark those routes. The program will be panicked with a “not yet implemented” error message, if the program runs through those routes.
This is the standard macro to mark routes that the program should not enter. The program will be panicked with a “‘internal error: entered unreachable code’” error message, if the program entered those routes.
🔎 These are similar to above assert macros. But these statements are only enabled in non optimized builds by default. All these debug_assert macros will be omitted in release builds, unless we pass -C debug-assertions to the compiler.
\ No newline at end of file
diff --git a/docs/docs/panicking/og.jpg b/docs/docs/panicking/og.jpg
new file mode 100644
index 00000000..58e4b3c6
Binary files /dev/null and b/docs/docs/panicking/og.jpg differ
diff --git a/docs/docs/primitive-data-types/index.html b/docs/docs/primitive-data-types/index.html
new file mode 100644
index 00000000..31366af4
--- /dev/null
+++ b/docs/docs/primitive-data-types/index.html
@@ -0,0 +1,125 @@
+Primitive Data Types · Learning Rust
leta='x';
+letb: char='😎';
+
+// ⭐️ no "x", only single quotes
+
Because of Unicode support, char is not a single byte, but four(32 bits).
i8, i16, i32, i64, i128
8, 16, 32, 64 and 128 bit fixed sized signed(+/-) integer types
DATA TYPE
MIN
MAX
i8
-128
127
i16
-32768
32767
i32
-2147483648
2147483647
i64
-9223372036854775808
9223372036854775807
i128
-170141183460469231731687303715884105728
170141183460469231731687303715884105727
💡 The min and max values are based on the following equation; from -(2ⁿ⁻¹) to 2ⁿ⁻¹-1. You can use MIN and MAX constants to find min and max of each integer type. ex.i8::MIN;
leta=10;// ⭐️ The default integer type in Rust is i32
+letb: i8=-128;
+
u8, u16, u32, u64, u128
8, 16, 32, 64 and 128 bit fixed sized unsigned(0/+) integer types
DATA TYPE
MIN
MAX
u8
0
255
u16
0
65535
u32
0
4294967295
u64
0
18446744073709551615
u128
0
340282366920938463463374607431768211455
💡 The min and max values are based on the following equation; from 0 to 2ⁿ-1. Same way you can use MIN and MAX constants to find min and max of each integer type. ex.u8::MAX
isize, usize
Pointer sized signed and unsigned integer types
The actual bit size depends on the computer architecture you are compiling your program for. By default, the sizes are equal to 32 bits on 32-bit platforms and 64 bits on 64-bit platforms. You can use MIN and MAX constants to find min and max of each integer type. ex.isize::MAX.
32 and 64 bit sized floating point numbers(numbers with decimal points)
Rust follows IEEE Standard for Binary Floating-Point Arithmetic. The f32 type is similar to float(Single precision) in other languages, while f64 is similar to double(Double precision) in other languages.
leta=1.5;// ⭐️ The default float type in Rust is f64
+letb: f64=2.0;
+
💡 Should avoid using f32, unless you need to reduce memory consumption badly or if you are doing low-level optimization, when targeted hardware does not support for double-precision or when single-precision is faster than double-precision on it.
Array
Fixed size list of elements of same data type
leta=[1,2,3];
+
+letb: [i32;3]=[1,2,3];// with the data type 💡 [Type; NO of elements]
+// 💡let b: [i32; 3] = [1, 2]; // Compiling error : mismatched types : expected an array with a size of 3, found one with a size of 2
+
+letc: [i32;0]=[];// An empty array
+
// Accessing and changing elements
+letmuta: [i32;3]=[1,2,3];
+a[0]=2;
+a[1]=4;
+a[2]=6;
+
+// Printing with debug and pretty-print debug specifiers
+println!("{a:?}");// [2, 4, 6]
+println!("{a:#?}");
+// [
+// 2,
+// 4,
+// 6,
+// ]
+
⭐️ Arrays are immutable by default and even with mut, its element count cannot be changed.
🔎 If you are looking for a dynamic/ growable array, you can use vectors. Vectors can contain any type of elements but all elements must be in the same data type.
Tuple
Fixed size ordered list of elements of different(or same) data types
leta=(1,1.5,true,'a');
+
+letb: (i32,f64,bool,char)=(1,1.5,true,'a');// With the data types
+
+letc=(0,);// single-element tuple
+
// Accessing and changing elements
+letmuta=(1,1.5);
+a.0=2;
+a.1=3.0;
+
+// Printing with debug and pretty-print debug specifiers
+println!("{a:?}");// (2, 3.0)
+println!("{a:#?}");
+// (
+// 2,
+// 3.0,
+// )
+
// Destructuring
+leta=(1,1.5);
+let(b,c)=a;// b = 1, c = 1.5
+
+leta=(1,1.5,true,'a');
+let(b,_,_,c)=a;// b = 1, c = 'a'
+let(b,..,c)=a;// b = 1, c = 'a'
+
+leta=(1,2,3,true,false,'a','b','c');
+let(b,..)=a;// b = 1
+let(..,c)=a;// c = 'c'
+let(e,f,g,..,h,i,j)=a;// 1 2 3 'a' 'b' 'c'
+
⭐️ Tuples are also immutable by default and even with mut, its element count cannot be changed. Also, if you want to change an element’s value, the new value should have the same data type of previous value.
Slice
Dynamically-sized reference to another data structure
Imagine you want to get/ pass a part of an array or any other data structure. Instead of copying it to another array (or same data structure), Rust allows for creating a view/ reference to access only that part of the data. This view/ reference can be mutable or immutable.
leta: [i32;4]=[1,2,3,4];// Parent Array
+
+// Slice whole array
+letb: &[i32]=&a;// data type is optional
+letc=&a[0..4];// From 0th position to 4th(excluding)
+letd=&a[..];// high or low bounds are optional
+
+// Slicing part of the array
+lete=&a[1..3];// [2, 3]
+letf=&a[1..];// [2, 3, 4]
+letg=&a[..3];// [1, 2, 3]
+
// directly creating a slice
+leth=&[1,2];
+leth: &[i32]=&[1,2];// with the datatype
+
str is a UTF-8 sequence of Unicode string slice; It’s unsized. You can’t create a variable of type str directly because Rust needs to know sizes at compile time. So, it must always be used behind a pointer — like &str, Box<str>, or Rc<str>.
&str is a fat pointer (a pointer to str and a length). So, it’s a sized reference that carries both a pointer and a length.
&'static str is an &str that is statically allocated directly to the read-only data segment in the program binary. The 'static lifetime means it lives for the entire program duration.
p1 is a function pointer to plus_one() in the following code.
fnmain(){
+letp1=plus_one;// Without type declarations
+leta=p1(5);// 6
+
+letp1: fn(i32)-> i32=plus_one;// With the type declarations
+letb=p1(5);// 6
+}
+
+fnplus_one(i: i32)-> i32{
+i+1
+}
+
Type Inference
The Rust compiler can infer the data type when we don’t explicitly specify it. For example, in Rust, the default integer type is i32 and the default float type is f64. However, the Rust compiler checks the usage and determines the best data type based on the context.
leta=10;// type inference: i32
+letb=3.14;// type inference: f64
+letc=true;// type inference: bool
+
We can check the default byte sizes of data types via std::mem::size_of. For example: size_of::<bool>(), size_of::<f32>(), size_of::<&str>(), etc.
Data type
bytes
bits
bool
1
8
char
4
32
i8 i16 i32 i64 i128
1, 2, 4, 8, 16
8, 16, 32, 64, 128
u8 u16 u32 u64 u128
1, 2, 4, 8, 16
8, 16, 32, 64, 128
isize usize
8, 8
64, 64
f32 f64
4, 8
32, 64
&str
16
128
👨🏫 Before going to the next…
Other than adding the type annotations to the variables, for numeric types, we can append the data type directly to the value as the suffix. Also, to improve the readability of long numbers, we can use _ as a divider.
leta=5i8;// Equals to `let a: i8 = 5;`
+
+letb=100_000_000;// Equals to `let b = 100000000;`
+// 💡 The placements of _s are not strict. ex. 10000_0000 is also valid.
+
+letpi=3.141_592_653_59_f64;// Equals to `let pi: f64 = 3.14159265359`
+// 💡 make sure group digits consistently by underscores avoid warnings
+
+constPI: f64=3.141_592_653_59;// In the constants and statics, the data type must be annotated in the beginning.
+
\ No newline at end of file
diff --git a/docs/docs/primitive-data-types/og.jpg b/docs/docs/primitive-data-types/og.jpg
new file mode 100644
index 00000000..207ac39d
Binary files /dev/null and b/docs/docs/primitive-data-types/og.jpg differ
diff --git a/docs/docs/rust_playground.png b/docs/docs/rust_playground.png
new file mode 100644
index 00000000..580f0049
Binary files /dev/null and b/docs/docs/rust_playground.png differ
diff --git a/docs/docs/smart-compiler/index.html b/docs/docs/smart-compiler/index.html
new file mode 100644
index 00000000..27c76acc
--- /dev/null
+++ b/docs/docs/smart-compiler/index.html
@@ -0,0 +1,82 @@
+Smart Compiler · Learning Rust
The Rust compiler does the most significant job to prevent errors in Rust programs. It analyzes the code at compile-time and issues warnings, if the code does not follow memory management rules or lifetime annotations correctly.
For example,
#[allow(unused_variables)]//💡 A lint attribute used to suppress the warning; unused variable: `b`
+fnmain(){
+leta=vec![1,2,3];
+letb=a;
+
+println!("{:?}",a);
+}
+
+
+// ------ Compile-time error ------
+error[E0382]: useofmovedvalue: `a`
+--> src/main.rs:6:22
+|
+3|letb=a;
+|-valuemovedhere
+4|
+5|println!("{:?}",a);
+|^valueusedhereaftermove
+|
+=note: moveoccursbecause`a`hastype`std::vec::Vec<i32>`,whichdoesnotimplementthe`Copy`trait
+
+error: abortingduetopreviouserror
+Formoreinformationaboutthiserror,try`rustc--explainE0382`.
+
+// ⭐ instead using #[allow(unused_variables)], consider using "let _b = a;" in line 4.
+// Also you can use "let _ =" to completely ignore return values
+
💭 In the previous sections, we have discussed memory management concepts like ownership, borrowing, lifetimes and etc.
Rust compiler checks not only issues related with lifetimes or memory management and also common coding mistakes, like the following code.
Above error messages are very descriptive and we can easily see where is the error. But while we can not identify the issue via the error message, rustc --explain commands help us to identify the error type and how to solve it, by showing simple code samples which express the same problem and the solution we have to use.
For example, rustc --explain E0571 shows the following output in the console.
A`break`statementwithanargumentappearedinanon-`loop`loop.
+
+Exampleoferroneouscode:
+```
+letresult=whiletrue{
+ifsatisfied(i){
+break2*i;// error: `break` with value from a `while` loop
+}
+i+=1;
+};
+```
+
+The`break`statementcantakeanargument(whichwillbethevalueoftheloop
+expressionifthe`break`statementisexecuted)in`loop`loops,butnot
+`for`,`while`,or`whilelet`loops.
+
+Makesure`breakvalue;`statementsonlyoccurin`loop`loops:
+```
+letresult=loop{// ok!
+ifsatisfied(i){
+break2*i;
+}
+i+=1;
+};
+```
+
\ No newline at end of file
diff --git a/docs/docs/smart-compiler/og.jpg b/docs/docs/smart-compiler/og.jpg
new file mode 100644
index 00000000..9e1bfa0a
Binary files /dev/null and b/docs/docs/smart-compiler/og.jpg differ
diff --git a/docs/docs/std-primitives-and-preludes/index.html b/docs/docs/std-primitives-and-preludes/index.html
new file mode 100644
index 00000000..8c312d6c
--- /dev/null
+++ b/docs/docs/std-primitives-and-preludes/index.html
@@ -0,0 +1,93 @@
+STD, Primitives and Preludes · Learning Rust
The std library has been divided into modules, according to the main areas each covered.
⭐️ While primitives are implemented by the compiler, the standard library implements the most useful methods directly on the primitive types. But some rarely useful language elements of some primitives are stored on relevant std modules. This is why you can see char, str and integer types on both primitives and std modules.
Primitives
// Primitives: Defined by the compiler and methods are directly implemented by std
+bool,char,slice,str
+
+i8,i16,i32,i64,i128,isize
+u8,u16,u32,u64,u128,usize
+
+f32,f64
+
+array,tuple
+
+pointer,fn,reference
+
Standard Macros
// Standard Macros also defined by both compiler and std
+print,println,eprint,eprintln
+format,format_args
+write,writeln
+
+concat,concat_idents,stringify// concat_idents: nightly-only experimental API
+
+include,include_bytes,include_str
+
+assert,assert_eq,assert_ne
+debug_assert,debug_assert_eq,debug_assert_ne
+
+try,panic,compile_error,unreachable,unimplemented
+
+file,line,column,module_path
+env,option_env
+cfg
+
+select,thread_local// select: nightly-only experimental API
+
+vec
+
🔎 When examining Rust’s source code, you can see that the src directory is a workspace. Even though it is having many library crates, by examining root Cargo.toml file you can easily identify that main crates are rustc(compiler) and libstd (std). In libstd/lib.rs std modules have been re-exported via pub use and the original location of most of the std modules is src/libcore.
Few important std modules are,
std::io - Core I/O functionality
std::fs - Filesystem specific functionality
std::path - Cross-platform path specific functionality
std::env - Process’s environment related functionality
std::mem - Memory related functionality
std::net - TCP/UDP communication
std::os - OS specific functionality
std::thread - Native threads specific functionality
Even though Rust std contains many modules, by default it doesn’t load each and everything of std library on every rust program. Instead, it loads only the smallest list of things which require for almost every single Rust program. These are called preludes. They import only,
extern crate std; : into the crate root of every crate
use std::prelude::v1::*; : into every module
+So you don’t need to import these each time.
The concept of preludes is quite common on Rust libraries. Even some modules inside std crate (ex.std::io) and many libraries (ex. Diesel) are having their own prelude modules.
⭐️ But preludes are used to create a single place to import all important components which are required while using the library. They do not load automatically unless you imported them manually. Only std::prelude imports automatically in every Rust programs.
\ No newline at end of file
diff --git a/docs/docs/std-primitives-and-preludes/og.jpg b/docs/docs/std-primitives-and-preludes/og.jpg
new file mode 100644
index 00000000..bf8fb014
Binary files /dev/null and b/docs/docs/std-primitives-and-preludes/og.jpg differ
diff --git a/docs/docs/structs/index.html b/docs/docs/structs/index.html
new file mode 100644
index 00000000..62529418
--- /dev/null
+++ b/docs/docs/structs/index.html
@@ -0,0 +1,157 @@
+Structs · Learning Rust
Tuple structs: One or more , separated values enclosed in ()
structColor(u8,u8,u8);
+
Unit structs: A struct with no fields/ members
structBlack;
+
⭐️ In Rust, data (attributes) and behavior (associated functions and methods) are placed separately. Structs and Enums are used to group related data, and impls and traits are used to add associated and shared behavior to that data.
💡 In Rust, the term “instantiation” is used to describe the act of creating a concrete instance of a type (struct or enum).
💡 In Rust, the term “field” is used to describe a named component in a C-like struct & struct-like enum variant, and the term “element” is used to describe an unnamed component in a tuple struct & tuple-like enum variant. The term “member” is used to describe both.
structColor{
+red: u8,
+green: u8,
+blue: u8,
+}
+
+fnmain(){
+// 1. Instantiation
+letwhite=Color{
+red: 255,
+green: 255,
+blue: 255,
+};
+
+// 2. Instantiation without redundant field names, when using the same variable names
+let(red,green,blue)=(0,0,0);
+letblack=Color{red,green,blue};
+
+// 3. Instantiation + copy fields' values from another instance
+letred=Color{red: 255,..black};// 💡 Copy green and blue from black
+letgreen=Color{green: 255,..black};// 💡 Copy red and blue from black
+letmutblue=Color{..black};// 💡 Copy all fields' values from black
+blue.blue=255;
+
+println!("RGB({}, {}, {})",white.red,white.green,white.blue);// RGB(255, 255, 255)
+println!("RGB({}, {}, {})",black.red,black.green,black.blue);// RGB(0, 0, 0)
+
+println!("RGB({}, {}, {})",red.red,red.green,red.blue);// RGB(255, 0, 0)
+println!("RGB({}, {}, {})",green.red,green.green,green.blue);// RGB(0, 255, 0)
+println!("RGB({}, {}, {})",blue.red,blue.green,blue.blue);// RGB(0, 0, 255)
+}
+
// 4. Instantiation with default values
+
+#[derive(Default)]
+structPerson{
+name: String,
+age: f32,
+}
+
+fnmain(){
+leta=Person::default();// Instantiation with default values
+
+assert_eq!(a.name,"");// String default value ""
+assert_eq!(a.age,0.0);// f32 default value 0.0
+}
+
💡 In Rust, the #[derive()] attribute is used to automatically generate an implementation of certain traits for a custom data structure (struct and enum), instead of you writing them by hand. The std::default::Default trait allows us to create a new instance of a type with the Type::default() method.
💯 5. We can also use a constructor function inside an impl block to initialize a struct.
Destructuring
structPerson{
+name: String,
+company_name: String,
+}
+
+fnget_steve()-> Person{
+Person{
+name: "Steve Jobs".to_string(),
+company_name: "Apple".to_string(),
+}
+}
+
+fnmain(){
+letsteve=Person{
+name: "Steve Jobs".to_string(),
+company_name: "Apple".to_string(),
+};
+
+letPerson{name: a,company_name: b}=steve;// 1. Destructuring fields' values to a and b
+println!("{a}{b}");// Steve Jobs Apple
+
+letPerson{company_name: c,..}=get_steve();// 2. Destructuring only selected fields' values; directly from the function call
+println!("{c}");// Apple
+}
+
+// 💯 let Person {name: ref a, company_name: ref b} = steve; // add ref keyword, to pass a field's value as a reference
+
Tuple Structs
Looks like a named tuples.
Can access fields using the ./ dot notation and the index number of the field, like on tuples.
⭐️ When a tuple struct has only one element, we call it newtype pattern. Because it helps to create a new type.
It defines a new type, but it resembles an empty tuple, ()
This is rarely useful on its own. But in combination with other features (such as generics), it can become useful.
Definition & Instantiation
structElectron;
+
+fnmain(){
+letx=Electron;
+}
+
📖 ex: A library may ask you to create a structure that implements a certain trait to handle events. If you don’t have any data you need to store in the structure, you can create a unit-like struct.
Debug Printing and Pretty Debug Printing
In Rust, the #[derive()] attribute is used to automatically generate an implementation of certain traits for a custom data structure (struct and enum), instead of you writing them by hand. The std::fmt::Debug trait allows us to format a value with {:?} or {:#?} in println! and similar macros.
#![allow(unused)]// 💡 skip unused warnings, as we don't read fields in the structs
+
+#[derive(Debug)]
+structElectron;
+
+#[derive(Debug)]
+structDepartment(String);
+
+#[derive(Debug)]
+structPerson{
+name: String,
+company_name: String,
+}
+
+fnmain(){
+leta=Electron;
+println!("{a:?}");// Electron // 💡{a:#?} prints the same
+
+letb=Department("Engineering".to_string());
+println!("{b:?}");// Department("Engineering")
+println!("{b:#?}");
+// Department(
+// "Engineering",
+// )
+
+letc=Person{name: "Steve Jobs".to_string(),company_name: "Apple".to_string()};
+println!("{c:?}");// Person { name: "Steve Jobs", company_name: "Apple" }
+println!("{c:#?}");
+// Person {
+// name: "Steve Jobs",
+// company_name: "Apple",
+// }
+}
+
\ No newline at end of file
diff --git a/docs/docs/structs/og.jpg b/docs/docs/structs/og.jpg
new file mode 100644
index 00000000..6eabb228
Binary files /dev/null and b/docs/docs/structs/og.jpg differ
diff --git a/docs/docs/traits/index.html b/docs/docs/traits/index.html
new file mode 100644
index 00000000..56614d88
--- /dev/null
+++ b/docs/docs/traits/index.html
@@ -0,0 +1,436 @@
+Traits · Learning Rust
A trait is a contract that defines a set of behaviors or properties that a type must implement. It can contain associated types, constants, function or method signatures, and overridable default implementations.
Definition
With No Associates
💡 Mostly used to mark a type as having certain properties to allow in certain operations. Known as Marker Traits.
A trait must have to be implemented first before implementing the current trait.
pubtraitCopy: Clone{}// 💡 Any type that copyable should be clonable
+
+// 💡 Any type that clonable should be sized
+pubtraitClone: Sized{
+fnclone(&self)-> Self;
+fnclone_from(&mutself,source: &Self){...}
+}
+
💯 trait Subtrait: Super or trait Subtrait: SupertraitA + SupertraitB
With Generic Types
// 💡 Convert from one type to another. If successful, retrun Type; else return associated Error
+pubtraitTryFrom<T>: Sized{
+typeError;
+
+fntry_from(value: T)-> Result<Self,Self::Error>;
+}
+
Trait Impls (Manual Implementation)
Manually implementing a shared behavior defined in a trait for a type via an impl block.
With Required Components
When a trait has only declarations of associated items, it’s required to implement all of them.
Allows the type to be used as a key in a HashMap or HashSet
💯 Marker traits are the traits that have no associated constants, types, methods, etc. So, the compiler-generated implementation has only an empty impl Trait for Type { } block.
#![allow(unused)]
+
+#[derive(Debug, Clone, Copy)]// 💡 Copy trait needs the Clone trait as a supertrait
+structPoint{
+x: i32,
+y: i32,
+}
+
+fnmain(){
+leta=Point{x: 0,y: 1};
+letb=a;// Copy: 💡 duplicate data. a and b are separate instances
+
+println!("{a:?}");
+println!("{b:?}");
+}
+// 👨🏫 Try remove Copy derive on Point and explisitly copy via .clone()
+
🔎 Copy set the ability to duplicate via simply copying bits (pass by duplicating)
Auto Traits
Implicitly bound/ automatically implemented by the compiler without any keywords.
⭐️ Most simple types in Rust have a fixed size known at compile time and automatically implement Sized marker trait.
💯 Unsized types (or dynamically sized types, DSTs) cannot be used directly as local variables, function parameters, or return values. They must always be placed behind an indirection, such as a reference (& or &mut), a Box, Rc, or Arc. Common examples include slices ([T], &str) and trait objects (dyn Trait).
🔎 Pointers to these types are known as “wide pointers” or “fat pointers” because they contain both a pointer to the data and additional metadata. Metadata: for slices - length (number of elements) and for trait objects - a pointer to the vtable/ virtual function table. Ex: &[T], *mut str, Box<dyn Trait>
💡 To allow a type to be unsized (relaxes the default Sized requirement), we can use the ?Sized bound.
Static Dispatch
Monomorphization is a compiler optimization and implementation strategy that transforms polymorphic (generic) code into specialized, monomorphic (single-type) versions for each unique set of concrete types used in a program. This increases the binary size.
Dispatch is the process of deciding which implementation of a polymorphic function to execute, either statically at compile time or dynamically at runtime (via a lookup in a vtable).
Rust compiler generates highly optimized code blocks for each type used for a generic function. So, function calls are statically resolved at compile time and no runtime overhead.
Trait Bounds
Specify the type constraints by traits in generics (<T: Trait>) rather than using exact types. Allowed in a field types & function return and argument.
Dynamic dispatch is used when we need to handle multiple different concrete types (mix types) and resolve the trait implementation dynamically at runtime (because this is not possible with static dispatch).
🔎 The compiler uses vtable (virtual method table) pointers. Instead of knowing the type at compile time, the program follows a pointer to a table that contains the addresses of the methods for that specific instance.
👨🏫 Try to implement TryFrom and check the blanket implementation it provides.
Trait Coherence & Orphan Rule
Rust ensures there is only one implementation of a specific trait for a specific type in the global scope/ in the entire program (Only One Implementation Per Type). This is primarily done to prevent multiple conflicting implementations across different layers of an application. This is called Coherence (or Trait Coherence). If multiple implementations exist, the code will not compile.
To prevent overwriting an existing implementation in a different layer of the application, Rust prohibits implementing a foreign trait for a foreign type. In other words, either the trait or the type must be defined in the current crate. This is called the Orphan Rule.
Suppose you want to implement a std trait for a std/ foreign type but Rust not allow it due to the orphan rule. In that case, we can create a brand-new type that wraps the foreign type and implements the trait for the wrapper type. This is called Newtype Pattern.
useanyhow::{Context,Result};
+usestd::fmt;
+usestd::time::{SystemTime,UNIX_EPOCH};
+
+structTimestamp(SystemTime);// 💡 The newtype that wraps the std type
+
+implTimestamp{
+fnget_seconds(&self)-> Result<u64>{
+self.0
+.duration_since(UNIX_EPOCH)
+.with_context(||"Clock is set before 1970")
+.map(|d|d.as_secs())
+}
+}
+
+// 💡 Implement std trait, Display for newtype
+implfmt::DisplayforTimestamp{
+fnfmt(&self,f: &mutfmt::Formatter)-> fmt::Result{
+letsecs=self.get_seconds().map_err(|_|fmt::Error)?;
+write!(f,"{secs}")
+}
+}
+
+fnmain()-> Result<()>{
+letnow=Timestamp(SystemTime::now());
+println!("Current time: {}",now);
+
+Ok(())
+}
+
\ No newline at end of file
diff --git a/docs/docs/traits/og.jpg b/docs/docs/traits/og.jpg
new file mode 100644
index 00000000..cb190537
Binary files /dev/null and b/docs/docs/traits/og.jpg differ
diff --git a/docs/docs/unwrap-and-expect/index.html b/docs/docs/unwrap-and-expect/index.html
new file mode 100644
index 00000000..89035bed
--- /dev/null
+++ b/docs/docs/unwrap-and-expect/index.html
@@ -0,0 +1,162 @@
+Unwrap and Expect · Learning Rust
If an Option type has Some value or a Result type has a Ok value, the value inside them passes to the next step.
If the Option type has None value or the Result type has Err value, program panics; If Err, panics with the error message.
The functionality is bit similar to the following codes, which are using match instead unwrap().
Example with Option and match, before using unwrap()
fnmain(){
+letx;
+matchget_an_optional_value(){
+Some(v)=>x=v,// if Some("abc"), set x to "abc"
+None=>panic!(),// if None, panic without any message
+}
+
+println!("{}",x);// "abc" ; if you change line 14 `false` to `true`
+}
+
+fnget_an_optional_value()-> Option<&'staticstr>{
+
+//if the optional value is not empty
+iffalse{
+returnSome("abc");
+}
+
+//else
+None
+}
+
+
+// --------------- Compile-time error ---------------
+thread'main'panickedat'explicitpanic',src/main.rs:5:17
+
Example with Result and match, before using unwrap()
fnmain(){
+letx;
+matchfunction_with_error(){
+Ok(v)=>x=v,// if Ok(255), set x to 255
+Err(e)=>panic!(e),// if Err("some message"), panic with error message "some message"
+}
+
+println!("{}",x);// 255 ; if you change line 13 `true` to `false`
+}
+
+fnfunction_with_error()-> Result<u64,String>{
+//if error happens
+iftrue{
+returnErr("some message".to_string());
+}
+
+// else, return valid output
+Ok(255)
+}
+
+
+// ---------- Compile-time error ----------
+thread'main'panickedat'somemessage',src/main.rs:5:19
+
Same codes in above main functions can be written with unwrap() using two lines.
The opposite case of unwrap() and expect(); Panics with Ok values, instead Err. Both print the value inside Ok on the error message.
💡 Usually use with tests.
// 01. unwrap_err error message for Ok
+fnmain(){
+leto: Result<i8,&str>=Ok(8);
+
+o.unwrap_err();
+}
+
+// ---------- Compile-time error ----------
+thread'main'panickedat'called`Result::unwrap_err()`onan`Ok`value: 8',libcore/result.rs:945:5
+
+
+// 02. expect_err error message for Ok
+fnmain(){
+leto: Result<i8,&str>=Ok(8);
+
+o.expect_err("Should not get Ok value");
+}
+
+// ---------- Compile-time error ----------
+thread'main'panickedat'ShouldnotgetOkvalue: 8',libcore/result.rs:945:5
+
unwrap_or(), unwrap_or_default() and unwrap_or_else()
💡 These are bit similar to unwrap(), If an Option type has Some value or a Result type has a Ok value, the value inside them passes to the next step. But when having None or Err, the functionalities are bit different.
unwrap_or() : With None or Err, the value you passes to unwrap_or() is passing to the next step. But the data type of the value you passes should match with the data type of the relevant Some or Ok.
unwrap_or_default() : With None or Err, the default value of the data type of the relevant Some or Ok, is passing to the next step.
fnmain(){
+letv=8;
+letv_default=0;
+
+lets_v: Option<i8>=Some(8);
+letn: Option<i8>=None;
+
+assert_eq!(s_v.unwrap_or_default(),v);// Some(v) unwrap_or_default = v
+assert_eq!(n.unwrap_or_default(),v_default);// None unwrap_or_default = default value of v
+
+leto_v: Result<i8,&str>=Ok(8);
+lete: Result<i8,&str>=Err("error");
+
+assert_eq!(o_v.unwrap_or_default(),v);// Ok(v) unwrap_or_default = v
+assert_eq!(e.unwrap_or_default(),v_default);// Err unwrap_or_default = default value of v
+}
+
unwrap_or_else() : Similar to unwrap_or(). The only difference is, instead of passing a value, you have to pass a closure which returns a value with the same data type of the relevant Some or Ok.
\ No newline at end of file
diff --git a/docs/docs/unwrap-and-expect/og.jpg b/docs/docs/unwrap-and-expect/og.jpg
new file mode 100644
index 00000000..16dada3c
Binary files /dev/null and b/docs/docs/unwrap-and-expect/og.jpg differ
diff --git a/docs/docs/use/index.html b/docs/docs/use/index.html
new file mode 100644
index 00000000..4af7b28d
--- /dev/null
+++ b/docs/docs/use/index.html
@@ -0,0 +1,95 @@
+Use · Learning Rust
Mainly use keyword is used to bind a full path of an element to a new name. So the user doesn’t want to repeat the full path each time.
// -- Initial code without the `use` keyword --
+modphrases{
+pubmodgreetings{
+pubfnhello(){
+println!("Hello, world!");
+}
+}
+}
+
+fnmain(){
+phrases::greetings::hello();// Using full path
+}
+
+
+// -- Usage of the `use` keyword --
+// 01. Create an alias for module
+usephrases::greetings;
+fnmain(){
+greetings::hello();
+}
+
+// 02. Create an alias for module elements
+usephrases::greetings::hello;
+fnmain(){
+hello();
+}
+
+// 03. Customize names with the `as` keyword
+usephrases::greetings::helloasgreet;
+fnmain(){
+greet();
+}
+
02. Import elements to scope
Another common usage of use is importing elements to scope. Remember that, this is also a bit similar to creating an alias and using it instead of using the full path.
fnhello()-> String{
+"Hello, world!".to_string()
+}
+
+#[cfg(test)]
+modtests{
+usesuper::hello;// Import the `hello()` function into the scope
+
+#[test]
+fntest_hello(){
+assert_eq!("Hello, world!",hello());// If not using the above `use` statement, we can run same via `super::hello()`
+}
+}
+
💡 By default, use declarations use absolute paths, starting from the crate root. But self and super declarations make that path relative to the current module.
Same way the use keyword is used to import the elements of other crates including the std, Rust’s Standard Library.
// -- 01. Importing elements --
+usestd::fs::File;
+
+fnmain(){
+File::create("empty.txt").expect("Can not create the file!");
+}
+
+
+// -- 02. Importing module and elements --
+usestd::fs::{self,File}// `use std::fs; use std::fs::File;`
+
+fnmain(){
+fs::create_dir("some_dir").expect("Can not create the directry!");
+File::create("some_dir/empty.txt").expect("Can not create the file!");
+}
+
+
+// -- 03. Importing multiple elements --
+usestd::fs::File;
+usestd::io::{BufReader,BufRead};// `use std::io::BufReader; use std::io::BufRead;`
+
+fnmain(){
+letfile=File::open("src/hello.txt").expect("file not found");
+letbuf_reader=BufReader::new(file);
+
+forlineinbuf_reader.lines(){
+println!("{}",line.unwrap());
+}
+}
+
We don’t need to use extern crate std; when using the std library. We will discuss more about this under the Standard Library section.
💡 use statements import only what we’ve specified into the scope, instead of importing all elements of a module or crate. So it improves the efficiency of the program.
03. Re-exporting
Another special case is pub use. When creating a module, you can export things from another module into your module. So after that, they can be accessed directly from your module. This is called re-exporting.
This pattern is quite common in large libraries. It helps to hide the complexity of the internal module structure of the library from users. Because users don’t need to know/follow the whole directory map of the elements of the library while working with them.
\ No newline at end of file
diff --git a/docs/docs/use/og.jpg b/docs/docs/use/og.jpg
new file mode 100644
index 00000000..e2e54432
Binary files /dev/null and b/docs/docs/use/og.jpg differ
diff --git a/docs/docs/variable-bindings-constants-and-statics/index.html b/docs/docs/variable-bindings-constants-and-statics/index.html
new file mode 100644
index 00000000..c2c62169
--- /dev/null
+++ b/docs/docs/variable-bindings-constants-and-statics/index.html
@@ -0,0 +1,70 @@
+Variable bindings, Constants & Statics · Learning Rust
Rust is a statically typed language; it checks data types at compile-time. But it doesn’t require you to actually type data types when declaring variable bindings. In that case, the compiler checks the usage and sets a better data type for it.
⭐️ For constants and statics, we must annotate the data type.
Types come after a : (colon) sign.
The naming convention for the variable bindings is using the snake_case. But, for constants and statics, we should follow the SCREAMING_SNAKE_CASE.
💭 In the following examples, we will use data types like bool, i32, i64 and f64. Don’t worry about them for now; they’ll be discussed later.
Variable Bindings
The let keyword is used in binding expressions. We can bind a name to a value or a function. Also, because the left-hand side of a let expression is a “pattern”, you can bind multiple names to a set of values or function values.
In Rust, variables are immutable by default, so we call them Variable bindings. To make them mutable, the mut keyword is used.
Declaration & Assignment
leta;// Declaration; without data type
+a=5;// Assignment
+
+letb: i8;// Declaration; with data type
+b=5;
+
+letc=true;// Declaration + assignment; without data type
+letd: bool=false;// Declaration + assignment; with data type
+
+lete=4+2;// e = 6
+
Mutability
As mentioned, variable bindings are immutable by default. We need to add the mut keyword to make them mutable.
// Declaration + assignment
+let(a,b)=(1,2);// a = 1 and b = 2
+
// Declaration + assignment + mutability
+let(muta,mutb)=(3,4);// a = 3 and b = 4
+(a,b)=(a-b,a+b);// a = -1 and b = 7
+
Scope
let(a,b)=(1,2);// a = 1 and b = 2
+
+letc={
+leta=4;// affects inside wrapping {} only
+letb=6;// affects inside wrapping {} only
+
+a+b
+};// c = 10
+
+letd={a+b};// d = 3
+
+println!("{a}{b}{c}{d}");// 1 2 10 3
+
Constants
The const keyword is used to define constants and after the assignment their values are not allowed to change. They live for the entire lifetime of a program but has no fixed address in the memory.
The static keyword is used to define a “global variable” type facility. There is only one instance for each value, and it’s at a fixed location in memory.
💭 While you need constants, always use const, instead of static. It’s pretty rare that you actually want a memory location associated with your constant, and using a const allows for optimizations like constant propagation, not only in your crate but also in downstream crates.
Variable Shadowing
Sometimes, while dealing with data, initially we get them in one unit but need to transform them into another unit for further processing. In this situation, instead of using different variable names, Rust allows us to redeclare the same variable with a different data type and/ or with a different mutability setting. We call this Shadowing.
Usually, constants and statics are placed at the top of the code file, outside the functions (after module imports/ use declarations).
constPI: f64=3.14159265359;
+
+fnmain(){
+println!("π value is {}",PI);
+}
+
\ No newline at end of file
diff --git a/docs/docs/variable-bindings-constants-and-statics/og.jpg b/docs/docs/variable-bindings-constants-and-statics/og.jpg
new file mode 100644
index 00000000..4551af7e
Binary files /dev/null and b/docs/docs/variable-bindings-constants-and-statics/og.jpg differ
diff --git a/docs/docs/vectors/index.html b/docs/docs/vectors/index.html
new file mode 100644
index 00000000..53c015a2
--- /dev/null
+++ b/docs/docs/vectors/index.html
@@ -0,0 +1,85 @@
+Vectors · Learning Rust
If you remember, the array is a fixed-size list of elements, of the same data type. Even with mut, its element count cannot be changed. A vector is kind of a re-sizable array but all elements must be in the same type.
It’s a generic type, written as Vec<T>. T can have any type, ex. A vector of i32s is Vec<i32>. Also, Vectors always allocate their data in a dynamically allocated heap.
Creation
Empty Vector
letmuta=Vec::new();// 1. With new() keyword
+letmutb=vec![];// 2. Using the vec! macro (💡 usually create with values same time)
+
+// ⭐️ If you need an immutable empty vector, you must have to specify the data type.
+leta: Vec<i32>=Vec::new();
+letb: Vec<String>=vec![];
+
With Type Annotations
leta: Vec<i32>=Vec::new();
+letb: Vec<i32>=vec![];
+
+letc=vec![1i32,2,3];// Suffixing 1st value with data type
+
We can access and change elements of a vector, via the index (like we access/ change elements of an array).
letmuta=vec![1,2,3];
+
+println!("{}{}{}",a[0],a[1],a[2]);// 1 2 3
+
+a[0]=4;// [4, 2, 3]
+(a[1],a[2])=(a[2],a[1]);// Shuffle
+
+println!("{:?}",a);// [4, 3, 2]
+
+a[5]=2;// 💥 panics at runtime; index out of bounds: the len is 3 but the index is 5
+
By the get Method
Similar to accessing elements via the index, but safer, as it always returns an Option<T>/ optional value.
💭 Option<T> can be either Some value or None (no value). It is also a generic type, like Vec<T>. We’ll discuss more details in the Generics: Option. For the moment, focus on vectors.
By the push and pop Methods
letmuta: Vec<i32>=Vec::new();
+
+a.push(1);// Add 1 to the end; a = [1]
+a.push(2);// Add 2 to the end; a = [1, 2]
+
+a.pop();// Remove 2 from the end; a = [1]
+
+letx=a.pop();// Remove 1 from the end and assign it to x as Option<T>; a = []
+// x = Some(1)
+
+lety=a.pop();// Remove nothing as a is empty; a = [] ⭐️ No panics
+// y = None
+
Length and Capacity
In Rust, most types have a fixed size known at compile time and implement the trait Sized. Vec<T> is also a sized type; A struct that internally stores,
A pointer: points to the heap-allocated memory storing the elements contiguously, like a slice [T]
Length: NO of elements currently have
Capacity: Amount of space allocated for any future elements
⭐️ If the length of a vector exceeds its capacity, its capacity will be increased automatically. But its elements will be reallocated(which can be slow). So, always use Vec::with_capacity whenever it’s possible.
letmute: Vec<i32>=Vec::with_capacity(10);// Length: 0, Capacity : 10
+
+// These are all done without reallocating...
+foriin0..10{
+e.push(i);
+}
+
+// ...but this may make the vector reallocate as exceeded current capacity
+e.push(11);
+
🔎 Dynamically sized types (DSTs)/ unsized types don’t have a fixed size at compile time, and the size is known only at run-time. Slices and trait objects are two examples of DSTs.
👨🏫 Before going to the next…
💯 Vectors can be used with iterators in three ways,
letmuta=vec![1,2,3,4,5];
+
+foriina{
+println!("Take ownership of the vector and its element {}",i);
+}
+
+foriin&a{
+println!("A reference to {}",i);
+}
+
+foriin&muta{
+println!("A mutable reference to {}",i);
+}
+
💯 The String/ &str data types are UTF-8 encoded vectors. But you can not index into a String because of encoding.
⭐️ We can iterate over the characters of a string via the chars() method. But for more accurate results, you should use a crate like unicode_segmentation that follows more accurate Unicode text segmentation standards.
leta=String::from("Hello!");
+print!("{}",a.chars().count());// 6
+// 💡 H e l l o !
+
Rust was initially designed and developed by former Mozilla employee Graydon Hoare as a personal project. Mozilla began sponsoring the project in 2009 and announced it in 2010. But the first stable release, Rust 1.0, was released on May 15, 2015.
Since Rust 1.0, major updates have been released as Editions approximately every three years: Rust 2015 (with the release of Rust 1.0) , Rust 2018, Rust 2021, and Rust 2024, all maintaining backward compatibility.
Initial Goals
Rust is a systems programming language focused on three goals: safety, speed, and concurrency.~ Rust Documentation
It uses LLVM on the backend and supports many different operating systems, architectures, targets, and cross-compiling.
It supports imperative procedural, concurrent actor, object-oriented, and pure functional styles. Rust also supports generic programming and metaprogramming, in both static and dynamic styles.
It doesn’t use a built-in runtime or an automated garbage collection system (GC).
💡 However, async Rust requires an async runtime, which is provided by community-maintained crates like tokio, soml etc. The async runtime will be bundled into the final executable.
One of Rust’s most unique and compelling features is Ownership, which is used to achieve memory safety. Rust creates memory pointers optimistically, checks memory pointers’ limited accesses at compile-time with the usage of References and Borrowing. And it does automatic compile-time memory management by checking the Lifetimes.
Influences
Its design elements came from a wide range of sources.
Abstract Machine Model: C
Data types: C, SML, OCaml, Lisp, Limbo
Optional Bindings: Swift
Hygienic Macros: Scheme
Functional Programming: Haskell, OCaml, F#
Attributes: ECMA-335
Memory Model and Memory Management: C++, ML Kit, Cyclone
Type Classes: Haskell
Crate: Assembly in the ECMA-335 CLI model
Channels and Concurrency: Newsqueak, Alef, Limbo
Message passing and Thread failure: Erlang
and etc.
Rust compiler observes the code at compile-time and helps to prevent many types of errors that are possible to write in C, C++ like programming languages.
👨🏫 Before going to the next…
The following guides will be helpful for you to understand the maturity of the Rust ecosystem and the tools you need to choose, according to the area you want to master.
\ No newline at end of file
diff --git a/docs/docs/why-rust/og.jpg b/docs/docs/why-rust/og.jpg
new file mode 100644
index 00000000..8e6df777
Binary files /dev/null and b/docs/docs/why-rust/og.jpg differ
diff --git a/docs/docs/workspaces/index.html b/docs/docs/workspaces/index.html
new file mode 100644
index 00000000..ffbba10d
--- /dev/null
+++ b/docs/docs/workspaces/index.html
@@ -0,0 +1,55 @@
+Workspaces · Learning Rust
When the code base is getting larger, you might need to work with multiple crates on the same project. Rust supports this via Workspaces. You can analyze (cargo check), build, run tests or generate docs for all crates at once by running cargo commands from the project root.
⭐️ When working on multiple crates same time, there is a higher possibility of having shared dependencies on crates. To prevent downloading and compiling the same dependency multiple times, Rust uses a shared build directory under the project root, while running cargo build from the project root.
Let’s create a library crate with a simple hello world function and a binary crate which uses the library crate.
Assume we run,
mkdir greetings
+touch greetings/Cargo.toml
+cargo new greetings/lib --lib
+cargo new greetings/examples/hello
+
// 01. greetings/Cargo.toml to mark as a workspace and to add members
+[workspace]
+members=[
+"lib",
+"examples/hello"
+]
+
+// 02.1 greetings/lib/Cargo.toml to change the package name to greetings
+[package]
+name="greetings"
+version="0.1.0"
+authors=["Dumindu Madunuwan"]
+
+[dependencies]
+
+// 02.2 greetings/lib/src/lib.rs to add a simple hello world function
+pubfnhello(){
+println!("Hello, world!");
+}
+
+// 03.1 greetings/examples/hello/Cargo.toml to add the `greetings` lib as a dependency
+[package]
+name="hello"
+version="0.1.0"
+authors=["Dumindu Madunuwan"]
+
+[dependencies]
+greetings={path="../../lib"}
+
+// 03.2 greetings/examples/hello/src/main.rs to import the `greetings` lib and call its hello world function
+externcrategreetings;
+
+fnmain(){
+greetings::hello();
+}
+
💡 On Linux and Mac, you can run cargo commands on each crate without changing the working directory all the times via Subshells (A command list embedded between parentheses). For example, if you are in the greetings directory, even you run (cd examples/hello && cargo run) your working directory will be kept as same in greetings folder.
\ No newline at end of file
diff --git a/docs/index.xml b/docs/index.xml
new file mode 100644
index 00000000..e4e8581e
--- /dev/null
+++ b/docs/index.xml
@@ -0,0 +1,453 @@
+Learning Rusthttps://learning-rust.github.io/Recent content on Learning RustHugoen-USBorrowinghttps://learning-rust.github.io/docs/borrowing/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/borrowing/<p>In real life applications, most of the times we have to pass variable bindings to other functions or assign them to other variable bindings. In this case, we are <strong>referencing</strong> the original binding; <strong>borrow</strong> the data of it.</p>
+<h2 id="what-is-borrowing">What is Borrowing?</h2>
+<blockquote>
+<p><a href="https://github.com/nikomatsakis/rust-tutorials-keynote/blob/master/Ownership%20and%20Borrowing.pdf" target="_blank" >Borrow (verb)</a><br>
+To receive something with the promise of returning it.</p>
+</blockquote>
+<h2 id="shared--mutable-borrowings">Shared & Mutable borrowings</h2>
+<p>⭐️ There are two types of Borrowing,</p>
+<ol>
+<li>
+<p><strong>Shared Borrowing</strong> <code>(&T)</code></p>
+<ul>
+<li>A piece of data can be <strong>borrowed by a single or multiple users</strong>, but <strong>data should not be altered</strong>.</li>
+</ul>
+</li>
+<li>
+<p><strong>Mutable Borrowing</strong> <code>(&mut T)</code></p>Cargo, Crates and Basic Project Structurehttps://learning-rust.github.io/docs/cargo-crates-and-basic-project-structure/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/cargo-crates-and-basic-project-structure/<h2 id="cargo">Cargo</h2>
+<p>Cargo is Rust’s built-in package manager and build system. It also supports the following actions,</p>
+<table>
+ <thead>
+ <tr>
+ <th>Command</th>
+ <th>Action</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>cargo new</code></td>
+ <td>Create a new project</td>
+ </tr>
+ <tr>
+ <td><code>cargo init</code></td>
+ <td>Create a new project in an existing directory</td>
+ </tr>
+ <tr>
+ <td><code>cargo check</code></td>
+ <td>Verify the project compiles without errors</td>
+ </tr>
+ <tr>
+ <td><code>cargo build</code></td>
+ <td>Build the executable</td>
+ </tr>
+ <tr>
+ <td><code>cargo run</code></td>
+ <td>Build the executable and run</td>
+ </tr>
+ <tr>
+ <td><code>cargo clean</code></td>
+ <td>Remove the build system directories/ <code>target</code> directory</td>
+ </tr>
+ </tbody>
+</table>
+<blockquote>
+<p>💡 The <code>cargo check</code> command verifies that the project compiles without errors, without producing an executable.
+Thus, it is often faster than <code>cargo build</code>.</p>Combinatorshttps://learning-rust.github.io/docs/combinators/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/combinators/<h2 id="what-is-a-combinator">What is a combinator?</h2>
+<ul>
+<li>
+<p>One meaning of “combinator” is a more informal sense referring to the <strong>combinator pattern</strong>, a style of organizing libraries centered around the idea of combining things. Usually there is <strong>some type T</strong>, some <strong>functions for constructing “primitive” values of type T</strong>, and some “<strong>combinators</strong>” which can <strong>combine values of type T</strong> in various ways to <strong>build up more complex values of type T</strong>. The other definition is <strong>“function with no free variables”</strong>.
+__ <a href="https://wiki.haskell.org/Combinator" target="_blank" >wiki.haskell.org</a></p>Comments and Documenting the codehttps://learning-rust.github.io/docs/comments-and-documenting-the-code/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/comments-and-documenting-the-code/<h2 id="comments">Comments</h2>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">// Line comments
+</span></span></span><span class="line"><span class="cl"><span class="cm">/* Block comments */</span><span class="w">
+</span></span></span></code></pre></div><p>Nested block comments are supported.</p>
+<p>💡 <strong>By convention, try to avoid using block comments. Use line comments instead.</strong></p>
+<h2 id="doc-comments">Doc Comments</h2>
+<p><a href="https://learning-rust.github.io/docs/cargo-crates-and-basic-project-structure/#cargo" >As we discussed</a>, we can generate the project documentation via <a href="https://doc.rust-lang.org/stable/rustdoc/" target="_blank" >rustdoc</a> by running the <strong><code>cargo doc</code></strong> command. It uses the doc comments to generate the documentation.</p>
+<p>💡 Usually we are adding doc comments on library crates. Also, we can use <a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet" target="_blank" >Markdown notations</a> inside the doc comments.</p>Control Flowshttps://learning-rust.github.io/docs/control-flows/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/control-flows/<h2 id="if---else-if---else">if - else if - else</h2>
+<h3 id="if"><code>if</code></h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">age</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">13</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="w"> </span><span class="n">age</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">18</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, child!"</span><span class="p">);</span><span class="w"> </span><span class="c1">// The code prints this
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="if-else"><code>if</code> <code>else</code></h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">7</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">if</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Even"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Odd"</span><span class="p">);</span><span class="w"> </span><span class="c1">// The code prints this
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="with-let-statements">With <code>let</code> Statements</h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">age</span>: <span class="kt">u8</span> <span class="o">=</span><span class="w"> </span><span class="mi">13</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">is_below_eighteen</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">age</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">18</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kc">false</span><span class="w"> </span><span class="p">};</span><span class="w"> </span><span class="c1">// true
+</span></span></span></code></pre></div><h3 id="if-else-if-else"><code>if</code> <code>else if</code> <code>else</code></h3>
+<p>i. A simple example,</p>Crateshttps://learning-rust.github.io/docs/crates/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/crates/<p>💭 Crates are a bit similar to the packages in some other languages. Crates compile individually. If the crate has child file modules, those files will get merged with the crate file and compile as a single unit.</p>
+<p>💭 A crate can produce an executable/ a binary or a library. <code>src/main.rs</code> is the crate root/ entry point for a binary crate and <code>src/lib.rs</code> is the entry point for a library crate.</p>Custom Error Typeshttps://learning-rust.github.io/docs/custom-error-types/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/custom-error-types/<p>Rust allow us to create our own <code>Err</code> types. We call them “<em>Custom Error Types</em>”.</p>
+<h2 id="error-trait">Error trait</h2>
+<p>As you know <strong>traits define the functionality a type must provide</strong>. But we don’t always need to define new traits for common functionalities, because Rust <strong>standard library provides reusable traits</strong> which can be implemented on our own types. While creating custom error types the <a href="https://doc.rust-lang.org/std/error/trait.Error.html" target="_blank" ><code>std::error::Error</code> trait</a> helps us to convert any type to an <code>Err</code> type.</p>Enumshttps://learning-rust.github.io/docs/enums/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/enums/<ul>
+<li>An enum is a single type that contains variants, which represent the possible values of the enum at any given time.</li>
+<li>By convention, the enum name and its variants’ names should follow <a href="https://en.wikipedia.org/wiki/Camel_case" target="_blank" ><code>PascalCase</code></a>.</li>
+<li>Can access the variants using the <code>::</code> notation and the variant name. ex. Day::Sunday</li>
+</ul>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">enum</span> <span class="nc">Day</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Sunday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Monday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Tuesday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Wednesday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Thursday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Friday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Saturday</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// 💡 Day is the enum. Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday are its variants.
+</span></span></span></code></pre></div><ul>
+<li>An enum variant can have either,
+<ul>
+<li>No data (a unit variant)</li>
+<li>Unnamed ordered data (a tuple variant)</li>
+<li>Named data/ fields (a struct variant)</li>
+</ul>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">enum</span> <span class="nc">FlashMessage</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Success</span><span class="p">,</span><span class="w"> </span><span class="c1">// 💡 A unit variant (no data)
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Error</span><span class="p">(</span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="nb">String</span><span class="p">),</span><span class="w"> </span><span class="c1">// 💡 A tuple variant (one or more , separated data)
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">Warning</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">field</span>: <span class="nb">String</span><span class="p">,</span><span class="w"> </span><span class="n">message</span>: <span class="nb">String</span> <span class="p">},</span><span class="w"> </span><span class="c1">// 💡 A struct variant (one or more , separated name: value data)
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// 💡 FlashMessage is the emnum, Success, Error, Warning are its variants.
+</span></span></span></code></pre></div></li>
+</ul>
+<blockquote>
+<p>💡 In Rust, the term “instantiation” is used to describe the act of creating a concrete instance of a type (struct or enum).</p>Error and None Propagationhttps://learning-rust.github.io/docs/error-and-none-propagation/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/error-and-none-propagation/<p>We should use panics like <code>panic!()</code>, <code>unwrap()</code>, <code>expect()</code> only if we can not handle the situation in a better way. Also if a function contains expressions which can produce either <code>None</code> or <code>Err</code>,</p>
+<ul>
+<li>we can handle them inside the same function. Or,</li>
+<li>we can return <code>None</code> and <code>Err</code> types immediately to the caller. So the caller can decide how to handle them.</li>
+</ul>
+<p>💡 <code>None</code> types no need to handle by the caller of the function always. But Rusts’ convention to handle <strong><code>Err</code></strong> types is, <strong>return them immediately to the caller to give more control to the caller to decide how to handle them.</strong></p>Functionshttps://learning-rust.github.io/docs/functions/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/functions/<h2 id="named-functions">Named Functions</h2>
+<ul>
+<li>Named functions are declared with the keyword <strong><code>fn</code></strong></li>
+<li>When using <strong>arguments</strong>, we <strong>must declare the data types</strong>.</li>
+<li>By default, functions <strong>return an empty <a href="https://learning-rust.github.io/docs/primitive-data-types/#tuple" >tuple</a>/ <code>()</code></strong>. If you want to return a value, the <strong>return type must be specified</strong> after <strong><code>-></code></strong></li>
+</ul>
+<h3 id="hello-world">Hello world</h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="passing-arguments">Passing Arguments</h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">print_sum</span><span class="p">(</span><span class="n">a</span>: <span class="kt">i8</span><span class="p">,</span><span class="w"> </span><span class="n">b</span>: <span class="kt">i8</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"sum is: </span><span class="si">{}</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">b</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="returning-values">Returning Values</h3>
+<ul>
+<li>
+<p>Without the <code>return</code> keyword. Only the last expression returns.</p>Genericshttps://learning-rust.github.io/docs/generics/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/generics/<ul>
+<li>The core concept of generics is abstraction over types. They let us write one piece of code to operate with any data type without repeating ourselves to write separate versions for each type. At the compile time, Rust ensures the type safety and generates an optimized code for each concrete type used in the program.</li>
+<li>Use an uppercase letter (<code>T</code>, <code>U</code>, …) or a <a href="https://en.wikipedia.org/wiki/Camel_case" target="_blank" ><code>PascalCase</code></a> identifier for the data type.
+<ul>
+<li>Instead of <code>x: u8</code> we use <code>x: T</code>.</li>
+<li>Inform the compiler that <code>T</code> is a generic type by adding <code><T></code> at first.</li>
+</ul>
+</li>
+</ul>
+<h2 id="with-one-generic-type">With One Generic Type</h2>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Point</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">x</span>: <span class="nc">T</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">y</span>: <span class="nc">T</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">to_tuple</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">(</span><span class="n">x</span>: <span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="nc">T</span><span class="p">)</span><span class="w"> </span>-> <span class="p">(</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span>: <span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="mi">1</span><span class="w"> </span><span class="p">};</span><span class="w"> </span><span class="c1">// a: Point<i32>
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">to_tuple</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">y</span><span class="p">);</span><span class="w"> </span><span class="c1">// (i32, i32)
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{b:?}</span><span class="s">"</span><span class="p">);</span><span class="w"> </span><span class="c1">// (0, 1)
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span>: <span class="nc">false</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="nc">true</span><span class="w"> </span><span class="p">};</span><span class="w"> </span><span class="c1">// a: Point<bool>
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">to_tuple</span><span class="p">(</span><span class="n">c</span><span class="p">.</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="p">.</span><span class="n">y</span><span class="p">);</span><span class="w"> </span><span class="c1">// (bool, bool)
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{d:?}</span><span class="s">"</span><span class="p">);</span><span class="w"> </span><span class="c1">// (false, true)
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h2 id="with-multiple-generic-types">With Multiple Generic Types</h2>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Point</span><span class="o"><</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">U</span><span class="o">></span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">x</span>: <span class="nc">T</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">y</span>: <span class="nc">U</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">to_shuffled_tuple</span><span class="o"><</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">U</span><span class="o">></span><span class="p">(</span><span class="n">x</span>: <span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="nc">U</span><span class="p">)</span><span class="w"> </span>-> <span class="p">(</span><span class="n">U</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="p">,</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span>: <span class="mi">1</span><span class="k">u8</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="nc">true</span><span class="w"> </span><span class="p">};</span><span class="w"> </span><span class="c1">// a: Point<u8, bool>
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">to_shuffled_tuple</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">y</span><span class="p">);</span><span class="w"> </span><span class="c1">// (bool, u8)
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{b:?}</span><span class="s">"</span><span class="p">);</span><span class="w"> </span><span class="c1">// (true, 1)
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><p>On some occasions, the compiler cannot inter the type, and we have to specify the type when using the generic type. By the way, it’s good practice to specify the type on variables when using a generic implementation.</p>Hello Worldhttps://learning-rust.github.io/docs/hello-world/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/hello-world/<h2 id="hello-world">Hello, World!</h2>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><p><code>fn</code> means function. The <code>main</code> function is the beginning of every Rust program.
+<code>println!()</code> prints text to the console and its <code>!</code> indicates that it’s a <a href="https://doc.rust-lang.org/book/ch19-06-macros.html" target="_blank" >macro</a> rather than a function.</p>
+<blockquote>
+<p>💡 Rust files should have <code>.rs</code> file extension and if you’re using more than one word for the file name, follow the <a href="https://en.wikipedia.org/wiki/Snake_case" target="_blank" >snake_case</a> convention.</p>
+</blockquote>
+<ul>
+<li>Save the above code in <code>file.rs</code> , but it can be any name with <code>.rs</code> extension.</li>
+<li>Compile it with <code>rustc file.rs</code></li>
+<li>Execute it with <code>./file</code> on Linux and Mac or <code>file.exe</code> on Windows</li>
+</ul>
+<h2 id="rust-playground">Rust Playground</h2>
+<p><a href="https://play.rust-lang.org/" target="_blank" >Rust Playground</a> is a web interface for running Rust code.</p>Implshttps://learning-rust.github.io/docs/impls/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/impls/<ul>
+<li>Earlier, we discussed that structs and enums group related data, while impl blocks and traits add associated and shared behavior to the data.</li>
+<li>Usage of <code>Self</code> vs <code>self</code> keywords:
+<ul>
+<li><code>Self</code>: Refers to the type itself (the blueprint).</li>
+<li><code>self</code>: Refers to the instance of the type (the actual data).
+<ul>
+<li>💯 This can be any form of <code>self</code>, <code>&self</code>, <code>&mut self</code>, <code>self: Box<Self></code>, <code>self: Pin<&mut Self></code>, etc.</li>
+</ul>
+</li>
+</ul>
+</li>
+<li>There are multiple ways to implement a behavior for a type. We discuss only about the <code>impl</code> blocks with this article. The patterns involving traits are discussed under <a href="https://learning-rust.github.io/docs/traits" >Traits</a>.</li>
+</ul>
+<h2 id="inherent-impls">Inherent impls</h2>
+<p>Implement associated functions, methods, and constants directly for a type.</p>Installationhttps://learning-rust.github.io/docs/installation/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/installation/<h2 id="rustup">Rustup</h2>
+<p>There are many ways to install Rust on your system. For the moment the official way to install Rust is using <a href="https://rustup.rs/" target="_blank" >Rustup</a>.</p>
+<p><a href="https://rust-lang.github.io/rustup/index.html" target="_blank" >📖</a> Rustup installs The Rust Programming Language from the official release channels, enabling you to easily switch between <strong>stable, beta, and nightly</strong> compilers and keep them updated. It also makes cross-compiling simpler with binary builds of the standard library for common platforms.</p>
+<p><a href="https://rust-lang.github.io/rustup/installation/index.html" target="_blank" >📖</a> Rustup installs <code>rustc</code>, <code>cargo</code>, <code>rustup</code> and other standard tools to <strong>Cargo’s <code>bin</code> directory</strong>. On Unix it is located at <code>$HOME/.cargo/bin</code> and on Windows at <code>%USERPROFILE%\.cargo\bin</code>. This is the same directory that <code>cargo install</code> will install Rust programs and Cargo plugins.</p>Lifetimeshttps://learning-rust.github.io/docs/lifetimes/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/lifetimes/<p>When we are dealing with references, we have to make sure that the referencing data stay alive until we stop using the references.</p>
+<p>Think,</p>
+<ul>
+<li>We have a <strong>variable binding</strong>, <code>a</code>.</li>
+<li>We are <strong>referencing</strong> the value of <code>a</code>, <strong>from another variable binding</strong> <code>x</code>.
+We have to make sure that <strong><code>a</code> lives until we stop using <code>x</code></strong>.</li>
+</ul>
+<blockquote>
+<p>🔎 <strong>Memory management</strong> is a form of resource management applied to computer memory. Up until the mid-1990s, the majority of programming languages used <strong>Manual Memory Management</strong> which <strong>requires the programmer to give manual instructions</strong> to identify and deallocate unused objects/ garbage. Around 1959 John McCarthy invented <strong>Garbage collection</strong>(GC), a form of <strong>Automatic Memory Management</strong>(AMM). It determines what memory is no longer used and frees it automatically instead of relying on the programmer. However <strong>Objective-C and Swift</strong> provide similar functionality through <strong>Automatic Reference Counting</strong>(ARC).</p>Moduleshttps://learning-rust.github.io/docs/modules/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/modules/<h2 id="01-in-the-same-file">01. In the same file</h2>
+<p>Related code and data are grouped into a module and stored in the same file.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">greetings</span>::<span class="n">hello</span><span class="p">();</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">mod</span> <span class="nn">greetings</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c1">// ⭐️ By default, everything inside a module is private
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">hello</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// ⭐️ So function has to be public to access from outside
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><p>Modules can also be nested.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">phrases</span>::<span class="n">greetings</span>::<span class="n">hello</span><span class="p">();</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">mod</span> <span class="nn">phrases</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">mod</span> <span class="nn">greetings</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">hello</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><p>Private functions can be called from the same module or from a child module.</p>Operatorshttps://learning-rust.github.io/docs/operators/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/operators/<h2 id="arithmetic-operators">Arithmetic Operators</h2>
+<p><code>+ - * / %</code></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="c1">// 6
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="c1">// 4
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span><span class="w"> </span><span class="c1">// 10
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span><span class="w"> </span><span class="c1">// ⭐️ 2 not 2.5
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span><span class="w"> </span><span class="c1">// 1
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">5.0</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2.0</span><span class="p">;</span><span class="w"> </span><span class="c1">// 2.5
+</span></span></span></code></pre></div><h2 id="comparison-operators">Comparison Operators</h2>
+<p><code>== != < > <= >=</code></p>Option and Resulthttps://learning-rust.github.io/docs/option-and-result/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/option-and-result/<h2 id="why-option-and-result">Why Option and Result?</h2>
+<p>Many languages use <strong><code>null</code>\ <code>nil</code>\ <code>undefined</code> types</strong> to represent empty outputs, and <strong><code>Exceptions</code></strong> to handle errors. Rust skips using both, especially to prevent issues like <strong>null pointer exceptions, sensitive data leakages through exceptions</strong>, etc. Instead, Rust provides two special <strong>generic enums</strong>;<code>Option</code> and <code>Result</code> to deal with above cases.</p>
+<blockquote>
+<p>💭 In the previous sections, we have discussed about the basics of <a href="https://learning-rust.github.io/docs/enums" >enums</a>, <a href="https://learning-rust.github.io/docs/generics" >generics</a> and <a href="https://learning-rust.github.io/docs/generics/#generalizing-enums" ><code>Result</code> & <code>Option</code> types</a>.</p>Overviewhttps://learning-rust.github.io/docs/overview/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/overview/<h2 id="about-me">About me</h2>
+<blockquote>
+<p>🧑💻 I am an expat working in Singapore as a Go Backend and DevOps Engineer. Feel free to reach out if you find any mistakes or anything that needs to be changed, including spelling or grammar errors. Alternatively, you can create a pull request, open an issue, or <a href="https://gist.github.com/dumindu/00a0be2d175ed5ff3bc3c17bbf1ca5b6" target="_blank" >share your awesome ideas in this gist</a>. Good luck with learning Rust!</p>
+</blockquote>
+<p><a href="https://github.com/learning-rust/learning-rust.github.io" target="_blank" ><img src="https://img.shields.io/github/stars/learning-rust/learning-rust.github.io?style=for-the-badge&logo=rust&label=learning-rust.github.io&logoColor=333333&labelColor=f9f9f9&color=F46623" alt="learning-rust.github.io"></a>
+<a href="https://learning-cloud-native-go.github.io" target="_blank" ><img src="https://img.shields.io/github/stars/learning-cloud-native-go/learning-cloud-native-go.github.io?style=for-the-badge&logo=go&logoColor=333333&label=learning-cloud-native-go.github.io&labelColor=f9f9f9&color=00ADD8" alt="learning-cloud-native-go.github.io"></a></p>
+<p><a href="https://github.com/dumindu" target="_blank" ><img src="https://img.shields.io/badge/dumindu-866ee7?style=for-the-badge&logo=GitHub&logoColor=333333&labelColor=f9f9f9" alt="github.com"></a>
+<a href="https://www.buymeacoffee.com/dumindu" target="_blank" ><img src="https://img.shields.io/badge/Buy%20me%20a%20coffee-dumindu-FFDD00?style=for-the-badge&logo=buymeacoffee&logoColor=333333&labelColor=f9f9f9" alt="buymeacoffee"></a></p>
+<h2 id="overview">Overview</h2>
+<p>This publication has its origins in the posts I authored on Medium at <a href="https://medium.com/learning-rust" target="_blank" >https://medium.com/learning-rust</a>. However, please note that I have ceased updating the Medium posts. All current and future updates, new content, code, and grammar fixes will be exclusively maintained and released here, <a href="https://learning-rust.github.io" target="_blank" >https://learning-rust.github.io</a>.</p>Ownershiphttps://learning-rust.github.io/docs/ownership/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/ownership/<p>We discussed in the <a href="https://learning-rust.github.io/docs/traits/#derive-traits" >Derive Traits</a>, the usage of <a href="https://doc.rust-lang.org/std/marker/trait.Copy.html" target="_blank" ><code>Copy</code> marker trait</a> and <a href="https://doc.rust-lang.org/std/clone/index.html" target="_blank" ><code>.clone()</code></a> with the below code.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="cp">#[derive(Debug, Clone, Copy)]</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Point</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">x</span>: <span class="kt">i32</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">y</span>: <span class="kt">i32</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span>: <span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="mi">1</span><span class="w"> </span><span class="p">};</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{a:?}</span><span class="s">, </span><span class="si">{b:?}</span><span class="s">"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><p>If we try to remove <code>Copy</code> derive on <code>Point</code> and run, we will get the following error while compiling.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="n">error</span><span class="p">[</span><span class="n">E0382</span><span class="p">]</span>: <span class="nc">borrow</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">moved</span><span class="w"> </span><span class="n">value</span>: <span class="err">`</span><span class="n">a</span><span class="err">`</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">-</span>-> <span class="nc">src</span><span class="o">/</span><span class="n">main</span><span class="p">.</span><span class="n">rs</span>:<span class="mi">11</span>:<span class="mi">16</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span>: <span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">y</span>: <span class="mi">1</span><span class="w"> </span><span class="p">};</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="k">move</span><span class="w"> </span><span class="n">occurs</span><span class="w"> </span><span class="n">because</span><span class="w"> </span><span class="err">`</span><span class="n">a</span><span class="err">`</span><span class="w"> </span><span class="n">has</span><span class="w"> </span><span class="k">type</span> <span class="err">`</span><span class="n">Point</span><span class="err">`</span><span class="p">,</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="n">does</span><span class="w"> </span><span class="n">not</span><span class="w"> </span><span class="n">implement</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="err">`</span><span class="nb">Copy</span><span class="err">`</span><span class="w"> </span><span class="k">trait</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="mi">9</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="n">moved</span><span class="w"> </span><span class="n">here</span><span class="w">
+</span></span></span></code></pre></div><p>This is because of Ownership, which is used to achieve Rust’s memory safety.</p>Panickinghttps://learning-rust.github.io/docs/panicking/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/panicking/<h2 id="panic">panic!()</h2>
+<ul>
+<li>In some cases, when an error occurs we can not do anything to handle it, <strong>if the error is something which should not have happened</strong>. In other words, if it’s an <strong>unrecoverable error</strong>.</li>
+<li>Also <strong>when we are not using a feature-rich debugger or proper logs</strong>, sometimes we need to <strong>debug the code by quitting the program from a specific line of code</strong> by printing out a specific message or a value of a variable binding to understand the current flow of the program.
+For above cases, we can use <code>panic!</code> macro.</li>
+</ul>
+<p>⭐ <code>panic!()</code> runs <strong>thread based</strong>. One thread can be panicked, while other threads are running.</p>Primitive Data Typeshttps://learning-rust.github.io/docs/primitive-data-types/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/primitive-data-types/<h2 id="bool">bool</h2>
+<p>true or false</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">b</span>: <span class="kt">bool</span> <span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// ⭐️ no TRUE, FALSE, 1, 0
+</span></span></span></code></pre></div><p>bool is a single byte(8 bits) in size.</p>
+<h2 id="char">char</h2>
+<p>A single Unicode scalar value</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sc">'x'</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">b</span>: <span class="kt">char</span> <span class="o">=</span><span class="w"> </span><span class="sc">'😎'</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// ⭐️ no "x", only single quotes
+</span></span></span></code></pre></div><p>Because of Unicode support, char is not a single byte, but four(32 bits).</p>
+<h2 id="i8-i16-i32-i64-i128">i8, i16, i32, i64, i128</h2>
+<p>8, 16, 32, 64 and 128 bit fixed sized signed(+/-) integer types</p>Smart Compilerhttps://learning-rust.github.io/docs/smart-compiler/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/smart-compiler/<h2 id="why-compiler">Why Compiler?</h2>
+<p>The Rust compiler does the most significant job to prevent errors in Rust programs. It <strong>analyzes the code at compile-time</strong> and issues warnings, if the code does not follow memory management rules or lifetime annotations correctly.</p>
+<p>For example,</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="cp">#[allow(unused_variables)]</span><span class="w"> </span><span class="c1">//💡 A lint attribute used to suppress the warning; unused variable: `b`
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">];</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{:?}</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// ------ Compile-time error ------
+</span></span></span><span class="line"><span class="cl"><span class="n">error</span><span class="p">[</span><span class="n">E0382</span><span class="p">]</span>: <span class="nc">use</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">moved</span><span class="w"> </span><span class="n">value</span>: <span class="err">`</span><span class="n">a</span><span class="err">`</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">-</span>-> <span class="nc">src</span><span class="o">/</span><span class="n">main</span><span class="p">.</span><span class="n">rs</span>:<span class="mi">6</span>:<span class="mi">22</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="mi">3</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="n">moved</span><span class="w"> </span><span class="n">here</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="mi">4</span><span class="w"> </span><span class="o">|</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="mi">5</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"</span><span class="si">{:?}</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="n">used</span><span class="w"> </span><span class="n">here</span><span class="w"> </span><span class="n">after</span><span class="w"> </span><span class="k">move</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">|</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">note</span>: <span class="nc">move</span><span class="w"> </span><span class="n">occurs</span><span class="w"> </span><span class="n">because</span><span class="w"> </span><span class="err">`</span><span class="n">a</span><span class="err">`</span><span class="w"> </span><span class="n">has</span><span class="w"> </span><span class="k">type</span> <span class="err">`</span><span class="n">std</span>::<span class="n">vec</span>::<span class="nb">Vec</span><span class="o"><</span><span class="kt">i32</span><span class="o">></span><span class="err">`</span><span class="p">,</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="n">does</span><span class="w"> </span><span class="n">not</span><span class="w"> </span><span class="n">implement</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="err">`</span><span class="nb">Copy</span><span class="err">`</span><span class="w"> </span><span class="k">trait</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="n">error</span>: <span class="nc">aborting</span><span class="w"> </span><span class="n">due</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">previous</span><span class="w"> </span><span class="n">error</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="n">For</span><span class="w"> </span><span class="n">more</span><span class="w"> </span><span class="n">information</span><span class="w"> </span><span class="n">about</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">error</span><span class="p">,</span><span class="w"> </span><span class="kr">try</span><span class="w"> </span><span class="err">`</span><span class="n">rustc</span><span class="w"> </span><span class="o">--</span><span class="n">explain</span><span class="w"> </span><span class="n">E0382</span><span class="err">`</span><span class="p">.</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// ⭐ instead using #[allow(unused_variables)], consider using "let _b = a;" in line 4.
+</span></span></span><span class="line"><span class="cl"><span class="c1">// Also you can use "let _ =" to completely ignore return values
+</span></span></span></code></pre></div><blockquote>
+<p>💭 In the previous sections, we have discussed memory management concepts like <a href="https://learning-rust.github.io/docs/ownership" >ownership</a>, <a href="https://learning-rust.github.io/docs/borrowing" >borrowing</a>, <a href="https://learning-rust.github.io/docs/lifetimes" >lifetimes</a> and etc.</p>STD, Primitives and Preludeshttps://learning-rust.github.io/docs/std-primitives-and-preludes/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/std-primitives-and-preludes/<p>⭐️ In Rust, language elements are implemented by not only <strong><code>std</code> library</strong> crate but also <strong>compiler</strong> as well. Examples,</p>
+<ul>
+<li><strong><a href="https://doc.rust-lang.org/std/#primitives" target="_blank" >Primitives</a></strong>: Defined by the compiler and methods are implemented by <code>std</code> library directly on primitives.</li>
+<li><strong><a href="https://doc.rust-lang.org/std/#macros" target="_blank" >Standard Macros</a></strong>: Defined by both compiler and <code>std</code></li>
+</ul>
+<p>The <strong><code>std</code></strong> library has been divided into <strong><a href="https://doc.rust-lang.org/std/#modules" target="_blank" >modules</a></strong>, according to the main areas each covered.</p>
+<p>⭐️ While primitives are implemented by the <strong>compiler</strong>, the standard library implements the <strong>most useful methods</strong> directly on the primitive types. But some <strong>rarely useful language elements</strong> of some primitives are stored on relevant <strong><code>std</code> modules</strong>. This is why you can see <code>char</code>, <code>str</code> and integer types on both <a href="https://doc.rust-lang.org/std/#primitives" target="_blank" >primitives</a> and <a href="https://doc.rust-lang.org/std/#modules" target="_blank" ><code>std</code> modules</a>.</p>Structshttps://learning-rust.github.io/docs/structs/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/structs/<ul>
+<li>Used to <strong>encapsulate related properties into one unified data type</strong>.</li>
+<li>By convention, the name should follow <a href="https://en.wikipedia.org/wiki/Camel_case" target="_blank" ><code>PascalCase</code></a>.</li>
+<li>3 variants,
+<ul>
+<li>
+<p>C-like structs: One or more <code>,</code> separated <code>name: value pairs</code> enclosed in <code>{}</code></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Color</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">red</span>: <span class="kt">u8</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">green</span>: <span class="kt">u8</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">blue</span>: <span class="kt">u8</span><span class="p">,</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div></li>
+<li>
+<p>Tuple structs: One or more <code>,</code> separated <code>values</code> enclosed in <code>()</code></p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Color</span><span class="p">(</span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="kt">u8</span><span class="p">);</span><span class="w">
+</span></span></span></code></pre></div></li>
+<li>
+<p>Unit structs: A struct with no fields/ members</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Black</span><span class="p">;</span><span class="w">
+</span></span></span></code></pre></div></li>
+</ul>
+</li>
+</ul>
+<blockquote>
+<p>⭐️ In Rust, data (attributes) and behavior (associated functions and methods) are placed separately. Structs and Enums are used to group related data, and impls and traits are used to add associated and shared behavior to that data.</p>Traitshttps://learning-rust.github.io/docs/traits/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/traits/<p>A trait is a contract that defines a set of behaviors or properties that a type must implement. It can contain associated types, constants, function or method signatures, and overridable default implementations.</p>
+<h2 id="definition">Definition</h2>
+<h3 id="with-no-associates">With No Associates</h3>
+<p>💡 Mostly used to mark a type as having certain properties to allow in certain operations. Known as Marker Traits.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">pub</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="nb">Sized</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="with-the-declarations-of-associates">With the Declarations of Associates</h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">trait</span><span class="w"> </span><span class="n">Greet</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="no">PREFIX</span>: <span class="kp">&</span><span class="nb">'static</span> <span class="kt">str</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">type</span> <span class="nc">Item</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">fn</span> <span class="nf">greet</span><span class="p">(</span><span class="o">&</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">String</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="with-the-default-implementations-of-associates">With the Default Implementations of Associates</h3>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">trait</span><span class="w"> </span><span class="n">Greet</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="no">PREFIX</span>: <span class="kp">&</span><span class="nb">'static</span> <span class="kt">str</span> <span class="o">=</span><span class="w"> </span><span class="s">"Hello"</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">fn</span> <span class="nf">greet</span><span class="p">(</span><span class="o">&</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">String</span> <span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">format!</span><span class="p">(</span><span class="s">"</span><span class="si">{}</span><span class="s">!"</span><span class="p">,</span><span class="w"> </span><span class="nb">String</span>::<span class="n">from</span><span class="p">(</span><span class="bp">Self</span>::<span class="no">PREFIX</span><span class="p">))</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h3 id="with-supertraits">With Supertraits</h3>
+<p>A trait must have to be implemented first before implementing the current trait.</p>Unwrap and Expecthttps://learning-rust.github.io/docs/unwrap-and-expect/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/unwrap-and-expect/<h2 id="unwrap">unwrap()</h2>
+<ul>
+<li>If an <code>Option</code> type has <strong><code>Some</code></strong> value or a <code>Result</code> type has a <strong><code>Ok</code></strong> value, <strong>the value inside them</strong> passes to the next step.</li>
+<li>If the <code>Option</code> type has <strong><code>None</code></strong> value or the <code>Result</code> type has <strong><code>Err</code></strong> value, <strong>program panics</strong>; If <code>Err</code>, panics with the error message.</li>
+</ul>
+<p>The functionality is bit similar to the following codes, which are using <code>match</code> instead <code>unwrap()</code>.</p>
+<p>Example with <code>Option</code> and <code>match</code>, before using <code>unwrap()</code></p>Usehttps://learning-rust.github.io/docs/use/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/use/<p>Let’s see the main usages of the <code>use</code> keyword.</p>
+<h2 id="01-bind-a-full-path-to-a-new-name">01. Bind a full path to a new name</h2>
+<p>Mainly <code>use</code> keyword is used to bind a full path of an element to a new name. So the user doesn’t want to repeat the full path each time.</p>
+<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="c1">// -- Initial code without the `use` keyword --
+</span></span></span><span class="line"><span class="cl"><span class="k">mod</span> <span class="nn">phrases</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">mod</span> <span class="nn">greetings</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">hello</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Hello, world!"</span><span class="p">);</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">phrases</span>::<span class="n">greetings</span>::<span class="n">hello</span><span class="p">();</span><span class="w"> </span><span class="c1">// Using full path
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// -- Usage of the `use` keyword --
+</span></span></span><span class="line"><span class="cl"><span class="c1">// 01. Create an alias for module
+</span></span></span><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">phrases</span>::<span class="n">greetings</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">greetings</span>::<span class="n">hello</span><span class="p">();</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// 02. Create an alias for module elements
+</span></span></span><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">phrases</span>::<span class="n">greetings</span>::<span class="n">hello</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">hello</span><span class="p">();</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="c1">// 03. Customize names with the `as` keyword
+</span></span></span><span class="line"><span class="cl"><span class="k">use</span><span class="w"> </span><span class="n">phrases</span>::<span class="n">greetings</span>::<span class="n">hello</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">greet</span><span class="p">;</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">greet</span><span class="p">();</span><span class="w">
+</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
+</span></span></span></code></pre></div><h2 id="02-import-elements-to-scope">02. Import elements to scope</h2>
+<p>Another common usage of <code>use</code> is importing elements to scope. Remember that, this is also a bit similar to creating an alias and using it instead of using the full path.</p>Variable bindings, Constants & Staticshttps://learning-rust.github.io/docs/variable-bindings-constants-and-statics/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/variable-bindings-constants-and-statics/<ul>
+<li>Rust is a statically typed language; it checks data types at compile-time. But it doesn’t require you to actually type data types when declaring variable bindings. In that case, the compiler checks the usage and sets a better data type for it.</li>
+<li>⭐️ For <strong>constants and statics, we must annotate the data type</strong>.</li>
+<li>Types come after a <code>:</code> (colon) sign.</li>
+<li>The naming convention for the variable bindings is using the <a href="https://en.wikipedia.org/wiki/Snake_case" target="_blank" ><code>snake_case</code></a>. But, for constants and statics, we should follow the <a href="https://en.wikipedia.org/wiki/Snake_case" target="_blank" ><code>SCREAMING_SNAKE_CASE</code></a>.</li>
+</ul>
+<blockquote>
+<p>💭 In the following examples, we will use <a href="https://learning-rust.github.io/docs/primitive-data-types" >data types</a> like <code>bool</code>, <code>i32</code>, <code>i64</code> and <code>f64</code>. Don’t worry about them for now; they’ll be discussed later.</p>Vectorshttps://learning-rust.github.io/docs/vectors/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/vectors/<p>If you remember, the array is a fixed-size list of elements, of the same data type. Even with mut, its element count cannot be changed. A vector is <strong>kind of a re-sizable array</strong> but <strong>all elements must be in the same type</strong>.</p>
+<blockquote>
+<p>💡 <code>Vec<T></code>: capital “V” as <a href="https://doc.rust-lang.org/std/vec/struct.Vec.html" target="_blank" >it’s a struct</a>.</p>
+</blockquote>
+<p>It’s a generic type, written as <strong><code>Vec<T></code></strong>. T can have any type, ex. A vector of i32s is <code>Vec<i32></code>. Also, Vectors always allocate their data in a dynamically allocated heap.</p>Why Rust?https://learning-rust.github.io/docs/why-rust/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/why-rust/<h2 id="history-of-rust">History of Rust</h2>
+<p>Rust was initially designed and developed by former Mozilla employee <strong><a href="https://github.com/graydon" target="_blank" >Graydon Hoare</a></strong> as a personal project. Mozilla began sponsoring the project in 2009 and announced it in 2010. But the first stable release, Rust 1.0, was released on May 15, 2015.</p>
+<p>Since Rust 1.0, major updates have been released as <a href="https://learning-rust.github.io/docs/cargo-crates-and-basic-project-structure/#rust-editions" ><code>Editions</code></a> approximately every three years: Rust 2015 (with the release of Rust 1.0) , Rust 2018, Rust 2021, and Rust 2024, all maintaining backward compatibility.</p>Workspaceshttps://learning-rust.github.io/docs/workspaces/Mon, 01 Jan 0001 00:00:00 +0000https://learning-rust.github.io/docs/workspaces/<p>When the code base is getting larger, you might need to work with <strong>multiple crates on the same project</strong>. Rust supports this via Workspaces. You can <strong>analyze (<code>cargo check</code>), build, run tests or generate docs for all crates</strong> at once by running <code>cargo</code> commands from the project root.</p>
+<p>⭐️ When working on multiple crates same time, there is a higher possibility of having shared dependencies on crates. To prevent downloading and compiling the same dependency multiple times, Rust uses a <strong>shared build directory</strong> under the project root, while running <code>cargo build</code> from the project root.</p>
\ No newline at end of file
diff --git a/docs/manifest.json b/docs/manifest.json
new file mode 100644
index 00000000..87493f4f
--- /dev/null
+++ b/docs/manifest.json
@@ -0,0 +1,21 @@
+{
+ "name": "Learning Rust",
+ "short_name": "Learning Rust",
+ "description": "Rust Programming Language Tutorials for Everyone!",
+ "start_url": "/?source=pwa",
+ "display": "standalone",
+ "icons": [
+ {
+ "src": "/favicon/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/favicon/android-chrome-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "background_color": "#866ee7",
+ "theme_color": "#866ee7"
+}
\ No newline at end of file
diff --git a/docs/og.jpg b/docs/og.jpg
new file mode 100644
index 00000000..a7e65376
Binary files /dev/null and b/docs/og.jpg differ
diff --git a/docs/robots.txt b/docs/robots.txt
new file mode 100644
index 00000000..1068142a
--- /dev/null
+++ b/docs/robots.txt
@@ -0,0 +1,41 @@
+User-agent: Googlebot
+User-agent: YandexBot
+User-agent: baiduspider
+User-agent: Applebot
+Allow: /
+
+User-agent: *
+Disallow: /docs/borrowing/
+Disallow: /docs/cargo-crates-and-basic-project-structure/
+Disallow: /docs/combinators/
+Disallow: /docs/comments-and-documenting-the-code/
+Disallow: /docs/control-flows/
+Disallow: /docs/crates/
+Disallow: /docs/custom-error-types/
+Disallow: /docs/
+Disallow: /docs/enums/
+Disallow: /docs/error-and-none-propagation/
+Disallow: /docs/functions/
+Disallow: /docs/generics/
+Disallow: /docs/hello-world/
+Disallow: /docs/impls/
+Disallow: /docs/installation/
+Disallow: /
+Disallow: /docs/lifetimes/
+Disallow: /docs/modules/
+Disallow: /docs/operators/
+Disallow: /docs/option-and-result/
+Disallow: /docs/overview/
+Disallow: /docs/ownership/
+Disallow: /docs/panicking/
+Disallow: /docs/primitive-data-types/
+Disallow: /docs/smart-compiler/
+Disallow: /docs/std-primitives-and-preludes/
+Disallow: /docs/structs/
+Disallow: /docs/traits/
+Disallow: /docs/unwrap-and-expect/
+Disallow: /docs/use/
+Disallow: /docs/variable-bindings-constants-and-statics/
+Disallow: /docs/vectors/
+Disallow: /docs/why-rust/
+Disallow: /docs/workspaces/
\ No newline at end of file
diff --git a/docs/sitemap.xml b/docs/sitemap.xml
new file mode 100644
index 00000000..8cafa00b
--- /dev/null
+++ b/docs/sitemap.xml
@@ -0,0 +1 @@
+https://learning-rust.github.io/docs/borrowing/2022-10-17T01:47:29+08:00https://learning-rust.github.io/docs/cargo-crates-and-basic-project-structure/2025-10-13T20:20:39+08:00https://learning-rust.github.io/docs/combinators/2025-10-13T20:20:39+08:00https://learning-rust.github.io/docs/comments-and-documenting-the-code/2025-10-30T20:23:09+08:00https://learning-rust.github.io/docs/control-flows/2025-10-30T20:23:09+08:00https://learning-rust.github.io/docs/crates/2025-10-13T20:20:39+08:00https://learning-rust.github.io/docs/custom-error-types/2023-11-11T20:38:50+08:00https://learning-rust.github.io/docs/2026-03-04T11:37:51+08:00https://learning-rust.github.io/docs/enums/2025-12-09T03:28:34+08:00https://learning-rust.github.io/docs/error-and-none-propagation/2023-11-11T20:38:50+08:00https://learning-rust.github.io/docs/functions/2025-10-30T20:23:09+08:00https://learning-rust.github.io/docs/generics/2025-12-10T03:17:52+08:00https://learning-rust.github.io/docs/hello-world/2025-10-30T20:23:09+08:00https://learning-rust.github.io/docs/impls/2026-01-14T16:01:02+08:00https://learning-rust.github.io/docs/installation/2025-10-13T20:20:39+08:00https://learning-rust.github.io/2026-03-04T11:37:51+08:00https://learning-rust.github.io/docs/lifetimes/2025-10-13T20:20:39+08:00https://learning-rust.github.io/docs/modules/2022-10-17T01:47:29+08:00https://learning-rust.github.io/docs/operators/2025-11-03T21:22:05+08:00https://learning-rust.github.io/docs/option-and-result/2024-02-01T19:02:07+01:00https://learning-rust.github.io/docs/overview/2024-03-10T20:15:12+08:00https://learning-rust.github.io/docs/ownership/2026-02-23T20:27:43+08:00https://learning-rust.github.io/docs/panicking/2023-11-11T20:38:50+08:00https://learning-rust.github.io/docs/primitive-data-types/2025-12-01T20:29:50+08:00https://learning-rust.github.io/docs/smart-compiler/2023-11-11T20:38:50+08:00https://learning-rust.github.io/docs/std-primitives-and-preludes/2022-10-17T01:47:29+08:00https://learning-rust.github.io/docs/structs/2026-01-02T13:09:17+08:00https://learning-rust.github.io/docs/traits/2026-03-04T11:37:51+08:00https://learning-rust.github.io/docs/unwrap-and-expect/2023-11-11T20:38:50+08:00https://learning-rust.github.io/docs/use/2022-10-17T01:47:29+08:00https://learning-rust.github.io/docs/variable-bindings-constants-and-statics/2025-10-30T20:23:09+08:00https://learning-rust.github.io/docs/vectors/2025-12-01T20:29:50+08:00https://learning-rust.github.io/docs/why-rust/2026-01-02T11:44:19+08:00https://learning-rust.github.io/docs/workspaces/2025-10-13T20:20:39+08:00
\ No newline at end of file
diff --git a/docs/sw.js b/docs/sw.js
new file mode 100644
index 00000000..9c27f9f3
--- /dev/null
+++ b/docs/sw.js
@@ -0,0 +1,56 @@
+const cacheName = 'learning-rust-{{ now.Format "2006-01-02" }}';
+const staticAssets = [
+ './',
+ './index.html',
+ './manifest.json',
+ './docs/**/*',
+ './favicon/android-chrome-192x192.png',
+ './favicon/android-chrome-512x512.png',
+ './favicon/apple-touch-icon.png',
+ './favicon/favicon.ico',
+ './favicon/favicon-16x16.png',
+ './favicon/favicon-32x32.png',
+ './css/home.min.*.css',
+ './css/docs.min.*.css',
+ './js/home.min.*.js',
+ './js/docs.min.*.js',
+];
+
+self.addEventListener('install', async e => {
+ const cache = await caches.open(cacheName);
+ await cache.addAll(staticAssets);
+ return self.skipWaiting();
+});
+
+self.addEventListener('activate', e => {
+ self.clients.claim();
+});
+
+self.addEventListener('fetch', async e => {
+ const req = e.request;
+ const url = new URL(req.url);
+
+ if (url.origin === location.origin) {
+ e.respondWith(cacheFirst(req));
+ } else {
+ e.respondWith(networkFirst(req));
+ }
+});
+
+async function cacheFirst(req) {
+ const cache = await caches.open(cacheName);
+ const cached = await cache.match(req);
+ return cached || fetch(req);
+}
+
+async function networkFirst(req) {
+ const cache = await caches.open(cacheName);
+ try {
+ const fresh = await fetch(req);
+ cache.put(req, fresh.clone());
+ return fresh;
+ } catch (e) {
+ const cached = await cache.match(req);
+ return cached;
+ }
+}
\ No newline at end of file
diff --git a/docs/tags/index.xml b/docs/tags/index.xml
new file mode 100644
index 00000000..6e03319c
--- /dev/null
+++ b/docs/tags/index.xml
@@ -0,0 +1 @@
+Tags on Learning Rusthttps://learning-rust.github.io/tags/Recent content in Tags on Learning RustHugoen-US
\ No newline at end of file