qemu_command_builder/args/
msg.rs1use crate::parsers::ARG_MSG;
2use std::str::FromStr;
3
4use crate::common::OnOff;
5use crate::parsers::DELIM_COMMA;
6use crate::qao;
7use crate::shell_string::ShellStringError;
8use crate::to_command::ToCommand;
9use bon::Builder;
10use proptest_derive::Arbitrary;
11
12const KEY_TIMESTAMP: &str = "timestamp=";
13const KEY_GUEST_NAME: &str = "guest-name=";
14
15#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Default, Builder, Arbitrary)]
16pub struct Msg {
17 timestamp: Option<OnOff>,
19 guest_name: Option<OnOff>,
21}
22
23impl ToCommand for Msg {
24 fn command(&self) -> String {
25 ARG_MSG.to_string()
26 }
27 fn has_args(&self) -> bool {
28 self.timestamp.is_some() || self.guest_name.is_some()
29 }
30 fn to_args(&self) -> Vec<String> {
31 let mut args = vec![];
32 qao!(&self.timestamp, args, KEY_TIMESTAMP);
33 qao!(&self.guest_name, args, KEY_GUEST_NAME);
34 vec![args.join(DELIM_COMMA)]
35 }
36}
37
38impl FromStr for Msg {
39 type Err = ShellStringError;
40
41 fn from_str(s: &str) -> Result<Self, Self::Err> {
42 let mut timestamp = None;
43 let mut guest_name = None;
44
45 for part in s.split(DELIM_COMMA).filter(|part| !part.is_empty()) {
46 match part {
47 "timestamp" => timestamp = Some(OnOff::On),
48 "guest-name" => guest_name = Some(OnOff::On),
49 _ => {
50 let (key, value) = part.split_once('=').ok_or_else(|| ShellStringError::new(format!("invalid -msg option: {part}")))?;
51 match key {
52 "timestamp" => timestamp = Some(value.parse::<OnOff>().map_err(|_| ShellStringError::new(format!("invalid timestamp value: {value}")))?),
53 "guest-name" => guest_name = Some(value.parse::<OnOff>().map_err(|_| ShellStringError::new(format!("invalid guest-name value: {value}")))?),
54 other => return Err(ShellStringError::new(format!("unsupported -msg option: {other}"))),
55 }
56 }
57 }
58 }
59
60 Ok(Msg { timestamp, guest_name })
61 }
62}