{"id":13476725,"url":"https://github.com/donbright/rust-lang-cheat-sheet","last_synced_at":"2026-03-02T06:02:17.316Z","repository":{"id":45243409,"uuid":"159932592","full_name":"donbright/rust-lang-cheat-sheet","owner":"donbright","description":"cheat sheet for rust language","archived":false,"fork":false,"pushed_at":"2023-12-24T17:55:52.000Z","size":830,"stargazers_count":284,"open_issues_count":0,"forks_count":45,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-11T08:38:40.752Z","etag":null,"topics":["cheatsheet","rust-lang"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/donbright.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-12-01T10:17:49.000Z","updated_at":"2025-10-03T13:10:41.000Z","dependencies_parsed_at":"2023-12-24T20:12:11.283Z","dependency_job_id":null,"html_url":"https://github.com/donbright/rust-lang-cheat-sheet","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/donbright/rust-lang-cheat-sheet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donbright%2Frust-lang-cheat-sheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donbright%2Frust-lang-cheat-sheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donbright%2Frust-lang-cheat-sheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donbright%2Frust-lang-cheat-sheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/donbright","download_url":"https://codeload.github.com/donbright/rust-lang-cheat-sheet/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donbright%2Frust-lang-cheat-sheet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29993540,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-02T01:47:34.672Z","status":"online","status_checked_at":"2026-03-02T02:00:07.342Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cheatsheet","rust-lang"],"created_at":"2024-07-31T16:01:33.868Z","updated_at":"2026-03-02T06:02:17.297Z","avatar_url":"https://github.com/donbright.png","language":null,"funding_links":[],"categories":["Others","JavaScript-based Frameworks:\u003ca name=\"frameworks\"\u003e\u003c/a\u003e"],"sub_categories":["Rust\u003ca name=\"2j\"\u003e\u003c/a\u003e"],"readme":"\n\n[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://stand-with-ukraine.pp.ua)\n\n\n## Singularity notice\n\nAs of 2023, 90+% of the stuff on this cheat-sheet you can figure out a lot faster by asking an AI, like ChatGPT. Ask it simply:\n\n     \"Please help me write a Rust function that takes a Vector of floating point numbers and returns an array of strings\" \n     \nThe LLM will spit out example code in two seconds, and then within three clicks you can copy/paste that code into \nplayground.rust-lang.org , hold down Control-Enter, and run it, and if there is an error, just copy/paste the entire\nerror message back into ChatGPT and it will tell you what the error was and how to fix it. You can easily adapt this\nto your own needs much faster than building up some example from a cheatsheet. \n\nNow if you want to learn more about something, its really easy to just ask the LLM \n\n     \"Could you please explain to me how Vectors and Strings in Rust work? What are they? Explain it to\n     me like im 10 years old, then again like I'm an undergrad with a background in C++\" \n     \nand it will just write several pages of explanation and simple examples just for you. This kind of \"Cheat Sheet\"\nis kind of becoming obsolete in the face of such technology.  \n\n## Warning\n\nThis cheat sheet is in a reasonably useful state for basic things, but it does contain many errors and typos and \npedagological mistakes of omission and ordering \u0026 etc. \n\nAlso note that Rust is still changing quite a bit in 2019-2022 so some of the below may be outdated/deprecated. \n\n## Rust in a Nutshell\n\n* Syntax tokens somewhat similar to C / C++ / Go\n* Ownership of memory enforced at build time\n* Statically linked\n* Not so Object-Orientish, tends to be Functional-ish\n* Control flow using pattern matching, Option+Result enums\n* Packages: 'cargo add' command, https://crates.io\n* Testing: 'cargo test' command, #[test] unit tests, integration tests\n* Concurrency: ownership, mutability, channels, mutex, crossbeam + Rayon packages\n* Auto formatter: 'rustfmt filename.rs' (see rust-lang.org for installation)\n* compiler engine: LLVM, no non-LLVM compilers yet\n* To use raw pointers, low level, call C/C++: unsafe{} keyword + ffi package\n* smart pointers and reference counted: Box, Rc, Arc\n* online playgrounds: https://play.rust-lang.org, https://tio.run/ \n* A survivial horror game where griefing is ... oops wrong Rust\n* Polymorphism: Traits, Trait Extensions, Trait Objects\n* Generic programming (a la C++ Templates): Generic Types\n  \n## Hello World\n\nSee https://www.rust-lang.org for installation details.\n\n```rust\nfn main() {\n    println!(\"Hello World\");\n}\n```\n\n```bash\n$ rustc main.rs   \n$ ./main\nHello World\n```\n\n## Hello Packages, Hello Tests, Hello Dependencies\n\n```bash\n$ rustup.sh         # install rust, see rust-lang.org for details\n$ cargo new myproj  # start new executable project under myproj path\n$ cd myproj         # cd into the new directory\n$ ls -lR            # list our skeleton of files\nsrc/main.rs         # main.rs, has main() entry point\nCargo.toml          # Cargo.toml defines packaging\n$ $EDITOR Cargo.toml  # add dependencies and other details\n[package]\nname = \"helloworld\"\nversion = \"0.1.0\"\nauthors = [\"ada astra \u003cada@astra.moon\u003e\"]\n\n[dependencies]\nserde = \"1.0.80\"\n# edit main.rs to say \"extern crate serde;\" and \"use serde::*;\"\n$ cargo add chrono # auto add dependency w/o wediting Cargo.toml\n# edit main.rs to say \"extern crate chrono;\" and \"use chrono::*;\"\n$ cargo build      # downloads dependencies + builds main.rs \n$ cargo run        # runs program created from main.rs\n$ cargo test       # runs tests (in parallel by default)\n$ cargo test -- --test-threads=1  # run tests one at a time\n$ cargo test -- --nocapture       # run tests, show output\n$ cargo run --example fundemo -- --arg # run example with arg (./examples subdir)\n$ cargo build --feature blargh     # build, enable the blargh feature of the crate\n```\n\n## Mutability basics\n\n```rust\nlet x = false;           // all variable bindings are immutable by default\nx = true; // err         // compile error. can't change a variable which has an immutable binding\nlet mut p = false;       // \"mut\" designates a binding as mutable\np = true;                // ok, a variable with mutable binding can change;\n```\n\n## types, variables, declarations, initialization\n```rust\nlet x: bool = false;    // let keyword\nlet k = false;          // rustc can determine some types automatically\nlet y: char = '上';     // all chars are 4 bytes\nlet 上 = 5; //err       // error. identifiers must be ASCII characters \nlet a: i8 = -2;         // 8 bit signed integers, also i16, i32, i64  \nlet b: u8 = 200;        // 8 bit unsigned integers, also u16, u32, u64\nlet n: f32 = 0.45;      // 32 bit float (automatcally converted+rounded from base-10 decimal to binary)\nlet n2 = 42.01f64;      // 64 bit float literal of the number 42.01 (approximately)\nlet r: [u8;3] = [3,4,5];          // array of 3 int, immutable, cannot grow or change values\nlet mut rm: [u8;3] = [3,4,5];     // same as r but mutable. cannot grow, but values can change.\nlet mut s1 = [0;500];             // array of 500 integers, each initialized to 0.\ns1[0..200].fill(7);               // set the first 200 integers to the value 7\ns1[400..].fill(5);                // set the last 100 integers to the value 5\nlet s2 = \u0026r[0..2];                // slice of array, s==\u0026[3,4]\nlet s3 = \u0026r[0..2][0];             // index into slice, s==3\nlet s4 = \u0026r[1..];                 // slice from index 1 to end\nlet s5 = \u0026r[..2];                 // slice from beginning to index 2\nlet mut u:Vec\u003cu8\u003e = Vec::new();   // create empty vector of unsigned 8 bit int, can grow\nlet mut v = vec![3,4,5];          // initialize mutable vector using vec! macro\nlet w = vec![1,12,13];            // vectors can be immutable too\nlet z = (0..999).collect::\u003cVec\u003cu32\u003e\u003e(); // init Vector from Range (0..999)\nu.push( 2 );                  // add item to vector\nv.rotate_right( 1 );          // in-place rotate of mutable vector [5,3,4]\nv.rotate_left( 1 );           // in-place rotate [3,4,5]\nlet s6 = \u0026mut v[1..];         // mutable slice, allows vector-like operations on a...\ns6.rotate_right( 1 );         // ...subslice of the vector [3,5,4] \nu.pop();                      // vectors can pop, return+remove last input (like a stack)\nv.contains(\u00263);               // true if vector contains value\nv.remove(1);                  // remove the nth item from a vector...\nv.append(u);                  // append v with u (u becomes empty ([]), both mutable)\nv.extend(w);                  // extend v with w (v owns w, w can be immutable)\nv.resize(200,0);              // make vector have 200 elements, set them to 0\nv.resize(4398046511104,0);    // memory allocation of 4398046511104 bytes failed. core dumped.\n                              // There is no malloc() style checking for success, Rust just crashes\nv[0..100].fill(7);            // set the first 100 elements in v to the value 7\nv[150..].fill(9);             // set the last 50 elements in v to the value 7\nv.fill(9);                    // set all elements of v to have the value 9\nlet x = \u0026w[1..];              // get a slice of a vector (a view into it's elements)\nprint(\"{:?}\",x);              // [12,13]; \nlet vs = v.len();             // length of vector\nlet (p,d,q) = (4,5,6);        // tuple() can assign multiple variables at once\nprint(\"{}\",p);                // you can use them alone after tuple assignment\nlet m = (4,5,\"a\");            // tuples can have multiple different types as elements\nlet (a,b) = m.1, m.3;         // tuple dereference with .1, .2, .3\nlet (c,d) = m.p, m.q; //err   // error, cannot index into a tuple using a variable\n\nlet s = String::from(\"上善若水 \"); // String is a heap variable. Strings are UTF8 encoded.\nlet s2 = \"水善利萬物而不爭\";       // \"\" literals are type \u0026str, different from String\nlet s3 = \u0026s;                    // \u0026 when prefixed to String gives \u0026str\nlet s4 = s2.to_string();        // create String from \u0026str\nlet s5 = format!(\"{}{}\",s2,s3); // concatenate \u0026str to \u0026str\nlet s6 = s + s2;                // concatenate String to \u0026str\nfor i in \"말 한마디에 천냥 빚을 갚는다\".split(\" \") {print!(\"{i}\");} // split \u0026str\ns.chars().nth(4);               // get nth char. \ns.get(2..).unwrap(); // ERROR   // get substring failed because 上 was 3 bytes\ns.get(3..).unwrap(); \t\t// 善若水\ns.trim();                       // 上善若水, no trailing space\ns.starts_with(\"上善\");          // true\ns.ends_with(\"水\");              // true\n\nlet i4 = s.find('水').unwrap_or(-1); // index of character (not always a byte offset, b/c utf8)\nlet hellomsg = r###\"                 // Multi-line \u0026str with embedded quotes\n \"Hello\" in Chinese is 你好 ('Ni Hao')\n \"Hello\" in Hindi is नमस्ते ('Namaste')\n\"###;\n\nlet x = vec![5,12,13];           // indices into slices/arrays/vectors must be of type usize\nlet y = 2 as u8;                 // using u8, u16, etc will not work\nprint!(\"{}\",x[y]);               // error[E0277]: the type `[{integer}]` cannot be indexed by `u8`\nlet z = 2 as usize;              // usize is the pointer size. used in loops, vector length, etc\nprint!(\"{}\",x[z]);               // ok.   there is also \"isize\" if usize needs to be signed\n\nconst BILBOG: i32 = 10;         // constant\nstatic ORGOG: \u0026str = \"zormpf\";  // static, global-ish variable\nstatic FOOBY: i32 = 5;          // statics are only mutable inside unsafe{} blocks. \nstatic Z_ERRMSG : [\u0026str;2] = [\"need input\",\"need more input\"]; // static strings\n\ntype Valid = bool;              // typedef ( make your own type names ) \n\nlet mut v = vec![1u8,2u8,3u8];  // determine the type of expression expr by looking at rustc error\nprintln!(\"{}\",v.iter_mut());    // for example, if we want to know the type of v, build an error\nprintln!(\"{}\",v.iter_mut());    // type of v.iter_mut() is std::slice::IterMut\u003c'_, u8\u003e`\n ```\n\n\n## Operators\n\n```rust\n1 + 2 - 3 * 4 / 5  // arithmetic add, minus, multiply, divide\n7 % 5              // modulo (remainder)\n\u0026 | ^              // bitwise and, or, xor\n\u003c\u003c \u003e\u003e              // leftshift, rightshift, will crash on overflow\n// note that in C, overflowing \u003c\u003c is actually undefined. \n// Rust has multiple versions, each defined. \nlet a:u8 = 0b10110011; // print!(\"{:08b}\",a); // 0b10110011 padded binary output \na.rotate_left(1)    // 01100111 circular bit rotation, out of left -\u003e in at right\na.wrapping_shl(1)   // 01100110 this destroys the left-most bits that would cause overflow\na.overflowing_shl(1)// 01100110,false returns tuple (value,did it overflow the number type)  \na.rotate_right(4)   // 11011001 circular bit rotation to the right\n!a                  // 01001100 bitwise not\na == b != c \u003c d \u003c= e \u003e f \u003e= g  // logical comparison\na \u0026\u0026 b || c ! d    // logical boolean, and, or, not\n\nlet a = 5;         // pointer + dereference example\nlet b = \u0026a;        // \u0026a is 'address of a' in computers memory\nlet c = *b;        // *b is contents of memory at address in b (dereference)\nprint(\"{c}\");     // 5\n\noverloading: see struct\n```\n\n## Run time errors, Crashing, panic, except, unwrap, Option, Result\n\n```rust\npanic!(\"oops\");             // panic!() instantly crashes program\nlet v = vec![3,4,5];\nlet a = v[0];               // ok, normal lookup, a is 3\nlet b = v[12];              // will call panic! at runtime, v[12] doesn't exist\n```\n\n```bash\n$ export RUST_BACKTRACE=1\n$ cargo run    # will tell you exact line where panic occured, with call stack trace\n```\n\n### Option - a type for functions that may return Some thing, or None thing \n\n```rust\nlet v = vec![3,4,5];        // create Vector with three elements. then try to get() the element at index 12. \nlet c = v.get(12);          // there is no element at index 12, but this will not crash, get returns an Option\nprint!(\"{:?}\",v.get(12));   // prints the word \"None\", since there is no 12th element in v\nprint!(\"{:?}\",v.get(0));    // prints the word \"Some(3)\", because there is an element at index 0\n                            // Options have a value of either None, or Some(item), i.e. they are \"Enums\"\nlet e = v.get(0).unwrap();  // ok, 'unwrap' the Option returned by get(0), e is now 3\nlet d = v.get(12).unwrap(); // this crashes. 'unwrap' of a None Option will call panic!\nlet f = v.get(5).unwrap_or(\u00260); // unwrap_or gives a value if get() is None. f = 0\n```\nOption and Match - a control flow similar to **if else** but with more error checking at compile time\n```\nlet x = v.get(12);\nmatch x { Some(x)=\u003eprintln!(\"OK! {x}\"),  // print OK if v has 13th item\n\t  None=\u003eprintln!(\"sad face\"), }   // otherwise print sad face\n// you will get a compile-time error if you forget to handle both Some and None\n```\n\n### Result - a type like Option but with Ok() and Err() instead of Some() and None. \n\n```rust\n\nmatch std::env::var(\"SHLVL\") {  // env::var() returns a std::result::Result(\u003cT,E\u003e) enum type. \n\tOk(v)=\u003eprintln!(\"SHLVL = {v:?}\"), // if OK, std::env returns value of Environment variable\n\tErr(e)=\u003eprintln!(\"error message: {:?}\",e.to_string()) }; // if not, error message\n\nnote there is also std::io::Result used a lot in file operations. \n\n```\n\n**If Let** - A control statemnt like match but with a no-op for None or Err() \n\n```rust\n\nif let Some(x) = v.get(12) { println(\"OK! {x}\"); } \n// we don't have to type out a handler for None. it does nothing. \n\nif let Ok(x) = std::env::var(\"SHLVL\") { println!(\"SHLVL = {x:?}\"); }\n// if the Result is Err, then nothing is done. \n```\n\nOption in particular can prevent the use of null pointers, preventing crashes one might see in C/C++.\nSay we are keeping tack of Owls, we know each Owls name, but not necessarily their last location.\n\t\n```rust\nstruct Owl { name: String, \n\tlast_location: Option\u003cString\u003e  }   // in C++ location might be a *char which could init as NULL \n\nlet owls = [Owl{name:\"Opv\".to_string(),last_location:None},\n            Owl{name:\"Marty\".to_string(),last_location:Some(\"Barn\".to_string())}];\n\nfor owl in \u0026owls {\n\tmatch \u0026owl.last_location {\n\t\tNone=\u003eprintln!(\"Owl named {} - location is not being tracked\",owl.name),\n\t\tSome(loc)=\u003eprintln!(\"Owl named {} - last known location was {}\",owl.name,loc),\n}}\n// note that we did not have to check for null pointers, nor derefernece any\n// pointer. if we forgot to check for None, the compiler would give an error at compile time.\n// there are no null-related runtime errors possible.\n\n```\n\nNote that there are no Exceptions. Panic/Option/Result/multi-value-return are used instead. \n\n## Printing\n\n```rust\nprintln!(\"Hello, 你好, नमस्ते, Привет, ᎣᏏᏲ\");    // unicode text is OK \nprint!(\"Hi, is {}x{}={} ?\",6,9,42);           // curly braces {} get replaced by arguments\nHi, is 7x9=42 ?\nlet (meepo,beepo) = (5,6);                    // print variables without using arguments..\nprint!(\"{meepo}:{beepo}\");                    // .. by putting the names inside {}\n\nlet v = vec![1,2,3];\nprintln!( \"v[0] from {:?} = {}\", v, v[0] )    // {:?} can print lots of special types\nprintln!(\"{:02x?}\",v);                        // {:02x?} can print 2 digit hex of vector\nlet s = format!( \"x coord={}\", p.X )          // print to string \ns2 := fmt.Sprintf( \"{e}\", 17.0 )              // another way to print to string\nuse std::fmt::Write;                          // yet another way - like C++ stringstream\nlet mut s3 = String::new();                   // String implements fmt::Write so we can\nmatch writeln!(s3,\"Hello There\") {            // write to a String like a file.\n   Ok(_)=\u003e(), Err(e)=\u003eprintln!(\"error writing to string {} {:?}\",s3,e),} \nwriteln!(s3,\"Hello Too\").unwrap_or(());       // the concise version w/o any error msg\n\n// C / printf style formatted output: \nprintln!(\"hex:{:x} bin:{:b} sci:{:e}\",17,17,17.0); // hexadecimal, binary, etc. \n//   \"hex:11 bin:10001 sci:1.7e1\"\n// Pad with zeros: \nprintln!(\"dec:{:#04} hex:{:#06x} bin:{:08b} sci:{:09e}\",17,17,17,17.0); \n//   \"dec:0017 hex:0x0011 bin:00010001 sci:00001.7e1\"\nprintln!(\" {:.40} \", 1.0f32/3.0f32 );  // print 40 digits of precision for floating point\n//   \"0.3333333432674407958984375000000000000000\" \nprintln!(\" {:\u003e4} {:\u003e4} \", 232, 8 );    // pad as columns, width 4 spaces, align right\n//   \" 232    8\"\nlet mut s=String::new();               // build string, concatenate over lines \ns.push_str(\u0026format!(\"{} {} \",1,2));\ns.push_str(\u0026format!(\"{} {}\\n\",3,4));    // \"1 2 3 4\\n\"\nlet mut s2=String::new();              // alternate version, same goal  \nwrite!(s2,\"{} {}\",1,2).unwrap_or(()); \nwriteln!(s2,\"{} {}\",3,4).unwrap_or(()); // \"1 2 3 4\\n\"\n\nprintln!(\"\\u{2766}\");                  // ❦  unicode floral heart, character hex 2766 \n\n// derive Debug can make your own structs, enums, and unions printable by {:?}\n#[derive(Debug)]\nstruct Wheel{radius:i8}                \nprintln!(\"{:?}\",vec![Wheel{radius:4},Wheel{radius:3},Wheel{radius:2}]);\n// [Wheel { radius: 4 }, Wheel { radius: 3 }, Wheel { radius: 2 }]\n\n// If you want to customize your debug output, you can implement Debug yourself\nuse std::fmt;\nstruct Wheel{radius:i8}     \nimpl std::fmt::Debug for Wheel {\n  fn fmt(\u0026self, f: \u0026mut fmt::Formatter)-\u003efmt::Result{\n    write!(f, \"輪:徑[{}]\", self.radius)\n}}\nprintln!(\"{:?}\",vec![Wheel{radius:4},Wheel{radius:3},Wheel{radius:2}]);\n// [輪:徑[4], 輪:徑[3], 輪:徑[2]]\n\n// fmt::Display makes your own structs and enums printable with ordinary {} symbol\nimpl std::fmt::Display for Wheel{\n  fn fmt(\u0026self, f: \u0026mut fmt::Formatter)-\u003efmt::Result{\n    write!(f, \"W[{}]\", self.radius)\n   }\n}\n\n// Display for enums\npub enum Apple{PinkLady,HoneyCrisp}  \nimpl std::fmt::Display for Apple {\n    fn fmt(\u0026self, f: \u0026mut fmt::Formatter) -\u003e fmt::Result {\n        match self { Apple::PinkLady=\u003ewrite!(f, \"Ap:PLad\"),\n                     Apple::HoneyCrisp=\u003ewrite!(f, \"Ap:HonCr\"),\n\t\t     }\n    }\n}\n```\n\n### loop, for, while\n```rust\n\nfor i in 0..10 {print!(\"{},\",x)};          // 0,1,2,3,4,5,6,7,8,9\nfor i in 0..10.rev() {print!(\"{},\",x)};    // 9,8,7,6,5,4,3,2,1,0\nfor i in (0..10).step_by(2) {print!(\"{},\",x)};              // 0 2 4 6 8 \nfor i in (0..10).skip(1).step_by(2) {print!(\"{},\",x)};      // 1 3 5 7 9\nfor i in (0..10).rev().step_by(2){print!(\"{},\",x)};         // 9 7 5 3 1 \nfor i in (0..=10).rev().step_by(2){print!(\"{},\",x)};        // 10 8 6 4 2 0 \nfor i in (0..=10).step_by(2){print!(\"{},\",x)}     ;         // 0 2 4 6 8 10 \nfor i in (0..9).rev().step_by(2){print!(\"{},\",x)} ;         // 8 6 4 2 0 \nfor i in (0..9).step_by(2){print!(\"{},\",x)}       ;         // 0 2 4 6 8 \nfor i in (0..10).cycle().skip(5).take(10){print!(\"{},\",x)}  // 5 6 7 8 9 0 1 2 3 4 \n\nlet v = vec![3,5,7];\nfor n in v { println!(\"{}\",n) }             // for loop over vector\n\nfor (i, n) in v.iter().enumerate() {        // iterate with (index, item) tuple \n\tprintln!(\"{},{} \", i, n);}          // 0,3 \\n 1,5 \\n 2,7\n\nlet mut i = 0;\t\t\t\t    // while loop\nwhile i \u003c 10 {print!(\"{}\",i); i += 2;}      // 0 2 4 6 8\nlet mut j:u8 = 9;                           \nwhile j \u003e 0 {print!(\"{}\",j); j -= 2;}       // 9 7 5 3 1 Panic! j is unsigned but goes below 0 \n\nlet mut i = 0;                              // loop\nloop { i=i+1; if i\u003c10 { break; } };\t    // plain loop, exit with break;\nlet x = loop { i=i+1; if i\u003e=10 {break i;} } // loop that returns value, x = 10\n```\n\nIterators as an alternative to loops\n\n```rust\nlet v = vec![3,5,7,11];                    // vector to iterate\nv.iter().for_each(|x| print!(\"{} \",x));    // for_each over iterator, 3 5 7 11\nprint!(\"{}\",v.iter().fold(0,|a,i| a+i));   // adds 0+1+2+3, prints 6. \n// for more info , see iterators/functional section below\n```\n\n```rust\n// While Let, can be used in situations where we expect Option::Some() for several iterations,\n// but we expect a Option::None() to be at the end of the iterations. For example:\nlet mut x = (0..12).filter(|x| x%2==0);          // x is an iterator\nwhile let Some(i) = x.next() {print!(\"{}:\",i);}  // While loop over the iterator\n// 0:2:4:6:8:10:   // prints the even numbers between 0 and 12\n```\n\n## Parallel processing\n\n```rust\nextern crate rayon;\nuse rayon::prelude::*;\n\nfn main() {\n    let mut v = Vec::new();  // create a vector of floats, to multiply each by 0.9\n    for i in 0..1024*1280 { v.push(i as f32); }\n    v.iter_mut().for_each(     |x| *x = *x * 0.9 ); // single thread version \n    v.par_iter_mut().for_each( |x| *x = *x * 0.9 ); // multiple threads version\n    \n    let v = (0..999).collect::\u003cVec\u003cu32\u003e\u003e(); // par_iter is slightly different\n    let tot = v.par_iter().map(|i|i*i).reduce(||0,|a,x|a+x); // parallel sum of squares\n    // see https://docs.rs/rayon/latest/rayon/iter/trait.ParallelIterator.html#method.fold\n    // for info on fold, reduce, map, etc, in Rayon\n    \n    very_slow_function1(); // two single threaded functions that take a long time\n    very_slow_function2(); \n    \n    rayon::join( || very_slow_function1()    // run them in parallel if appropriate\n    \t\t || very_slow_function2() );\n    \n    s = \"VeryLargeString ...pretend goes on for 10Mb \"; // imagine 10Mb string\n    s.chars().par_iter().do_stuff() // error // par_iter() cant work on string because\n                                  // it doesnt know where to cut the byte boundaries\n    let v = s.iter().collect::\u003cVec\u003cchar\u003e\u003e9); // so convert to vector of char each 4 bytes\n    v.par_iter().map(|ch| ch.to_ascii_lowercase()).do_stuff() // now you can\n\t\t \n}\n```\n\n```bash\n$ cargo add rayon  # add rayon dependency\n$ cargo run        # installs rayon, runs program\n```\n\n```rust \nchannels: todo\nmutex: todo\nconcurrency: todo\n```\n\n## Smart pointers\n\nBox is a smart pointer. It is not possible to become null or to point to invalid memory.\n\nAs an example, consider a tree data structure. In C you might have nodes that have\npointers to child nodes, and then at the leaf nodes , the child node pointers are NULL. \n\nIn Rust, the nodes have Boxed pointers to child nodes. The Boxes are all wrapped with an Option.\nSo if there is no child, the Option is None. If there is a child, it is Some(Box(childnode)) \n\n```rust\nstruct Node { data: char, leftchild: Option\u003cBox\u003cNode\u003e\u003e, rightchild: Option\u003cBox\u003cNode\u003e\u003e }\nlet mut x = Node{data:'x',leftchild:None,rightchild:None};\nlet y = Node{data:'y',leftchild:None,rightchild:None};\nlet z = Node{data:'z',leftchild:None,rightchild:None};\n(x.leftchild,x.rightchild) = (Some(Box::new(y)),Some(Box::new(z)));\n// Node { data: 'x', \n//        leftchild: Some(Node { data: 'y', leftchild: None, rightchild: None }), \n//        rightchild: Some(Node { data: 'z', leftchild: None, rightchild: None }) }\n```\n\nAnother way is to use Enum variants for the different node types, then you dont\neven need to use Option at all. Each node is actually a different Variant so the leaf\nnodes do not even have children they only have data, while the inner branch nodes have\nchildren but do not have data.\n\nSee below section on \"Enums - not like C\" for more on how Enums work in Rust. \n\n```rust\nenum Node { Branch(Box\u003cNode\u003e,Box\u003cNode\u003e), Leaf(char) }\nlet y = Node::Leaf('y');\nlet z = Node::Leaf('z');\nlet x = Node::Branch(Box::new(y),Box::new(z));\n// print!(\"{:?}\",x); // Branch(Leaf('y'), Leaf('z'))\n```\n\nhttps://doc.rust-lang.org/std/boxed/index.html\n\nhttps://rosettacode.org/wiki/Huffman_coding#Rust\n\nArc, RC - reference counted pointers. Todo\n\n## Functions and closures\n```rust\nfn add( a:i8, b:i8 ) -\u003e i32 { b + a }     // 'return' keyword optional\nfn getcodes(a:i8)-\u003e(i8,i32){ (9,a*99) }   // multi return via tuples\nlet (x, s) = getcodes( 3, 56 );           // assign multi-return w tuples\nfn multy(a:i8,b:i8=5)-\u003ei16{a*b}   //error // Rust has no default parameters.\nfn multy(a:i8,b:Option\u003ci8\u003e)-\u003ei16 {        // but you can fake it with Option unwrap_or\n  a * b.unwrap_or(5) }                    // unwrap_or(x) means x is the default value\nfn main(){ print!(\"{}\",multy(3,None));}   // pass None to the func, result here=15\nfm main(){ print!(\"{}\",multy(3,Some(4));} // awkward, tho, as normal calls require Some()\nfn f(t:i8) {                              // nesting functions is OK\n  fn g(u:i8) { u*5 };                     // g nested inside f\n  let a = t + g(2);  }                    // g can be called from inside f\nfn f2(t:i8) {             // however, nested functs cannot access outside variables \n  let mut m = 2;          // m is declared outside the scope of g2 block\n  fn g2(u:i8){u*5 + m};}  // error[E0434]: can't capture dynamic environment in a fn item\nfn f(t:i8) {\n  struct W{a:int}; t+1 }  // structs can be declared inside functions too\n\n// function pointers\nfn addtwo(t:i8)-\u003ei8{t+2}; // simple function, adds 2 to argument. \nprintln!(\"{}\",addtwo(5)); // prints 7\nlet fp = addtwo;          // fp = function pointer to addtwo function\nprintln!(\"{}\",fp(5));     // now we can call fp() just like we called addtwo\nfn f\u003cF\u003e(fp: F) where F: Fn(i8)-\u003ei8 { println!(\"{}\",fp(1)) } \n// 'where F:Fn' lets us build a function that can accept another function as an argument\nf(fp);  // call function f, passing a pointer to the 'addtwo' function. result=3\n\ntype ZFillCallback = fn(bottom:u32,top:u32)-\u003eu32;  // typedef of a function\n\nfn maximum(t:i8,...) {} // error, can't have variable number of arguments.\n                        // only macros! can be Variadic in Rust (see below)\n\n// closures\nlet c = |x| x + 2;    // define a closure, which is kinda like a lambda function\nlet a = c(5);         // closures can be called, like functions. result = 7\nlet value = 5;        // a closure can also read values outside its scope\nlet d = |x| value + x;// d(n) will now add 'value' to any input n. (in this case,5) \nfn f\u003cF\u003e(fp: F) where F: Fn(i8)-\u003ei8 { println!(\"{}\",fp(1)) }  // f takes a function as an argument \nf(c);                 // a closure can be passed, like a function pointer, result = 3\nf(|x| x * value);     // and a closure can be anonymous, without a name. result = 5\n\nfor i in 0..4.filter(|x| x\u003e1) // anonymous closures are used often with iterators (see below) \nprint!(\"{} \",i)               // 2 3  (0 1 2 3 filtered to only values greater than 1)\n\n\n```\n\n## Unit tests, integration tests\n\nUnit tests, placed in the same file as the code being tested\n\n```rust\n./src/lib.rs:\n\npub fn process(v:\u0026mut Vec\u003cu8\u003e)-\u003e\u0026Vec\u003cu8\u003e{ v.update(|x| f(x)) } // main function called by users\nfn f(x:u8)-\u003eu8 { x*x }   // small piece of our code, to test in unit testing\n\n#[cfg(test)]        // cfg -\u003e section will only compiled during 'cargo test'\nmod tests {         // namespace helper\n    use super::*;   // bring in our functions above\n    #[test]         // next function will be a single test\n    fn test_f() { assert!(f(4)==16); } // test f() by itself (unit)\n}\n```\n\nIntegration tests, for overall crate, lives under ./tests/*.rs\n\n```rust\n./tests/file.rs:         // will only be built dring 'cargo test'\nextern crate mypackage;  // include package we are testing\n#test                    // treat next function as a test\nfn bigtest() {           // not a unit test. instead, test overall code\n\tlet mut d = vec![1,2,3];               // set up some typical data users would have\n\tlet expected_results = vec![1,4,9];    // some results we expect\n\tassert!(process(d)==expected_results); // test what a user would typically call, process()\n}\n```\n\n```bash\n$ cargo test           # test build, will include cfg(test) sections\n-\u003e test_f passed       # cargo reports on passed tests\n-\u003e test_bigtest failed # cargo reports on failed tests\n```\n\n## Documentation\n\nrust-doc and cargo doc allow automatic building of html documentation\nfor code. precede documentation of your code with three slashmarks\ninstead of the normal two slashmarks, like so:\n\n```rust\n/// blorg() returns the blorgification of input x\n/// # Details\n/// this code implements the krishnamurthi procedure\n/// for blimfication of zorgonautic primes \n/// # Arguments\n/// * `x` - typically a square number\n/// # Safety\n/// Cannot panic unless x overflows u64\n/// # Example\n///     let n = blorg(36); \nfn blorg(x:u64)-\u003eu64 {\n   x+x*x\n}\n```\n\nThen run rust-doc or cargo doc and view the result.\n\n```bash\n$ cargo doc\n$ firefox target/doc/cratename/index.html\n```\n\nGood examples of the results are on https://crates.io\n\n## If, conditionals, patterns, match, control flow\n\n```rust\n\nlet oz = ounces_in_recipe();\n\n// normal if else, like C, Pascal, etc\nif oz == 1 {\n\tprint!(\"1 ounce\")\n} else if oz == 8 {\n\tprint!(\"1 cup\")\n} else if oz == 16 {\n\tprint!(\"1 pint\")\n} else if oz == 128 {\n\tprint!(\"1 gallon\")\n} else {\n\tprint!(\"non-unit # of ounces\");\n}\n\nmatch oz { // match, like case, works on literals not variables\n\t1 =\u003e print!(\"1 ounce\"),  // \"=\u003e\" signifies a branch or leg of the match\n\t8 =\u003e print!(\"1 cup\"),    // have as many=\u003e legs as you want\n\t16 =\u003e print!(\"1 pint\"),    // end each leg with a comma ,\n\t128 =\u003e print!(\"1 gallon\"),\n\t_ =\u003e print!(\"non-unit # of ounces\") // underscore _ will match anything not previously matched\n}\n\n // match can work on enums too, if you want to limit what values a variable can be assigned\npub enum UnitVolume{Cup,Pint,Gallon}\n\nlet ozv = UnitVolume::Cup;\n\nmatch ozv {           \n\tUnitVolume::Cup =\u003e print!(\"cup\"),    // \"=\u003e\" signifies a branch or leg of the match\n\tUnitVolume::Pint =\u003e print!(\"pint\"),    // have as many=\u003e legs as you want\n\tUnitVolume::Gallon =\u003e print!(\"gallon\"),    // end each leg with a comma ,\n        // don't need underscore match-arm with Enums, it knows its complete\n}\n\nlet x = [1i8,2i8];                    // match patterns can be structs, enums, arrays, etc\nlet y = match x {                     // match can 'return a result' to y\n        [1,0] =\u003e \"1,0\",               // match a specific array\n        [2,0]|[4,0] =\u003e \"2,0 or 4,0\",  // |, binary or, can be used in patterns\n        [_,2] =\u003e \"ends with 2\",       // [_,2] will match [0,2] [1,2] [2,2], [3,2], etc\n        _ =\u003e \"other\"\n};\nprintln!(\"{}\",y);                     // \"ends with 2\"\n\n\nlet m = 3;\t \t\t     // match patterns can only be constant, but you can\nlet n = 4;                           // do similar things with \"match guard\", an if statement \nlet y = match (n,m) {                // which is inside of a =\u003e arm. First, we match tuple (n,m)\n        (0,0) =\u003e \"ok\",               //  this leg matches any tuple with first element 0, return ok\n        (3,_) if m%5==0 =\u003e \"ok\",     //  this leg matches when first element=3, and second divisible by 5\n\t(_,_) if m%3==0 =\u003e \"ok\",     //  this leg matches any tuple where the second element is divisble by 3\n        _ =\u003e \"stop\",                 //  this leg matches anything else. \n};\n\nlet hour = get_24hr_time();          // patterns can be integer ranges (x..=y)\nampm = match hour {                  // however it has to be inclusive \n\t0..=11 =\u003e \"am\"               // 1..11 is not ok, 1..=11 is ok.\n\t12..=23 =\u003e \"pm\"          \n\t_=\u003e \"unknown\"            \n};\n\nlet x = 5i32;                          // we can use the match value in match arms,\nlet y = match x-1 {                    // this is also called \"binding with @\", like so:\n\t0..=9 =\u003e 7,                    // since x is 5, x-1 is 4 and 4 is in 0..=9, so y=7 \n\tm @ 10..=19 =\u003e m*2,            // if x-1 was 14, m becomes 14, so y would be 28\n\t_=\u003e -1,                        // if x-1 was \u003e=20, y would become -1\n};\n\nlet mut v = vec![0;4096];                // match also works with Result\u003c\u003e\nmatch File::open(\"/dev/random\") {     \n\tOk(f)=\u003ef.read(\u0026v),\n\tErr(why)=\u003eprintln!(\"file open failed, {}\",why),\n}\n\nlet v = vec![1,2,3];\t\t\t// match works with Option too\nlet n = 1;\nmatch v.get(n) {\n\tSome(x) =\u003e println!(\"nth item of v is {}\",x),\n\tNone =\u003e println!(\"v has no nth item for n={}\",n),\n};\n\n```\n\nSee also: While let, if let. \n\n## Ownership, Borrowing, References, Lifetimes\n\nResources have exactly one owner. They can be 'moved' from one owner to another.\n \n```rust\n// stack memory, no moves, only copies\nlet a = 5;\nlet b = a;  // ok\nlet c = a;  // ok\n\n// heap memory\nlet a = String::new(); \nlet b = a;  // 'move' of ownership from a to b\nlet c = a;  // error. cannot \"move\" a again, b already owns it\n\n// heap memory + function call\nlet a = String::new();\nlet b = a;  // 'move' of ownership from a to b\nfn f(t:String) { } // function takes ownership of the variable passed as t\nf(a); // error. f(a) would move a into f(), but a was already moved into b\n```\n\nBorrowing is an alternative to moving. It is done with References \u0026 (memory addresses)\n\n```rust\n// heap memory, using borrows and references instead of moves\nlet a = String::from(\"☪☯ॐ✡γ⚕✝\");\nlet b = \u0026a;  // this is borrowing, not moving, a to b\nlet c = \u0026a;  // it is OK to have more than one borrower of non-mutable variables\nprintln!(\"{}\",a);    // ☪☯ॐ✡γ⚕✝\nprintln!(\"{:p}\",\u0026a); // 0x7ffcffb6b278\nprintln!(\"{:p}\",b);  // 0x7ffcffb6b278  // b and c hold the address of a\nprintln!(\"{:p}\",c);  // 0x7ffcffb6b278\nprintln!(\"{:p}\",\u0026b); // 0x7ffcffb6b290  // b and c are distinct variables\nprintln!(\"{:p}\",\u0026c); // 0x7ffcffb6b298  // with their own addresses\n```\n\nHowever borrowing has special rules regarding mutability. \n\nIn a block, only one of these statements can be true for a given resource R\n* The program has one or more immutable references to R\n* The program has exactly one mutable reference to R \n\n```rust\n\n// example error[E0502]: cannot borrow `a` as mutable because `a` is also borrowed as immutable\nlet mut a = 5;\nlet b = \u0026a;\nlet c = \u0026mut a;\n\n// example error[E0499]: cannot borrow `a` as mutable more than once at a time\nlet mut a = 5;\nlet b = \u0026mut a;\nlet c = \u0026mut a;\n\n```\nAnother way to think about it is Shared vs Exclusive\n* A plain old \u0026 borrow is a Shared Reference, since multiple people can share at once\n* A \u0026mut reference is an Exclusive reference, only one can have it.  \n\nLifetime in Rust: Resources are destroyed, (their heap memory is freed), at the end of a 'scope'. Their owners are also destroyed. That is the point of ownership - so that resources won't be accessed after they are destroyed, which is the source of a huge number of errors in C programs.\n\nBorrowed resources are not destroyed when the borrowed reference itself goes out of scope. However the borrow cannot \"outlive\" the destruction of the original resource nor it's owner.\n\nTake, for example, the case where we borrow a variable via ```\u0026```. The borrow has a lifetime that is determined by where it is declared. As a result, the borrow is valid as long as it ends before the lender is destroyed. However, the scope of the borrow is determined by where the reference is used.\n\n```rust \nfn main() { // main block starts \n    let i = 3; // Lifetime for `i` starts. ────────────────┐\n    //                                                     │\n    { // new block starts                                  │\n        let borrow1 = \u0026i; // `borrow1` lifetime starts. ──┐│\n        //                                                ││\n        println!(\"borrow1: {}\", borrow1); //              ││\n    } // block for `borrow1 ends. ─────────-──────────────┘│\n    //                                                     │\n    //                                                     │\n    { // new block starts                                  │\n        let borrow2 = \u0026i; // `borrow2` lifetime starts. ──┐│\n        //                                                ││\n        println!(\"borrow2: {}\", borrow2); //              ││\n    } // block for `borrow2` ends. ───────────────────────┘│\n    //                                                     │\n}   // main block ends, so does Lifetime ends. ────────────┘\n\n```\n\n\n## Structs\n\n```rust\nstruct Wheel{ r:i8, s:i8};  // basic struct, like C, pascal, etc. r = radius, s = number of spokes \nstruct badWheel{ mut r: i8, mut h: i8, }; // error, mut keyword doesnt work inside struct\nlet w = Wheel{r:5,s:7};   // new wheel, radius 5, spokes 7, immutable binding\nw.r = 6; // error, cannot mutably borrow field of immutable binding\nlet mut mw = Wheel{r:5,s:7}; //  new mutable wheel. fields inherit mutability of struct;\nmw.r = 6;  // ok\n\nimpl Wheel {              // impl -\u003e implement methods for struct, kinda like a C++ class\n        fn new(r: isize) -\u003e Wheel { Wheel { r:r, s:4 } }  // our own default\n        fn dump(    \u0026self) { println!(\"{} {}\",self.r,self.s); }  // immutable self\n\tfn badgrow(    \u0026self) { self.s += 4; } // error, cannot mutably borrow field of immutable binding\n        fn  okgrow(\u0026mut self) { self.s += 4; } // ok, mutable self\n};\nw.dump();    // ok , w is immutable, self inside dump() is immutable\nw.okgrow();  // error, w is immutable, self inside okgrow() is mutable\n             //  cannot borrow immutable local variable `w` as mutable\nmw.dump();   // ok, mw is mutable, self inside dump is immutable.  \nmw.okgrow(); // ok, mw is mutable, self inside grow() is mutable.\n\n#[derive(Default,Copy,Clone,Debug,PartialEq)] // automatic implementations \nstruct Moo {x:u8,y:u8,z:u8,}\nlet m1:Moo=Default::default();            // Default, x=0 y=0 z=0\nlet m2:Moo=Moo{x:3,..Default::default()}; // Default, x=3 y=0 z=0\nlet (mut n,mut k)=(M{x:-1,y:-1,z:-1},Default::default());\nn=k;                          // Copy\nvec![M{x:0,y:1,z:2};42];      // Clone\nprintln!(\"{:?}\",n);           // Debug, formatter\nif n==k {println!(\"hi\");};    // PartialEq, operator overloading \n\n// customized operator overloading\nimpl PartialEq for Wheel{ fn eq(\u0026self,o:\u0026Wheel)-\u003ebool {self.r==o.r\u0026\u0026self.s==o.s} }\nif mw == w { print!(\"equal wheels\"); }\n\n// default values for members of struct\n#[derive(Debug,Default)]\nstruct Wheel1{ r:i8, s:i8};\nprintln!(\"{:?}\",Wheel1{..Default::default()});        // Wheel1 { r: 0, s: 0 } \n\n// custom default values for members of struct\n#[derive(Debug)]\nstruct Wheel2{ r:i8, s:i8};\nimpl Default for Wheel2 { fn default() -\u003e Wheel2{Wheel2 { r: 8, s: 8 }}  }\nprintln!(\"{:?}\",Wheel2{..Default::default()});        // Wheel2 { r: 8, s: 8 } \nprintln!(\"{:?}\",Wheel2{r:10,..Default::default()});   // Wheel2 { r: 10, s: 8 }\n\n#[derive(Debug)]                       // Initialize one struct from another\nstruct Apple {color:(u8,u8,u8),price:f32};  \nlet a = Apple{color:(100,0,0),price:0.2};\nlet b = Apple{color:(9,12,38),..a };      // this is called \"struct update\"\n\n```\n\nStructs with function pointers as members\n\n```\nstruct ThingDoer {\n    name: String,\n    do_thing: fn(x:\u0026Vec\u003cu8\u003e) -\u003e u8,\n}\nfn baseball(v:\u0026Vec\u003cu8\u003e)-\u003eu8{ 42 }\nfn main (){\n    let adder = ThingDoer{name:\"addthing\".to_string(), do_thing:|n| n.iter().fold(0,|a,b|a+b)};\n    let multer = ThingDoer{name:\"multhing\".to_string(), do_thing:|n| n.iter().fold(1,|a,b|a*b)};\n    let nother = ThingDoer{name:\"nothing\".to_string(), do_thing:|n|baseball(\u0026n)};\n    let (f1,f2,f3) = (adder.do_thing,multer.do_thing,nother.do_thing);\n    let v = vec![1,2,3,4];\n    println!(\"{} {} {}\",f1(\u0026v),f2(\u0026v),f3(\u0026v));\n}\n```\n\n\n## Enums - not like C\n\nEnums in Rust do more than Enums in C/C++. They are actually more like \nTagged Unions or ADT / Algebraic Data Types from Functional programming languages.\nOther places call them Sum Types\n\n```rust\nenum Fruit { Apple, Banana, Pear }\nlet x = call_some_function( Fruit::Apple );  \nenum Errs { ErrOK = 3, ErrFile = 5, ErrFire = 12 } // custom Discriminats (integers)\nenum Planet { Earth = 3, Mars, Jupiter } // mars will be 4, Jupiter 5. \n\nenum Blorg {     // enums can have different types as members\n Flarg(u8),\n Blarg(u32),\n Norg(String),\n Florg(bool)\n}\n\nlet x = Blorg::Flarg(1); // enums can be detected with a match\nmatch x {\n    Blorg::Flarg(1) =\u003e println!(\"x is a Flarg with value of 1!\"),\n    Blorg::Flarg(_) =\u003e println!(\"x is a Flarg with non-1 value\"),\n    Blorg::Norg(_) =\u003e println!(\"x is a Norg\"),\n    _ =\u003e println!(\"neither Flarg nor Norg\"),\n}\n\n// Enums can also derive traits\n#[derive(Clone,Debug,PartialEq)]  // cannot derive Default on enum\nenum ColorMapData {\n    OneByteColors(Vec\u003cu8\u003e),\n    FourByteColors(Vec\u003cu32\u003e),\n}\n\n// Enums can also have methods / functions, using impl\n// the key is that inside the function, pattern matching is used\n// to determine which variant of the Enum the function receives\nimpl ColorMapData {\n  fn description(\u0026self)-\u003eString {\n    let (numcolors,numbytes) = match self {\n      ColorMapData::OneByteColors(x) =\u003e (x.len(),\"1\"),\n      ColorMapData::FourByteColors(x) =\u003e (x.len(),\"4\"),\n    };\n    format!(\"ColorMap with {} colors, {} bytes per color\",numcolors,numbytes)\n}}\n\n// functions can take Enum as arguments\nfn examinecm( c:ColorMapData ) { println!(\"{}\",c.description()); }\nlet ca = ColorMapData::FourByteColors(vec![0xFFAA32FFu32,0x00AA0011,0x0000AA00]);\nlet cb = ColorMapData::OneByteColors(vec![0,1,3,9,16]);\nexaminecm(ca);\n// ColorMap with 3 colors, 4 bytes per color\nexaminecm(cb);\n// ColorMap with 5 colors, 1 bytes per color\n```\n\nUsing strum, a reflection package, you can iterate an enum's values\n\n```\n$ cargo add strum strum_macros\nuse strum::IntoEnumIterator;  \n#[derive(Debug, strum_macros::EnumIter)]\nenum Tofu { Smooth, Firm, ExtraFirm }\nTofu::iter().for_each(|d|print!(\"{d:?},\")); // Smooth,Firm,ExtraFirm\n```\n\n## Collections, Key-value pairs, Sets\n\nHashMap, aka associative array / key-value store / map \n\n```rust\nuse std::collections::{HashMap};\nlet mut m = HashMap\u003cchar,i32\u003e::new();   \nm.insert('a', 1);                   // key is 'a', value is 1\nlet b = m[\u0026'a'];                    // [] lookup, this crashes at runtime if 'a' is not in map\nlet c = m.get(\u0026'a').unwrap_or(\u0026-1); // .get(), c == -1 if a is not in map. no crash.\nmatch m.get(\u0026'a') {                 // deal with map get() lookup using Match + Option\n    Some(x)=\u003eprintln!(\"a found in map, value is {}\",x),\n    None=\u003eprintln!(\"a not found in map\"),\n}\nif let Some(x) = m.get(\u0026'a') {     // deal with map get() lookup using if let + Option\n    println!(\"a found in map, value is {}\",x);\n}  // if 'a' is not in map, do nothing\n\n*m.get_mut(\u0026'a').unwrap() += 2;  // change a value inside a map\n\n```\n\nConcise initialization with from and from_iter using tuples of (key,value)\n\n```rust\nlet mut phonecodes = HashMap::from(  // from uses a fixed size array\n  [(\"Afghanistan\",93),(\"American Samoa\",1),(\"Ukraine\",380)]   );\nlet mut squares:HashMap\u003cu32,u32\u003e = HashMap::from_iter(\n  (0..24).map(|i| (i, i*i))   );     // from_iter uses an iterator\nprintln!(\"{:?}\",phonecodes); //{\"Afghanistan: 93, Ukraine: 380...\nprintln!(\"{:?}\",squares); //{10: 100, 3: 9, 1: 1, 13: 169, ...\n```\n\nHashSet\n\n```rust\nuse std::collections::HashSet;\nlet mut squares = HashSet::new();\nsquares.insert(0);\nsquares.insert(4);\nlet b = squares.contains(\u00264);   // b==true\n```\n\n## Macros\n\nDoes not act like a preprocessor. It replaces items in the abstract syntax tree\n\n```rust\nmacro_rules! hello {\n    ($a:ident) =\u003e ($a = 5)\n}\nlet mut a = 0;\nprintln!(\"{}\",a); // 0\nhello!(a);\nprintln!(\"{}\",a); // 5\n    \nmacro_rules! bellana {\n    ($a:expr,$b:expr) =\u003e ($a + $b)\n}\nprintln!(\"{:?}\",bellana!(5,(9*2))); // 23\n\nmacro_rules! maximum {   \n    ($x:expr) =\u003e ($x);\n    ($x:expr, $($y:expr),+) =\u003e ( std::cmp::max($x, maximum!($($y),+)) )\n}\nmaximum!(1,2,3,4);   // 4\n\nmacro_rules! dlog {\n    ($loglevel:expr, $($s:expr),*) =\u003e (\n        if DLOG_LEVEL\u003e=$loglevel { println!($($s),+); }\n    )\n}\nlet DLOG_LEVEL=5;\ndlog!(4,\"program is running, dlog:{}\",DLOG_LEVEL);  // \"program is running, dlog:5\"\n\n/*\ndesignators: \nblock   // rust block, like {}.        expr    // expressions\nident   // variable/function names.    item    // \npat     // pattern.                    path    // rust path\nstmt    // statement.                  tt      // token tree\nty      // type.                       vis     // visibility qualifier\n*/\n```\n\n\n\n\n## Arrays, Slices, Ranges\n\nArrays\n\n```rust\nlet arr: [u8; 4] = [1, 2, 3, 4]; // immutable array. cant change size.\nlet mut arrm: [u8; 4] = [1,2,3,4]; // mutable array. cant change size.\nlet n = arr.len();     // length of array = 4 items \nlet s1 = \u0026arr[0..2];   // slice of underlying array\nlet n2 = s1.len();     // length of slice = 2 items\nprintln!(\"{:?}\",s1);   // 1 2, contents of slice\nlet s2 = \u0026arr[1..];    // slice until end\nprintln!(\"{:?}\",s2);   // 2 3 4 contents of slice until end\nlet sm = \u0026mut arrm[0..2];  // mutable slice\nsm[0] = 11;                // change element of mutable slice,\nprintln!(\"{:?}\",sm);       // 11 2 3 4  \n                           // underlying array was changed\nprintln!(\"{:?}\",arrm);     // 11 2 3 4 \n\nlet z = [1,6,1,8,0,0,3];\nprintln!(\"{:?}\",z[0..4]);   // error - not a slice\n^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time\nprintln!(\"{:?}\",\u0026z[0..4]);  // OK to take a slice   \n// 1,6,1,8\n\n// pass array slice to function\nfn dostuff(x:\u0026mut [u8]) {\n\tx[0] = 5;\n\tprintln!(\"{:?}  {}\",x,x.len()); // 5 2 3 4   4\n}\n\nfn main() {\n\tlet mut arr: [u8; 4] = [1, 2, 3, 4];\n\tdostuff( \u0026mut arr );\n}\n\n```\n\nGet(), a byte index into a UTF8 String\n\n```rust\nlet sa = String::from(\"a\"); // get() - byte index slice from a String\nlet sga = sa.get(0..1); // Some(\"a\"). get returns Option, but not a Option\u003cchar\u003e \nlet s = String::from(\"上善若水\"); // get() with a UTF8 String where char.len()!=1\nlet sg0 = s.get(0..0);  // Some(\"\") , the empty string.\nlet sg1 = s.get(0..1);  // None, because the first byte of 上 is not a utf8 char\nlet sg2 = s.get(0..2);  // None, same reason\nlet sg3 = s.get(0..3);  // Some(\"上\"), this works because 上 in utf8 is 3 bytes\nlet sg4 = s.get(0..4);  // None again, because we now have 上 + 1 other byte\n// see 上 at http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=4E0A\n```\n\n## Split_At_Mut - Mutability and References into a Vector\n\nFor the special case for getting references to items within a vector:\n\nImagine we have three Wheels (struct W) with radius (W.r) and they are inside\na vector v. We start with wheels of radius 3,4,5 and want to change \nit to be radiuses of 2, 4, 8.\n\n```rust\n    #[derive(Debug)]\n    struct W{ r:u32 }       // wheel struct\n    let mut v = vec![W{r:3},W{r:4},W{r:5}];   // vector of structs\n    let wheela = \u0026mut v[0];      // mutable reference to Wheel with radius 3\n    let wheelb = \u0026mut v[2];      // compile error! two mutables for one variable!\n    //  error[E0499]: cannot borrow `v` as mutable more than once at a time\n    wheela.r = 2;  // nope\n    wheelb.r = 8;  // nope\n```\nThe borrow checker treats the entire vector as one gigantic variable, so\nyou can't edit part of it with a mutable reference and then edit another part,\nbecause the parts aren't considered parts. They are considered as if you are\nediting the variable v. \n\nBut there is a workaround built into the language. It is called..\n\nsplit_at_mut\n\nIt can create mutable slices, which allow mutable access to the vector.\n\n```rust\n     #[derive(Debug)]\n    struct W{ r:u32 }       // wheel struct\n    let mut v = vec![W{r:3},W{r:4},W{r:5}];   // vector of structs\n    let (l, r) = v.split_at_mut(2);  // split after the wheel with r4\n    let wheela = \u0026mut l[0];  // first item of left part of split\n    let wheelb = \u0026mut r[0];  // first item of right part of split\n    wheela.r = 2;       // no problem\n    wheelb.r = 8;       // no problem\n    println!(\"{:?} {:?}\",l,r); // [W { r: 2 }, W { r: 4 }] [W { r: 8 }]\n    println!(\"{:?}\",v); // [W { r: 2 }, W { r: 4 }, W { r: 8 }]\n```\n\n## Object-Oriented alternatives\n\nInheritance and Polymorphism - Rust doesn't have the object-oriented style of these things. Alternatives:\n\n- \"composition\" (struct within struct),\n- Traits (sort of like Interfaces), \n- Enums (which can do much more than C enums, they are more like Tagged Unions aka Algebraic Data Types aka Sum Types)\n- \"NewType\" pattern, aka Tuple Structs where for example you say struct MyWrapper(u32) to wrap u32 and then impl your own methods on MyWrapper to mimic u32, along with derive_more and implement deref (u32 could be any other struct or type from another external crate).\n- todo - describe Dynamic Trait Objects \n- todo - describe Generics\n\n## Files\n\n```rust\nuse std::fs::File;         // File handling module\nuse std::io::{Write,Read}  // read and write capabilities for File\nuse std::fs::OpenOptions;  // specialized version of File\n\n// read file, non-crashing example\nlet filename = \"test.txt\";\nmatch File::open(filename) {\n\tErr(why) =\u003e println!(\"failed to open file '{}': {}\", filename, why),\n        Ok(mut f) =\u003e {\n        \tprintln!(\"ok, opened {}\",filename);\n                let mut data = String::new();\n                match f.read_to_string( \u0026mut data ) {\n                \tErr(why) =\u003e println!(\"failed to read {}, {}\",filename,why),\n                        Ok(n) =\u003e println!(\"read {} bytes\",n),\n                };\n\t},\n}\n\n// crash-on-error examples ( unwrap() calls panic! on error, crashes the program )\nlet mut s = String::new();\nFile::open(\"test.txt\").unwrap().read_to_string(\u0026mut s).unwrap();    // read into s\nFile::create(\"output.txt\").unwrap().write(s.to_bytes()).unwrap();   // write string\nf = File::create(\"output.txt\").unwrap();                            // create if doesnt exist\nf = OpenOptions::new().write(true).truncate(true).create(true).open(\"out.txt\").unwrap();       // create if doesnt exist\nf = OpenOptions::new().append(true).open(\"out.txt\").unwrap();       // append\nf = OpenOptions::new().append(true).create(true).open(\"out.txt\").unwrap(); // append + create\nwrite!(f,\"{}\",s).unwrap(); // write formatted string, given file object f\n\nlet mut v = vec![];                                                 // read binary data, vec of u8\nf = File::open(\"test.bin\").unwrap().read_to_end(\u0026mut v);            // without using buffering\n\nuse std::io::{self,BufRead};  // read from stdin aka standard input\nlet line = io::stdin().lock().lines().next().unwrap().unwrap();\n\nlet x = include!(\"datafile.txt\"); // include external data file, example: vec![0,0,0];\n\n// handle errors inside a io::Result-returning function with the question mark ?\nfn readfunc()  -\u003e std::io::Result\u003c()\u003e {\n  let mut tmpbuf = vec![0u8;4096];\n  let mut f = File::open(\"somefile.bin\")?;   // instead of unwrap, just return error\n  let count = f.read( \u0026mut tmpbuf )?;        // instead of match, just return error\n  Ok(())                                     // we got this far, so there's no error\n}\n\n// read binary data in a loop to a buffer\nfn readfunc2()  -\u003e std::io::Result\u003c()\u003e {\n  let mut tmpbuf = vec![0u8;4096];\n  let mut f = File::open(\"somefile.bin\")?;   \n  loop {\n    let numbytes_read = f.read( \u0026mut tmpbuf )?; \n    println!(\"read data {}\",numbytes_read);\n    if numbytes_read==0 { break Ok(()); }\n  } \n}\n\n// same loop as above, but with While Let\nfn readfunc3()  -\u003e std::io::Result\u003c()\u003e {\n  let mut tmpbuf = vec![0u8;4096];\n  let mut f = File::open(\"somefile.bin\")?;   \n  while let numbytes_read = f.read( \u0026mut tmpbuf )? {\n    println!(\"read # bytes: {}\",numbytes_read);\n    if numbytes_read==0 { break; }\n  };\n  Ok(())\n}\n\n\n// Passing File to function... \npub fn zipread( mut rd:\u0026File )  { let x = rd.read(\u0026[buf])?; println!(\"{}\",x); }\n// .. or... pass any struct with read trait \npub fn zipread( mut rd:impl Read )  { let x = rd.read(\u0026[buf])?; println!(\"{}\",x); }\n\n// File position\n// note this here is a u64 so y'all with a exabyte of data gone hafta finda workaroun'\n// also for some reason f has to be mutable if you do this. \nuse std::io::Seek;\nprintln!(\"{:?}\",f.stream_position()); \n\n// there is no 'close', files close automatically at the end of scope ( \"}\" )\n\n```\n\n### Filesystem\n\n```rust\nuse std::fs;\nmatch std::fs::copy( \"file.txt\", \"newfile.txt\") {\n\tOk =\u003e println!(\"copy successfull\"),\n\tErr(why) =\u003e println!(\"copy failed\"),\n}\nstd::fs::remove_file(\"newfile.txt\").unwrap(); // panic if failure\n\n```\n\n## System, arguments to main(), environment variables\n\n```rust\nstd::env::args().for_each(|x| print!(\"{} \",x)); // main arguments as iterator, print each one \nfor arg in std::env::args().collect::\u003cVec\u003cString\u003e\u003e() { print!(\"{} \",arg); }; // same, as vector\nif std::env::args().any(|x| x==\"--help\") {help()};            // if called with --help, run help()\nlet progname = std::env::args().nth(0)  // first argument. but this wont compile! its an Option()\nlet progname = std::env::args().nth(0).unwrap_or(\"yr system is very broken\".to_string()); \n// on most systems, first argument = program name. but args is not guaranteed to exist, its an iterator\n// that could be empty. so we can use unwrap_or() to deal with the Option if no arguments are there\n```\n\n### clap - command line argument parser\n\n    # if you want your program 'mycompiler' to have args like this:\n    mycompiler input.txt -o binary.exe -optimize -I./include -I/usr/include\n    # install clap crate: \n    cargo add clap --features derive   # bash command to add clap dependency\n \n```rust\nmycompiler.rs:\nextern crate clap;\n// clap will parse the struct and automatically handle errors,\n// detect the argument type based on the variable (Vec,Option,bool)\n// with Option for optional args, no Option for Requred args, Vec for\n// multiple args, bool for flag style args, etc. clap will also\n// automatically provide --verison and --help using /// comments\n#[derive(clap::Parser, Debug)]\npub struct Args {\n    /// inputfile - filename to compile \n    inputfile: String,   \n    \n    /// outfile - filename for binary output\n    #[arg(short = 'o', long)]\n    outfile: Option(String), \n    \n    /// paths to search for header files\n    #[arg(short = 'I', long)]\n    include: Vec\u003cString\u003e,\n\n    /// use the optimizer during compilation\n    #[arg(short='O', long)]\n    optimize: bool       \n}\n\nfn main() {\n    let clapargs = Args::parse_from(std::env::args.clone());\n    println!(\"{:?}\",clapargs);\n    let mut output = \"a.out\";\n    if let Some(outname) = clapargs.outfile.as_deref() { output = outname};\n    if let Some(input) = clapargs.inputfile.as_deref() {\n\tcompile(input,output,clapargs.optimize);\n    } \n}\n\n```\n\n### Environment variables\n```rust\nstd::env::var(\"IGNORE_CASE\")  // environment variable IGNORE_CASE, returns Result or Err\nif let Ok(v) = std::env::var(\"SHLVL\") {println!(\"{:?}\",v);} // print SHLVL if it's there, otherwise ignore\nlet sl = match std::env::var(\"SHLVL\") { Ok(v)=\u003ev,Err(e)=\u003e\"not set\".to_string() }; // set s1 to SHLVL or \"not set\" if unset\nprintln!(\"{:?}\",std::env::vars().collect::\u003cVec\u003c(String,String)\u003e\u003e()); // print all environment variables\nfor v in std::env::vars() {println!(\"{:?}\",v);}  // print env vars line by line\n```\n\n\n## Reflection\n\nFor enums:\n```\nuse strum::IntoEnumIterator;  \n#[derive(strum_macros::EnumIter)]\nenum Attachment { Avoidant, Anxious, Secure };\nAttachment::iter().for_each(|d|print!(\"{d:?},\")); // Avoidant, Anxious, Secure\n```\n\nFor others: todo\n\n## Traits\n\ntodo. Traits are like 'interfaces' in other languages.\nYou can see examples above where a Struct will Derive the Debug trait\nso that gives it certain abilities. Traits are used extensively\nwhen dealing with iterators, see below. \n\n## Iterators, functional style programming\n\n```rust\nlet v = vec![3,4,5];\nlet it = v.iter(); // iterator as object\nprintln!(\"{:?} {:?} {:?}\",it.next(),it.next(),it.next()); // consumed\nprintln!(\"{:?}\",it.next()); // None\n\nlet v = vec![3];\nlet mut i = v.iter().peekable();\nprintln!(\"{:?}\",i.peek());  // Some(3)\nprintln!(\"{:?}\",i.peek());  // Some(3)\nprintln!(\"{:?}\",i.next());  // 3\nprintln!(\"{:?}\",i.next());  // None\n\nlet mut i = v.iter();\nprint!(\"{:?}\",i.collect::\u003cVec\u003c_\u003e\u003e(); // iterator back to vector \n\n// basic iteration\nfor i in v.iter() {print!(\"{i} \");} // 3 4 5 \nvec![3,4,5].iter().for_each(|x| print!(\"{x} \")); // 3 4 5\nlet biggest = v.iter().max();        // 5\nlet hasle2 = v.iter().any(|x| x\u003c=4); // true if any element is less than or equal to 2\nlet biggest = v[0..1].iter().max();  // will return 4, not 5, b/c we took a slice of the vector\nfor i in vec![3,4,5].iter().take(2) {print(\"{i}\");} // 3, 4\nfor (i,n) in vec![3,4,5].iter().enumerate() {print!(\"{i}:{n} \");} // 0:3 1:4 2:5\nvec![3,4,5,3].iter().find(|\u0026\u0026x| x == 3) // Some(\u00263), first three\nvec![3,4,5].iter().position(|\u0026\u0026x| x == 5) // 2 // kind of like indexOf() in other langs\n\n// combine multiple iterators\n(3..=5).chain(9..=11).for_each(|i|print!(\"{i:?} \")); // 3 4 5 9 10 11\n(3..=5).zip(9..=11).for_each(|i|print!(\"{i:?} \")); // (3, 9) (4, 10) (5, 11) \n\n// skipping elements\nfor i in v.iter().step_by(2) {print!(\"{i} \");} // 3 5 vec![\nfor i in vec![3,4,5].iter().skip(1) {print(\"{i}\");} // 4, 5\nprint!(\"{:?}\",vec![3,4,5].into_iter().map(|x| 2 * x).collect::\u003cVec\u003cu8\u003e\u003e()); // 6 8 10\nfor i in vec![3,4,5].iter().filter(|x| x\u003c=4) {print!(\"{i}\");} // 3 4\nfor i in vec![Some(3),None,Some(4)].iter().fuse() {print!(\"{i}\");} // Some(3), None\nvec![4,5,3,3].iter().skip_while(|x| **x\u003e=4).for_each(|x|print!(\"{},\",x));  // 3,3, \nfor i in vec![3,4,5,3].iter().skip_while(|x| **x\u003e=4) {print!(\"{i},\");} // 3,4,5,3\nfor i in vec![4,5,3,3,9,6].iter().take_while(|x| **x\u003e=4) {print!(\"{i},\");} // 4,5\nfor i in vec![3,4,5,3].iter().take_while(|x| **x\u003e=4) {print!(\"{i},\");} //   (nothing) \nvec![3,4,5].iter().cycle().take(6).for_each(|x|print!(\"{},\",x)); // 3,4,5,3,4,5 cycle allows wraparound\n\n// modify elements\nv.iter_mut().for_each(|v|*v=*v+5);\n\n// mathematical operations\nfor i in vec![3,4,5].iter().scan(0,|a,\u0026x| {*a=*a+x;Some(*a)}) {print!(\"{i}\")} // 3,7,12\nprint!(\"{}\",vec![3,4,5].iter().fold(0, |a, x| a + x)); // 12\nvec![3,4,5].iter().sum() // 3+4+5, 12\nvec![3,4,5].iter().product() // 12*5, 60\n(1..4).reduce(|x,y| x*y).unwrap_or(0); // 6   // 6 is 1*2*3\nprintln!(\"{}\",vec![1.,2.,3.].iter().cloned().fold(std::f64::MIN, f64::max)); // max, 3\nprintln!(\"{}\",vec![1.,2.,3.].iter().cloned().fold(std::f64::MAX, f64::min)); // min, 1\nprint!(\"{:?}\",vec![['a','b','c'], ['d','e','f']].iter().flatten().collect::\u003cString\u003e() ); // \"abcdef\"\nprint!(\"{:?}\",vec![vec![3,4],vec![5,1]].iter().flatten().collect::\u003cVec\u003c_\u003e\u003e()); // 3,4,5,1\nlet (a,b): (Vec\u003c_\u003e, Vec\u003c_\u003e) = vec![3,4,5].into_iter().partition(|x| x\u003e\u00264);\nprintln!(\"{:?} {:?}\",a,b); // [5] [3,4]\nvec![3,4,5].iter().all(|x| x\u003e2) // true\nvec![3,4,5].iter().all(|x| x\u003e4) // false\nvec![3,4,5].iter().any(|x| x\u003c4) // true\nvec![3,4,5].iter().any(|x| x\u003c2) // false\n// comparisons: cmp, le, eq, ne, lt, etc\nprint!(\"{}\",vec![3,4,5].iter().eq(vec![1,3,4,5].iter().skip(1))); // true\n\n// misc\npermutations(n) // n-based permutations of each element of the iterator\nunique() // remove duplicates from iterators\ncloned() // clones each element\nunzip() // backwards of zip()\nrev() // reverse iterator\nrposition() // combine reverse and position\nmax_by_key() // max using single func on each item\nmax_by()    // max using compare closure |x,y| f(x,y)\nv.min_by(|a,b| a.x.partial_cmp(\u0026b.x).unwrap_or(std::cmp::Ordering::Equal)); //min val,float\nfind_map() // combine find and map \nflat_map() // combine flatten and map \nfilter_map() // combine filter and map\n\ninto_iter() // can help you collect\nlet (v,u)=(vec![1,2,3],vec![4,5,6]);\nprint!(\"{:?}\", v.into_iter().zip(u.into_iter()).collect\u003cVec\u003c(i8,i8)\u003e\u003e()); // E0277\n// value of type `Vec\u003c(i8, i8)\u003e` cannot be built from `std::iter::Iterator\u003cItem=(\u0026{integer}...\nprint!(\"{:?}\", v.into_iter().zip(u.into_iter()).collect\u003cVec\u003c(i8,i8)\u003e\u003e()); // [(1, 4), (2, 5), (3, 6)]\n```\n\n\n\nItertools library: more adapters\n```rust\n    use itertools::Itertools;\n    // these are periodically integrated into Rust core, and/or may change\n    \n    // sort related\n    vec![13,1,12].into_iter().sorted(); // [1,12,13]\n    vec![(3,13),(4,1),(5,12)].into_iter().sorted_by(|x,y| Ord::cmp(\u0026x.1,\u0026y.1)); // [(4,1),(5,12),(3,13)]            \n    \"Mississippi\".chars().dedup().collect::\u003cString\u003e(); // Misisipi\n    \"agcatcagcta\".chars().unique().collect::\u003cString\u003e(); // agct\n\n    // mingling single items into others\n    \"四四\".chars().join(\"十\")); // 四十四\n    (1..4).interleave(6..9).collect_vec(); // 1,6,2,7,3,8\n    \" 十是十 \".chars().intersperse('四').collect::\u003cString\u003e(); // \"四十四是四十四\"\n    \"愛\".chars().pad_using(4,|_| '.').collect::\u003cString\u003e(); // \"愛...\"\n\n    // multiple iterators\n    \"az\".chars().merge(\"lm\".chars()).collect::\u003cString\u003e(); // \"almz\"\n    \"za\".chars().merge_by(\"ml\".chars(),|x,y| x\u003ey ).collect::\u003cString\u003e(); // \"zmla\"\n    vec![\"az\".chars(),\"lm\".chars()].into_iter().kmerge().collect::\u003cString\u003e(); //\"almz\"\n    for c in \u0026vec![1,2,3,4,5].into_iter().chunks(2) {  // chunk - split into new iterator groups of 2\n      for x in c { print!(\"{:?}\",x); } print!(\",\"); } // each group is 2 items. output: 12,34,5,\n\n    // mathematical operations\n    \"ab\".chars().cartesian_product(\"cd\".chars()).collect_vec() ; // [(a,b),(a,d),(b,c),(b,d)]\n    (1..=3).combinations(2).collect_vec(); // [[1,2], [1,3], [2,3]]\n    \"Go raibh maith agat\".chars().positions(|c| c=='a').collect_vec();// [4, 10, 15, 17]\n    (\"四十四是四十四\".chars().all_equal(), \"謝謝\".chars().all_equal()); // (false, true)\n    [1,5,10].iter().minmax().into_option().unwrap() // (1,10) // faster than min() then max()\n    (0..3).zip_eq(\"abc\".chars()).collect_vec(); // [(0,'a'), (1,'b'), (2,'c')]\n\n    // modifying and removing items\n    \"bananas\".chars().coalesce(|x,y| if x=='a'{Ok('z')}else{Err((x,y))}).collect::\u003cString\u003e(); \n    // result = bzzz - coalesce will replace a pair of items with a new single item, if the item matches\n    vec![1,2,3].into_iter().update(|n| *n *= *n).collect_vec(); // [1,4,9]\n    let mut s=['.';3];s.iter_mut().set_from(\"abcdefgh\".chars()); s.iter().collect::\u003cString\u003e(); // \"abc\"\n```\n\n## Implementing your own iterator for your own struct\n\nIf you want to be able to use all the cool adapters like filter(), map(), fold(), etc, \non your own cusom data structure you can implement the Iterator trait for your \nstruct. Basically you need to create another struct called a \"XIterator\" that implements \na 'next()' method. Then you create a method in your own struct called 'iter()' that returns \na brand new XIterator struct.\n\nHere is a super simple example, all it does is iterate over a data inside of custom \ndata struct Mine. The data is stored in a vector so it's pretty straightforward to access it.\n\n\n```rust\n\n#[derive(Debug)]\nstruct Mine{\n    v:Vec\u003cu8\u003e\n}\n\nimpl Mine{\n    fn iter(self:\u0026Mine) -\u003e MineIterator {\n        MineIterator {\n            m:\u0026self, count:0,\n        }\n    }\n}\n\nstruct MineIterator\u003c'a\u003e {\n    m: \u0026'a Mine,\n    count: usize,\n}\n\nimpl\u003c'a\u003e Iterator for MineIterator\u003c'a\u003e {\n    type Item = \u0026'a u8;\n    fn next(\u0026mut self) -\u003e Option\u003cSelf::Item\u003e {\n        self.count+=1;\n        if self.count\u003c=self.m.v.len() {\n\t\tSome(\u0026self.m.v[self.count-1])\n\t} else {\n\t\tNone\n\t}\n    }\n}\n\nfn main() {\n    let m=Mine{v:vec![3,4,5]};\n    m.iter().for_each(|i| print!(\"{:?} \",i));println!(\"\"); // 3 4 5\n    m.iter().filter(|x|x\u003e3).fold(0,|a,x| a+x); // 9 \n}\n\n```\n\nIf you want to create a Mutable Iterator, you will (as of writing, 2018)\nhave to use an unsafe code with a raw pointer. This is alot like what the\nstandard library does. If you are not extremely careful, your program may\nexhibit bizarre behavior and have security bugs, which defeats the purpose\nof using Rust in the first place. \n\n* https://gitlab.com/Boiethios/blog/snippets/1742789\n* https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer\n\n```rust\n\n\nimpl Mine{\n    fn iter_mut(self:\u0026mut Mine) -\u003e MineIterMut {\n            MineIterMut {\n            m:self, count:0,//_marker:std::marker::PhantomData,\n        }\n    }\n}\n\npub struct MineIterMut\u003c'a\u003e {\n    m: \u0026'a mut Mine,\n    count: usize,\n}\n\nimpl\u003c'a\u003e Iterator for MineIterMut\u003c'a\u003e {\n    type Item = \u0026'a mut u8;\n    fn next(\u0026mut self) -\u003e Option\u003c\u0026'a mut u8\u003e {\n            if self.count == self.m.v.len() {\n                None\n            } else {\n                let ptr: *mut u8 = \u0026mut self.m.v[self.count];\t    \n                self.count += 1;\n\t\tunsafe{ Some(\u0026mut *ptr) }\n            }\n    }\n}\n\nfn main() {\n    let mut m=Mine{v:vec![3,4,5]};\n    m.iter().for_each(|i| print!(\"{:?} \",i));println!(\"\"); // 3 4 5\n    m.iter_mut().for_each(|i| *i += 1);\n    m.iter().for_each(|i| print!(\"{:?} \",i));println!(\"\"); // 4 5 6\n}\n```\n\n### make your own Iterator with impl Iterator \n\n\"impl Iterator\" can help build iterators without creating your own custom struct.\nFor example you can return an Iterator from a function that modifies your data. Examples\nfollows for Itertools iproduct! macro and cartesian_product adapter.\n\n```rust\nfn f2() -\u003e impl Iterator\u003cItem = (u8,u8)\u003e { iproduct!(0..2,0..3) }\nfn f3(mut v:Vec\u003cu8\u003e) -\u003e impl Iterator\u003cItem = (u8,u8)\u003e {\n    v.push(1); v.into_iter().cartesian_product(0..3) }\n\nfor vertex in f2() {println!(\"{:?}\", vertex);} // (0,0) (0,1) (0,2) (1,0) (1,1) (1,2)\nfor vertex in f3(vec![0]) {println!(\"{:?}\", vertex);} // (0,0) (0,1) (0,2) (1,0) (1,1) (1,2)\n```\n\n## Math\n\n### arithmetic\n\n```rust\n\nlet x=250u8;           // addition can crash, max value of u8 is 255\nprintln!(\"{}\",x+10);   // crashes, attempt to add with overflow\nprintln!(\"{}\",x.wrapping_add(10));   // wraps around, result: 5\nprintln!(\"{}\",x.saturating_add(10)); // stays at max, result: 255\nprintln!(\"{}\",x.wrapping_sub(u8::MAX)); // wraparound subtraction\nstd::f32::MIN;         // minimum binary floating point 32 bit value\nstd::i32::MAX;         // maximum 32 bit integer value\n\nlet b = -5;\nlet c = b.abs();       // error, abs not defined on generic integer\nlet b = -5i32;\nlet c = b.abs();       // ok, abs is defined on i32, 32 bit integer\n42.25f32.round();      // can also call functions on float literals    \n9.0f32.sqrt();         // square root approximation\n9.sqrt()               // error, sqrt only for floats\nlet x = 3/4;           // 0\nlet y = 3.0/4;         // error, no implementation for `{float} / {integer}`\nlet z = 3.0/4.0;       // 0.75\n```\n\nExponentials, exponentiation, power, raising to a power\n\n```rust\nlet p1 = 2.pow(32) //err    // error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`\nlet p2 = 2_u8.pow(32) //err // thread 'main' panicked at 'attempt to multiply with overflow'\nlet p3 = 2_u8.checked_pow(32); // v becomes \"None\".\nlet p4 = match 2_u8.checked_pow(32) { Ok(n)=\u003en,None=\u003e0 } // match a checked_pow b/c it returns Option\nlet p5 = 2u8.checked_pow(k).unwrap_or(0); // 0 if overflow, simpler than match \nlet p6 = 2_u64.pow(32)                    // ok\n```\n\n### data conversion\n\n```rust\nlet x: u16 = 42;           // integer conversion. start with u16\nlet y: u8 = x as u8;       // cast to unsigned 8 bit integer\nlet z: i32 = x as i32;     // cast to signed 32 bit integer\nlet bez = z.to_le_bytes(); // get individual 8 bit bytes in the 32 bit int \nlet bbz = z.to_be_bytes(); // same, but in big endian order  \nprintln!(\"{:?},{:?},{:?},{:?}\",bez[0],bez[1],bez[2],bez[3]); // 42,0,0,0\nprintln!(\"{:?},{:?},{:?},{:?}\",bbz[0],bbz[1],bbz[2],bbz[3]); // 0,0,0,42\n\nlet a = u32::from('A')              // get integer value of char. all chars are 4 bytes.\nlet a = char::from_u32(68)          // get char value of an integer (utf8/ascii)\nlet a = char::from_digit(4,10)      // get char '4' from integer 4, base 10\n\nlet s = [0,1,2,3];                  // u8 to u32, start with array of four u8\nlet ls = u32::from_le_bytes(s);     // convert to u32, little endian\nlet bs = u32::from_be_bytes(s);     // convert. to u32, big endian\nprintln!(\"{:?} {:?}\",ls,bs);        // 50462976 66051\nlet s2 = vec![0,0,0,1,2,3,4,5,6,7]; // vector of ten u8\nlet ars2 = [s2[2],s2[3],s2[4],s2[5]]; // array of four u8\nlet be = u32::from_be_bytes(ars2);    // create u32 from 3rd-6th bytes of ars2\nprintln!(\"{:?}\",be);                // 66051\n\n// converting vectors of integers\nlet mut v1 = vec![0u8;2];                // 2 u8, each with '0'\nlet v2 = vec![0xffeeaa00u32,0xff0000dd]; // two u32 in a vector\nv2.extend(v2);  // error the trait bound `Vec\u003cu8\u003e: Extend\u003cu32\u003e` is not satisfied\nfor d in v2 { v1.extend(d.to_le_bytes()) }; // convert each u32 by itself\nprintln!(\"{:?}\",v1) // [0, 0, 0, 170, 238, 255, 221, 0, 0, 255]\n\n// integer conversion using byteorder crate\nextern crate byteorder; // modify your Cargo.toml to add byteorder crate. then:\nuse byteorder::{BigEndian, ReadBytesExt, NativeEndian, ByteOrder, LittleEndian, WriteBytesExt};\nlet arr = [0,1,2,3];\nlet s = NativeEndian::read_u32(\u0026arr[0..4]);   // array of four bytes into u32.\nlet mut v = vec![0u8];\ns.write_u8( v );\n\nlet vx = vec![0u8,1,2,0xff,4,5,6,0xff];     // vector of u8\n//let mut vy = vec![0u32];                  // vector of u32\n//LittleEndian::read_u32_into(\u0026vx,\u0026mut vy); // panic, vy cant hold vx\nlet mut vy = vec![0u32;2];                  // vector of u32\nLittleEndian::read_u32_into(\u0026vx,\u0026mut vy);   // convert u8s to u32s\nprintln!(\"{:x?}\",vy);                       // [ff020100, ff060504]\nlet mut vx2 = vec![0u8;8];                  // new vector of u8\nLittleEndian::write_u32_into(\u0026vy,\u0026mut vx2); // convert back to u8s\nprintln!(\"{:02x?}\",vx);                     // [00, 01, 02, ff, 04, 05, 06, ff]\n\n// converting vectors of integers using unsafe mem::transmute\nlet v = vec![0u8;80]; let i = 0;\nlet n:i32 = {unsafe { std::mem::transmute::\u003c\u0026[u8],\u0026[i32]\u003e(\u0026v[i..i+4])}}[0]; \nlet x:f32 = {unsafe { std::mem::transmute::\u003c\u0026[u8],\u0026[f32]\u003e(\u0026v[i..i+4])}}[0];\nlet mut block = vec![0u8;64];  // convert entire block at once\nlet mut X = unsafe { mem::transmute::\u003c\u0026mut [u8], \u0026mut [u32]\u003e(\u0026mut block) }; \n#[cfg(target_endian = \"big\")]   // deal with endian issues if needed\nfor j in 0..16 { X[j] = X[j].swap_bytes(); }\n\n\n\n\nlet s = format!(\"{:e}\",0.0f32);    // convert float32 to base-10 decimal string (scientific format)\nlet n = s.parse::\u003cf32\u003e().unwrap(); // parse float from string, panic/crash if theres an error\nlet mut n = 0.0f32;                // parse float from string, without panic/crashing\nmatch s.parse::\u003cf32\u003e() {\n\tErr(e)=\u003eprintln!(\"bad parse of {}, because {}\",s,e),\n\tOk(x)=\u003en=x\n}\nlet a = \"537629.886026485\"                        // base-10 decimal string to binary float point\nprint!(\"{:.50}\",a.to_string().parse::\u003cf32\u003e().unwrap();// 537629.875000000000000000000000000000000 \nlet b = 537629.886026485;    print!(\"{:.50}\",b);      // 537629.886026485008187592029571533203125\nlet c = 537629.886026485f32; print!(\"{:.50}\",c);      // 537629.875000000000000000000000000000000\nlet d = 537629.886026485f64; print!(\"{:.50}\",d);      // 537629.886026485008187592029571533203125\n\nlet ch='e';\nch.is_digit(16) // true, 'e' is a numerical digit in base 16\nch.is_digit(10) // false, 'e' is not a numerical digit in base 10, only 0-9 are.\nlet y:u32 = ch.to_digit(16).unwrap_or(0);  // convert 'e' into 15, since base=16. if fail, make y 0\nlet n = 'x'.is_alphabetic(); // detect whether letter\nprintln!(\"𝄠 is hex 0x{:06x}, or decimal {}\",'𝄠' as u32,'𝄠' as u32); // unicode codepoint\nprintln!(\"a is hex 0x{:06x}, or decimal {}\",'a' as u32,'a' as u32); // for \u003c128 this is the ascii code\n\nlet m = 0b0001; // binary literal\nlet m = 0o0007; // octal literal\nlet m = 0x000f; // hexadecimal literal\nlet (a,b,c) = (0b00_01,0o00_07,0x00_0f); // literals with underscores for ease of reading\n\nprintln!(\"{:x}\",0x12345678u32.swap_bytes());  // 0x78563412 32-bit byteswap \n\n\n\n```\n\n#### string conversion\n\n```rust\n\nuse std::i64;\nlet z = i64::from_str_radix(\"0x1f\".trim_start_matches(\"0x\"), 16).unwrap(); // hex string to integer\nlet q = i64::from_str_radix(\"0b10001\".trim_start_matches(\"0b\"), 2).unwrap(); // binary string to integer\n\nprintln!(\"{:?}\",\"abc\".as_bytes()); // \u0026[u8] slice, [97, 98, 99] ( utf8 string into bytes )\nprintln!(\"{:?}\",\"abc\".as_bytes().to_vec()); // Vec\u003cu8\u003e [97, 98, 99] string into slice into Vector of bytes\nprintln!(\"{:?}\",\"ᏣᎳᎩ\".as_bytes()); // [225, 143, 163, 225, 142, 179, 225, 142, 169] ( Cherokee utf8 )\nlet s = b\"\\x61\\x62\\x63\"; // b precedes sequence of bytes, hexadecimal, pseudo-string form\nprintln!(\"{}\",std::str::from_utf8( s ).unwrap()); // abc // decodes utf8 to string, crash if invalid utf8\n\nprintln!(\"{:?}\", \"सूर्य नमस्कार्कार\".as_bytes()); // [224, 164, 184,...] \nlet s = [224, 164, 184, 224, 165, 130, 224, 164, 176, 224, 165, \n         141, 224, 164, 175, 32, 224, 164, 168, 224, 164, 174, 224, \n\t 164, 184, 224, 165, 141, 224, 164, 149, 224, 164, 190, 224, 164, 176];\nprintln!(\"{}\",std::str::from_utf8( \u0026s ).unwrap()); // सूर्य नमस्कार   \nprintln!(\"{:?}\",std::str::from_utf8( \u0026s ).unwrap()); // \"स\\u{942}र\\u{94d}य नमस\\u{94d}कार\" different decoding\n```\n\n```rust\nlet s = \"hello\" ;                   // s = \u0026str\nlet s = \"hello\".to_string();        // s = String\nlet m = s.replace(\"hello\",\"new\");   // m = \"new\"\nlet y = s.to_uppercase();           // y = \"NEW\"\n\n// str.as_bytes() converts to slice, which implements Read\nlet s = \"Reedeth Senek, and redeth eek Boece\";\nlet s2= \"Ther shul ye seen expres that it no drede is\"\nlet buf = \u0026mut vec![0u8; 64];\ns.as_bytes().read(buf).unwrap();\ns2.as_bytes().read(\u0026buf[30]).unwrap();\n```\n\nRegular expressions typically use an external crate.\nSyntax for regex: https://docs.rs/regex/1.1.2/regex/index.html#syntax\n\nIn cargo.toml,\n[dependencies]\nregex = \"1.1.0\"\n\nIn main.rs:\n```rust\nuse regex::Regex;\nlet text = r###\"The country is named France, I think the biggest city is Paris;\nthe Boulangerie are beautiful on la rue du Cherche-Midi\"###;              // multiline string\n\nlet re = Regex::new(r\"country is named (?P\u003ccountry\u003e.*?),.*?biggest city is (?P\u003cbiggestcity\u003e.*?);\").unwrap();\nlet caps = re.captures(text).unwrap();\nprintln!(\"{}, {}\",\u0026caps[\"biggestcity\"],\u0026caps[\"country\"]);                  // Paris, France\n\nlet re = Regex::new(r\"(?ms)city is (?P\u003ccitname\u003e.*?).$.*?beautiful on (?P\u003cstreetname\u003e.*?)$\").unwrap();\nlet caps = re.captures(text).unwrap();\nprintln!(\"{}, {}\",\u0026caps[\"streetname\"],\u0026caps[\"citname\"]);               // la Rue de Cherche Midi, Paris\n```\n\n\n### comparison and sorting\n\n```rust\n\nuse std::cmp           \t\t\t// max/min of values\nlet a = cmp::max(5,3); \t\t\t// maximum value of 2 integers\nlet b = cmp::max(5.0,3.0); \t\t// build error, floats cant compare b/c of NaN,Inf\nlet v = vec![1,2,3,4,5];   \t\t// list, to find max of\nlet m = v.iter.max().unwrap(); \t\t// max of numbers in a list, crash on error\nmatch v.iter().max() { \t\t\t// max of numbers in a list, don't crash\n    Some(n)=\u003eprintln!(\"max {}\",n), \t// do stuff with max value n\n    None=\u003eprintln!(\"vector was empty\")\n}\nlet m = v.iter.max().unwrap_or(0);      // max of numbers in a list, or 0 if list empty\n\nv = vec![1,3,2];                               \nv.sort();                                      // sort integers\nv = vec![1.0,3.0,2.0];                         // sort floats\nv.sort();                                      // error, float's NaN can't be compared\nv.sort_by(|a, b| b.cmp(a));                    // sort integers using closure\nv.sort_by(|a, b| a.partial_cmp(b).unwrap());   // sort floating point using closure\nv.min_by(|a,b| a.x.partial_cmp(\u0026b.x).unwrap_or(std::cmp::Ordering::Equal)); // minimum value\nprintln!(\"{}\",vec![1.,2.,3.].iter().cloned().fold(std::f64::MIN, f64::max)); // 3\nprintln!(\"{}\",vec![1.,2.,3.].iter().cloned().fold(std::f64::MAX, f64::min)); // 1\n\nstruct Wheel{ r:i8, s:i8};                     // sort a vector that holds a struct\nlet mut v = vec![Wheel{r:1,s:2},Wheel{r:3,s:2},Wheel{r:-2,s:2}];\nv.sort_by(|a, b| a.r.cmp(\u0026b.r));               // sort using closure, based on value of field 'r'\nv.sort_by(|a, b| a.r.cmp(\u0026(\u0026b.r.abs())));      // sort using closure, based on abs value of r\n\nfn compare_s( a:\u0026Wheel, b:\u0026Wheel ) -\u003e std::cmp::Ordering {      // sort using a function\n     a.s.partial_cmp(\u0026b.s).unwrap_or(std::cmp::Ordering::Equal)\n}\nv.sort_by( compare_s );                        \n```\n\n### Pseudo randoms\n\nPseudo Random number generators, aka PRNGs\n\n```rust\nextern crate rand;   /// add rand to dependencies in Cargo.toml\nuse rand::prelude::*; \nlet x = rand::random(); // boolean\nlet y = rand::random::\u003cint\u003e(); // integer\nlet x = rand::thread_rng().gen_range(0, 100); // between\nlet mut rng = rand::thread_rng();\nlet z: f64 = rng.gen(); // float 0...1\nlet mut nums: Vec\u003ci32\u003e = (1..100).collect();\nnums.shuffle(\u0026mut rng);\n```\n```rust\n// alternative, without needing external crate, based on codeproject.com by Dr John D Cook\n// https://www.codeproject.com/Articles/25172/Simple-Random-Number-Generation\n// License: BSD, see https://opensource.org/licenses/bsd-license.php\nuse std::time::{SystemTime, UNIX_EPOCH};\nlet mut m_z = SystemTime::now().duration_since(UNIX_EPOCH).expect(\"Time reversed\").as_millis();\nlet mut m_w = m_z.wrapping_add( 1 );\nlet mut prng = || {  m_z = 36969 * (m_z \u0026 65535) + (m_z \u003e\u003e 16);\n                     m_w = 18000 * (m_w \u0026 65535) + (m_w \u003e\u003e 16);\n                     m_z.rotate_left( 16 ) + m_w };\nlet buf = (0..1000).map(|_| prng() as u8).collect::\u003cVec\u003cu8\u003e\u003e();\n// creates 1000 pseudo random bytes in buf, using Closure named prng\n```\n\n### Hashing\n\n```rust\nuse std::collections::hash_map::DefaultHasher; \nuse std::hash::{Hash, Hasher};\nlet mut hasher = DefaultHasher::new(); // hashing, via a Hasher object, which holds state\nlet x = 1729u32;\nlet y = 137u32;\nhasher.write_u32( x );                 // input x to hash func, store output in hasher \nhasher.write_u32( y );                 // input y, combine w existing state, store in hasher\nprintln!(\"{:x}\", hasher.finish());     // .finish() function Hasher gives current state\n345.hash(\u0026mut hasher);                 // update hasher's state using '.hash()' trait\nprintln!(\"{:x}\", hasher.finish());     // .finish() does not 'reset' hasher objects\n\n```\n\n### Date and Time\n\n```rust\nuse std::time::{Instant};\nlet t = Instant::now();\n// do something for 5.3 seonds\nprintln!(\"{}\",t.elapsed().as_secs());          // 5, seconds, rounded\nprintln!(\"{}\",t.elapsed().subsec_millis());    // 300. remainder in milliseconds\n\nuse chrono::prelude::*;\nprintln!(\"{:?} \", Utc::now().to_rfc2822());\nprintln!(\"{:?} \", Utc::now().format(\"%Y-%m-%d %H:%M:%S\").to_string());\nprintln!(\"{:?} \", Local::now().to_rfc2822());\nprintln!(\"{:?} \",DateTime::parse_from_str(\"2014-11-28 21:00:09 +09:00\", \"%Y-%m-%d %H:%M:%S %z\"));\nprintln!(\"{:?} \",Utc.with_ymd_and_hms(2014, 11, 28, 12, 0, 9).unwrap());\nprintln!(\"{:?} \",Utc.timestamp(1500000000, 0)); // Epoch time seconds, aka mtime on Unix files.\n\"Tue, 17 Jan 2023 03:12:07 +0000\" \n\"2023-01-17 03:12:07\" \n\"Mon, 16 Jan 2023 21:12:07 -0600\"\nOk(2014-11-28T21:00:09+09:00)\n2014-11-28T12:00:09Z\n2017-07-14T02:40:00Z\n```\n\n## Annotations\n\nAka hashtags aka warning thingies. These statements typically affect compilation and begin with a hashtag, and square brackets. They are sort of like a mix of #pragma and #ifdef from C. \n\n```rust\n#![allow(dead_code)]             // stop compiler from printing warnings on unused funcs/vars,   \n#![allow(unused_variables)]      // this is good when you are working on a library\n//  = note: #[warn(unused_assignments)] on by default\n#![allow(unused_assignments)]    // you can take most warnings, and disable by changing 'warn' to 'allow'\n\n// by removing ! and placing on line before a fn, you can disbale warning only for the function\n#[allow(unused_assignments)]     \nfn zoogle_poof( n:u8 )-\u003eu8 { let a = 0; 5+n };\n\nlet mut a = 0x00ffee22;          // modify numbers for big endian machines.\n#[cfg(target_endian = \"big\")]    // target = machine the code will be run on\na = a.swap_bytes();              // the line (or block) immediately following the # gets affected.\n```\n\n## Linked Lists\n\nTextbook C/Java-style implementations of linked lists often involve ownership that is not allowed by the Rust borrow checker. However it can be accomplished. There is builting \"LinkedList\" type in std::collections, also some resources from A. Beinges :\n\nhttps://cglab.ca/~abeinges/blah/too-many-lists/book/\n\nYou can also implement a linked list as a Vector of structs, using integer indexes into the vector instead of pointers.\n\n## FFI, Calling C functions, porting C code\n\nforeign function interface, aka calling code from other languages. \n\nlayout\n```bash\n   src/lib.rs\n   src/ccode.c\n   build.rs\n   Cargo.toml\n```\n\nCargo.toml\n```rust\n[package]\nname = \"duh\"\nversion = \"0.1.0\"\nauthors = [\"akhmatova\"]\nbuild = \"build.rs\"\n[build-dependencies]\ncc = \"1.0\"\nlibc = \"0.2.0\"\n```\n\nbuild.rs\n```rust\nextern crate cc;\n\nfn main() {\n    cc::Build::new().file(\"src/ccode.c\").compile(\"ccode\");\n}\n```\n\nsrc/ccode.c\n```C\n#include \u003cstdio.h\u003e\nint quadrance( int x1, int y1, int x2, int y2) {\n\treturn (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);\n}\nchar * blerg( *char txt ) {\n\tprintf(\"This is C. Here is text from Rust: %s\", txt);\n\tint fd = open(\"/tmp/blerg\",0);\n\treturn \"blerg\";\n}\nvoid printerrs() {\n        int code = errno;\n        printf(\"C: errno: %i strerror: %s\\n\",code,strerror(code));\n}\n```\n\nsrc/main.rs\n```rust\nuse std::os::raw::{c_int,c_char,c_void};\nuse std::ffi::{CString,CStr};  \nextern \"C\" {\n    fn quadrance(x1: c_int, y1: c_int, x2: c_int, y2: c_int) -\u003e c_int;\n    fn blerg(v: *const char)-\u003e*const c_char;\n    fn printerrs()-\u003ec_void;\n}\nfn main() {\n    unsafe {\n        println!(\"4^2+3^2={:?}\", quadrance(0, 0, 4, 3));\n\tlet tmp = CString::new(\"blarg\").unwrap(); // CString must be assigned\n\tlet msg = blerg(tmp.as_ptr()); // so as_ptr() will have something to point at \n\tprintln!(\"This is Rust. Here's text from C: {:?}\",CStr::from_ptr(msg));\n\tprinterrs(); // was there an error?\n    }\n}\n```\n\nRun:\n```bash\ndon@oysters:~/duh$ cargo run\n   Compiling duh v0.1.0 (/home/don/duh)                                         \n    Finished dev [unoptimized + debuginfo] target(s) in 1.95s                   \n     Running `target/debug/duh`\n4^2+3^2=25\nThis is C. Here is text from Rust: blarg\nThis is Rust. Here's text from C: blerg\n```\n\nSee also: https://s3.amazonaws.com/temp.michaelfbryan.com/index.html\n\nc++ - https://hsivonen.fi/modern-cpp-in-rust/\n\nhttps://doc.rust-lang.org/nomicon/ffi.html\n\nMichael Bryan's unofficial guide\nhttps://s3.amazonaws.com/temp.michaelfbryan.com/index.html\n\nUsing char** C functions:\nhttps://stackoverflow.com/questions/42717473/passing-vecstring-from-rust-to-char-in-c\n\nNote that much C code does not initialize structs or memory, which may be forgotten\nwhen one is used to Rust\nhttp://www.ex-parrot.com/~chris/random/initialise.html\n\nStructs and bindgen auto header conversion\nhttps://medium.com/dwelo-r-d/using-c-libraries-in-rust-13961948c72a\n\n\nSetting CFLAGS examples:\n\nmodify build.rs:\n\n```rust\nextern crate cc;\n\nfn main() {\n    std::env::set_var(\"CFLAGS\",\"-w\");  // turn off all warnings\n    std::env::set_var(\"CFLAGS\",\"-v\");  // run compiler in verbose mode\n    std::env::set_var(\"CFLAGS\",\"-v -O2\");  // optimize level 2 + verbose mode\n    cc::Build::new().file(\"src/ccode.c\").compile(\"ccode\");\n}\n```\n\nUnions:\n\nIn Rust, Enums are typically preferred over union, as a traditional C-style union is\nonly available by using unsafe{}. But unions can help talking to / porting C code:\n``` rust\n#[repr(C)]\nunion Borgle { dorgle: u32, porgle: u8[4] }\nlet mut a=Borgle{dorgle:1234};\nunsafe{ a.dorgle = 0xa0ca0c };\n```\n\nGoto vs labels, loops, and breaks:\n\nRust does not have Goto, however sometimes a similar result \ncan be achieved using labelled loops and breaks. \n\n```rust\n    'label1: loop {\n    \tif zimblatz == 5 {\n\t    break; // breaks labe1 loop\n\t}\n        'label2: for frobnoz in 0..4 {\n            if blorg==KUMQUAT {break;} // breaks label2 only\n\t    while j\u003c5 {\n\t    \tif snog==7 { \n\t\t\t// goto end of label1 loop immediately\n\t\t\tbreak 'label1; \n\t\t}\n\t\tj+=1;\n\t    }\n        }\t\n    } // end of 'label1 loop\n    do_something();\n```\n\nPointer arithmetic\n\n```rust\nuse std::raw::c_uchar;\nunsafe{\n\tlet mut x = some_c_func() as *const c_uchar;\n\tx = x.offset(1);  // instead of x++\n}\n```\n\n## source code layout and modules\n\nHere is an example source code organization layout for a simple library, which has a handful of modules, some examples, integration tests, benchmarking, and two executable binaries.\n \n```bash\n$ ls ..\n./mycrate                  \t  # main crate folder\n./mycrate/Cargo.toml       \t  # cargo file, lists dependencies etc\n./mycrate/src/lib.rs        \t  # only one library is allowed per crate\n./mycrate/src/mod1.rs      \t  # module 1. a library can use multiple modules\n./mycrate/src/mod2.rs       \t  # module 2 , a second module\n./mycrate/src/bin/program1.rs     # source code for an executable\n./mycrate/src/bin/program2.rs     # source code for another executable\n./mycrate/tests             \t  # integration tests (as opposed to unit tests at end of every .rs file)\n./mycrate/tests/integration_test.rs  # big test that tests big part of library\n./mycrate/tests/test_data_file       # integration tests often use test files\n./mycrate/examples          \t  # easy to follow examples   \n./mycrate/examples/helloworld.rs  # simple example, \"use mycrate::*\"\n./mycrate/examples/zoogbnoz.rs    # more complicated example\n./mycrate/benches           \t  # benchmarking code and files\n./mycrate/benches/benchtest.rs    # program to run benchmarking speed tests\n./mycrate/build.rs                # optional program to run before build\n./mycrate/target\t\t  # binaries are generated under target\n./mycrate/target/debug/program1   # debug build executable\n./mycrate/target/release/program1 # release build executable (optimized for speed) \n$ cargo build                     # this builds all files in crate\n```\n\n\nsrc/lib.rs: (our main library file which the world will use)\n```rust\nmod mod1;      // we must add each modules in lib.rs with 'mod' before we can use them within each other\nuse mod1::*;   // import symbols from mod1.rs\npub mod mod2;  // this module is public, anyone using this crate can access its functions too\nuse mod2::*;   // import symbols from mod2.rs\npub fn mycrate_init() { \n  let x = do_stuff1(9);  // call function from mod1.rs\n  mycrate_monster(x);\n}\npub fn mycrate_monster(y:u8) -\u003e Monster { // Monster - type from mod1.rs\n  let mut a = Monster{ true,y };\n  do_stuff2( \u0026mut a );   // call function from mod2.rs\n  a\n}\npub fn mycrate_calcteeth()-\u003e { 23 }\n```\n\nsrc/mod1.rs: (our 1st module that does stuff)\n```rust\npub fn do_stuff1(x:u8)-\u003eu8 { x+5 } // public function, available to other modules\npub struct Monster1 {  // public struct, available to other modules\n    pub is_happy:bool, // public struct member, available to others\n    pub num_teeth:i8,\n}\n```\n\nsrc/mod2.rs: (\n```rust\nuse super::*; // use functions from lib.rs\nuse mod1::*;  // use functions/types from mod1.rs, like Monster struct \n              // note: this only works if \"mod mod1\" line is in lib.rs\n\t      // otherwise you get E0432 unresolved import , maybe a missing crate\npub fn do_stuff2( a: \u0026mut Monster ) { \n\ta.is_happy = calc_happy();           // call our own private function\n\ta.num_teeth = mycrate_calcteeth();   // call a function from lib.rs\n}\nfn calc_happy() -\u003e bool { // private function only available within mod2.rs\n  match today { Tuesday =\u003e true ,_=\u003efalse } }\n```\n\nSee also\nhttps://doc.rust-lang.org/book/ch07-02-modules-and-use-to-control-scope-and-privacy.html\n\n\n## ANSI colors\n\nIn C, ansi colors for terminal text output are typically done with the escape code\nin octal format, such as printf(\"\\033]0;31m test red\"); In Rust, you can use\nthe unicode escape sequence, instead of 033 octal, we can use unicode with 001b hexadecimal:\n\n```rust\nfn main() {\n    println!(\"\\u{001b}[0;31m{}\", \"test red\");\n    println!(\"\\u{001b}[0;32m{}\", \"test green\");\n    println!(\"\\u{001b}[0;33m{}\", \"test orange\");\n    println!(\"\\u{001b}[0;34m{}\", \"test blue\");\n    println!(\"\\u{001b}[0;35m{}\", \"test magenta\");\n    println!(\"\\u{001b}[0;36m{}\", \"test cyan\");\n    println!(\"\\u{001b}[0;37m{}\", \"test white\");\n    println!(\"\\u{001b}[0;91m{}\", \"test bright red\");\n    println!(\"\\u{001b}[0;92m{}\", \"test bright green\");\n    println!(\"\\u{001b}[0;93m{}\", \"test yellow\");\n    println!(\"\\u{001b}[0;94m{}\", \"test bright blue\");\n    println!(\"\\u{001b}[0;95m{}\", \"test bright magenta\");\n    println!(\"\\u{001b}[0;96m{}\", \"test bright cyan\");\n    println!(\"\\u{001b}[0;97m{}\", \"test bright white\");\n    println!(\"\\u{001b}[0m{}\", \"restored to default\");\n}\n```\n\nThere are also several crates that do this. Search the web for additional ANSI color features.\n\n## Thanks\n\nBased on a8m's go-lang-cheat-sheet, https://github.com/a8m/go-lang-cheat-sheet, and\n\n- rust-lang.org, Rust book, https://doc.rust-lang.org/book/second-edition\n- rust-lang.org, Rust reference, https://doc.rust-lang.org\n- rust-lang.org, Rust by example, https://doc.rust-lang.org/rust-by-example/\n- rust playground, from integer32, https://play.integer32.com/\n- Phil Opp builds an OS in rust, https://os.phil-opp.com/unit-testing/\n- Rust Cookbook, Language Nursery https://rust-lang-nursery.github.io/rust-cookbook/algorithms/sorting.html\n- Itertools docs https://docs.rs/itertools/*/itertools/trait.Itertools.html for more details\n- carols10cent's js-rust cheatsheet, https://gist.github.com/carols10cents/65f5744b9099eb1c3a6f\n- c0g https://stackoverflow.com/questions/29483365/what-is-the-syntax-for-a-multiline-string-literal\n- codngame https://www.codingame.com/playgrounds/365/getting-started-with-rust/primitive-data-types\n- Adam Leventhal post here, http://dtrace.org/blogs/ahl/2015/06/22/first-rust-program-pain/\n- Shepmaster, https://stackoverflow.com/questions/33133882/fileopen-panics-when-file-doesnt-exist\n- again, https://stackoverflow.com/questions/32381414/converting-a-hexadecimal-string-to-a-decimal-integer\n- user4815162342, https://stackoverflow.com/questions/26836488/how-to-sort-a-vector-in-rust\n- mbrubek, https://www.reddit.com/r/rust/comments/3fg0xr/how_do_i_find_the_max_value_in_a_vecf64/\n- https://stackoverflow.com/questions/19671845/how-can-i-generate-a-random-number-within-a-range-in-rust\n- Amir Shrestha https://amirkoblog.wordpress.com/2018/07/05/calling-native-c-code-from-rust/ \n- Julia Evans https://jvns.ca/blog/2016/01/18/calling-c-from-rust/\n- huon https://stackoverflow.com/questions/23850486/how-do-i-convert-a-string-into-a-vector-of-bytes-in-rust\n- EvilTak https://stackoverflow.com/questions/43176841/how-to-access-the-element-at-variable-index-of-a-tuple\n- https://www.90daykorean.com/korean-proverbs-sayings/\n- oli_obk https://stackoverflow.com/questions/30186037/how-can-i-read-a-single-line-from-stdin\n- ogeon https://users.rust-lang.org/t/how-to-get-a-substring-of-a-string/1351\n- A.R https://stackoverflow.com/questions/54472982/converting-a-vector-of-integers-to-and-from-bytes-in-rust\n- dten https://stackoverflow.com/questions/25060583/what-is-the-preferred-way-to-byte-swap-values-in-rust\n- How To Rust-doc https://brson.github.io/2012/04/14/how-to-rustdoc\n- Pavel Strakhov https://stackoverflow.com/questions/40030551/how-to-decode-and-encode-a-float-in-rust\n- Zargony https://stackoverflow.com/questions/19650265/is-there-a-faster-shorter-way-to-initialize-variables-in-a-rust-struct/19653453#19653453\n- Wesley Wiser https://stackoverflow.com/questions/41510424/most-idiomatic-way-to-create-a-default-struct\n- u/excaliburhissheath and u/connorcpu https://www.reddit.com/r/rust/comments/30k4k4/is_it_possible_to_modify_wrapped\n- Simson https://stackoverflow.com/questions/54472982/how-to-convert-vector-of-integers-to-and-from-bytes\n- Raul Jordan https://rauljordan.com/rust-concepts-i-wish-i-learned-earlier/\n- Will Crichton https://www.youtube.com/watch?v=bnnacleqg6k\n- Jimmy Hartzell https://www.thecodedmessage.com/posts/oop-2-polymorphism/\n- Peter Hall https://stackoverflow.com/questions/63437935/in-rust-how-do-i-create-a-mutable-iterator\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonbright%2Frust-lang-cheat-sheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdonbright%2Frust-lang-cheat-sheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonbright%2Frust-lang-cheat-sheet/lists"}