Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
target/
target/
.env
5 changes: 5 additions & 0 deletions src/bin/02ca_strings.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
// Some Notes:
// clones are expensive, since the data in the heap for the strings must be copied into another heap location
// borrowed strings &str are fixed sized references to the underlying str data

fn main() {
let speech = "\"Ouch!\" said the well.\n";
// All Strings are the same size because they are simply the size of the Fat pointer pointing to some region in the heap memory

println!("Speech: {speech}");

Expand Down
10 changes: 10 additions & 0 deletions src/bin/0a_intro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,14 @@ fn main() {
the current directory the user must explicity specify the current directory
as the path to check for the script
*/

let name = String::from("Brian");
println!("Outer {name}");

{
let name = String::from("Hello");
println!("Inner {name}");
}

println!("Outer {name}");
}
13 changes: 13 additions & 0 deletions src/bin/17bb_hashset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use std::collections::{HashMap, HashSet};

fn main() {
let mut _ages = HashMap::<String, String>::new();
let mut seen = HashSet::<&str>::new();

// the insert method on hashset returns a boolean indicating whethere the item was added or not
// the item is added when it's not already present in the hashset else is it not added
let _inserted = seen.insert("Brian");
let _inserted = seen.insert("Joseph");

let _ = _ages.keys();
}
27 changes: 27 additions & 0 deletions src/bin/22d_more_on_iterators.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
fn main() {
let v = vec![1, 2, 3, 4, 5, 6];
let v_iter = v.iter();

for item in v_iter {
println!("Item: {item}")
}

for item in v {
println!("I: {item}");
}

// methods that call the next method in iterators are called consumers
// methods that do not call next method are called adapters
let sum_of_values = [1, 2, 3, 4, 5].iter().sum::<i32>();
println!("Sum of values = {sum_of_values}");

// after using a consumer, the iterator is well, CONSUMED
// adapters are methods that produce other iterators
// in this case, the map method is an adapter method
let _v2_iter = [2, 3, 4, 5].iter().map(|x| x * x).collect::<Vec<_>>();

// let sum_of_squares: i32 = v.iter()
// .filter(|&x| x % 2 == 0)
// .map(|x| x*x)
// .sum();
}
2 changes: 0 additions & 2 deletions src/bin/45_strings_and_text.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

fn main() {
// Rust treats strings as UTF-8 Encoded by default
let s = "你好 Rust";
Expand Down Expand Up @@ -31,4 +30,3 @@ fn main() {
// .is_ascii_alphabetic() ...
//
}

31 changes: 31 additions & 0 deletions src/bin/48c_send_and_sync.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::{sync::Arc, thread};

fn main() {
// Send data types can be sent across thread
let string = String::from("Data");
let handle = thread::spawn(move || {
println!("{string}");
});

handle.join().unwrap();

// Sync data types can be referenced from multiple threads
// the Arc is placed on the heap and a reference count it maintained
let data = Arc::new(5);

let clone1 = Arc::clone(&data);
let clone2 = Arc::clone(&data);

let handle_2 = thread::spawn(move || {
println!("{}", clone1);
});

let handle_3 = thread::spawn(move || {
println!("{}", clone2);
});

handle_2.join().unwrap();
handle_3.join().unwrap();

// T is Sync if &T is Send
}
146 changes: 146 additions & 0 deletions src/bin/49_macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
fn main() {
// an example of a macro is the assert_eq! macro
// this functionality could have been written as a generic function
// but macros do more than functions can do, for example, when an assert_eq! macro fails
// it prints the filename and the line number where the failure happened, fucntions have no way of getting that information

// macros are expanded during the compilation phase before types are checked and well before
// any machine code is generated, they are expanded recursively into rust code, since macros expansion
// can themselves contain macros
//
// macros are differentiated from functions with the bang symbol before their parenthesis
//
// macro_rules! macro is the main way to define macros in Rust
// when defining macros, the ! is not used, it is only used when calling them
// a macro defined by macro_rules works entirely by pattern matching
/*
* (pattern 1) => (template 1)
* (pattern 2) => (template 2)
*
*/

// you can use square brackets or curly braces for macros, they are still work
println!("Hello");
println!["Hello"]; // this is why vec! is possible
println! {"Hello"};

// by convention, () are used for assert_*! macros, [] for vec! and {} for macro_rules!
// assert_eq! expands to
// assert_eq![2, 1 + 1];

/*
* match (&2, &(1 + 1)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(
kind,
&*left_val,
&*right_val,
::core::option::Option::None,
);
}
}
};
*/

macro_rules! answer {
() => {
42
};
}

macro_rules! double {
($x:expr) => {
$x * 2
};
}

let result = double!(answer!());
println!("Result: {}", result);

// Some interestig macros
// file!() return a string path of the current file
// line!() return the line which the first macro that call it was called from
// column!() same as above, but for column
// include!("filename.rs"), includes the content of the file in the current line, the content must be valid Rust code
// include_str!("file.txt"), include the text content of the specified file
// include_bytes!("file.dat") same as above, but the file is treated a binary data
// todo!(), unimplemented!()
// matches!(value, pattern)

// Building the json! Macro
use std::collections::HashMap;

#[allow(dead_code)]
#[derive(Clone, PartialEq, Debug)]
enum Json {
Null,
Boolean(bool),
Number(f64),
String(String),
Array(Vec<Json>),
#[allow(clippy::box_collection)]
Object(Box<HashMap<String, Json>>),
}

macro_rules! json {
// the null literal must be matched directly
(null) => { Json::Null };
([ $( $element:tt ),* ]) => { Json::Array(vec![ $( json!($element) ),* ]) };
({ $( $key:tt : $value:tt ),* }) => { Json::Object(Box::new(vec![
$( ($key.to_string(), json!($value)) ),*
])) };
( $other:tt ) => {
Json::from($other)
}
}

impl From<bool> for Json {
fn from(b: bool) -> Json {
Json::Boolean(b)
}
}

impl From<String> for Json {
fn from(value: String) -> Json {
Json::String(value)
}
}

impl<'a> From<&'a str> for Json {
fn from(value: &'a str) -> Json {
Json::String(value.to_string())
}
}

macro_rules! impl_from_num_for_json {
( $( $t:ident ),* ) => {
$(
impl From<$t> for Json {
fn from(n: $t) -> Json {
Json::Number(n as f64)
}
}
)*
};
}

impl_from_num_for_json!(
u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64
);

assert_eq!(json!(null), Json::Null);

let macro_generated_array = json!([1, 2, 3, 4]);
let hand_coded_array = Json::Array(vec![
Json::Number(1.),
Json::Number(2.),
Json::Number(3.),
Json::Number(4.),
]);

assert_eq!(macro_generated_array, hand_coded_array);

// Macros marked with #[macro_export] are automatically public to other modules
}
14 changes: 14 additions & 0 deletions src/bin/50_unsafe_code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
macro_rules! capitalize {
($a: expr) => {
let mut v: Vec<char> = $a.chars().collect();
v[0] = v[0].to_uppercase().nth(0).unwrap();
$a = v.into_iter().collect();
};
}

fn main() {
let mut name = String::from("test");
capitalize!(name);

println!("{name}");
}
3 changes: 3 additions & 0 deletions src/bin/51_environment_variables.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// const API_KEY: &'static str = env!("API_KEY");

fn main() {}
Loading