diff --git a/sgf/src/bin/read_sgf.rs b/sgf/src/bin/read_sgf.rs index af3c5e9..66438e6 100644 --- a/sgf/src/bin/read_sgf.rs +++ b/sgf/src/bin/read_sgf.rs @@ -11,9 +11,5 @@ fn main() { println!("{:?}", file); let games = parse_sgf_file(&file).unwrap(); - for sgf in games { - if let Ok(sgf) = sgf { - println!("{:?}", sgf.white_player); - } - } + games.into_iter().flatten().for_each(|sgf| println!("{:?}", sgf.white_player)); } diff --git a/sgf/src/game.rs b/sgf/src/game.rs index 1343565..d11b677 100644 --- a/sgf/src/game.rs +++ b/sgf/src/game.rs @@ -118,7 +118,7 @@ impl GameRecord { /// Generate a list of moves which constitute the main line of the game. This is the game as it /// was actually played out, and by convention consists of the first node in each list of /// children. - pub fn mainline<'a>(&'a self) -> Vec<&'a GameNode> { + pub fn mainline(&self) -> Vec<&GameNode> { let mut moves: Vec<&GameNode> = vec![]; let mut next = self.children.get(0); @@ -150,7 +150,7 @@ impl Node for GameRecord { self.children.iter().collect::>() } - fn add_child<'a>(&'a mut self, node: GameNode) -> &'a mut GameNode { + fn add_child(&mut self, node: GameNode) -> &mut GameNode { self.children.push(node); self.children.last_mut().unwrap() } @@ -227,7 +227,7 @@ impl TryFrom<&parser::Tree> for GameRecord { parser::Property::Round(v) => s.round = Some(v.clone()), parser::Property::Ruleset(v) => s.rules = Some(v.clone()), parser::Property::Source(v) => s.source = Some(v.clone()), - parser::Property::TimeLimit(v) => s.time_limit = Some(v.clone()), + parser::Property::TimeLimit(v) => s.time_limit = Some(*v), parser::Property::Overtime(v) => s.overtime = Some(v.clone()), // parser::Property::Data(v) => s.transcriber = Some(v.clone()), _ => {} @@ -238,7 +238,7 @@ impl TryFrom<&parser::Tree> for GameRecord { .root .next .iter() - .map(|node| GameNode::try_from(node)) + .map(GameNode::try_from) .collect::, GameNodeError>>() .map_err(GameError::InvalidGameNode)?; @@ -257,18 +257,17 @@ pub trait Node { fn nodes<'a>(&'a self) -> Vec<&'a GameNode> { self.children() .iter() - .map(|node| { + .flat_map(|node| { let mut children = node.nodes(); let mut v = vec![*node]; v.append(&mut children); v }) - .flatten() .collect::>() } - fn children<'a>(&'a self) -> Vec<&'a GameNode>; - fn add_child<'a>(&'a mut self, node: GameNode) -> &'a mut GameNode; + fn children(&self) -> Vec<&GameNode>; + fn add_child(&mut self, node: GameNode) -> &mut GameNode; } impl GameNode { @@ -281,21 +280,21 @@ impl GameNode { } impl Node for GameNode { - fn children<'a>(&'a self) -> Vec<&'a GameNode> { + fn children(&self) -> Vec<&GameNode> { match self { GameNode::MoveNode(node) => node.children(), GameNode::SetupNode(node) => node.children(), } } - fn nodes<'a>(&'a self) -> Vec<&'a GameNode> { + fn nodes(&self) -> Vec<&GameNode> { match self { GameNode::MoveNode(node) => node.nodes(), GameNode::SetupNode(node) => node.nodes(), } } - fn add_child<'a>(&'a mut self, new_node: GameNode) -> &'a mut GameNode { + fn add_child(&mut self, new_node: GameNode) -> &mut GameNode { match self { GameNode::MoveNode(node) => node.add_child(new_node), GameNode::SetupNode(node) => node.add_child(new_node), @@ -326,7 +325,7 @@ impl TryFrom<&parser::Node> for GameNode { let children = n .next .iter() - .map(|n| GameNode::try_from(n)) + .map(GameNode::try_from) .collect::, Self::Error>>()?; let node = match (move_node, setup_node) { @@ -389,7 +388,7 @@ impl Node for MoveNode { self.children.iter().collect::>() } - fn add_child<'a>(&'a mut self, node: GameNode) -> &'a mut GameNode { + fn add_child(&mut self, node: GameNode) -> &mut GameNode { self.children.push(node); self.children.last_mut().unwrap() } @@ -417,7 +416,7 @@ impl TryFrom<&parser::Node> for MoveNode { if s.time_left.is_some() { return Err(Self::Error::ConflictingProperty); } - s.time_left = Some(duration.clone()); + s.time_left = Some(*duration); } parser::Property::Comment(cmt) => { if s.comments.is_some() { @@ -492,7 +491,7 @@ impl Node for SetupNode { } #[allow(dead_code)] - fn add_child<'a>(&'a mut self, _node: GameNode) -> &'a mut GameNode { + fn add_child(&mut self, _node: GameNode) -> &mut GameNode { unimplemented!() } } @@ -509,7 +508,7 @@ impl TryFrom<&parser::Node> for SetupNode { } #[allow(dead_code)] -pub fn path_to_node<'a>(node: &'a GameNode, id: Uuid) -> Vec<&'a GameNode> { +pub fn path_to_node(node: &GameNode, id: Uuid) -> Vec<&GameNode> { if node.id() == id { return vec![node]; } diff --git a/sgf/src/lib.rs b/sgf/src/lib.rs index 5f23da1..6849499 100644 --- a/sgf/src/lib.rs +++ b/sgf/src/lib.rs @@ -70,7 +70,7 @@ impl From> for ParseError { /// The inner Result is for errors in each individual game in the file. All of the other games can /// still be kept as valid. pub fn parse_sgf(input: &str) -> Result>, Error> { - let (_, games) = parse_collection::>(&input)?; + let (_, games) = parse_collection::>(input)?; let games = games .into_iter() .map(|game| GameRecord::try_from(&game)) diff --git a/sgf/src/parser.rs b/sgf/src/parser.rs index 8de8e28..d395dd1 100644 --- a/sgf/src/parser.rs +++ b/sgf/src/parser.rs @@ -10,7 +10,7 @@ use nom::{ IResult, Parser, }; use serde::{Deserialize, Serialize}; -use std::{num::ParseIntError, time::Duration}; +use std::{fmt::Write, num::ParseIntError, time::Duration}; impl From for Error { fn from(_: ParseSizeError) -> Self { @@ -303,9 +303,9 @@ impl Move { if s.len() == 2 { let mut parts = s.chars(); let row_char = parts.next().unwrap(); - let row = row_char as u8 - 'a' as u8; + let row = row_char as u8 - b'a'; let column_char = parts.next().unwrap(); - let column = column_char as u8 - 'a' as u8; + let column = column_char as u8 - b'a'; Some((row, column)) } else { unimplemented!("moves must contain exactly two characters"); @@ -527,22 +527,20 @@ impl ToString for Property { Property::WhiteRank(value) => format!("WR[{}]", value), Property::WhiteTeam(value) => format!("WT[{}]", value), Property::Territory(Color::White, positions) => { - format!( - "TW{}", - positions - .iter() - .map(|Position(p)| format!("[{}]", p)) - .collect::() - ) + positions + .iter() + .fold("TW".to_owned(), |mut output, Position(p)| { + let _ = write!(output, "{}", p); + output + }) } Property::Territory(Color::Black, positions) => { - format!( - "TB{}", - positions - .iter() - .map(|Position(p)| format!("[{}]", p)) - .collect::() - ) + positions + .iter() + .fold("TB".to_owned(), |mut output, Position(p)| { + let _ = write!(output, "{}", p); + output + }) } Property::Unknown(UnknownProperty { ident, value }) => { format!("{}[{}]", ident, value) @@ -965,7 +963,7 @@ fn parse_win_score<'a, E: nom::error::ParseError<&'a str>>() -> impl Parser<&'a mod test { use super::*; - const EXAMPLE: &'static str = "(;FF[4]C[root](;C[a];C[b](;C[c]) + const EXAMPLE: &str = "(;FF[4]C[root](;C[a];C[b](;C[c]) (;C[d];C[e])) (;C[f](;C[g];C[h];C[i]) (;C[j])))";