Skip to main content

gorrosion_gtp/data/
simple_entity.rs

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	// TODO: Better error type
71	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				// TODO: map!($in, parse_gtp!(t), From::from)
117				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}