diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e126300dc5192775b9516ea65e2e307b2b68daf3..2cb69b4ab02eec99607328a0280f843fd4ca4f95 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,6 +2,14 @@
 # https://hub.docker.com/r/library/rust/tags/
 image: "rust:1.70-alpine3.17"
 # Use cargo to test the project
+before_script:
+  - apk add --no-cache musl-dev curl
+  - mkdir -p $HOME/.cargo/bin
+  - which rustc
+  - which cargo
+  - curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.31/mdbook-v0.4.31-x86_64-unknown-linux-musl.tar.gz | tar -xz --directory=$HOME/.cargo/bin
+  - export PATH=$PATH:$HOME/.cargo/bin
+
 test:cargo:
   script:
     - rustc --version && cargo --version  # Print version info for debugging
@@ -10,3 +18,5 @@ run_test_doc:
   script:
     - cd codes
     - ./run_tests.sh
+    - cd ../book
+    - mdbook build
diff --git a/book/.gitignore b/book/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..7585238efedfc33acdd9494b0269951aaf3909ec
--- /dev/null
+++ b/book/.gitignore
@@ -0,0 +1 @@
+book
diff --git a/book/book.toml b/book/book.toml
new file mode 100644
index 0000000000000000000000000000000000000000..9a31d1e76990f25a14ecdbc82df88213983dd9dd
--- /dev/null
+++ b/book/book.toml
@@ -0,0 +1,6 @@
+[book]
+authors = ["Orestis Malaspinas, Michaël El Kharroubi"]
+language = "fr"
+multilingual = false
+src = "src"
+title = "Rust-101: Université d'été"
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
new file mode 100644
index 0000000000000000000000000000000000000000..99b1e890d5924a70d36a9347c3ed2e9dd709433d
--- /dev/null
+++ b/book/src/SUMMARY.md
@@ -0,0 +1,3 @@
+# Summary
+
+- [Part 00](./part00.md)
diff --git a/book/src/part00.md b/book/src/part00.md
new file mode 100644
index 0000000000000000000000000000000000000000..8d091e451deff80d3f744127d0d7235a14059d9e
--- /dev/null
+++ b/book/src/part00.md
@@ -0,0 +1,160 @@
+# Discussion du code `part00`
+
+## Préambule
+
+Ce court texte n'a pas vocation à remplacer un cours complet, mais à rappeler les concepts importants vus dans chaque partie du cours.
+
+Les codes discutés ont tous pour but de calculer la valeur minimale d'entiers contenus dans un tableau. La difficulté
+et l'élégance de ces codes ira en augmentant pour illustrer de façon itératives les différents concepts du présents
+dans le langage.
+
+### Installation du compilateur Rust
+
+Afin d'installer le compilateur Rust, il n'est pas recommandé d'utiliser votre gestionnaire de paquet,
+mais plutôt de télécharger toute la chaîne de compilation grâce à l'outil [rustup](https://www.rust-lang.org/tools/install).
+Ou alors d'exécuter la commande suivante dans un terminal
+```bash
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+Ce script installera pour vous le gestionnaire de paquet et de compilation `cargo`,
+le compilateur `rustc`, ainsi que le linter `clippy` et l'outil de formatage de code
+`rustfmt`.
+
+Vous pouvez maintenant créer un nouveau projet rust (astucieusement nommé `new_project`) avec la commande
+```bash
+cargo new new_project
+```
+Cette commande crée un répertoire `new_project`, ainsi que les fichiers `new_project/Cargo.toml` et `new_project/main.rs`.
+
+Vous pouvez compiler votre programme avec 
+```bash
+cargo build
+```
+Puis l'exécuter à l'aide de la commande
+```bash
+cargo run
+```
+
+La commande cargo run dépend de l'étape de compilation, par conséquent si le code n'est pas compilé, alors la commande `cargo run` lancera la compilation avant d'exécuter votre programme.
+
+Il est également possible de nettoyer les artéfacts de compilation ainsi que l'exécutable à l'aide de la commande
+
+```bash
+cargo clean
+```
+
+## Concepts
+
+Les concepts abordés dans cet exemple sont:
+
+1. [Les variables mutables ou non, les constantes.](#variables-variables-mutables-et-constantes)
+2. [Les structures de contrôle `if ... else` et `for`.](#structures-de-contrôle)
+3. [L'utilisation de tableaux statiques.](#structures-de-contrôle)
+4. [L'utilisation de macros pour la gestion d'erreurs ou les sorties dans le terminal.](#macros)
+
+## Discussion
+
+Chaque code Rust a un unique point d'entrée: la fonction `fn main() {}`.
+Ainsi, le code le plus simple (qui ne fait absolument rien) est.
+```rust,no_run
+fn main() {
+}
+```
+Le corps de votre programme se trouvera donc entre les accolades.
+
+### Variables, variables mutables, et constantes
+
+Dans l'ordre d'apparition, nous avons d'abord une **constante** nommée SIZE, dont le type est `usize` (entier non signé dont la taille dépend de l'architecture, 8 octets sur une architecture 64 bits) et qui vaut `9`. Le nom du type vient après `:`.
+```rust,no_run
+const SIZE: usize = 9;
+```
+Ensuite nous déclarons un tableau statique (alloué sur la pile) d'entiers 32 bits et de taille `SIZE`.
+```rust,no_run
+# const SIZE: usize = 9;
+let tab: [i32; SIZE] = [10, 32, 12, 43, 52, 53, 83, 2, 9];
+```
+Vous notez le mot clé `let` qui permet de déclarer une variable **immutables** (les valeurs contenues dans `tab` ou sa taille ne pourront plus changer). On dit qu'on **lie** (ou **bind** en anglais) `tab` à la valeur du `[10, 32, 12, 43, 52, 53, 83, 2, 9]`. Plus bas nous déclarons au contraire une variable **mutable** (qui elle pourra changer de valeur au cours de l'exécution du programme).
+```rust
+# const SIZE: usize = 9;
+# let tab: [i32; SIZE] = [10, 32, 12, 43, 52, 53, 83, 2, 9];
+let mut min = tab[0];
+```
+et l'initialisons avec la valeur du 1er élément de `tab` (ici la valeur est `10`).
+
+### Structures de contrôle
+
+Nous avons deux `if` dans ce code. Dans le premier
+```rust,should_panic
+const SIZE: usize = 0;
+if SIZE == 0 {
+    panic!("Size is of tab = 0.");
+}
+```
+nous testons si `SIZE == 0` et utilisons la macro `panic!` qui lorsqu'elle est exécutée fait quitter le programme et
+affiche le message d'erreur en argument. Ainsi le code ci-dessus retourne:
+```bash
+   Compiling playground v0.0.1 (/playground)
+    Finished dev [unoptimized + debuginfo] target(s) in 0.56s
+     Running `target/debug/playground`
+thread 'main' panicked at 'Size is of tab = 0.', src/main.rs:5:5
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+```
+
+Dans le second cas, nous sommes dans une boucle `for`
+```rust,no_run
+# const SIZE: usize = 9;
+# let tab: [i32; SIZE] = [10, 32, 12, 43, 52, 53, 83, 2, 9];
+let mut min = tab[0];
+for i in 1..SIZE {
+    if min > tab[i] {
+        min = tab[i];
+    }
+}
+```
+où l'indice `i` prend successivement les valeur `1` à `SIZE-1` (la notation `a..b` veut dire de `a` à `b` non inclus) et assignons
+la valeur `tab[i]` à la *variable mutable* `min`. Si nous avions omis le mot clé `mut` lors de la déclaration de `min` l'assignation
+donnerait une erreur (cliquez sur "play" pour la démonstration)
+```rust,compile_fail
+# const SIZE: usize = 9;
+# let tab: [i32; SIZE] = [10, 32, 12, 43, 52, 53, 83, 2, 9];
+let min = tab[0];
+for i in 1..SIZE {
+    if min > tab[i] {
+        min = tab[i];
+    }
+}
+```
+
+
+### Macros
+
+Outre la macro `panic!()` nous utilisons ici deux macros permettant d'afficher des chaînes de caractère
+dans le terminal. Les macros sont toujours identifiées à l'aide du `!` se trouvant à la fin de l'appel,
+comme pour `panic!()`, `print!()` (affiche la chaîne de caractère en argument) ou `println!()` (qui est comme `print!()` mais
+retourne à la ligne après avoir affiché). Comme on le voit dans les lignes suivantes
+```rust
+# const SIZE: usize = 9;
+# let tab: [i32; SIZE] = [10, 32, 12, 43, 52, 53, 83, 2, 9];
+# let mut min = tab[0];
+# for i in 1..SIZE {
+#     if min > tab[i] {
+#         min = tab[i];
+#     }
+# }
+println!("Among the numbers in the list:");
+for i in 0..SIZE {
+    print!("{} ", tab[i]);
+}
+println!();
+```
+le formatage de la ligne de caractère se fait à l'aide des accolades `{}` et les macros `print!()` / `println!()` prennent un nombre
+d'arguments variables. A chaque `{}` doit correspondre une variable dont on veut afficher le contenu.
+
+Il est également possible de numéroter chaque `{}`. Par exemple 
+```rust
+println!("{1} {0}", "abc", "def");
+```
+
+Affichera `def abc`.
+
+
diff --git a/codes/rust_lang/part05/src/main.rs b/codes/rust_lang/part05/src/main.rs
index a135c6aad37e6df02c942cafdf3ba33da2cb54df..936bf3c28f8e4386d0aff407f4d8d6d4f330f27e 100644
--- a/codes/rust_lang/part05/src/main.rs
+++ b/codes/rust_lang/part05/src/main.rs
@@ -123,7 +123,8 @@ fn read_command_line() -> [i32; SIZE] {
     [10, 32, 12, 43, 52, 53, 83, 2, 9]
 }
 
-/// Prints all the elements of the `tab` and returns `tab`.
+/// Prints all the elements of the `tab`.
+/// Tab is borrowed here
 fn print_tab(tab: &[i32; SIZE]) {
     for t in tab {
         print!("{} ", t);
@@ -132,7 +133,7 @@ fn print_tab(tab: &[i32; SIZE]) {
 }
 
 /// Computes the minimum of an Array of a type T which implements the [Minimum] trait.
-/// Returns the array and a [SomethingOrNothing::Something] containing the the minimum value
+/// Returns a [SomethingOrNothing::Something] containing the the minimum value
 /// or [SomethingOrNothing::Nothing] if no minimum value was found.
 ///
 /// # Example
@@ -145,20 +146,18 @@ fn print_tab(tab: &[i32; SIZE]) {
 /// # }
 /// ```
 fn find_min<T: Minimum>(tab: &[T; SIZE]) -> SomethingOrNothing<T> {
-    let mut min = SomethingOrNothing::Nothing;
-    // Here is T is not Copyable tab is consumed and cannot be returned
+    let mut minimum = SomethingOrNothing::Nothing;
+    // Here is T is Copyable. Which means that t is not moved in the loop
     for t in tab {
-        min = min.min(SomethingOrNothing::Something(*t));
+        minimum = minimum.min(SomethingOrNothing::Something(*t));
     }
-    min
+    minimum
 }
 
 fn main() {
     let tab = read_command_line();
-
     println!("Among the Somethings in the list:");
     print_tab(&tab);
-
     // There are alternatives to access fields of tuples
     let min = find_min(&tab);
     // The first field is not used therefore we can replace it with "_"
diff --git a/codes/rust_lang/part08/src/big_int.rs b/codes/rust_lang/part08/src/big_int.rs
new file mode 100644
index 0000000000000000000000000000000000000000..d52815b485df22c780b8d2363d7b32da3384521f
--- /dev/null
+++ b/codes/rust_lang/part08/src/big_int.rs
@@ -0,0 +1,117 @@
+use crate::minimum::Minimum;
+
+/// Larger ints based on a [Vec] of [u8] to repensent arbitrary lengthy numbers.
+/// The number has a sign as well.
+pub struct BigInt {
+    /// The data contains the unsigned integers that are read from right to left
+    /// The number 1337 is stored as vec![7, 3, 3, 1]. Each number must be in the range [0,9]
+    /// and no trailing 0s are allowed.
+    data: Vec<u8>,
+    /// Contains the sign of the number +/-1;
+    sign: i8,
+}
+
+impl BigInt {
+    /// Tries to create a new [BigInt]. If the number is valid it returns
+    /// an Ok(BigInt) an Error otherwise.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use part08::big_int::BigInt;
+    /// let num = BigInt::try_new(vec![1, 2, 3, 4], 1);
+    /// assert!(num.is_ok());
+    /// let num = BigInt::try_new(vec![1, 2, 3, 4], -1);
+    /// assert!(num.is_ok());
+    /// let num = BigInt::try_new(vec![1, 2, 3, 4], 10);
+    /// assert!(num.is_err());
+    /// let num = BigInt::try_new(vec![1, 2, 3, 4], -10);
+    /// assert!(num.is_err());
+    /// ```
+    ///
+    pub fn try_new(data: Vec<u8>, sign: i8) -> Result<Self, String> {
+        // EXERCISE:
+        // We don't check for trailing 0s but maybe this could be an exercise.
+        // Also we should check numbers are between 0 and 9.
+        if sign == 1 || sign == -1 {
+            Ok(BigInt { data, sign })
+        } else {
+            Err(String::from("Invalid sign."))
+        }
+    }
+}
+
+impl Clone for BigInt {
+    fn clone(&self) -> Self {
+        BigInt {
+            data: self.data.clone(),
+            sign: self.sign,
+        }
+    }
+}
+
+impl Minimum for BigInt {
+    // EXERCISE: Correct this function by using clippy and let it guide you.
+    //           Get inspiration from Display to compute the Minimum
+    fn min(self, rhs: Self) -> Self {
+        if self.sign < rhs.sign {
+            return self;
+        } else if self.sign > rhs.sign {
+            return rhs;
+        }
+        if self.data.len() < rhs.data.len() {
+            return self;
+        } else if self.data.len() > rhs.data.len() {
+            return rhs;
+        }
+        for (l, r) in self.data.iter().rev().zip(rhs.data.iter().rev()) {
+            let ls = (*l as i8) * self.sign;
+            let rs = (*r as i8) * self.sign;
+            if ls < rs {
+                return self;
+            } else if ls > rs {
+                return rhs;
+            }
+        }
+        self
+    }
+}
+
+impl PartialEq for BigInt {
+    fn eq(&self, other: &Self) -> bool {
+        if self.sign == other.sign && self.data.len() == other.data.len() {
+            self.data
+                .iter()
+                .zip(other.data.iter())
+                .try_fold(true, |_, (l, r)| if l == r { Some(true) } else { None })
+                .is_some()
+        } else {
+            false
+        }
+    }
+}
+
+impl std::fmt::Display for BigInt {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        // This could be replaced by an `?`
+        if self.sign == -1 {
+            if let Err(e) = write!(f, "-") {
+                return Err(e);
+            }
+        }
+
+        // This could be replaced by an `?`
+        let res = self
+            .data
+            .iter()
+            .rev()
+            .try_fold((), |_, t| write!(f, "{}", t));
+        res
+    }
+}
+
+// EXERCISE: write tests
+// EXERCISE: Modify Minimum trait to take references?
+
+#[cfg(test)]
+mod tests {}