Skip to content
Merged
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
2 changes: 1 addition & 1 deletion csharp-book/src/ch13-concurrency.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
>
> **Difficulty:** 🔴 Advanced

> **Deep dive**: For production async patterns (stream processing, graceful shutdown, connection pooling, cancellation safety), see the companion [Async Rust Training](../../source-docs/ASYNC_RUST_TRAINING.md) guide.
> **Deep dive**: For production async patterns (stream processing, graceful shutdown, connection pooling, cancellation safety), see the companion [Async Rust Training](../../async-book/src/summary.md) guide.
>
> **Prerequisites**: [Ownership & Borrowing](ch07-ownership-and-borrowing.md) and [Smart Pointers](ch07-3-smart-pointers-beyond-single-ownership.md) (Rc vs Arc decision tree).

Expand Down
2 changes: 1 addition & 1 deletion csharp-book/src/ch14-unsafe-rust-and-ffi.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

Unsafe Rust allows you to perform operations that the borrow checker cannot verify. Use it sparingly and with clear documentation.

> **Advanced coverage**: For safe abstraction patterns over unsafe code (arena allocators, lock-free structures, custom vtables), see [Rust Patterns](../../source-docs/RUST_PATTERNS.md).
> **Advanced coverage**: For safe abstraction patterns over unsafe code (arena allocators, lock-free structures, custom vtables), see [Rust Patterns](../../rust-patterns-book/src/summary.md).

