Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions rust_session/Assignemnt/student_registry/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions rust_session/Assignemnt/student_registry/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[package]
name = "student_registry"
version = "0.1.0"
edition = "2021"
104 changes: 104 additions & 0 deletions rust_session/Assignemnt/student_registry/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Rust Student Registry
### A beginner project covering: `struct` · `Vec<T>` · `enum` · `Option<T>` · `impl`

```bash
// ============================================================
// STUDENT REGISTRY — Beginner Rust Project
// Concepts covered:
// • struct — grouping related data
// • enum — a value that can be one of several variants
// • Vec<T> — a growable list
// • Option<T> — a value that may or may not exist
// • impl block — adding methods to a struct
// • pattern matching (match, if let)
// • ownership & borrowing in practice
// ============================================================
```

---

## How to run

### Step 1 — Install Rust (if you haven't yet)
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
Then restart your terminal, or run:
```bash
source "$HOME/.cargo/env"
```

### Step 2 — Verify the install
```bash
rustc --version # e.g. rustc 1.78.0
cargo --version # e.g. cargo 1.78.0
```

### Step 3 — Run the project
```bash
# Clone / copy this folder, then:
cd student_registry

cargo run # compiles + runs in one command
```

### Other useful commands
```bash
cargo build # compile only (output goes to ./target/debug/)
cargo check # fast type-check without producing a binary (great while learning)
cargo run --release # compile with full optimisations (faster binary)
```

---

## What the project teaches

| Concept | Where to look in main.rs |
|---|---|
| `struct` | `Student` and `Registry` definitions (~line 30, 90) |
| `enum` | `Grade` definition (~line 14) |
| `impl` block | `impl Grade`, `impl Student`, `impl Registry` |
| `Vec<T>` | `Registry.students` field; `push`, `retain`, `iter` |
| `Option<T>` | `find_by_name`, `find_by_id` return types; `demo_option()` |
| `match` | `Grade::as_str`, `letter_grade`, search demos |
| `if let` | `update_score`, `summary`, `demo_option` |
| Ownership / borrowing | `&self` vs `&mut self` on every method |
| Iterator methods | `summary()` — `.map()`, `.sum()`, `.max_by()` |

---

## Expected output (abridged)

```
╔══════════════════════════════════════╗
║ RUST STUDENT REGISTRY v1.0 ║
║ struct · Vec · enum · Option · impl ║
╚══════════════════════════════════════╝

┌─ 1. Adding students (struct + Vec::push)
✅ Added: Kay (ID 1)
✅ Added: Yusrah (ID 2)
...

┌─ 3. Search by name (Option<&Student>)
Found → ID: 2 Grade: 2nd Year Score: 64
'Yaw Owusu' not found in registry.

┌─ 8. Summary (iterators: map, sum, max_by)
Total students : 4
Average score : 71.5
Top student : Esi Boateng (91.0)
```

---

## Project structure

```
student_registry/
├── Cargo.toml ← project metadata & dependencies
└── src/
└── main.rs ← all code lives here (heavily annotated)
```

Everything is in one file intentionally — beginners don't need to navigate modules yet.
167 changes: 167 additions & 0 deletions rust_session/Assignemnt/student_registry/notes/borrowing_deep_dive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# Borrowing Deep Dive
Borrowing is like lending something to a friend.

---

## The core idea

```rust
fn main() {
let book = String::from("Rust Programming");

read(&book); // lend the book to `read`

// book is still yours after the function returns
println!("I still have: {}", book);
}

fn read(b: &String) { // b is a borrowed reference — not the owner
println!("Reading: {}", b);
} // borrow ends here — nothing is dropped
```

You still own `book`. `read` just borrowed it temporarily. When `read` finishes,
the book comes back to you automatically.

---

## Without borrowing — ownership moves away

```rust
fn main() {
let book = String::from("Rust Programming");

read(book); // ownership MOVES into read — you no longer have it

println!("{}", book); // ❌ compile error: book was moved
}

fn read(b: String) { // b owns the book now
println!("Reading: {}", b);
} // b is dropped here — book is gone forever
```

This is why borrowing exists. Without `&`, the value moves in and never comes back.

---

## Two kinds of borrow

### 1. Immutable borrow `&T` — look but don't touch

```rust
fn main() {
let score = 95;

print_score(&score); // lend score for reading

println!("score is still {}", score); // ✅ still usable
}

fn print_score(s: &i32) {
println!("Score: {}", s);
// *s = 100; // ❌ can't change it — it's an immutable borrow
}
```

### 2. Mutable borrow `&mut T` — borrow AND change it

```rust
fn main() {
let mut score = 95; // must be `mut` to lend mutably

add_bonus(&mut score); // lend score for writing

println!("new score: {}", score); // 100
}

fn add_bonus(s: &mut i32) {
*s += 5; // * means "go to what this points to and change it"
}
```

---

## The two rules Rust enforces

### Rule 1 — as many readers as you like

```rust
fn main() {
let name = String::from("Henry");

let r1 = &name; // borrow 1 — fine
let r2 = &name; // borrow 2 — also fine
let r3 = &name; // borrow 3 — still fine

println!("{} {} {}", r1, r2, r3); // ✅ multiple readers are safe
}
```

Think of a book in a library — unlimited people can read the same book at the
same time because no one is changing it.

### Rule 2 — only ONE writer, and no readers at the same time

```rust
fn main() {
let mut name = String::from("Henry");

let r1 = &name; // immutable borrow
let r2 = &mut name; // ❌ compile error — can't have &mut while &name exists

println!("{} {}", r1, r2);
}
```

```rust
fn main() {
let mut name = String::from("Henry");

let r1 = &name;
println!("{}", r1); // r1 last used here — borrow ends

let r2 = &mut name; // ✅ fine now — r1 is done
r2.push_str(" Osei");
println!("{}", r2); // "Henry Osei"
}
```

Think of a whiteboard — unlimited people can read it, but the moment someone
starts writing on it, everyone else has to step back.

---

## In the student registry

```rust
// &mut self — we need to CHANGE the registry (push a new student)
pub fn add(&mut self, name: &str, ...) {
// ^^^
// mutable borrow — we will modify self.students

self.students.push(student); // this is the change
}

// &self — we only READ the registry (print students)
pub fn list_all(&self) {
// ^^^^^
// immutable borrow — we never change anything

for student in &self.students { // borrow each student for printing
println!("{}", student.name);
}
}
```

---

## One-line mental model

```
&T → "I want to look at it"
&mut T → "I want to look at it AND change it"
T → "I want to own it and take it with me"
```

Rust checks these rules at compile time — zero runtime cost, zero crashes.
Loading
Loading