diff --git a/src/definitions.rs b/src/definitions.rs index 701b7c8..487ffcd 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -1,6 +1,7 @@ +use parser::{SliceParseError, TagParseError}; use serde::{Deserialize, Serialize}; -use self::parser::{FilePosition, ParseError, ParseQuery}; +use self::parser::{FilePosition, ParseError, SliceParse}; pub mod parser; @@ -18,8 +19,13 @@ pub struct Tag { } impl Tag { - fn parse_value(&self) -> Result { - T::parse(&self.values).map_err(|_| ParseError::ValueParseError(self.clone())) + fn parse_value(&self) -> Result { + T::parse(&self.values).map_err(|err| { + ParseError::TagParseError(match err { + SliceParseError::ParseError => TagParseError::ParseError(self.clone()), + SliceParseError::MissingValue => TagParseError::MissingValue(self.clone()), + }) + }) } } diff --git a/src/definitions/parser.rs b/src/definitions/parser.rs index b18c3c2..1b86d4e 100644 --- a/src/definitions/parser.rs +++ b/src/definitions/parser.rs @@ -2,13 +2,13 @@ use std::{borrow::BorrowMut, io::Read, str::FromStr}; use crate::definitions::{CreatureDef, SiteDef, Tag, TopLevelTag}; -pub trait ParseQuery: Sized { - fn parse(values: &Vec) -> Result; +pub trait SliceParse: Sized { + fn parse(values: &[String]) -> Result; } trait Parseable: Sized + FromStr { - fn parse(string: &str) -> Result { - string.parse().map_err(|_| ()) + fn parse(string: &str) -> Option { + string.parse().ok() } } @@ -25,22 +25,20 @@ impl Parseable for bool {} macro_rules! parse_query_impl { ($t:ident) => { - impl<$t: Parseable> ParseQuery for $t { - fn parse(values: &Vec) -> Result { + impl<$t: Parseable> SliceParse for $t { + fn parse(values: &[String]) -> Result { let mut iter = values.iter(); - Ok( - $t::parse(iter.next().ok_or(())?)? - ) + $t::parse(iter.next().ok_or(SliceParseError::MissingValue)?).ok_or(SliceParseError::ParseError) } } }; ($x:ident, $($t:ident),+) => { - impl<$x: Parseable, $($t: Parseable),+> ParseQuery for ($x, $($t),+) { - fn parse(values: &Vec) -> Result { + impl<$x: Parseable, $($t: Parseable),+> SliceParse for ($x, $($t),+) { + fn parse(values: &[String]) -> Result { let mut iter = values.iter(); Ok(( - $x::parse(iter.next().ok_or(())?)?, - $($t::parse(iter.next().ok_or(())?)?,)+ + $x::parse(iter.next().ok_or(SliceParseError::MissingValue)?).ok_or(SliceParseError::ParseError)?, + $($t::parse(iter.next().ok_or(SliceParseError::MissingValue)?).ok_or(SliceParseError::ParseError)?,)+ )) } } @@ -68,11 +66,22 @@ impl Default for FilePosition { pub enum ParseError { LexerError(LexerError), SyntaxError(String), - ValueParseError(Tag), + TagParseError(TagParseError), NoDefinitionsError, UnexpectedError, } +pub enum SliceParseError { + MissingValue, + ParseError, +} + +#[derive(Debug)] +pub enum TagParseError { + MissingValue(Tag), + ParseError(Tag), +} + #[derive(Debug)] pub enum LexerError { Io(std::io::Error), @@ -138,9 +147,7 @@ impl DefinitionParser { let mut tags = vec![]; let mut tag_builder: Option = None; let mut buffer = String::new(); - source - .read_to_string(&mut buffer) - .map_err(|err| LexerError::Io(err))?; + source.read_to_string(&mut buffer).map_err(LexerError::Io)?; let mut file_position = FilePosition::default(); for c in buffer.chars() { if c == '\n' { diff --git a/src/main.rs b/src/main.rs index 33c5563..4b02d42 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,38 +6,32 @@ use sim::{Site, World}; pub mod definitions; pub mod sim; -const SAVE_FILE: &'static str = "world.bin"; +const SAVE_FILE: &str = "world.bin"; fn main() { let mut parse_error_files = vec![]; let mut site_definitions = HashMap::new(); let mut creature_definitions = HashMap::new(); - for entry in std::fs::read_dir(resources_path()).unwrap() { - match entry { - Ok(entry) => { - if entry.file_name().to_string_lossy().ends_with(".def") { - let source = BufReader::new(std::fs::File::open(entry.path()).unwrap()); - match DefinitionParser::parse(source) { - Ok(defs) => { - for def in defs.0 { - if let Some(prev) = site_definitions.insert(def.id.clone(), def) { - eprintln!("Duplicate site definition '{}'", prev.id); - } - } - for def in defs.1 { - if let Some(prev) = creature_definitions.insert(def.id.clone(), def) - { - eprintln!("Duplicate site definition '{}'", prev.id); - } - } + for entry in std::fs::read_dir(resources_path()).unwrap().flatten() { + if entry.file_name().to_string_lossy().ends_with(".def") { + let source = BufReader::new(std::fs::File::open(entry.path()).unwrap()); + match DefinitionParser::parse(source) { + Ok(defs) => { + for def in defs.0 { + if let Some(prev) = site_definitions.insert(def.id.clone(), def) { + eprintln!("Duplicate site definition '{}'", prev.id); } - Err(err) => { - parse_error_files.push((err, entry.path())); + } + for def in defs.1 { + if let Some(prev) = creature_definitions.insert(def.id.clone(), def) { + eprintln!("Duplicate site definition '{}'", prev.id); } } } + Err(err) => { + parse_error_files.push((err, entry.path())); + } } - _ => (), } } @@ -53,7 +47,7 @@ fn main() { Ok(data) => bincode::deserialize(&data).unwrap(), Err(_) => { let mut world = World::default(); - let mut site = Site::from_def(&site_def); + let mut site = Site::from_def(site_def); site.populate_randomly(&creature_definitions.values().collect::>()); world.sites.push(site); std::fs::write("world.bin", bincode::serialize(&world).unwrap()).unwrap(); @@ -68,7 +62,7 @@ fn main() { let mut input = String::new(); loop { std::io::stdin().read_line(&mut input).unwrap(); - if vec!["q", "quit", "exit"] + if ["q", "quit", "exit"] .iter() .any(|quit_cmd| input.trim() == *quit_cmd) { diff --git a/src/sim.rs b/src/sim.rs index b2bf6f1..844262d 100644 --- a/src/sim.rs +++ b/src/sim.rs @@ -160,13 +160,13 @@ impl Display for Site { for creature in area.population.iter() { write!(f, "\n\t\t{}", creature)?; } - if area.population.len() > 0 { + if !area.population.is_empty() { write!(f, "\n\t")?; } write!(f, "]")?; } if !self.areas.is_empty() { - write!(f, "\n")?; + writeln!(f)?; } write!(f, "]") } @@ -383,12 +383,12 @@ pub fn resolve_combat(combatants: &[Creature], max_rounds: u16) -> Option Option = participants.iter().map(|(uuid, _)| *uuid).collect(); + let mut order: Vec = participants.keys().copied().collect(); fastrand::shuffle(&mut order); let mut kills: Vec<_> = vec![]; let mut attacks: Vec<_> = vec![];