diff --git a/stackline/Cargo.toml b/stackline/Cargo.toml index 7e9a113..6da3068 100755 --- a/stackline/Cargo.toml +++ b/stackline/Cargo.toml @@ -15,7 +15,8 @@ veccell = { version = "0.4.0", features = ["serde"] } pathfinding = "3.0" colored = "2.0" serde = { version = "1", features = ["derive"] } -serde_with = "2.0.0" +serde_with = "2.0" +float_duration = "0.3" [dev-dependencies] criterion = { version = "0.3.5", features = ["html_reports"] } diff --git a/stackline/src/lib.rs b/stackline/src/lib.rs index ad67e86..e1446b0 100644 --- a/stackline/src/lib.rs +++ b/stackline/src/lib.rs @@ -7,10 +7,6 @@ This library is the rust implementation of the core logic of the language. */ -#![feature(div_duration)] -#![feature(drain_filter)] -#![feature(try_blocks)] - use std::num::NonZeroUsize; pub mod signal; diff --git a/stackline/src/utils.rs b/stackline/src/utils.rs index acdbb2f..a7ba2ba 100644 --- a/stackline/src/utils.rs +++ b/stackline/src/utils.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; use std::time::Duration; +use float_duration::FloatDuration; /// Represents one or many undirected orientation(s), since we are in a 2D grid, /// this may either be [Horizontal](Orientation::Horizontal), [Vertical](Orientation::Vertical) or both ([Any](Orientation::Any)) @@ -146,7 +147,9 @@ impl Blink { if self.blink_speed.is_zero() { 0 } else { - self.elapsed.div_duration_f32(self.blink_speed) as usize % amount + let elapsed = FloatDuration::from(self.elapsed); + let blink_speed = FloatDuration::from(self.blink_speed); + (elapsed / blink_speed) as usize % amount } } diff --git a/stackline/tiles/storage.rs b/stackline/tiles/storage.rs index e304a48..0a0e5de 100644 --- a/stackline/tiles/storage.rs +++ b/stackline/tiles/storage.rs @@ -6,6 +6,14 @@ use crate::tile::prelude::*; use serde_with::{serde_as, DefaultOnNull}; use veccell::VecRef; +macro_rules! macro_try { + ( $instructions:block ) => { + (|| { + $instructions + })() + } +} + #[serde_as] #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct Store { @@ -84,7 +92,7 @@ impl Reader { impl Tile for Reader { fn update<'b>(&'b mut self, mut context: UpdateContext<'b>) { if let Some(_signal) = context.take_signal() { - let _: Option<()> = try { + let _: Option<()> = macro_try!({ let store_position = context.offset(self.0.opposite().into_offset())?; let store = context.get(store_position).and_then(get_store)?; let signal = store.signal.clone(); @@ -93,7 +101,9 @@ impl Tile for Reader { let target_position = context.offset(self.0.into_offset())?; let _ = context.send(target_position, self.0, signal); - }; + + Some(()) + }); } if context.state() != State::Idle { diff --git a/stackline/tiles/transmit.rs b/stackline/tiles/transmit.rs index e49af79..1398a1a 100644 --- a/stackline/tiles/transmit.rs +++ b/stackline/tiles/transmit.rs @@ -167,9 +167,18 @@ impl Tile for Sender { } if needs_sending { - for (signal, _time) in self.signals.drain_filter(|(_, time)| *time >= self.length) { - context.send_outbound(self.coordinates.clone(), signal); + let vec = Vec::with_capacity(self.signals.len()); + + // Keep signals where time < self.length, send the other ones + for (signal, time) in std::mem::replace(&mut self.signals, vec) { + if time >= self.length { + context.send_outbound(self.coordinates.clone(), signal); + } else { + self.signals.push((signal, time)); + } } + + self.signals.shrink_to_fit(); } if context.state() == State::Active || context.state() == State::Dormant && self.signals.is_empty() {