Skip to main content

loam_console/
queue.rs

1/// Tokenized with `crate::parse_line`, so queue and console share one grammar.
2#[derive(Clone, Debug, PartialEq, Eq)]
3pub struct CommandLine {
4    pub name: String,
5    pub args: Vec<String>,
6}
7
8impl CommandLine {
9    pub fn parse(line: &str) -> Option<Self> {
10        let (name, args) = crate::parse_line(line)?;
11        Some(Self { name, args })
12    }
13
14    pub fn arg_refs(&self) -> Vec<&str> {
15        self.args.iter().map(String::as_str).collect()
16    }
17}
18
19#[derive(Debug, Default)]
20pub struct CommandQueue {
21    pending: Vec<CommandLine>,
22}
23
24impl CommandQueue {
25    pub const fn new() -> Self {
26        Self {
27            pending: Vec::new(),
28        }
29    }
30
31    pub fn submit(&mut self, command: CommandLine) {
32        self.pending.push(command);
33    }
34
35    pub fn submit_line(&mut self, line: &str) -> bool {
36        match CommandLine::parse(line) {
37            Some(command) => {
38                self.submit(command);
39                true
40            }
41            None => false,
42        }
43    }
44
45    pub fn drain(&mut self) -> std::vec::Drain<'_, CommandLine> {
46        self.pending.drain(..)
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn queues_preserve_order_without_sharing_state() {
56        let mut first = CommandQueue::new();
57        let mut second = CommandQueue::new();
58        first.submit_line("alpha 1");
59        second.submit_line("other");
60        first.submit_line("beta");
61        assert_eq!(
62            first
63                .drain()
64                .map(|command| command.name)
65                .collect::<Vec<_>>(),
66            ["alpha", "beta"]
67        );
68        assert_eq!(second.drain().next().unwrap().name, "other");
69        assert!(first.drain().next().is_none());
70    }
71
72    #[test]
73    fn submitted_arguments_keep_console_quoting() {
74        let mut queue = CommandQueue::new();
75        assert!(queue.submit_line(r#"load "5 cell" fast"#));
76        assert!(!queue.submit_line("  "));
77        let commands: Vec<_> = queue.drain().collect();
78        assert_eq!(commands.len(), 1);
79        assert_eq!(commands[0].name, "load");
80        assert_eq!(commands[0].args, ["5 cell", "fast"]);
81    }
82}