🎨 Make clippy happy

main
Shad Amethyst 2 years ago
parent be259cc6f5
commit 9e32cd54b9
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -337,11 +337,12 @@ fn prop(world: &mut World, x: i32, y: i32, prop_name: &str, value: String) {
return return
} }
*tile = match serde_json::from_value(tile_value) { match serde_json::from_value(tile_value) {
Ok(tile) => tile, Ok(t) => {
*tile = t;
}
Err(err) => { Err(err) => {
eprintln!("Error while inserting value: {}", err); eprintln!("Error while inserting value: {}", err);
return
} }
}; };
} }
@ -355,11 +356,12 @@ fn set(world: &mut World, x: i32, y: i32, name: &str) {
} }
}; };
*tile = match AnyTile::new(name) { match AnyTile::new(name) {
Some(tile) => FullTile::from(tile), Some(t) => {
*tile = FullTile::from(t);
}
None => { None => {
eprintln!("No tile named {}", name); eprintln!("No tile named {}", name);
return;
} }
}; };
} }
@ -369,7 +371,6 @@ fn remove(world: &mut World, x: i32, y: i32) {
Some(tile) => *tile = FullTile::new(None), Some(tile) => *tile = FullTile::new(None),
None => { None => {
eprintln!("No tile at {}:{}!", x, y); eprintln!("No tile at {}:{}!", x, y);
return;
} }
} }
} }
@ -382,7 +383,6 @@ fn signal(world: &mut World, x: i32, y: i32) {
} }
None => { None => {
eprintln!("No tile at {}:{}!", x, y); eprintln!("No tile at {}:{}!", x, y);
return;
} }
} }
} }
@ -395,7 +395,6 @@ fn clear(world: &mut World, x: i32, y: i32) {
} }
None => { None => {
eprintln!("No tile at {}:{}!", x, y); eprintln!("No tile at {}:{}!", x, y);
return;
} }
} }
} }
@ -441,7 +440,6 @@ fn push(world: &mut World, x: i32, y: i32, value: String) {
} }
None => { None => {
eprintln!("No tile at {}:{}!", x, y); eprintln!("No tile at {}:{}!", x, y);
return;
} }
} }
} }
@ -472,7 +470,6 @@ fn pop(world: &mut World, x: i32, y: i32) {
} }
None => { None => {
eprintln!("No tile at {}:{}!", x, y); eprintln!("No tile at {}:{}!", x, y);
return;
} }
} }
} }
@ -499,7 +496,6 @@ fn dir(world: &mut World, x: i32, y: i32, direction: &str) {
} }
None => { None => {
eprintln!("No tile at {}:{}!", x, y); eprintln!("No tile at {}:{}!", x, y);
return;
} }
} }
} }
@ -519,7 +515,6 @@ fn state(world: &mut World, x: i32, y: i32, state: &str) {
} }
None => { None => {
eprintln!("No tile at {}:{}!", x, y); eprintln!("No tile at {}:{}!", x, y);
return;
} }
} }
} }

@ -8,7 +8,6 @@ edition = "2021"
[dependencies] [dependencies]
palette = "0.6" palette = "0.6"
enum_dispatch = "0.3" enum_dispatch = "0.3"
contracts = { version = "0.6.3", features = ["override_debug"] }
veccell = { version = "0.4.0", features = ["serde"] } veccell = { version = "0.4.0", features = ["serde"] }
pathfinding = "3.0" pathfinding = "3.0"
colored = "2.0" colored = "2.0"

