qemu_command_builder/args/
fw_cfg.rs1use bon::Builder;
2use proptest_derive::Arbitrary;
3use std::path::PathBuf;
4use std::str::FromStr;
5
6use crate::parsers::{ARG_FW_CFG, DELIM_COMMA};
7use crate::to_command::ToCommand;
8
9#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Arbitrary)]
10pub enum StringOrPathBuf {
11 String(String),
12 PathBuf(PathBuf),
13}
14
15#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Default, Builder, Arbitrary)]
16pub struct FwCfg {
17 name: Option<String>,
19 data: Option<StringOrPathBuf>,
21}
22
23impl ToCommand for FwCfg {
24 fn command(&self) -> String {
25 ARG_FW_CFG.to_string()
26 }
27 fn to_args(&self) -> Vec<String> {
28 let mut args = vec![];
29 if let Some(name) = &self.name {
30 args.push(format!("name={}", name));
31 }
32 if let Some(data) = &self.data {
33 match &data {
34 StringOrPathBuf::String(string) => {
35 args.push(format!("string={}", string));
36 }
37 StringOrPathBuf::PathBuf(path) => {
38 args.push(format!("file={}", path.display()));
39 }
40 }
41 }
42
43 vec![args.join(DELIM_COMMA)]
44 }
45}
46
47impl FromStr for FwCfg {
48 type Err = String;
49
50 fn from_str(s: &str) -> Result<Self, Self::Err> {
51 let mut parts = s.split(DELIM_COMMA);
52 let first = parts.next().ok_or_else(|| "empty -fw_cfg argument".to_string())?;
53
54 let mut name = None;
55 let mut data = None;
56
57 if let Some(value) = first.strip_prefix("name=") {
58 name = Some(value.to_string());
59 } else if !first.contains('=') {
60 name = Some(first.to_string());
61 } else {
62 let (key, value) = first.split_once('=').ok_or_else(|| format!("invalid -fw_cfg option: {first}"))?;
63 match key {
64 "file" => data = Some(StringOrPathBuf::PathBuf(PathBuf::from(value))),
65 "string" => data = Some(StringOrPathBuf::String(value.to_string())),
66 other => return Err(format!("unsupported -fw_cfg option: {other}")),
67 }
68 }
69
70 for part in parts {
71 let (key, value) = part.split_once('=').ok_or_else(|| format!("invalid -fw_cfg option: {part}"))?;
72 match key {
73 "name" => name = Some(value.to_string()),
74 "file" => data = Some(StringOrPathBuf::PathBuf(PathBuf::from(value))),
75 "string" => data = Some(StringOrPathBuf::String(value.to_string())),
76 other => return Err(format!("unsupported -fw_cfg option: {other}")),
77 }
78 }
79
80 Ok(Self { name, data })
81 }
82}