# Introduction

Rust learning notebook.


# Rust Introduction


# Collections

* [Hashing](/collections/hashing)


# Hashing

## Writing a custom hasher in Rust

Implementing [FNV Hash](http://www.isthe.com/chongo/tech/comp/fnv/index.html),

```rust
struct FnvHasher(u64);

impl Default for FnvHasher {
    fn default() -> Self {
        FnvHasher(0x811c9dc5)
    }
}

impl Hasher for FnvHasher {
    fn finish(&self) -> u64 {
        self.0
    }

    fn write(&mut self, bytes: &[u8]) {
        let FnvHasher(mut hash) = *self;

        for c in bytes.iter() {
            hash = hash.wrapping_mul(0x01000193);
            hash ^= *c as u64;
        }
    }
}
```


# Text Processing

* [Splitting a string into fields](/text-processing/string-splitting)
* [Converting a string to vectors and back](/text-processing/string-to-vecs)
* [Two way for fast substring search](/text-processing/twoway)


# Splitting a string

## How to split a string based on specific separators?

* By separator - `s.split("separator")`
* By whitespace - `s.split_whitespace()`
* By newlines - `s.lines()`

## How to split a string based on multiple characters?

Standard library `split` can be used with a closure to fulfill this use case.

```rust
fn split_stuff() {
    let message = "Hello there | how are you ; doing?";
    for s in message.split(|c| (c == '|') || (c == ';')) {
        dbg!(s);
    }
}
```

Output would be as follows,

> s = "Hello there " s = " how are you " s = " doing?"

To get rid of spaces, [`trim()`](https://doc.rust-lang.org/std/string/struct.String.html#method.trim) method can be used.

Although it is possible to write a closure to split on arbitrarily complex conditions, it easier to use `regex` crate for splitting based on regular expressions.

Another approach without using a closure would be to make use of string slice [patterns](https://doc.rust-lang.org/std/str/pattern/trait.Pattern.html). As an example, we can write the above split as,

```rust
for s in message.split(&['|', ';'][..]) {
// ...
}
```

Splits can be collected to a vector and other types of Rust collections with `collect` method.

## How to split a string based on regular expressions?

Splitting a string such as `"hello there; how| are|you, chathura"` based on multiple characters and taking into account multiple spaces is not simple without using regular expressions.

Following solution demonstrates the use of regex crate to accomplish the task.

```rust
fn split_by_regex() {
    let message = "hello there; how|    are|you, Chathura";

    let re = regex::Regex::new(r"[;,|\s]\s*").unwrap();

    for s in re.split(message) {
        dbg!(s);
    }
}
```


# Converting a string to vectors and back

## How to convert a String to a vector of chars?

```rust
let s = "Hello there";

// Convert a string to a Vec<char>
let cvec: Vec<char> = s.chars().collect();
```

## How to convert vector of chars back to a String?

Carrying from the above example,

```rust
// Convert a string to a Vec<char>
let cvec: Vec<char> = s.chars().collect();

// Convert a Vec<char> into a String
let back: String = cvec.into_iter().collect();
```


# Twoway

## Fast substring search by two way algorithm

[twoway](https://github.com/bluss/twoway) implements [Two way algorithm](http://www-igm.univ-mlv.fr/~lecroq/string/node26.html) for substring search which is highly optimised using SMID acceleration (depending on availability).

Example usage,

```rust
let loc = twoway::find_str("hello there how are you?", "there");
assert_eq!(Some(6), loc);
```


# Benchmarking

* [criterion](/benchmarking/criterion)


# criterion

## How to benchmark functions using criterion library?

```rust
use criterion::{black_box, criterion_group, criterion_main, Criterion};

pub fn fib(n: i32) -> i32 {
    if n > 1 {
        fib(n - 1) + fib(n - 2)
    } else {
        1
    }
}

pub fn fib_fast(n: i32) -> i32 {
    let mut a = 1;
    let mut b = 1;

    for _ in 0..n {
        b += a;
        a = b - a;
    }

    a
}

fn criterion_fib_slow(c: &mut Criterion) {
    c.bench_function("fib 10", |b| b.iter(|| fib(black_box(10))));
}

fn criterion_fib_fast(c: &mut Criterion) {
    c.bench_function("fib_fast 10", |b| b.iter(|| fib_fast(black_box(10))));
}

criterion_group!(benches, criterion_fib_fast, criterion_fib_slow);
criterion_main!(benches);
```

Add following dependencies to the `Cargo.toml`.

```yaml
[dev-dependencies]
criterion = "0.3.1"

[[bench]]
name = "lib"
path = "src/lib.rs"
harness = false
```

Benchmarks can be run by `cargo bench`.


# Testing

## How to get output from tests with cargo test?

Provide `nocapture` option as an argument to `cargo test`, as follows.

```
cargo test -- --nocapture
```


# Package Management

* [Cargo workspaces](/package-management/cargo-workspaces)


# Cargo workspaces

## How to create a workspace for managing multiple cargo projects?

A [workspace](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html) can be defined to group multiple cargo projects. Following is the main workspace definition for the code for this project's examples.

```
[workspace]

members = [
  "benchmarking",
  "testing",
  "text-processing",
]
```


# Concurrent Programming

## TODO


# Actor model

## TODO


# Actix actors

## TODO


# Bastion

## TODO


# Parallel Programming

* [Rayon](/parallel-programming/rayon)


# Ryaon

## Parllalel collection transformations using rayon

Mutating a vectors to double its elements can be done by,

```rust
let mut nums = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
// Transform sequentially
nums.iter_mut().for_each(|n| *n *= 2);
dbg!(nums);
```

With [rayon](https://docs.rs/rayon/1.3.0/rayon/) it is easy to perform the same operation in parallel by using `par` iterators instead,

```rust
use rayon::prelude::*;

let mut nums = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
// Transform in parallel
nums.iter_mut().for_each(|n| *n *= 2);
dbg!(nums);
```


# Optimisations


# Cache alignment


# TODO

* [ ] String processing
  * [ ] Regex
  * [ ] Two way
* [ ] Concurrency
  * [ ] Actix actor model
* [ ] Parallelism
  * [ ] Rayon
* [ ] Services
  * [ ] GRPC services
  * [ ] REST web servcies
* [ ] Monitoring
  * [ ] Logging
  * [ ] Tracing
* [ ] Benchmarking   &#x20;
* [ ] Mocking   &#x20;