@ -1,6 +1,7 @@
use std::env; use std::env;
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::fmt::Write;
use syn::{Item, ItemImpl, Type}; use syn::{Item, ItemImpl, Type};
// This script reads the contents of any rust file in the `tiles/` directory, // This script reads the contents of any rust file in the `tiles/` directory,
@ -38,6 +39,7 @@ fn main() {
.unwrap_or_else(|err| panic!("Unable to parse file {:?}: {}", src_path, err)); .unwrap_or_else(|err| panic!("Unable to parse file {:?}: {}", src_path, err));
for item in syntax.items.iter() { for item in syntax.items.iter() {
#[allow(clippy::single_match)] // I'd like to keep the match for future-proofing, for instance if I need to match for a macro call
match item { match item {
Item::Impl(item) => { Item::Impl(item) => {
if let Some(name) = parse_impl_tile(item) { if let Some(name) = parse_impl_tile(item) {
@ -48,9 +50,9 @@ fn main() {
} }
} }
if local_names.len() > 0 { if !local_names.is_empty() {
let canonical = fs::canonicalize(src_path.clone()) let canonical = fs::canonicalize(src_path.clone())
.expect(&format!("Couldn't canonicalize {:?}", src_path)); .unwrap_or_else(|err| panic!("Couldn't canonicalize {}: {}", src_path.display(), err));
for name in local_names.iter() { for name in local_names.iter() {
names.push(name.clone()); names.push(name.clone());
} }
@ -72,7 +74,7 @@ fn parse_impl_tile(item: &ItemImpl) -> Option<String> {
let (_, trait_, _) = item.trait_.as_ref()?; let (_, trait_, _) = item.trait_.as_ref()?;
let ident = trait_.get_ident()?; let ident = trait_.get_ident()?;
if ident.to_string() == "Tile" { if *ident == "Tile" {
if let Type::Path(path) = &*item.self_ty { if let Type::Path(path) = &*item.self_ty {
let name = path.path.get_ident().map(|i| i.to_string())?; let name = path.path.get_ident().map(|i| i.to_string())?;
return Some(name); return Some(name);
@ -102,18 +104,17 @@ fn generate_code(files: Vec<(PathBuf, Vec<String>)>, names: Vec<String>) -> Stri
let module_name = file let module_name = file
.as_path() .as_path()
.file_stem() .file_stem()
.map(|x| x.to_str()) .and_then(|x| x.to_str())
.flatten() .unwrap_or_else(|| panic!(
.expect(&format!(
"Couldn't extract valid UTF-8 filename from path {:?}", "Couldn't extract valid UTF-8 filename from path {:?}",
file file
)); ));
let path = file.as_path().to_str().expect("Invalid UTF-8 path"); let path = file.as_path().to_str().expect("Invalid UTF-8 path");
res += &format!("#[path = \"{}\"]\nmod {};\n", path, module_name); writeln!(res, "#[path = \"{}\"]\nmod {};", path, module_name).unwrap();
res += &format!("pub use {}::{{", module_name); write!(res, "pub use {}::{{", module_name).unwrap();
for name in names { for name in names {
res += &format!("{}, ", name); write!(res, "{}, ", name).unwrap();
} }
res += "};\n\n"; res += "};\n\n";
} }
@ -125,7 +126,7 @@ fn generate_code(files: Vec<(PathBuf, Vec<String>)>, names: Vec<String>) -> Stri
res += "pub enum AnyTile {\n"; res += "pub enum AnyTile {\n";
for name in names.iter() { for name in names.iter() {
res += &format!(" {0}({0}),\n", name); writeln!(res, " {0}({0}),", name).unwrap();
} }
res += "}\n"; res += "}\n";
@ -136,7 +137,7 @@ fn generate_code(files: Vec<(PathBuf, Vec<String>)>, names: Vec<String>) -> Stri
res += " match name {\n"; res += " match name {\n";
for name in names.iter() { for name in names.iter() {
res += &format!(" \"{0}\" => Some(Self::{0}(<{0} as Default>::default())),\n", name); writeln!(res, " \"{0}\" => Some(Self::{0}(<{0} as Default>::default())),", name).unwrap();
} }
res += " _ => None\n"; res += " _ => None\n";
@ -144,7 +145,7 @@ fn generate_code(files: Vec<(PathBuf, Vec<String>)>, names: Vec<String>) -> Stri
for name in names { for name in names {
// impl<T: Tile> TryInto<&T> for &AnyTile // impl<T: Tile> TryInto<&T> for &AnyTile
res += &format!( writeln!(res,
concat!( concat!(
"impl<'a> TryInto<&'a {0}> for &'a AnyTile {{\n", "impl<'a> TryInto<&'a {0}> for &'a AnyTile {{\n",
" type Error = ();\n", " type Error = ();\n",
@ -154,13 +155,13 @@ fn generate_code(files: Vec<(PathBuf, Vec<String>)>, names: Vec<String>) -> Stri
" _ => Err(()),\n", " _ => Err(()),\n",
" }}\n", " }}\n",
" }}\n", " }}\n",
"}}\n", "}}",
), ),
name name
); ).unwrap();
// impl<T: Tile> TryInto<&mut T> for &mut AnyTile // impl<T: Tile> TryInto<&mut T> for &mut AnyTile
res += &format!( writeln!(res,
concat!( concat!(
"impl<'a> TryInto<&'a mut {0}> for &'a mut AnyTile {{\n", "impl<'a> TryInto<&'a mut {0}> for &'a mut AnyTile {{\n",
" type Error = ();\n", " type Error = ();\n",
@ -170,10 +171,10 @@ fn generate_code(files: Vec<(PathBuf, Vec<String>)>, names: Vec<String>) -> Stri
" _ => Err(()),\n", " _ => Err(()),\n",
" }}\n", " }}\n",
" }}\n", " }}\n",
"}}\n", "}}",
), ),
name name
); ).unwrap();
} }
res res

@ -65,22 +65,6 @@ pub struct UpdateContext<'a> {
impl<'a> UpdateContext<'a> { impl<'a> UpdateContext<'a> {
/// Creates a new UpdateContext /// Creates a new UpdateContext
/// Returns `None` if the tile was already updated, is empty or does not exist. /// Returns `None` if the tile was already updated, is empty or does not exist.
#[ensures(
old(pane.get(position).is_none()) -> ret.is_none(),
"Should return None if the tile does not exist"
)]
#[ensures(
old(pane.get(position).is_some() && pane.get(position).unwrap().updated) -> ret.is_none(),
"Should return None if the tile was already updated"
)]
#[ensures(
old(pane.get(position).is_some() && (*pane.get(position).unwrap()).get().is_none()) -> ret.is_none(),
"Should return None if the tile is empty"
)]
#[ensures(
ret.is_some() -> ret.as_ref().unwrap().0.commit.updates.iter().find(|&&x| x == position).is_some(),
"Should add an entry in self.commit.updates if result is Some"
)]
pub(crate) fn new<'b>( pub(crate) fn new<'b>(
pane: &'b Pane, pane: &'b Pane,
position: (usize, usize), position: (usize, usize),
@ -100,7 +84,7 @@ impl<'a> UpdateContext<'a> {
position, position,
state: tile.state(), state: tile.state(),
signal: tile.take_signal(), signal: tile.take_signal(),
pane: pane, pane,
commit, commit,
}; };
@ -178,7 +162,6 @@ impl<'a> UpdateContext<'a> {
/// } /// }
/// ``` /// ```
#[inline] #[inline]
#[ensures(self.signal.is_none(), "Should leave the signal to None")]
pub fn take_signal(&mut self) -> Option<Signal> { pub fn take_signal(&mut self) -> Option<Signal> {
std::mem::take(&mut self.signal) std::mem::take(&mut self.signal)
} }
@ -195,11 +178,6 @@ impl<'a> UpdateContext<'a> {
/// ///
/// The actions of this function will only be executed *after* all the tiles of the [`Pane`] were [`updated`](Pane::step). /// The actions of this function will only be executed *after* all the tiles of the [`Pane`] were [`updated`](Pane::step).
#[inline] #[inline]
#[ensures(
self.commit.states.iter().find(|(x, y, _)| self.position == (*x, *y)).is_some(),
"Should add an entry in self.commit.states"
)]
#[ensures(self.state == state)]
pub fn set_state(&mut self, state: State) { pub fn set_state(&mut self, state: State) {
self.state = state; self.state = state;
self.commit.set_state(self.position, self.state); self.commit.set_state(self.position, self.state);
@ -211,11 +189,6 @@ impl<'a> UpdateContext<'a> {
/// ///
/// The actions of this function will only be executed *after* all the tiles of the [`Pane`] were [`updated`](Pane::step). /// The actions of this function will only be executed *after* all the tiles of the [`Pane`] were [`updated`](Pane::step).
#[inline] #[inline]
#[ensures(
self.commit.states.iter().find(|(x, y, _)| self.position == (*x, *y)).is_some(),
"Should add an entry in self.commit.states"
)]
#[ensures(self.state == old(self.state).next())]
pub fn next_state(&mut self) { pub fn next_state(&mut self) {
self.state = self.state.next(); self.state = self.state.next();
self.commit.set_state(self.position, self.state); self.commit.set_state(self.position, self.state);
@ -243,7 +216,6 @@ impl<'a> UpdateContext<'a> {
/// Returns `true` iff `(x, y)` is within the bounds of the current pane. /// Returns `true` iff `(x, y)` is within the bounds of the current pane.
#[inline] #[inline]
#[ensures(ret == true -> position.0 < self.width().get() && position.1 < self.height().get())]
pub fn in_bounds(&self, position: (usize, usize)) -> bool { pub fn in_bounds(&self, position: (usize, usize)) -> bool {
self.pane.in_bounds(position) self.pane.in_bounds(position)
} }
@ -261,7 +233,6 @@ impl<'a> UpdateContext<'a> {
/// Returns whether or not the tile at `pos` accepts a signal coming from `direction`. /// Returns whether or not the tile at `pos` accepts a signal coming from `direction`.
/// If the tile does not exist, then this function will return `false`. /// If the tile does not exist, then this function will return `false`.
#[inline] #[inline]
#[ensures(ret == true -> self.get(pos).is_some() && (*self.get(pos).unwrap()).get().is_some())]
pub fn accepts_signal(&self, pos: (usize, usize), direction: Direction) -> bool { pub fn accepts_signal(&self, pos: (usize, usize), direction: Direction) -> bool {
match self.get(pos) { match self.get(pos) {
Some(tile) => tile.accepts_signal(direction), Some(tile) => tile.accepts_signal(direction),
@ -313,15 +284,6 @@ impl<'a> UpdateContext<'a> {
/// ///
/// The actions of this function will only be executed *after* all the tiles of the [`Pane`] were [`updated`](Pane::step). /// The actions of this function will only be executed *after* all the tiles of the [`Pane`] were [`updated`](Pane::step).
/// See [`keep`](UpdateContext::keep) for a variant of this method that takes effect immediately. /// See [`keep`](UpdateContext::keep) for a variant of this method that takes effect immediately.
#[ensures(
!self.in_bounds(position) -> ret.is_err(),
"Should return None if position is out of bounds"
)]
#[ensures(
ret.is_ok() -> self.commit.signals.iter().find(|(x, y, _)| position == (*x, *y)).is_some(),
"Should add an entry in self.commit.signals if result is Some"
)]
#[allow(unused_mut)]
pub fn force_send(&mut self, position: (usize, usize), mut signal: Signal) -> Result<(), SendError> { pub fn force_send(&mut self, position: (usize, usize), mut signal: Signal) -> Result<(), SendError> {
if !self.in_bounds(position) { if !self.in_bounds(position) {
return Err(SendError(signal)); return Err(SendError(signal));
@ -341,14 +303,6 @@ impl<'a> UpdateContext<'a> {
/// ///
/// The actions of this function will only be executed *after* all the tiles of the [`Pane`] were [`updated`](Pane::step). /// The actions of this function will only be executed *after* all the tiles of the [`Pane`] were [`updated`](Pane::step).
/// See [`keep`](UpdateContext::keep) for a variant of this method that takes effect immediately. /// See [`keep`](UpdateContext::keep) for a variant of this method that takes effect immediately.
#[ensures(
!self.in_bounds(position) -> ret.is_err(),
"Should return None if position is out of bounds"
)]
#[ensures(
ret.is_ok() -> self.commit.signals.iter().find(|(x, y, _)| position == (*x, *y)).is_some(),
"Should add an entry in self.commit.signals if result is Some"
)]
pub fn send(&mut self, position: (usize, usize), direction: Direction, signal: Signal) -> Result<(), SendError> { pub fn send(&mut self, position: (usize, usize), direction: Direction, signal: Signal) -> Result<(), SendError> {
if self.accepts_signal(position, direction) { if self.accepts_signal(position, direction) {
let original_direction = signal.direction(); let original_direction = signal.direction();
@ -394,13 +348,9 @@ impl<'a> UpdateContext<'a> {
/// } /// }
/// } /// }
/// ``` /// ```
#[ensures(self.signal.is_none())]
pub fn keep(&mut self) { pub fn keep(&mut self) {
match std::mem::take(&mut self.signal) { if let Some(signal) = std::mem::take(&mut self.signal) {
Some(signal) => { self.commit.set_self_signal(Some(signal));
self.commit.set_self_signal(Some(signal));
},
_ => {}
} }
} }
@ -513,11 +463,8 @@ impl UpdateCommit {
/// Applies transformations on a FullTile before the end of the update phase /// Applies transformations on a FullTile before the end of the update phase
#[inline] #[inline]
pub(crate) fn apply_immediate(&mut self, tile: &mut FullTile) { pub(crate) fn apply_immediate(&mut self, tile: &mut FullTile) {
match std::mem::take(&mut self.self_signal) { if let Some(signal) = std::mem::take(&mut self.self_signal) {
Some(signal) => { tile.set_signal(Some(signal));
tile.set_signal(Some(signal));
}
None => {}
} }
} }
} }

@ -9,9 +9,6 @@ This library is the rust implementation of the core logic of the language.
#![feature(drain_filter)] #![feature(drain_filter)]
#[macro_use]
extern crate contracts;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
pub mod signal; pub mod signal;

@ -36,8 +36,6 @@ impl Pane {
/// // Perform a simulation step /// // Perform a simulation step
/// pane.step(); /// pane.step();
/// ``` /// ```
#[ensures(ret.is_some() -> width > 0)]
#[ensures(ret.is_some() -> height > 0)]
pub fn empty(width: usize, height: usize) -> Option<Self> { pub fn empty(width: usize, height: usize) -> Option<Self> {
// TODO: check that width * height is a valid usize // TODO: check that width * height is a valid usize
let length = width.checked_mul(height)?; let length = width.checked_mul(height)?;
@ -120,10 +118,6 @@ impl Pane {
/// assert_eq!(pane.offset((1, 0), (3, 0)), None); // (1 + 3, 0 + 0) = (4, 0), outside /// assert_eq!(pane.offset((1, 0), (3, 0)), None); // (1 + 3, 0 + 0) = (4, 0), outside
/// ``` /// ```
#[inline] #[inline]
#[ensures(ret.is_some() -> position.0 as isize + offset.0 as isize >= 0)]
#[ensures(ret.is_some() -> position.1 as isize + offset.1 as isize >= 0)]
#[ensures(ret.is_some() -> position.0 as isize + (offset.0 as isize) < self.width.get() as isize)]
#[ensures(ret.is_some() -> position.1 as isize + (offset.1 as isize) < self.height.get() as isize)]
pub fn offset(&self, position: (usize, usize), offset: (i8, i8)) -> Option<(usize, usize)> { pub fn offset(&self, position: (usize, usize), offset: (i8, i8)) -> Option<(usize, usize)> {
if offset.0 < 0 && (-offset.0) as usize > position.0 if offset.0 < 0 && (-offset.0) as usize > position.0
|| offset.1 < 0 && (-offset.1) as usize > position.1 || offset.1 < 0 && (-offset.1) as usize > position.1
@ -161,8 +155,7 @@ impl Pane {
/// let tile = pane.get((0, 0)).unwrap(); /// let tile = pane.get((0, 0)).unwrap();
/// ``` /// ```
#[inline] #[inline]
#[ensures(self.in_bounds(position) -> ret.is_some())] pub fn get(&self, position: (usize, usize)) -> Option<VecRef<'_, FullTile>> {
pub fn get<'b>(&'b self, position: (usize, usize)) -> Option<VecRef<'b, FullTile>> {
if !self.in_bounds(position) { if !self.in_bounds(position) {
return None; return None;
} }
@ -221,8 +214,7 @@ impl Pane {
/// tile.set_state(State::Active); /// tile.set_state(State::Active);
/// ``` /// ```
#[inline] #[inline]
#[ensures(old(self.in_bounds(position)) -> ret.is_some())] pub fn get_mut(&mut self, position: (usize, usize)) -> Option<&mut FullTile> {
pub fn get_mut<'b>(&'b mut self, position: (usize, usize)) -> Option<&'b mut FullTile> {
if !self.in_bounds(position) { if !self.in_bounds(position) {
return None; return None;
} }
@ -252,7 +244,7 @@ impl Pane {
/// *wire = Wire::new(Orientation::Vertical); /// *wire = Wire::new(Orientation::Vertical);
/// ``` /// ```
#[inline] #[inline]
pub fn get_mut_as<'b, T: Tile>(&'b mut self, position: (usize, usize)) -> Option<&'b mut T> pub fn get_mut_as<T: Tile>(&mut self, position: (usize, usize)) -> Option<&mut T>
where where
for<'c> &'c mut AnyTile: TryInto<&'c mut T>, for<'c> &'c mut AnyTile: TryInto<&'c mut T>,
{ {
@ -265,10 +257,10 @@ impl Pane {
/// This function does not need a mutable reference to `self`, and makes use /// This function does not need a mutable reference to `self`, and makes use
/// of [`VecCell`]'s ability to provide interior mutability for one item at a time. /// of [`VecCell`]'s ability to provide interior mutability for one item at a time.
#[inline] #[inline]
pub(crate) fn borrow_mut<'b>( pub(crate) fn borrow_mut(
&'b self, &self,
position: (usize, usize), position: (usize, usize),
) -> Option<VecRefMut<'b, FullTile>> { ) -> Option<VecRefMut<'_, FullTile>> {
if !self.in_bounds(position) { if !self.in_bounds(position) {
return None; return None;
} }
@ -303,7 +295,7 @@ impl Pane {
/// *wire = Wire::new(Orientation::Vertical); /// *wire = Wire::new(Orientation::Vertical);
/// ``` /// ```
#[inline] #[inline]
pub fn borrow_mut_as<'b, T: Tile>(&'b self, position: (usize, usize)) -> Option<VecRefMut<'b, T>> pub fn borrow_mut_as<T: Tile>(&self, position: (usize, usize)) -> Option<VecRefMut<'_, T>>
where where
for<'c> &'c mut AnyTile: TryInto<&'c mut T>, for<'c> &'c mut AnyTile: TryInto<&'c mut T>,
{ {
@ -318,7 +310,6 @@ impl Pane {
/// Sets the tile at `position` to `tile`. `T` must either implement [`Tile`] or be `()`. /// Sets the tile at `position` to `tile`. `T` must either implement [`Tile`] or be `()`.
#[inline] #[inline]
#[ensures(self.in_bounds(position) -> ret.is_some())]
pub fn set_tile<T>(&mut self, position: (usize, usize), tile: T) -> Option<()> pub fn set_tile<T>(&mut self, position: (usize, usize), tile: T) -> Option<()>
where where
FullTile: From<T>, FullTile: From<T>,
@ -353,9 +344,8 @@ impl Pane {
/// assert_eq!(pane.get_state((0, 0)), Some(State::Dormant)); /// assert_eq!(pane.get_state((0, 0)), Some(State::Dormant));
/// ``` /// ```
#[inline] #[inline]
#[ensures(self.in_bounds(position) -> ret.is_some())]
pub fn get_state(&self, position: (usize, usize)) -> Option<State> { pub fn get_state(&self, position: (usize, usize)) -> Option<State> {
self.get(position).map(|x| x.state().clone()) self.get(position).map(|x| x.state())
} }
/// Sets the signal for the tile at `position` to `signal`. /// Sets the signal for the tile at `position` to `signal`.
@ -384,9 +374,6 @@ impl Pane {
/// assert!(pane.get((0, 0)).unwrap().signal().is_some()); /// assert!(pane.get((0, 0)).unwrap().signal().is_some());
/// ``` /// ```
#[inline] #[inline]
#[ensures(ret.is_some() -> self.in_bounds(position) && (*self.get(position).unwrap()).get().is_some())]
#[ensures(!self.in_bounds(position) -> ret.is_none())]
#[allow(unused_mut)]
pub fn set_signal(&mut self, position: (usize, usize), mut signal: Signal) -> Option<()> { pub fn set_signal(&mut self, position: (usize, usize), mut signal: Signal) -> Option<()> {
signal.set_position(position); signal.set_position(position);
if let Some(tile) = self.get_mut(position) { if let Some(tile) = self.get_mut(position) {
@ -418,15 +405,13 @@ impl Pane {
} }
#[inline] #[inline]
#[ensures(self.in_bounds(position) -> self.get(position).unwrap().updated)]
#[ensures(!self.in_bounds(position) -> ret.is_none())]
fn update(&mut self, position: (usize, usize), commit: &mut UpdateCommit) -> Option<()> { fn update(&mut self, position: (usize, usize), commit: &mut UpdateCommit) -> Option<()> {
// NOTE: Tiles will only be updated once as per UpdateContext::new // NOTE: Tiles will only be updated once as per UpdateContext::new
let (ctx, mut tile) = UpdateContext::new(self, position, commit)?; let (ctx, mut tile) = UpdateContext::new(self, position, commit)?;
(*tile).get_mut()?.update(ctx); (*tile).get_mut()?.update(ctx);
commit.apply_immediate(&mut *tile); commit.apply_immediate(&mut tile);
Some(()) Some(())
} }
@ -483,7 +468,7 @@ impl Pane {
pub fn step(&mut self) -> PaneResult { pub fn step(&mut self) -> PaneResult {
let mut commit = UpdateCommit::new(); let mut commit = UpdateCommit::new();
for position in std::mem::replace(&mut self.signals, Vec::new()) { for position in std::mem::take(&mut self.signals) {
let _ = self.update(position, &mut commit); let _ = self.update(position, &mut commit);
} }
@ -500,11 +485,11 @@ impl Pane {
/// Returns an iterator over the tiles and their coordinates /// Returns an iterator over the tiles and their coordinates
#[inline] #[inline]
pub fn tiles<'b>(&'b self) -> impl Iterator<Item = (usize, usize, VecRef<'b, FullTile>)> + 'b { pub fn tiles(&self) -> impl Iterator<Item = (usize, usize, VecRef<'_, FullTile>)> + '_ {
self.tiles self.tiles
.iter() .iter()
.enumerate() .enumerate()
.filter_map(move |(i, v)| Some((i % self.width, i / self.width, v))) .map(move |(i, v)| (i % self.width, i / self.width, v))
} }
/// Draws the Pane at `(dx + self.position.0, dy + self.position.1)` on a [`TextSurface`]. /// Draws the Pane at `(dx + self.position.0, dy + self.position.1)` on a [`TextSurface`].

@ -24,7 +24,7 @@ impl Value {
impl From<f64> for Value { impl From<f64> for Value {
fn from(x: f64) -> Value { fn from(x: f64) -> Value {
Value::Number(x.into()) Value::Number(x)
} }
} }
@ -174,10 +174,15 @@ impl Signal {
/// ///
/// assert_eq!(signal.len(), 2); /// assert_eq!(signal.len(), 2);
/// ``` /// ```
#[allow(clippy::len_without_is_empty)] // The signal will hold a `heap` in the future, making `is_empty` ambiguous
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.stack.len() self.stack.len()
} }
pub fn is_stack_empty(&self) -> bool {
self.stack.is_empty()
}
pub fn stack(&self) -> &Vec<Value> { pub fn stack(&self) -> &Vec<Value> {
&self.stack &self.stack
} }

@ -144,7 +144,7 @@ impl std::fmt::Display for TextSurface {
write!(f, "{}", string)?; write!(f, "{}", string)?;
} }
write!(f, "\n")?; writeln!(f)?;
} }
Ok(()) Ok(())

@ -48,19 +48,19 @@ impl FullTile {
/// Returns the internal state of this full tile /// Returns the internal state of this full tile
#[inline] #[inline]
pub fn get<'b>(&'b self) -> Option<&'b AnyTile> { pub fn get(&self) -> Option<&AnyTile> {
self.cell.as_ref() self.cell.as_ref()
} }
/// Returns a mutable reference to the internal state of this tile /// Returns a mutable reference to the internal state of this tile
#[inline] #[inline]
pub fn get_mut<'b>(&'b mut self) -> Option<&'b mut AnyTile> { pub fn get_mut(&mut self) -> Option<&mut AnyTile> {
self.cell.as_mut() self.cell.as_mut()
} }
/// Returns the signal of this tile /// Returns the signal of this tile
#[inline] #[inline]
pub fn signal<'b>(&'b self) -> Option<&'b Signal> { pub fn signal(&self) -> Option<&Signal> {
self.signal.as_ref() self.signal.as_ref()
} }
@ -89,9 +89,8 @@ impl FullTile {
/// Draws itself on a [`TextSurface`] at `(x, y)`. /// Draws itself on a [`TextSurface`] at `(x, y)`.
/// If the tile is empty, does nothing /// If the tile is empty, does nothing
pub fn draw(&self, x: i32, y: i32, surface: &mut TextSurface) { pub fn draw(&self, x: i32, y: i32, surface: &mut TextSurface) {
match self.cell { if let Some(cell) = &self.cell {
Some(ref cell) => cell.draw(x, y, self.state, surface), cell.draw(x, y, self.state, surface);
None => {}
} }
} }
} }

@ -53,14 +53,13 @@ impl Orientation {
/// Returns true iff `dir ∈ self` /// Returns true iff `dir ∈ self`
#[inline] #[inline]
pub fn contains(&self, dir: Direction) -> bool { pub fn contains(&self, dir: Direction) -> bool {
match (self, dir) { matches!((self, dir),
(Orientation::Vertical, Direction::Up) => true, (Orientation::Vertical, Direction::Up)
(Orientation::Vertical, Direction::Down) => true, | (Orientation::Vertical, Direction::Down)
(Orientation::Horizontal, Direction::Left) => true, | (Orientation::Horizontal, Direction::Left)
(Orientation::Horizontal, Direction::Right) => true, | (Orientation::Horizontal, Direction::Right)
(Orientation::Any, _) => true, | (Orientation::Any, _)
_ => false, )
}
} }
} }
@ -115,10 +114,7 @@ impl State {
/// Returns true if `Idle` /// Returns true if `Idle`
pub fn accepts_signal(self) -> bool { pub fn accepts_signal(self) -> bool {
match self { matches!(self, State::Idle)
State::Idle => true,
_ => false,
}
} }
} }

@ -34,7 +34,7 @@ impl World {
self.panes.insert(name, pane); self.panes.insert(name, pane);
} }
pub fn get<'b>(&'b self, (x, y): (i32, i32)) -> Option<VecRef<'b, FullTile>> { pub fn get(&self, (x, y): (i32, i32)) -> Option<VecRef<'_, FullTile>> {
for pane in self.panes.values() { for pane in self.panes.values() {
let x2 = x - pane.position().0; let x2 = x - pane.position().0;
let y2 = y - pane.position().1; let y2 = y - pane.position().1;
@ -49,7 +49,7 @@ impl World {
None None
} }
pub fn get_with_pos<'b>(&'b self, (x, y): (i32, i32)) -> Option<(VecRef<'b, FullTile>, usize, usize)> { pub fn get_with_pos(&self, (x, y): (i32, i32)) -> Option<(VecRef<'_, FullTile>, usize, usize)> {
for pane in self.panes.values() { for pane in self.panes.values() {
let x2 = x - pane.position().0; let x2 = x - pane.position().0;
let y2 = y - pane.position().1; let y2 = y - pane.position().1;
@ -64,7 +64,7 @@ impl World {
None None
} }
pub fn get_mut<'b>(&'b mut self, (x, y): (i32, i32)) -> Option<&'b mut FullTile> { pub fn get_mut(&mut self, (x, y): (i32, i32)) -> Option<&mut FullTile> {
for pane in self.panes.values_mut() { for pane in self.panes.values_mut() {
let x2 = x - pane.position().0; let x2 = x - pane.position().0;
let y2 = y - pane.position().1; let y2 = y - pane.position().1;
@ -79,7 +79,7 @@ impl World {
None None
} }
pub fn get_mut_with_pos<'b>(&'b mut self, (x, y): (i32, i32)) -> Option<(&'b mut FullTile, usize, usize)> { pub fn get_mut_with_pos(&mut self, (x, y): (i32, i32)) -> Option<(&mut FullTile, usize, usize)> {
for pane in self.panes.values_mut() { for pane in self.panes.values_mut() {
let x2 = x - pane.position().0; let x2 = x - pane.position().0;
let y2 = y - pane.position().1; let y2 = y - pane.position().1;
@ -94,11 +94,11 @@ impl World {
None None
} }
pub fn get_pane<'b>(&'b self, name: &str) -> Option<&'b Pane> { pub fn get_pane(&self, name: &str) -> Option<&Pane> {
self.panes.get(name) self.panes.get(name)
} }
pub fn get_pane_mut<'b>(&'b mut self, name: &str) -> Option<&'b mut Pane> { pub fn get_pane_mut(&mut self, name: &str) -> Option<&mut Pane> {
self.panes.get_mut(name) self.panes.get_mut(name)
} }
@ -155,6 +155,12 @@ impl std::fmt::Display for World {
} }
} }
impl Default for World {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

@ -157,9 +157,7 @@ impl Tile for Sender {
} }
} }
if context.state() == State::Active { if context.state() == State::Active || context.state() == State::Dormant && self.signals.is_empty() {
context.next_state();
} else if context.state() == State::Dormant && self.signals.len() == 0 {
context.next_state(); context.next_state();
} }
} }
@ -396,7 +394,7 @@ mod test {
.get_as::<Sender>((0, 0)) .get_as::<Sender>((0, 0))
.unwrap(); .unwrap();
assert!(sender.signals.len() == 0); assert!(sender.signals.is_empty());
assert_no_signal!(world.get_pane("main").unwrap(), (0, 0)); assert_no_signal!(world.get_pane("main").unwrap(), (0, 0));
assert_signal!(world.get_pane("main").unwrap(), (0, 2)); assert_signal!(world.get_pane("main").unwrap(), (0, 2));

@ -114,10 +114,8 @@ impl Tile for Resistor {
if let Some(signal) = context.take_signal() { if let Some(signal) = context.take_signal() {
self.signal = Some(signal); self.signal = Some(signal);
context.set_state(State::Active); context.set_state(State::Active);
} else { } else if context.state() != State::Idle {
if context.state() != State::Idle { context.next_state();
context.next_state();
}
} }
} }

Loading…
Cancel
Save