sgf_parse/
game_tree.rs

1use std::fmt::Debug;
2
3use crate::{go, unknown_game, SgfNode, SgfParseError};
4
5/// The game recorded in a [`GameTree`].
6///
7/// Any [`GameTree`] retured by [`parse`](`crate::parse`) will have a game type which corresponds to
8/// the SGF `GM` property of the root node.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum GameType {
11    Go,
12    Unknown,
13}
14
15/// An SGF [GameTree](https://www.red-bean.com/sgf/sgf4.html#ebnf-def) value.
16///
17/// This type allows creating a collection of [`SgfNode`] values for different games. This is
18/// used in the return type of the [`parse`](`crate::parse()`) function. Users of the
19/// [`serialize`](`crate::serialize()`) function will need to build these.
20///
21/// For now, all non-Go games will parse as [`GameTree::Unknown`] which should also be used for any
22/// serialization of non-Go games.
23#[derive(Clone, Debug, PartialEq)]
24pub enum GameTree {
25    GoGame(SgfNode<go::Prop>),
26    Unknown(SgfNode<unknown_game::Prop>),
27}
28
29impl GameTree {
30    /// Consumes a Go game `GameTree` and returns the contained [`SgfNode`].
31    ///
32    /// This is a convenience method for go games.
33    ///
34    /// # Errors
35    /// Returns an error if the variant isn't a [`GameTree::GoGame`].
36    ///
37    /// # Examples
38    /// ```
39    /// use sgf_parse::parse;
40    ///
41    /// let gametree = parse("(;B[de]C[A comment])").unwrap().into_iter().next().unwrap();
42    /// let sgf_node = gametree.into_go_node().unwrap();
43    /// ```
44    pub fn into_go_node(self) -> Result<SgfNode<go::Prop>, SgfParseError> {
45        match self {
46            Self::GoGame(sgf_node) => Ok(sgf_node),
47            _ => Err(SgfParseError::UnexpectedGameType),
48        }
49    }
50
51    /// Returns the [`GameType`] for this [`GameTree`].
52    ///
53    /// # Examples
54    /// ```
55    /// use sgf_parse::{parse, GameType};
56    ///
57    /// let gametree = parse("(;GM[1]B[de]C[A comment])").unwrap().into_iter().next().unwrap();
58    /// assert_eq!(gametree.gametype(), GameType::Go);
59    /// ```
60    pub fn gametype(&self) -> GameType {
61        match self {
62            Self::GoGame(_) => GameType::Go,
63            Self::Unknown(_) => GameType::Unknown,
64        }
65    }
66}
67
68impl std::fmt::Display for GameTree {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        let node_text = match self {
71            Self::GoGame(sgf_node) => sgf_node.serialize(),
72            Self::Unknown(sgf_node) => sgf_node.serialize(),
73        };
74        std::fmt::Display::fmt(&node_text, f)
75    }
76}
77
78impl std::convert::From<SgfNode<go::Prop>> for GameTree {
79    fn from(sgf_node: SgfNode<go::Prop>) -> Self {
80        Self::GoGame(sgf_node)
81    }
82}
83
84impl std::convert::From<SgfNode<unknown_game::Prop>> for GameTree {
85    fn from(sgf_node: SgfNode<unknown_game::Prop>) -> Self {
86        Self::Unknown(sgf_node)
87    }
88}