Skip to main content

qemu_command_builder/
lib.rs

1#![recursion_limit = "256"]
2
3pub mod args;
4pub mod common;
5pub mod parser;
6pub mod parsers;
7pub mod shell_path;
8pub mod shell_string;
9pub mod to_command;
10
11use std::path::PathBuf;
12use std::str::FromStr;
13
14use bon::Builder;
15use chrono::{DateTime, TimeZone, Utc};
16use newtype_uuid::{TypedUuidKind, TypedUuidTag};
17use proptest::prelude::{Arbitrary, Just};
18use proptest_derive::Arbitrary;
19
20use crate::args::accel::Accel;
21use crate::args::acpitable::AcpiTable;
22use crate::args::action::{Action, WatchdogAction};
23use crate::args::addfs::AddFd;
24use crate::args::audio::Audio;
25use crate::args::audiodev::AudioDev;
26use crate::args::blockdev::BlockDev;
27use crate::args::boot::Boot;
28use crate::args::chardev::CharDev;
29use crate::args::compact::Compact;
30use crate::args::cpu::{CpuAarch64, CpuX86};
31use crate::args::device::Device;
32use crate::args::display::QemuDisplay;
33use crate::args::drive::Drive;
34use crate::args::fsdev::FsDev;
35use crate::args::fw_cfg::FwCfg;
36use crate::args::g::G;
37use crate::args::global::Global;
38use crate::args::icount::Icount;
39use crate::args::incoming::Incoming;
40use crate::args::iscsi::Iscsi;
41use crate::args::machine::{MachineAarch64, MachineX86_64};
42use crate::args::memory::Memory;
43use crate::args::mon::Mon;
44use crate::args::msg::Msg;
45use crate::args::name::Name;
46use crate::args::netdev::NetDev;
47use crate::args::network_compat::{LegacyNet, Nic};
48use crate::args::numa::NUMA;
49use crate::args::object::Object;
50use crate::args::overcommit::Overcommit;
51use crate::args::plugin::Plugin;
52use crate::args::rtc::Rtc;
53use crate::args::runwith::RunWith;
54use crate::args::sandbox::Sandbox;
55use crate::args::semihosting::SemihostingConfig;
56use crate::args::serial::SpecialDevice;
57use crate::args::set::Set;
58use crate::args::smbios::Smbios;
59use crate::args::smp::SMP;
60use crate::args::spice::Spice;
61use crate::args::tpmdev::TpmDev;
62use crate::args::trace::Trace;
63use crate::args::usb::USBDevice;
64use crate::args::vga::VGA;
65use crate::args::virtfs::Virtfs;
66use crate::args::vnc::VNC;
67use crate::parser::parse_qemu_command_line;
68use crate::parsers::{
69    ARG_APPEND, ARG_BIG_D, ARG_BIG_S, ARG_BIOS, ARG_CDROM, ARG_DAEMONIZE, ARG_DEBUGCON, ARG_DFILTER, ARG_DTB, ARG_DUMP_VMSTATE, ARG_ECHR, ARG_ENABLE_KVM, ARG_ENABLE_SYNC_PROFILE, ARG_FDA, ARG_FDB,
70    ARG_FULL_SCREEN, ARG_GDB, ARG_HDA, ARG_HDB, ARG_HDC, ARG_HDD, ARG_INITRD, ARG_JITDUMP, ARG_K, ARG_KERNEL, ARG_L, ARG_LITTLE_D, ARG_LITTLE_S, ARG_LOADVM, ARG_MEM_PATH, ARG_MEM_PREALLOC,
71    ARG_MONITOR, ARG_MTDBLOCK, ARG_NO_FD_BOOTCHK, ARG_NO_REBOOT, ARG_NO_SHUTDOWN, ARG_NO_USER_CONFIG, ARG_NODEFAULTS, ARG_NOGRAPHIC, ARG_ONLY_MIGRATABLE, ARG_OPTION_ROM, ARG_PARALLEL, ARG_PERFMAP,
72    ARG_PFLASH, ARG_PIDFILE, ARG_PRECONFIG, ARG_PROM_ENV, ARG_QMP, ARG_QMP_PRETTY, ARG_QTEST, ARG_QTEST_LOG, ARG_READCONFIG, ARG_SD, ARG_SEED, ARG_SEMIHOSTING, ARG_SERIAL, ARG_SHIM, ARG_SNAPSHOT,
73    ARG_USB, ARG_UUID, ARG_WIN2K_HACK, ARG_XEN_ATTACH, ARG_XEN_DOMID, ARG_XEN_DOMID_RESTRICT, DELIM_COMMA,
74};
75use crate::parsers::{ARG_CHROOT, ARG_RUNAS};
76use crate::parsers::{ARG_MIGRATE_MODE_ENABLE, ARG_NO_HPET, ARG_ONLY_CPR_CAPABLE};
77use crate::shell_string::ShellString;
78use crate::to_command::{ToArg, ToCommand};
79
80/// QEMU binary name for x86_64
81const QEMU_BIN_X86_64: &str = "qemu-system-x86_64";
82
83/// QEMU binary name for aarch64
84const QEMU_BIN_AARCH64: &str = "qemu-system-aarch64";
85
86#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder, Arbitrary)]
87pub struct QemuInstanceBase<Machine, Cpu> {
88    pub qemu_binary: PathBuf,
89
90    pub machine: Option<Machine>,
91    pub cpu: Option<Cpu>,
92
93    pub accel: Option<Accel>,
94    pub smp: Option<SMP>,
95    pub numa: Option<Vec<NUMA>>,
96    pub add_fd: Option<Vec<AddFd>>,
97    pub set: Option<Vec<Set>>,
98    pub global: Option<Vec<Global>>,
99    pub boot: Option<Boot>,
100    pub m: Option<Memory>,
101    pub mem_path: Option<PathBuf>,
102    pub mem_prealloc: Option<bool>,
103    pub k: Option<String>,
104    pub audio: Option<Audio>,
105    pub audiodev: Option<Vec<AudioDev>>,
106    pub device: Option<Vec<Device>>,
107    pub name: Option<Name>,
108    pub uuid: Option<newtype_uuid::TypedUuid<QUuid>>,
109    pub fda: Option<PathBuf>,
110    pub fdb: Option<PathBuf>,
111    pub hda: Option<PathBuf>,
112    pub hdb: Option<PathBuf>,
113    pub hdc: Option<PathBuf>,
114    pub hdd: Option<PathBuf>,
115    pub cdrom: Option<PathBuf>,
116    pub blockdev: Option<Vec<BlockDev>>,
117    pub drive: Option<Vec<Drive>>,
118    pub mdtblock: Option<PathBuf>,
119    pub sd: Option<PathBuf>,
120    pub snapshot: Option<bool>,
121    pub fsdev: Option<Vec<FsDev>>,
122    pub virtfs: Option<Vec<Virtfs>>,
123    pub iscsi: Option<Iscsi>,
124    pub usb: Option<bool>,
125    pub usbdevice: Option<USBDevice>,
126    pub display: Option<QemuDisplay>,
127    pub nographic: Option<bool>,
128    pub spice: Option<Spice>,
129    pub vga: Option<VGA>,
130    pub full_screen: Option<bool>,
131    pub g: Option<G>,
132    pub vnc: Option<VNC>,
133    pub win2k_hack: Option<bool>,
134    pub no_fd_bootchk: Option<bool>,
135    pub acpitable: Option<Vec<AcpiTable>>,
136    pub smbios: Option<Vec<Smbios>>,
137    pub netdev: Option<Vec<NetDev>>,
138    pub nic: Option<Vec<Nic>>,
139    pub net: Option<Vec<LegacyNet>>,
140    pub chardev: Option<Vec<CharDev>>,
141    pub tpmdev: Option<Vec<TpmDev>>,
142    pub bios: Option<PathBuf>,
143    pub pflash: Option<PathBuf>,
144    pub kernel: Option<PathBuf>,
145    pub shim: Option<PathBuf>,
146    pub append: Option<ShellString>,
147    pub initrd: Option<PathBuf>,
148    pub dtb: Option<PathBuf>,
149    pub compact: Option<Compact>,
150    pub fw_cfg: Option<Vec<FwCfg>>,
151    pub serial: Option<Vec<SpecialDevice>>,
152    pub parallel: Option<Vec<SpecialDevice>>,
153    pub monitor: Option<Vec<SpecialDevice>>,
154    pub qmp: Option<Vec<SpecialDevice>>,
155    pub qmp_pretty: Option<Vec<SpecialDevice>>,
156    pub mon: Option<Vec<Mon>>,
157    pub debugcon: Option<SpecialDevice>,
158    pub pidfile: Option<PathBuf>,
159    pub preconfig: Option<bool>,
160    pub big_s: Option<bool>,
161    pub overcommit: Option<Overcommit>,
162    pub gdb: Option<SpecialDevice>,
163    pub s: Option<bool>,
164    pub d: Option<Vec<String>>,
165    pub big_d: Option<PathBuf>,
166    pub dfilter: Option<Vec<String>>,
167    pub seed: Option<usize>,
168    pub big_l: Option<PathBuf>,
169    pub enable_kvm: Option<bool>,
170    pub xen_domid: Option<String>,
171    pub xen_attach: Option<bool>,
172    pub xen_domid_restrict: Option<bool>,
173    pub no_reboot: Option<bool>,
174    pub no_hpet: Option<bool>,
175    pub no_shutdown: Option<bool>,
176    pub action: Option<Action>,
177    pub loadvm: Option<String>,
178    pub daemonize: Option<bool>,
179    pub option_rom: Option<PathBuf>,
180    pub rtc: Option<Rtc>,
181    pub icount: Option<Icount>,
182    pub watchdog_action: Option<WatchdogAction>,
183    pub echr: Option<String>,
184    pub incoming: Option<Vec<Incoming>>,
185    pub only_migratable: Option<bool>,
186    pub only_cpr_capable: Option<bool>,
187    pub migrate_mode_enable: Option<String>,
188    pub nodefaults: Option<bool>,
189    pub sandbox: Option<Sandbox>,
190    pub readconfig: Option<PathBuf>,
191    pub no_user_config: Option<bool>,
192    pub trace: Option<Trace>,
193    pub plugin: Option<Vec<Plugin>>,
194    pub semihosting: Option<bool>,
195    pub semihosting_config: Option<SemihostingConfig>,
196    pub qtest: Option<String>,
197    pub qtest_log: Option<PathBuf>,
198    pub prom_env: Option<Vec<String>>,
199    pub run_with: Option<RunWith>,
200    // compat w/ qemu 7.x+
201    pub runas: Option<String>,
202    // compat w/ qemu 7.x+
203    pub chroot: Option<PathBuf>,
204    pub msg: Option<Msg>,
205    pub dump_vmstate: Option<PathBuf>,
206    pub enable_sync_profile: Option<bool>,
207    pub perfmap: Option<PathBuf>,
208    pub jitdump: Option<PathBuf>,
209    pub object: Option<Vec<Object>>,
210}
211
212impl<Machine: ToCommand, Cpu: ToCommand> ToCommand for QemuInstanceBase<Machine, Cpu>
213where
214    QemuInstanceBase<Machine, Cpu>: FromStr,
215{
216    fn command(&self) -> String {
217        self.qemu_binary.display().to_string()
218    }
219
220    fn to_args(&self) -> Vec<String> {
221        let mut cmd = vec![];
222
223        if let Some(machine) = &self.machine {
224            cmd.append(&mut machine.to_command());
225        }
226        if let Some(cpu) = &self.cpu {
227            cmd.append(&mut cpu.to_command());
228        }
229        if let Some(accel) = &self.accel {
230            cmd.append(&mut accel.to_command());
231        }
232        if let Some(smp) = &self.smp {
233            cmd.append(&mut smp.to_command());
234        }
235        if let Some(numas) = &self.numa {
236            for numa in numas {
237                cmd.append(&mut numa.to_command());
238            }
239        }
240        if let Some(add_fds) = &self.add_fd {
241            for add_fd in add_fds {
242                cmd.append(&mut add_fd.to_command());
243            }
244        }
245        if let Some(sets) = &self.set {
246            for set in sets {
247                cmd.append(&mut set.to_command());
248            }
249        }
250        if let Some(globals) = &self.global {
251            for global in globals {
252                cmd.append(&mut global.to_command());
253            }
254        }
255        if let Some(boot) = &self.boot {
256            cmd.append(&mut boot.to_command());
257        }
258        if let Some(m) = &self.m {
259            cmd.append(&mut m.to_command());
260        }
261        if let Some(path) = &self.mem_path {
262            cmd.push(ARG_MEM_PATH.to_string());
263            cmd.push(path.display().to_string());
264        }
265        if let Some(state) = self.mem_prealloc
266            && state
267        {
268            cmd.push(ARG_MEM_PREALLOC.to_string());
269        }
270        if let Some(lang) = &self.k {
271            cmd.push(ARG_K.to_string());
272            cmd.push(lang.to_string());
273        }
274        if let Some(audio) = &self.audio {
275            cmd.append(&mut audio.to_command());
276        }
277        if let Some(audiodevs) = &self.audiodev {
278            for audiodev in audiodevs {
279                cmd.append(&mut audiodev.to_command());
280            }
281        }
282        if let Some(devices) = &self.device {
283            for device in devices {
284                cmd.append(&mut device.to_command());
285            }
286        }
287        if let Some(name) = &self.name {
288            cmd.append(&mut name.to_command());
289        }
290        if let Some(uuid) = &self.uuid {
291            cmd.push(ARG_UUID.to_string());
292            cmd.push(uuid.to_string());
293        }
294        if let Some(fda) = &self.fda {
295            cmd.push(ARG_FDA.to_string());
296            cmd.push(fda.display().to_string());
297        }
298        if let Some(fdb) = &self.fdb {
299            cmd.push(ARG_FDB.to_string());
300            cmd.push(fdb.display().to_string());
301        }
302        if let Some(hda) = &self.hda {
303            cmd.push(ARG_HDA.to_string());
304            cmd.push(hda.display().to_string());
305        }
306        if let Some(hdb) = &self.hdb {
307            cmd.push(ARG_HDB.to_string());
308            cmd.push(hdb.display().to_string());
309        }
310        if let Some(hdc) = &self.hdc {
311            cmd.push(ARG_HDC.to_string());
312            cmd.push(hdc.display().to_string());
313        }
314        if let Some(hdd) = &self.hdd {
315            cmd.push(ARG_HDD.to_string());
316            cmd.push(hdd.display().to_string());
317        }
318        if let Some(cdrom) = &self.cdrom {
319            cmd.push(ARG_CDROM.to_string());
320            cmd.push(cdrom.display().to_string());
321        }
322        if let Some(blockdevs) = &self.blockdev {
323            for blockdev in blockdevs {
324                cmd.append(&mut blockdev.to_command());
325            }
326        }
327        if let Some(drives) = &self.drive {
328            for drive in drives {
329                cmd.append(&mut drive.to_command());
330            }
331        }
332        if let Some(mdtblock) = &self.mdtblock {
333            cmd.push(ARG_MTDBLOCK.to_string());
334            cmd.push(mdtblock.display().to_string());
335        }
336        if let Some(sd) = &self.sd {
337            cmd.push(ARG_SD.to_string());
338            cmd.push(sd.display().to_string());
339        }
340        if let Some(state) = &self.snapshot
341            && *state
342        {
343            cmd.push(ARG_SNAPSHOT.to_string());
344        }
345        if let Some(fsdevs) = &self.fsdev {
346            for fsdev in fsdevs {
347                cmd.append(&mut fsdev.to_command());
348            }
349        }
350        if let Some(virtfses) = &self.virtfs {
351            for virtfs in virtfses {
352                cmd.append(&mut virtfs.to_command());
353            }
354        }
355        if let Some(iscsi) = &self.iscsi {
356            cmd.append(&mut iscsi.to_command());
357        }
358        if let Some(state) = &self.usb
359            && *state
360        {
361            cmd.push(ARG_USB.to_string());
362        }
363        if let Some(usbdevice) = &self.usbdevice {
364            cmd.append(&mut usbdevice.to_command());
365        }
366        if let Some(display) = &self.display {
367            cmd.append(&mut display.to_command());
368        }
369        if let Some(state) = &self.nographic
370            && *state
371        {
372            cmd.push(ARG_NOGRAPHIC.to_string());
373        }
374        if let Some(spice) = &self.spice {
375            cmd.append(&mut spice.to_command());
376        }
377        if let Some(vga) = &self.vga {
378            cmd.append(&mut vga.to_command());
379        }
380        if let Some(full_screen) = &self.full_screen
381            && *full_screen
382        {
383            cmd.push(ARG_FULL_SCREEN.to_string());
384        }
385        if let Some(g) = &self.g {
386            cmd.append(&mut g.to_command());
387        }
388        if let Some(vnc) = &self.vnc {
389            cmd.append(&mut vnc.to_command());
390        }
391        if let Some(win2k_hack) = &self.win2k_hack
392            && *win2k_hack
393        {
394            cmd.push(ARG_WIN2K_HACK.to_string());
395        }
396        if let Some(no_fd_bootchk) = &self.no_fd_bootchk
397            && *no_fd_bootchk
398        {
399            cmd.push(ARG_NO_FD_BOOTCHK.to_string());
400        }
401        if let Some(acpitables) = &self.acpitable {
402            for acpitable in acpitables {
403                cmd.append(&mut acpitable.to_command());
404            }
405        }
406        if let Some(smbioss) = &self.smbios {
407            for smbios in smbioss {
408                cmd.append(&mut smbios.to_command());
409            }
410        }
411        if let Some(netdevs) = &self.netdev {
412            for netdev in netdevs {
413                cmd.append(&mut netdev.to_command());
414            }
415        }
416        if let Some(nics) = &self.nic {
417            for nic in nics {
418                cmd.append(&mut nic.to_command());
419            }
420        }
421        if let Some(nets) = &self.net {
422            for net in nets {
423                cmd.append(&mut net.to_command());
424            }
425        }
426        if let Some(chardevs) = &self.chardev {
427            for chardev in chardevs {
428                cmd.append(&mut chardev.to_command());
429            }
430        }
431        if let Some(tpmdevs) = &self.tpmdev {
432            for tpmdev in tpmdevs {
433                cmd.append(&mut tpmdev.to_command());
434            }
435        }
436        if let Some(bios) = &self.bios {
437            cmd.push(ARG_BIOS.to_string());
438            cmd.push(bios.display().to_string());
439        }
440        if let Some(pflash) = &self.pflash {
441            cmd.push(ARG_PFLASH.to_string());
442            cmd.push(pflash.display().to_string());
443        }
444        if let Some(kernel) = &self.kernel {
445            cmd.push(ARG_KERNEL.to_string());
446            cmd.push(kernel.display().to_string());
447        }
448        if let Some(shim) = &self.shim {
449            cmd.push(ARG_SHIM.to_string());
450            cmd.push(shim.display().to_string());
451        }
452        if let Some(append) = &self.append {
453            cmd.push(ARG_APPEND.to_string());
454            cmd.push(append.as_ref().to_string());
455        }
456        if let Some(initrd) = &self.initrd {
457            cmd.push(ARG_INITRD.to_string());
458            cmd.push(initrd.display().to_string());
459        }
460        if let Some(dtb) = &self.dtb {
461            cmd.push(ARG_DTB.to_string());
462            cmd.push(dtb.display().to_string());
463        }
464        if let Some(compact) = &self.compact {
465            cmd.append(&mut compact.to_command());
466        }
467        if let Some(fw_cfgs) = &self.fw_cfg {
468            for fw_cfg in fw_cfgs {
469                cmd.append(&mut fw_cfg.to_command());
470            }
471        }
472        if let Some(serials) = &self.serial {
473            for serial in serials {
474                cmd.push(ARG_SERIAL.to_string());
475                cmd.append(&mut serial.to_args());
476            }
477        }
478        if let Some(parallels) = &self.parallel {
479            for parallel in parallels {
480                cmd.push(ARG_PARALLEL.to_string());
481                cmd.append(&mut parallel.to_args());
482            }
483        }
484        if let Some(monitors) = &self.monitor {
485            for monitor in monitors {
486                cmd.push(ARG_MONITOR.to_string());
487                cmd.append(&mut monitor.to_args());
488            }
489        }
490        if let Some(qmps) = &self.qmp {
491            for qmp in qmps {
492                cmd.push(ARG_QMP.to_string());
493                cmd.append(&mut qmp.to_args());
494            }
495        }
496        if let Some(qmp_pretties) = &self.qmp_pretty {
497            for qmp_pretty in qmp_pretties {
498                cmd.push(ARG_QMP_PRETTY.to_string());
499                cmd.append(&mut qmp_pretty.to_args());
500            }
501        }
502        if let Some(mons) = &self.mon {
503            for mon in mons {
504                cmd.append(&mut mon.to_command());
505            }
506        }
507        if let Some(debugcon) = &self.debugcon {
508            cmd.push(ARG_DEBUGCON.to_string());
509            cmd.append(&mut debugcon.to_args());
510        }
511        if let Some(pidfile) = &self.pidfile {
512            cmd.push(ARG_PIDFILE.to_string());
513            cmd.push(pidfile.display().to_string());
514        }
515        if let Some(preconfig) = &self.preconfig
516            && *preconfig
517        {
518            cmd.push(ARG_PRECONFIG.to_string());
519        }
520        if let Some(s) = &self.big_s
521            && *s
522        {
523            cmd.push(ARG_BIG_S.to_string());
524        }
525        if let Some(overcommit) = &self.overcommit {
526            cmd.append(&mut overcommit.to_command());
527        }
528        if let Some(gdb) = &self.gdb {
529            cmd.push(ARG_GDB.to_string());
530            cmd.append(&mut gdb.to_args());
531        }
532        if let Some(s) = &self.s
533            && *s
534        {
535            cmd.push(ARG_LITTLE_S.to_string());
536        }
537        if let Some(d) = &self.d {
538            cmd.push(ARG_LITTLE_D.to_string());
539            cmd.push(d.join(DELIM_COMMA));
540        }
541        if let Some(big_d) = &self.big_d {
542            cmd.push(ARG_BIG_D.to_string());
543            cmd.push(big_d.display().to_string());
544        }
545        if let Some(dfilter) = &self.dfilter {
546            cmd.push(ARG_DFILTER.to_string());
547            cmd.push(dfilter.join(DELIM_COMMA));
548        }
549        if let Some(seed) = &self.seed {
550            cmd.push(ARG_SEED.to_string());
551            cmd.push(seed.to_string());
552        }
553        if let Some(l) = &self.big_l {
554            cmd.push(ARG_L.to_string());
555            cmd.push(l.display().to_string());
556        }
557        if let Some(enable_kvm) = &self.enable_kvm
558            && *enable_kvm
559        {
560            cmd.push(ARG_ENABLE_KVM.to_string());
561        }
562        if let Some(xen_domid) = &self.xen_domid {
563            cmd.push(ARG_XEN_DOMID.to_string());
564            cmd.push(xen_domid.to_string());
565        }
566        if let Some(xen_attach) = &self.xen_attach
567            && *xen_attach
568        {
569            cmd.push(ARG_XEN_ATTACH.to_string());
570        }
571        if let Some(xen_domid_restrict) = &self.xen_domid_restrict
572            && *xen_domid_restrict
573        {
574            cmd.push(ARG_XEN_DOMID_RESTRICT.to_string());
575        }
576        if let Some(no_reboot) = &self.no_reboot
577            && *no_reboot
578        {
579            cmd.push(ARG_NO_REBOOT.to_string());
580        }
581        if self.no_hpet == Some(true) {
582            cmd.push(ARG_NO_HPET.to_string());
583        }
584        if let Some(no_shutdown) = &self.no_shutdown
585            && *no_shutdown
586        {
587            cmd.push(ARG_NO_SHUTDOWN.to_string());
588        }
589        if let Some(action) = &self.action {
590            cmd.append(&mut action.to_command());
591        }
592        if let Some(loadvm) = &self.loadvm {
593            cmd.push(ARG_LOADVM.to_string());
594            cmd.push(loadvm.to_string());
595        }
596        if let Some(daemonize) = &self.daemonize
597            && *daemonize
598        {
599            cmd.push(ARG_DAEMONIZE.to_string());
600        }
601        if let Some(option_rom) = &self.option_rom {
602            cmd.push(ARG_OPTION_ROM.to_string());
603            cmd.push(option_rom.display().to_string());
604        }
605        if let Some(rtc) = &self.rtc {
606            cmd.append(&mut rtc.to_command());
607        }
608        if let Some(icount) = &self.icount {
609            cmd.append(&mut icount.to_command());
610        }
611        if let Some(watchdog_action) = &self.watchdog_action {
612            cmd.push("-watchdog-action".to_string());
613            cmd.push(watchdog_action.to_arg().to_string());
614        }
615        if let Some(echr) = &self.echr {
616            cmd.push(ARG_ECHR.to_string());
617            cmd.push(echr.to_string());
618        }
619        if let Some(incomings) = &self.incoming {
620            for incoming in incomings {
621                cmd.append(&mut incoming.to_command());
622            }
623        }
624        if let Some(only_migratable) = &self.only_migratable
625            && *only_migratable
626        {
627            cmd.push(ARG_ONLY_MIGRATABLE.to_string());
628        }
629        if self.only_cpr_capable == Some(true) {
630            cmd.push(ARG_ONLY_CPR_CAPABLE.to_string());
631        }
632        if let Some(mode) = &self.migrate_mode_enable {
633            cmd.push(ARG_MIGRATE_MODE_ENABLE.to_string());
634            cmd.push(mode.clone());
635        }
636        if let Some(nodefaults) = &self.nodefaults
637            && *nodefaults
638        {
639            cmd.push(ARG_NODEFAULTS.to_string());
640        }
641        if let Some(sandbox) = &self.sandbox {
642            cmd.append(&mut sandbox.to_command());
643        }
644        if let Some(readconfig) = &self.readconfig {
645            cmd.push(ARG_READCONFIG.to_string());
646            cmd.push(readconfig.display().to_string());
647        }
648        if let Some(no_user_config) = &self.no_user_config
649            && *no_user_config
650        {
651            cmd.push(ARG_NO_USER_CONFIG.to_string());
652        }
653        if let Some(trace) = &self.trace {
654            cmd.append(&mut trace.to_command());
655        }
656        if let Some(plugins) = &self.plugin {
657            for plugin in plugins {
658                cmd.append(&mut plugin.to_command());
659            }
660        }
661        if self.semihosting == Some(true) {
662            cmd.push(ARG_SEMIHOSTING.to_string());
663        }
664        if let Some(config) = &self.semihosting_config {
665            cmd.append(&mut config.to_command());
666        }
667        if let Some(qtest) = &self.qtest {
668            cmd.push(ARG_QTEST.to_string());
669            cmd.push(qtest.clone());
670        }
671        if let Some(qtest_log) = &self.qtest_log {
672            cmd.push(ARG_QTEST_LOG.to_string());
673            cmd.push(qtest_log.display().to_string());
674        }
675        if let Some(prom_envs) = &self.prom_env {
676            for prom_env in prom_envs {
677                cmd.push(ARG_PROM_ENV.to_string());
678                cmd.push(prom_env.clone());
679            }
680        }
681        if let Some(run_with) = &self.run_with {
682            cmd.append(&mut run_with.to_command());
683        }
684        if let Some(runas) = &self.runas {
685            cmd.push(ARG_RUNAS.to_string());
686            cmd.push(runas.to_string());
687        }
688        if let Some(chroot) = &self.chroot {
689            cmd.push(ARG_CHROOT.to_string());
690            cmd.push(chroot.display().to_string());
691        }
692        if let Some(msg) = &self.msg {
693            cmd.append(&mut msg.to_command());
694        }
695        if let Some(dump_vmstate) = &self.dump_vmstate {
696            cmd.push(ARG_DUMP_VMSTATE.to_string());
697            cmd.push(dump_vmstate.display().to_string());
698        }
699        if let Some(enable_sync_profile) = &self.enable_sync_profile
700            && *enable_sync_profile
701        {
702            cmd.push(ARG_ENABLE_SYNC_PROFILE.to_string());
703        }
704        if let Some(perfmap) = &self.perfmap {
705            cmd.push(ARG_PERFMAP.to_string());
706            cmd.push(perfmap.display().to_string());
707        }
708        if let Some(jitdump) = &self.jitdump {
709            cmd.push(ARG_JITDUMP.to_string());
710            cmd.push(jitdump.display().to_string());
711        }
712        if let Some(objects) = &self.object {
713            for object in objects {
714                cmd.append(&mut object.to_command());
715            }
716        }
717        cmd
718    }
719}
720
721pub type QemuInstanceForX86_64 = QemuInstanceBase<MachineX86_64, CpuX86>;
722pub type QemuInstanceForAarch64 = QemuInstanceBase<MachineAarch64, CpuAarch64>;
723
724#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
725pub enum QemuCommand {
726    X86_64(QemuInstanceBase<MachineX86_64, CpuX86>),
727    Aarch64(QemuInstanceBase<MachineAarch64, CpuAarch64>),
728}
729
730impl ToCommand for QemuCommand {
731    fn to_args(&self) -> Vec<String> {
732        match self {
733            QemuCommand::X86_64(instance) => instance.to_args(),
734            QemuCommand::Aarch64(instance) => instance.to_args(),
735        }
736    }
737
738    fn to_command(&self) -> Vec<String> {
739        match self {
740            QemuCommand::X86_64(instance) => instance.to_command(),
741            QemuCommand::Aarch64(instance) => instance.to_command(),
742        }
743    }
744}
745
746impl FromStr for QemuCommand {
747    type Err = String;
748
749    fn from_str(s: &str) -> Result<Self, Self::Err> {
750        parse_qemu_command_line(s)
751    }
752}
753
754pub struct QUuid {}
755
756impl TypedUuidKind for QUuid {
757    fn tag() -> TypedUuidTag {
758        // Tags are required to be ASCII identifiers, with underscores
759        // and dashes also supported. The validity of a tag can be checked
760        // at compile time by assigning it to a const, like so:
761        const TAG: TypedUuidTag = TypedUuidTag::new("my_kind");
762        TAG
763    }
764}
765
766#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
767pub struct QDateTime(DateTime<Utc>);
768
769impl Arbitrary for QDateTime {
770    type Parameters = ();
771    fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
772        let dt = Utc.with_ymd_and_hms(1984, 10, 22, 0, 1, 5).unwrap();
773        Just(QDateTime(dt))
774    }
775
776    type Strategy = proptest::strategy::Just<Self>;
777}
778
779#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
780pub struct QIpv4Net {
781    ip: ipnet::Ipv4Net,
782}
783
784impl Arbitrary for QIpv4Net {
785    type Parameters = ();
786    fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
787        todo!()
788    }
789
790    type Strategy = proptest::strategy::Just<Self>;
791}
792
793#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
794pub struct QIpv6Net {
795    ip: ipnet::Ipv6Net,
796}
797
798impl Arbitrary for QIpv6Net {
799    type Parameters = ();
800    fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
801        todo!()
802    }
803
804    type Strategy = proptest::strategy::Just<Self>;
805}