Putting It All Together β A Complete Diagnostic Platform π‘
What you'll learn: How all seven core patterns (ch02βch09) compose into a single diagnostic workflow β authentication, sessions, typed commands, audit tokens, dimensional results, validated data, and phantom-typed registers β with zero total runtime overhead.
Cross-references: Every core pattern chapter (ch02βch09), ch14 (testing these guarantees)
Goal
This chapter combines seven patterns from chapters 2β9 into a single, realistic diagnostic workflow. We'll build a server health check that:
- Authenticates (capability token β ch04)
- Opens an IPMI session (type-state β ch05)
- Sends typed commands (typed commands β ch02)
- Uses single-use tokens for audit logging (single-use types β ch03)
- Returns dimensional results (dimensional analysis β ch06)
- Validates FRU data (validated boundaries β ch07)
- Reads typed registers (phantom types β ch09)
use std::marker::PhantomData;
use std::io;
// ββββ Pattern 1: Dimensional Types (ch06) ββββ
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Celsius(pub f64);
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Rpm(pub f64);
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Volts(pub f64);
// ββββ Pattern 2: Typed Commands (ch02) ββββ
/// Same trait shape as ch02, using methods (not associated constants)
/// for consistency. Associated constants (`const NETFN: u8`) are an
/// equally valid alternative when the value is truly fixed per type.
pub trait IpmiCmd {
type Response;
fn net_fn(&self) -> u8;
fn cmd_byte(&self) -> u8;
fn payload(&self) -> Vec<u8>;
fn parse_response(&self, raw: &[u8]) -> io::Result<Self::Response>;
}
pub struct ReadTemp { pub sensor_id: u8 }
impl IpmiCmd for ReadTemp {
type Response = Celsius; // β dimensional type!
fn net_fn(&self) -> u8 { 0x04 }
fn cmd_byte(&self) -> u8 { 0x2D }
fn payload(&self) -> Vec<u8> { vec![self.sensor_id] }
fn parse_response(&self, raw: &[u8]) -> io::Result<Celsius> {
if raw.is_empty() {
return Err(io::Error::new(io::ErrorKind::InvalidData, "empty"));
}
Ok(Celsius(raw[0] as f64))
}
}
pub struct ReadFanSpeed { pub fan_id: u8 }
impl IpmiCmd for ReadFanSpeed {
type Response = Rpm;
fn net_fn(&self) -> u8 { 0x04 }
fn cmd_byte(&self) -> u8 { 0x2D }
fn payload(&self) -> Vec<u8> { vec![self.fan_id] }
fn parse_response(&self, raw: &[u8]) -> io::Result<Rpm> {
if raw.len() < 2 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "need 2 bytes"));
}
Ok(Rpm(u16::from_le_bytes([raw[0], raw[1]]) as f64))
}
}
// ββββ Pattern 3: Capability Token (ch04) ββββ
pub struct AdminToken { _private: () }
pub fn authenticate(user: &str, pass: &str) -> Result<AdminToken, &'static str> {
if user == "admin" && pass == "secret" {
Ok(AdminToken { _private: () })
} else {
Err("authentication failed")
}
}
// ββββ Pattern 4: Type-State Session (ch05) ββββ
pub struct Idle;
pub struct Active;
pub struct Session<State> {
host: String,
_state: PhantomData<State>,
}
impl Session<Idle> {
pub fn connect(host: &str) -> Self {
Session { host: host.to_string(), _state: PhantomData }
}
pub fn activate(
self,
_admin: &AdminToken, // β requires capability token
) -> Result<Session<Active>, String> {
println!("Session activated on {}", self.host);
Ok(Session { host: self.host, _state: PhantomData })
}
}
impl Session<Active> {
/// Execute a typed command β only available on Active sessions.
/// Returns io::Result to propagate transport errors (consistent with ch02).
pub fn execute<C: IpmiCmd>(&mut self, cmd: &C) -> io::Result<C::Response> {
let raw_response = self.raw_send(cmd.net_fn(), cmd.cmd_byte(), &cmd.payload())?;
cmd.parse_response(&raw_response)
}
fn raw_send(&self, _nf: u8, _cmd: u8, _data: &[u8]) -> io::Result<Vec<u8>> {
Ok(vec![42, 0x1E]) // stub: raw IPMI response
}
pub fn close(self) { println!("Session closed"); }
}
// ββββ Pattern 5: Single-Use Audit Token (ch03) ββββ
/// Each diagnostic run gets a unique audit token.
/// Not Clone, not Copy β ensures each audit entry is unique.
pub struct AuditToken {
run_id: u64,
}
impl AuditToken {
pub fn issue(run_id: u64) -> Self {
AuditToken { run_id }
}
/// Consume the token to write an audit log entry.
pub fn log(self, message: &str) {
println!("[AUDIT run_id={}] {}", self.run_id, message);
// token is consumed β can't log the same run_id twice
}
}
// ββββ Pattern 6: Validated Boundary (ch07) ββββ
// Simplified from ch07's full ValidFru β only the fields needed for this
// composite example. See ch07 for the complete TryFrom<RawFruData> version.
pub struct ValidFru {
pub board_serial: String,
pub product_name: String,
}
impl ValidFru {
pub fn parse(raw: &[u8]) -> Result<Self, &'static str> {
if raw.len() < 8 { return Err("FRU too short"); }
if raw[0] != 0x01 { return Err("bad FRU version"); }
Ok(ValidFru {
board_serial: "SN12345".to_string(), // stub
product_name: "ServerX".to_string(),
})
}
}
// ββββ Pattern 7: Phantom-Typed Registers (ch09) ββββ
pub struct Width16;
pub struct Reg<W> { offset: u16, _w: PhantomData<W> }
impl Reg<Width16> {
pub fn read(&self) -> u16 { 0x8086 } // stub
}
pub struct PcieDev {
pub vendor_id: Reg<Width16>,
pub device_id: Reg<Width16>,
}
impl PcieDev {
pub fn new() -> Self {
PcieDev {
vendor_id: Reg { offset: 0x00, _w: PhantomData },
device_id: Reg { offset: 0x02, _w: PhantomData },
}
}
}
// ββββ Composite Workflow ββββ
fn full_diagnostic() -> Result<(), String> {
// 1. Authenticate β get capability token
let admin = authenticate("admin", "secret")
.map_err(|e| e.to_string())?;
// 2. Connect and activate session (type-state: Idle β Active)
let session = Session::connect("192.168.1.100");
let mut session = session.activate(&admin)?; // requires AdminToken
// 3. Send typed commands (response type matches command)
let temp: Celsius = session.execute(&ReadTemp { sensor_id: 0 })
.map_err(|e| e.to_string())?;
let fan: Rpm = session.execute(&ReadFanSpeed { fan_id: 1 })
.map_err(|e| e.to_string())?;
// Type mismatch would be caught:
// let wrong: Volts = session.execute(&ReadTemp { sensor_id: 0 })?;
// β ERROR: expected Celsius, found Volts
// 4. Read phantom-typed PCIe registers
let pcie = PcieDev::new();
let vid: u16 = pcie.vendor_id.read(); // guaranteed u16
// 5. Validate FRU data at the boundary
let raw_fru = vec![0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xFD];
let fru = ValidFru::parse(&raw_fru)
.map_err(|e| e.to_string())?;
// 6. Issue single-use audit token
let audit = AuditToken::issue(1001);
// 7. Generate report (all data is typed and validated)
let report = format!(
"Server: {} (SN: {}), VID: 0x{:04X}, CPU: {:?}, Fan: {:?}",
fru.product_name, fru.board_serial, vid, temp, fan,
);
// 8. Consume audit token β can't log twice
audit.log(&report);
// audit.log("oops"); // β use of moved value
// 9. Close session (type-state: Active β dropped)
session.close();
Ok(())
}
What the Compiler Proves
| Bug class | How it's prevented | Pattern |
|---|---|---|
| Unauthenticated access | activate() requires &AdminToken | Capability token |
| Command in wrong session state | execute() only exists on Session<Active> | Type-state |
| Wrong response type | ReadTemp::Response = Celsius, fixed by trait | Typed commands |
| Unit confusion (Β°C vs RPM) | Celsius β Rpm β Volts | Dimensional types |
| Register width mismatch | Reg<Width16> returns u16 | Phantom types |
| Processing unvalidated data | Must call ValidFru::parse() first | Validated boundary |
| Duplicate audit entries | AuditToken is consumed on log | Single-use type |
| Out-of-order power sequencing | Each step requires previous token | Capability tokens (ch04) |
Total runtime overhead of ALL these guarantees: zero.
Every check happens at compile time. The generated assembly is identical to hand-written C code with no checks at all β but C can have bugs, this can't.
Key Takeaways
- Seven patterns compose seamlessly β capability tokens, type-state, typed commands, single-use types, dimensional types, validated boundaries, and phantom types all work together.
- The compiler proves eight bug classes impossible β see the "What the Compiler Proves" table above.
- Zero total runtime overhead β the generated assembly is identical to unchecked C code.
- Each pattern is independently useful β you don't need all seven; adopt them incrementally.
- The integration chapter is a design template β use it as a starting point for your own typed diagnostic workflows.
- From IPMI to Redfish at scale β ch17 and ch18 apply these same seven patterns (plus capability mixins from ch08) to a full Redfish client and server. The IPMI workflow here is the foundation; the Redfish walkthroughs show how the composition scales to production systems with multiple data sources and schema-version constraints.