yash_env/input/
memory.rs

1// This file is part of yash, an extended POSIX shell.
2// Copyright (C) 2025 WATANABE Yuki
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17//! `Memory` definition
18
19use super::{Context, Input, Result};
20
21/// Input function that reads from a string in memory
22pub struct Memory<'a> {
23    lines: std::str::SplitInclusive<'a, char>,
24}
25
26impl Memory<'_> {
27    /// Creates a new `Memory` that reads the given string.
28    pub fn new(code: &str) -> Memory<'_> {
29        let lines = code.split_inclusive('\n');
30        Memory { lines }
31    }
32}
33
34impl<'a> From<&'a str> for Memory<'a> {
35    fn from(code: &'a str) -> Memory<'a> {
36        Memory::new(code)
37    }
38}
39
40impl Input for Memory<'_> {
41    async fn next_line(&mut self, _context: &Context) -> Result {
42        Ok(self.lines.next().unwrap_or("").to_owned())
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::{Context, Input, Memory};
49    use futures_util::FutureExt as _;
50
51    #[test]
52    fn memory_empty_source() {
53        let mut input = Memory::new("");
54        let context = Context::default();
55
56        let line = input.next_line(&context).now_or_never().unwrap().unwrap();
57        assert_eq!(line, "");
58    }
59
60    #[test]
61    fn memory_one_line() {
62        let mut input = Memory::new("one\n");
63        let context = Context::default();
64
65        let line = input.next_line(&context).now_or_never().unwrap().unwrap();
66        assert_eq!(line, "one\n");
67
68        let line = input.next_line(&context).now_or_never().unwrap().unwrap();
69        assert_eq!(line, "");
70    }
71
72    #[test]
73    fn memory_three_lines() {
74        let mut input = Memory::new("one\ntwo\nthree");
75        let context = Context::default();
76
77        let line = input.next_line(&context).now_or_never().unwrap().unwrap();
78        assert_eq!(line, "one\n");
79
80        let line = input.next_line(&context).now_or_never().unwrap().unwrap();
81        assert_eq!(line, "two\n");
82
83        let line = input.next_line(&context).now_or_never().unwrap().unwrap();
84        assert_eq!(line, "three");
85
86        let line = input.next_line(&context).now_or_never().unwrap().unwrap();
87        assert_eq!(line, "");
88    }
89}