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