### When You Need Unsafe
```rust
Expand Down
8 changes: 4 additions & 4 deletions csharp-book/src/ch16-3-rust-tooling-ecosystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ cargo expand module_name # Expand specific module

For deeper exploration of advanced topics mentioned in this guide, see the companion training documents:

- **[Rust Patterns](../../source-docs/RUST_PATTERNS.md)** — Pin projections, custom allocators, arena patterns, lock-free data structures, and advanced unsafe patterns
- **[Async Rust Training](../../source-docs/ASYNC_RUST_TRAINING.md)** — Deep dive into tokio, async cancellation safety, stream processing, and production async architectures
- **[Rust Training for C++ Developers](./RUST_TRAINING_FOR_CPP.md)** — Useful if your team also has C++ experience; covers move semantics mapping, RAII differences, and template vs generics
- **[Rust Training for C Developers](./RUST_TRAINING_FOR_C.md)** — Relevant for interop scenarios; covers FFI patterns, embedded Rust debugging, and `no_std` programming
- **[Rust Patterns](../../rust-patterns-book/src/SUMMARY.md)** — Pin projections, custom allocators, arena patterns, lock-free data structures, and advanced unsafe patterns
- **[Async Rust Training](../../async-book/src/SUMMARY.md)** — Deep dive into tokio, async cancellation safety, stream processing, and production async architectures
- **[Rust Training for C++ Developers](../../c-cpp-book/src/SUMMARY.md)** — Useful if your team also has C++ experience; covers move semantics mapping, RAII differences, and template vs generics
- **[Rust Training for C Developers](../../c-cpp-book/src/SUMMARY.md)** — Relevant for interop scenarios; covers FFI patterns, embedded Rust debugging, and `no_std` programming
12 changes: 6 additions & 6 deletions type-driven-correctness-book/src/ch00-introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

---

A practical guide to using Rust's type system to make entire classes of bugs **impossible to compile**. While the companion [Rust Patterns](../rust-patterns-book/index.html) book covers the mechanics (traits, associated types, type-state), this guide shows how to **apply** those mechanics to real-world domains — hardware diagnostics, cryptography, protocol validation, and embedded systems.
A practical guide to using Rust's type system to make entire classes of bugs **impossible to compile**. While the companion [Rust Patterns](../../rust-patterns-book/src/SUMMARY.md) book covers the mechanics (traits, associated types, type-state), this guide shows how to **apply** those mechanics to real-world domains — hardware diagnostics, cryptography, protocol validation, and embedded systems.

Every pattern here follows one principle: **push invariants from runtime checks into the type system so the compiler enforces them.**

Expand Down Expand Up @@ -61,11 +61,11 @@ Every pattern here follows one principle: **push invariants from runtime checks

| Concept | Where to learn it |
|---------|-------------------|
| Ownership and borrowing | [Rust Patterns](../rust-patterns-book/index.html), ch01 |
| Traits and associated types | [Rust Patterns](../rust-patterns-book/index.html), ch02 |
| Newtypes and type-state | [Rust Patterns](../rust-patterns-book/index.html), ch03 |
| PhantomData | [Rust Patterns](../rust-patterns-book/index.html), ch04 |
| Generics and trait bounds | [Rust Patterns](../rust-patterns-book/index.html), ch01 |
| Ownership and borrowing | [Rust Patterns](../rust-patterns-book/src/SUMMARY.md), ch01 |
| Traits and associated types | [Rust Patterns](../rust-patterns-book/src/SUMMARY.md), ch02 |
| Newtypes and type-state | [Rust Patterns](../rust-patterns-book/src/SUMMARY.md), ch03 |
| PhantomData | [Rust Patterns](../rust-patterns-book/src/SUMMARY.md), ch04 |
| Generics and trait bounds | [Rust Patterns](../rust-patterns-book/src/SUMMARY.md), ch01 |

## The Correct-by-Construction Spectrum

Expand Down
67 changes: 60 additions & 7 deletions xtask/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,68 @@ fn write_landing_page(site: &Path) {
println!(" ✓ index.html");
}

/// Resolve `request_target` (HTTP request path, e.g. `/foo/bar?x=1`) to a file under `site_canon`.
/// Returns `None` for traversal attempts, missing files, or paths that escape `site_canon` (symlinks).
fn resolve_site_file(site_canon: &Path, request_target: &str) -> Option<PathBuf> {
let path_only = request_target.split('?').next()?.split('#').next()?;
let decoded = percent_decode_path(path_only);
if decoded.as_bytes().contains(&0) {
return None;
}
let rel = decoded.trim_start_matches('/');
let mut file_path = site_canon.to_path_buf();
if !rel.is_empty() {
for seg in rel.split('/').filter(|s| !s.is_empty()) {
if seg == ".." {
return None;
}
file_path.push(seg);
}
}
if file_path.is_dir() {
file_path.push("index.html");
}
let real = fs::canonicalize(&file_path).ok()?;
if !real.starts_with(site_canon) {
return None;
}
real.is_file().then_some(real)
}

fn hex_val(c: u8) -> Option<u8> {
match c {
b'0'..=b'9' => Some(c - b'0'),
b'a'..=b'f' => Some(c - b'a' + 10),
b'A'..=b'F' => Some(c - b'A' + 10),
_ => None,
}
}

fn percent_decode_path(input: &str) -> String {
let mut decoded = Vec::with_capacity(input.len());
let b = input.as_bytes();
let mut i = 0;
while i < b.len() {
if b[i] == b'%' && i + 2 < b.len() {
if let (Some(hi), Some(lo)) = (hex_val(b[i + 1]), hex_val(b[i + 2])) {
decoded.push(hi << 4 | lo);
i += 3;
continue;
}
}
decoded.push(b[i]);
i += 1;
}
String::from_utf8_lossy(&decoded).into_owned()
}

// ── serve ────────────────────────────────────────────────────────────

fn cmd_serve() {
let site = project_root().join("site");
let site_canon = fs::canonicalize(&site).expect(
"site/ not found — run `cargo xtask build` first (e.g. `cargo xtask serve` runs build automatically)",
);
let addr = "127.0.0.1:3000";
let listener = TcpListener::bind(addr).expect("failed to bind port 3000");

Expand All @@ -313,12 +371,7 @@ fn cmd_serve() {
.and_then(|line| line.split_whitespace().nth(1))
.unwrap_or("/");

let mut file_path = site.join(path.trim_start_matches('/'));
if file_path.is_dir() {
file_path = file_path.join("index.html");
}

if file_path.is_file() {
if let Some(file_path) = resolve_site_file(&site_canon, path) {
let body = fs::read(&file_path).unwrap_or_default();
let mime = guess_mime(&file_path);
let header = format!(
Expand Down Expand Up @@ -404,4 +457,4 @@ fn cmd_clean() {
println!("Removed {dir_name}/");
}
}
}
}