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}