Pragmatic Rust
I. Rust install

Debian details:
Debian Linux has rustc, and using apt install works fine, but doesn't include cargo (rust package manager),

- but should use cargo
- So www.rustup.rs -install.
  - adds ~\.cargo
  - adds to ~\.profile
  - adds rustup for itself, and cargo and rustc for rust-compiler

For other OS: use rustup.rs

In Vim, add Ale in vim plugins dir for in-editor syntax & compilation errors.



II. Rust project

$ cargo init
(edit src/main.rsi Hello -text, save)
$ cargo run


What is #[test]?

  A: Test code for this file, see next answer:

What is #[cfg(test)]?

  A: Instruction for cargo build tool that the next code is test module, and contains 'mod tests' -block. To run tests use 
     $ cargo test
     Tests are also run when
     $ cargo run

     See more: https://doc.rust-lang.org/1.5.0/book/testing.html



III. Rust proggy

(todo)


IV. Debugging Rust

How to see asm output of the compiler?
https://github.com/gnzlbg/cargo-asm
- A cargo subcommand that displays the assembly or llvm-ir generated for Rust source code.


Rust compiler output to see parse tree and resulting intermediate code?
(todo)

Rust debugging with dfb?
1. Compile 
2. set debugger to single thread mode
3. > gdb rust-executable
4. (gdb) run
5. How to set breakpoint, view stack or heap?
   (gdb) break functionName
   (gdb) run 
   (gdb) frame
   (gdb) n


Rust Editions
- When we want to release a feature that would otherwise be backwards incompatible, we do so as part of a new Rust edition.
- Editions 2015, 2018, 2021 https://doc.rust-lang.org/edition-guide/editions/index.html


V. Rust Theory

- Olisko siistiä jos tää oliskin rust-ohjelma jota voi lukea

Rust concepts

- Bit pattern
  0b001010110110

  - Eventually all types converted into a bit pattern.

- Floating points f32
  0.0 == (-0.0)


- stack, heapo

- Variables
  - pass something by value
  - move when passed in function, copy when int/char/primitive
  - ownership/borrowing &
  - "&" - pass something by reference - f.ex. "&my_var"
      calculate_sum( &entries );
      fn calculate_sum(index: &vec) -> Integer { index = do stuff ... }
      
      - Aliasing Model https://plv.mpi-sws.org/rustbelt/stacked-borrows/

  - mutating mut vars are passed/defined in fn with "&mut"


  - &str[4..5] - string slice type -> "&str"
    - points to a slice of the binary
    - also type &[i32]

- Struct

    struct Stuff {
      num: f32;
    }

    Stuff { num: 1.1; }

- Trait
  - https://doc.rust-lang.org/reference/types/trait-object.html
  - collection of methods for an unknown type Self.
  - Almost like abstract base class or an interface.
  - How to see what functions to implement for a trait?
      22:30 < palindrome> how do I know from the docs which trait my struct has to implement in
      order to use BinaryHeap ?
      22:42 < ChaiTRex> palindrome: Two places to look are the struct definition and the impl 
      blocks containing the methods or associated functions you want to use. 
      For example, let's say you want to use the new associated function. Go to 
      the new associated function in the docs and scroll up to the impl block 
      it's just under. You'll see it's impl BinaryHeap where T: Ord.
      https://doc.rust-lang.org/src/alloc/collections/binary_heap.rs.html#350-809
  - traits can't have async fns
  - Example:

    trait Movement {
      fn forward(&mut self, speed: f32) {};
      fn turn(&mut self, direction: f32) {};
    }

  struct Sentinel;

  impl Movement for Sentinel {
    fn forward(&mut self, speed: f32) {};
    fn turn(&mut self, direction: f32) {};
  }

  - Example:

    - cAMP: What is Vec>>
    - Alexendoo: dyn Foo + Send is a trait object that implements Foo and is Send.

    - Ever wanted to give your things some default value? Like, give an enumerable or structs default value? Default trait https://doc.rust-lang.org/std/default/trait.Default.html
      - impl Default for SomeEnumerables { ... }

    

    - https://doc.rust-lang.org/std/marker/trait.Send.html

- Lifetimes

