1#[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}