use std::sync::Arc;
use std::time::Duration;
use rich_rust::console::Console;
use rich_rust::renderables::pretty::{Inspect, Pretty};
use crate::Config;
use crate::scenes::{Scene, SceneError};
use crate::state::{DemoState, FailureEvent, FailureScenario, ServiceHealth, ServiceInfo};
pub struct DebugToolsScene;
impl DebugToolsScene {
#[must_use]
pub const fn new() -> Self {
Self
}
}
impl Scene for DebugToolsScene {
fn name(&self) -> &'static str {
"debug_tools"
}
fn summary(&self) -> &'static str {
"Pretty/Inspect + Traceback + RichLogger (+ tracing)."
}
fn run(&self, console: &Arc<Console>, _cfg: &Config) -> Result<(), SceneError> {
console.print("[section.title]Debug Tools: Pretty & Inspect[/]");
console.print("");
console.print("[dim]rich_rust provides debugging tools for inspecting Rust values.[/]");
console.print("");
render_pretty_demo(console);
console.print("");
render_inspect_demo(console);
console.print("");
render_failure_demo(console);
Ok(())
}
}
fn render_pretty_demo(console: &Console) {
console.print("[brand.accent]Pretty: Styled Debug Output[/]");
console.print("");
let service = ServiceInfo {
name: "api".to_string(),
health: ServiceHealth::Ok,
latency: Duration::from_millis(12),
version: "1.2.3".to_string(),
};
console.print("[dim]ServiceInfo struct:[/]");
console.print("");
let pretty = Pretty::new(&service);
console.print_renderable(&pretty);
console.print("");
console.print("[hint]Pretty uses the Debug trait to render values with optional wrapping.[/]");
}
fn render_inspect_demo(console: &Console) {
console.print("[brand.accent]Inspect: Value + Type Information[/]");
console.print("");
let state = DemoState::demo_seeded(42, 12345);
let snapshot = crate::state::DemoStateSnapshot::from(&state);
console.print("[dim]DemoStateSnapshot (partial):[/]");
console.print("");
let inspect = Inspect::new(&snapshot);
console.print_renderable(&inspect);
console.print("");
console.print("[hint]Inspect shows the Rust type name and extracts struct fields.[/]");
}
fn render_failure_demo(console: &Console) {
console.print("[brand.accent]Failure Context Inspection[/]");
console.print("");
let failure = FailureEvent::new(FailureScenario::DatabaseTimeout, Duration::from_secs(45));
console.print("[dim]FailureEvent (database timeout):[/]");
console.print("");
let context_pretty = Pretty::new(&failure.context);
console.print_renderable(&context_pretty);
console.print("");
console.print("[dim]Stack trace frames:[/]");
console.print("");
for frame in &failure.stack_frames {
console.print(&format!(
" [brand.accent]{}[/] at [dim]{}:{}[/]",
frame.function, frame.file, frame.line
));
for (var, val) in &frame.locals {
console.print(&format!(" [dim]{var}[/] = [status.info]{val}[/]"));
}
}
console.print("");
console.print("[hint]Failure events capture context for debugging and display.[/]");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn debug_tools_scene_has_correct_name() {
let scene = DebugToolsScene::new();
assert_eq!(scene.name(), "debug_tools");
}
#[test]
fn debug_tools_scene_runs_without_error() {
let scene = DebugToolsScene::new();
let console = Console::builder()
.force_terminal(false)
.markup(true)
.build()
.shared();
let cfg = Config::with_defaults();
let result = scene.run(&console, &cfg);
assert!(result.is_ok());
}
}