- Errors
  - Errors are returned.
  - Result type
  - No exceptions!
  - inrecoverable get panic
    panic("My panic message")
  - Library should have custom error types, prefer not to panic
    
    enum Result {
      Ok(T),
      Err(E),
    }

    fn init() -> Result<(), ie::Error> {
      let mut file = match File::create("ferris.txt") {
        Ok(f) => f,
        Err(e) => return Err(e)
      };

      // this one can be written as below
      match file.write_all("Foo") {
        Ok(_) => Ok(()),
        Err(e) => return Err(e)
      }

      // with a question mark that returns result or error
      file.write_all("Foo")?

      // with unwrap result or panics
      file.write_all("Foo").unwrap()

      // expect
      // map_err

    }


Rust REPL??
Rust inline-debugger?
Rust linting


VI. Rust idioms

 - Vectors

    12:11 < frogzilla> Easiest way to convert Vec, E>> to Vec? 
    12:13 < dpc1> map, unwrap(x2), collect
    

 - Closures - closure expressions https://doc.rust-lang.org/reference/types/closure.html
  - unique anonymous type that cannot be written out

 - Error Handling question mark
   - ? mark at the end of a statement "pops the error out, and exits the handler"

 - Match
   - The "@ operator" https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#-bindings
   - Creates a variable while matching the value of the variable
   - Rust 1.56 allows bindings in this @ operator pattern

 - Slice

   https://adventures.michaelfbryan.com/posts/daily/slice-patterns/?utm_source=reddit&utm_medium=social&utm_campaign=daily-rust-slice-patterns 

- Clone trait
    #[derive(Clone)]

    dostuff(numbers.clone()):


- PartialEq

    let bit_pattern = 32424;
    f32::frombits(bit_pattern) == f32::from_bits(bit_pattern)

    (f32::NAN).to_bits()

- Rc and Arc
  - An example of a non-Send type is the reference-counting pointer rc::Rc. If two threads attempt to clone Rcs that point to the same reference-counted value, they might try to update the reference count at the same time, which is undefined behavior because Rc doesn’t use atomic operations. Its cousin sync::Arc does use atomic operations (incurring some overhead) and thus is Send.


- underline
  - when name does not matter
  - elide type
  - receive must_use results

- asterisk
  dereference?
  *&T ?

- open file? stream?
- match
- self
- traits
- Deref trait
  Allows type to turn into other types.

  *std::ops::Deref::deref(&x) in an immutable place expression context


- Iterator trait

  impl Iterator for WhatEver {
    type tuff = Stuff;
    fn next(&mut self) -> Option<> {
      /* next -> Option */
    }
  }


- Display trait
  Allows to print types to console.
  How to implement Display?

  use std::fmt;
  impl fmt::Display for City2 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
      /* this line is workaround for editor syntax highlight '> */
      write!(f, "City<{}>", self.name);
    }
  }


VII. Rust Crates

  - Axum web framework https://tokio.rs/blog/2021-07-announcing-axum


VIII. Rust on Linux

  https://github.com/Rust-for-Linux/linux/blob/rust/Documentation/rust/coding-guidelines.rst
  For Linux kernel related code, write as much of your code with safe.
  Use unsafe blocks inside unsafe functions.
    - like:
        pub unsafe fn load(p: *const i32) { unsafe { *p } }
    - Use unsafe fn denotation, with unsafe blocks inside.
    - Document the safety requirements with /// # Safety -blocks:
        // SAFETY: the returned string is foo bar etc cetera
  Uphold type invariants
    - idea is to constrain types to safe knowns, maintain an invariant, avoid going outside that definition.
    - Document invariants with /// # Invariant -blocks:
        // INVARIANT: foo is guaranteed to be xyz of strBar
  Document examples for function, type, trait, module and crate
    - with /// Examples -blocks:
  Document modules
    - using //!: First line of module description comment block
  For examples see core::ptr::read
  Write tests, as tests will be integrated with (CI) builds in the future.



Rust examples?


APPENDIX

Rust Webassembly Cloud Project - Krustlet
  https://github.com/krustlet/krustlet

Random stuff

  TESTING 
  18:40 < CuriousErnestBro> I'm running a  teardown() functions at the end of every test. but the tests are full with .unwrap()'s and sometimes they fail, and I still want teardown() to run, how2rust?
  18:47 < trev> CuriousErnestBro just encapulate the test part (put into another fn for cleanliness?) and have it return Result so you can unwrap, then put it between init() and teardown()
  18:47 < trev> not unwrap, but ?
  18:48 < trev> probably need anyhow::Result for that