1use super::super::messages::WriteGTP;
2use super::*;
3use nom::IResult;
4use std::io;
5use std::str::FromStr;
6
7#[derive(Clone, Debug, PartialEq)]
8pub enum Value {
9 Int(int::Value),
10 Float(float::Value),
11 String(string::Value),
12 Vertex(vertex::Value),
13 Color(color::Value),
14 Motion(motion::Value),
15 Boolean(boolean::Value),
16}
17
18macro_rules! impl_froms {
19 ( $(($t:ident, $m:ident)), * ) => {
20 $(impl From<$m::Value> for Value {
21 fn from(v: $m::Value) -> Self {
22 Value::$t(v)
23 }
24 })*
25
26 $(impl From<$m::Type> for Type {
27 fn from(_t: $m::Type) -> Self {
28 Type::$t
29 }
30 })*
31 }
32}
33
34impl_froms!(
35 (Int, int),
36 (Float, float),
37 (String, string),
38 (Vertex, vertex),
39 (Color, color),
40 (Motion, motion),
41 (Boolean, boolean)
42);
43
44impl WriteGTP for Value {
45 fn write_gtp(&self, f: &mut impl io::Write) -> io::Result<()> {
46 match self {
47 Value::Int(v) => v.write_gtp(f),
48 Value::Float(v) => v.write_gtp(f),
49 Value::String(v) => v.write_gtp(f),
50 Value::Vertex(v) => v.write_gtp(f),
51 Value::Color(v) => v.write_gtp(f),
52 Value::Motion(v) => v.write_gtp(f),
53 Value::Boolean(v) => v.write_gtp(f),
54 }
55 }
56}
57
58#[derive(Clone, Debug, PartialEq, Eq)]
59pub enum Type {
60 Int,
61 Float,
62 String,
63 Vertex,
64 Color,
65 Motion,
66 Boolean,
67}
68
69impl FromStr for Type {
70 type Err = ();
72
73 fn from_str(s: &str) -> Result<Type, Self::Err> {
74 let s = nom::types::CompleteStr(s);
75 let result = alt!(s,
76 map!(parse_to!(int::Type), From::from) |
77 map!(parse_to!(float::Type), From::from) |
78 map!(parse_to!(string::Type), From::from) |
79 map!(parse_to!(vertex::Type), From::from) |
80 map!(parse_to!(color::Type), From::from) |
81 map!(parse_to!(motion::Type), From::from) |
82 map!(parse_to!(boolean::Type), From::from)
83 );
84 if let Ok((rem, res)) = result {
85 if rem.is_empty() {
86 Err(())
87 } else {
88 Ok(res)
89 }
90 } else {
91 Err(())
92 }
93 }
94}
95
96impl HasType<Type> for Value {
97 fn has_type(&self, t: &Type) -> bool {
98 match (self, t) {
99 (Value::Int(_), Type::Int) => true,
100 (Value::Float(_), Type::Float) => true,
101 (Value::String(_), Type::String) => true,
102 (Value::Vertex(_), Type::Vertex) => true,
103 (Value::Color(_), Type::Color) => true,
104 (Value::Motion(_), Type::Motion) => true,
105 (Value::Boolean(_), Type::Boolean) => true,
106 _ => false,
107 }
108 }
109}
110
111macro_rules! parse {
112 ( $in:expr, $e:expr; $( ($t:ident, $m:ident) ), * ) => {
113 match $e {
114 $( Type::$t => {
115 let t = &$m::Type::default();
116 let result = $m::Value::parse($in, t);
118 result.map(|(i, v)| (i, From::from(v)))
119 } )*
120 }
121 }
122}
123
124impl Data for Value {
125 type Type = Type;
126
127 fn parse<'a, I: Input<'a>>(i: I, t: &Self::Type) -> IResult<I, Self> {
128 #[rustfmt::skip]
129 parse!(i, t;
130 (Int, int),
131 (Float, float),
132 (String, string),
133 (Vertex, vertex),
134 (Color, color),
135 (Motion, motion),
136 (Boolean, boolean)
137 )
138 }
139}