├── 00_hello_world ├── python │ ├── hello_world.py │ └── syntax.py └── rust │ ├── hello_world.rs │ └── syntax.rs ├── 01_numbers ├── python │ ├── cast.py │ ├── numbers.py │ ├── scope.py │ └── variables.py └── rust │ ├── cast.rs │ ├── numbers.rs │ ├── scope.rs │ └── variables.rs ├── 02_ecosystem └── geo │ ├── Cargo.toml │ ├── examples │ └── demo.rs │ └── src │ └── lib.rs ├── 03_tuples_arrays ├── python │ ├── arrays.py │ ├── lists.py │ └── tuples.py └── rust │ ├── arrays.rs │ ├── tuples.rs │ └── vectors.rs ├── 04_strings_unicode ├── python │ ├── multiline.py │ ├── strings.py │ ├── uppercase.py │ └── utf8.py └── rust │ ├── multiline.rs │ ├── strings.rs │ ├── uppercase.rs │ └── utf8.rs ├── 05_functions ├── python │ ├── closures.py │ ├── fizzbuzz.py │ └── functions.py └── rust │ ├── closures.rs │ ├── fizzbuzz.rs │ └── functions.rs ├── 06_pattern_matching ├── python │ ├── fizzbuzz.py │ └── pattern_matching.py └── rust │ ├── fizzbuzz.rs │ └── pattern_matching.rs ├── 07_structs ├── python │ ├── classes.py │ └── defaults.py └── rust │ ├── defaults.rs │ └── structs.rs ├── 08_hashmaps ├── python │ ├── defaultdict.py │ └── dicts.py └── rust │ ├── hashmap.rs │ ├── maplit.rs │ └── or_insert.rs ├── 09_iterators ├── python │ └── iterators.py └── rust │ └── iterators │ ├── Cargo.toml │ └── src │ └── lib.rs ├── 0a_error_handling ├── python │ ├── boilerplate.py │ └── nohandling.py └── rust │ ├── boilerplate.rs │ ├── more_boilerplate.rs │ ├── nohandling.rs │ └── using_eyre │ ├── Cargo.toml │ └── src │ ├── bin │ └── thiserror.rs │ └── main.rs ├── 0b_traits ├── python │ ├── defaults.py │ ├── iterators.py │ └── super.py └── rust │ ├── defaults.rs │ ├── iterators │ ├── Cargo.toml │ └── src │ │ └── lib.rs │ ├── return_trait.rs │ └── supertraits.rs ├── 0c_operator_overloading └── rust │ └── operator_overloading.rs ├── 0d_files ├── python │ ├── binary.py │ └── simple.py └── rust │ ├── binary │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── bufread_iterator.rs │ ├── bufread_lines.rs │ └── simple.rs ├── 0f_debugging └── rust │ └── fizzbuzz.rs ├── 10_smart_pointers ├── python │ ├── bintree.py │ └── rc.py └── rust │ ├── bintree.rs │ ├── rc.rs │ └── smartpointers.rs ├── 11_multithreading ├── python │ ├── lock_count.py │ └── naive_count.py └── rust │ ├── lock_count.rs │ ├── lock_object.rs │ ├── naive_count.rs │ └── naive_object.rs ├── 12_modules ├── python │ ├── foo │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-39.pyc │ │ │ └── other.cpython-39.pyc │ │ └── other.py │ ├── main.py │ └── modules.py └── rust │ ├── foo.rs │ ├── foo │ └── other.rs │ ├── main.rs │ ├── modules.rs │ └── reexports.rs ├── 13_async ├── python │ └── minimal.py └── rust │ └── std_async │ ├── Cargo.toml │ └── src │ └── main.rs ├── 14_context_manager ├── python │ └── context_manager.py └── rust │ └── context_manager.rs ├── 15_pymod_in_rust ├── python │ └── monte_carlo_pi.py └── rust │ ├── monte_carlo_pi │ ├── Cargo.toml │ ├── examples │ │ └── pi.rs │ └── src │ │ └── lib.rs │ ├── py_monte_carlo_pi │ ├── .cargo │ │ └── config │ ├── Cargo.toml │ └── src │ │ └── lib.rs │ └── pyo3_monte_carlo_pi │ ├── .cargo │ └── config │ ├── Cargo.toml │ └── src │ └── lib.rs ├── 16_python_inside_rust └── rust │ ├── inlinepy │ ├── Cargo.toml │ ├── rust-toolchain │ └── src │ │ └── main.rs │ └── py_in_rust │ ├── Cargo.toml │ └── src │ └── main.rs ├── 17_regex ├── python │ ├── io_regex.py │ └── iso_8601.py └── rust │ └── io_regex │ ├── Cargo.toml │ └── src │ ├── iso_8601.rs │ └── main.rs ├── 18_argparse ├── python │ └── argp.py └── rust │ └── argp │ ├── Cargo.toml │ └── src │ └── main.rs ├── 19_numpy ├── python │ ├── eigenvector.py │ └── simple.py └── rust │ └── simple │ ├── Cargo.toml │ ├── README.md │ ├── examples │ └── eigenvector.rs │ └── src │ └── main.rs ├── 1a_logging ├── python │ ├── foo │ │ ├── __init__.py │ │ └── bar.py │ ├── log.py │ └── logconf.yaml └── rust │ └── logex │ ├── Cargo.toml │ └── src │ └── main.rs ├── 1b_sockets ├── python │ ├── echoclient.py │ ├── echoserver.py │ ├── tlsechoclient.py │ └── tlsechoserver.py └── rust │ ├── echoclient.rs │ ├── echoserver.rs │ └── tlsecho │ ├── Cargo.toml │ └── src │ ├── bin │ ├── rawserver.rs │ └── server.rs │ └── main.rs ├── 1c_xml ├── cd-list.xml ├── python │ ├── elemtree.py │ └── minidom.py └── rust │ └── xml │ ├── Cargo.toml │ └── src │ ├── bin │ └── minidom.rs │ └── main.rs ├── 1d_json ├── python │ ├── minimal.py │ └── person.py └── rust │ └── json │ ├── Cargo.toml │ ├── rust-toolchain │ └── src │ ├── bin │ └── person.rs │ └── main.rs ├── 1e_http_client ├── python │ ├── async.py │ ├── blocking.py │ └── person.py └── rust │ └── http_client │ ├── Cargo.toml │ └── src │ ├── bin │ └── async.rs │ ├── lib.rs │ ├── main.rs │ └── person.rs ├── 1f_http_server ├── python │ └── fastapi_srv.py ├── rust │ └── warp_srv │ │ ├── Cargo.toml │ │ └── src │ │ └── main.rs └── static │ └── index.html ├── 20_sqlite ├── import_cases.sh ├── import_cases.sql ├── python │ └── sqlite.py └── rust │ └── sqlite │ ├── Cargo.toml │ └── src │ ├── helpers.rs │ └── main.rs ├── 21_postgresql ├── import_cases.sh ├── import_cases.sql ├── python │ ├── helper.py │ ├── pg_async.py │ └── pg_blocking.py └── rust │ ├── pg_async │ ├── Cargo.toml │ └── src │ │ └── main.rs │ └── pg_blocking │ ├── Cargo.toml │ └── src │ └── main.rs ├── 22_websockets_server ├── python │ ├── atomic.py │ └── fastapi_ws.py ├── rust │ └── warp_ws │ │ ├── Cargo.toml │ │ └── src │ │ └── main.rs └── static │ └── index.html ├── 23_websockets_client ├── python │ └── ws_client.py └── rust │ └── ws_client │ ├── Cargo.toml │ └── src │ └── main.rs ├── 24_raster_graphics ├── python │ └── thumbnails.py └── rust │ └── thumbnail │ ├── Cargo.toml │ └── src │ └── main.rs ├── 25_vector_graphics ├── python │ └── cairodraw.py └── rust │ └── cairodraw │ ├── Cargo.toml │ └── src │ └── main.rs ├── 26_plotting ├── python │ └── matplotlib_ex.py └── rust │ └── plotters_ex │ ├── Cargo.toml │ └── src │ └── main.rs ├── 27_fltk ├── python │ └── fltk_ex.py └── rust │ └── fltk_ex │ ├── Cargo.toml │ └── src │ └── main.rs ├── 28_rusty_python └── python │ ├── higher_order.py │ ├── pattern_matching.py │ └── type_hinting.py ├── 29_pattern_matching_revisited ├── python │ ├── cmd_split.py │ └── match_obj.py └── rust │ └── pattern │ ├── Cargo.toml │ ├── examples │ └── enum_dispatch.rs │ └── src │ └── main.rs ├── 2a_builder_pattern ├── python │ └── default_args.py └── rust │ └── builder │ ├── Cargo.toml │ └── src │ └── main.rs ├── 2b_builder_type_state ├── python │ └── typed_builder.py └── rust │ ├── email_builder │ ├── Cargo.toml │ └── src │ │ └── main.rs │ └── typed_builder_example │ ├── Cargo.toml │ └── src │ └── main.rs ├── LICENSE └── README.md /00_hello_world/python/hello_world.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | "classic Hello World example in Python." 3 | 4 | if __name__ == '__main__': 5 | # output of hello world 6 | print("Hello World") 7 | -------------------------------------------------------------------------------- /00_hello_world/python/syntax.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | "docstring for module." 3 | 4 | def multiply(x: int, y: int) -> int: 5 | "docstring for function." 6 | # one line comment 7 | return x * y 8 | """multiline comment explaining 9 | that type hints using annotations are not 10 | enforced but can be used by third party tools 11 | such as type checkers, IDEs, linters, etc. 12 | """ 13 | 14 | 15 | if __name__ == "__main__": 16 | z = multiply(5, 6) 17 | print("result: {}".format(z)) 18 | txt = f"result: {z}" # python >= 3.6 19 | print(txt) 20 | -------------------------------------------------------------------------------- /00_hello_world/rust/hello_world.rs: -------------------------------------------------------------------------------- 1 | 2 | //! classic Hello World example in Rust 3 | 4 | fn main() { 5 | // output of hello world 6 | println!("Hello World"); 7 | } 8 | -------------------------------------------------------------------------------- /00_hello_world/rust/syntax.rs: -------------------------------------------------------------------------------- 1 | //! docstring for module 2 | 3 | /// docstring for function 4 | fn multiply(x: i64, y: i64) -> i64 { 5 | 6 | // one line comment 7 | x * y 8 | /* multiline comment explaining 9 | * that for returning a value 10 | * an expression as last line is enough 11 | */ 12 | } 13 | 14 | 15 | fn main() { 16 | let z = multiply(5, 6); 17 | println!("result: {}", z); 18 | let txt = format!("result: {z}", z=z); 19 | println!("{}", txt); 20 | } 21 | -------------------------------------------------------------------------------- /01_numbers/python/cast.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | f = 1.23 3 | i = int(f) 4 | 5 | print(i, f) 6 | 7 | x = 1.321 8 | y = 1.32 9 | print(f"{x} == {y}", x == y) 10 | x = 1.3200000000000000001 11 | y = 1.32 12 | print(f"{x} == {y}", x == y) 13 | -------------------------------------------------------------------------------- /01_numbers/python/numbers.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | # integers 3 | x = -1000 4 | 5 | y = 100 6 | 7 | large_number = 123_456_789 # python >= 3.6 8 | 9 | # floats 10 | xf = -1.2345 11 | xf = -1.2345 12 | 13 | # complex numbers 14 | complex_integer = complex(10, 20) 15 | complex_float = complex(10.0, 20.1) 16 | 17 | # binary literals 18 | x = 0b1010_1010 19 | y = 0b0101_0101 20 | print(x | y) 21 | 22 | # hex literals 23 | x = 0xAF 24 | largex = 0xABCD_EF01 25 | print(x, largex) 26 | 27 | # boolean 28 | yes = True 29 | no = False 30 | -------------------------------------------------------------------------------- /01_numbers/python/scope.py: -------------------------------------------------------------------------------- 1 | # LEGB rule: Local, Enclosing, Global, and Built-in 2 | 3 | global_variable = 1 4 | 5 | def f(): 6 | global global_variable 7 | local_variable = 2 8 | def subf(): 9 | print("local", local_variable) 10 | print("global", global_variable) 11 | enclosed_variable = 3 12 | #local_variable = 5 13 | subf() 14 | #print("enclosed", enclosed_variable) 15 | global_variable = 9 16 | local_variable = 1 17 | print("global", global_variable) 18 | print("local", local_variable) 19 | # example use of built-in scope 20 | blah = int("42") 21 | 22 | 23 | if __name__ == '__main__': 24 | f() 25 | -------------------------------------------------------------------------------- /01_numbers/python/variables.py: -------------------------------------------------------------------------------- 1 | if __name__ == '__main__': 2 | 3 | x = 1 4 | print(x) 5 | # bind x again shadows old one from above 6 | x = 'i' 7 | print(x) 8 | 9 | # declare, init 10 | something = None 11 | x = 5 12 | print("x, something", x, something) 13 | something = x * 5 14 | print("x, something", x, something) 15 | 16 | # mutability 17 | y = 0 18 | y = y * 2 + x 19 | print(y) 20 | 21 | BLAH = 42 # only const by convention 22 | y *= BLAH 23 | -------------------------------------------------------------------------------- /01_numbers/rust/cast.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let f = 1.23_f32; 3 | let i = f as u8; 4 | 5 | dbg!(i, f); 6 | 7 | let word: u16 = 128; 8 | let byte = word as i8; 9 | let ubyte = word as u8; 10 | dbg!(word, byte, ubyte); 11 | 12 | let too_big = 1000; 13 | let too_small = too_big as u8; 14 | dbg!(too_big, too_small); 15 | 16 | dbg!(unchecked(0x0fff_ffff, 0x0fff_ffff)); 17 | dbg!(checked(0x0fff_ffff, 0x0fff_ffff)); 18 | 19 | dbg!(float_eq(1.321, 1.32)); 20 | dbg!(float_eq(1.32, 1.321)); 21 | dbg!(float_eq(1.320000001, 1.32)); 22 | dbg!(1.320000001_f32 == 1.32_f32); 23 | assert_eq!(1.320000001, 1.32); 24 | } 25 | 26 | /// wraps like it would in C 27 | pub fn unchecked(x: i32, y: i32) -> i32 { 28 | x.wrapping_mul(y) 29 | } 30 | 31 | /// in debug builds this will panic! 32 | pub fn checked(x: i32, y: i32) -> i32 { 33 | x * y 34 | } 35 | 36 | /// float equality (hack! - does not handle NaN/Infinity, see https://floating-point-gui.de/errors/comparison/) 37 | pub fn float_eq(a: f32, b: f32) -> bool { 38 | (a - b).abs() <= f32::EPSILON 39 | } 40 | -------------------------------------------------------------------------------- /01_numbers/rust/numbers.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // integers 3 | let x: i32 = -1000; 4 | let x = -1000i32; 5 | let y: u64 = 100; 6 | let y = 100u64; 7 | let large_number = 100_000_000; 8 | 9 | // floats 10 | let xf: f32 = -1.2345; 11 | let xf = -1.2345_f32; 12 | 13 | // complex numbers 14 | // not part of rusts standard library 15 | let complex_integer = num::complex::Complex::new(10, 20); 16 | let complex_float = num::complex::Complex::new(10.1, 20.1); 17 | 18 | // binary literals 19 | let x: u8 = 0b1010_1010; 20 | let y: u8 = 0b0101_0101; 21 | dbg!(x | y); 22 | 23 | // hex 24 | let x: u8 = 0xAF; 25 | let largex = 0xABCD_EF01_u32; 26 | 27 | // boolean 28 | let yes = true; 29 | let no = false; 30 | } 31 | -------------------------------------------------------------------------------- /01_numbers/rust/scope.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | // scope 4 | // This binding lives in the main function 5 | let long_lived_binding = 1; 6 | 7 | // This is a block, and has a smaller scope than the main function 8 | { 9 | // This binding only exists in this block 10 | let short_lived_binding = 2; 11 | 12 | println!("inner short: {}", short_lived_binding); 13 | 14 | // This binding *shadows* the outer one 15 | let long_lived_binding = 5_f32; 16 | 17 | println!("inner long: {}", long_lived_binding); 18 | } 19 | // End of the block 20 | 21 | // Error! `short_lived_binding` doesn't exist in this scope 22 | println!("outer short: {}", short_lived_binding); 23 | 24 | println!("outer long: {}", long_lived_binding); 25 | 26 | // This binding also *shadows* the previous binding 27 | let long_lived_binding = 'a'; 28 | 29 | println!("outer long: {}", long_lived_binding); 30 | } 31 | -------------------------------------------------------------------------------- /01_numbers/rust/variables.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | let x = 1; 4 | println!("x: {}", x); 5 | // binds x again, shadowing the old one from above 6 | let x = 'i'; 7 | println!("x: {}", x); 8 | 9 | // declare, initialize 10 | let something; 11 | let x = 5; 12 | println!("x, something: {}, {}", x, something); 13 | something = x * 5; 14 | println!("x, something: {}, {}", x, something); 15 | 16 | // Mutability 17 | let y = 0; 18 | y = y * 2 + x; 19 | dbg!(y); 20 | 21 | const blah: i32 = 42; 22 | y *= blah; 23 | dbg!(y); 24 | } 25 | -------------------------------------------------------------------------------- /02_ecosystem/geo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "geo" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /02_ecosystem/geo/examples/demo.rs: -------------------------------------------------------------------------------- 1 | use geo::{Area, Circle, Perimeter, Square}; 2 | 3 | fn main() { 4 | let c = Circle { 5 | x: 0.0, 6 | y: 1.0, 7 | radius: 3.0, 8 | }; 9 | let s = Square { 10 | x: 0.0, 11 | y: 1.0, 12 | sidelen: 2.0, 13 | }; 14 | println!("The circles area is: {}", c.area()); 15 | println!("The circles perimeter is: {}", c.circumference()); 16 | println!("The squares area is: {}", s.area()); 17 | } 18 | -------------------------------------------------------------------------------- /02_ecosystem/geo/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # most amazing geometric object library ever 2 | //! This is starting off like clockwork 3 | //! - bullet 4 | //! - points 5 | 6 | /// for surface area calculation of a geometric object 7 | pub trait Area { 8 | fn area(&self) -> f64; 9 | } 10 | 11 | /// for Perimeter/circumferen calculation of a geometric object 12 | pub trait Perimeter { 13 | fn circumference(&self) -> f64; 14 | } 15 | 16 | /// Circle object, coords and radius as properties 17 | pub struct Circle { 18 | /// x-coordinate in 2D space 19 | pub x: f64, 20 | /// y-coordinate in 2D space 21 | pub y: f64, 22 | /// Radius, unit-less 23 | pub radius: f64, 24 | } 25 | 26 | /// Circle object supports area computation 27 | impl Area for Circle { 28 | /// most efficient way to compute area 29 | fn area(&self) -> f64 { 30 | std::f64::consts::PI * (self.radius.powi(2)) 31 | } 32 | } 33 | 34 | /// Circle also supports circumference 35 | impl Perimeter for Circle { 36 | /// most efficient way to compute perimeter 37 | fn circumference(&self) -> f64 { 38 | std::f64::consts::PI * 2. * self.radius 39 | } 40 | } 41 | 42 | /// Square object, coords and sidelength as properties 43 | pub struct Square { 44 | /// x-coordinate in 2D space 45 | pub x: f64, 46 | /// y-coordinate in 2D space 47 | pub y: f64, 48 | /// sidelength unit-less 49 | pub sidelen: f64, 50 | } 51 | 52 | /// Only Area supported, circumference is too hard to compute 53 | impl Area for Square { 54 | /// super amazing surface area computation 55 | /// ``` 56 | /// # use geo::Area; 57 | /// let s = geo::Square{x: 1.0, y: 3.0, sidelen: 2.0}; 58 | /// assert_eq!(s.area(), 4.); 59 | /// ``` 60 | fn area(&self) -> f64 { 61 | self.sidelen.powi(2) 62 | } 63 | } 64 | 65 | #[cfg(test)] 66 | mod tests { 67 | use crate::*; 68 | #[test] 69 | fn it_works() { 70 | let c = Circle { 71 | x: 0.0, 72 | y: 1.0, 73 | radius: 3.0, 74 | }; 75 | assert_eq!(c.area(), 28.274333882308138); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /03_tuples_arrays/python/arrays.py: -------------------------------------------------------------------------------- 1 | "demo of arrays." 2 | from array import array 3 | if __name__ == "__main__": 4 | xs = array('i', [1, 2, 3, 4, 5]) 5 | 6 | # this is dumb, use `numpy.zeros((500,), dtype=numpy.uint64)` instead 7 | ys = array('Q', [0] * 500) 8 | 9 | print("first element of the array:", xs[0]) 10 | print("second element of the array:", xs[1]) 11 | 12 | print("small size:", len(xs)) 13 | print("big size:", len(ys)) 14 | 15 | print("a section of the array as a slice", xs[1:3]) 16 | 17 | print(xs[5]) 18 | -------------------------------------------------------------------------------- /03_tuples_arrays/python/lists.py: -------------------------------------------------------------------------------- 1 | "demo of lists." 2 | if __name__ == "__main__": 3 | 4 | xs = [1, 2, 3] 5 | print("Initial list:", xs) 6 | 7 | print("Push 4 into the list") 8 | xs.append(4) 9 | print("list:", xs) 10 | 11 | print("lists length:", len(xs)) 12 | 13 | print("Second element:", xs[1]) 14 | 15 | print("Pop last element:", xs.pop()) 16 | 17 | print("Fourth element:", xs[3]) 18 | 19 | print("Contents of xs:") 20 | for x in xs: 21 | print(">", x) 22 | """ 23 | # enumerate 24 | # this 25 | for i, x in enumerate(xs): 26 | print(f"In position {i} we have value {x}") 27 | 28 | for i, x in enumerate(xs): 29 | xs[i] = x * 3 30 | # more idiomatic 31 | xs = [x * 3 for x in xs] 32 | print("Updated list:", xs) 33 | 34 | collected_iterator = [x for x in range(0, 10)] 35 | print("Collected (0..10) into:", collected_iterator) 36 | """ 37 | -------------------------------------------------------------------------------- /03_tuples_arrays/python/tuples.py: -------------------------------------------------------------------------------- 1 | "demoing tuple use." 2 | 3 | 4 | def reverse(pair: tuple) -> tuple: 5 | integer, boolean = pair 6 | return (boolean, integer) 7 | 8 | 9 | from collections import namedtuple 10 | Matrix = namedtuple('Matrix', ['x0', 'x1', 'x2', 'x3']) 11 | 12 | if __name__ == "__main__": 13 | many_types = (1, 2, 'a', True) 14 | 15 | print("first value:", many_types[0]) 16 | print("second value:", many_types[1]) 17 | 18 | tuple_of_tuples = ((1, 2, 2), (4, -1, -2)) 19 | print("tuple of tuples:", tuple_of_tuples) 20 | 21 | pair = (1, True) 22 | print("pair is ", pair) 23 | print("the reversed pair is ", reverse(pair)) 24 | 25 | print("one element tuple: {:?}", (5, )) 26 | print("just an integer: {:?}", (5)) 27 | 28 | _tuple = (1, "hello", 4.5, True) 29 | a, b, c, d = _tuple 30 | print(a, b, c, d) 31 | 32 | matrix = Matrix(1.1, 1.2, 2.1, 2.2) 33 | print(matrix) 34 | -------------------------------------------------------------------------------- /03_tuples_arrays/rust/arrays.rs: -------------------------------------------------------------------------------- 1 | /// demo of arrays 2 | 3 | fn main() { 4 | let xs = [1, 2, 3, 4, 5]; 5 | 6 | let ys: [i32; 500] = [0; 500]; 7 | let _ys = [0_u64; 500]; 8 | 9 | println!("first element of the array: {}", xs[0]); 10 | println!("second element of the array: {}", xs[1]); 11 | 12 | println!("small size: {}", xs.len()); 13 | println!("big size: {}", ys.len()); 14 | 15 | println!("borrow a section of the array as a slice {:?}", &xs[1..3]); 16 | 17 | println!("{}", xs[5]); 18 | } 19 | -------------------------------------------------------------------------------- /03_tuples_arrays/rust/tuples.rs: -------------------------------------------------------------------------------- 1 | //! demoing tuple use. 2 | 3 | fn reverse(pair: (i32, bool)) -> (bool, i32) { 4 | let (integer, boolean) = pair; 5 | 6 | (boolean, integer) 7 | } 8 | 9 | #[derive(Debug)] 10 | struct Matrix(f32, f32, f32, f32); 11 | 12 | fn main() { 13 | let many_types = (1u8, 2u16, 'a', true); 14 | 15 | println!("first value: {}", many_types.0); 16 | println!("second value: {}", many_types.1); 17 | 18 | let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16); 19 | println!("tuple of tuples: {:?}", tuple_of_tuples); 20 | 21 | let pair = (1, true); 22 | println!("pair is {:?}", pair); 23 | println!("the reversed pair is {:?}", reverse(pair)); 24 | 25 | println!("one element tuple: {:?}", (5u32,)); 26 | println!("just an integer: {:?}", (5u32)); 27 | 28 | let tuple = (1, "hello", 4.5, true); 29 | let (a, b, c, d) = tuple; 30 | println!("{:?}, {:?}, {:?}, {:?}", a, b, c, d); 31 | 32 | let matrix = Matrix(1.1, 1.2, 2.1, 2.2); 33 | println!("{:?}", matrix); 34 | } 35 | -------------------------------------------------------------------------------- /03_tuples_arrays/rust/vectors.rs: -------------------------------------------------------------------------------- 1 | //! demo of vectors 2 | 3 | fn main() { 4 | let mut xs = vec![1_i32, 2, 3]; 5 | println!("Initial vector: {:?}", xs); 6 | 7 | println!("Push 4 into the vector"); 8 | xs.push(4); 9 | println!("Vector: {:?}", xs); 10 | 11 | println!("Vector length: {}", xs.len()); 12 | 13 | println!("Second element: {}", xs[1]); 14 | 15 | println!("Pop last element: {:?}", xs.pop()); 16 | 17 | println!("Fourth element: {}", xs[3]); 18 | 19 | println!("Contents of xs:"); 20 | for x in xs { 21 | // borrow or don't use into_iter() 22 | println!("> {}", x); 23 | } 24 | 25 | /* 26 | for (i, x) in xs.iter().enumerate() { 27 | println!("In position {} we have value {}", i, x); 28 | } 29 | 30 | for x in xs.iter_mut() { 31 | *x *= 3; 32 | } 33 | let xs: Vec = xs.iter().map(|x| x * 3).collect(); 34 | println!("Updated vector: {:?}", xs); 35 | 36 | let collected_iterator: Vec = (0..10).collect(); 37 | println!("Collected (0..10) into: {:?}", collected_iterator); 38 | */ 39 | } 40 | -------------------------------------------------------------------------------- /04_strings_unicode/python/multiline.py: -------------------------------------------------------------------------------- 1 | more = """many 2 | lines 3 | whitespace 4 | """ 5 | print(more) 6 | 7 | escape = ''' blah """ escaped ' 8 | newline 9 | \n 10 | test 11 | ''' 12 | print(escape) 13 | 14 | single_char = 'ca' 15 | -------------------------------------------------------------------------------- /04_strings_unicode/python/strings.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | alice = "I like dogs" 3 | bob = alice.replace("dog", "cat") 4 | 5 | print("Alice says:", alice) 6 | print("Bob says:", bob) 7 | print("Bob says again:", bob) 8 | 9 | pangram = "the quick brown fox jumps over the lazy" 10 | print("Pangram:", pangram) 11 | 12 | print("Words in reverse") 13 | for word in reversed(pangram.split()): 14 | print(">", word) 15 | 16 | 17 | chars = [c for c in pangram] 18 | chars = sorted(set(chars)) 19 | 20 | 21 | string = "" 22 | for c in chars: 23 | string += c 24 | string += ", " 25 | 26 | 27 | chars_to_trim = ' ,' 28 | trimmed_str = string.strip(chars_to_trim) 29 | print("Used characters:", string) 30 | print("Trimmed characters:", trimmed_str) 31 | -------------------------------------------------------------------------------- /04_strings_unicode/python/uppercase.py: -------------------------------------------------------------------------------- 1 | def ascii_capitalize(name): 2 | if name: 3 | first = name[0] 4 | if first.isascii(): 5 | return first.upper() + name[1:] 6 | return name 7 | return "" 8 | 9 | 10 | names = ["alice", "bob", "özgül", "ßad"] 11 | for name in names: 12 | print(name, '->', name.capitalize()) 13 | print(name, '->', ascii_capitalize(name)) 14 | print("") 15 | -------------------------------------------------------------------------------- /04_strings_unicode/python/utf8.py: -------------------------------------------------------------------------------- 1 | import sys 2 | ascii = "Hello" 3 | mem_size = sys.getsizeof(ascii) 4 | print(f"'{ascii}': length: {len(ascii)} chars: {len(ascii)} mem_size: {mem_size}") 5 | 6 | # make bytes 7 | print(ascii.encode('utf-8')) 8 | print("after e:", ascii[2:]) 9 | 10 | # 11 | print("---") 12 | 13 | uni = "Héllö" 14 | mem_size = sys.getsizeof(uni) 15 | print(f"'{uni}': length: {len(uni)} chars: {len(uni)} mem_size: {mem_size}") 16 | 17 | # make bytes 18 | # 19 | # 20 | print(uni.encode('utf-8')) 21 | print("after e:", uni[2:]) 22 | -------------------------------------------------------------------------------- /04_strings_unicode/rust/multiline.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let more = "many 3 | lines 4 | whitespace" 5 | .to_string(); 6 | println!("{}", more); 7 | 8 | let escape = " blah \"\"\" escaped ' 9 | newline 10 | \n 11 | test 12 | " 13 | .to_string(); 14 | println!("{}", escape); 15 | 16 | let single_char = 'a'; 17 | } 18 | -------------------------------------------------------------------------------- /04_strings_unicode/rust/strings.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let alice = String::from("I like dogs"); 3 | let bob: String = alice.replace("dog", "cat"); 4 | 5 | println!("Alice says: {}", alice); 6 | println!("Bob says: {}", bob); 7 | println!("Bob says again: {}", bob); 8 | 9 | let pangram: &'static str = "the quick brown fox jumps over the lazy"; 10 | println!("Pangram: {}", pangram); 11 | 12 | println!("Words in reverse"); 13 | for word in pangram.split_whitespace().rev() { 14 | println!("> {}", word); 15 | } 16 | 17 | let mut chars: Vec = pangram.chars().collect(); 18 | chars.sort(); 19 | chars.dedup(); 20 | 21 | let mut string = String::new(); 22 | for c in chars { 23 | string.push(c); 24 | string.push_str(", "); 25 | } 26 | 27 | let chars_to_trim: &[char] = &[' ', ',']; 28 | let trimmed_str: &str = string.trim_matches(chars_to_trim); 29 | println!("Used characters: {}", string); 30 | println!("Trimmed characters: {}", trimmed_str); 31 | } 32 | -------------------------------------------------------------------------------- /04_strings_unicode/rust/uppercase.rs: -------------------------------------------------------------------------------- 1 | //! example showing uppercasing for unicode and ASCII 2 | //! 3 | fn naive_capitalize(s: &str) -> String { 4 | let mut c = s.chars(); 5 | match c.next() { 6 | None => String::new(), 7 | Some(f) => f.to_uppercase().to_string() + c.as_str(), 8 | } 9 | } 10 | 11 | fn ascii_capitalize(s: &str) -> String { 12 | let mut c = s.chars(); 13 | match c.next() { 14 | None => String::new(), 15 | Some(f) => f.to_ascii_uppercase().to_string() + c.as_str(), 16 | } 17 | } 18 | 19 | fn main() { 20 | let names: Vec = vec![ 21 | "alice".to_string(), 22 | "bob".to_string(), 23 | "özgül".to_string(), 24 | "ßad".to_string(), 25 | ]; 26 | for name in names.iter() { 27 | println!("{} -> {}", name, naive_capitalize(name)); 28 | println!("{} -> {}", name, ascii_capitalize(name)); 29 | println!(""); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /04_strings_unicode/rust/utf8.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let ascii = String::from("Hello"); 3 | println!( 4 | "'{}': length: {} chars: {} memsize: {}", 5 | ascii, 6 | ascii.len(), 7 | ascii.chars().count(), 8 | std::mem::size_of::() + ascii.len() 9 | ); 10 | println!("{:?}", ascii.as_bytes()); 11 | println!("after e: {:?}", &ascii[2..]); 12 | 13 | println!("---"); 14 | 15 | let uni = String::from("Héllö"); 16 | println!( 17 | "'{}': length: {} chars: {} memsize: {}", 18 | uni, 19 | uni.len(), 20 | uni.chars().count(), 21 | std::mem::size_of::() + uni.len() 22 | ); 23 | println!("{:?}", uni.as_bytes()); 24 | println!("after é: {:?}", &uni[2..]); 25 | } 26 | -------------------------------------------------------------------------------- /05_functions/python/closures.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | example_closure = lambda x: x 3 | 4 | s = example_closure("hello") 5 | n = example_closure(5) 6 | print(s, n) 7 | 8 | x = [1, 2, 3] 9 | 10 | equal_to_x = lambda z: z == x 11 | 12 | print("this is x", x) 13 | y = [1, 2, 3] 14 | assert equal_to_x(y) 15 | 16 | items = [1, 2, 3, 4, 5] 17 | plus_one = list(map(lambda x: x + 1, items)) 18 | sum_all = sum(map(lambda x: x + 1, items)) 19 | print(plus_one, sum_all) 20 | 21 | two_args = lambda x, y: x - y 22 | print(two_args(5, 3)) 23 | -------------------------------------------------------------------------------- /05_functions/python/fizzbuzz.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | # not possible as lambda 3 | def fizz_buzz(x): 4 | if x % 15 == 0: 5 | print("FizzBuzz") 6 | elif x % 3 == 0: 7 | print("Fizz") 8 | elif x % 5 == 0: 9 | print("Buzz") 10 | else: 11 | print(x) 12 | 13 | for i in range(1, 16): 14 | fizz_buzz(i) 15 | 16 | print("---") 17 | list(map(fizz_buzz, range(1, 16))) 18 | -------------------------------------------------------------------------------- /05_functions/python/functions.py: -------------------------------------------------------------------------------- 1 | def do_something(x): 2 | def do_some_other(x): 3 | return x * 3 4 | 5 | return do_some_other(x) 6 | 7 | 8 | if __name__ == '__main__': 9 | print(do_something(3)) 10 | -------------------------------------------------------------------------------- /05_functions/rust/closures.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let example_closure = |x| x; 3 | 4 | let s = example_closure(String::from("hello")); 5 | let n = example_closure(5); 6 | println!("{} {}", s, n); 7 | 8 | let x = vec![1, 2, 3]; 9 | 10 | let equal_to_x = move |z| z == x; 11 | 12 | println!("this is x {:?}", x); 13 | let y = vec![1, 2, 3]; 14 | assert!(equal_to_x(y)); 15 | 16 | let items: Vec = vec![1, 2, 3, 4, 5]; 17 | let plus_one: Vec<_> = items.iter().map(|x| x + 1).collect(); 18 | let sum_all: i32 = items.iter().map(|x| x + 1).sum(); 19 | println!("{:?} {}", plus_one, sum_all); 20 | 21 | let two_args = |x, y| x - y; 22 | println!("{}", two_args(5, 3)); 23 | } 24 | -------------------------------------------------------------------------------- /05_functions/rust/fizzbuzz.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let fizz_buzz = |x| { 3 | if x % 15 == 0 { 4 | println!("FizzBuzz") 5 | } else if x % 3 == 0 { 6 | println!("Fizz") 7 | } else if x % 5 == 0 { 8 | println!("Buzz") 9 | } else { 10 | println!("{}", x) 11 | } 12 | }; 13 | for i in 1..16 { 14 | fizz_buzz(i) 15 | } 16 | println!("---"); 17 | (1..16).into_iter().for_each(fizz_buzz); 18 | } 19 | -------------------------------------------------------------------------------- /05_functions/rust/functions.rs: -------------------------------------------------------------------------------- 1 | fn do_something(x: u32) -> u32 { 2 | fn do_some_other(x: u32) -> u32 { 3 | x * 3 4 | } 5 | do_some_other(x) 6 | } 7 | 8 | fn main() { 9 | println!("{}", do_something(3)); 10 | } 11 | -------------------------------------------------------------------------------- /06_pattern_matching/python/fizzbuzz.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | # not possible as lambda 3 | def if_buzz(x): 4 | if x % 15 == 0: 5 | print("FizzBuzz") 6 | elif x % 3 == 0: 7 | print("Fizz") 8 | elif x % 5 == 0: 9 | print("Buzz") 10 | else: 11 | print(x) 12 | 13 | def fizz_buzz(x): 14 | match x % 3, x % 5: 15 | case 0, 0: print("FizzBuzz"), 16 | case 0, _: print("Fizz"), 17 | case _, 0: print("Buzz"), 18 | case _, _: print("{}", x) 19 | 20 | list(map(fizz_buzz, range(1, 24))) 21 | -------------------------------------------------------------------------------- /06_pattern_matching/python/pattern_matching.py: -------------------------------------------------------------------------------- 1 | class Dog: 2 | def __init__(self, name): 3 | self.name = name 4 | 5 | class Cat: 6 | def __init__(self, age): 7 | self.age = age 8 | 9 | 10 | 11 | 12 | 13 | 14 | def classify(pet): 15 | match pet: 16 | case Cat(age=age): 17 | print("A cat that's {} years old".format(age)) 18 | case Dog: 19 | print("A dog named {}".format(pet.name)) 20 | 21 | def number(x): 22 | match x: 23 | case 1: print("one"), 24 | case 2 | 3: print("two or three"), 25 | case x if x >=4: print("four or bigger"), # range matching not yet possible 26 | case _: print("anything"), 27 | 28 | 29 | 30 | if __name__ == "__main__": 31 | for x in range(0, 6): 32 | number(x) 33 | classify(Dog("Fido")) 34 | classify(Cat(3)) 35 | -------------------------------------------------------------------------------- /06_pattern_matching/rust/fizzbuzz.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | fn if_buzz(x: i32) { 3 | if x % 15 == 0 { 4 | println!("FizzBuzz") 5 | } else if x % 3 == 0 { 6 | println!("Fizz") 7 | } else if x % 5 == 0 { 8 | println!("Buzz") 9 | } else { 10 | println!("{}", x) 11 | } 12 | } 13 | 14 | let fizz_buzz = |x| match (x % 3, x % 5) { 15 | (0, 0) => println!("FizzBuzz"), 16 | (0, _) => println!("Fizz"), 17 | (_, 0) => println!("Buzz"), 18 | (_, _) => println!("{}", x), 19 | }; 20 | 21 | (1..24).into_iter().for_each(fizz_buzz); 22 | } 23 | -------------------------------------------------------------------------------- /06_pattern_matching/rust/pattern_matching.rs: -------------------------------------------------------------------------------- 1 | struct Dog { 2 | name: String, 3 | } 4 | 5 | struct Cat { 6 | age: u8, 7 | } 8 | 9 | enum Animals { 10 | Dog(Dog), 11 | Cat(Cat), 12 | } 13 | 14 | fn classify(animal: Animals) { 15 | match animal { 16 | Animals::Cat(Cat {age}) => println!("A cat that's {} years old", age), 17 | Animals::Dog(d) => println!("A dog named {}", d.name), 18 | } 19 | } 20 | 21 | fn number(x: i32) { 22 | match x { 23 | 1 => println!("one"), 24 | 2 | 3 => println!("two or three"), 25 | 4..=i32::MAX => println!("four or bigger"), 26 | _ => println!("anything"), 27 | } 28 | } 29 | 30 | fn main() { 31 | for x in 0..6 { number(x) } 32 | classify(Animals::Dog(Dog { 33 | name: "Fido".to_string(), 34 | })); 35 | classify(Animals::Cat(Cat { age: 3 })); 36 | } 37 | -------------------------------------------------------------------------------- /07_structs/python/classes.py: -------------------------------------------------------------------------------- 1 | class A: 2 | def __init__(self, x, y): 3 | self.x = x 4 | self.y = y 5 | 6 | 7 | class B: 8 | members = [] 9 | 10 | def __init__(self, x): 11 | self.members.append(x) 12 | 13 | 14 | if __name__ == '__main__': 15 | a = A(1, 2) 16 | a.x += 2 17 | print("a.x", a.x) 18 | b1 = B(1) 19 | b2 = B(2) 20 | print(b1.members, b2.members) 21 | -------------------------------------------------------------------------------- /07_structs/python/defaults.py: -------------------------------------------------------------------------------- 1 | class D: 2 | def __init__(self, x, y, z=None): 3 | self.x = x 4 | self.y = y 5 | self.z = z if z is not None else 0 6 | 7 | def __str__(self): 8 | return f"D({self.x}, {self.y}, {self.z})" 9 | 10 | 11 | if __name__ == "__main__": 12 | d = D(1, 2) 13 | print(d) 14 | -------------------------------------------------------------------------------- /07_structs/rust/defaults.rs: -------------------------------------------------------------------------------- 1 | use std::default::Default; 2 | 3 | #[derive(Debug)] 4 | struct D { 5 | x: i32, 6 | y: i32, 7 | z: i32, 8 | } 9 | 10 | impl D { 11 | fn new(x: i32, y: i32, z: Option) -> Self { 12 | match z { 13 | Some(z) => Self { x, y, z }, 14 | None => Self { x, y, z: 0 }, 15 | } 16 | } 17 | } 18 | 19 | impl Default for D { 20 | fn default() -> Self { 21 | Self { x: 0, y: 0, z: 0 } 22 | } 23 | } 24 | 25 | fn main() { 26 | let d1 = D::new(1, 2, None); 27 | let d2 = D { 28 | x: 1, 29 | y: 2, 30 | ..D::default() 31 | }; 32 | println!("{:?}", d1); 33 | println!("{:?}", d2); 34 | } 35 | -------------------------------------------------------------------------------- /07_structs/rust/structs.rs: -------------------------------------------------------------------------------- 1 | struct A { 2 | x: i32, 3 | y: i32, 4 | } 5 | 6 | struct B { 7 | members: static Vec, 8 | } 9 | 10 | fn main() { 11 | let mut a = A { x: 1, y: 2 }; 12 | a.x += 2; 13 | let a_updated = A { y: 4, ..a }; 14 | println!("a.x {} a_updated.x {}", a.x, a_updated.x); 15 | println!("a.y {} a_updated.y {}", a.y, a_updated.y); 16 | } 17 | -------------------------------------------------------------------------------- /08_hashmaps/python/defaultdict.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | if __name__ == "__main__": 4 | d = defaultdict(list) 5 | 6 | d["banana"].append(0) 7 | print(d) 8 | 9 | # loops 10 | for k in d.keys(): 11 | print(k) 12 | 13 | for v in d.values(): 14 | print(v) 15 | # tuples as keys 16 | td = dict() 17 | td[(0, 1)] = [] 18 | print(td) 19 | -------------------------------------------------------------------------------- /08_hashmaps/python/dicts.py: -------------------------------------------------------------------------------- 1 | 2 | if __name__ == '__main__': 3 | literal = dict([("key", "value"), ("blah", "blubb")]) 4 | literal = { 5 | "key": "value", 6 | "blah": "blubb", 7 | } 8 | print(literal) 9 | 10 | # normal init 11 | mutable = dict() 12 | mutable["one"] = 1 13 | mutable["two"] = 2 14 | del (mutable["one"]) 15 | print(mutable.get("one")) 16 | print(mutable.get("two")) 17 | 18 | # add kv 19 | mutable["three"] = 3 20 | for k, v in mutable.items(): 21 | print(k, v) 22 | -------------------------------------------------------------------------------- /08_hashmaps/rust/hashmap.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; // also look at BTreeMap 2 | 3 | fn main() { 4 | let literal: HashMap<_, _> = vec![("key", "value"), ("blah", "blubb")] 5 | .into_iter() 6 | .collect(); 7 | println!("{:?}", literal); 8 | 9 | let mut mutable = HashMap::new(); 10 | mutable.insert("one", 1); 11 | mutable.insert("two", 2); 12 | mutable.remove("one"); 13 | println!("{:?}", mutable.get("one")); 14 | println!("{:?}", mutable.get("two")); 15 | 16 | mutable.insert("three", 3); 17 | for (k, v) in &mutable { 18 | println!("{}: {}", k, v); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /08_hashmaps/rust/maplit.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate maplit; 2 | 3 | let map = hashmap!{ 4 | "a" => 1, 5 | "b" => 2, 6 | }; 7 | -------------------------------------------------------------------------------- /08_hashmaps/rust/or_insert.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | fn main() { 4 | let mut d: HashMap> = HashMap::new(); 5 | 6 | d.entry("banana".to_string()) 7 | .or_insert_with(Vec::new) 8 | .push(0); 9 | println!("{:?}", d); 10 | for k in d.keys() { 11 | println!("{:?}", k); 12 | } 13 | for v in d.values() { 14 | println!("{:?}", v); 15 | } 16 | 17 | let mut td: HashMap<(i32, i32), Vec> = HashMap::new(); 18 | td.insert((0, 1), vec![]); 19 | } 20 | -------------------------------------------------------------------------------- /09_iterators/python/iterators.py: -------------------------------------------------------------------------------- 1 | class Counter: 2 | def __init__(self): 3 | self.count = 0 4 | 5 | def __iter__(self): 6 | return self 7 | 8 | def __next__(self): 9 | if self.count < 5: 10 | self.count += 1 11 | return self.count 12 | raise StopIteration 13 | 14 | 15 | if __name__ == '__main__': 16 | counter = Counter() 17 | assert next(counter) == 1 18 | assert next(counter) == 2 19 | assert next(counter) == 3 20 | assert next(counter) == 4 21 | assert next(counter) == 5 22 | try: 23 | next(counter) 24 | except StopIteration: 25 | assert True 26 | 27 | count1 = Counter() 28 | count2 = Counter() 29 | next(count2) 30 | assert sum(filter(lambda x: x % 3 == 0, map(lambda t: t[0] * t[1], zip(count1, count2)))) == 18 31 | count1 = Counter() 32 | count2 = Counter() 33 | next(count2) 34 | assert sum((x for x in (a * b for a, b in zip(count1, count2)) if x % 3 == 0)) == 18 35 | -------------------------------------------------------------------------------- /09_iterators/rust/iterators/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iterators" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /09_iterators/rust/iterators/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub struct Counter { 2 | count: u32, 3 | } 4 | 5 | impl Counter { 6 | pub fn new() -> Self { 7 | Self { count: 0 } 8 | } 9 | } 10 | 11 | impl Iterator for Counter { 12 | type Item = u32; 13 | 14 | fn next(&mut self) -> Option { 15 | if self.count < 5 { 16 | self.count += 1; 17 | Some(self.count) 18 | } else { 19 | None 20 | } 21 | } 22 | } 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | 28 | #[test] 29 | fn calling_next_directly() { 30 | let mut counter = Counter::new(); 31 | 32 | assert_eq!(counter.next(), Some(1)); 33 | assert_eq!(counter.next(), Some(2)); 34 | assert_eq!(counter.next(), Some(3)); 35 | assert_eq!(counter.next(), Some(4)); 36 | assert_eq!(counter.next(), Some(5)); 37 | assert_eq!(counter.next(), None); 38 | } 39 | 40 | #[test] 41 | fn using_other_iterator_trait_methods() { 42 | let sum: u32 = Counter::new() 43 | .zip(Counter::new().skip(1)) 44 | .map(|(a, b)| a * b) 45 | .filter(|x| x % 3 == 0) 46 | .sum(); 47 | assert_eq!(18, sum); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /0a_error_handling/python/boilerplate.py: -------------------------------------------------------------------------------- 1 | def double_first(vec): 2 | try: 3 | first = vec[0] 4 | parsed = int(first) 5 | return parsed * 2 6 | except IndexError: 7 | print("no first item") 8 | except ValueError: 9 | print("invalid first item") 10 | 11 | 12 | if __name__ == '__main__': 13 | numbers = ["42", "93", "18"] 14 | empty = [] 15 | strings = ["tofu", "93", "18"] 16 | 17 | print(double_first(numbers)) 18 | print(double_first(empty)) 19 | print(double_first(strings)) 20 | -------------------------------------------------------------------------------- /0a_error_handling/python/nohandling.py: -------------------------------------------------------------------------------- 1 | def multiply(first: str, second: str): 2 | first = int(first) 3 | second = int(second) 4 | return first * second 5 | 6 | 7 | if __name__ == '__main__': 8 | twenty = multiply("10", "2") 9 | print(f"double is {twenty}") 10 | 11 | tt = multiply("t", "2") 12 | print(f"double is {tt}") 13 | -------------------------------------------------------------------------------- /0a_error_handling/rust/boilerplate.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | use std::fmt; 3 | 4 | type Result = std::result::Result>; 5 | 6 | #[derive(Debug)] 7 | struct EmptyVec; 8 | 9 | impl fmt::Display for EmptyVec { 10 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 11 | write!(f, "invalid first item to double") 12 | } 13 | } 14 | 15 | impl error::Error for EmptyVec {} 16 | 17 | fn double_first(vec: Vec<&str>) -> Result { 18 | let first = vec.first().ok_or(EmptyVec)?; 19 | let parsed = first.parse::()?; 20 | Ok(2 * parsed) 21 | } 22 | 23 | fn print(result: Result) { 24 | match result { 25 | Ok(n) => println!("The first doubled is {}", n), 26 | Err(e) => println!("Error: {}", e), 27 | } 28 | } 29 | 30 | fn main() { 31 | let numbers = vec!["42", "93", "18"]; 32 | let empty = vec![]; 33 | let strings = vec!["tofu", "93", "18"]; 34 | 35 | print(double_first(numbers)); 36 | print(double_first(empty)); 37 | print(double_first(strings)); 38 | } 39 | -------------------------------------------------------------------------------- /0a_error_handling/rust/more_boilerplate.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | use std::num::ParseIntError; 3 | use std::fmt; 4 | 5 | type Result = std::result::Result; 6 | 7 | #[derive(Debug)] 8 | enum DoubleError { 9 | EmptyVec, 10 | // We will defer to the parse error implementation for their error. 11 | // Supplying extra info requires adding more data to the type. 12 | Parse(ParseIntError), 13 | } 14 | 15 | impl fmt::Display for DoubleError { 16 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 17 | match *self { 18 | DoubleError::EmptyVec => 19 | write!(f, "please use a vector with at least one element"), 20 | // This is a wrapper, so defer to the underlying types' implementation of `fmt`. 21 | DoubleError::Parse(ref e) => e.fmt(f), 22 | } 23 | } 24 | } 25 | 26 | impl error::Error for DoubleError { 27 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { 28 | match *self { 29 | DoubleError::EmptyVec => None, 30 | // The cause is the underlying implementation error type. Is implicitly 31 | // cast to the trait object `&error::Error`. This works because the 32 | // underlying type already implements the `Error` trait. 33 | DoubleError::Parse(ref e) => Some(e), 34 | } 35 | } 36 | } 37 | 38 | // Implement the conversion from `ParseIntError` to `DoubleError`. 39 | // This will be automatically called by `?` if a `ParseIntError` 40 | // needs to be converted into a `DoubleError`. 41 | impl From for DoubleError { 42 | fn from(err: ParseIntError) -> DoubleError { 43 | DoubleError::Parse(err) 44 | } 45 | } 46 | 47 | fn double_first(vec: Vec<&str>) -> Result { 48 | let first = vec.first().ok_or(DoubleError::EmptyVec)?; 49 | let parsed = first.parse::()?; 50 | 51 | Ok(2 * parsed) 52 | } 53 | 54 | fn print(result: Result) { 55 | match result { 56 | Ok(n) => println!("The first doubled is {}", n), 57 | Err(e) => println!("Error: {}", e), 58 | } 59 | } 60 | 61 | fn main() { 62 | let numbers = vec!["42", "93", "18"]; 63 | let empty = vec![]; 64 | let strings = vec!["tofu", "93", "18"]; 65 | 66 | print(double_first(numbers)); 67 | print(double_first(empty)); 68 | print(double_first(strings)); 69 | } 70 | 71 | -------------------------------------------------------------------------------- /0a_error_handling/rust/nohandling.rs: -------------------------------------------------------------------------------- 1 | fn multiply(first_number_str: &str, second_number_str: &str) -> i32 { 2 | let first_number = first_number_str.parse::().unwrap(); 3 | let second_number = second_number_str.parse::().unwrap(); 4 | first_number * second_number 5 | } 6 | 7 | fn main() { 8 | let twenty = multiply("10", "2"); 9 | println!("double is {}", twenty); 10 | 11 | let tt = multiply("t", "2"); 12 | println!("double is {}", tt); 13 | } 14 | -------------------------------------------------------------------------------- /0a_error_handling/rust/using_eyre/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "using_eyre" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | eyre = "0.6.1" 11 | thiserror = "1.0.21" 12 | -------------------------------------------------------------------------------- /0a_error_handling/rust/using_eyre/src/bin/thiserror.rs: -------------------------------------------------------------------------------- 1 | use eyre::Result; 2 | use thiserror::Error; 3 | 4 | #[derive(Error, Debug)] 5 | enum DoubleError { 6 | #[error("no first item")] 7 | EmptyVec, 8 | #[error("invalid first item, error: '{0}'")] 9 | Parse(#[from] std::num::ParseIntError), 10 | } 11 | 12 | fn double_first(vec: Vec<&str>) -> Result { 13 | let first = vec.first().ok_or(DoubleError::EmptyVec)?; 14 | let parsed = first.parse::().map_err(|e| DoubleError::Parse(e))?; 15 | Ok(2 * parsed) 16 | } 17 | 18 | fn print(result: Result) { 19 | match result { 20 | Ok(n) => println!("The first doubled is {}", n), 21 | Err(e) => println!("Error: {}", e), 22 | } 23 | } 24 | 25 | fn main() { 26 | let numbers = vec!["42", "93", "18"]; 27 | let empty = vec![]; 28 | let strings = vec!["tofu", "93", "18"]; 29 | 30 | print(double_first(numbers)); 31 | print(double_first(empty)); 32 | print(double_first(strings)); 33 | } 34 | -------------------------------------------------------------------------------- /0a_error_handling/rust/using_eyre/src/main.rs: -------------------------------------------------------------------------------- 1 | use eyre::{eyre, Result}; 2 | 3 | fn double_first(vec: Vec<&str>) -> Result { 4 | let first = vec.first().ok_or_else(|| eyre!("no first item"))?; 5 | let parsed = first.parse::()?; 6 | Ok(2 * parsed) 7 | } 8 | 9 | fn print(result: Result) { 10 | match result { 11 | Ok(n) => println!("The first doubled is {}", n), 12 | Err(e) => println!("Error: {}", e), 13 | } 14 | } 15 | 16 | fn main() { 17 | let numbers = vec!["42", "93", "18"]; 18 | let empty = vec![]; 19 | let strings = vec!["tofu", "93", "18"]; 20 | 21 | print(double_first(numbers)); 22 | print(double_first(empty)); 23 | print(double_first(strings)); 24 | } 25 | -------------------------------------------------------------------------------- /0b_traits/python/defaults.py: -------------------------------------------------------------------------------- 1 | class D: 2 | def __init__(self, x, y, z=None): 3 | self.x = x 4 | self.y = y 5 | self.z = z if z is not None else 0 6 | 7 | def __str__(self): 8 | return f"D({self.x}, {self.y}, {self.z})" 9 | 10 | def __add__(self, rh): 11 | return D(self.x + rh.x, self.y + rh.y, self.z + rh.z) 12 | 13 | def __eq__(self, rh): 14 | return self.x == rh.x and self.y == rh.y and self.z == rh.z 15 | 16 | 17 | if __name__ == "__main__": 18 | d1 = D(1, 2) 19 | d2 = D(1, 2, None) 20 | print(d1, d2) 21 | print(d1 + d2) 22 | assert d1 == d2 23 | -------------------------------------------------------------------------------- /0b_traits/python/iterators.py: -------------------------------------------------------------------------------- 1 | class Counter: 2 | def __init__(self): 3 | self.count = 0 4 | 5 | def __iter__(self): 6 | return self 7 | 8 | def __next__(self): 9 | if self.count < 5: 10 | self.count += 1 11 | return self.count 12 | raise StopIteration 13 | 14 | def __del__(self): 15 | print("destroyed at", self.count) 16 | 17 | 18 | if __name__ == '__main__': 19 | counter = Counter() 20 | assert next(counter) == 1 21 | assert next(counter) == 2 22 | assert next(counter) == 3 23 | assert next(counter) == 4 24 | assert next(counter) == 5 25 | try: 26 | next(counter) 27 | except StopIteration: 28 | assert True 29 | 30 | count1 = Counter() 31 | count2 = Counter() 32 | next(count2) 33 | assert sum(filter(lambda x: x % 3 == 0, map(lambda t: t[0] * t[1], zip(count1, count2)))) == 18 34 | count1 = Counter() 35 | count2 = Counter() 36 | next(count2) 37 | assert sum((x for x in (a * b for a, b in zip(count1, count2)) if x % 3 == 0)) == 18 38 | -------------------------------------------------------------------------------- /0b_traits/python/super.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | 3 | 4 | class Person: 5 | def __init__(self, name): 6 | self._name = name 7 | 8 | def name(self): 9 | return self._name 10 | 11 | 12 | class Student(Person): 13 | def __init__(self, name): 14 | super().__init__(name) 15 | 16 | def university(self): 17 | raise NotImplementedError 18 | 19 | 20 | class Programmer(metaclass=ABCMeta): 21 | @abstractmethod 22 | def fav_language(self): 23 | pass 24 | 25 | 26 | class CompSciStudent(Student): 27 | def __init__(self, name): 28 | super().__init__(name) 29 | 30 | def git_username(self): 31 | raise NotImplementedError 32 | 33 | 34 | class CollegeStudent(Student): 35 | def __init__(self, name): 36 | super().__init__(name) 37 | 38 | def university(self): 39 | return "Community College" 40 | 41 | 42 | class RustProgrammer(Person, Programmer): 43 | def fav_language(self): 44 | return "Rust" 45 | 46 | 47 | class SuperCompSciStudent(Student, Programmer): 48 | def __init__(self, name): 49 | super().__init__(name) 50 | 51 | def university(self): 52 | return "Alma Mater" 53 | 54 | def fav_language(self): 55 | return "Rust and Python" 56 | 57 | def git_username(self): 58 | return self.name().lower() 59 | 60 | 61 | def make_person(rnd): 62 | if 0 <= rnd <= 3: 63 | return StreetPerson("Bob") 64 | elif 4 <= rnd <= 6: 65 | return CollegeStudent("Bobby") 66 | elif 7 <= rnd <= 9: 67 | return RustProgrammer("Robert") 68 | else: 69 | return SuperCompSciStudent("Bert") 70 | 71 | 72 | def comp_sci_student_greeting(student): 73 | return "My name is {} and I attend {}. My favorite language is {}. My Git username is {}".format( 74 | student.name(), student.university(), student.fav_language(), student.git_username()) 75 | 76 | 77 | if __name__ == "__main__": 78 | p = make_person(10) 79 | cs = CollegeStudent("Bob") 80 | print(cs.name(), cs.university()) 81 | print(comp_sci_student_greeting(p)) 82 | -------------------------------------------------------------------------------- /0b_traits/rust/defaults.rs: -------------------------------------------------------------------------------- 1 | use std::default::Default; 2 | 3 | #[derive(Debug, PartialEq, Default)] 4 | struct D { 5 | x: i32, 6 | y: i32, 7 | z: i32, 8 | } 9 | 10 | impl D { 11 | fn new(x: i32, y: i32, z: Option) -> Self { 12 | match z { 13 | Some(z) => Self { x, y, z }, 14 | None => Self { x, y, z: 0 }, 15 | } 16 | } 17 | } 18 | 19 | impl std::ops::Add for D { 20 | type Output = D; 21 | 22 | fn add(self, other: D) -> D { 23 | D { 24 | x: self.x + other.x, 25 | y: self.y + other.y, 26 | z: self.z + other.z, 27 | } 28 | } 29 | } 30 | 31 | fn main() { 32 | let d1 = D::new(1, 2, None); 33 | let d2 = D { 34 | x: 1, 35 | y: 2, 36 | ..D::default() 37 | }; 38 | assert_eq!(d1, d2); 39 | println!("{:?} {:?}", d1, d2); 40 | println!("{:?}", d1 + d2); 41 | } 42 | -------------------------------------------------------------------------------- /0b_traits/rust/iterators/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iterators" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /0b_traits/rust/iterators/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub struct Counter { 2 | count: u32, 3 | } 4 | 5 | impl Counter { 6 | pub fn new() -> Self { 7 | Self { count: 0 } 8 | } 9 | } 10 | 11 | impl Iterator for Counter { 12 | type Item = u32; 13 | 14 | fn next(&mut self) -> Option { 15 | if self.count < 5 { 16 | self.count += 1; 17 | Some(self.count) 18 | } else { 19 | None 20 | } 21 | } 22 | } 23 | 24 | impl Drop for Counter { 25 | fn drop(&mut self) { 26 | println!("Dropping at {}", self.count); 27 | } 28 | } 29 | 30 | #[cfg(test)] 31 | mod tests { 32 | use super::*; 33 | 34 | #[test] 35 | fn calling_next_directly() { 36 | let mut counter = Counter::new(); 37 | 38 | assert_eq!(counter.next(), Some(1)); 39 | assert_eq!(counter.next(), Some(2)); 40 | assert_eq!(counter.next(), Some(3)); 41 | assert_eq!(counter.next(), Some(4)); 42 | assert_eq!(counter.next(), Some(5)); 43 | assert_eq!(counter.next(), None); 44 | } 45 | 46 | #[test] 47 | fn using_other_iterator_trait_methods() { 48 | let sum: u32 = Counter::new() 49 | .zip(Counter::new().skip(1)) 50 | .map(|(a, b)| a * b) 51 | .filter(|x| x % 3 == 0) 52 | .sum(); 53 | assert_eq!(18, sum); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /0b_traits/rust/return_trait.rs: -------------------------------------------------------------------------------- 1 | fn make_adder_function(y: i32) -> impl Fn(i32) -> i32 { 2 | let closure = move |x: i32| x + y; 3 | closure 4 | } 5 | 6 | fn main() { 7 | let plus_one = make_adder_function(1); 8 | assert_eq!(plus_one(2), 3); 9 | } 10 | -------------------------------------------------------------------------------- /0b_traits/rust/supertraits.rs: -------------------------------------------------------------------------------- 1 | trait Person { 2 | fn name(&self) -> String { 3 | String::from("Unnamed") 4 | } 5 | } 6 | 7 | trait Student: Person { 8 | fn university(&self) -> String; 9 | } 10 | 11 | trait Programmer { 12 | fn fav_language(&self) -> String; 13 | } 14 | 15 | trait CompSciStudent: Programmer + Student { 16 | fn git_username(&self) -> String; 17 | } 18 | 19 | struct StreetPerson(String); 20 | struct CollegeStudent(String); 21 | struct RustProgrammer(String); 22 | struct ArtificialProgrammer(String); 23 | struct SuperCompSciStudent(String); 24 | 25 | impl Person for StreetPerson {} 26 | 27 | impl Person for RustProgrammer {} 28 | impl Programmer for RustProgrammer { 29 | fn fav_language(&self) -> String { 30 | String::from("Rust") 31 | } 32 | } 33 | 34 | impl Programmer for ArtificialProgrammer { 35 | fn fav_language(&self) -> String { 36 | String::from("Any") 37 | } 38 | } 39 | 40 | impl Person for CollegeStudent {} 41 | impl Student for CollegeStudent { 42 | fn university(&self) -> String { 43 | String::from("Community College") 44 | } 45 | } 46 | 47 | impl Person for SuperCompSciStudent { 48 | fn name(&self) -> String { 49 | self.0.clone() 50 | } 51 | } 52 | impl Programmer for SuperCompSciStudent { 53 | fn fav_language(&self) -> String { 54 | String::from("Rust and Python") 55 | } 56 | } 57 | impl Student for SuperCompSciStudent { 58 | fn university(&self) -> String { 59 | String::from("Alma Mater") 60 | } 61 | } 62 | impl CompSciStudent for SuperCompSciStudent { 63 | fn git_username(&self) -> String { 64 | self.0.to_lowercase() 65 | } 66 | } 67 | 68 | fn comp_sci_student_greeting(student: &dyn CompSciStudent) -> String { 69 | format!( 70 | "My name is {} and I attend {}. My favorite language is {}. My Git username is {}", 71 | student.name(), 72 | student.university(), 73 | student.fav_language(), 74 | student.git_username() 75 | ) 76 | } 77 | 78 | fn comp_sci(student: &T) -> String { 79 | comp_sci_student_greeting(student) 80 | } 81 | 82 | fn comp_sci_vs_programmer(student: &T, programmer: &U) -> String 83 | where 84 | T: CompSciStudent, 85 | U: Programmer + Person, 86 | { 87 | println!( 88 | "Programmer named {} likes {}", 89 | programmer.name(), 90 | programmer.fav_language() 91 | ); 92 | comp_sci_student_greeting(student) 93 | } 94 | 95 | fn make_person(rnd: u8) -> Box { 96 | match rnd { 97 | 0..=3 => Box::new(StreetPerson("Bob".to_string())), 98 | 4..=6 => Box::new(CollegeStudent("Bobby".to_string())), 99 | 7..=9 => Box::new(RustProgrammer("Robert".to_string())), 100 | _ => Box::new(SuperCompSciStudent("Bert".to_string())), 101 | } 102 | } 103 | 104 | fn main() { 105 | let p = make_person(8); 106 | println!("{}", p.name()); 107 | let css = SuperCompSciStudent("Bert".to_string()); 108 | println!("{}", comp_sci_student_greeting(&css)); 109 | println!("{}", comp_sci(&css)); 110 | let prog = RustProgrammer("Robert".to_string()); 111 | //let prog = ArtificialProgrammer("AI".to_string()); 112 | println!("{}", comp_sci_vs_programmer(&css, &prog)); 113 | } 114 | -------------------------------------------------------------------------------- /0c_operator_overloading/rust/operator_overloading.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::fmt::Write; 3 | use std::ops; 4 | 5 | #[derive(Debug, Clone)] 6 | struct MyString(String); 7 | 8 | impl fmt::Display for MyString { 9 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 10 | write!(f, "{}", self.0) 11 | } 12 | } 13 | 14 | impl ops::Add for MyString { 15 | type Output = MyString; 16 | 17 | fn add(self, rhs: String) -> Self::Output { 18 | println!("> MyString.add({}) was called", &rhs); 19 | MyString(format!("{}{}", self.0, rhs)) 20 | } 21 | } 22 | 23 | impl ops::Add for MyString { 24 | type Output = MyString; 25 | 26 | fn add(self, rhs: i32) -> Self::Output { 27 | println!("> MyString.add({}) was called", &rhs); 28 | MyString(format!("{}{}", self.0, rhs)) 29 | } 30 | } 31 | 32 | impl ops::Add for i32 { 33 | type Output = MyString; 34 | 35 | fn add(self, rhs: MyString) -> Self::Output { 36 | println!("> i32.add({}) was called", &rhs); 37 | MyString(format!("{}{}", self, rhs)) 38 | } 39 | } 40 | 41 | impl ops::Mul for MyString { 42 | type Output = MyString; 43 | 44 | fn mul(self, rhs: i32) -> Self::Output { 45 | println!("> MyString.mul({}) was called", &rhs); 46 | let caplen: usize = if rhs <= 0 { 0 } else { rhs as usize }; 47 | let mut temp = String::with_capacity(&self.0.len() * caplen); 48 | for _ in 0..rhs { 49 | temp.write_str(&self.0).expect("writing to string failed"); 50 | } 51 | MyString(temp) 52 | } 53 | } 54 | 55 | fn main() { 56 | let ms = MyString("Foo".to_string()); 57 | println!("Foo + Bar = {}", ms + "Bar".to_string()); 58 | println!("Foo + -12 = {}", ms + -12_i32); 59 | println!("100 + Foo = {}", 100_i32 + ms.clone()); 60 | println!("Foo * -12 = {}", ms.clone() * -12_i32); 61 | println!("Foo * 12 = {}", ms.clone() * 12_i32); 62 | } 63 | -------------------------------------------------------------------------------- /0d_files/python/binary.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pathlib import Path 3 | 4 | 5 | def bytes_from_file(filename): 6 | return bytearray(Path(filename).read_bytes()) 7 | 8 | 9 | if __name__ == "__main__": 10 | filename = sys.argv[1] 11 | data = bytes_from_file(filename) 12 | print(f"data size {len(data)}bytes") 13 | 14 | user_home = Path.home() 15 | user_fonts = user_home.joinpath('Library', 'Fonts') 16 | print(f"user_home: {user_home} user_fonts: {user_fonts}") 17 | 18 | data = bytes_from_file(user_fonts) 19 | -------------------------------------------------------------------------------- /0d_files/python/simple.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | if __name__ == "__main__": 5 | 6 | 7 | with open(sys.argv[1]) as fh: 8 | count = 0 9 | 10 | 11 | for line in fh: 12 | elems = line.split(',') 13 | if elems[1] == "Tanzania": 14 | count += 1 15 | 16 | 17 | 18 | print(f"found {count} sales for Tanzania") 19 | -------------------------------------------------------------------------------- /0d_files/rust/binary/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "binary" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | dirs = "3.0.1" 11 | -------------------------------------------------------------------------------- /0d_files/rust/binary/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::path::{Path, PathBuf}; 3 | 4 | fn bytes_from_file(filename: impl AsRef) -> io::Result> { 5 | Ok(std::fs::read(filename)?) 6 | } 7 | 8 | fn main() -> io::Result<()> { 9 | let args: Vec = std::env::args().collect(); 10 | 11 | let data = bytes_from_file(&args[1])?; 12 | println!("data size {}bytes", data.len()); 13 | 14 | let user_home: PathBuf = dirs::home_dir().expect("Could not find home directory."); 15 | let user_fonts = Path::new(&user_home).join("Library").join("Fonts"); 16 | println!("user_home: {:?} user_fonts: {:?}", user_home, user_fonts); 17 | 18 | let _data = bytes_from_file(user_fonts)?; 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /0d_files/rust/bufread_iterator.rs: -------------------------------------------------------------------------------- 1 | /// Example using single Stringbuffer and iterators (needs to use Rc!) 2 | 3 | fn main() -> std::io::Result<()> { 4 | for line in my_reader::BufReader::open("Cargo.toml")? { 5 | println!("{}", line?.trim()); 6 | } 7 | 8 | Ok(()) 9 | } 10 | 11 | mod my_reader { 12 | use std::{ 13 | fs::File, 14 | io::{self, prelude::*}, 15 | rc::Rc, 16 | }; 17 | 18 | pub struct BufReader { 19 | reader: io::BufReader, 20 | buf: Rc, 21 | } 22 | 23 | fn new_buf() -> Rc { 24 | Rc::new(String::with_capacity(1024)) // Tweakable capacity 25 | } 26 | 27 | impl BufReader { 28 | pub fn open(path: impl AsRef) -> io::Result { 29 | let file = File::open(path)?; 30 | let reader = io::BufReader::new(file); 31 | let buf = new_buf(); 32 | 33 | Ok(Self { reader, buf }) 34 | } 35 | } 36 | 37 | impl Iterator for BufReader { 38 | type Item = io::Result>; 39 | 40 | fn next(&mut self) -> Option { 41 | let buf = match Rc::get_mut(&mut self.buf) { 42 | Some(buf) => { 43 | buf.clear(); 44 | buf 45 | } 46 | None => { 47 | self.buf = new_buf(); 48 | Rc::make_mut(&mut self.buf) 49 | } 50 | }; 51 | 52 | self.reader 53 | .read_line(buf) 54 | .map(|u| { 55 | if u == 0 { 56 | None 57 | } else { 58 | Some(Rc::clone(&self.buf)) 59 | } 60 | }) 61 | .transpose() 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /0d_files/rust/bufread_lines.rs: -------------------------------------------------------------------------------- 1 | /// Example using a single String Buffer vs new String for every line 2 | 3 | fn main() -> std::io::Result<()> { 4 | let mut reader = my_reader::BufReader::open("Cargo.toml")?; 5 | let mut buffer = String::new(); 6 | 7 | while let Some(line) = reader.read_line(&mut buffer) { 8 | println!("{}", line?.trim()); 9 | } 10 | 11 | Ok(()) 12 | } 13 | 14 | mod my_reader { 15 | use std::{ 16 | fs::File, 17 | io::{self, prelude::*}, 18 | }; 19 | 20 | pub struct BufReader { 21 | reader: io::BufReader, 22 | } 23 | 24 | impl BufReader { 25 | pub fn open(path: impl AsRef) -> io::Result { 26 | let file = File::open(path)?; 27 | let reader = io::BufReader::new(file); 28 | 29 | Ok(Self { reader }) 30 | } 31 | 32 | pub fn read_line<'buf>( 33 | &mut self, 34 | buffer: &'buf mut String, 35 | ) -> Option> { 36 | buffer.clear(); 37 | 38 | self.reader 39 | .read_line(buffer) 40 | .map(|u| if u == 0 { None } else { Some(buffer) }) 41 | .transpose() 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /0d_files/rust/simple.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::{self, BufRead, BufReader}; 3 | 4 | fn main() -> io::Result<()> { 5 | let args: Vec = std::env::args().collect(); 6 | 7 | let file = File::open(&args[1])?; 8 | let reader = BufReader::new(file); 9 | 10 | let mut found = 0usize; 11 | for line in reader.lines() { 12 | let line = line?; 13 | let elems: Vec<&str> = line.split(',').collect(); 14 | if elems[1] == "Tanzania" { 15 | found += 1; 16 | } 17 | } 18 | println!("found {} sales for Tanzania", found); 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /0f_debugging/rust/fizzbuzz.rs: -------------------------------------------------------------------------------- 1 | fn fizz_buzz(x: i32) -> String { 2 | match (x % 3, x % 5) { 3 | (0, 0) => "FizzBuzz".into(), 4 | (0, _) => "Fizz".into(), 5 | (_, 0) => "Buzz".into(), 6 | (_, _) => format!("{}", x), 7 | } 8 | } 9 | 10 | fn vec_fizz_buzz(n: i32) -> Vec { 11 | let mut v = Vec::new(); 12 | for i in 1..(n + 1) { 13 | v.push(dbg!(fizz_buzz(i))); 14 | } 15 | v 16 | } 17 | 18 | fn main() { 19 | println!("{:?}", vec_fizz_buzz(1)); 20 | } 21 | -------------------------------------------------------------------------------- /10_smart_pointers/python/bintree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | printed = set() 3 | 4 | def __init__(self, value): 5 | self.parent = None 6 | self.left = None 7 | self.right = None 8 | self.value = value 9 | 10 | def __repr__(self): 11 | try: 12 | if id(self) in self.printed: 13 | return f"-" 14 | self.printed.add(id(self)) 15 | spaces = " " * len(self.printed) 16 | s = f"Node\n{spaces}{spaces}parent: {self.parent}, left: {self.left}, right: {self.right}, v: {self.value}\n" 17 | return s 18 | except RecursionError: 19 | return "-" 20 | 21 | 22 | if __name__ == '__main__': 23 | root = Node(0) 24 | node = Node(1) 25 | node.parent = root 26 | root.left = node 27 | node2 = Node(2) 28 | root.parent = node2 29 | 30 | print("Root:", root) 31 | Node.printed = set() 32 | print("Parent left:", root.left.parent.value) 33 | Node.printed = set() 34 | print("ids: {} {}".format(id(node2), id(root.parent))) 35 | del node2 36 | #root.parent = None 37 | print("Parent: ", root.parent) 38 | -------------------------------------------------------------------------------- /10_smart_pointers/python/rc.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | if __name__ == "__main__": 4 | rc_examples = "Rc examples" 5 | print("refcount of rc_examples", sys.getrefcount(rc_examples)) 6 | 7 | def scope(): 8 | print("rc created") 9 | 10 | rc_a = rc_examples 11 | print("refcount of rc_a", sys.getrefcount(rc_a)) 12 | 13 | def subscope(): 14 | rc_b = rc_a 15 | print("refcount of rc_b", sys.getrefcount(rc_b)) 16 | print("refcount of rc_a", sys.getrefcount(rc_a)) 17 | print("refcount of rc_examples", sys.getrefcount(rc_examples)) 18 | 19 | subscope() 20 | print("refcount of rc_examples after del rc_b", sys.getrefcount(rc_examples)) 21 | 22 | scope() 23 | print("refcount of rc_examples after del rc_a", sys.getrefcount(rc_examples)) 24 | -------------------------------------------------------------------------------- /10_smart_pointers/rust/bintree.rs: -------------------------------------------------------------------------------- 1 | /// for illustration purposes only, do not use IRL! 2 | use std::cell::RefCell; // a "runtime borrow-checker" 3 | use std::fmt::Debug; 4 | use std::rc::{Rc, Weak}; 5 | 6 | #[derive(Debug)] 7 | struct Node { 8 | parent: Option>>>, 9 | left: Option>>>, 10 | right: Option>>>, 11 | value: T, 12 | } 13 | 14 | impl Node { 15 | fn new(value: T) -> Node { 16 | Node { 17 | parent: None, 18 | left: None, 19 | right: None, 20 | value, 21 | } 22 | } 23 | 24 | fn print_parent(&self) { 25 | if let Some(parent) = &self.parent { 26 | if let Some(parent) = parent.upgrade() { 27 | println!("Parent: {:?}", parent.borrow().value); 28 | } else { 29 | println!("Parent: no more parent"); 30 | } 31 | } else { 32 | println!("Parent: None"); 33 | } 34 | } 35 | } 36 | 37 | fn main() { 38 | let root = Rc::new(RefCell::new(Node::new(0))); 39 | let node = Rc::new(RefCell::new(Node::new(1))); 40 | node.borrow_mut().parent = Some(Rc::downgrade(&root)); 41 | 42 | let node2 = Rc::new(RefCell::new(Node::new(2))); 43 | 44 | root.borrow_mut().parent = Some(Rc::downgrade(&node2)); 45 | root.borrow_mut().left = Some(node); 46 | 47 | println!("Root: {:?}", *root.borrow()); 48 | if let Some(left) = &root.borrow().left { 49 | &left.borrow().print_parent(); 50 | }; 51 | &root.borrow().print_parent(); 52 | drop(node2); 53 | &root.borrow().print_parent(); 54 | } 55 | -------------------------------------------------------------------------------- /10_smart_pointers/rust/rc.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | fn main() { 4 | let rc_examples = "Rc examples".to_string(); 5 | // new scope 6 | { 7 | println!("--- rc_a is created ---"); 8 | 9 | let rc_a: Rc = Rc::new(rc_examples); 10 | println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a)); 11 | 12 | // one more scope 13 | { 14 | let rc_b: Rc = Rc::clone(&rc_a); 15 | println!("Ref Count of rc_b: {}", Rc::strong_count(&rc_b)); 16 | println!("Ref Count of rc_a: {}", Rc::strong_count(&rc_a)); 17 | 18 | // Two `Rc`s are equal if their inner values are equal 19 | println!("rc_a and rc_b are equal: {}", rc_a.eq(&rc_b)); 20 | 21 | // We can use methods of a value directly 22 | println!("Length of the value inside rc_a: {}", rc_a.len()); 23 | println!("Value of rc_b: {}", rc_b); 24 | } 25 | 26 | println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a)); 27 | 28 | println!("--- rc_a is dropped out of scope ---"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /10_smart_pointers/rust/smartpointers.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | use std::rc::Rc; 3 | 4 | type Result = std::result::Result>; 5 | 6 | struct List { 7 | next: Option>, 8 | value: i32, 9 | } 10 | 11 | fn main() -> Result<()> { 12 | let a = Box::new(5); 13 | println!("deref of box {:?} yields {}", a, *a); 14 | let mut l = List { 15 | next: None, 16 | value: 1, 17 | }; 18 | l.next = Some(Box::new(List { 19 | next: None, 20 | value: 2, 21 | })); 22 | println!("list value {}", l.value); 23 | 24 | let b = Rc::new(*a); 25 | let _c = Rc::clone(&b); // increase reference count (cheap) 26 | println!("{} refcount: {}", &b, Rc::strong_count(&b)); 27 | // if b is not a Rc type this is potentially deep-copying (expensive) 28 | // avoid this notation when doing refcount clones 29 | let _d = b.clone(); 30 | println!("{} refcount: {}", &b, Rc::strong_count(&b)); 31 | Ok(()) 32 | } 33 | -------------------------------------------------------------------------------- /11_multithreading/python/lock_count.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | def thread_plus(name): 4 | global data, lock 5 | with lock: 6 | for _ in range(100_000): 7 | data += 1 8 | 9 | if __name__ == "__main__": 10 | data = 0 11 | lock = threading.Lock() 12 | threads = list() 13 | for index in range(10): 14 | x = threading.Thread(target=thread_plus, args=(index,)) 15 | threads.append(x) 16 | x.start() 17 | 18 | for h in threads: 19 | h.join() 20 | print(data) 21 | -------------------------------------------------------------------------------- /11_multithreading/python/naive_count.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | def thread_plus(name): 4 | global data 5 | for _ in range(100_000): 6 | data += 1 7 | 8 | if __name__ == "__main__": 9 | data = 0 10 | threads = list() 11 | for index in range(10): 12 | x = threading.Thread(target=thread_plus, args=(index,)) 13 | threads.append(x) 14 | x.start() 15 | 16 | for h in threads: 17 | h.join() 18 | print(data) 19 | -------------------------------------------------------------------------------- /11_multithreading/rust/lock_count.rs: -------------------------------------------------------------------------------- 1 | use std::sync::{Arc, Mutex}; 2 | 3 | fn main() { 4 | let x: u32 = 0; 5 | let data = Arc::new(Mutex::new(x)); 6 | let mut handles = vec![]; 7 | 8 | for _ in 0..10 { 9 | let mydata = data.clone(); 10 | let h = std::thread::spawn(move || { 11 | let mut y = mydata.lock().unwrap(); 12 | for _ in 0..100_000 { 13 | *y += 1; 14 | } 15 | }); 16 | handles.push(h); 17 | } 18 | for h in handles { 19 | h.join().unwrap(); 20 | } 21 | println!("{}", *data.lock().unwrap()); 22 | } 23 | -------------------------------------------------------------------------------- /11_multithreading/rust/lock_object.rs: -------------------------------------------------------------------------------- 1 | use std::sync::{Arc, Mutex}; 2 | 3 | fn main() { 4 | let x = vec![0, 0]; 5 | let data = Arc::new(Mutex::new(x)); 6 | let mut handles = vec![]; 7 | 8 | for _ in 0..10 { 9 | let mydata = data.clone(); 10 | let h = std::thread::spawn(move || { 11 | let mut y = mydata.lock().unwrap(); 12 | for _ in 0..100_000 { 13 | y[0] += 1; 14 | } 15 | }); 16 | handles.push(h); 17 | } 18 | for h in handles { 19 | h.join().unwrap(); 20 | } 21 | println!("{:?}", *data.lock().unwrap()); 22 | } 23 | -------------------------------------------------------------------------------- /11_multithreading/rust/naive_count.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut data: u32 = 0; 3 | let mut handles = vec![]; 4 | 5 | for _ in 0..10 { 6 | let h = std::thread::spawn(move || { 7 | for _ in 0..100_000 { 8 | data += 1; 9 | } 10 | println!("{}", data); 11 | }); 12 | 13 | handles.push(h); 14 | } 15 | for h in handles { 16 | h.join().unwrap(); 17 | } 18 | println!("{}", data); 19 | } 20 | -------------------------------------------------------------------------------- /11_multithreading/rust/naive_object.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut data = vec![0, 0]; 3 | let mut handles = vec![]; 4 | 5 | for _ in 0..10 { 6 | let h = std::thread::spawn(move || { 7 | for _ in 0..100_000 { 8 | data[0] += 1; 9 | } 10 | println!("{:?}", data); 11 | }); 12 | 13 | handles.push(h); 14 | } 15 | for h in handles { 16 | h.join().unwrap(); 17 | } 18 | println!("{:?}", data); 19 | } 20 | -------------------------------------------------------------------------------- /12_modules/python/foo/__init__.py: -------------------------------------------------------------------------------- 1 | from .other import otherstuff 2 | 3 | 4 | def bar(): 5 | print("bar") 6 | otherstuff() 7 | -------------------------------------------------------------------------------- /12_modules/python/foo/__pycache__/__init__.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bedroombuilds/python2rust/e6589dae1ee253777b0c302bec3cc8236c39fd81/12_modules/python/foo/__pycache__/__init__.cpython-39.pyc -------------------------------------------------------------------------------- /12_modules/python/foo/__pycache__/other.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bedroombuilds/python2rust/e6589dae1ee253777b0c302bec3cc8236c39fd81/12_modules/python/foo/__pycache__/other.cpython-39.pyc -------------------------------------------------------------------------------- /12_modules/python/foo/other.py: -------------------------------------------------------------------------------- 1 | def otherstuff(): 2 | print("otherstuff") 3 | -------------------------------------------------------------------------------- /12_modules/python/main.py: -------------------------------------------------------------------------------- 1 | import foo 2 | 3 | if __name__ == "__main__": 4 | print("main") 5 | foo.bar() 6 | foo.otherstuff() 7 | -------------------------------------------------------------------------------- /12_modules/python/modules.py: -------------------------------------------------------------------------------- 1 | import sys as mysys 2 | from os import path as p, system 3 | import os 4 | 5 | # inline module not possible 6 | 7 | if __name__ == "__main__": 8 | os.path.isfile("/etc/hosts") 9 | p.isdir("/etc/hosts") 10 | system("ls") 11 | mysys.exit(1) 12 | -------------------------------------------------------------------------------- /12_modules/rust/foo.rs: -------------------------------------------------------------------------------- 1 | mod other; 2 | 3 | pub use self::other::otherstuff; 4 | pub fn bar() { 5 | dbg!("bar"); 6 | otherstuff(); 7 | } 8 | -------------------------------------------------------------------------------- /12_modules/rust/foo/other.rs: -------------------------------------------------------------------------------- 1 | pub fn otherstuff() { 2 | dbg!("otherstuff"); 3 | } 4 | -------------------------------------------------------------------------------- /12_modules/rust/main.rs: -------------------------------------------------------------------------------- 1 | mod foo; // this loads the file foo.rs 2 | 3 | fn main() { 4 | dbg!("main"); 5 | foo::bar(); 6 | foo::otherstuff(); 7 | //foo::other::otherstuff(); 8 | } 9 | -------------------------------------------------------------------------------- /12_modules/rust/modules.rs: -------------------------------------------------------------------------------- 1 | use std::io as sio; 2 | use std::rc::{Rc as RefCounted, Weak}; 3 | 4 | mod foo { 5 | pub fn bar() {} 6 | } 7 | 8 | fn main() -> sio::Result<()> { 9 | let x = RefCounted::new(std::i32::MAX); 10 | let _y: Weak = RefCounted::downgrade(&x); 11 | foo::bar(); 12 | Ok(()) 13 | } 14 | -------------------------------------------------------------------------------- /12_modules/rust/reexports.rs: -------------------------------------------------------------------------------- 1 | mod family { 2 | mod parents { 3 | pub fn call_mom() {} 4 | pub fn call_brother() {} 5 | } 6 | 7 | // re-export 8 | pub use self::parents::{call_brother, call_mom}; 9 | } 10 | 11 | fn main() { 12 | family::call_mom(); 13 | family::call_brother(); 14 | //family::parents::call_brother(); 15 | } 16 | -------------------------------------------------------------------------------- /13_async/python/minimal.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | async def a(): 4 | print('Hello ...') 5 | await asyncio.sleep(3) 6 | print("waited") 7 | return 1 8 | 9 | async def b(): 10 | print('... World!') 11 | return 2 12 | 13 | async def main(): 14 | await a() 15 | await b() 16 | print("serial\n") 17 | 18 | result = await asyncio.gather(a(), b()) 19 | print("joined\n") 20 | assert result == [1, 2] 21 | 22 | done, pending = await asyncio.wait( 23 | [asyncio.create_task(a()), asyncio.create_task(b())], return_when=asyncio.FIRST_COMPLETED) 24 | for p in pending: 25 | p.cancel() 26 | print("done {}\n".format(done.pop().result())) 27 | 28 | futures = [b(), a(), b()] 29 | result = await asyncio.gather(*futures) 30 | print("joined vector\n") 31 | 32 | if __name__ == "__main__": 33 | # Python 3.7+ 34 | asyncio.run(main()) 35 | -------------------------------------------------------------------------------- /13_async/rust/std_async/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "std_async" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | async-std = {version = "1.8.0", features = ["attributes", "unstable"] } 11 | futures = "0.3.12" 12 | -------------------------------------------------------------------------------- /13_async/rust/std_async/src/main.rs: -------------------------------------------------------------------------------- 1 | use async_std::prelude::FutureExt; 2 | use futures::future::join_all; 3 | use futures::FutureExt as BoxedExt; 4 | 5 | async fn a() -> u8 { 6 | println!("Hello ..."); 7 | async_std::task::sleep(std::time::Duration::from_secs(3)).await; 8 | println!("waited"); 9 | 1u8 10 | } 11 | 12 | async fn b() -> u8 { 13 | println!("... World!"); 14 | 2u8 15 | } 16 | 17 | #[async_std::main] 18 | async fn main() { 19 | a().await; 20 | b().await; 21 | println!("serial\n"); 22 | 23 | let result = a().join(b()).await; 24 | println!("joined\n"); 25 | assert_eq!(result, (1u8, 2u8)); 26 | 27 | let result = a().race(b()).await; // often called `select` 28 | println!("raced {:?}\n", result); 29 | 30 | // `BoxedExt::boxed()` does `Box::pin(a()) as Pin>>` for us 31 | let futures: Vec<_> = vec![b().boxed(), a().boxed(), b().boxed()]; 32 | assert_eq!(join_all(futures).await, [2, 1, 2]); 33 | println!("joined vector\n"); 34 | } 35 | -------------------------------------------------------------------------------- /14_context_manager/python/context_manager.py: -------------------------------------------------------------------------------- 1 | class FileManager(): 2 | def __init__(self, filename, mode): 3 | self.filename = filename 4 | self.mode = mode 5 | self.file = None 6 | 7 | def __enter__(self): 8 | self.file = open(self.filename, self.mode) 9 | return self.file 10 | 11 | def __exit__(self, exc_type, exc_value, exc_traceback): 12 | self.file.close() 13 | 14 | 15 | if __name__ == "__main__": 16 | with FileManager('test.txt', 'w') as f: 17 | f.write('Test') 18 | 19 | print(f.closed) 20 | -------------------------------------------------------------------------------- /14_context_manager/rust/context_manager.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::{self, Write}; 3 | 4 | struct FileManager { 5 | filename: std::path::PathBuf, 6 | mode: char, 7 | file: Option, 8 | } 9 | 10 | impl FileManager { 11 | fn new(filename: impl AsRef, mode: char) -> FileManager { 12 | FileManager { 13 | filename: filename.as_ref().to_owned(), 14 | mode, 15 | file: None, 16 | } 17 | } 18 | 19 | fn with(self: &mut Self, f: F) -> io::Result<()> 20 | where 21 | F: Fn(&mut File) -> io::Result<()>, 22 | { 23 | if self.mode == 'w' { 24 | self.file = Some(File::create(&self.filename)?); 25 | f(&mut self.file.as_mut().unwrap())?; 26 | self.file = None; 27 | } 28 | Ok(()) 29 | } 30 | 31 | fn closed(self: &Self) -> bool { 32 | self.file.is_none() 33 | } 34 | } 35 | 36 | fn main() -> io::Result<()> { 37 | let mut fm = FileManager::new("test.txt", 'w'); 38 | fm.with(|f| -> io::Result<()> { 39 | f.write(b"Test")?; 40 | Ok(()) 41 | })?; 42 | println!("{}", fm.closed()); 43 | Ok(()) 44 | } 45 | -------------------------------------------------------------------------------- /15_pymod_in_rust/python/monte_carlo_pi.py: -------------------------------------------------------------------------------- 1 | """ 2 | Silly method to compute PI using monte carlo approach 3 | """ 4 | import math 5 | import random 6 | import time 7 | import concurrent.futures 8 | import psutil 9 | import multiprocessing 10 | 11 | 12 | def monte_carlo_pi(iterations): 13 | num_cpus = psutil.cpu_count(logical=True) # real and virtual 14 | 15 | now = time.time() 16 | #total_inside = thread_monte_carlo_pi(num_cpus, iterations) 17 | total_inside = proc_monte_carlo_pi(num_cpus, iterations) 18 | 19 | stop = time.time() 20 | total_iterations = num_cpus * iterations 21 | elapsed = stop - now 22 | pi = total_inside / total_iterations * 4 23 | calculations_string = round(total_iterations / elapsed) 24 | return (pi, f'{calculations_string:,}') 25 | 26 | 27 | def monte_compute(iterations): 28 | inside = 0 29 | random.seed() 30 | for _ in range(iterations): 31 | a = random.random() 32 | b = random.random() 33 | c = math.pow(a, 2.0) + math.pow(b, 2.0) 34 | if c <= 1.0: 35 | inside += 1 36 | return inside 37 | 38 | 39 | def proc_monte_carlo_pi(num_cpus, iterations): 40 | with multiprocessing.Pool(num_cpus) as p: 41 | results = p.map(monte_compute, [iterations] * num_cpus) 42 | total_inside = sum(results) 43 | return total_inside 44 | 45 | 46 | def thread_monte_carlo_pi(num_cpus, iterations): 47 | with concurrent.futures.ThreadPoolExecutor() as executor: 48 | futures = [executor.submit(monte_compute, iterations) for _ in range(num_cpus)] 49 | total_inside = sum([f.result() for f in futures]) 50 | return total_inside 51 | 52 | 53 | if __name__ == "__main__": 54 | start = time.time() 55 | pi, calcs_p_sec = monte_carlo_pi(1_000_000) 56 | stop = time.time() 57 | print(f'{stop - start:.2f}secs runtime') 58 | print(pi) 59 | print(f"{calcs_p_sec} calculations per second") 60 | -------------------------------------------------------------------------------- /15_pymod_in_rust/rust/monte_carlo_pi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "monte_carlo_pi" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | num-format = "0.4.0" 11 | num_cpus = "1.13.0" 12 | rand = "0.8.3" 13 | -------------------------------------------------------------------------------- /15_pymod_in_rust/rust/monte_carlo_pi/examples/pi.rs: -------------------------------------------------------------------------------- 1 | use monte_carlo_pi::monte_carlo_pi; 2 | use std::time::Instant; 3 | 4 | fn main() { 5 | // Print PI and the avg. number of calculations/sec 6 | let now = Instant::now(); 7 | let (pi, calculations_string) = monte_carlo_pi(1_000_000); 8 | println!("{:.2}secs runtime", now.elapsed().as_secs_f64()); 9 | println!("{}", pi); 10 | println!("{} calculations per second", calculations_string); 11 | } 12 | -------------------------------------------------------------------------------- /15_pymod_in_rust/rust/monte_carlo_pi/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Silly method calculating PI using a Monte Carlo simulation. 2 | use num_format::{Locale, ToFormattedString}; 3 | use rand::prelude::*; 4 | use std::thread; 5 | use std::time::Instant; 6 | 7 | /// Argument takes number of iterations per thread 8 | pub fn monte_carlo_pi(iterations: u32) -> (f64, String) { 9 | let num_cpus = num_cpus::get() as u32; // real and virtual 10 | 11 | let now = Instant::now(); 12 | let mut handles = vec![]; 13 | for _ in 0..num_cpus { 14 | handles.push(thread::spawn(move || { 15 | let mut rng = thread_rng(); 16 | 17 | // Count number of random points inside unit circle 18 | // within quarter circle segment. 19 | let mut inside: u64 = 0; 20 | for _ in 0..iterations { 21 | let a = rng.gen::(); 22 | let b = rng.gen::(); 23 | let c = a.powf(2f64) + b.powf(2f64); 24 | if c <= 1f64 { 25 | inside += 1; 26 | } 27 | } 28 | 29 | inside 30 | })); 31 | } 32 | 33 | let mut total_inside: u64 = 0; 34 | for h in handles { 35 | total_inside += h.join().unwrap(); 36 | } 37 | 38 | let total_iterations = iterations as u64 * num_cpus as u64; 39 | let pi = total_inside as f64 / total_iterations as f64 * 4.0; 40 | let calculations_string = ((total_iterations as f64 / now.elapsed().as_secs_f64()) as u64) 41 | .to_formatted_string(&Locale::en); 42 | (pi, calculations_string) 43 | } 44 | -------------------------------------------------------------------------------- /15_pymod_in_rust/rust/py_monte_carlo_pi/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.x86_64-apple-darwin] 2 | rustflags = [ 3 | "-C", "link-arg=-undefined", 4 | "-C", "link-arg=dynamic_lookup", 5 | ] 6 | 7 | [target.aarch64-apple-darwin] 8 | rustflags = [ 9 | "-C", "link-arg=-undefined", 10 | "-C", "link-arg=dynamic_lookup", 11 | ] 12 | -------------------------------------------------------------------------------- /15_pymod_in_rust/rust/py_monte_carlo_pi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "py_monte_carlo_pi" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | monte_carlo_pi = {path = "../monte_carlo_pi"} 11 | 12 | [lib] 13 | name = "montecarlopi" 14 | crate-type = ["cdylib"] 15 | 16 | [dependencies.cpython] 17 | version = "0.5" 18 | features = ["extension-module"] 19 | -------------------------------------------------------------------------------- /15_pymod_in_rust/rust/py_monte_carlo_pi/src/lib.rs: -------------------------------------------------------------------------------- 1 | use cpython::{py_fn, py_module_initializer, PyResult, Python}; 2 | use monte_carlo_pi::monte_carlo_pi; 3 | 4 | py_module_initializer!(montecarlopi, |py, m| { 5 | m.add(py, "__doc__", "This module is implemented in Rust.")?; 6 | m.add( 7 | py, 8 | "sum_as_string", 9 | py_fn!(py, sum_as_string_py(a: i64, b: i64)), 10 | )?; 11 | m.add(py, "mcpi", py_fn!(py, mcpi_py(iterations: i64)))?; 12 | Ok(()) 13 | }); 14 | 15 | fn sum_as_string(a: i64, b: i64) -> String { 16 | format!("{}", a + b).to_string() 17 | } 18 | 19 | fn sum_as_string_py(_: Python, a: i64, b: i64) -> PyResult { 20 | let out = sum_as_string(a, b); 21 | Ok(out) 22 | } 23 | 24 | fn mcpi_py(_: Python, iterations: i64) -> PyResult<(f64, String)> { 25 | let out = monte_carlo_pi(iterations as u32); 26 | Ok(out) 27 | } 28 | -------------------------------------------------------------------------------- /15_pymod_in_rust/rust/pyo3_monte_carlo_pi/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.x86_64-apple-darwin] 2 | rustflags = [ 3 | "-C", "link-arg=-undefined", 4 | "-C", "link-arg=dynamic_lookup", 5 | ] 6 | 7 | [target.aarch64-apple-darwin] 8 | rustflags = [ 9 | "-C", "link-arg=-undefined", 10 | "-C", "link-arg=dynamic_lookup", 11 | ] 12 | -------------------------------------------------------------------------------- /15_pymod_in_rust/rust/pyo3_monte_carlo_pi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pyo3_monte_carlo_pi" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | [lib] 8 | name = "montecarlopi" 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | monte_carlo_pi = {path = "../monte_carlo_pi"} 13 | 14 | [dependencies.pyo3] 15 | version = "0.13.1" 16 | features = ["extension-module"] 17 | 18 | -------------------------------------------------------------------------------- /15_pymod_in_rust/rust/pyo3_monte_carlo_pi/src/lib.rs: -------------------------------------------------------------------------------- 1 | use pyo3::prelude::*; 2 | use pyo3::wrap_pyfunction; 3 | 4 | use monte_carlo_pi::monte_carlo_pi; 5 | 6 | #[pyfunction] 7 | fn mcpi(iterations: u32) -> PyResult<(f64, String)> { 8 | Ok(monte_carlo_pi(iterations as u32)) 9 | } 10 | 11 | #[pymodule] 12 | fn montecarlopi(_py: Python, m: &PyModule) -> PyResult<()> { 13 | m.add_function(wrap_pyfunction!(mcpi, m)?)?; 14 | 15 | Ok(()) 16 | } 17 | 18 | #[cfg(test)] 19 | mod tests { 20 | #[test] 21 | fn it_works() { 22 | assert_eq!(2 + 2, 4); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /16_python_inside_rust/rust/inlinepy/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "inlinepy" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | inline-python = "0.6.0" 11 | -------------------------------------------------------------------------------- /16_python_inside_rust/rust/inlinepy/rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly 2 | -------------------------------------------------------------------------------- /16_python_inside_rust/rust/inlinepy/src/main.rs: -------------------------------------------------------------------------------- 1 | use inline_python::python; 2 | 3 | fn main() { 4 | let who = "world"; 5 | let n = 5; 6 | python! { 7 | for i in range('n): 8 | print(i, "Hello", 'who) 9 | print("Goodbye") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /16_python_inside_rust/rust/py_in_rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "py_in_rust" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | 11 | [dependencies.pyo3] 12 | version = "0.13.1" 13 | features = ["auto-initialize"] 14 | -------------------------------------------------------------------------------- /16_python_inside_rust/rust/py_in_rust/src/main.rs: -------------------------------------------------------------------------------- 1 | use pyo3::prelude::*; 2 | use pyo3::types::IntoPyDict; 3 | 4 | fn main() -> Result<(), ()> { 5 | Python::with_gil(|py| { 6 | main_(py).map_err(|e| { 7 | // We can't display Python exceptions via std::fmt::Display, 8 | // so print the error here manually. 9 | e.print_and_set_sys_last_vars(py); 10 | }) 11 | }) 12 | } 13 | 14 | fn main_(py: Python) -> PyResult<()> { 15 | let sys = py.import("sys")?; 16 | let version: String = sys.get("version")?.extract()?; 17 | let locals = [("os", py.import("os")?)].into_py_dict(py); 18 | let code = "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"; 19 | let user: String = py.eval(code, None, Some(&locals))?.extract()?; 20 | println!("Hello {}, I'm Python {}", user, version); 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /17_regex/python/io_regex.py: -------------------------------------------------------------------------------- 1 | import re 2 | import sys 3 | 4 | from iso_8601 import is_8601_date 5 | RE = None 6 | 7 | 8 | def is_proper_date(line): 9 | global RE 10 | if RE is None: 11 | RE = re.compile(r"^(\d{4})-(\d{2})-(\d{2})$") 12 | return RE.match(line) 13 | 14 | 15 | if __name__ == "__main__": 16 | print("type 'quit' to quit") 17 | for line in sys.stdin: 18 | line = line.strip() 19 | 20 | if line == "quit": 21 | print("Good bye") 22 | break 23 | 24 | yn = " " if is_proper_date(line) else " not " 25 | 26 | print(f"{line} is{yn}a date") 27 | -------------------------------------------------------------------------------- /17_regex/python/iso_8601.py: -------------------------------------------------------------------------------- 1 | "Regex to check for ISO 8601 conform dates." 2 | import re 3 | 4 | 5 | def is_8601_date(line): 6 | # optionally use functools.cache 7 | RE = re.compile( 8 | r"^(?:(?=[02468][048]00|[13579][26]00|[0-9][0-9]0[48]|[0-9][0-9][2468][048]|[0-9][0-9][13579][26])\d{4}(?:(-|)(?:(?:00[1-9]|0[1-9][0-9]|[1-2][0-9][0-9]|3[0-5][0-9]|36[0-6])|(?:01|03|05|07|08|10|12)(?:\1(?:0[1-9]|[12][0-9]|3[01]))?|(?:04|06|09|11)(?:\1(?:0[1-9]|[12][0-9]|30))?|02(?:\1(?:0[1-9]|[12][0-9]))?|W(?:0[1-9]|[1-4][0-9]|5[0-3])(?:\1[1-7])?))?)$|^(?:(?![02468][048]00|[13579][26]00|[0-9][0-9]0[48]|[0-9][0-9][2468][048]|[0-9][0-9][13579][26])\d{4}(?:(-|)(?:(?:00[1-9]|0[1-9][0-9]|[1-2][0-9][0-9]|3[0-5][0-9]|36[0-5])|(?:01|03|05|07|08|10|12)(?:\2(?:0[1-9]|[12][0-9]|3[01]))?|(?:04|06|09|11)(?:\2(?:0[1-9]|[12][0-9]|30))?|(?:02)(?:\2(?:0[1-9]|1[0-9]|2[0-8]))?|W(?:0[1-9]|[1-4][0-9]|5[0-3])(?:\2[1-7])?))?)$" 9 | ) 10 | return RE.match(line) 11 | -------------------------------------------------------------------------------- /17_regex/rust/io_regex/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "io_regex" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | fancy-regex = "0.4.1" 11 | lazy_static = "1.4.0" 12 | regex = "1.4.3" 13 | -------------------------------------------------------------------------------- /17_regex/rust/io_regex/src/iso_8601.rs: -------------------------------------------------------------------------------- 1 | //! using fancy regex for ISO 8601 conform date checks 2 | use fancy_regex::Regex as FancyRegex; 3 | use lazy_static::lazy_static; 4 | 5 | /// more realistic validation, uses fancy-regex for backreferences and lookaround 6 | pub fn is_8601_date(text: &str) -> bool { 7 | lazy_static! { 8 | static ref RE: FancyRegex = FancyRegex::new(r"^(?:(?=[02468][048]00|[13579][26]00|[0-9][0-9]0[48]|[0-9][0-9][2468][048]|[0-9][0-9][13579][26])\d{4}(?:(-|)(?:(?:00[1-9]|0[1-9][0-9]|[1-2][0-9][0-9]|3[0-5][0-9]|36[0-6])|(?:01|03|05|07|08|10|12)(?:\1(?:0[1-9]|[12][0-9]|3[01]))?|(?:04|06|09|11)(?:\1(?:0[1-9]|[12][0-9]|30))?|02(?:\1(?:0[1-9]|[12][0-9]))?|W(?:0[1-9]|[1-4][0-9]|5[0-3])(?:\1[1-7])?))?)$|^(?:(?![02468][048]00|[13579][26]00|[0-9][0-9]0[48]|[0-9][0-9][2468][048]|[0-9][0-9][13579][26])\d{4}(?:(-|)(?:(?:00[1-9]|0[1-9][0-9]|[1-2][0-9][0-9]|3[0-5][0-9]|36[0-5])|(?:01|03|05|07|08|10|12)(?:\2(?:0[1-9]|[12][0-9]|3[01]))?|(?:04|06|09|11)(?:\2(?:0[1-9]|[12][0-9]|30))?|(?:02)(?:\2(?:0[1-9]|1[0-9]|2[0-8]))?|W(?:0[1-9]|[1-4][0-9]|5[0-3])(?:\2[1-7])?))?)$").unwrap(); 9 | } 10 | 11 | RE.is_match(text).unwrap() 12 | } 13 | -------------------------------------------------------------------------------- /17_regex/rust/io_regex/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use lazy_static::lazy_static; 3 | use regex::Regex; 4 | mod iso_8601; 5 | 6 | /// The recognized date format is YYYY-MM-DD. 7 | fn is_proper_date(text: &str) -> bool { 8 | lazy_static! { 9 | static ref RE: Regex = Regex::new(r"^(\d{4})-(\d{2})-(\d{2})$").unwrap(); 10 | } 11 | RE.is_match(text) 12 | } 13 | 14 | fn main() { 15 | println!("Type 'quit' to exit."); 16 | let mut input = String::new(); 17 | loop { 18 | io::stdin().read_line(&mut input).unwrap(); 19 | input.truncate(input.len() - 1); // remove trailing newline 20 | 21 | if input == "quit" { 22 | println!("Good bye"); 23 | break; 24 | } 25 | 26 | let is_date = is_proper_date(&input); 27 | //let is_date = iso_8601::is_8601_date(&input); 28 | println!( 29 | "{0} is{1}a date", 30 | input, 31 | if is_date { " " } else { " not " } 32 | ); 33 | input.clear(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /18_argparse/python/argp.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from enum import Enum 3 | 4 | 5 | class Categories(Enum): 6 | Science = 28 7 | People = 22 8 | Comedy = 23 9 | 10 | 11 | VALID_CATEGORIES = [c.name for c in Categories] 12 | 13 | if __name__ == '__main__': 14 | parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) 15 | parser.add_argument('--file', required=True, help='Video file to upload') 16 | parser.add_argument('--title', help='Video title') 17 | parser.add_argument('--category', 18 | choices=VALID_CATEGORIES, 19 | default='Science', 20 | help='video category.') 21 | parser.add_argument('--verbose', action='store_true', help='show more output') 22 | parser.add_argument('-n', 23 | '--name', 24 | dest='names', 25 | action='append', 26 | help="provides names to greet") 27 | args = parser.parse_args() 28 | 29 | args.category = Categories.__getitem__(args.category) 30 | print(args) 31 | -------------------------------------------------------------------------------- /18_argparse/rust/argp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "argp" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | structopt = "0.3.21" 11 | strum = "0.20" 12 | strum_macros = "0.20" 13 | -------------------------------------------------------------------------------- /18_argparse/rust/argp/src/main.rs: -------------------------------------------------------------------------------- 1 | use structopt::StructOpt; 2 | use strum::VariantNames; 3 | use strum_macros::{EnumString, EnumVariantNames}; 4 | 5 | #[derive(Debug, EnumString, EnumVariantNames)] 6 | #[strum(serialize_all = "kebab_case")] 7 | enum Categories { 8 | Science = 28, 9 | People = 22, 10 | Comedy = 23, 11 | } 12 | 13 | #[derive(Debug, StructOpt)] 14 | #[structopt(name = "argparse example", about = "usage example")] 15 | struct Options { 16 | /// filename of video to upload 17 | #[structopt(short, long)] 18 | file: std::path::PathBuf, 19 | /// title if none given created from filename 20 | #[structopt(short, long)] 21 | title: Option, 22 | /// Video Category 23 | #[structopt(long, default_value="science", possible_values = &Categories::VARIANTS)] 24 | category: Categories, 25 | /// show more output 26 | #[structopt(short, long)] 27 | verbose: bool, 28 | /// provides names to greet 29 | #[structopt(short = "n", long = "name")] 30 | names: Vec, 31 | } 32 | 33 | fn main() { 34 | let options = Options::from_args(); 35 | println!("{:?}", options); 36 | } 37 | -------------------------------------------------------------------------------- /19_numpy/python/eigenvector.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | 3 | if __name__ == "__main__": 4 | a = numpy.matrix([[2.0, 1.0, 2.0], [-2.0, 2.0, 1.0], [1.0, 2.0, -2.0]]) 5 | e, vecs = numpy.linalg.eig(a) 6 | print("eigenvalues =", e) 7 | print("V =", vecs) 8 | a_c = a.astype(complex) 9 | av = a_c.dot(vecs) 10 | print("AV =", av) 11 | -------------------------------------------------------------------------------- /19_numpy/python/simple.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | if __name__ == '__main__': 4 | a = np.array([0, 30, 45, 60, 90]) 5 | 6 | print('angles ', a) 7 | print('sine(a)', np.sin(a * np.pi / 180)) 8 | 9 | a = np.arange(9, dtype=np.float_).reshape(3, 3) 10 | b = np.array([10, 10, 10]) 11 | 12 | print("a: ", a) 13 | print("b: ", b) 14 | print("a * 2", a * 2) 15 | print("a + b", a + b) 16 | print("a * b", a * b) 17 | print("average(a)", np.average(a)) 18 | print("mean(b)", np.mean(b)) 19 | -------------------------------------------------------------------------------- /19_numpy/rust/simple/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simple" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | ndarray = "0.14.0" 11 | ndarray-linalg = { version="0.13.0", features = ["intel-mkl-system"] } 12 | -------------------------------------------------------------------------------- /19_numpy/rust/simple/README.md: -------------------------------------------------------------------------------- 1 | # Intel MKL for Rust 2 | 3 | 4 | ## Build instructions on macOS 5 | 6 | ```bash 7 | # workaround for searchpath of mkl-src 8 | sudo mkdir -p /opt/intel/mkl/lib/ 9 | sudo ln -s /opt/intel/oneapi/mkl/latest/lib /opt/intel/mkl/lib/intel64 10 | 11 | export PKG_CONFIG_PATH=/opt/intel/oneapi/mkl/latest/bin/pkgconfig/ 12 | export MKLROOT=/opt/intel/oneapi/mkl/latest/ 13 | export PKG_CONFIG_MKL_DYNAMIC_LP64_IOMP_MKLROOT=/opt/intel/oneapi/mkl/latest/ 14 | # verify it is found 15 | pkg-config --libs mkl-dynamic-lp64-iomp 16 | 17 | # to run the binary 18 | export DYLD_LIBRARY_PATH=/opt/intel/oneapi/mkl/latest/lib/ 19 | ``` 20 | -------------------------------------------------------------------------------- /19_numpy/rust/simple/examples/eigenvector.rs: -------------------------------------------------------------------------------- 1 | use ndarray::*; 2 | use ndarray_linalg::*; 3 | 4 | fn main() { 5 | let a = arr2(&[[2.0, 1.0, 2.0], [-2.0, 2.0, 1.0], [1.0, 2.0, -2.0]]); 6 | let (e, vecs) = a.eig().unwrap(); 7 | println!("eigenvalues = \n{:?}", e); 8 | println!("V = \n{:?}", vecs); 9 | let a_c: Array2 = a.map(|f| c64::new(*f, 0.0)); 10 | let av = a_c.dot(&vecs); 11 | println!("AV = \n{:?}", av); 12 | } 13 | -------------------------------------------------------------------------------- /19_numpy/rust/simple/src/main.rs: -------------------------------------------------------------------------------- 1 | use ndarray::prelude::*; 2 | use std::f64::consts::PI; 3 | 4 | fn main() -> Result<(), ndarray::ShapeError> { 5 | let a: Array1 = array![0., 30., 45., 60., 90.]; 6 | 7 | println!("angles {}", a); 8 | println!("sine(a) {}", (a * PI / 180_f64).map(|x| x.sin())); 9 | 10 | let a = Array::from_shape_vec((3, 3), Array1::range(0., 9., 1.).to_vec())?; 11 | let b = array![10., 10., 10.]; 12 | 13 | println!("a: {}", &a); 14 | println!("b: {}", &b); 15 | println!("a * 2 {}", &a * 2.); 16 | println!("a + b {}", &a + &b); // & makes an ArrayView, avoiding move 17 | println!("a * b {}", &a * &b); 18 | println!("average(a) {}", a.sum() / a.len() as f64); 19 | println!("mean(b) {}", b.mean().unwrap()); 20 | Ok(()) 21 | } 22 | -------------------------------------------------------------------------------- /1a_logging/python/foo/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from . import bar 4 | 5 | log = logging.getLogger(__name__) 6 | 7 | 8 | def run(): 9 | log.warn("warn") 10 | log.info("info") 11 | log.debug("debug") 12 | bar.run() 13 | -------------------------------------------------------------------------------- /1a_logging/python/foo/bar.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | log = logging.getLogger(__name__) 4 | 5 | 6 | def run(): 7 | log.warn("warn") 8 | log.info("info") 9 | log.debug("debug") 10 | -------------------------------------------------------------------------------- /1a_logging/python/log.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import logging.config 3 | import yaml 4 | 5 | import foo 6 | 7 | if __name__ == "__main__": 8 | with open('logconf.yaml', 'r') as f: 9 | log_cfg = yaml.safe_load(f.read()) 10 | logging.config.dictConfig(log_cfg) 11 | logging.warning('warn') 12 | logging.error("error") 13 | logging.info('info') 14 | logging.debug("debug") 15 | foo.run() 16 | -------------------------------------------------------------------------------- /1a_logging/python/logconf.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | formatters: 4 | simple: 5 | format: "%(asctime)s [%(levelname)s] [%(name)s] - %(message)s" 6 | datefmt: "%Y-%m-%dT%H:%M:%S" 7 | extended: 8 | format: "%(asctime)s [%(levelname)s] [%(name)s:%(lineno)s] - %(message)s" 9 | datefmt: "%Y-%m-%dT%H:%M:%S" 10 | 11 | handlers: 12 | console: 13 | class: logging.StreamHandler 14 | level: DEBUG 15 | formatter: simple 16 | 17 | file_handler: 18 | class: logging.FileHandler 19 | level: DEBUG 20 | filename: test.log 21 | formatter: extended 22 | 23 | loggers: 24 | foo: 25 | level: INFO 26 | handlers: [console] 27 | propagate: no 28 | foo.bar: 29 | level: DEBUG 30 | handlers: [console, file_handler] 31 | propagate: no 32 | root: 33 | level: INFO 34 | handlers: [console] 35 | -------------------------------------------------------------------------------- /1a_logging/rust/logex/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "logex" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | chrono = "0.4.19" 11 | env_logger = "0.8.3" 12 | log = "0.4.14" 13 | -------------------------------------------------------------------------------- /1a_logging/rust/logex/src/main.rs: -------------------------------------------------------------------------------- 1 | use chrono::Local; 2 | use env_logger::Builder; 3 | use log::LevelFilter; 4 | use std::io::Write; 5 | 6 | mod foo { 7 | mod bar { 8 | pub fn run() { 9 | log::warn!("warn"); 10 | log::info!("info"); 11 | log::debug!("debug"); 12 | } 13 | } 14 | 15 | pub fn run() { 16 | log::warn!("warn"); 17 | log::info!("info"); 18 | log::debug!("debug"); 19 | bar::run(); 20 | } 21 | } 22 | 23 | fn main() { 24 | Builder::new() 25 | .format(|buf, record| { 26 | writeln!( 27 | buf, 28 | "{} [{}] [{}] - {}", 29 | Local::now().format("%Y-%m-%dT%H:%M:%S"), 30 | record.level(), 31 | record.module_path().unwrap_or("-"), 32 | record.args() 33 | ) 34 | }) 35 | // run with LOGEX_LOG="warn,logex::foo=info,logex::foo::bar=debug" 36 | .parse_env("LOGEX_LOG") 37 | // filter_level wins over environment 38 | .filter_level(LevelFilter::Info) 39 | .init(); 40 | 41 | log::warn!("warn"); 42 | log::error!("error"); 43 | log::info!("info"); 44 | log::debug!("debug"); 45 | foo::run(); 46 | } 47 | -------------------------------------------------------------------------------- /1b_sockets/python/echoclient.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | HOST = "127.0.0.1" 4 | PORT = 65432 5 | 6 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 7 | s.connect((HOST, PORT)) 8 | s.sendall(b"Hello, world") 9 | data = s.recv(1024) 10 | 11 | print("Received", repr(data)) 12 | -------------------------------------------------------------------------------- /1b_sockets/python/echoserver.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | HOST = "127.0.0.1" 4 | PORT = 65432 5 | 6 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 7 | s.bind((HOST, PORT)) 8 | s.listen() 9 | conn, addr = s.accept() 10 | with conn: 11 | print("Connected by", addr) 12 | while True: 13 | data = conn.recv(1024) 14 | if not data: 15 | break 16 | conn.sendall(data) 17 | -------------------------------------------------------------------------------- /1b_sockets/python/tlsechoclient.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | 4 | HOST = "127.0.0.1" 5 | HOSTNAME = 'michael.kefeder.at' 6 | PORT = 65432 7 | context = ssl.create_default_context() 8 | 9 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 10 | with context.wrap_socket(s, server_hostname=HOSTNAME) as ssock: 11 | print(ssock.version()) 12 | ssock.connect((HOST, PORT)) 13 | ssock.sendall(b"Hello, world") 14 | data = ssock.recv(1024) 15 | 16 | print("Received", repr(data)) 17 | -------------------------------------------------------------------------------- /1b_sockets/python/tlsechoserver.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import ssl 3 | 4 | context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) 5 | context.load_cert_chain('../certchain.pem', '../private.key') 6 | 7 | HOST = "127.0.0.1" 8 | PORT = 65432 9 | 10 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 11 | s.bind((HOST, PORT)) 12 | s.listen() 13 | with context.wrap_socket(s, server_side=True) as ssock: 14 | conn, addr = ssock.accept() 15 | with conn: 16 | print("Connected by", addr) 17 | while True: 18 | data = conn.recv(1024) 19 | if not data: 20 | break 21 | conn.sendall(data) 22 | -------------------------------------------------------------------------------- /1b_sockets/rust/echoclient.rs: -------------------------------------------------------------------------------- 1 | use std::io::prelude::*; 2 | use std::io::BufReader; 3 | use std::net::TcpStream; 4 | 5 | fn main() { 6 | let mut stream = TcpStream::connect("127.0.0.1:12321").unwrap(); 7 | 8 | let len = stream.write(b"hello socket world\n"); 9 | println!("written {:?}", len); 10 | let mut reader = BufReader::new(stream); 11 | let mut line = String::new(); 12 | let len = reader.read_line(&mut line); 13 | println!("{:?} {:?}", &line, len); 14 | } 15 | -------------------------------------------------------------------------------- /1b_sockets/rust/echoserver.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufRead, BufReader, Write}; 2 | use std::net::{TcpListener, TcpStream}; 3 | use std::thread; 4 | 5 | fn main() { 6 | let listener = TcpListener::bind("127.0.0.1:12321").unwrap(); 7 | for stream in listener.incoming() { 8 | let stream = stream.unwrap(); 9 | thread::spawn(move || handle_client(stream)); 10 | } 11 | } 12 | 13 | fn handle_client(stream: TcpStream) { 14 | let mut stream = BufReader::new(stream); 15 | loop { 16 | let mut buf = String::new(); 17 | if stream.read_line(&mut buf).is_err() { 18 | break; 19 | } 20 | stream.get_ref().write(buf.as_bytes()).unwrap(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /1b_sockets/rust/tlsecho/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tlsecho" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | rustls = "0.19.0" 10 | webpki = "0.21.4" 11 | webpki-roots = "0.21.0" 12 | -------------------------------------------------------------------------------- /1b_sockets/rust/tlsecho/src/bin/rawserver.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | use std::io::{BufRead, BufReader, Read, Write}; 3 | use std::net::{TcpListener, TcpStream}; 4 | use std::sync::Arc; 5 | use std::thread; 6 | 7 | fn open_cert_file(file: &str, method: F) -> Vec 8 | where 9 | F: Fn(&mut dyn BufRead) -> Result, ()>, 10 | { 11 | let certfile = fs::File::open(file).unwrap(); 12 | let mut reader = BufReader::new(certfile); 13 | method(&mut reader).unwrap() 14 | } 15 | 16 | fn main() { 17 | let mut config = rustls::ServerConfig::new(rustls::NoClientAuth::new()); 18 | let certs = open_cert_file("../../certchain.pem", rustls::internal::pemfile::certs); 19 | let key = open_cert_file( 20 | "../../private.key", 21 | rustls::internal::pemfile::pkcs8_private_keys, 22 | ) 23 | .pop() 24 | .unwrap(); 25 | let listener = TcpListener::bind("127.0.0.1:12321").unwrap(); 26 | config.set_single_cert(certs, key).unwrap(); 27 | println!("server is running on 127.0.0.1:12321 ..."); 28 | 29 | for socket in listener.incoming() { 30 | let socket = socket.unwrap(); 31 | let config = config.clone(); 32 | thread::spawn(move || handle_client(socket, Arc::new(config))); 33 | } 34 | } 35 | 36 | fn handle_client(mut socket: TcpStream, config: Arc) { 37 | let mut sess = rustls::ServerSession::new(&config); 38 | let mut stream = rustls::Stream::new(&mut sess, &mut socket); 39 | loop { 40 | let mut buf = [0u8; 1024]; 41 | let bytes = stream.read(&mut buf).unwrap(); 42 | if bytes == 0 { 43 | continue; 44 | } 45 | println!("{:?}", &buf[..bytes]); 46 | let written = stream.write(&buf[..bytes]).unwrap(); 47 | println!("{:?}", &written); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /1b_sockets/rust/tlsecho/src/bin/server.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | use std::io::{BufRead, BufReader, Read, Write}; 3 | use std::net::{TcpListener, TcpStream}; 4 | use std::sync::Arc; 5 | use std::thread; 6 | 7 | fn open_cert_file(file: &str, method: F) -> Vec 8 | where 9 | F: Fn(&mut dyn BufRead) -> Result, ()>, 10 | { 11 | let certfile = fs::File::open(file).unwrap(); 12 | let mut reader = BufReader::new(certfile); 13 | method(&mut reader).unwrap() 14 | } 15 | 16 | fn main() { 17 | let mut config = rustls::ServerConfig::new(rustls::NoClientAuth::new()); 18 | let certs = open_cert_file("../../certchain.pem", rustls::internal::pemfile::certs); 19 | let key = open_cert_file( 20 | "../../private.key", 21 | rustls::internal::pemfile::pkcs8_private_keys, 22 | ) 23 | .pop() 24 | .unwrap(); 25 | let listener = TcpListener::bind("127.0.0.1:12321").unwrap(); 26 | config.set_single_cert(certs, key).unwrap(); 27 | println!("server is running on 127.0.0.1:12321 ..."); 28 | 29 | for socket in listener.incoming() { 30 | let socket = socket.unwrap(); 31 | let config = config.clone(); 32 | thread::spawn(move || handle_client(socket, Arc::new(config))); 33 | } 34 | } 35 | 36 | fn handle_client(mut socket: TcpStream, config: Arc) { 37 | let mut sess = rustls::ServerSession::new(&config); 38 | let stream = rustls::Stream::new(&mut sess, &mut socket); 39 | let mut reader = BufReader::new(stream); 40 | loop { 41 | let mut buf = String::new(); 42 | if reader.read_line(&mut buf).is_err() { 43 | break; 44 | } 45 | if !buf.is_empty() { 46 | reader.get_mut().write_all(buf.as_bytes()).unwrap(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /1b_sockets/rust/tlsecho/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use std::io::{stdout, Read, Write}; 4 | use std::net::TcpStream; 5 | 6 | use rustls; 7 | use webpki; 8 | use webpki_roots; 9 | 10 | use rustls::Session; 11 | 12 | fn main() { 13 | let hostname = "michael.kefeder.at"; 14 | let host = "127.0.0.1:12321"; 15 | let mut config = rustls::ClientConfig::new(); 16 | config 17 | .root_store 18 | .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); 19 | 20 | let dns_name = webpki::DNSNameRef::try_from_ascii_str(hostname).unwrap(); 21 | let mut sess = rustls::ClientSession::new(&Arc::new(config), dns_name); 22 | let mut sock = TcpStream::connect(host).unwrap(); 23 | let mut tls = rustls::Stream::new(&mut sess, &mut sock); 24 | tls.write_all(b"Hello bob\n").unwrap(); 25 | let ciphersuite = tls.sess.get_negotiated_ciphersuite().unwrap(); 26 | writeln!( 27 | &mut std::io::stderr(), 28 | "Current ciphersuite: {:?}", 29 | ciphersuite.suite 30 | ) 31 | .unwrap(); 32 | let mut plaintext = [0u8; 1024]; 33 | let num_bytes = tls.read(&mut plaintext).unwrap(); 34 | if num_bytes > 0 { 35 | stdout().write_all(&plaintext).unwrap(); 36 | } 37 | println!("{:?}", num_bytes); 38 | } 39 | -------------------------------------------------------------------------------- /1c_xml/cd-list.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | My (reduced) Hard Bop list 4 | 5 | John Coltrane 6 | Blue Train 7 | Jazz 8 | 9 | From Wikipedia: 10 |

