# Rust Basics

Rust concepts used in this project, explained for beginners.

## Table of Contents

- [Ownership & Borrowing](#ownership--borrowing)
- [Structs & Enums](#structs--enums)
- [Option & Result](#option--result)
- [Error Handling](#error-handling)
- [Modules](#modules)
- [Traits](#traits)
- [Async/Await](#asyncawait)
- [Common Patterns](#common-patterns)

---

## Ownership & Borrowing

Rust's killer feature. Every value has exactly one owner.

### Ownership

```rust
let s1 = String::from("hello");  // s1 owns the string
let s2 = s1;                      // Ownership MOVES to s2
// println!("{}", s1);            // ERROR! s1 no longer valid
```

### Borrowing with References

Instead of moving, we can borrow:

```rust
let s1 = String::from("hello");
let len = calculate_length(&s1);  // Borrow s1 (immutable reference)
println!("{} has length {}", s1, len);  // s1 still valid!

fn calculate_length(s: &String) -> usize {
    s.len()
}
```

### Mutable References

```rust
let mut s = String::from("hello");
change(&mut s);  // Mutable borrow

fn change(s: &mut String) {
    s.push_str(" world");  // Can modify!
}
```

### In Our Code

```rust
// In transform.rs
pub fn transform_request(body: &str) -> Option<String> {
//                            ^^^^
//                            Borrows the string, doesn't take ownership
```

---

## Structs & Enums

### Structs (like classes/objects)

```rust
pub struct OAuthTokens {
    pub access_token: String,
    pub refresh_token: String,
    pub expires_at: u64,
}

// Implementation block - where methods live
impl OAuthTokens {
    // Method that borrows self
    pub fn is_expired(&self) -> bool {
        let now = /* get current time */;
        self.expires_at < now
    }
}
```

### Enums (tagged unions)

```rust
pub enum AuthMode {
    Max,      // Variant 1
    Console,  // Variant 2
}

// Enums can hold data too
pub enum Error {
    Http(reqwest::Error),           // Holds an error
    TokenRefresh { status: u16 },   // Holds named fields
    OAuth(String),                  // Holds a string
}
```

### In Our Code

```rust
// In oauth.rs
pub enum AuthMode {
    Max,      // Claude Pro/Max (claude.ai)
    Console,  // API Console (console.anthropic.com)
}

impl AuthMode {
    fn host(&self) -> &'static str {
        match self {
            AuthMode::Max => "claude.ai",
            AuthMode::Console => "console.anthropic.com",
        }
    }
}
```

---

## Option & Result

Rust has no null. Instead, we use `Option` and `Result`.

### Option - Maybe a Value

```rust
enum Option<T> {
    Some(T),  // Has a value
    None,     // No value
}

// Usage
let maybe_number: Option<i32> = Some(42);
let nothing: Option<i32> = None;

// Extract the value
match maybe_number {
    Some(n) => println!("Got: {}", n),
    None => println!("Nothing here"),
}

// Or use if let
if let Some(n) = maybe_number {
    println!("Got: {}", n);
}
```

### Result - Success or Error

```rust
enum Result<T, E> {
    Ok(T),   // Success with value
    Err(E),  // Error with error info
}

// Usage
fn divide(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err("Cannot divide by zero".to_string())
    } else {
        Ok(a / b)
    }
}
```

### In Our Code

```rust
// In transform.rs
pub fn transform_request(body: &str) -> Option<String> {
    let mut parsed: Value = serde_json::from_str(body).ok()?;
    //                                                 ^^^^^^
    //  .ok() converts Result to Option
    //  ?     returns None if it's None, otherwise unwraps

    serde_json::to_string(&parsed).ok()
    //                            ^^^^
    //  Returns Option<String>
}
```

---

## Error Handling

### The ? Operator

The `?` operator is magic for error handling:

```rust
// Without ?
fn read_file() -> Result<String, Error> {
    let content = match std::fs::read_to_string("file.txt") {
        Ok(c) => c,
        Err(e) => return Err(e.into()),
    };
    Ok(content)
}

// With ? (equivalent, but cleaner)
fn read_file() -> Result<String, Error> {
    let content = std::fs::read_to_string("file.txt")?;
    Ok(content)
}
```

### thiserror Crate

We use `thiserror` to define errors easily:

```rust
use thiserror::Error;

#[derive(Error, Debug)]
pub enum Error {
    #[error("HTTP request failed: {0}")]
    Http(#[from] reqwest::Error),
    //   ^^^^^^
    //   Auto-converts reqwest::Error into our Error::Http

    #[error("Token refresh failed: {status}")]
    TokenRefresh { status: u16 },
}
```

### In Our Code

```rust
// In oauth.rs
pub async fn exchange(&self, code: &str, verifier: &str) -> Result<OAuthTokens> {
    let response = self.client
        .post("https://console.anthropic.com/v1/oauth/token")
        .json(&body)
        .send()
        .await?;  // If this fails, return Error::Http automatically

    if !response.status().is_success() {
        return Err(Error::OAuth("Token exchange failed".into()));
    }

    // ... rest of function
}
```

---

## Modules

Rust organizes code into modules.

### File Structure

```
src/
├── lib.rs           # Crate root
├── error.rs         # src/error.rs -> mod error
├── pkce.rs          # src/pkce.rs -> mod pkce
└── anthropic/
    ├── mod.rs       # src/anthropic/mod.rs -> mod anthropic
    ├── oauth.rs     # Declared in mod.rs
    ├── client.rs
    └── transform.rs
```

### Declaring Modules

```rust
// In lib.rs
pub mod error;      // Look for src/error.rs
pub mod pkce;       // Look for src/pkce.rs
pub mod anthropic;  // Look for src/anthropic/mod.rs

// Re-export for convenience
pub use error::{Error, Result};
```

```rust
// In anthropic/mod.rs
mod oauth;      // Private submodule
mod client;
mod transform;

// Re-export public items
pub use oauth::{AuthMode, OAuthTokens, AnthropicOAuth};
pub use client::AnthropicClient;
```

### Visibility

```rust
pub struct Foo;        // Public (accessible from outside)
struct Bar;            // Private (only this module)
pub(crate) struct Baz; // Public within crate only
```

---

## Traits

Traits are like interfaces - they define shared behavior.

### Defining a Trait

```rust
trait Greet {
    fn greet(&self) -> String;
}
```

### Implementing a Trait

```rust
struct Person {
    name: String,
}

impl Greet for Person {
    fn greet(&self) -> String {
        format!("Hello, I'm {}", self.name)
    }
}
```

### Derive Macros

Common traits can be auto-implemented:

```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OAuthTokens {
    pub access_token: String,
    pub refresh_token: String,
    pub expires_at: u64,
}

// Now we can:
println!("{:?}", tokens);           // Debug
let copy = tokens.clone();          // Clone
serde_json::to_string(&tokens);     // Serialize
```

---

## Async/Await

Rust's async is zero-cost and requires a runtime (we use Tokio).

### Basic Async

```rust
// Async function returns a Future
async fn fetch_data() -> Result<String> {
    let response = reqwest::get("https://api.example.com")
        .await?;  // Wait for the HTTP request

    let text = response.text()
        .await?;  // Wait for body

    Ok(text)
}
```

### Running Async Code

```rust
// In main, use #[tokio::main]
#[tokio::main]
async fn main() {
    let result = fetch_data().await;
}
```

### In Our Code

```rust
// In client.rs
pub async fn messages(&self, body: &str) -> Result<String> {
    let access_token = self.get_access_token().await?;

    let response = self.http
        .post("https://api.anthropic.com/v1/messages")
        .headers(headers)
        .body(transformed_body)
        .send()
        .await?;  // Async HTTP request

    let text = response.text().await?;
    Ok(text)
}
```

---

## Common Patterns

### Builder Pattern

```rust
let response = client
    .post(url)           // Returns builder
    .headers(headers)    // Chain methods
    .body(body)
    .send()              // Finally execute
    .await?;
```

### Pattern Matching

```rust
// Match on enum
match result {
    Ok(value) => println!("Got: {}", value),
    Err(e) => eprintln!("Error: {}", e),
}

// If let for single case
if let Some(tools) = parsed.get("tools") {
    // Do something with tools
}

// While let
while let Some(item) = iterator.next() {
    // Process item
}
```

### Closures

```rust
// Inline functions
let add = |a, b| a + b;
println!("{}", add(2, 3));  // 5

// Used with iterators
let numbers = vec![1, 2, 3];
let doubled: Vec<_> = numbers.iter().map(|x| x * 2).collect();
```

### String Types

```rust
// String - owned, heap-allocated, mutable
let mut s = String::from("hello");
s.push_str(" world");

// &str - borrowed string slice, immutable
let slice: &str = "hello";
let slice2: &str = &s[0..5];

// Converting
let owned: String = slice.to_string();
let borrowed: &str = &owned;
```

---

## Next Steps

- Read [The Rust Book](https://doc.rust-lang.org/book/) (free online)
- Try [Rustlings](https://github.com/rust-lang/rustlings) exercises
- Check out [Rust by Example](https://doc.rust-lang.org/rust-by-example/)
