From 0e22f529009d3b7bd80695fe4d8cf3e86a3544cd Mon Sep 17 00:00:00 2001 From: cenonym <131857452+cenonym@users.noreply.github.com> Date: Fri, 3 Jul 2026 08:07:03 +0200 Subject: [PATCH 1/7] feat: add stall and cycle detection - Incremental hash of tape and head state updated per step - Brent's algorithm with structural snapshot verification, hash collisions can never fake a cycle - Stall detected immediately when no head has a transition --- src/machine/detection.rs | 255 +++++++++++++++++++++++++++++++++++++++ src/machine/grid.rs | 6 +- src/machine/mod.rs | 143 +++++++++++++++++++--- 3 files changed, 386 insertions(+), 18 deletions(-) create mode 100644 src/machine/detection.rs diff --git a/src/machine/detection.rs b/src/machine/detection.rs new file mode 100644 index 0000000..f3e8ad2 --- /dev/null +++ b/src/machine/detection.rs @@ -0,0 +1,255 @@ +use rustc_hash::FxHashMap; +use super::grid::Grid; +use super::heads::Head; +use super::rules::Direction; + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum DetectionStatus { + Running, + Stalled { at_step: u64 }, + Cycle { at_step: u64, period: u64 }, +} + +// splitmix64 finalizer +#[inline] +fn mix64(mut z: u64) -> u64 { + z = z.wrapping_add(0x9E37_79B9_7F4A_7C15); + z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9); + z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB); + z ^ (z >> 31) +} + +#[inline] +fn dir_code(d: Direction) -> u64 { + match d { + Direction::Up => 0, Direction::Down => 1, + Direction::Left => 2, Direction::Right => 3, + Direction::UpLeft => 4, Direction::UpRight => 5, + Direction::DownLeft => 6, Direction::DownRight => 7, + } +} + +// Empty cells contribute nothing, stored or absent +#[inline] +fn cell_contrib(x: i32, y: i32, c: char) -> u64 { + if c == Grid::EMPTY { + return 0; + } + mix64(((x as u64 & 0xFFFF) << 48) | ((y as u64 & 0xFFFF) << 32) | c as u64) +} + +#[inline] +fn head_contrib(index: usize, x: i32, y: i32, dir: Direction, istate: usize) -> u64 { + let word = ((index as u64) << 56) + | ((x as u64 & 0xFFFF) << 40) + | ((y as u64 & 0xFFFF) << 24) + | (dir_code(dir) << 21) + | (istate as u64 & 0x1F_FFFF); + mix64(word ^ 0xDEAD_BEEF_CAFE_F00D) +} + +#[derive(Debug, Clone, PartialEq)] +struct Snapshot { + tape: FxHashMap<(i32, i32), char>, + heads: Vec<(i32, i32, Direction, usize)>, +} + +impl Snapshot { + fn capture(grid: &Grid, heads: &[Head]) -> Self { + Self { + tape: grid.tape.iter() + .filter(|&(_, &c)| c != Grid::EMPTY) + .map(|(&pos, &c)| (pos, c)) + .collect(), + heads: heads.iter() + .map(|h| (h.x, h.y, h.direction, h.internal_state)) + .collect(), + } + } +} + +fn full_hash(grid: &Grid, heads: &[Head]) -> u64 { + let mut h = 0u64; + for (&(x, y), &c) in &grid.tape { + h ^= cell_contrib(x, y, c); + } + for (i, head) in heads.iter().enumerate() { + h ^= head_contrib(i, head.x, head.y, head.direction, head.internal_state); + } + h +} + +#[derive(Debug)] +pub struct CycleDetector { + hash: u64, + saved_hash: u64, + snapshot: Snapshot, + power: u64, + lam: u64, + status: DetectionStatus, +} + +impl CycleDetector { + pub fn new() -> Self { + Self { + hash: 0, + saved_hash: 0, + snapshot: Snapshot { tape: FxHashMap::default(), heads: Vec::new() }, + power: 1, + lam: 0, + status: DetectionStatus::Running, + } + } + + pub fn reset_with(&mut self, grid: &Grid, heads: &[Head]) { + self.hash = full_hash(grid, heads); + self.saved_hash = self.hash; + self.snapshot = Snapshot::capture(grid, heads); + self.power = 1; + self.lam = 0; + self.status = DetectionStatus::Running; + } + + #[inline] + pub fn cell_delta(&mut self, x: i32, y: i32, old: char, new: char) { + self.hash ^= cell_contrib(x, y, old) ^ cell_contrib(x, y, new); + } + + #[inline] + pub fn head_delta( + &mut self, + index: usize, + old: (i32, i32, Direction, usize), + new: (i32, i32, Direction, usize), + ) { + self.hash ^= head_contrib(index, old.0, old.1, old.2, old.3) + ^ head_contrib(index, new.0, new.1, new.2, new.3); + } + + pub fn mark_stalled(&mut self, at_step: u64) { + if self.status == DetectionStatus::Running { + self.status = DetectionStatus::Stalled { at_step }; + } + } + + pub fn on_step_end(&mut self, grid: &Grid, heads: &[Head], steps: u64) { + if self.status != DetectionStatus::Running { + return; + } + self.lam += 1; + // Only a structural match proves a cycle + if self.hash == self.saved_hash && self.snapshot == Snapshot::capture(grid, heads) { + self.status = DetectionStatus::Cycle { at_step: steps, period: self.lam }; + return; + } + if self.lam == self.power { + self.power <<= 1; + self.lam = 0; + self.saved_hash = self.hash; + self.snapshot = Snapshot::capture(grid, heads); + } + } + + pub fn status(&self) -> DetectionStatus { + self.status + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ratatui::style::Color; + + fn make_head(x: i32, y: i32) -> Head { + Head::new(x, y, Color::White) + } + + #[test] + fn incremental_hash_matches_full_recompute() { + let mut grid = Grid::new(); + let mut heads = vec![make_head(3, 4)]; + let mut det = CycleDetector::new(); + det.reset_with(&grid, &heads); + + let writes = [(1, 2, 'B'), (5, 5, 'C'), (1, 2, 'D'), (5, 5, 'A')]; + for &(x, y, new) in &writes { + let old = grid.get_cell(x, y); + grid.set_cell(x, y, new, Color::White, None, false); + det.cell_delta(x, y, old, new); + } + let old = (heads[0].x, heads[0].y, heads[0].direction, heads[0].internal_state); + heads[0].x = 7; + heads[0].direction = Direction::Left; + heads[0].internal_state = 2; + let new = (7, 4, Direction::Left, 2); + det.head_delta(0, old, new); + + assert_eq!(det.hash, full_hash(&grid, &heads)); + } + + #[test] + fn detects_cycle_with_exact_period() { + let grid = Grid::new(); + let mut heads = vec![make_head(0, 0)]; + let mut det = CycleDetector::new(); + det.reset_with(&grid, &heads); + + let orbit = [ + (1, 0, Direction::Right), + (1, 1, Direction::Down), + (0, 1, Direction::Left), + (0, 0, Direction::Up), + ]; + for step in 1..=40u64 { + let i = ((step - 1) % 4) as usize; + let old = (heads[0].x, heads[0].y, heads[0].direction, heads[0].internal_state); + heads[0].x = orbit[i].0; + heads[0].y = orbit[i].1; + heads[0].direction = orbit[i].2; + det.head_delta(0, old, (orbit[i].0, orbit[i].1, orbit[i].2, 0)); + det.on_step_end(&grid, &heads, step); + if det.status() != DetectionStatus::Running { + break; + } + } + match det.status() { + DetectionStatus::Cycle { period, .. } => assert_eq!(period, 4), + other => panic!("expected cycle, got {:?}", other), + } + } + + #[test] + fn hash_collision_without_structural_match_is_rejected() { + let grid = Grid::new(); + let heads = vec![make_head(0, 0)]; + let mut det = CycleDetector::new(); + det.reset_with(&grid, &heads); + // Forge a collision, same hash but different structure + det.snapshot.heads[0].0 = 99; + det.on_step_end(&grid, &heads, 1); + assert_eq!(det.status(), DetectionStatus::Running); + } + + #[test] + fn reset_clears_status_and_rebuilds_hash() { + let mut grid = Grid::new(); + let heads = vec![make_head(2, 2)]; + let mut det = CycleDetector::new(); + det.mark_stalled(10); + grid.set_cell(1, 1, 'B', Color::White, None, false); + det.reset_with(&grid, &heads); + assert_eq!(det.status(), DetectionStatus::Running); + assert_eq!(det.hash, full_hash(&grid, &heads)); + } + + #[test] + fn stall_is_latched_and_not_overwritten() { + let grid = Grid::new(); + let heads = vec![make_head(0, 0)]; + let mut det = CycleDetector::new(); + det.reset_with(&grid, &heads); + det.mark_stalled(5); + det.on_step_end(&grid, &heads, 6); + assert_eq!(det.status(), DetectionStatus::Stalled { at_step: 5 }); + } +} diff --git a/src/machine/grid.rs b/src/machine/grid.rs index d01f205..489e2dc 100644 --- a/src/machine/grid.rs +++ b/src/machine/grid.rs @@ -9,6 +9,8 @@ pub struct Grid { } impl Grid { + pub const EMPTY: char = 'A'; + pub fn new() -> Self { Self { tape: FxHashMap::with_capacity_and_hasher(8192, Default::default()), @@ -19,11 +21,11 @@ impl Grid { #[inline(always)] pub fn get_cell(&self, x: i32, y: i32) -> char { - self.tape.get(&(x, y)).copied().unwrap_or('A') + self.tape.get(&(x, y)).copied().unwrap_or(Self::EMPTY) } pub fn set_cell(&mut self, x: i32, y: i32, state: char, color: Color, display_char: Option, state_based_colors: bool) { - if state == 'A' && !state_based_colors { + if state == Self::EMPTY && !state_based_colors { self.tape.remove(&(x, y)); self.tape_colors.remove(&(x, y)); self.tape_chars.remove(&(x, y)); diff --git a/src/machine/mod.rs b/src/machine/mod.rs index c82b468..ed0051f 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -1,6 +1,7 @@ pub mod rules; pub mod grid; pub mod heads; +pub mod detection; use ratatui::style::Color; use rustc_hash::{FxHashMap, FxHashSet}; @@ -13,6 +14,7 @@ use crate::machine::rules::Direction; pub use rules::{StateTransition, TurnDirection}; pub use heads::Head; pub use grid::Grid; +pub use detection::{CycleDetector, DetectionStatus}; #[derive(Debug)] pub struct TuringMachine { @@ -33,12 +35,15 @@ pub struct TuringMachine { head_char_sequence: Vec, trail_char_sequence: Vec, sequence_length: usize, + pub detector: CycleDetector, + pub has_looped: bool, + pub auto_halted: bool, } impl TuringMachine { pub fn new(num_heads: usize, rule_string: &str, config: &Config) -> Self { let sequence_length = 10000; - + let mut machine = Self { grid: Grid::new(), heads: Vec::with_capacity(num_heads.min(256)), @@ -57,6 +62,9 @@ impl TuringMachine { head_char_sequence: Vec::with_capacity(sequence_length), trail_char_sequence: Vec::with_capacity(sequence_length), sequence_length, + detector: CycleDetector::new(), + has_looped: false, + auto_halted: false, }; machine.update_colors(config); @@ -125,6 +133,13 @@ impl TuringMachine { } self.generate_random_sequences(config); + self.reset_detection(); + } + + fn reset_detection(&mut self) { + self.detector.reset_with(&self.grid, &self.heads); + self.has_looped = false; + self.auto_halted = false; } // Calculate char based on direction @@ -264,28 +279,35 @@ impl TuringMachine { let cell_color = config.display.get_cell_color(transition.new_cell_state, i); self.grid.set_cell( - head.x, - head.y, - transition.new_cell_state, - cell_color, + head.x, + head.y, + transition.new_cell_state, + cell_color, display_char, config.display.state_based_colors ); + self.detector.cell_delta(head.x, head.y, current_cell, transition.new_cell_state); self.dirty_cells.insert((head.x, head.y)); } } - let updates = self.updates_buffer.clone(); - for (i, _, turn_direction, new_internal_state, x, y, live_color) in updates { + for &(i, _, turn_direction, new_internal_state, x, y, live_color) in &self.updates_buffer { let head = &mut self.heads[i]; + let old = (head.x, head.y, head.direction, head.internal_state); let new_direction = turn_direction.apply(head.direction); head.set_direction(new_direction); head.internal_state = new_internal_state; head.color = live_color; head.move_to(x, y, config.simulation.trail_length); + self.detector.head_delta(i, old, (x, y, new_direction, new_internal_state)); } - + self.steps += 1; + if self.updates_buffer.is_empty() && !self.heads.is_empty() { + self.detector.mark_stalled(self.steps); + } else { + self.detector.on_step_end(&self.grid, &self.heads, self.steps); + } } pub fn tape_chars(&self) -> &FxHashMap<(i32, i32), String> { @@ -296,16 +318,15 @@ impl TuringMachine { self.running = !self.running; } - // Save runtime state and reset - pub fn reset(&mut self, config: &Config) { + fn save_state(&self) { let _ = Config::save_current_seed(&self.current_seed); let _ = Config::save_current_rule(&self.rule_string); - - self.running = config.simulation.autoplay; - self.steps = 0; - self.grid.clear(); - self.dirty_cells.clear(); - self.spawn_heads(config); + } + + // Save runtime state and reset + pub fn reset(&mut self, config: &Config) { + self.save_state(); + self.reset_clean(config); } pub fn reset_clean(&mut self, config: &Config) { @@ -316,6 +337,25 @@ impl TuringMachine { self.spawn_heads(config); } + // Replay the current run, saving state on the first restart only + pub fn restart_replay(&mut self, config: &Config) { + if !self.has_looped { + self.save_state(); + } + self.reset_clean(config); + self.has_looped = true; + self.running = true; + } + + pub fn auto_halt(&mut self) { + self.running = false; + self.auto_halted = true; + } + + pub fn detection_pending(&self) -> bool { + self.detector.status() != DetectionStatus::Running && !self.auto_halted + } + pub fn set_head_count(&mut self, count: usize, config: &Config) { self.num_heads = count.min(256); self.spawn_heads(config); @@ -326,6 +366,7 @@ impl TuringMachine { // Clear existing cells when dimensions change self.grid.clear(); self.dirty_cells.clear(); + self.reset_detection(); } self.grid_width = width; self.grid_height = height; @@ -338,4 +379,74 @@ impl TuringMachine { pub fn tape_colors(&self) -> &FxHashMap<(i32, i32), Color> { &self.grid.tape_colors } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::rules::TurnDirection; + + // 1-head machine with hand-authored rules, no seed or state files + fn test_machine(transitions: &[((usize, char), StateTransition)]) -> (TuringMachine, Config) { + let config = Config::default(); + let mut m = TuringMachine::new(1, "RL", &config); + m.rules = transitions.iter().cloned().collect(); + m.heads.truncate(1); + m.heads[0].x = 4; + m.heads[0].y = 4; + m.heads[0].direction = Direction::Up; + m.heads[0].internal_state = 0; + m.grid.clear(); + m.steps = 0; + m.detector.reset_with(&m.grid, &m.heads); + (m, config) + } + + #[test] + fn walling_in_head_stalls() { + // Paints a 2x2 box then hits its own 'B' with no rule and freezes + let (mut m, config) = test_machine(&[( + (0, 'A'), + StateTransition { new_cell_state: 'B', turn_direction: TurnDirection::Right, new_internal_state: 0 }, + )]); + for _ in 0..100 { + m.step(8, 8, &config); + } + assert!(matches!(m.detector.status(), DetectionStatus::Stalled { .. })); + } + + #[test] + fn orbiting_head_cycles_with_period_4() { + // Writes nothing and turns right forever, a pure 4-step orbit + let (mut m, config) = test_machine(&[( + (0, 'A'), + StateTransition { new_cell_state: 'A', turn_direction: TurnDirection::Right, new_internal_state: 0 }, + )]); + for _ in 0..100 { + m.step(8, 8, &config); + if m.detector.status() != DetectionStatus::Running { + break; + } + } + match m.detector.status() { + DetectionStatus::Cycle { period, .. } => assert_eq!(period, 4), + other => panic!("expected cycle, got {:?}", other), + } + } + + #[test] + fn reset_returns_detector_to_running() { + let (mut m, config) = test_machine(&[( + (0, 'A'), + StateTransition { new_cell_state: 'B', turn_direction: TurnDirection::Right, new_internal_state: 0 }, + )]); + for _ in 0..100 { + m.step(8, 8, &config); + } + assert!(matches!(m.detector.status(), DetectionStatus::Stalled { .. })); + m.has_looped = true; + m.reset_clean(&config); + assert_eq!(m.detector.status(), DetectionStatus::Running); + assert!(!m.has_looped, "new run must clear the proven-loop flag"); + } } \ No newline at end of file From 33e03f084d097fd999e76ad11c5429425af21d07 Mon Sep 17 00:00:00 2001 From: cenonym <131857452+cenonym@users.noreply.github.com> Date: Fri, 3 Jul 2026 08:08:21 +0200 Subject: [PATCH 2/7] feat: add simulation mode with halt and loop - mode = "halt" stops the machine when a run provably ends - mode = "loop" restarts the same rule and seed indefinitely - Restarts keep running regardless of autoplay and save state once --- src/config/mod.rs | 2 +- src/config/simulation.rs | 32 ++++++++++++++++++- src/render/mod.rs | 66 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index 0da9cae..4315f42 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -7,7 +7,7 @@ use ratatui::style::Color; use serde::{Deserialize, Serialize}; use std::{error::Error, fs, path::PathBuf}; -pub use simulation::SimulationConfig; +pub use simulation::{SimulationConfig, SimMode}; pub use display::{DisplayConfig, CharData}; pub use controls::ControlsConfig; diff --git a/src/config/simulation.rs b/src/config/simulation.rs index 6f0ba48..fb3cf87 100644 --- a/src/config/simulation.rs +++ b/src/config/simulation.rs @@ -2,6 +2,14 @@ use serde::{Deserialize, Serialize}; use rand::Rng; use std::collections::{HashSet}; +// What to do when detection proves a run is done +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum SimMode { + Halt, + Loop, +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct SimulationConfig { #[serde(default = "autoplay")] @@ -18,6 +26,8 @@ pub struct SimulationConfig { pub color_cells: bool, #[serde(default = "seed")] pub seed: Option, + #[serde(default = "mode")] + pub mode: SimMode, } // Default functions @@ -28,6 +38,7 @@ fn speed() -> f64 { 5.0 } fn trail_length() -> usize { 16 } fn color_cells() -> bool { true } fn seed() -> Option { Some(String::new()) } +fn mode() -> SimMode { SimMode::Halt } impl Default for SimulationConfig { fn default() -> Self { @@ -39,6 +50,7 @@ impl Default for SimulationConfig { trail_length: trail_length(), color_cells: color_cells(), seed: seed(), + mode: mode(), } } } @@ -166,7 +178,7 @@ impl SimulationConfig { transitions.join(",") } - + // Score rules based on potential for interesting behavior fn score_rule_potential(rule: &str) -> i32 { let mut score = 0; @@ -194,4 +206,22 @@ impl SimulationConfig { score } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn mode_parses_from_toml_and_defaults_to_halt() { + let parsed: SimulationConfig = toml::from_str("mode = \"loop\"").unwrap(); + assert_eq!(parsed.mode, SimMode::Loop); + let empty: SimulationConfig = toml::from_str("").unwrap(); + assert_eq!(empty.mode, SimMode::Halt); + assert_eq!(SimulationConfig::default().mode, SimMode::Halt); + assert!(toml::from_str::("mode = \"disco\"").is_err()); + // create_example_config serializes this, so the TOML name has to round-trip + let serialized = toml::to_string(&SimulationConfig::default()).unwrap(); + assert!(serialized.contains("mode = \"halt\""), "{serialized}"); + } } \ No newline at end of file diff --git a/src/render/mod.rs b/src/render/mod.rs index ed0b77c..f54a9aa 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -3,7 +3,7 @@ pub mod effects; pub mod ui; use ratatui::Frame; -use crate::{machine::TuringMachine, config::Config}; +use crate::{machine::TuringMachine, config::{Config, SimMode}}; use std::time::Duration; pub struct App { @@ -80,11 +80,28 @@ impl App { for _ in 0..steps_per_frame.min(100) { self.machine.step(width, height, &self.config); + if self.machine.detection_pending() { + break; + } } self.machine.mark_trail_dirty(); self.last_step = std::time::Instant::now(); } + + if self.machine.running { + self.apply_mode_reaction(); + } + } + + fn apply_mode_reaction(&mut self) { + if !self.machine.detection_pending() { + return; + } + match self.config.simulation.mode { + SimMode::Loop => self.machine.restart_replay(&self.config), + SimMode::Halt => self.machine.auto_halt(), + } } } @@ -105,4 +122,51 @@ pub fn ui(f: &mut Frame, app: &mut App) { } app.machine.clear_dirty_cells(); +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::machine::DetectionStatus; + + #[test] + fn no_reaction_while_detector_running() { + let mut config = Config::default(); + config.simulation.mode = SimMode::Loop; + let mut app = App::new(config); + app.machine.running = true; + app.apply_mode_reaction(); + assert!(app.machine.running); + assert!(!app.machine.auto_halted); + } + + // has_looped pre-set keeps the test out of ~/.local/state + #[test] + fn proven_loop_restart_keeps_running_despite_autoplay_off() { + let mut config = Config::default(); + config.simulation.mode = SimMode::Loop; + config.simulation.autoplay = false; + let mut app = App::new(config); + app.machine.running = true; + app.machine.has_looped = true; + app.machine.detector.mark_stalled(10); + app.apply_mode_reaction(); + assert_eq!(app.machine.steps, 0, "restart must reset the run"); + assert!(app.machine.running, "machine-initiated restarts keep running"); + assert!(app.machine.has_looped); + assert_eq!(app.machine.detector.status(), DetectionStatus::Running); + } + + #[test] + fn halt_mode_stops_the_machine_on_detection() { + let mut config = Config::default(); + config.simulation.mode = SimMode::Halt; + let mut app = App::new(config); + app.machine.running = true; + app.machine.detector.mark_stalled(10); + app.apply_mode_reaction(); + assert!(!app.machine.running); + assert!(app.machine.auto_halted); + assert_eq!(app.machine.detector.status(), DetectionStatus::Stalled { at_step: 10 }); + } } \ No newline at end of file From ee7fb4b8a5b90b8f2a987bf671c830fc861a0ff4 Mon Sep 17 00:00:00 2001 From: cenonym <131857452+cenonym@users.noreply.github.com> Date: Fri, 3 Jul 2026 08:09:09 +0200 Subject: [PATCH 3/7] feat: show detection status in statusbar - Running, Looping, Halted or Paused based on machine state - Looping requires a proven restart, Halted means the machine stopped itself --- src/render/ui.rs | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/render/ui.rs b/src/render/ui.rs index 1961055..9703ea3 100644 --- a/src/render/ui.rs +++ b/src/render/ui.rs @@ -302,6 +302,17 @@ pub fn render_help_overlay(f: &mut Frame, app: &App) { render_popup(f, help_text, PopupConfig::help()); } +// Halted means the machine stopped itself, even if paused again after a resume +fn status_label(running: bool, proven_looping: bool, auto_halted: bool) -> &'static str { + if !running { + if auto_halted { "Halted" } else { "Paused" } + } else if proven_looping { + "Looping" + } else { + "Running" + } +} + pub fn render_statusbar_overlay(f: &mut Frame, app: &App) { let speed_ms = if app.step_interval >= std::time::Duration::from_millis(1) { app.step_interval.as_millis() as f64 @@ -315,7 +326,11 @@ pub fn render_statusbar_overlay(f: &mut Frame, app: &App) { format!("{}ms", speed_ms) }; - let running_text = if app.machine.running { "Running" } else { "Paused" }; + let running_text = status_label( + app.machine.running, + app.machine.has_looped, + app.machine.auto_halted, + ); let status_text = format!( "{} | Heads: {} | Steps: {} | Speed: {} | Rule: {} | Seed: {}", @@ -336,4 +351,19 @@ pub fn render_keycast_overlay(f: &mut Frame, app: &App) { let content = vec![Line::from(keypress.clone())]; render_popup(f, content, PopupConfig::keycast()); } -} \ No newline at end of file +} +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn status_label_table() { + assert_eq!(status_label(true, true, false), "Looping"); + assert_eq!(status_label(true, false, false), "Running"); + assert_eq!(status_label(true, false, true), "Running"); // resumed past a halt + assert_eq!(status_label(false, false, false), "Paused"); // manual pause + assert_eq!(status_label(false, true, false), "Paused"); // manual pause beats Looping + assert_eq!(status_label(false, true, true), "Halted"); + assert_eq!(status_label(false, false, true), "Halted"); + } +} From c72f00155bc33576fad28eac1a9a3119426fdb8b Mon Sep 17 00:00:00 2001 From: cenonym <131857452+cenonym@users.noreply.github.com> Date: Fri, 3 Jul 2026 08:10:30 +0200 Subject: [PATCH 4/7] docs: fix home-manager example config - Add missing semicolon after direction_based_chars - Add missing step keybind --- nix/modules/home-manager.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nix/modules/home-manager.nix b/nix/modules/home-manager.nix index 708feaf..e63a1fe 100644 --- a/nix/modules/home-manager.nix +++ b/nix/modules/home-manager.nix @@ -39,11 +39,12 @@ in { cell_char = "░░"; randomize_heads = false; randomize_trails = false; - direction_based_chars = false + direction_based_chars = false; }; controls = { quit = "q"; toggle = " "; + step = "."; reset = "r"; faster = "+"; slower = "-"; From 3c5d5a6cd2d7262f2ebc0d153f9fcd35a12503ec Mon Sep 17 00:00:00 2001 From: cenonym <131857452+cenonym@users.noreply.github.com> Date: Fri, 3 Jul 2026 08:19:53 +0200 Subject: [PATCH 5/7] docs: document mode option --- README.md | 2 ++ nix/modules/home-manager.nix | 1 + 2 files changed, 3 insertions(+) diff --git a/README.md b/README.md index 34e0081..1455971 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ You can also use the `home-manager` module to install and configure `trmt`. Firs config = { simulation = { autoplay = true; + mode = "halt"; heads = 3; rule = "RL"; speed_ms = 20; @@ -193,6 +194,7 @@ https://github.com/user-attachments/assets/eefc272b-09b2-4c9c-93dc-984c1ae60ed0 ```toml [simulation] autoplay = true # If true, simulation starts running automatically on launch, reset and config reload +mode = "halt" # What happens when a run stalls or repeats exactly. "halt" = pause, "loop" = restart heads = 3 # Number of heads on initialization rule = "RL" # Rules for the simulation speed_ms = 20 # Simulation speed in milliseconds diff --git a/nix/modules/home-manager.nix b/nix/modules/home-manager.nix index e63a1fe..c68b184 100644 --- a/nix/modules/home-manager.nix +++ b/nix/modules/home-manager.nix @@ -21,6 +21,7 @@ in { { simulation = { autoplay = true; + mode = "halt"; heads = 3; rule = "RL"; speed_ms = 20; From 6f80bcfc81dfa344e532e3666e1e9f13e32a87fd Mon Sep 17 00:00:00 2001 From: cenonym <131857452+cenonym@users.noreply.github.com> Date: Fri, 3 Jul 2026 08:20:14 +0200 Subject: [PATCH 6/7] docs: add mode option to example configs --- examples/builders.md | 1 + examples/critter_highway.md | 1 + examples/dotgrid.md | 1 + examples/factory.md | 1 + examples/matrix.md | 1 + examples/pipedream.md | 1 + examples/scaffold.md | 1 + examples/transistor.md | 1 + 8 files changed, 8 insertions(+) diff --git a/examples/builders.md b/examples/builders.md index 24488e8..9325965 100644 --- a/examples/builders.md +++ b/examples/builders.md @@ -5,6 +5,7 @@ ```toml [simulation] autoplay = true +mode = "halt" heads = 6 rule = "L1>1,R1>1:R1>1,R0>0" speed_ms = 8.0 diff --git a/examples/critter_highway.md b/examples/critter_highway.md index fd851a4..b5e9e0a 100644 --- a/examples/critter_highway.md +++ b/examples/critter_highway.md @@ -5,6 +5,7 @@ ```toml [simulation] autoplay = true +mode = "halt" heads = 6 rule = "WRSWNL" speed_ms = 10.0 diff --git a/examples/dotgrid.md b/examples/dotgrid.md index 6275aa4..0503385 100644 --- a/examples/dotgrid.md +++ b/examples/dotgrid.md @@ -5,6 +5,7 @@ ```toml [simulation] autoplay = true +mode = "halt" heads = 6 rule = "R1>1,L0>2,U1>0:D0>0,R1>1:L0>1,R1>2" speed_ms = 30.0 diff --git a/examples/factory.md b/examples/factory.md index ae3c18a..42fa7f7 100644 --- a/examples/factory.md +++ b/examples/factory.md @@ -5,6 +5,7 @@ ```toml [simulation] autoplay = true +mode = "halt" heads = 4 rule = "R1>1,L0>1:U1>0,D0>1" speed_ms = 5.0 diff --git a/examples/matrix.md b/examples/matrix.md index 4e46e7b..b6b6a54 100644 --- a/examples/matrix.md +++ b/examples/matrix.md @@ -6,6 +6,7 @@ Inspired by [cmatrix](https://github.com/abishekvashok/cmatrix) and [unimatrix]( ```toml [simulation] autoplay = true +mode = "halt" heads = 128 rule = "S" speed_ms = 100.0 diff --git a/examples/pipedream.md b/examples/pipedream.md index ebb9980..1bcae32 100644 --- a/examples/pipedream.md +++ b/examples/pipedream.md @@ -5,6 +5,7 @@ ```toml [simulation] autoplay = true +mode = "halt" heads = 4 rule = "DUWLWWRWD" speed_ms = 10.0 diff --git a/examples/scaffold.md b/examples/scaffold.md index 6cc3121..28deb80 100644 --- a/examples/scaffold.md +++ b/examples/scaffold.md @@ -5,6 +5,7 @@ ```toml [simulation] autoplay = true +mode = "halt" heads = 4 rule = "DULNESWUNW" speed_ms = 10.0 diff --git a/examples/transistor.md b/examples/transistor.md index 18db4ad..8494fbc 100644 --- a/examples/transistor.md +++ b/examples/transistor.md @@ -5,6 +5,7 @@ ```toml [simulation] autoplay = true +mode = "halt" heads = 5 rule = "WUNRSL" speed_ms = 9.0 From 7cb04ae0f0f293c5d37a9879be2815cb0c174930 Mon Sep 17 00:00:00 2001 From: cenonym <131857452+cenonym@users.noreply.github.com> Date: Fri, 3 Jul 2026 08:53:50 +0200 Subject: [PATCH 7/7] build: update dependencies --- Cargo.lock | 596 ++++++++++++++++++++++++----------------------------- 1 file changed, 268 insertions(+), 328 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a59793..d1e88d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,18 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] [[package]] name = "atomic" @@ -34,9 +43,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "base64" @@ -67,9 +76,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "block-buffer" @@ -82,9 +91,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "by_address" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" [[package]] name = "bytemuck" @@ -115,9 +130,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "compact_str" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" +checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" dependencies = [ "castaway", "cfg-if", @@ -145,13 +160,19 @@ dependencies = [ "libc", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crossterm" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.13.0", "crossterm_winapi", "derive_more", "document-features", @@ -212,7 +233,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -223,7 +244,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -237,9 +258,6 @@ name = "deranged" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "powerfmt", -] [[package]] name = "derive_more" @@ -260,7 +278,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -305,9 +323,9 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "equivalent" @@ -327,9 +345,9 @@ dependencies = [ [[package]] name = "euclid" -version = "0.22.13" +version = "0.22.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df61bf483e837f88d5c2291dcf55c67be7e676b3a51acc48db3a7b163b91ed63" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" dependencies = [ "num-traits", ] @@ -344,6 +362,12 @@ dependencies = [ "regex", ] +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + [[package]] name = "filedescriptor" version = "0.8.3" @@ -375,15 +399,33 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.5" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "futures-core" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] -name = "foldhash" -version = "0.2.0" +name = "futures-task" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] [[package]] name = "generic-array" @@ -420,35 +462,35 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "wasip2", - "wasip3", ] [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ - "foldhash 0.1.5", + "allocator-api2", + "equivalent", + "foldhash", ] [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" dependencies = [ "allocator-api2", "equivalent", - "foldhash 0.2.0", + "foldhash", ] [[package]] @@ -463,12 +505,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" @@ -477,14 +513,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", - "serde", - "serde_core", + "hashbrown 0.17.1", ] [[package]] @@ -498,15 +532,15 @@ dependencies = [ [[package]] name = "instability" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357b7205c6cd18dd2c86ed312d1e70add149aea98e7ef72b9fdf0270e555c11d" +checksum = "5eb2d60ef19920a3a9193c3e371f726ec1dafc045dac788d0fb3704272458971" dependencies = [ "darling", "indoc", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -520,25 +554,26 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.91" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ - "once_cell", + "cfg-if", + "futures-util", "wasm-bindgen", ] [[package]] name = "kasuari" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fe90c1150662e858c7d5f945089b7517b0a80d8bf7ba4b1b5ffc984e7230a5b" +checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899" dependencies = [ "hashbrown 0.16.1", "portable-atomic", @@ -558,33 +593,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] -name = "leb128fmt" -version = "0.1.0" +name = "libc" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] -name = "libc" -version = "0.2.182" +name = "libm" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.14" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ "libc", ] [[package]] name = "line-clipping" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4de44e98ddbf09375cbf4d17714d18f39195f4f4894e8524501726fd9a8a4a" +checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.13.0", ] [[package]] @@ -610,17 +645,17 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "lru" -version = "0.16.3" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" +checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9" dependencies = [ - "hashbrown 0.16.1", + "hashbrown 0.17.1", ] [[package]] @@ -635,9 +670,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "memmem" @@ -662,9 +697,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mio" -version = "1.1.1" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", "log", @@ -678,7 +713,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.13.0", "cfg-if", "cfg_aliases", "libc", @@ -697,9 +732,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-derive" @@ -709,7 +744,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -732,9 +767,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "option-ext" @@ -751,6 +786,30 @@ dependencies = [ "num-traits", ] +[[package]] +name = "palette" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" +dependencies = [ + "approx", + "fast-srgb8", + "libm", + "palette_derive", +] + +[[package]] +name = "palette_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" +dependencies = [ + "by_address", + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -804,7 +863,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -844,7 +903,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -857,7 +916,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -869,6 +928,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + [[package]] name = "portable-atomic" version = "1.13.1" @@ -890,16 +955,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.117", -] - [[package]] name = "proc-macro2" version = "1.0.106" @@ -911,9 +966,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -932,18 +987,18 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "rand_core 0.6.4", ] [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha", "rand_core 0.9.5", @@ -976,31 +1031,35 @@ dependencies = [ [[package]] name = "ratatui" -version = "0.30.0" +version = "0.30.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc" +checksum = "3274ba0a2c5e1bcad2a2005d20f4dc59dad26b2eb0940fb094500dba4099d57d" dependencies = [ "instability", "ratatui-core", "ratatui-crossterm", "ratatui-macros", + "ratatui-termina", "ratatui-termwiz", "ratatui-widgets", + "serde", ] [[package]] name = "ratatui-core" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" +checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.13.0", "compact_str", - "hashbrown 0.16.1", - "indoc", + "critical-section", + "hashbrown 0.17.1", "itertools", "kasuari", "lru", + "palette", + "serde", "strum", "thiserror 2.0.18", "unicode-segmentation", @@ -1010,9 +1069,9 @@ dependencies = [ [[package]] name = "ratatui-crossterm" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3" +checksum = "567584a3b0e6a8203c23de40b4861497266725eb5363dbfd18a1edd603cca9f0" dependencies = [ "cfg-if", "crossterm", @@ -1022,19 +1081,30 @@ dependencies = [ [[package]] name = "ratatui-macros" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f1342a13e83e4bb9d0b793d0ea762be633f9582048c892ae9041ef39c936f4" +checksum = "ed7dc68daa7498a43e4d68e0eb078427e10c38fbcfbb1e42d955f1fa2140d814" dependencies = [ "ratatui-core", "ratatui-widgets", ] [[package]] -name = "ratatui-termwiz" +name = "ratatui-termina" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f76fe0bd0ed4295f0321b1676732e2454024c15a35d01904ddb315afd3d545c" +checksum = "c0bf912d9e66f057a759d92e386a280ea886b352ab757d6ac4d653c7ed2c43c2" +dependencies = [ + "instability", + "ratatui-core", + "termina", +] + +[[package]] +name = "ratatui-termwiz" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf03e0380b7744054d6cb74224fe3adf062a029754933f575ca1e3b4c2ce977" dependencies = [ "ratatui-core", "termwiz", @@ -1042,17 +1112,18 @@ dependencies = [ [[package]] name = "ratatui-widgets" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db" +checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" dependencies = [ - "bitflags 2.11.0", - "hashbrown 0.16.1", + "bitflags 2.13.0", + "hashbrown 0.17.1", "indoc", "instability", "itertools", "line-clipping", "ratatui-core", + "serde", "strum", "time", "unicode-segmentation", @@ -1065,7 +1136,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.13.0", ] [[package]] @@ -1081,9 +1152,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.3" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", @@ -1104,15 +1175,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -1129,7 +1200,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys", @@ -1156,9 +1227,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -1187,20 +1258,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", -] - -[[package]] -name = "serde_json" -version = "1.0.149" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", + "syn 2.0.118", ] [[package]] @@ -1256,15 +1314,21 @@ dependencies = [ [[package]] name = "siphasher" -version = "1.0.2" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + +[[package]] +name = "slab" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "static_assertions" @@ -1280,23 +1344,23 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1312,15 +1376,28 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "termina" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9048a889effe34a5cddee0af7f53285198b16dca3be510858d38dfdb3e62a04e" +dependencies = [ + "bitflags 2.13.0", + "parking_lot", + "rustix", + "signal-hook", + "windows-sys 0.61.2", +] + [[package]] name = "terminfo" version = "0.9.0" @@ -1350,7 +1427,7 @@ checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" dependencies = [ "anyhow", "base64", - "bitflags 2.11.0", + "bitflags 2.13.0", "fancy-regex", "filedescriptor", "finl_unicode", @@ -1410,7 +1487,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1421,14 +1498,14 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "time" -version = "0.3.47" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", "libc", @@ -1441,9 +1518,9 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "toml" @@ -1492,7 +1569,7 @@ version = "0.6.0" dependencies = [ "crossterm", "dirs", - "rand 0.9.2", + "rand 0.9.4", "ratatui", "rustc-hash", "serde", @@ -1501,9 +1578,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "ucd-trie" @@ -1519,9 +1596,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-truncate" @@ -1536,15 +1613,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" - -[[package]] -name = "unicode-xid" -version = "0.2.6" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "utf8parse" @@ -1554,12 +1625,12 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.21.0" +version = "1.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" +checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" dependencies = [ "atomic", - "getrandom 0.4.2", + "getrandom 0.4.3", "js-sys", "wasm-bindgen", ] @@ -1587,27 +1658,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.114" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -1618,9 +1680,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.114" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1628,60 +1690,26 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.114" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.114" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.11.0", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - [[package]] name = "wezterm-bidi" version = "0.2.3" @@ -1859,123 +1887,35 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn 2.0.117", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.117", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.11.0", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" +version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "zerocopy" -version = "0.8.40" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.40" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"