qemu_command_builder/args/
network_compat.rs1use crate::parsers::{ARG_NET, ARG_NIC, DELIM_COMMA};
2use crate::to_command::ToCommand;
3use bon::Builder;
4use proptest_derive::Arbitrary;
5use std::str::FromStr;
6
7#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Arbitrary)]
9pub struct NetworkProperty {
10 pub key: String,
11 pub value: Option<String>,
12}
13
14#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder, Arbitrary)]
16pub struct Nic {
17 backend: String,
18 #[builder(default)]
19 properties: Vec<NetworkProperty>,
20}
21
22#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder, Arbitrary)]
24pub struct LegacyNet {
25 kind: String,
26 #[builder(default)]
27 properties: Vec<NetworkProperty>,
28}
29
30macro_rules! impl_network_option {
31 ($type:ty, $field:ident, $arg:expr) => {
32 impl ToCommand for $type {
33 fn command(&self) -> String {
34 $arg.to_string()
35 }
36
37 fn to_args(&self) -> Vec<String> {
38 let mut parts = vec![self.$field.clone()];
39 for property in &self.properties {
40 parts.push(match &property.value {
41 Some(value) => format!("{}={}", property.key, value),
42 None => property.key.clone(),
43 });
44 }
45 vec![parts.join(DELIM_COMMA)]
46 }
47 }
48
49 impl FromStr for $type {
50 type Err = String;
51
52 fn from_str(value: &str) -> Result<Self, Self::Err> {
53 let mut parts = value.split(DELIM_COMMA);
54 let first = parts.next().filter(|part| !part.is_empty()).ok_or_else(|| format!("empty {} argument", $arg))?;
55 let properties = parts
56 .map(|part| match part.split_once('=') {
57 Some((key, value)) if !key.is_empty() => Ok(NetworkProperty {
58 key: key.to_string(),
59 value: Some(value.to_string()),
60 }),
61 None if !part.is_empty() => Ok(NetworkProperty { key: part.to_string(), value: None }),
62 _ => Err(format!("invalid {} property: {part}", $arg)),
63 })
64 .collect::<Result<Vec<_>, _>>()?;
65 Ok(Self {
66 $field: first.to_string(),
67 properties,
68 })
69 }
70 }
71 };
72}
73
74impl_network_option!(Nic, backend, ARG_NIC);
75impl_network_option!(LegacyNet, kind, ARG_NET);