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}