1use std::ops::DerefMut;
20use std::pin::Pin;
21
22#[derive(Debug)]
27#[non_exhaustive]
28pub struct Context {
29 is_first_line: bool,
30}
31
32impl Default for Context {
33 fn default() -> Self {
34 Self {
35 is_first_line: true,
36 }
37 }
38}
39
40impl Context {
41 #[inline]
43 #[must_use]
44 pub fn is_first_line(&self) -> bool {
45 self.is_first_line
46 }
47
48 #[inline]
53 pub fn set_is_first_line(&mut self, is_first_line: bool) {
54 self.is_first_line = is_first_line;
55 }
56}
57
58pub type Error = std::io::Error;
60
61pub type Result = std::result::Result<String, Error>;
63
64#[must_use = "Input instances should be used by a parser"]
70pub trait Input {
71 fn next_line(&mut self, context: &Context) -> impl Future<Output = Result>;
81}
82
83impl<T> Input for T
84where
85 T: DerefMut,
86 T::Target: Input,
87{
88 fn next_line(&mut self, context: &Context) -> impl Future<Output = Result> {
89 self.deref_mut().next_line(context)
90 }
91}
92
93pub trait InputObject {
102 fn next_line<'a>(
103 &'a mut self,
104 context: &'a Context,
105 ) -> Pin<Box<dyn Future<Output = Result> + 'a>>;
106}
107
108impl<T: Input> InputObject for T {
109 fn next_line<'a>(
110 &'a mut self,
111 context: &'a Context,
112 ) -> Pin<Box<dyn Future<Output = Result> + 'a>> {
113 Box::pin(Input::next_line(self, context))
114 }
115}
116
117pub struct Memory<'a> {
119 lines: std::str::SplitInclusive<'a, char>,
120}
121
122impl Memory<'_> {
123 pub fn new(code: &str) -> Memory<'_> {
125 let lines = code.split_inclusive('\n');
126 Memory { lines }
127 }
128}
129
130impl<'a> From<&'a str> for Memory<'a> {
131 fn from(code: &'a str) -> Memory<'a> {
132 Memory::new(code)
133 }
134}
135
136impl Input for Memory<'_> {
137 async fn next_line(&mut self, _context: &Context) -> Result {
138 Ok(self.lines.next().unwrap_or("").to_owned())
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use super::{Context, Input, Memory};
145 use futures_util::FutureExt;
146
147 #[test]
148 fn memory_empty_source() {
149 let mut input = Memory::new("");
150 let context = Context::default();
151
152 let line = input.next_line(&context).now_or_never().unwrap().unwrap();
153 assert_eq!(line, "");
154 }
155
156 #[test]
157 fn memory_one_line() {
158 let mut input = Memory::new("one\n");
159 let context = Context::default();
160
161 let line = input.next_line(&context).now_or_never().unwrap().unwrap();
162 assert_eq!(line, "one\n");
163
164 let line = input.next_line(&context).now_or_never().unwrap().unwrap();
165 assert_eq!(line, "");
166 }
167
168 #[test]
169 fn memory_three_lines() {
170 let mut input = Memory::new("one\ntwo\nthree");
171 let context = Context::default();
172
173 let line = input.next_line(&context).now_or_never().unwrap().unwrap();
174 assert_eq!(line, "one\n");
175
176 let line = input.next_line(&context).now_or_never().unwrap().unwrap();
177 assert_eq!(line, "two\n");
178
179 let line = input.next_line(&context).now_or_never().unwrap().unwrap();
180 assert_eq!(line, "three");
181
182 let line = input.next_line(&context).now_or_never().unwrap().unwrap();
183 assert_eq!(line, "");
184 }
185}