sgf_parse/props/
sgf_prop.rs

1use std::fmt::{Debug, Display};
2
3use super::{PropertyType, ToSgf};
4use crate::InvalidNodeError;
5
6/// A type that can be used for properties in an [`SgfNode`](`crate::SgfNode`).
7///
8/// This trait is sealed and cannot be implemented for types outside of `sgf_parse`.
9pub trait SgfProp: Debug + Display + Sized + Clone + Eq + private::Sealed {
10    type Point: Debug + Clone + PartialEq + Eq + std::hash::Hash + ToSgf;
11    type Stone: Debug + Clone + PartialEq + Eq + std::hash::Hash + ToSgf;
12    type Move: Debug + Clone + PartialEq + Eq + ToSgf;
13
14    /// Returns a new property parsed from the provided identifier and values
15    ///
16    /// # Examples
17    /// ```
18    /// use sgf_parse::SgfProp;
19    /// use sgf_parse::go::Prop;
20    ///
21    /// // Prop::B(Point{ x: 2, y: 3 }
22    /// let prop = Prop::new("B".to_string(), vec!["cd".to_string()]);
23    /// // Prop::AB(vec![Point{ x: 2, y: 3 }, Point { x: 3, y: 3 }])
24    /// let prop = Prop::new("AB".to_string(), vec!["cd".to_string(), "dd".to_string()]);
25    /// // Prop::Unknown("FOO", vec!["Text"])
26    /// let prop = Prop::new("FOO".to_string(), vec!["Text".to_string()]);
27    /// ```
28    fn new(identifier: String, values: Vec<String>) -> Self;
29
30    /// Returns a the identifier associated with the [`SgfProp`].
31    ///
32    /// # Examples
33    /// ```
34    /// use sgf_parse::SgfProp;
35    /// use sgf_parse::go::Prop;
36    ///
37    /// let prop = Prop::new("W".to_string(), vec!["de".to_string()]);
38    /// assert_eq!(prop.identifier(), "W");
39    /// let prop = Prop::new("FOO".to_string(), vec!["de".to_string()]);
40    /// assert_eq!(prop.identifier(), "FOO");
41    /// ```
42    fn identifier(&self) -> String;
43
44    /// Returns the [`PropertyType`] associated with the property.
45    ///
46    /// # Examples
47    /// ```
48    /// use sgf_parse::{PropertyType, SgfProp};
49    /// use sgf_parse::go::Prop;
50    ///
51    /// let prop = Prop::new("W".to_string(), vec!["de".to_string()]);
52    /// assert_eq!(prop.property_type(), Some(PropertyType::Move));
53    /// let prop = Prop::new("FOO".to_string(), vec!["de".to_string()]);
54    /// assert_eq!(prop.property_type(), None);
55    /// ```
56    fn property_type(&self) -> Option<PropertyType>;
57
58    /// Validates a set of properties.
59    ///
60    /// # Errors
61    /// Returns an error if the collection of properties isn't valid.
62    fn validate_properties(properties: &[Self], is_root: bool) -> Result<(), InvalidNodeError>;
63}
64
65// Prevent users from implementing the SgfProp trait.
66// Because `parse` has to return an enum, with the current design, implementing
67// a new game outside the crate is a mess.
68//
69// If you'd like to implement this trait for a new game, PR's are very welcome!
70mod private {
71    pub trait Sealed {}
72    impl Sealed for crate::go::Prop {}
73    impl Sealed for crate::unknown_game::Prop {}
74    impl<T> Sealed for &T where T: ?Sized + Sealed {}
75}