Skip to main content

gorrosion_gtp/input/
nom.rs

1//! Implement the traits defined by nom
2//! so that we can use nom to write our parsers.
3//!
4//! These are simply wrappers
5//! (but not all are simple wrappers)
6//! around the interface exposed by the sister modules engine and controller.
7//! All GTP specific (pre-)processing happens in these modules.
8
9use super::{controller, engine, for_t, Byte};
10use data::int;
11use nom::*;
12use std::convert::TryFrom;
13
14/// Implement all the nom interfaces required by input::Input<'a>
15/// for a generic type name.
16macro_rules! impl_nom {
17	( $T:ident, $I:ident, $E:ident ) => {
18		impl<'a> AtEof for $T<'a> {
19			/// While it might be possible in some settings
20			/// to determine that the connection has closed
21			/// and no further data may arrive,
22			/// it is quite irrelevant
23			/// considering the particular syntax of GTP.
24			/// The only use case would be determining malformed input
25			/// which ends without proper termination
26			/// but this is currently beyond the scope
27			/// of this implementation.
28			fn at_eof(&self) -> bool {
29				false
30			}
31		}
32
33		impl<'a> InputLength for $T<'a> {
34			// TODO: Is this the correct behaviour?
35			//       The rest of the nom interface suggests
36			//       that by “length of the input“
37			//       the bytewise length is meant
38			//       instead of the number of elements
39			//       returned by the iterator
40			//       but it is not made explicit in the documentation.
41			fn input_len(&self) -> usize {
42				self.bytes().len()
43			}
44		}
45
46		impl<'a> InputTake for $T<'a> {
47			fn take(&self, count: usize) -> Self {
48				let bytes = &self.bytes()[0..count];
49				$T::from(bytes)
50			}
51
52			// FIXME: This behaviour is incorrect for engine::Input,
53			//        as it fails to respect comments and empty lines.
54			fn take_split(&self, count: usize) -> (Self, Self) {
55				let (prefix, suffix) =
56					self.bytes().split_at(count);
57				let prefix = $T::from(prefix);
58				let suffix = $T::from(suffix);
59				(suffix, prefix)
60			}
61		}
62
63		impl<'a, R> Slice<R> for $T<'a>
64		where
65			&'a [Byte]: Slice<R>,
66		{
67			// TODO: Is this the correct behaviour?
68			//       The rest of the nom interface suggests
69			//       that by “length of the input“
70			//       the bytewise length is meant
71			//       instead of the number of elements
72			//       returned by the iterator
73			//       but it is not made explicit in the documentation.
74			// FIXME: This behaviour is incorrect for engine::Input,
75			//        as it fails to respect comments and empty lines.
76			fn slice(&self, range: R) -> Self {
77				let bytes = self.bytes().slice(range);
78				$T::from(bytes)
79			}
80		}
81
82		impl<'a> Offset for $T<'a> {
83			fn offset(&self, second: &Self) -> usize {
84				self.bytes().offset(second.bytes())
85			}
86		}
87
88		impl<'a, R> ParseTo<R> for $T<'a>
89		where
90			for<'b> &'b [Byte]: ParseTo<R>,
91		{
92			fn parse_to(&self) -> Option<R> {
93				let str: Vec<Byte> =
94					self.iter_elements().collect();
95				str.as_bytes().parse_to()
96			}
97		}
98
99		impl<'a> ParseTo<int::Value> for $T<'a> {
100			fn parse_to(&self) -> Option<int::Value> {
101				let i: u32 = self.parse_to()?;
102				int::Value::try_from(i).ok()
103			}
104		}
105
106		impl<'a> for_t::Slice for $T<'a> {}
107		impl<'a> for_t::ParseTo for $T<'a> {}
108
109		impl<'a, S> Compare<S> for $T<'a>
110		where
111			&'a [Byte]: Compare<S>,
112		{
113			// FIXME: Needs to iterate over iter_elements.
114			fn compare(&self, t: S) -> CompareResult {
115				self.bytes().compare(t)
116			}
117
118			// FIXME: Needs to iterate over iter_elements.
119			fn compare_no_case(&self, t: S) -> CompareResult {
120				self.bytes().compare_no_case(t)
121			}
122		}
123
124		impl<'a> InputIter for $T<'a> {
125			type Item = Byte;
126			type RawItem = Byte;
127			type Iter = $E<'a>;
128			type IterElem = $I<'a>;
129
130			fn iter_indices(&self) -> Self::Iter {
131				$E::new(self)
132			}
133
134			fn iter_elements(&self) -> Self::IterElem {
135				$I::new(self)
136			}
137
138			fn position<P>(&self, predicate: P) -> Option<usize>
139			where
140				P: Fn(Self::RawItem) -> bool,
141			{
142				let mut iter = self.iter_indices();
143				loop {
144					if let Some((index, elem)) = iter.next()
145					{
146						if predicate(elem) {
147							continue;
148						} else {
149							break Some(index);
150						}
151					} else {
152						break None;
153					}
154				}
155			}
156
157			fn slice_index(&self, count: usize) -> Option<usize> {
158				let mut iter = self.iter_indices();
159				let (res, _) = iter.nth(count)?;
160				Some(res)
161			}
162		}
163
164		/// This allows us to use a default implementation
165		/// for `InputTakeAtPosition`.
166		impl<'a> UnspecializedInput for $T<'a> {}
167	};
168}
169
170type ControllerInput<'a> = controller::Input<'a>;
171type ControllerIterator<'a> = controller::Iterator<'a>;
172type ControllerEnumerator<'a> = controller::Enumerator<'a>;
173type EngineInput<'a> = engine::Input<'a>;
174type EngineIterator<'a> = engine::Iterator<'a>;
175type EngineEnumerator<'a> = engine::Enumerator<'a>;
176impl_nom!(ControllerInput, ControllerIterator, ControllerEnumerator);
177impl_nom!(EngineInput, EngineIterator, EngineEnumerator);