mirror of
https://github.com/microsoft/RustTraining.git
synced 2026-05-06 06:06:43 -04:00
Fix Mermaid diagrams: replace \n with <br/> for v10+ compatibility
Mermaid v10+ renders \n as literal text in node labels. Replace all 152 occurrences across 28 files with <br/> which produces proper line breaks in the rendered diagrams.
This commit is contained in:
@@ -292,12 +292,12 @@ Structs in Rust are similar to classes in C#, but with some key differences arou
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "C# Class (Heap)"
|
||||
CObj["Object Header\n+ vtable ptr"] --> CFields["Name: string ref\nAge: int\nHobbies: List ref"]
|
||||
CObj["Object Header<br/>+ vtable ptr"] --> CFields["Name: string ref<br/>Age: int<br/>Hobbies: List ref"]
|
||||
CFields --> CHeap1["#quot;Alice#quot; on heap"]
|
||||
CFields --> CHeap2["List<string> on heap"]
|
||||
end
|
||||
subgraph "Rust Struct (Stack)"
|
||||
RFields["name: String\n ptr | len | cap\nage: i32\nhobbies: Vec\n ptr | len | cap"]
|
||||
RFields["name: String<br/> ptr | len | cap<br/>age: i32<br/>hobbies: Vec<br/> ptr | len | cap"]
|
||||
RFields --> RHeap1["#quot;Alice#quot; heap buffer"]
|
||||
RFields --> RHeap2["Vec heap buffer"]
|
||||
end
|
||||
|
||||
@@ -104,12 +104,12 @@ Rust can expose C-compatible functions that C# can call via P/Invoke.
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "C# Process"
|
||||
CS["C# Code"] -->|"P/Invoke"| MI["Marshal Layer\nUTF-16 → UTF-8\nstruct layout"]
|
||||
CS["C# Code"] -->|"P/Invoke"| MI["Marshal Layer<br/>UTF-16 → UTF-8<br/>struct layout"]
|
||||
end
|
||||
MI -->|"C ABI call"| FFI["FFI Boundary"]
|
||||
subgraph "Rust cdylib (.so / .dll)"
|
||||
FFI --> RF["extern \"C\" fn\n#[no_mangle]"]
|
||||
RF --> Safe["Safe Rust\ninternals"]
|
||||
FFI --> RF["extern \"C\" fn<br/>#[no_mangle]"]
|
||||
RF --> Safe["Safe Rust<br/>internals"]
|
||||
end
|
||||
|
||||
style FFI fill:#fff9c4,color:#000
|
||||
|
||||
@@ -12,11 +12,11 @@ This capstone pulls together concepts from every part of the book. You'll build
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
CLI["main.rs\nclap CLI parser"] --> Client["client.rs\nreqwest + tokio"]
|
||||
CLI["main.rs<br/>clap CLI parser"] --> Client["client.rs<br/>reqwest + tokio"]
|
||||
Client -->|"HTTP GET"| API["Weather API"]
|
||||
Client -->|"JSON → struct"| Model["weather.rs\nserde Deserialize"]
|
||||
Model --> Display["display.rs\nfmt::Display"]
|
||||
CLI --> Err["error.rs\nthiserror"]
|
||||
Client -->|"JSON → struct"| Model["weather.rs<br/>serde Deserialize"]
|
||||
Model --> Display["display.rs<br/>fmt::Display"]
|
||||
CLI --> Err["error.rs<br/>thiserror"]
|
||||
Client --> Err
|
||||
|
||||
style CLI fill:#bbdefb,color:#000
|
||||
|
||||
@@ -544,13 +544,13 @@ flowchart TD
|
||||
START["Need compile-time work?"] -->|No| SKIP["No build.rs needed"]
|
||||
START -->|Yes| WHAT{"What kind?"}
|
||||
|
||||
WHAT -->|"Embed metadata"| P1["Pattern 1\nCompile-Time Constants"]
|
||||
WHAT -->|"Compile C/C++"| P2["Pattern 2\ncc crate"]
|
||||
WHAT -->|"Code generation"| P3["Pattern 3\nprost-build / tonic-build"]
|
||||
WHAT -->|"Link system lib"| P4["Pattern 4\npkg-config"]
|
||||
WHAT -->|"Detect features"| P5["Pattern 5\ncfg flags"]
|
||||
WHAT -->|"Embed metadata"| P1["Pattern 1<br/>Compile-Time Constants"]
|
||||
WHAT -->|"Compile C/C++"| P2["Pattern 2<br/>cc crate"]
|
||||
WHAT -->|"Code generation"| P3["Pattern 3<br/>prost-build / tonic-build"]
|
||||
WHAT -->|"Link system lib"| P4["Pattern 4<br/>pkg-config"]
|
||||
WHAT -->|"Detect features"| P5["Pattern 5<br/>cfg flags"]
|
||||
|
||||
P1 --> RERUN["Always emit\ncargo::rerun-if-changed"]
|
||||
P1 --> RERUN["Always emit<br/>cargo::rerun-if-changed"]
|
||||
P2 --> RERUN
|
||||
P3 --> RERUN
|
||||
P4 --> RERUN
|
||||
|
||||
@@ -417,17 +417,17 @@ linker = "musl-gcc"
|
||||
flowchart TD
|
||||
START["Need to cross-compile?"] --> STATIC{"Static binary?"}
|
||||
|
||||
STATIC -->|Yes| MUSL["musl target\n--target x86_64-unknown-linux-musl"]
|
||||
STATIC -->|Yes| MUSL["musl target<br/>--target x86_64-unknown-linux-musl"]
|
||||
STATIC -->|No| GLIBC{"Need old glibc?"}
|
||||
|
||||
GLIBC -->|Yes| ZIG["cargo-zigbuild\n--target x86_64-unknown-linux-gnu.2.17"]
|
||||
GLIBC -->|Yes| ZIG["cargo-zigbuild<br/>--target x86_64-unknown-linux-gnu.2.17"]
|
||||
GLIBC -->|No| ARCH{"Target arch?"}
|
||||
|
||||
ARCH -->|"Same arch"| NATIVE["Native toolchain\nrustup target add + linker"]
|
||||
ARCH -->|"Same arch"| NATIVE["Native toolchain<br/>rustup target add + linker"]
|
||||
ARCH -->|"ARM/other"| DOCKER{"Docker available?"}
|
||||
|
||||
DOCKER -->|Yes| CROSS["cross build\nDocker-based, zero setup"]
|
||||
DOCKER -->|No| MANUAL["Manual sysroot\napt install gcc-aarch64-linux-gnu"]
|
||||
DOCKER -->|Yes| CROSS["cross build<br/>Docker-based, zero setup"]
|
||||
DOCKER -->|No| MANUAL["Manual sysroot<br/>apt install gcc-aarch64-linux-gnu"]
|
||||
|
||||
style MUSL fill:#91e5a3,color:#000
|
||||
style ZIG fill:#91e5a3,color:#000
|
||||
|
||||
@@ -440,13 +440,13 @@ criterion_main!(benches);
|
||||
flowchart TD
|
||||
START["Want to measure performance?"] --> WHAT{"What level?"}
|
||||
|
||||
WHAT -->|"Single function"| CRITERION["Criterion.rs\nStatistical, regression detection"]
|
||||
WHAT -->|"Quick function check"| DIVAN["Divan\nLighter, attribute macros"]
|
||||
WHAT -->|"Whole binary"| HYPERFINE["hyperfine\nEnd-to-end, wall-clock"]
|
||||
WHAT -->|"Find hot spots"| PERF["perf + flamegraph\nCPU sampling profiler"]
|
||||
WHAT -->|"Single function"| CRITERION["Criterion.rs<br/>Statistical, regression detection"]
|
||||
WHAT -->|"Quick function check"| DIVAN["Divan<br/>Lighter, attribute macros"]
|
||||
WHAT -->|"Whole binary"| HYPERFINE["hyperfine<br/>End-to-end, wall-clock"]
|
||||
WHAT -->|"Find hot spots"| PERF["perf + flamegraph<br/>CPU sampling profiler"]
|
||||
|
||||
CRITERION --> CI_BENCH["Continuous benchmarking\nin GitHub Actions"]
|
||||
PERF --> OPTIMIZE["Profile-Guided\nOptimization (PGO)"]
|
||||
CRITERION --> CI_BENCH["Continuous benchmarking<br/>in GitHub Actions"]
|
||||
PERF --> OPTIMIZE["Profile-Guided<br/>Optimization (PGO)"]
|
||||
|
||||
style CRITERION fill:#91e5a3,color:#000
|
||||
style DIVAN fill:#91e5a3,color:#000
|
||||
|
||||
@@ -381,11 +381,11 @@ done
|
||||
flowchart TD
|
||||
START["Need code coverage?"] --> ACCURACY{"Priority?"}
|
||||
|
||||
ACCURACY -->|"Most accurate"| LLVM["cargo-llvm-cov\nSource-based, compiler-native"]
|
||||
ACCURACY -->|"Quick check"| TARP["cargo-tarpaulin\nLinux only, fast"]
|
||||
ACCURACY -->|"Multi-run aggregate"| GRCOV["grcov\nMozilla, combines profiles"]
|
||||
ACCURACY -->|"Most accurate"| LLVM["cargo-llvm-cov<br/>Source-based, compiler-native"]
|
||||
ACCURACY -->|"Quick check"| TARP["cargo-tarpaulin<br/>Linux only, fast"]
|
||||
ACCURACY -->|"Multi-run aggregate"| GRCOV["grcov<br/>Mozilla, combines profiles"]
|
||||
|
||||
LLVM --> CI_GATE["CI coverage gate\n--fail-under-lines 80"]
|
||||
LLVM --> CI_GATE["CI coverage gate<br/>--fail-under-lines 80"]
|
||||
TARP --> CI_GATE
|
||||
|
||||
CI_GATE --> UPLOAD{"Upload to?"}
|
||||
|
||||
@@ -575,15 +575,15 @@ Least overhead Most thorough
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
START["Have unsafe code?"] -->|No| SAFE["Safe Rust — no\nverification needed"]
|
||||
START["Have unsafe code?"] -->|No| SAFE["Safe Rust — no<br/>verification needed"]
|
||||
START -->|Yes| KIND{"What kind?"}
|
||||
|
||||
KIND -->|"Pure Rust unsafe"| MIRI["Miri\nMIR interpreter\ncatches aliasing, UB, leaks"]
|
||||
KIND -->|"FFI / C interop"| VALGRIND["Valgrind memcheck\nor ASan"]
|
||||
KIND -->|"Pure Rust unsafe"| MIRI["Miri<br/>MIR interpreter<br/>catches aliasing, UB, leaks"]
|
||||
KIND -->|"FFI / C interop"| VALGRIND["Valgrind memcheck<br/>or ASan"]
|
||||
KIND -->|"Concurrent unsafe"| CONC{"Lock-free?"}
|
||||
|
||||
CONC -->|"Atomics/lock-free"| LOOM["loom\nModel checker for atomics"]
|
||||
CONC -->|"Mutex/shared state"| TSAN["TSan or\nMiri -Zmiri-check-number-validity"]
|
||||
CONC -->|"Atomics/lock-free"| LOOM["loom<br/>Model checker for atomics"]
|
||||
CONC -->|"Mutex/shared state"| TSAN["TSan or<br/>Miri -Zmiri-check-number-validity"]
|
||||
|
||||
MIRI --> CI_MIRI["CI: cargo +nightly miri test"]
|
||||
VALGRIND --> CI_VALGRIND["CI: valgrind --leak-check=full"]
|
||||
|
||||
@@ -317,10 +317,10 @@ unknown-git = "deny"
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
PR["Pull Request"] --> AUDIT["cargo audit\nKnown CVEs"]
|
||||
AUDIT --> DENY["cargo deny check\nLicenses + Bans + Sources"]
|
||||
DENY --> OUTDATED["cargo outdated\nWeekly schedule"]
|
||||
OUTDATED --> SEMVER["cargo semver-checks\nLibrary crates only"]
|
||||
PR["Pull Request"] --> AUDIT["cargo audit<br/>Known CVEs"]
|
||||
AUDIT --> DENY["cargo deny check<br/>Licenses + Bans + Sources"]
|
||||
DENY --> OUTDATED["cargo outdated<br/>Weekly schedule"]
|
||||
OUTDATED --> SEMVER["cargo semver-checks<br/>Library crates only"]
|
||||
|
||||
AUDIT -->|"Fail"| BLOCK["❌ Block merge"]
|
||||
DENY -->|"Fail"| BLOCK
|
||||
|
||||
@@ -252,13 +252,13 @@ cargo shear --fix
|
||||
```mermaid
|
||||
flowchart TD
|
||||
START["Binary too large?"] --> STRIP{"strip = true?"}
|
||||
STRIP -->|"No"| DO_STRIP["Add strip = true\n-50 to -70% size"]
|
||||
STRIP -->|"No"| DO_STRIP["Add strip = true<br/>-50 to -70% size"]
|
||||
STRIP -->|"Yes"| LTO{"LTO enabled?"}
|
||||
LTO -->|"No"| DO_LTO["Add lto = true\ncodegen-units = 1"]
|
||||
LTO -->|"Yes"| BLOAT["Run cargo-bloat\n--crates"]
|
||||
LTO -->|"No"| DO_LTO["Add lto = true<br/>codegen-units = 1"]
|
||||
LTO -->|"Yes"| BLOAT["Run cargo-bloat<br/>--crates"]
|
||||
BLOAT --> BIG_DEP{"Large dependency?"}
|
||||
BIG_DEP -->|"Yes"| REPLACE["Replace with lighter\nalternative or disable\ndefault features"]
|
||||
BIG_DEP -->|"No"| UDEPS["cargo-udeps\nRemove unused deps"]
|
||||
BIG_DEP -->|"Yes"| REPLACE["Replace with lighter<br/>alternative or disable<br/>default features"]
|
||||
BIG_DEP -->|"No"| UDEPS["cargo-udeps<br/>Remove unused deps"]
|
||||
UDEPS --> OPT_LEVEL{"Need smaller?"}
|
||||
OPT_LEVEL -->|"Yes"| SIZE_OPT["opt-level = 's' or 'z'"]
|
||||
|
||||
|
||||
@@ -418,14 +418,14 @@ pub fn get_battery_status() -> Option<u8> {
|
||||
flowchart TD
|
||||
START["Compile too slow?"] --> WHERE{"Where's the time?"}
|
||||
|
||||
WHERE -->|"Recompiling\nunchanged crates"| SCCACHE["sccache\nShared compilation cache"]
|
||||
WHERE -->|"Linking phase"| MOLD["mold linker\n3-10× faster linking"]
|
||||
WHERE -->|"Running tests"| NEXTEST["cargo-nextest\nParallel test runner"]
|
||||
WHERE -->|"Everything"| COMBO["All of the above +\ncargo-udeps to trim deps"]
|
||||
WHERE -->|"Recompiling<br/>unchanged crates"| SCCACHE["sccache<br/>Shared compilation cache"]
|
||||
WHERE -->|"Linking phase"| MOLD["mold linker<br/>3-10× faster linking"]
|
||||
WHERE -->|"Running tests"| NEXTEST["cargo-nextest<br/>Parallel test runner"]
|
||||
WHERE -->|"Everything"| COMBO["All of the above +<br/>cargo-udeps to trim deps"]
|
||||
|
||||
SCCACHE --> CI_CACHE{"CI or local?"}
|
||||
CI_CACHE -->|"CI"| S3["S3/GCS shared cache"]
|
||||
CI_CACHE -->|"Local"| LOCAL["Local disk cache\nauto-configured"]
|
||||
CI_CACHE -->|"Local"| LOCAL["Local disk cache<br/>auto-configured"]
|
||||
|
||||
style SCCACHE fill:#91e5a3,color:#000
|
||||
style MOLD fill:#e3f2fd,color:#000
|
||||
|
||||
@@ -352,18 +352,18 @@ cargo check --target riscv32imac-unknown-none-elf # RISC-V
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
START["Does your code need\nthe standard library?"] --> NEED_FS{"File system,\nnetwork, threads?"}
|
||||
NEED_FS -->|"Yes"| USE_STD["Use std\nNormal application"]
|
||||
NEED_FS -->|"No"| NEED_HEAP{"Need heap allocation?\nVec, String, Box"}
|
||||
NEED_HEAP -->|"Yes"| USE_ALLOC["#![no_std]\nextern crate alloc"]
|
||||
NEED_HEAP -->|"No"| USE_CORE["#![no_std]\ncore only"]
|
||||
START["Does your code need<br/>the standard library?"] --> NEED_FS{"File system,<br/>network, threads?"}
|
||||
NEED_FS -->|"Yes"| USE_STD["Use std<br/>Normal application"]
|
||||
NEED_FS -->|"No"| NEED_HEAP{"Need heap allocation?<br/>Vec, String, Box"}
|
||||
NEED_HEAP -->|"Yes"| USE_ALLOC["#![no_std]<br/>extern crate alloc"]
|
||||
NEED_HEAP -->|"No"| USE_CORE["#![no_std]<br/>core only"]
|
||||
|
||||
USE_ALLOC --> VERIFY["cargo-hack\n--each-feature"]
|
||||
USE_ALLOC --> VERIFY["cargo-hack<br/>--each-feature"]
|
||||
USE_CORE --> VERIFY
|
||||
USE_STD --> VERIFY
|
||||
VERIFY --> TARGET{"Target has OS?"}
|
||||
TARGET -->|"Yes"| HOST_TEST["cargo test --lib\nStandard testing"]
|
||||
TARGET -->|"No"| CROSS_TEST["QEMU / defmt-test\nOn-device testing"]
|
||||
TARGET -->|"Yes"| HOST_TEST["cargo test --lib<br/>Standard testing"]
|
||||
TARGET -->|"No"| CROSS_TEST["QEMU / defmt-test<br/>On-device testing"]
|
||||
|
||||
style USE_STD fill:#91e5a3,color:#000
|
||||
style USE_ALLOC fill:#ffd43b,color:#000
|
||||
|
||||
@@ -374,17 +374,17 @@ implementation is complete — catching `cfg` mistakes early.
|
||||
flowchart TD
|
||||
START["Platform-specific code?"] --> HOW_MANY{"How many platforms?"}
|
||||
|
||||
HOW_MANY -->|"2 (Linux + Windows)"| CFG_BLOCKS["#[cfg] blocks\nin leaf functions"]
|
||||
HOW_MANY -->|"3+"| TRAIT_APPROACH["Platform trait\n+ per-platform impl"]
|
||||
HOW_MANY -->|"2 (Linux + Windows)"| CFG_BLOCKS["#[cfg] blocks<br/>in leaf functions"]
|
||||
HOW_MANY -->|"3+"| TRAIT_APPROACH["Platform trait<br/>+ per-platform impl"]
|
||||
|
||||
CFG_BLOCKS --> WINAPI{"Need Windows APIs?"}
|
||||
WINAPI -->|"Minimal"| WIN_SYS["windows-sys\nRaw FFI bindings"]
|
||||
WINAPI -->|"Rich (COM, etc)"| WIN_RS["windows crate\nSafe idiomatic wrappers"]
|
||||
WINAPI -->|"None\n(just #[cfg])"| NATIVE["cfg(windows)\ncfg(unix)"]
|
||||
WINAPI -->|"Minimal"| WIN_SYS["windows-sys<br/>Raw FFI bindings"]
|
||||
WINAPI -->|"Rich (COM, etc)"| WIN_RS["windows crate<br/>Safe idiomatic wrappers"]
|
||||
WINAPI -->|"None<br/>(just #[cfg])"| NATIVE["cfg(windows)<br/>cfg(unix)"]
|
||||
|
||||
TRAIT_APPROACH --> CI_CHECK["cargo-hack\n--each-feature"]
|
||||
TRAIT_APPROACH --> CI_CHECK["cargo-hack<br/>--each-feature"]
|
||||
CFG_BLOCKS --> CI_CHECK
|
||||
CI_CHECK --> XCOMPILE["Cross-compile in CI\ncargo-xwin or\nnative runners"]
|
||||
CI_CHECK --> XCOMPILE["Cross-compile in CI<br/>cargo-xwin or<br/>native runners"]
|
||||
|
||||
style CFG_BLOCKS fill:#91e5a3,color:#000
|
||||
style TRAIT_APPROACH fill:#ffd43b,color:#000
|
||||
|
||||
@@ -545,27 +545,27 @@ shows your release targets. You now have a production-grade Rust pipeline.
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph "Stage 1 — Fast Feedback < 2 min"
|
||||
CHECK["cargo check\ncargo clippy\ncargo fmt"]
|
||||
CHECK["cargo check<br/>cargo clippy<br/>cargo fmt"]
|
||||
end
|
||||
|
||||
subgraph "Stage 2 — Tests < 5 min"
|
||||
TEST["cargo nextest\ncargo test --doc"]
|
||||
TEST["cargo nextest<br/>cargo test --doc"]
|
||||
end
|
||||
|
||||
subgraph "Stage 3 — Coverage"
|
||||
COV["cargo llvm-cov\nfail-under 80%"]
|
||||
COV["cargo llvm-cov<br/>fail-under 80%"]
|
||||
end
|
||||
|
||||
subgraph "Stage 4 — Security"
|
||||
SEC["cargo audit\ncargo deny check"]
|
||||
SEC["cargo audit<br/>cargo deny check"]
|
||||
end
|
||||
|
||||
subgraph "Stage 5 — Cross-Build"
|
||||
CROSS["musl static\naarch64 + x86_64"]
|
||||
CROSS["musl static<br/>aarch64 + x86_64"]
|
||||
end
|
||||
|
||||
subgraph "Stage 6 — Release (tag only)"
|
||||
REL["cargo dist\nGitHub Release"]
|
||||
REL["cargo dist<br/>GitHub Release"]
|
||||
end
|
||||
|
||||
CHECK --> TEST --> COV --> SEC --> CROSS --> REL
|
||||
|
||||
@@ -102,13 +102,13 @@ fn main() {
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph Python ["Python Types"]
|
||||
PI["int\n(arbitrary precision)"]
|
||||
PF["float\n(64-bit only)"]
|
||||
PI["int<br/>(arbitrary precision)"]
|
||||
PF["float<br/>(64-bit only)"]
|
||||
PB["bool"]
|
||||
PS["str\n(Unicode)"]
|
||||
PS["str<br/>(Unicode)"]
|
||||
end
|
||||
subgraph Rust ["Rust Types"]
|
||||
RI["i8 / i16 / i32 / i64 / i128\nu8 / u16 / u32 / u64 / u128"]
|
||||
RI["i8 / i16 / i32 / i64 / i128<br/>u8 / u16 / u32 / u64 / u128"]
|
||||
RF["f32 / f64"]
|
||||
RB["bool"]
|
||||
RS["String / &str"]
|
||||
|
||||
@@ -191,12 +191,12 @@ fn main() {
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph Python ["Python Object (Heap)"]
|
||||
PH["PyObject Header\n(refcount + type ptr)"] --> PW["width: float obj"]
|
||||
PH["PyObject Header<br/>(refcount + type ptr)"] --> PW["width: float obj"]
|
||||
PH --> PHT["height: float obj"]
|
||||
PH --> PD["__dict__"]
|
||||
end
|
||||
subgraph Rust ["Rust Struct (Stack)"]
|
||||
RW["width: f64\n(8 bytes)"] --- RH["height: f64\n(8 bytes)"]
|
||||
RW["width: f64<br/>(8 bytes)"] --- RH["height: f64<br/>(8 bytes)"]
|
||||
end
|
||||
style Python fill:#ffeeba
|
||||
style Rust fill:#d4edda
|
||||
|
||||
@@ -113,10 +113,10 @@ enum Message {
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
E["enum Message"] --> T["Text(String)\n🏷️ tag=0 + String data"]
|
||||
E --> I["Image { url, width, height }\n🏷️ tag=1 + 3 fields"]
|
||||
E --> Q["Quit\n🏷️ tag=2 + no data"]
|
||||
E --> M["Move { x, y }\n🏷️ tag=3 + 2 fields"]
|
||||
E["enum Message"] --> T["Text(String)<br/>🏷️ tag=0 + String data"]
|
||||
E --> I["Image { url, width, height }<br/>🏷️ tag=1 + 3 fields"]
|
||||
E --> Q["Quit<br/>🏷️ tag=2 + no data"]
|
||||
E --> M["Move { x, y }<br/>🏷️ tag=3 + 2 fields"]
|
||||
style E fill:#d4edda,stroke:#28a745
|
||||
style T fill:#fff3cd
|
||||
style I fill:#fff3cd
|
||||
|
||||
@@ -99,13 +99,13 @@ stateDiagram-v2
|
||||
a_owns --> shared: b = a
|
||||
shared --> b_only: del a (refcount 2→1)
|
||||
b_only --> freed: del b (refcount 1→0)
|
||||
note right of shared: Both a and b point\nto the SAME object
|
||||
note right of shared: Both a and b point<br/>to the SAME object
|
||||
}
|
||||
state "Rust (Ownership Move)" as RS {
|
||||
[*] --> a_owns2: let a = vec![1,2,3]
|
||||
a_owns2 --> b_owns: let b = a (MOVE)
|
||||
b_owns --> freed2: b goes out of scope
|
||||
note right of b_owns: a is INVALID after move\nCompile error if used
|
||||
note right of b_owns: a is INVALID after move<br/>Compile error if used
|
||||
}
|
||||
```
|
||||
|
||||
@@ -203,9 +203,9 @@ Rust: One person owns the book. Others can:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
R["Borrowing Rules"] --> IMM["✅ Many &T\n(shared/immutable)"]
|
||||
R --> MUT["✅ One &mut T\n(exclusive/mutable)"]
|
||||
R --> CONFLICT["❌ &T + &mut T\n(NEVER at same time)"]
|
||||
R["Borrowing Rules"] --> IMM["✅ Many &T<br/>(shared/immutable)"]
|
||||
R --> MUT["✅ One &mut T<br/>(exclusive/mutable)"]
|
||||
R --> CONFLICT["❌ &T + &mut T<br/>(NEVER at same time)"]
|
||||
IMM --> SAFE["Multiple readers, safe"]
|
||||
MUT --> SAFE2["Single writer, safe"]
|
||||
CONFLICT --> ERR["Compile error!"]
|
||||
|
||||
@@ -194,10 +194,10 @@ flowchart TD
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
AE["AppError (enum)"] --> NF["NotFound\n{ entity, id }"]
|
||||
AE --> VE["Validation\n{ field, message }"]
|
||||
AE --> IO["Io(std::io::Error)\n#[from]"]
|
||||
AE --> JSON["Json(serde_json::Error)\n#[from]"]
|
||||
AE["AppError (enum)"] --> NF["NotFound<br/>{ entity, id }"]
|
||||
AE --> VE["Validation<br/>{ field, message }"]
|
||||
AE --> IO["Io(std::io::Error)<br/>#[from]"]
|
||||
AE --> JSON["Json(serde_json::Error)<br/>#[from]"]
|
||||
IO2["std::io::Error"] -->|"auto-convert via From"| IO
|
||||
JSON2["serde_json::Error"] -->|"auto-convert via From"| JSON
|
||||
style AE fill:#d4edda,stroke:#28a745
|
||||
|
||||
@@ -173,10 +173,10 @@ flat = [item for sublist in nested for item in sublist]
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["Source\n[1,2,3,4,5]"] -->|.iter\(\)| B["Iterator"]
|
||||
A["Source<br/>[1,2,3,4,5]"] -->|.iter\(\)| B["Iterator"]
|
||||
B -->|.filter\(\|x\| x%2==0\)| C["[2, 4]"]
|
||||
C -->|.map\(\|x\| x*x\)| D["[4, 16]"]
|
||||
D -->|.collect\(\)| E["Vec<i32>\n[4, 16]"]
|
||||
D -->|.collect\(\)| E["Vec<i32><br/>[4, 16]"]
|
||||
style A fill:#ffeeba
|
||||
style E fill:#d4edda
|
||||
```
|
||||
|
||||
@@ -252,10 +252,10 @@ let db_host = get_config()["database"]["host"].as_str().unwrap();
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["1️⃣ Profile Python\n(find hotspots)"] --> B["2️⃣ Write Rust Extension\n(PyO3 + maturin)"]
|
||||
B --> C["3️⃣ Replace Python Call\n(same API)"]
|
||||
C --> D["4️⃣ Expand Gradually\n(more functions)"]
|
||||
D --> E{"Full rewrite\nworth it?"}
|
||||
A["1️⃣ Profile Python<br/>(find hotspots)"] --> B["2️⃣ Write Rust Extension<br/>(PyO3 + maturin)"]
|
||||
B --> C["3️⃣ Replace Python Call<br/>(same API)"]
|
||||
C --> D["4️⃣ Expand Gradually<br/>(more functions)"]
|
||||
D --> E{"Full rewrite<br/>worth it?"}
|
||||
E -->|Yes| F["Pure Rust🦀"]
|
||||
E -->|No| G["Hybrid🐍+🦀"]
|
||||
style A fill:#ffeeba
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["🟢 Week 1-2\nFoundations\n'Why won't this compile?'"] --> B["🟡 Week 3-4\nCore Concepts\n'Oh, it's protecting me'"]
|
||||
B --> C["🟡 Month 2\nIntermediate\n'I see why this matters'"]
|
||||
C --> D["🔴 Month 3+\nAdvanced\n'Caught a bug at compile time!'"]
|
||||
D --> E["🏆 Month 6\nFluent\n'Better programmer everywhere'"]
|
||||
A["🟢 Week 1-2<br/>Foundations<br/>'Why won't this compile?'"] --> B["🟡 Week 3-4<br/>Core Concepts<br/>'Oh, it's protecting me'"]
|
||||
B --> C["🟡 Month 2<br/>Intermediate<br/>'I see why this matters'"]
|
||||
C --> D["🔴 Month 3+<br/>Advanced<br/>'Caught a bug at compile time!'"]
|
||||
D --> E["🏆 Month 6<br/>Fluent<br/>'Better programmer everywhere'"]
|
||||
style A fill:#d4edda
|
||||
style B fill:#fff3cd
|
||||
style C fill:#fff3cd
|
||||
|
||||
@@ -793,8 +793,8 @@ combination — is two-dimensional:
|
||||
block-beta
|
||||
columns 4
|
||||
space header1["Locked"] header2["Unlocked"] header3["ExtendedUnlocked"]
|
||||
basic["Basic Vendor"]:1 b1["unlock()"] b2["read_reg()\nwrite_reg()"] b3["— unreachable —"]
|
||||
memory["Memory Vendor"]:1 m1["unlock()"] m2["read_reg()\nwrite_reg()\nextended_unlock()"] m3["read_reg()\nwrite_reg()\nread_memory()\nwrite_memory()"]
|
||||
basic["Basic Vendor"]:1 b1["unlock()"] b2["read_reg()<br/>write_reg()"] b3["— unreachable —"]
|
||||
memory["Memory Vendor"]:1 m1["unlock()"] m2["read_reg()<br/>write_reg()<br/>extended_unlock()"] m3["read_reg()<br/>write_reg()<br/>read_memory()<br/>write_memory()"]
|
||||
|
||||
style b1 fill:#ffd,stroke:#aa0
|
||||
style b2 fill:#efe,stroke:#3a3
|
||||
|
||||
@@ -300,14 +300,14 @@ No functional equivalent is cleaner. The loop with `match state` is the natural
|
||||
flowchart TB
|
||||
START{What are you doing?}
|
||||
|
||||
START -->|"Transforming a collection\ninto another collection"| PIPE[Use iterator chain]
|
||||
START -->|"Computing a single value\nfrom a collection"| AGG{How complex?}
|
||||
START -->|"Multiple outputs from\none pass"| LOOP[Use a for loop]
|
||||
START -->|"State machine with\nI/O or side effects"| LOOP
|
||||
START -->|"One Option/Result\ntransform + default"| COMB[Use combinators]
|
||||
START -->|"Transforming a collection<br/>into another collection"| PIPE[Use iterator chain]
|
||||
START -->|"Computing a single value<br/>from a collection"| AGG{How complex?}
|
||||
START -->|"Multiple outputs from<br/>one pass"| LOOP[Use a for loop]
|
||||
START -->|"State machine with<br/>I/O or side effects"| LOOP
|
||||
START -->|"One Option/Result<br/>transform + default"| COMB[Use combinators]
|
||||
|
||||
AGG -->|"Sum, count, min, max"| BUILTIN["Use .sum(), .count(),\n.min(), .max()"]
|
||||
AGG -->|"Custom accumulation"| FOLD{Accumulator has mutation\nor side effects?}
|
||||
AGG -->|"Sum, count, min, max"| BUILTIN["Use .sum(), .count(),<br/>.min(), .max()"]
|
||||
AGG -->|"Custom accumulation"| FOLD{Accumulator has mutation<br/>or side effects?}
|
||||
FOLD -->|"No"| FOLDF["Use .fold()"]
|
||||
FOLD -->|"Yes"| LOOP
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@ fn sensor_workflow() -> io::Result<()> {
|
||||
flowchart LR
|
||||
N["Nonce::new()"] -->|move| E["encrypt(nonce, msg)"]
|
||||
E -->|consumed| X["❌ nonce gone"]
|
||||
N -.->|"reuse attempt"| ERR["COMPILE ERROR:\nuse of moved value"]
|
||||
N -.->|"reuse attempt"| ERR["COMPILE ERROR:<br/>use of moved value"]
|
||||
style N fill:#e1f5fe,color:#000
|
||||
style E fill:#c8e6c9,color:#000
|
||||
style X fill:#ffcdd2,color:#000
|
||||
|
||||
@@ -1266,12 +1266,12 @@ bytes to Redfish-ready health values:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
RAW["Raw [u8; 16]\nSEL entries"]
|
||||
PARSE["TryFrom:\nValidSelRecord\n(enum tree)"]
|
||||
CLASSIFY["classify_event_health\n(exhaustive match)"]
|
||||
LINEARIZE["SDR linearize\nraw → Celsius/Rpm/Watts"]
|
||||
SUMMARY["TypedSelSummary\n(per-subsystem health\n+ dimensional readings)"]
|
||||
REDFISH["ch18: health rollup\n→ Status.Health JSON"]
|
||||
RAW["Raw [u8; 16]<br/>SEL entries"]
|
||||
PARSE["TryFrom:<br/>ValidSelRecord<br/>(enum tree)"]
|
||||
CLASSIFY["classify_event_health<br/>(exhaustive match)"]
|
||||
LINEARIZE["SDR linearize<br/>raw → Celsius/Rpm/Watts"]
|
||||
SUMMARY["TypedSelSummary<br/>(per-subsystem health<br/>+ dimensional readings)"]
|
||||
REDFISH["ch18: health rollup<br/>→ Status.Health JSON"]
|
||||
|
||||
RAW -->|"ch07 §Parse"| PARSE
|
||||
PARSE -->|"typed events"| CLASSIFY
|
||||
|
||||
@@ -18,17 +18,17 @@ A single `GET /redfish/v1/Systems/1` response must fuse data from many sources:
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph Sources
|
||||
SMBIOS["SMBIOS\nType 1, Type 17"]
|
||||
SDR["IPMI Sensors\n(SDR + readings)"]
|
||||
SEL["IPMI SEL\n(critical events)"]
|
||||
PCIe["PCIe Config\nSpace"]
|
||||
FW["Firmware\nVersion Table"]
|
||||
PWR["Power State\nRegister"]
|
||||
SMBIOS["SMBIOS<br/>Type 1, Type 17"]
|
||||
SDR["IPMI Sensors<br/>(SDR + readings)"]
|
||||
SEL["IPMI SEL<br/>(critical events)"]
|
||||
PCIe["PCIe Config<br/>Space"]
|
||||
FW["Firmware<br/>Version Table"]
|
||||
PWR["Power State<br/>Register"]
|
||||
end
|
||||
|
||||
subgraph Server["Redfish Server"]
|
||||
Handler["GET handler"]
|
||||
Builder["ComputerSystem\nBuilder"]
|
||||
Builder["ComputerSystem<br/>Builder"]
|
||||
end
|
||||
|
||||
SMBIOS -->|"Name, UUID, Serial"| Handler
|
||||
@@ -38,7 +38,7 @@ flowchart LR
|
||||
FW -->|"BIOS version"| Handler
|
||||
PWR -->|"PowerState"| Handler
|
||||
Handler --> Builder
|
||||
Builder -->|".build()"| JSON["Schema-compliant\nJSON response"]
|
||||
Builder -->|".build()"| JSON["Schema-compliant<br/>JSON response"]
|
||||
|
||||
style JSON fill:#c8e6c9,color:#000
|
||||
style Builder fill:#e1f5fe,color:#000
|
||||
|
||||
Reference in New Issue
Block a user