qemu_command_builder/args/
smp.rs1use crate::parsers::ARG_SMP;
2use crate::parsers::DELIM_COMMA;
3use crate::shell_string::ShellStringError;
4use crate::to_command::ToCommand;
5use crate::{pco, qao};
6use bon::Builder;
7use proptest_derive::Arbitrary;
8use std::str::FromStr;
9use winnow::ascii::{dec_uint, digit1};
10use winnow::combinator::opt;
11use winnow::token::literal;
12use winnow::{ModalResult, Parser};
13
14const KEY_MAXCPUS: &str = "maxcpus=";
15const KEY_DRAWERS: &str = "drawers=";
16const KEY_BOOKS: &str = "books=";
17const KEY_SOCKETS: &str = "sockets=";
18const KEY_DIES: &str = "dies=";
19const KEY_CLUSTERS: &str = "clusters=";
20const KEY_MODULES: &str = "modules=";
21const KEY_CORES: &str = "cores=";
22const KEY_THREADS: &str = "threads=";
23
24#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder, Arbitrary)]
57pub struct SMP {
58 cpus: u64,
60 maxcpus: Option<usize>,
62 drawers: Option<usize>,
64 books: Option<usize>,
66 sockets: Option<usize>,
68 dies: Option<usize>,
70 clusters: Option<usize>,
72 modules: Option<usize>,
74 cores: Option<usize>,
76 threads: Option<usize>,
78}
79
80impl Default for SMP {
81 fn default() -> Self {
82 SMP::new(1)
83 }
84}
85
86impl SMP {
87 pub fn new(cpus: u64) -> Self {
88 Self {
89 cpus,
90 maxcpus: None,
91 drawers: None,
92 books: None,
93 sockets: None,
94 dies: None,
95 clusters: None,
96 modules: None,
97 cores: None,
98 threads: None,
99 }
100 }
101}
102
103impl ToCommand for SMP {
104 fn command(&self) -> String {
105 ARG_SMP.to_string()
106 }
107 fn to_args(&self) -> Vec<String> {
108 let mut args = vec![self.cpus.to_string()];
109
110 qao!(self.maxcpus, args, KEY_MAXCPUS);
111 qao!(self.drawers, args, KEY_DRAWERS);
112 qao!(self.books, args, KEY_BOOKS);
113 qao!(self.sockets, args, KEY_SOCKETS);
114 qao!(self.dies, args, KEY_DIES);
115 qao!(self.clusters, args, KEY_CLUSTERS);
116 qao!(self.modules, args, KEY_MODULES);
117 qao!(self.cores, args, KEY_CORES);
118 qao!(self.threads, args, KEY_THREADS);
119
120 vec![args.join(DELIM_COMMA)]
121 }
122}
123
124impl FromStr for SMP {
125 type Err = ShellStringError;
126
127 fn from_str(s: &str) -> Result<Self, Self::Err> {
128 smp.parse(s).map_err(|e| ShellStringError::from_parse(e))
129 }
130}
131
132pco!(maxcpus, digit1, usize, KEY_MAXCPUS);
133pco!(drawers, digit1, usize, KEY_DRAWERS);
134pco!(books, digit1, usize, KEY_BOOKS);
135pco!(sockets, digit1, usize, KEY_SOCKETS);
136pco!(dies, digit1, usize, KEY_DIES);
137pco!(clusters, digit1, usize, KEY_CLUSTERS);
138pco!(modules, digit1, usize, KEY_MODULES);
139pco!(cores, digit1, usize, KEY_CORES);
140pco!(threads, digit1, usize, KEY_THREADS);
141
142fn smp(s: &mut &str) -> ModalResult<SMP> {
143 let cpus = dec_uint.parse_next(s)?;
144 let maxcpus = opt(maxcpus).parse_next(s)?;
145 let drawers = opt(drawers).parse_next(s)?;
146 let books = opt(books).parse_next(s)?;
147 let sockets = opt(sockets).parse_next(s)?;
148 let dies = opt(dies).parse_next(s)?;
149 let clusters = opt(clusters).parse_next(s)?;
150 let modules = opt(modules).parse_next(s)?;
151 let cores = opt(cores).parse_next(s)?;
152 let threads = opt(threads).parse_next(s)?;
153 Ok(SMP {
154 cpus,
155 maxcpus,
156 drawers,
157 books,
158 sockets,
159 dies,
160 clusters,
161 modules,
162 cores,
163 threads,
164 })
165}