The album was recorded in the midst of Coltrane's residency at the 11 | Five Spot as a member of the Thelonious Monk quartet. The personnel...

12 |
13 | 14 | 15 | Blue Train 16 | John coltrane 17 | Blues 18 | 19 | 20 | Moment's Notice 21 | John coltrane 22 | Hard Bop 23 | 24 | 25 |
26 | 27 | Art Blakey 28 | Moanin' 29 | 30 |
31 | -------------------------------------------------------------------------------- /1c_xml/python/elemtree.py: -------------------------------------------------------------------------------- 1 | import xml.etree.ElementTree as ET 2 | 3 | if __name__ == "__main__": 4 | tree = ET.parse('../cd-list.xml') 5 | root = tree.getroot() 6 | 7 | for child in root: 8 | print('childnode', child) 9 | 10 | for title in root.iter('title'): 11 | print('title', title.text) 12 | 13 | for track in root.iter('track'): 14 | print('track-no', track.attrib['no']) 15 | 16 | newcd = ET.SubElement(root, 'cd') 17 | artist = ET.SubElement(newcd, 'artist') 18 | artist.text = "Bob" 19 | title = ET.SubElement(newcd, 'title') 20 | title.text = "Song for Alice" 21 | ET.dump(root) 22 | -------------------------------------------------------------------------------- /1c_xml/python/minidom.py: -------------------------------------------------------------------------------- 1 | import xml.dom.minidom as md 2 | import io 3 | 4 | if __name__ == "__main__": 5 | dom = md.parse('../cd-list.xml') 6 | for child in dom.childNodes[0].childNodes: 7 | print('childnode', child) 8 | 9 | for title in dom.getElementsByTagName('title'): 10 | print('title', title.firstChild.nodeValue) 11 | 12 | for track in dom.getElementsByTagName('track'): 13 | print('track-no', track.getAttribute('no')) 14 | 15 | root = dom.childNodes[0] 16 | newcd = dom.createElement('cd') 17 | artist = dom.createElement('artist') 18 | artist.appendChild(dom.createTextNode('Bob')) 19 | artist.setAttribute('country', 'DE') 20 | newcd.appendChild(artist) 21 | title = dom.createElement('title') 22 | title.appendChild(dom.createTextNode('Song for Alice')) 23 | newcd.appendChild(title) 24 | root.appendChild(newcd) 25 | fd = io.StringIO() 26 | dom.writexml(fd) 27 | print(fd.getvalue()) 28 | -------------------------------------------------------------------------------- /1c_xml/rust/xml/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xml" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | minidom = "0.13.0" 10 | xmltree = "0.10.2" 11 | -------------------------------------------------------------------------------- /1c_xml/rust/xml/src/bin/minidom.rs: -------------------------------------------------------------------------------- 1 | use minidom::Element; 2 | 3 | const NS: &str = ""; 4 | fn main() -> Result<(), Box> { 5 | println!("minidom"); 6 | let data = std::fs::read_to_string("../../cd-list.xml")?; 7 | let mut root: Element = data.parse().unwrap(); 8 | 9 | for child in root.children() { 10 | println!("{:?}", child); 11 | } 12 | 13 | for child in root.children().filter(|e| e.is("title", NS)) { 14 | println!("title {:?}", child.text()); 15 | } 16 | for child in root.children().filter(|e| e.is("cd", NS)) { 17 | for tl in child.children().filter(|e| e.is("track-list", NS)) { 18 | for track in tl.children().filter(|e| e.is("track", NS)) { 19 | println!("track {:?}", track.attr("no")); 20 | } 21 | } 22 | } 23 | 24 | let newcd = Element::builder("cd", "") 25 | .append( 26 | Element::builder("artist", "") 27 | .append("bob") 28 | .attr("country", "DE"), 29 | ) 30 | .append(Element::builder("title", "").append("Song for Alice")) 31 | .build(); 32 | root.append_child(newcd); 33 | let mut buf = Vec::::new(); 34 | root.write_to(&mut buf).unwrap(); 35 | println!("{}", String::from_utf8(buf).unwrap()); 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /1c_xml/rust/xml/src/main.rs: -------------------------------------------------------------------------------- 1 | use xmltree::{Element, XMLNode}; 2 | 3 | fn main() -> Result<(), Box> { 4 | println!("Hello, world!"); 5 | let data = std::fs::read_to_string("../../cd-list.xml")?; 6 | let mut root = Element::parse(data.as_bytes()).unwrap(); 7 | for child in &root.children { 8 | println!("child {:?}", child); 9 | } 10 | let titles = &root.get_child("title").unwrap(); 11 | for title in &titles.children { 12 | println!("title {:?}", title.as_text()); 13 | println!("title {:?}", &titles.get_text()); 14 | } 15 | let cd = &root.get_child("cd").unwrap(); 16 | let track_list = cd.get_child("track-list").unwrap(); 17 | let track = track_list.get_child("track").unwrap(); 18 | println!("track-no {:?}", track.attributes["no"]); 19 | 20 | let mut newcd = Element::new("cd"); 21 | let mut artist = Element::new("artist"); 22 | artist.children.push(XMLNode::Text("Bob".to_owned())); 23 | artist 24 | .attributes 25 | .insert("country".to_owned(), "DE".to_owned()); 26 | let mut title = Element::new("title"); 27 | title 28 | .children 29 | .push(XMLNode::Text("Song for Alice".to_owned())); 30 | newcd.children.push(XMLNode::Element(title)); 31 | root.children.push(XMLNode::Element(newcd)); 32 | let mut buf = Vec::::new(); 33 | root.write(&mut buf).unwrap(); 34 | println!("{}", String::from_utf8(buf).unwrap()); 35 | Ok(()) 36 | } 37 | -------------------------------------------------------------------------------- /1d_json/python/minimal.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | if __name__ == "__main__": 4 | o_json = '["foo", {"bar": ["baz", null, 1.0, 2]}]'; 5 | o = json.loads(o_json) 6 | print(o) 7 | 8 | s = json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}]) 9 | print(s) 10 | 11 | o = json.loads(s) 12 | print(o) 13 | -------------------------------------------------------------------------------- /1d_json/python/person.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | class Person: 5 | def __init__(self, name, age, job, verified, parents): 6 | self.name = name 7 | self.age = age 8 | self.job = job 9 | self.verified = verified 10 | self.parents = parents 11 | 12 | def __str__(self): 13 | return ", ".join([f"{k}: {v}" for k, v in self.__dict__.items()]) 14 | 15 | 16 | class MyEncoder(json.JSONEncoder): 17 | def default(self, o): 18 | return o.__dict__ 19 | 20 | 21 | class MyDecoder(json.JSONDecoder): 22 | def decode(self, s): 23 | d = json.JSONDecoder.decode(self, s) 24 | return Person(**d) 25 | 26 | 27 | if __name__ == '__main__': 28 | bob = Person(name="Bob", age=12, job=None, verified=True, 29 | parents=["Alice", "Carl"]) 30 | bob_json = json.dumps(bob, cls=MyEncoder) 31 | print(bob_json) 32 | bob = json.loads(bob_json, cls=MyDecoder) 33 | print(bob) 34 | -------------------------------------------------------------------------------- /1d_json/rust/json/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "json" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | serde = { version = "1", features = ["derive"] } 10 | serde_json = "1" 11 | -------------------------------------------------------------------------------- /1d_json/rust/json/rust-toolchain: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly" 3 | -------------------------------------------------------------------------------- /1d_json/rust/json/src/bin/person.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Deserialize, Serialize)] 4 | struct Person { 5 | name: String, 6 | age: usize, 7 | job: Option, 8 | verified: bool, 9 | parents: Vec, 10 | } 11 | 12 | fn main() { 13 | let bob = Person { 14 | name: "Bob".to_string(), 15 | age: 12, 16 | verified: true, 17 | job: None, 18 | parents: ["Alice".to_string(), "Carl".to_string()].to_vec(), 19 | }; 20 | let json = serde_json::to_string(&bob).unwrap(); 21 | println!("{}", &json); 22 | 23 | let person: Person = serde_json::from_str(&json).unwrap(); 24 | 25 | println!("{:?}", person); 26 | } 27 | -------------------------------------------------------------------------------- /1d_json/rust/json/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(type_ascription)] 2 | use serde_json::json; 3 | 4 | fn main() { 5 | let o_json = r#"["foo", {"bar": ["baz", null, 1.0, 2]}]"#; 6 | let o: serde_json::Value = serde_json::from_str(&o_json).unwrap(); 7 | println!("{:?}", &o); 8 | 9 | let o = json!(["foo", {"bar": ("baz", None:Option, 1.0, 2)}]); 10 | println!("{:?}", &o); 11 | 12 | let s = &o.to_string(); 13 | println!("{}", &s); 14 | } 15 | -------------------------------------------------------------------------------- /1e_http_client/python/async.py: -------------------------------------------------------------------------------- 1 | import aiohttp 2 | import asyncio 3 | import time 4 | 5 | from person import URL, summary 6 | 7 | 8 | async def fetch_person(session, url): 9 | async with session.get(url) as resp: 10 | json = await resp.json() 11 | return json 12 | 13 | 14 | async def main(): 15 | async with aiohttp.ClientSession() as session: 16 | tasks = [] 17 | for _ in range(50): 18 | tasks.append(asyncio.ensure_future(fetch_person(session, URL))) 19 | 20 | all_data = await asyncio.gather(*tasks) 21 | for data in all_data: 22 | print(summary(data)) 23 | 24 | 25 | if __name__ == "__main__": 26 | start_time = time.time() 27 | asyncio.run(main()) 28 | print("--- %s seconds ---" % (time.time() - start_time)) 29 | -------------------------------------------------------------------------------- /1e_http_client/python/blocking.py: -------------------------------------------------------------------------------- 1 | import urllib.request 2 | import json 3 | import time 4 | 5 | from person import URL, summary 6 | 7 | def fetch(): 8 | request = urllib.request.Request( 9 | URL, 10 | headers={'User-Agent': 'Mozilla/5.0 (Macintosh; M1 Mac OS X 11)'}) 11 | res = urllib.request.urlopen(request) 12 | return json.load(res) 13 | 14 | 15 | def main(): 16 | for _ in range(50): 17 | person = fetch() 18 | print(summary(person)) 19 | 20 | 21 | if __name__ == "__main__": 22 | start_time = time.time() 23 | main() 24 | print("--- %s seconds ---" % (time.time() - start_time)) 25 | -------------------------------------------------------------------------------- /1e_http_client/python/person.py: -------------------------------------------------------------------------------- 1 | URL = "https://pipl.ir/v1/getPerson" 2 | 3 | 4 | def summary(data): 5 | p = data['person']['personal'] 6 | return f"{p['name']} {p['last_name']}, {p['age']}, {p['country']}" 7 | -------------------------------------------------------------------------------- /1e_http_client/rust/http_client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "http_client" 3 | version = "0.1.0" 4 | edition = "2018" 5 | default-run = "http_client" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | futures = "0.3.14" 11 | reqwest = {version= "0.11.3", features= ["json"]} 12 | serde = "1.0.125" 13 | serde_derive = "1.0.125" 14 | serde_json = "1.0.64" 15 | tokio = {version = "1.5.0", features = ["full"] } 16 | ureq = {version = "2.1.0", features = ["json"]} 17 | -------------------------------------------------------------------------------- /1e_http_client/rust/http_client/src/bin/async.rs: -------------------------------------------------------------------------------- 1 | use futures::future::join_all; 2 | use http_client::person; 3 | use std::time::Instant; 4 | 5 | #[tokio::main] 6 | async fn main() -> Result<(), Box> { 7 | let now = Instant::now(); 8 | let futures: Vec<_> = (0..50) 9 | .into_iter() 10 | .map(|_| reqwest::get(person::URL)) 11 | .collect(); 12 | for p in join_all(futures).await { 13 | println!( 14 | "{:#?}", 15 | person::summary(p?.json::().await?) 16 | ); 17 | } 18 | println!("{:.2}secs runtime", now.elapsed().as_secs_f64()); 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /1e_http_client/rust/http_client/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod person; 2 | -------------------------------------------------------------------------------- /1e_http_client/rust/http_client/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::time::Instant; 2 | 3 | mod person; 4 | 5 | fn main() -> Result<(), ureq::Error> { 6 | let data: person::Data = ureq::get(person::URL) 7 | .set("User-Agent", "Mozilla/5.0 (Macintosh; M1 Mac OS X 11_9_3)") 8 | .call()? 9 | .into_json()?; 10 | println!("{}", data); 11 | 12 | let now = Instant::now(); 13 | for _ in 0..50 { 14 | let body: serde_json::Value = ureq::get(person::URL) 15 | .set("User-Agent", "Mozilla/5.0 (Macintosh; M1 Mac OS X 11_9") 16 | .call()? 17 | .into_json()?; 18 | println!("{}", person::summary(body)); 19 | } 20 | println!("{:.2}secs runtime", now.elapsed().as_secs_f64()); 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /1e_http_client/rust/http_client/src/person.rs: -------------------------------------------------------------------------------- 1 | use serde_derive::Deserialize; 2 | 3 | pub static URL: &str = "https://pipl.ir/v1/getPerson"; 4 | 5 | pub fn summary(data: serde_json::Value) -> String { 6 | let p = &data["person"]["personal"]; 7 | format!( 8 | "{} {}, {}, {}", 9 | p["name"].as_str().unwrap(), 10 | p["last_name"].as_str().unwrap(), 11 | p["age"], 12 | p["country"].as_str().unwrap(), 13 | ) 14 | } 15 | 16 | #[derive(Deserialize)] 17 | pub struct Data { 18 | pub person: Person, 19 | } 20 | 21 | #[derive(Deserialize)] 22 | pub struct Person { 23 | pub education: serde_json::Value, 24 | pub marriage: Marriage, 25 | pub online_info: serde_json::Value, 26 | pub personal: serde_json::Value, 27 | pub work: serde_json::Value, 28 | } 29 | 30 | #[derive(Deserialize)] 31 | pub struct Marriage { 32 | pub married: bool, 33 | pub children: Option, 34 | pub spouse_name: Option, 35 | } 36 | 37 | impl std::fmt::Display for Data { 38 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 39 | let p = &self.person.personal; 40 | write!( 41 | f, 42 | "Person: {} {}, {}, {}", 43 | p["name"].as_str().unwrap(), 44 | p["last_name"].as_str().unwrap(), 45 | p["age"], 46 | p["country"].as_str().unwrap(), 47 | ) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /1f_http_server/python/fastapi_srv.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from fastapi.staticfiles import StaticFiles 3 | 4 | app = FastAPI() 5 | 6 | app.mount("/static", StaticFiles(directory="../static"), name="static") 7 | 8 | 9 | @app.get("/") 10 | @app.get("/hello/{name}") 11 | async def root(name: str = "World"): 12 | return {"message": f"Hello, {name}!"} 13 | 14 | 15 | @app.get("/items/{item_id}") 16 | async def read_item(item_id: int): 17 | return {"item_id": item_id} 18 | -------------------------------------------------------------------------------- /1f_http_server/rust/warp_srv/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "warp_srv" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | serde_json = "1.0.64" 10 | tokio = { version = "1", features = ["full"] } 11 | warp = "0.3" 12 | -------------------------------------------------------------------------------- /1f_http_server/rust/warp_srv/src/main.rs: -------------------------------------------------------------------------------- 1 | use serde_json::json; 2 | use warp::Filter; 3 | 4 | #[tokio::main] 5 | async fn main() { 6 | let directory = warp::path("static").and(warp::fs::dir("../../static/")); 7 | 8 | let opt_name = warp::path::param::() 9 | .map(Some) 10 | .or_else(|_| async { 11 | Ok::<(Option,), std::convert::Infallible>((None,)) }); 12 | let hello = warp::path("hello") 13 | .and(opt_name) 14 | .map(|name: Option| { 15 | let msg = format!( 16 | "Hello, {}!", 17 | name.unwrap_or("World".to_string())); 18 | warp::reply::json(&json!({ "message": msg })) 19 | }); 20 | let root = warp::path::end() 21 | .and(warp::get()) 22 | .map(|| warp::reply::json(&json!({"message": "Hello, World?"}))); 23 | 24 | let items = warp::path!("items" / i32) 25 | .map(|id| warp::reply::json(&json!({ "item_id": id }))); 26 | 27 | let routes = directory.or(hello).or(items).or(root); 28 | 29 | println!("Serving on localhost:3030"); 30 | warp::serve(routes).run(([127, 0, 0, 1], 3030)).await; 31 | } 32 | -------------------------------------------------------------------------------- /1f_http_server/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | Hello World! 3 | 4 | -------------------------------------------------------------------------------- /20_sqlite/import_cases.sh: -------------------------------------------------------------------------------- 1 | SQLITE="/usr/local/opt/sqlite3/bin/sqlite3" 2 | 3 | rm cts.sqlite3 4 | $SQLITE cts.sqlite3 < import_cases.sql 5 | -------------------------------------------------------------------------------- /20_sqlite/import_cases.sql: -------------------------------------------------------------------------------- 1 | .import --csv case_time_series.csv cases_csv 2 | 3 | ALTER TABLE cases_csv DROP COLUMN "Date"; 4 | 5 | CREATE TABLE cases( 6 | d timestamp, 7 | daily_confirmed integer, 8 | total_confirmed integer, 9 | daily_recovered integer, 10 | total_recovered integer, 11 | daily_deceased integer, 12 | total_deceased integer 13 | ); 14 | 15 | insert into cases 16 | select * from cases_csv; 17 | 18 | drop table cases_csv; 19 | 20 | CREATE TABLE month_cases ( 21 | mon text primary key, 22 | new_cases integer, 23 | recovered integer 24 | ); 25 | -------------------------------------------------------------------------------- /20_sqlite/python/sqlite.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | MOST_RECOVERED = '''SELECT * FROM cases 4 | WHERE daily_recovered = (SELECT max(daily_recovered) FROM cases);''' 5 | GROUP_BY_MONTH = ''' 6 | SELECT strftime('%Y-%m', d) as month, 7 | sum(daily_confirmed) as new_cases, 8 | sum(daily_recovered) as recovered 9 | FROM cases GROUP BY month; 10 | ''' 11 | 12 | if __name__ == '__main__': 13 | con = sqlite3.connect('../cts.sqlite3') 14 | con.row_factory = sqlite3.Row 15 | cursor = con.cursor() 16 | ins_cursor = con.cursor() 17 | for row in cursor.execute(MOST_RECOVERED): 18 | print('most recoveries', 19 | {k: v for k, v in zip(row.keys(), tuple(row))}) 20 | 21 | ins_cursor.execute("DELETE FROM month_cases") 22 | for row in cursor.execute(GROUP_BY_MONTH): 23 | print(tuple(row)) 24 | ins_cursor.execute( 25 | '''INSERT INTO month_cases 26 | (mon, new_cases, recovered) 27 | VALUES (?, ?, ?)''', row) 28 | 29 | con.commit() 30 | -------------------------------------------------------------------------------- /20_sqlite/rust/sqlite/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sqlite" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | rusqlite = { version = "0.25.1", features = ["column_decltype"] } 11 | -------------------------------------------------------------------------------- /20_sqlite/rust/sqlite/src/helpers.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | /// helper to make any row into a vector of strings 4 | pub fn row_to_str_vec(row: &rusqlite::Row) 5 | -> Result, rusqlite::Error> { 6 | let types = row.columns(); 7 | Ok((0..row.column_count()) 8 | .into_iter() 9 | .map(|ci| match types.get(ci).unwrap().decl_type() { 10 | Some("timestamp") => row.get_unwrap::(ci), 11 | Some("integer") => 12 | format!("{}", row.get_unwrap::(ci)), 13 | _ => String::from("t-unknown"), 14 | }) 15 | .collect::>()) 16 | } 17 | 18 | /// helper to make any row into a HashMap where k, v are Strings 19 | pub fn row_to_hashmap(row: &rusqlite::Row) 20 | -> Result, rusqlite::Error> { 21 | let types = row.columns(); 22 | Ok((0..row.column_count()) 23 | .into_iter() 24 | .map(|ci| { 25 | let col_name = row.column_name(ci).unwrap().to_owned(); 26 | match types.get(ci).unwrap().decl_type() { 27 | Some("timestamp") => 28 | (col_name, row.get_unwrap::(ci)), 29 | Some("integer") => 30 | (col_name, format!("{}", row.get_unwrap::(ci))), 31 | _ => (col_name, String::from("t-unknown")), 32 | } 33 | }) 34 | .collect::>()) 35 | } 36 | 37 | pub struct MonthCase { 38 | pub month: String, 39 | pub new_cases: u32, 40 | pub recovered: u32, 41 | } 42 | 43 | impl MonthCase { 44 | /// constructor from a rusqlite Row 45 | pub fn from_row(row: &rusqlite::Row) -> Self { 46 | MonthCase { 47 | month: row.get(0).unwrap(), 48 | new_cases: row.get(1).unwrap(), 49 | recovered: row.get(2).unwrap(), 50 | } 51 | } 52 | } 53 | 54 | impl std::fmt::Display for MonthCase { 55 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 56 | write!(f, "{}, {}, {}", self.month, self.new_cases, self.recovered) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /20_sqlite/rust/sqlite/src/main.rs: -------------------------------------------------------------------------------- 1 | use rusqlite::{params, Connection, Result}; 2 | mod helpers; 3 | 4 | static MOST_RECOVERED: &str = r#"SELECT * FROM cases 5 | WHERE daily_recovered = (SELECT max(daily_recovered) FROM cases);"#; 6 | static GROUP_BY_MONTH: &str = r#" 7 | SELECT strftime('%Y-%m', d) as month, 8 | sum(daily_confirmed) as new_cases, 9 | sum(daily_recovered) as recovered 10 | FROM cases GROUP BY month; 11 | "#; 12 | 13 | fn main() -> Result<()> { 14 | let conn = Connection::open("../../cts.sqlite3")?; 15 | let mut stmt = conn.prepare(MOST_RECOVERED)?; 16 | let row = stmt.query_row([], helpers::row_to_str_vec)?; 17 | println!("{:?}", row); 18 | let row = stmt.query_row([], helpers::row_to_hashmap)?; 19 | println!("most recoveries {:?}", row); 20 | 21 | conn.execute("DELETE FROM month_cases", [])?; 22 | let mut stmt = conn.prepare(GROUP_BY_MONTH)?; 23 | let month_cases = stmt.query_map([], 24 | |row| Ok(helpers::MonthCase::from_row(row)))?; 25 | for mc in month_cases { 26 | let mc = mc?; 27 | println!("{}", mc); 28 | conn.execute( 29 | "INSERT INTO month_cases 30 | (mon, new_cases, recovered) 31 | VALUES (?1, ?2, ?3)", 32 | params![mc.month, mc.new_cases, mc.recovered], 33 | )?; 34 | } 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /21_postgresql/import_cases.sh: -------------------------------------------------------------------------------- 1 | psql -f import_cases.sql 2 | -------------------------------------------------------------------------------- /21_postgresql/import_cases.sql: -------------------------------------------------------------------------------- 1 | drop table cases, month_cases; 2 | begin; 3 | 4 | CREATE TABLE cases( 5 | human_date text, 6 | d date, 7 | daily_confirmed integer, 8 | total_confirmed integer, 9 | daily_recovered integer, 10 | total_recovered integer, 11 | daily_deceased integer, 12 | total_deceased integer 13 | ); 14 | 15 | \copy cases from 'case_time_series.csv' with csv header; 16 | 17 | ALTER TABLE cases DROP COLUMN "human_date"; 18 | 19 | CREATE TABLE month_cases ( 20 | mon text primary key, 21 | new_cases integer, 22 | recovered integer 23 | ); 24 | commit; 25 | -------------------------------------------------------------------------------- /21_postgresql/python/helper.py: -------------------------------------------------------------------------------- 1 | MOST_RECOVERED = """SELECT * FROM cases 2 | WHERE daily_recovered = (SELECT max(daily_recovered) FROM cases);""" 3 | GROUP_BY_MONTH = """ 4 | SELECT date_trunc('month', d)::date as month, 5 | sum(daily_confirmed) as new_cases, 6 | sum(daily_recovered) as recovered 7 | FROM cases 8 | GROUP BY month 9 | ORDER BY month""" 10 | -------------------------------------------------------------------------------- /21_postgresql/python/pg_async.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import psycopg2.extras 3 | import aiopg 4 | import helper 5 | 6 | 7 | async def go(): 8 | async with aiopg.create_pool("host=localhost user=htd") as pool: 9 | async with pool.acquire() as conn: 10 | async with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur: 11 | await cur.execute(helper.MOST_RECOVERED) 12 | rows = await cur.fetchall() 13 | print('most recoveries', dict(rows[0])) 14 | 15 | await cur.execute("BEGIN") # conn.commit() not available 16 | await cur.execute("DELETE FROM month_cases") 17 | await cur.execute(helper.GROUP_BY_MONTH) 18 | ret = [] 19 | async for row in cur: 20 | ret.append(row) 21 | for row in ret: 22 | print(row) 23 | await cur.execute( 24 | '''INSERT INTO month_cases 25 | (mon, new_cases, recovered) 26 | VALUES (%s, %s, %s)''', row) 27 | await cur.execute("COMMIT") # conn.commit() not available 28 | 29 | 30 | if __name__ == '__main__': 31 | loop = asyncio.get_event_loop() 32 | loop.run_until_complete(go()) 33 | -------------------------------------------------------------------------------- /21_postgresql/python/pg_blocking.py: -------------------------------------------------------------------------------- 1 | import psycopg2 2 | import psycopg2.extras 3 | import helper 4 | 5 | if __name__ == '__main__': 6 | con = psycopg2.connect("host=localhost user=htd") 7 | cursor = con.cursor(cursor_factory=psycopg2.extras.DictCursor) 8 | ins_cursor = con.cursor() 9 | cursor.execute(helper.MOST_RECOVERED) 10 | for row in cursor: 11 | print('most recoveries', dict(row)) 12 | 13 | ins_cursor.execute("DELETE FROM month_cases") 14 | cursor.execute(helper.GROUP_BY_MONTH) 15 | for row in cursor: 16 | print(tuple(row)) 17 | ins_cursor.execute( 18 | '''INSERT INTO month_cases 19 | (mon, new_cases, recovered) 20 | VALUES (%s, %s, %s)''', row) 21 | 22 | con.commit() 23 | -------------------------------------------------------------------------------- /21_postgresql/rust/pg_async/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pg_async" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | chrono = "0.4.19" 11 | tokio = { version = "1.5", features = ["full"] } 12 | 13 | tokio-postgres = "0.7.2" 14 | postgres = { version = "0.19", features = ["with-chrono-0_4"] } 15 | futures = "0.3.14" 16 | #tokio-postgres = { version = "0.7", features = ["default"] } 17 | -------------------------------------------------------------------------------- /21_postgresql/rust/pg_async/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use tokio_postgres::{types::Type, Error, NoTls}; 3 | 4 | static MOST_RECOVERED: &str = r#"SELECT * FROM cases 5 | WHERE daily_recovered = (SELECT max(daily_recovered) FROM cases);"#; 6 | static GROUP_BY_MONTH: &str = " 7 | SELECT date_trunc('month', d)::date as month, 8 | sum(daily_confirmed) as new_cases, 9 | sum(daily_recovered) as recovered 10 | FROM cases 11 | GROUP BY month 12 | ORDER BY month"; 13 | 14 | /// silly way to convert row into Vec of Strings from postgres types 15 | /// see https://docs.rs/postgres/latest/postgres/types/trait.FromSql.html 16 | async fn row_to_str_vec(row: &tokio_postgres::Row) -> Vec { 17 | (0..row.len()) 18 | .into_iter() 19 | .map(|ci| match *row.columns().get(ci).unwrap().type_() { 20 | Type::DATE => row.get::(ci).to_string(), 21 | Type::INT4 => row.get::(ci).to_string(), 22 | Type::INT8 => row.get::(ci).to_string(), 23 | _ => "blah".to_string(), 24 | }) 25 | .collect() 26 | } 27 | 28 | async fn row_to_str_hashmap(row: &tokio_postgres::Row) -> HashMap { 29 | let values = row_to_str_vec(row).await; 30 | values 31 | .into_iter() 32 | .zip(row.columns().iter()) 33 | .map(|(v, k)| (k.name().to_string(), v)) 34 | .collect() 35 | } 36 | 37 | #[tokio::main] 38 | async fn main() -> Result<(), Error> { 39 | let (mut client, connection) = 40 | tokio_postgres::connect("host=localhost user=htd", NoTls).await?; 41 | 42 | // connection object performs communication with DB, spawned to run on its own 43 | tokio::spawn(async move { 44 | if let Err(e) = connection.await { 45 | eprintln!("connection error: {}", e); 46 | } 47 | }); 48 | 49 | let rows = client.query(MOST_RECOVERED, &[]).await?; 50 | 51 | let value: chrono::NaiveDate = rows[0].get(0); 52 | println!("{:?}", value); 53 | println!("{:?}", row_to_str_vec(&rows[0]).await); 54 | println!("{:?}", row_to_str_hashmap(&rows[0]).await); 55 | 56 | let transaction = client.transaction().await?; 57 | transaction.query("DELETE FROM month_cases", &[]).await?; 58 | let ins_mv = transaction 59 | .prepare( 60 | "INSERT INTO month_cases 61 | (mon, new_cases, recovered) 62 | VALUES ($1, $2, $3)", 63 | ) 64 | .await?; 65 | 66 | for row in transaction.query(GROUP_BY_MONTH, &[]).await? { 67 | println!("{:?}", row_to_str_vec(&row).await); 68 | let date: chrono::NaiveDate = row.get(0); 69 | let new_cases: i64 = row.get(1); 70 | let recovered: i64 = row.get(2); 71 | transaction 72 | .execute( 73 | &ins_mv, 74 | &[&date.to_string(), &(new_cases as i32), &(recovered as i32)], 75 | ) 76 | .await?; 77 | } 78 | transaction.commit().await?; 79 | Ok(()) 80 | } 81 | -------------------------------------------------------------------------------- /21_postgresql/rust/pg_blocking/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pg_blocking" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | chrono = "0.4.19" 11 | postgres = { version = "0.19.1", features=["with-chrono-0_4"]} 12 | -------------------------------------------------------------------------------- /21_postgresql/rust/pg_blocking/src/main.rs: -------------------------------------------------------------------------------- 1 | use postgres::{types::Type, Client, Error, NoTls}; 2 | use std::collections::HashMap; 3 | 4 | static MOST_RECOVERED: &str = r#"SELECT * FROM cases 5 | WHERE daily_recovered = (SELECT max(daily_recovered) FROM cases);"#; 6 | static GROUP_BY_MONTH: &str = " 7 | SELECT date_trunc('month', d)::date as month, 8 | sum(daily_confirmed) as new_cases, 9 | sum(daily_recovered) as recovered 10 | FROM cases 11 | GROUP BY month 12 | ORDER BY month"; 13 | 14 | /// silly way to convert row into Vec of Strings from postgres types 15 | /// see https://docs.rs/postgres/latest/postgres/types/trait.FromSql.html 16 | fn row_to_str_vec(row: &postgres::Row) -> Vec { 17 | (0..row.len()) 18 | .into_iter() 19 | .map(|ci| match *row.columns().get(ci).unwrap().type_() { 20 | Type::DATE => row.get::(ci).to_string(), 21 | Type::INT4 => row.get::(ci).to_string(), 22 | Type::INT8 => row.get::(ci).to_string(), 23 | _ => "blah".to_string(), 24 | }) 25 | .collect() 26 | } 27 | 28 | fn row_to_str_hashmap(row: &postgres::Row) -> HashMap { 29 | let values = row_to_str_vec(row); 30 | values 31 | .into_iter() 32 | .zip(row.columns().iter()) 33 | .map(|(v, k)| (k.name().to_string(), v)) 34 | .collect() 35 | } 36 | 37 | fn main() -> Result<(), Error> { 38 | let mut client = Client::connect("host=localhost user=htd", NoTls)?; 39 | 40 | let rows = client.query(MOST_RECOVERED, &[])?; 41 | 42 | let value: chrono::NaiveDate = rows[0].get(0); 43 | println!("{:?}", value); 44 | println!("{:?}", row_to_str_vec(&rows[0])); 45 | println!("{:?}", row_to_str_hashmap(&rows[0])); 46 | 47 | let mut transaction = client.transaction()?; 48 | transaction.query("DELETE FROM month_cases", &[])?; 49 | let ins_mv = transaction.prepare( 50 | "INSERT INTO month_cases 51 | (mon, new_cases, recovered) 52 | VALUES ($1, $2, $3)", 53 | )?; 54 | for row in transaction.query(GROUP_BY_MONTH, &[])? { 55 | println!("{:?}", row_to_str_vec(&row)); 56 | let date: chrono::NaiveDate = row.get(0); 57 | let new_cases: i64 = row.get(1); 58 | let recovered: i64 = row.get(2); 59 | transaction.execute( 60 | &ins_mv, 61 | &[&date.to_string(), &(new_cases as i32), &(recovered as i32)], 62 | )?; 63 | } 64 | transaction.commit()?; 65 | Ok(()) 66 | } 67 | -------------------------------------------------------------------------------- /22_websockets_server/python/atomic.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | 4 | class AtomicCounter: 5 | """An atomic, thread-safe counter""" 6 | def __init__(self, initial=0): 7 | """Initialize a new atomic counter to given initial value""" 8 | self._value = initial 9 | self._lock = threading.Lock() 10 | 11 | def inc(self, num=1): 12 | """Atomically increment the counter by num and return the new value""" 13 | with self._lock: 14 | self._value += num 15 | return self._value 16 | 17 | def dec(self, num=1): 18 | """Atomically decrement the counter by num and return the new value""" 19 | with self._lock: 20 | self._value -= num 21 | return self._value 22 | 23 | @property 24 | def value(self): 25 | return self._value 26 | -------------------------------------------------------------------------------- /22_websockets_server/python/fastapi_ws.py: -------------------------------------------------------------------------------- 1 | from atomic import AtomicCounter 2 | 3 | from fastapi import FastAPI, WebSocket, WebSocketDisconnect 4 | from fastapi.responses import HTMLResponse 5 | 6 | app = FastAPI() 7 | 8 | 9 | class ConnectionManager: 10 | def __init__(self): 11 | self.user_counter = AtomicCounter() 12 | self.active_connections = dict() 13 | 14 | async def connect(self, websocket: WebSocket): 15 | await websocket.accept() 16 | client_id = self.user_counter.inc() 17 | self.active_connections[client_id] = websocket 18 | 19 | def disconnect(self, websocket: WebSocket): 20 | k = self.client_id(websocket) 21 | if k: 22 | del self.active_connections[k] 23 | 24 | def client_id(self, websocket: WebSocket): 25 | return next((uid for uid, ws in self.active_connections.items() if ws == websocket), None) 26 | 27 | async def broadcast(self, message: str, websocket): 28 | for connection in filter(lambda c: c != websocket, self.active_connections.values()): 29 | await connection.send_text(message) 30 | 31 | 32 | manager = ConnectionManager() 33 | 34 | 35 | @app.get("/") 36 | async def get(): 37 | with open('../static/index.html') as f: 38 | html = f.read() 39 | return HTMLResponse(html) 40 | 41 | 42 | @app.websocket("/chat") 43 | async def websocket_endpoint(websocket: WebSocket): 44 | await manager.connect(websocket) 45 | try: 46 | while True: 47 | data = await websocket.receive_text() 48 | await manager.broadcast(f": {data}", websocket) 49 | except WebSocketDisconnect: 50 | user_id = manager.client_id(websocket) 51 | manager.disconnect(websocket) 52 | await manager.broadcast(f"User#{user_id} left the chat", None) 53 | -------------------------------------------------------------------------------- /22_websockets_server/rust/warp_ws/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "warp_ws" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | futures = "0.3.15" 11 | warp = "0.3.1" 12 | tokio = { version = "1.0", features = ["macros", "sync", "rt-multi-thread"]} 13 | tokio-stream = { version = "0.1.1", features = ["net"] } 14 | -------------------------------------------------------------------------------- /22_websockets_server/rust/warp_ws/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::sync::{ 3 | atomic::{AtomicUsize, Ordering}, 4 | Arc, 5 | }; 6 | 7 | use futures::{FutureExt, StreamExt}; 8 | use tokio::sync::{mpsc, RwLock}; 9 | use tokio_stream::wrappers::UnboundedReceiverStream; 10 | use warp::ws::{Message, WebSocket}; 11 | use warp::Filter; 12 | 13 | static NEXT_USER_ID: AtomicUsize = AtomicUsize::new(1); 14 | static INDEX_HTML: &str = std::include_str!("../../../static/index.html"); 15 | 16 | type Users = Arc>>>>; 17 | 18 | #[tokio::main] 19 | async fn main() { 20 | let users = Users::default(); 21 | let users = warp::any().map(move || users.clone()); 22 | 23 | let chat = warp::path("chat") 24 | .and(warp::ws()) 25 | .and(users) 26 | .map(|ws: warp::ws::Ws, users| { 27 | ws.on_upgrade(move |socket| user_connected(socket, users)) 28 | }); 29 | 30 | let index = warp::path::end().map(|| warp::reply::html(INDEX_HTML)); 31 | let routes = index.or(chat); 32 | warp::serve(routes).run(([127, 0, 0, 1], 8000)).await; 33 | } 34 | 35 | async fn user_connected(ws: WebSocket, users: Users) { 36 | let my_id = NEXT_USER_ID.fetch_add(1, Ordering::Relaxed); 37 | 38 | eprintln!("new chat user: {}", my_id); 39 | 40 | let (user_ws_tx, mut user_ws_rx) = ws.split(); 41 | 42 | let (tx, rx) = mpsc::unbounded_channel(); 43 | let rx = UnboundedReceiverStream::new(rx); 44 | tokio::task::spawn(rx.forward(user_ws_tx).map(|result| { 45 | if let Err(e) = result { 46 | eprintln!("websocket send error: {}", e); 47 | } 48 | })); 49 | 50 | users.write().await.insert(my_id, tx); 51 | 52 | let users2 = users.clone(); 53 | 54 | while let Some(result) = user_ws_rx.next().await { 55 | let msg = match result { 56 | Ok(msg) => msg, 57 | Err(e) => { 58 | eprintln!("websocket error(uid={}): {}", my_id, e); 59 | break; 60 | } 61 | }; 62 | user_message(my_id, msg, &users).await; 63 | } 64 | 65 | user_disconnected(my_id, &users2).await; 66 | } 67 | 68 | async fn user_message(my_id: usize, msg: Message, users: &Users) { 69 | // Skip any non-Text messages... 70 | let msg = if let Ok(s) = msg.to_str() { 71 | s 72 | } else { 73 | return; 74 | }; 75 | 76 | let new_msg = format!(": {}", my_id, msg); 77 | 78 | for (&uid, tx) in users.read().await.iter() { 79 | if my_id != uid { 80 | if let Err(_disconnected) = tx.send(Ok(Message::text(new_msg.clone()))) { 81 | // nothing to do here, `user_disconnected` handles it 82 | } 83 | } 84 | } 85 | } 86 | 87 | async fn user_disconnected(my_id: usize, users: &Users) { 88 | eprintln!("good bye user: {}", my_id); 89 | users.write().await.remove(&my_id); 90 | } 91 | 92 | -------------------------------------------------------------------------------- /22_websockets_server/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo Chat 5 | 10 | 11 | 12 |

Demo chat

13 |
14 |

Connecting...

15 |
16 | 17 | 18 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /23_websockets_client/python/ws_client.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import websockets 3 | import sys 4 | 5 | 6 | async def read_stdin_line(): 7 | loop = asyncio.get_event_loop() 8 | return await loop.run_in_executor(None, sys.stdin.readline) 9 | 10 | 11 | async def stdin_to_ws(websocket): 12 | while True: 13 | line = await read_stdin_line() 14 | await websocket.send(line.strip()) 15 | if line.strip() == "/exit": 16 | break 17 | 18 | 19 | async def ws_next(websocket): 20 | try: 21 | return await websocket.recv() 22 | except: 23 | return None 24 | 25 | 26 | async def main(): 27 | uri = "ws://localhost:8000/chat" 28 | async with websockets.connect(uri) as websocket: 29 | print("connected successfully") 30 | while True: 31 | stdin = asyncio.create_task(stdin_to_ws(websocket)) 32 | ws = asyncio.create_task(ws_next(websocket)) 33 | done, _ = await asyncio.wait([stdin, ws], return_when=asyncio.FIRST_COMPLETED) 34 | msg = done.pop() 35 | if msg.result(): 36 | print(msg.result()) 37 | else: 38 | break 39 | 40 | 41 | if __name__ == "__main__": 42 | asyncio.get_event_loop().run_until_complete(main()) 43 | -------------------------------------------------------------------------------- /23_websockets_client/rust/ws_client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ws_client" 3 | version = "0.1.0" 4 | authors = ["Bedroom Builds"] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | tokio-tungstenite = "0.10" 11 | tungstenite = {version = "0.10", default-features = false} 12 | url = "2.1" 13 | tokio = { version = "0.2", features = ["full"] } 14 | futures = "0.3.15" 15 | -------------------------------------------------------------------------------- /23_websockets_client/rust/ws_client/src/main.rs: -------------------------------------------------------------------------------- 1 | use futures::{SinkExt, StreamExt}; 2 | use tokio::io::AsyncBufReadExt; 3 | use tokio::sync::mpsc; 4 | 5 | use tokio_tungstenite::connect_async; 6 | use tungstenite::protocol::Message; 7 | 8 | #[tokio::main] 9 | async fn main() { 10 | let connect_addr = "ws://localhost:8000/chat"; 11 | let url = url::Url::parse(&connect_addr).unwrap(); 12 | let (mut ws_stream, _) = connect_async(url).await.expect("Failed to connect"); 13 | println!("WebSocket handshake has been successfully completed"); 14 | 15 | let (mut tx_stdin, mut rx) = mpsc::channel::(10); 16 | // read from stdin 17 | let stdin_loop = async move { 18 | loop { 19 | let mut line = String::new(); 20 | let mut buf_stdin = tokio::io::BufReader::new(tokio::io::stdin()); 21 | buf_stdin.read_line(&mut line).await.unwrap(); 22 | tx_stdin.send(line.trim().to_string()).await.unwrap(); 23 | if line.trim() == "/exit" { 24 | break; 25 | } 26 | } 27 | }; 28 | tokio::task::spawn(stdin_loop); 29 | // handle websocket messages 30 | loop { 31 | tokio::select! { 32 | ws_msg = ws_stream.next() => { 33 | match ws_msg { 34 | Some(msg) => match msg { 35 | Ok(msg) => match msg { 36 | Message::Binary(x) => println!("binary {:?}", x), 37 | Message::Text(x) => println!("{}", x), 38 | Message::Ping(x) => println!("Ping {:?}", x), 39 | Message::Pong(x) => println!("Pong {:?}", x), 40 | Message::Close(x) => println!("Close {:?}", x), 41 | }, 42 | Err(_) => {println!("server went away"); break;} 43 | }, 44 | None => {println!("no message"); break;}, 45 | } 46 | }, 47 | stdin_msg = rx.next() => { 48 | match stdin_msg { 49 | Some(msg) => { 50 | let _ = ws_stream.send(Message::Text(msg)).await; 51 | }, 52 | None => break 53 | } 54 | } 55 | }; 56 | } 57 | // Gracefully close connection by Close-handshake procedure 58 | let _ = ws_stream.send(Message::Close(None)).await; 59 | let close = ws_stream.next().await; 60 | println!("server close msg: {:?}", close); 61 | assert!(ws_stream.next().await.is_none()); 62 | let _ = ws_stream.close(None).await; 63 | } 64 | -------------------------------------------------------------------------------- /24_raster_graphics/python/thumbnails.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | from PIL import Image 3 | import numpy as np 4 | 5 | 6 | def julia(): 7 | imgx = 800 8 | imgy = 800 9 | 10 | scalex = 3.0 / imgx 11 | scaley = 3.0 / imgy 12 | 13 | imgbuf = np.zeros((imgx, imgy, 3), dtype=np.uint8) 14 | for i in np.ndindex(imgbuf.shape[:2]): 15 | y, x = i 16 | r = (0.3 * x) 17 | b = (0.3 * y) 18 | cx = float(y) * scalex - 1.5 19 | cy = float(x) * scaley - 1.5 20 | c = complex(-0.4, 0.6) 21 | z = complex(cx, cy) 22 | 23 | g = 0 24 | while g < 255 and np.hypot(z.real, z.imag) <= 2.0: 25 | z = z * z + c 26 | g += 1 27 | imgbuf[i] = [r, g, b] 28 | 29 | im = Image.fromarray(imgbuf, 'RGB') 30 | im.save("fractal.png") 31 | 32 | 33 | if __name__ == "__main__": 34 | julia() 35 | for infile in sys.argv[1:]: 36 | outfile = os.path.splitext(infile)[0] + ".thumbnail.jpg" 37 | if infile != outfile: 38 | try: 39 | with Image.open(infile) as im: 40 | im.thumbnail((128, 128)) 41 | im.save(outfile, "JPEG") 42 | except OSError: 43 | print("cannot create thumbnail for", infile) 44 | -------------------------------------------------------------------------------- /24_raster_graphics/rust/thumbnail/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "thumbnail" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | image = "0.23.14" 10 | num-complex = "0.4.0" 11 | -------------------------------------------------------------------------------- /24_raster_graphics/rust/thumbnail/src/main.rs: -------------------------------------------------------------------------------- 1 | use image::{imageops::FilterType, ImageFormat}; 2 | use std::path::PathBuf; 3 | 4 | fn julia() { 5 | let imgx = 800; 6 | let imgy = 800; 7 | 8 | let scalex = 3.0 / imgx as f32; 9 | let scaley = 3.0 / imgy as f32; 10 | 11 | let mut imgbuf = image::ImageBuffer::new(imgx, imgy); 12 | 13 | for (x, y, pixel) in imgbuf.enumerate_pixels_mut() { 14 | let r = (0.3 * x as f32) as u8; 15 | let b = (0.3 * y as f32) as u8; 16 | let cx = y as f32 * scalex - 1.5; 17 | let cy = x as f32 * scaley - 1.5; 18 | 19 | let c = num_complex::Complex::new(-0.4, 0.6); 20 | let mut z = num_complex::Complex::new(cx, cy); 21 | 22 | let mut g = 0; 23 | while g < 255 && z.norm() <= 2.0 { 24 | z = z * z + c; 25 | g += 1; 26 | } 27 | *pixel = image::Rgb([r, g, b]); 28 | } 29 | 30 | imgbuf.save("fractal.png").unwrap(); 31 | } 32 | 33 | fn main() { 34 | julia(); 35 | for fname in std::env::args().skip(1) { 36 | let src_path = PathBuf::from(&fname); 37 | let mut thumb_path = PathBuf::from(&fname); 38 | thumb_path.set_extension("thumbnail.jpg"); 39 | if src_path != thumb_path { 40 | let src_img = image::open(&src_path).expect("Can't open input image."); 41 | let src_img = image::imageops::resize(&src_img, 128, 128, FilterType::CatmullRom); 42 | src_img 43 | .save_with_format(&thumb_path, ImageFormat::Jpeg) 44 | .unwrap(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /25_vector_graphics/python/cairodraw.py: -------------------------------------------------------------------------------- 1 | import cairo 2 | 3 | 4 | def draw(context): 5 | x, y, x1, y1 = 0.1, 0.5, 0.4, 0.9 6 | x2, y2, x3, y3 = 0.6, 0.1, 0.9, 0.5 7 | context.scale(200, 200) 8 | context.set_line_width(0.04) 9 | context.move_to(x, y) 10 | context.curve_to(x1, y1, x2, y2, x3, y3) 11 | context.stroke() 12 | context.set_source_rgba(1, 0.2, 0.2, 0.6) 13 | context.set_line_width(0.02) 14 | context.move_to(x, y) 15 | context.line_to(x1, y1) 16 | context.move_to(x2, y2) 17 | context.line_to(x3, y3) 18 | context.stroke() 19 | 20 | 21 | def draw_box(context, x, y, x2, y2): 22 | context.set_source_rgb(0.258, 0.525, 0.956) 23 | context.new_path() 24 | context.move_to(x, y) 25 | context.line_to(x2, y) 26 | context.line_to(x, y2) 27 | context.move_to(x2, y2) 28 | context.line_to(x2, y) 29 | context.line_to(x, y2) 30 | context.close_path() 31 | context.fill() 32 | 33 | 34 | if __name__ == "__main__": 35 | with cairo.SVGSurface("example.svg", 200, 200) as surface: 36 | context = cairo.Context(surface) 37 | draw_box(context, 0., 0., 32., 32.) 38 | draw(context) 39 | with cairo.ImageSurface(cairo.FORMAT_ARGB32, 200, 200) as surface: 40 | context = cairo.Context(surface) 41 | draw_box(context, 0., 0., 32., 32.) 42 | draw(context) 43 | surface.write_to_png("output.png") 44 | -------------------------------------------------------------------------------- /25_vector_graphics/rust/cairodraw/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cairodraw" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | cairo-rs = { version = "0.14", features = ["png", "svg"] } 10 | -------------------------------------------------------------------------------- /25_vector_graphics/rust/cairodraw/src/main.rs: -------------------------------------------------------------------------------- 1 | fn draw(context: &cairo::Context) -> Result<(), Box> { 2 | let (x, y, x1, y1) = (0.1, 0.5, 0.4, 0.9); 3 | let (x2, y2, x3, y3) = (0.6, 0.1, 0.9, 0.5); 4 | context.scale(200., 200.); 5 | context.set_line_width(0.04); 6 | context.move_to(x, y); 7 | context.curve_to(x1, y1, x2, y2, x3, y3); 8 | context.stroke()?; 9 | context.set_source_rgba(1., 0.2, 0.2, 0.6); 10 | context.set_line_width(0.02); 11 | context.move_to(x, y); 12 | context.line_to(x1, y1); 13 | context.move_to(x2, y2); 14 | context.line_to(x3, y3); 15 | context.stroke()?; 16 | Ok(()) 17 | } 18 | 19 | fn draw_box( 20 | context: &cairo::Context, 21 | x: f64, 22 | y: f64, 23 | x2: f64, 24 | y2: f64, 25 | ) -> Result<(), Box> { 26 | context.set_source_rgb(0.258, 0.525, 0.956); 27 | context.new_path(); 28 | context.move_to(x, y); 29 | context.line_to(x2, y); 30 | context.line_to(x, y2); 31 | context.move_to(x2, y2); 32 | context.line_to(x2, y); 33 | context.line_to(x, y2); 34 | context.close_path(); 35 | context.fill()?; 36 | Ok(()) 37 | } 38 | 39 | fn main() -> Result<(), Box> { 40 | let png_output_fn = "output.png"; 41 | let img_surface = cairo::ImageSurface::create(cairo::Format::ARgb32, 200, 200).unwrap(); 42 | let svg_fn = std::path::Path::new("output.svg"); 43 | let svg_surface = cairo::SvgSurface::new(200., 200., Some(svg_fn)).unwrap(); 44 | let img_ctx = cairo::Context::new(&img_surface)?; 45 | let svg_ctx = cairo::Context::new(&svg_surface)?; 46 | 47 | draw_box(&img_ctx, 0., 0., 32., 32.)?; 48 | draw_box(&svg_ctx, 0., 0., 32., 32.)?; 49 | draw(&img_ctx)?; 50 | draw(&svg_ctx)?; 51 | let mut file = std::fs::File::create(png_output_fn)?; 52 | img_surface.write_to_png(&mut file).unwrap(); 53 | Ok(()) 54 | } 55 | -------------------------------------------------------------------------------- /26_plotting/python/matplotlib_ex.py: -------------------------------------------------------------------------------- 1 | # Data is pulled from https://covid.ourworldindata.org/data/owid-covid-data.json 2 | import matplotlib.pyplot as plt 3 | import matplotlib.ticker 4 | import json 5 | 6 | countries = ["CHN", "USA", "RUS", "JPN", "DEU", "IND", "OWID_WRL"] 7 | 8 | if __name__ == "__main__": 9 | fig, ax = plt.subplots(figsize=(14, 8)) 10 | 11 | with open("../rust/plotters_ex/owid-covid-data.json") as f: 12 | data = json.load(f) 13 | for c in countries: 14 | nc = [] 15 | tc = [] 16 | for row in data[c]['data']: 17 | nc.append(row.get('new_cases', 0)) 18 | tc.append(row.get('total_cases', 0)) 19 | ax.plot(tc, nc, label=c) 20 | 21 | ax.set_xscale('log') 22 | ax.set_xticks([50, 100, 1000, 10000, 100000, 1000000, 10000000]) 23 | non_sci = matplotlib.ticker.ScalarFormatter() 24 | non_sci.set_scientific(False) 25 | ax.get_xaxis().set_major_formatter(non_sci) 26 | ax.set_yscale('log') 27 | ax.set_yticks([10, 50, 100, 1000, 10000, 100000, 200000]) 28 | ax.get_yaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) 29 | 30 | ax.set_title('World COVID-19 Cases') 31 | ax.set_xlabel('total cases') 32 | ax.set_ylabel('new cases') 33 | ax.grid(True) 34 | 35 | text = 'Data Source: https://covid.ourworldindata.org/data/owid-covid-data.json' 36 | plt.figtext(0.5, 0, text, fontsize=8, va="bottom", ha="center") 37 | 38 | box = ax.get_position() 39 | ax.set_position([box.x0, box.y0, box.width * 0.7, box.height]) 40 | legend = ax.legend(title="Countries", 41 | shadow=False, 42 | fontsize='x-large', 43 | loc='center left', 44 | bbox_to_anchor=(1.05, 0.5)) 45 | 46 | plt.savefig("test.svg") 47 | #plt.show() 48 | -------------------------------------------------------------------------------- /26_plotting/rust/plotters_ex/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "plotters_ex" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | plotters-svg = {version = "^0.3.*", optional = true} 10 | plotters = "0.3.1" 11 | serde = "1.0.127" 12 | serde_derive = "1.0.127" 13 | serde_json = "1.0.66" 14 | 15 | [dependencies.plotters-backend] 16 | version = "^0.3" 17 | 18 | [dependencies.plotters-bitmap] 19 | version = "^0.3" 20 | optional = true 21 | default_features = false 22 | -------------------------------------------------------------------------------- /26_plotting/rust/plotters_ex/src/main.rs: -------------------------------------------------------------------------------- 1 | // Data is pulled from https://covid.ourworldindata.org/data/owid-covid-data.json 2 | use plotters::prelude::*; 3 | use std::fs::File; 4 | use std::io::BufReader; 5 | 6 | #[derive(serde_derive::Deserialize)] 7 | struct DailyData { 8 | #[serde(default)] 9 | new_cases: f64, 10 | #[serde(default)] 11 | total_cases: f64, 12 | } 13 | 14 | #[derive(serde_derive::Deserialize)] 15 | struct CountryData { 16 | data: Vec, 17 | } 18 | 19 | const OUT_FILE_NAME: &'static str = "plot.svg"; 20 | fn main() -> Result<(), Box> { 21 | let root = SVGBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); 22 | root.fill(&WHITE)?; 23 | 24 | let (upper, lower) = root.split_vertically(750); 25 | 26 | lower.titled( 27 | "Data Source: https://covid.ourworldindata.org/data/owid-covid-data.json", 28 | ("sans-serif", 10).into_font().color(&BLACK.mix(0.5)), 29 | )?; 30 | 31 | let mut chart = ChartBuilder::on(&upper) 32 | .caption("World COVID-19 Cases", ("sans-serif", (5).percent_height())) 33 | .set_label_area_size(LabelAreaPosition::Left, (8).percent()) 34 | .set_label_area_size(LabelAreaPosition::Bottom, (4).percent()) 35 | .margin((1).percent()) 36 | .build_cartesian_2d( 37 | (20u32..5000_0000u32) 38 | .log_scale() 39 | .with_key_points(vec![50, 100, 1000, 10000, 100000, 1000000, 10000000]), 40 | (0u32..50_0000u32) 41 | .log_scale() 42 | .with_key_points(vec![10, 50, 100, 1000, 10000, 100000, 200000]), 43 | )?; 44 | 45 | chart 46 | .configure_mesh() 47 | .x_desc("Total Cases") 48 | .y_desc("New Cases") 49 | .draw()?; 50 | 51 | let data: std::collections::HashMap = 52 | serde_json::from_reader(BufReader::new(File::open("owid-covid-data.json")?))?; 53 | 54 | for (idx, &series) in ["CHN", "USA", "RUS", "JPN", "DEU", "IND", "OWID_WRL"] 55 | .iter() 56 | .enumerate() 57 | { 58 | let color = Palette99::pick(idx).mix(0.9); 59 | chart 60 | .draw_series(LineSeries::new( 61 | data[series].data.iter().map( 62 | |&DailyData { 63 | new_cases, 64 | total_cases, 65 | .. 66 | }| (total_cases as u32, new_cases as u32), 67 | ), 68 | color.stroke_width(3), 69 | ))? 70 | .label(series) 71 | .legend(move |(x, y)| Rectangle::new([(x, y - 5), (x + 10, y + 5)], color.filled())); 72 | } 73 | 74 | chart 75 | .configure_series_labels() 76 | .border_style(&BLACK) 77 | .draw()?; 78 | 79 | root.present().expect("Unable to write result to file"); 80 | println!("Result has been saved to {}", OUT_FILE_NAME); 81 | 82 | Ok(()) 83 | } 84 | -------------------------------------------------------------------------------- /27_fltk/python/fltk_ex.py: -------------------------------------------------------------------------------- 1 | from fltk import * 2 | import sys 3 | 4 | COUNTER = 0 5 | 6 | 7 | class Adder(Fl_Widget): 8 | def __new__(self): 9 | container = Fl_Pack(80, 50, 200, 20, "Adder Widget") 10 | button = Fl_Button(0, 0, 50, 20, "add 1") 11 | button.callback(self.add1) 12 | button2 = Fl_Button(0, 0, 50, 20, "add 2") 13 | button2.callback(self.add2) 14 | button3 = Fl_Button(0, 0, 80, 20, "subtract 3") 15 | button3.callback(self.sub3) 16 | container.end() 17 | container.type(FL_HORIZONTAL) 18 | 19 | container2 = Fl_Pack(80, 130, 200, 20, "file widget") 20 | button4 = Fl_Button(0, 0, 80, 20, "open file") 21 | button4.callback(self.open_file) 22 | container2.end() 23 | 24 | def add1(self): 25 | global COUNTER 26 | COUNTER += 1 27 | disp_frame.label(str(COUNTER)) 28 | 29 | def add2(self): 30 | global COUNTER 31 | COUNTER += 2 32 | disp_frame.label(str(COUNTER)) 33 | 34 | def sub3(self): 35 | global COUNTER 36 | COUNTER -= 3 37 | disp_frame.label(str(COUNTER)) 38 | 39 | def open_file(self): 40 | fc = Fl_File_Chooser(".", "*.rs", Fl_File_Chooser.SINGLE, "Choose File") 41 | fc.show() 42 | while fc.visible(): 43 | Fl.wait() 44 | self.filename = fc.value(1) 45 | 46 | 47 | class NoEscWindow(Fl_Window): 48 | def __init__(self, xpos, ypos, width, height, label): 49 | Fl_Window.__init__(self, xpos, ypos, width, height, label) 50 | 51 | def handle(self, ev): 52 | if ev == FL_SHORTCUT and Fl.event_key() == FL_Escape: 53 | return 1 54 | return Fl_Window.handle(self, ev) 55 | 56 | 57 | if __name__ == "__main__": 58 | win = NoEscWindow(200, 200, 300, 200, "Ordinal Events") 59 | adder = Adder() 60 | disp_frame = Fl_Box(0, 0, 200, 200, "0") 61 | win.end() 62 | win.show(len(sys.argv), sys.argv) 63 | Fl.run() 64 | -------------------------------------------------------------------------------- /27_fltk/rust/fltk_ex/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fltk_ex" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | fltk = "^1.0.18" 10 | num_enum = "0.5.3" 11 | -------------------------------------------------------------------------------- /27_fltk/rust/fltk_ex/src/main.rs: -------------------------------------------------------------------------------- 1 | use fltk::{ 2 | app, 3 | button::Button, 4 | enums::{Event, Key}, 5 | frame::Frame, 6 | group::{Pack, PackType}, 7 | prelude::*, 8 | window::Window, 9 | }; 10 | use num_enum::TryFromPrimitive; 11 | use std::cell::RefCell; 12 | use std::convert::TryFrom; 13 | use std::rc::Rc; 14 | 15 | #[derive(Debug, PartialEq, Eq, TryFromPrimitive)] 16 | #[repr(i32)] 17 | enum CustomEvents { 18 | AddOne = 41, // Values below 30 are reserved 19 | AddTwo, 20 | SubThree, 21 | OpenFile, 22 | } 23 | 24 | struct Adder {} 25 | 26 | impl Adder { 27 | pub fn new() -> Self { 28 | let mut container = Pack::new(80, 50, 200, 20, "Adder Widget"); 29 | let mut button = Button::new(0, 0, 50, 20, "add 1"); 30 | button.set_callback(move |_widg| { 31 | let _ = app::handle_main(CustomEvents::AddOne as i32); 32 | }); 33 | let mut button2 = Button::new(0, 0, 50, 20, "add 2"); 34 | button2.set_callback(move |_widg| { 35 | let _ = app::handle_main(CustomEvents::AddTwo as i32); 36 | }); 37 | let mut button3 = Button::new(0, 0, 80, 20, "subtract 3"); 38 | button3.set_callback(move |_widg| { 39 | let _ = app::handle_main(CustomEvents::SubThree as i32); 40 | }); 41 | container.end(); 42 | container.set_type(PackType::Horizontal); 43 | let mut container2 = Pack::new(80, 130, 200, 20, "File Widget"); 44 | let mut button4 = Button::new(0, 0, 80, 20, "open file"); 45 | button4.set_callback(move |_widg| { 46 | let _ = app::handle_main(CustomEvents::OpenFile as i32); 47 | }); 48 | container2.end(); 49 | container2.set_type(PackType::Horizontal); 50 | Adder {} 51 | } 52 | } 53 | 54 | struct MyWindow {} 55 | 56 | impl MyWindow { 57 | pub fn new() -> Self { 58 | let counter = Rc::from(RefCell::from(0)); 59 | 60 | let mut win = Window::new(200, 200, 300, 200, "Ordinal Events"); 61 | let mut disp_frame = Frame::new(200, 0, 200, 200, "0").center_of_parent(); 62 | let _adder = Adder::new(); 63 | 64 | let counter_cl = counter.clone(); 65 | 66 | disp_frame.handle(move |widg, ev| match CustomEvents::try_from(ev.bits()) { 67 | Ok(ce) => { 68 | dbg!("also handled event here"); 69 | match ce { 70 | CustomEvents::AddOne | CustomEvents::AddTwo | CustomEvents::SubThree => { 71 | widg.set_label(&*counter_cl.borrow_mut().to_string()); 72 | true 73 | } 74 | CustomEvents::OpenFile => true, 75 | } 76 | } 77 | Err(_) => false, 78 | }); 79 | 80 | win.end(); 81 | win.show(); 82 | 83 | win.handle(move |_widg, ev| { 84 | if ev == Event::Shortcut && app::event_key() == Key::Escape { 85 | dbg!("ignoring ESC key window-close"); 86 | return true; 87 | } 88 | match CustomEvents::try_from(ev.bits()) { 89 | Ok(ce) => { 90 | match ce { 91 | CustomEvents::AddOne => *counter.borrow_mut() += 1, 92 | CustomEvents::AddTwo => *counter.borrow_mut() += 2, 93 | CustomEvents::SubThree => *counter.borrow_mut() -= 3, 94 | CustomEvents::OpenFile => { 95 | let file = fltk::dialog::file_chooser("Choose File", "*.rs", ".", true) 96 | .unwrap(); 97 | dbg!(file); 98 | } 99 | } 100 | true 101 | } 102 | Err(_) => false, 103 | } 104 | }); 105 | 106 | MyWindow {} 107 | } 108 | } 109 | 110 | fn main() { 111 | let fltk_app = app::App::default(); 112 | let _ = MyWindow::new(); 113 | dbg!(CustomEvents::AddOne as i32); 114 | dbg!(CustomEvents::AddTwo as i32); 115 | dbg!(CustomEvents::SubThree as i32); 116 | fltk_app.run().unwrap(); 117 | } 118 | -------------------------------------------------------------------------------- /28_rusty_python/python/higher_order.py: -------------------------------------------------------------------------------- 1 | def HasColor(name, default=None, doc=None): 2 | propname = "__color_{}".format(name) 3 | colors = { 4 | "black": 0x00000000, 5 | "white": 0x00ffffff, 6 | "red": 0x00ff0000, 7 | "green": 0x0000ff00, 8 | "blue": 0x000000ff 9 | } 10 | 11 | def getter(self): 12 | return getattr(self, propname, default) 13 | 14 | def setter(self, value): 15 | if isinstance(value, int): 16 | if isinstance(value, bool): 17 | raise TypeError("integer colors must be ints") 18 | 19 | if value < 0 or value > 0x00ffffff: 20 | raise ValueError("integer colors must be 24-bit") 21 | 22 | setattr(self, propname, value) 23 | elif isinstance(value, str): 24 | if value not in colors: 25 | raise ValueError("unknown color '{}'".format(value)) 26 | 27 | setattr(self, propname, colors[value]) 28 | else: 29 | raise TypeError("color specifications must be ints or strs") 30 | 31 | class Inner: 32 | pass 33 | 34 | setattr(Inner, name, property(getter, setter, None, doc)) 35 | return Inner 36 | 37 | 38 | class Canvas(HasColor("foreground"), HasColor("background")): 39 | pass 40 | 41 | 42 | class Button(Canvas, HasColor("border"), HasColor("text")): 43 | pass 44 | 45 | 46 | if __name__ == "__main__": 47 | c = Canvas() 48 | c.foreground = 'red' 49 | 50 | b = Button() 51 | b.foreground = 'black' 52 | b.text = 'green' 53 | print(f"canvas fg: {c.foreground:06x}, button txt: {b.text:06X}, button fg: {b.foreground}") 54 | -------------------------------------------------------------------------------- /28_rusty_python/python/pattern_matching.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.10 2 | 3 | command = "bob key sword coin" 4 | 5 | class Character: 6 | def drop(self, what, where): 7 | print("dropping", what, "into", where) 8 | 9 | def pickup(self, what): 10 | print("pickup", what) 11 | 12 | character = Character() 13 | current_room = "bedroom" 14 | 15 | match command.split(): 16 | case ["drop", *objects]: 17 | for obj in objects: 18 | character.drop(obj, current_room) 19 | case ["pickup", *objects]: 20 | for obj in objects: 21 | character.pickup(obj) 22 | case ["test"]: 23 | print("unknown") 24 | -------------------------------------------------------------------------------- /28_rusty_python/python/type_hinting.py: -------------------------------------------------------------------------------- 1 | from typing import Iterator 2 | 3 | 4 | def fib(n: int) -> Iterator[int]: 5 | a, b = 0, 1 6 | while a < n: 7 | yield a 8 | a, b = b, a + b 9 | 10 | 11 | class BankAccount: 12 | def __init__(self, initial_balance: int = 0) -> None: 13 | self.balance = initial_balance 14 | 15 | def deposit(self, amount: int) -> None: 16 | self.balance += amount 17 | 18 | def withdraw(self, amount: int) -> None: 19 | self.balance -= amount 20 | 21 | def overdrawn(self) -> bool: 22 | return self.balance < 0 23 | 24 | 25 | if __name__ == "__main__": 26 | print(list(fib(10))) 27 | my_account = BankAccount(15) 28 | my_account.withdraw(5) 29 | print(my_account.balance) 30 | -------------------------------------------------------------------------------- /29_pattern_matching_revisited/python/cmd_split.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.10 2 | import sys 3 | 4 | def quit_game(): 5 | sys.exit(0) 6 | 7 | class Room: 8 | def __init__(self, objs=None): 9 | self.objects = objs 10 | if objs is None: 11 | self.objects = set(["banana", "chair", "piano"]) 12 | def describe(self): 13 | print("the room is dark and small, it contains", self.objects); 14 | def neighbor(self, direction): 15 | match direction: 16 | case "left": 17 | print("changed to room", direction) 18 | return Room(set(["knife", "bread", "butter"])) 19 | case "north": 20 | print("changed to room", direction) 21 | return Room(set(["polar-bear", "ice", "snow"])) 22 | case "right" |"front" |"back": 23 | print("No Room", direction) 24 | case _: 25 | print("unknown direction") 26 | return self 27 | 28 | class Character: 29 | def __init__(self): 30 | self.backpack = set() 31 | def take(self, obj, room): 32 | if obj in room.objects: 33 | self.backpack.add(obj) 34 | room.objects.remove(obj) 35 | else: 36 | print("not found", obj) 37 | 38 | def drop(self, obj, room): 39 | if obj in self.backpack: 40 | self.backpack.remove(obj) 41 | room.objects.add(obj) 42 | else: 43 | print("not in backpack", obj) 44 | 45 | 46 | if __name__ == "__main__": 47 | current_room = Room() 48 | character = Character() 49 | while True: 50 | command = input("What are you doing next? ") 51 | match command.split(): 52 | case ["quit"]: 53 | print("Goodbye!") 54 | quit_game() 55 | case ["look"]: 56 | current_room.describe() 57 | case ["look", "backpack"]: 58 | print("in backpack", character.backpack) 59 | case ["take", obj]: 60 | character.take(obj, current_room) 61 | case ["drop", *objects]: 62 | for obj in objects: 63 | character.drop(obj, current_room) 64 | case ["go", direction]: 65 | current_room = current_room.neighbor(direction) 66 | case ["go", ("north" | "south" | "east" | "west") as direction]: 67 | current_room = current_room.neighbor(direction) 68 | case ["go", chant] if chant in ["team", "wildcats"]: 69 | print(f"YEAH, GOOOOO {chant.upper()}!!") 70 | case _: 71 | print("didn't understand:", command) 72 | -------------------------------------------------------------------------------- /29_pattern_matching_revisited/python/match_obj.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.10 2 | from dataclasses import dataclass 3 | from enum import Enum 4 | 5 | class Button(Enum): 6 | LEFT = 0 7 | RIGHT = 1 8 | 9 | @dataclass 10 | class Click: 11 | position: tuple 12 | button: Button 13 | 14 | if __name__ == "__main__": 15 | events = [Button.LEFT, 16 | Click((2, 4), Button.LEFT), 17 | Click((32, 4), Button.RIGHT), 18 | {"text": "blah", "color": "blue"}, 19 | {"sleep": "long"}, 20 | {"sleep": 1.3}, 21 | Click((0, 4), Button.RIGHT), 22 | Click((0, 4), Button.LEFT), 23 | ] 24 | 25 | for event in events: 26 | match event: 27 | case Button.LEFT as b: 28 | print("button found", b) 29 | case Click((x, y), button=Button.RIGHT): 30 | print("right click", x, y) 31 | case Click((0, y)): 32 | print("clicked on x-axis y:", y) 33 | case Click((x, y)): 34 | print("Click", x, y) 35 | case {"text": message, "color": str(c)}: 36 | print("showing", message, "in color", c) 37 | case {"sleep": float(t)}: 38 | print(f"sleeping {t}secs") 39 | -------------------------------------------------------------------------------- /29_pattern_matching_revisited/rust/pattern/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pattern" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /29_pattern_matching_revisited/rust/pattern/examples/enum_dispatch.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | enum Button { 3 | Left, 4 | Right, 5 | } 6 | 7 | struct Click { 8 | position: (u16, u16), 9 | button: Button, 10 | } 11 | 12 | struct TextColor { 13 | text: String, 14 | color: String, 15 | } 16 | 17 | enum Event { 18 | Button(Button), 19 | Click(Click), 20 | TextColor(TextColor), 21 | SleepText { sleep: String }, 22 | Sleep { sleep: f64 }, 23 | } 24 | 25 | fn main() { 26 | let events = vec![ 27 | Event::Button(Button::Left), 28 | Event::Click(Click { 29 | position: (2, 4), 30 | button: Button::Left, 31 | }), 32 | Event::Click(Click { 33 | position: (32, 4), 34 | button: Button::Right, 35 | }), 36 | Event::TextColor(TextColor { 37 | text: "blah".to_string(), 38 | color: "blue".to_string(), 39 | }), 40 | Event::SleepText { 41 | sleep: "long".to_string(), 42 | }, 43 | Event::Sleep { sleep: 1.3 }, 44 | Event::Click(Click { 45 | position: (0, 4), 46 | button: Button::Right, 47 | }), 48 | Event::Click(Click { 49 | position: (0, 4), 50 | button: Button::Left, 51 | }), 52 | ]; 53 | 54 | for event in events { 55 | match event { 56 | Event::Button(b) => println!("button found {:?}", b), 57 | Event::Click(Click { 58 | position: (x, y), 59 | button: Button::Right, 60 | }) => println!("right click {} {}", x, y), 61 | Event::Click(Click { 62 | position: (0, y), 63 | button: _, 64 | }) => println!("clickend on x-axis y: {}", y), 65 | Event::Click(Click { 66 | position: (x, y), 67 | button: _, 68 | }) => println!("Click {} {}", x, y), 69 | Event::TextColor(TextColor { 70 | text: message, 71 | color, 72 | }) => println!("showing {} in color {}", message, color), 73 | Event::Sleep { sleep: t } => println!("sleeping {}secs", t), 74 | _ => continue, 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /29_pattern_matching_revisited/rust/pattern/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | use std::io::{self, BufRead, Write}; 3 | 4 | #[derive(Debug)] 5 | struct Room { 6 | objects: HashSet, 7 | } 8 | 9 | impl Room { 10 | fn new<'a>(iterable: impl std::iter::Iterator) -> Self { 11 | Self { 12 | objects: iterable.map(|a| a.to_owned()).collect(), 13 | } 14 | } 15 | 16 | fn describe(&self) { 17 | println!("the room is dark and small, it contains {:?}", self.objects); 18 | } 19 | 20 | fn neighbor(self, direction: &str) -> Self { 21 | match direction { 22 | "left" => { 23 | println!("changed to room {}", direction); 24 | Room::new(vec!["knife", "bread", "butter"].into_iter()) 25 | } 26 | "north" => { 27 | println!("changed to room {}", direction); 28 | Room::new(&mut ["polar-bear", "ice", "snow"].into_iter()) 29 | } 30 | "right" | "front" | "back" => { 31 | println!("No room to the {}", direction); 32 | self 33 | } 34 | _ => { 35 | println!("unknown direction {}", direction); 36 | self 37 | } 38 | } 39 | } 40 | } 41 | 42 | struct Character { 43 | backpack: HashSet, 44 | } 45 | 46 | impl Character { 47 | fn new() -> Self { 48 | Self { 49 | backpack: HashSet::new(), 50 | } 51 | } 52 | 53 | fn take(&mut self, obj: String, room: &mut Room) { 54 | if room.objects.contains(&obj) { 55 | room.objects.remove(&obj); 56 | self.backpack.insert(obj); 57 | } else { 58 | println!("not found {}", obj); 59 | } 60 | } 61 | 62 | fn drop(&mut self, obj: String, room: &mut Room) { 63 | if self.backpack.contains(&obj) { 64 | self.backpack.remove(&obj); 65 | room.objects.insert(obj); 66 | } else { 67 | println!("not in backpack {}", obj); 68 | } 69 | } 70 | } 71 | 72 | fn main() { 73 | let mut current_room = Room::new(vec!["banana", "chair", "piano"].into_iter()); 74 | let mut character = Character::new(); 75 | let valid_chants = vec!["team", "wildcats"]; 76 | 77 | let stdin = io::stdin(); 78 | loop { 79 | print!("What are you doing next? "); 80 | io::stdout().flush().unwrap(); 81 | let mut command = String::new(); 82 | stdin.lock().read_line(&mut command).unwrap(); 83 | let elems: Vec<&str> = command.split_whitespace().collect(); 84 | println!("{:?}", &elems); 85 | match &elems[..] { 86 | ["quit"] => { 87 | println!("Good bye!"); 88 | break; 89 | } 90 | ["look"] => current_room.describe(), 91 | ["look", "backpack"] => println!("in backpack {:?}", character.backpack), 92 | ["take", obj] => character.take(obj.to_string(), &mut current_room), 93 | ["drop", objects @ ..] => { 94 | for obj in objects { 95 | character.drop(obj.to_string(), &mut current_room); 96 | } 97 | } 98 | ["go", direction] => current_room = current_room.neighbor(direction), 99 | ["go", direction @ ("north" | "south" | "east" | "west")] => { 100 | current_room = current_room.neighbor(direction) 101 | } 102 | ["go", chant] if valid_chants.contains(chant) => { 103 | println!("YEAH, GOOOOO {}", chant.to_uppercase()) 104 | } 105 | _ => println!("dunno"), 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /2a_builder_pattern/python/default_args.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | class User: 4 | def __init__(self, uid, email, first_name=None, last_name=None): 5 | self.id = uid 6 | self.email = email 7 | self.first_name = first_name 8 | self.last_name = last_name 9 | 10 | def complete(self): 11 | return self.last_name is not None \ 12 | and self.id > 0 \ 13 | and not self.email.empty() \ 14 | and self.first_name is not None 15 | 16 | 17 | @dataclass 18 | class Channel: 19 | token: int = 0 20 | special_info: str = '' 21 | 22 | 23 | class ChannelBuilder: 24 | def __init__(self): 25 | self.token = 0 26 | self.special_info = '42' 27 | 28 | def build(self): 29 | return Channel(self.token, self.special_info) 30 | 31 | 32 | if __name__ == '__main__': 33 | bob = User(13, "bob@example.com") 34 | bob.first_name = "Bob" 35 | 36 | print("complete?", bob.complete()) 37 | print("bob_the_builder", bob) 38 | 39 | cb = ChannelBuilder() 40 | cb.special_info = "84" 41 | c1 = cb.build() 42 | c2 = Channel(4321) 43 | print(c1, c2) 44 | print(c1.token, c2.special_info) 45 | -------------------------------------------------------------------------------- /2a_builder_pattern/rust/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "builder" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | derive_builder = "0.10.2" 10 | -------------------------------------------------------------------------------- /2a_builder_pattern/rust/builder/src/main.rs: -------------------------------------------------------------------------------- 1 | use derive_builder::Builder; 2 | 3 | #[derive(Debug)] 4 | struct User { 5 | id: i32, 6 | email: String, 7 | first_name: Option, 8 | last_name: Option, 9 | } 10 | 11 | struct UserBuilder { 12 | id: i32, 13 | email: String, 14 | first_name: Option, 15 | last_name: Option, 16 | } 17 | 18 | impl UserBuilder { 19 | fn new(id: impl Into, email: impl Into) -> Self { 20 | Self { 21 | id: id.into(), 22 | email: email.into(), 23 | first_name: None, 24 | last_name: None, 25 | } 26 | } 27 | 28 | fn first_name(mut self, first_name: impl Into) -> Self { 29 | self.first_name = Some(first_name.into()); 30 | self 31 | } 32 | 33 | #[allow(dead_code)] 34 | fn last_name(mut self, last_name: impl Into) -> Self { 35 | self.last_name = Some(last_name.into()); 36 | self 37 | } 38 | 39 | fn build(self) -> User { 40 | let Self { 41 | id, 42 | email, 43 | first_name, 44 | last_name, 45 | } = self; 46 | User { 47 | id, 48 | email, 49 | first_name, 50 | last_name, 51 | } 52 | } 53 | } 54 | 55 | impl User { 56 | fn builder(id: impl Into, email: impl Into) -> UserBuilder { 57 | UserBuilder::new(id, email) 58 | } 59 | 60 | fn complete(&self) -> bool { 61 | self.last_name.is_some() 62 | && self.id > 0 63 | && !self.email.is_empty() 64 | && self.first_name.is_some() 65 | } 66 | } 67 | 68 | #[derive(Default, Builder, Debug)] 69 | #[builder(setter(into))] 70 | struct Channel { 71 | #[builder(default = "0")] 72 | token: i32, 73 | #[builder(default = r#""42".into()"#)] 74 | special_info: String, 75 | } 76 | 77 | fn main() -> Result<(), Box> { 78 | let bob = User::builder(13, "bob@example.com") 79 | .first_name("Bob") 80 | .build(); 81 | 82 | println!("complete? {}", bob.complete()); 83 | println!("bob_the_builder = {:#?}\n\n", bob); 84 | 85 | let c1 = ChannelBuilder::default() 86 | .special_info("84") 87 | .build() 88 | .unwrap(); 89 | let c2 = ChannelBuilder::default() 90 | .token(4321) 91 | .build()?; 92 | println!("{:?} {:?}", c1, c2); 93 | println!("{} {}", c1.token, c2.special_info); 94 | Ok(()) 95 | } 96 | -------------------------------------------------------------------------------- /2b_builder_type_state/python/typed_builder.py: -------------------------------------------------------------------------------- 1 | class User: 2 | @staticmethod 3 | def builder(): 4 | return UserBuilder() 5 | 6 | def __init__(self, uid, email, first_name, last_name): 7 | self.uid = uid 8 | self.email = email 9 | self.first_name = first_name 10 | self.last_name = last_name 11 | 12 | def __str__(self): 13 | return f"User (uid: {self.uid}, email: {self.email}, first_name: {self.first_name}, last_name: {self.last_name})" 14 | 15 | 16 | class UserBuilder: 17 | def id(self, uid): 18 | return UserBuilderHasId(uid) 19 | 20 | def email(self, email): 21 | return UserBuilderHasEmail(email) 22 | 23 | class UserBuilderHasId: 24 | def __init__(self, uid): 25 | self.uid = uid 26 | 27 | def email(self, email): 28 | return UserBuilderHasIdEmail(self.uid, email) 29 | 30 | class UserBuilderHasEmail: 31 | def __init__(self, email): 32 | self.email = email 33 | 34 | def id(self, uid): 35 | return UserBuilderHasIdEmail(uid, self.email) 36 | 37 | class UserBuilderHasIdEmail: 38 | def __init__(self, uid, email): 39 | self._uid = uid 40 | self._email = email 41 | self._first_name = None 42 | self._last_name = None 43 | 44 | def build(self): 45 | assert self._uid is not None 46 | assert self._email is not None 47 | return User(self._uid, self._email, self._first_name, self._last_name) 48 | 49 | def first_name(self, name): 50 | self._first_name = name 51 | return self 52 | 53 | def last_name(self, name): 54 | self._last_name = name 55 | return self 56 | 57 | if __name__ == "__main__": 58 | user = User.builder().id("42").email("bedroombuilds@example.com").first_name("Mike").build(); 59 | print(user) 60 | 61 | -------------------------------------------------------------------------------- /2b_builder_type_state/rust/email_builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "email_builder" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /2b_builder_type_state/rust/email_builder/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | 3 | #[derive(Debug)] 4 | struct Email { 5 | date: String, 6 | from: Vec, 7 | sender: Option, 8 | subject: Option, 9 | cc: Vec, 10 | bcc: Vec, 11 | body: String, 12 | } 13 | 14 | impl Email { 15 | fn builder() -> EmailBuilder { 16 | EmailBuilder::new() 17 | } 18 | 19 | fn send(&self) { 20 | dbg!(self); 21 | } 22 | } 23 | 24 | struct Date(String); 25 | struct NoDate; 26 | 27 | struct OneFrom(String); 28 | struct ManyFrom(Vec); 29 | struct NoFrom; 30 | 31 | struct NoCcBcc; 32 | struct Cc(Vec); 33 | struct Bcc(Vec); 34 | 35 | struct EmailBuilder { 36 | date: D, 37 | from: F, 38 | sender: Option, 39 | copies: C, 40 | subject: Option, 41 | body: Option, 42 | } 43 | 44 | impl EmailBuilder { 45 | fn new() -> Self { 46 | Self { 47 | date: NoDate, 48 | from: NoFrom, 49 | sender: None, 50 | copies: NoCcBcc, 51 | subject: None, 52 | body: None, 53 | } 54 | } 55 | } 56 | 57 | impl EmailBuilder { 58 | fn date(self, date: impl Into) -> EmailBuilder { 59 | let Self { 60 | from, 61 | sender, 62 | copies, 63 | subject, 64 | body, 65 | .. 66 | } = self; 67 | EmailBuilder { 68 | date: Date(date.into()), 69 | from, 70 | sender, 71 | copies, 72 | subject, 73 | body, 74 | } 75 | } 76 | } 77 | 78 | impl EmailBuilder { 79 | fn from(self, new_from: impl Into) -> EmailBuilder { 80 | let Self { 81 | date, 82 | sender, 83 | copies, 84 | subject, 85 | body, 86 | .. 87 | } = self; 88 | EmailBuilder { 89 | date, 90 | from: OneFrom(new_from.into()), 91 | sender, 92 | copies, 93 | subject, 94 | body, 95 | } 96 | } 97 | } 98 | 99 | impl EmailBuilder { 100 | fn from(self, new_from: impl Into) -> EmailBuilder { 101 | let Self { 102 | date, 103 | from: OneFrom(first_from), 104 | sender, 105 | copies, 106 | subject, 107 | body, 108 | } = self; 109 | let all_from = vec![first_from, new_from.into()]; 110 | EmailBuilder { 111 | date, 112 | from: ManyFrom(all_from), 113 | sender, 114 | copies, 115 | subject, 116 | body, 117 | } 118 | } 119 | 120 | fn cc(self, new_cc: impl Into) -> EmailBuilder { 121 | let Self { 122 | date, 123 | from, 124 | sender, 125 | copies, 126 | subject, 127 | body, 128 | } = self; 129 | EmailBuilder { 130 | date, 131 | from, 132 | sender, 133 | copies: Cc(vec![new_cc.into()]), 134 | subject, 135 | body, 136 | } 137 | } 138 | 139 | fn subject(mut self, subject: impl Into) -> Self { 140 | self.subject = Some(subject.into()); 141 | self 142 | } 143 | 144 | fn body(mut self, txt: impl Into) -> Self { 145 | self.body = Some(txt.into()); 146 | self 147 | } 148 | 149 | fn build(self) -> Email { 150 | let Self { 151 | date: Date(date), 152 | from: OneFrom(from), 153 | sender, 154 | copies, 155 | subject, 156 | body, 157 | } = self; 158 | let body = match body { 159 | Some(b) => b, 160 | None => "".to_owned(), 161 | }; 162 | Email { 163 | date, 164 | from: vec![from], 165 | sender, 166 | cc: vec![], 167 | bcc: vec![], 168 | subject, 169 | body, 170 | } 171 | } 172 | } 173 | 174 | impl EmailBuilder { 175 | fn sender(self, sender: impl Into) -> EmailBuilder { 176 | let Self { 177 | date, 178 | from, 179 | copies, 180 | subject, 181 | body, 182 | .. 183 | } = self; 184 | EmailBuilder { 185 | date, 186 | from, 187 | sender: Some(sender.into()), 188 | copies, 189 | subject, 190 | body, 191 | } 192 | } 193 | 194 | fn from(self, new_from: impl Into) -> EmailBuilder { 195 | let Self { 196 | date, 197 | from: ManyFrom(mut all_from), 198 | sender, 199 | copies, 200 | subject, 201 | body, 202 | } = self; 203 | all_from.push(new_from.into()); 204 | EmailBuilder { 205 | date, 206 | from: ManyFrom(all_from), 207 | sender, 208 | copies, 209 | subject, 210 | body, 211 | } 212 | } 213 | 214 | fn subject(mut self, subject: impl Into) -> Self { 215 | self.subject = Some(subject.into()); 216 | self 217 | } 218 | 219 | fn body(mut self, txt: impl Into) -> Self { 220 | self.body = Some(txt.into()); 221 | self 222 | } 223 | 224 | fn build(self) -> Email { 225 | let Self { 226 | date: Date(date), 227 | from: ManyFrom(from), 228 | sender, 229 | copies, 230 | subject, 231 | body, 232 | } = self; 233 | if let Some(ref sender) = sender { 234 | if !from.iter().any(|f| f == sender) { 235 | panic!("Sender must be an email found in From"); 236 | } 237 | } else { 238 | panic!("Sender header obligatory"); 239 | } 240 | let body = match body { 241 | Some(b) => b, 242 | None => "".to_owned(), 243 | }; 244 | Email { 245 | date, 246 | from, 247 | sender, 248 | cc: vec![], 249 | bcc: vec![], 250 | subject, 251 | body, 252 | } 253 | } 254 | } 255 | 256 | /// only copies branch for demonstration 257 | impl EmailBuilder { 258 | fn from(self, new_from: impl Into) -> EmailBuilder { 259 | let Self { 260 | date, 261 | from: OneFrom(first_from), 262 | sender, 263 | copies, 264 | subject, 265 | body, 266 | } = self; 267 | let all_from = vec![first_from, new_from.into()]; 268 | EmailBuilder { 269 | date, 270 | from: ManyFrom(all_from), 271 | sender, 272 | copies, 273 | subject, 274 | body, 275 | } 276 | } 277 | 278 | fn cc(self, new_cc: impl Into) -> EmailBuilder { 279 | let Self { 280 | date, 281 | from, 282 | sender, 283 | copies: Cc(mut copies), 284 | subject, 285 | body, 286 | } = self; 287 | copies.push(new_cc.into()); 288 | EmailBuilder { 289 | date, 290 | from, 291 | sender, 292 | copies: Cc(copies), 293 | subject, 294 | body, 295 | } 296 | } 297 | 298 | fn subject(mut self, subject: impl Into) -> Self { 299 | self.subject = Some(subject.into()); 300 | self 301 | } 302 | 303 | fn body(mut self, txt: impl Into) -> Self { 304 | self.body = Some(txt.into()); 305 | self 306 | } 307 | 308 | fn build(self) -> Email { 309 | let Self { 310 | date: Date(date), 311 | from: OneFrom(from), 312 | sender, 313 | copies: Cc(cc), 314 | subject, 315 | body, 316 | } = self; 317 | let body = match body { 318 | Some(b) => b, 319 | None => "".to_owned(), 320 | }; 321 | Email { 322 | date, 323 | from: vec![from], 324 | sender, 325 | cc, 326 | bcc: vec![], 327 | subject, 328 | body, 329 | } 330 | } 331 | } 332 | 333 | fn main() { 334 | let e = Email::builder() 335 | .from("one@example.com") 336 | .date("2022-04-01") 337 | .from("two@example.com") 338 | .sender("notfrom@example.com") 339 | .from("notfrom@example.com") 340 | .subject("Optionally usable") 341 | .body("Message Body") 342 | .build(); 343 | e.send(); 344 | // one from but with CC 345 | let e = Email::builder() 346 | .date("2022-04-01") 347 | .from("one@example.com") 348 | .cc("also.to@example.com") 349 | .subject("One copy") 350 | .body("Important message") 351 | .build(); 352 | e.send(); 353 | } 354 | -------------------------------------------------------------------------------- /2b_builder_type_state/rust/typed_builder_example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "typed_builder_example" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | typed-builder = "0.10.0" 10 | -------------------------------------------------------------------------------- /2b_builder_type_state/rust/typed_builder_example/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use typed_builder::TypedBuilder; 3 | 4 | #[derive(Debug, TypedBuilder)] 5 | struct User { 6 | id: String, 7 | email: String, 8 | #[builder(default)] 9 | first_name: Option, 10 | #[builder(default, setter(into, strip_option))] 11 | last_name: Option, 12 | } 13 | 14 | fn main() { 15 | let user = User::builder() 16 | .id("42".into()) 17 | //.email("bedroombuilds@example.com".into()) 18 | .first_name(Some("Bedroom".into())) 19 | //.last_name("Builds") 20 | .build(); 21 | dbg!(user); 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # From Python to Rust 2 | 3 | Source code for my bedroombuilds Youtube series introducing the Rust programming language to Python programmers. 4 | 5 | Episodes can be found on the YouTube Playlist: [From Python to Rust](https://www.youtube.com/playlist?list=PLEIv4NBmh-GsWGE9mY3sF9c5lgh5Z_jLr) 6 | --------------------------------------------------------------------------------