diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/argument.rs | 36 | ||||
-rw-r--r-- | src/linux.rs | 2 | ||||
-rw-r--r-- | src/main.rs | 570 | ||||
-rw-r--r-- | src/plugin/vcpu.rs | 5 |
4 files changed, 454 insertions, 159 deletions
diff --git a/src/argument.rs b/src/argument.rs index 02e97f0..26950a9 100644 --- a/src/argument.rs +++ b/src/argument.rs @@ -376,28 +376,34 @@ pub fn print_help(program_name: &str, required_arg: &str, args: &[Argument]) { return; } println!("Argument{}:", if args.len() > 1 { "s" } else { "" }); + for arg in args { - match arg.short { - Some(s) => print!(" -{}, ", s), - None => print!(" "), + println!(); + + if let Some(s) = arg.short { + print!(" -{}", s); + if !arg.long.is_empty() { + print!(","); + } } - if arg.long.is_empty() { - print!(" "); - } else { - print!("--"); + + print!(" "); + + if !arg.long.is_empty() { + print!("--{}", arg.long); } - print!("{:<12}", arg.long); + if let Some(v) = arg.value { - if arg.long.is_empty() { - print!(" "); - } else { + if !arg.long.is_empty() { print!("="); } - print!("{:<10}", v); - } else { - print!("{:<11}", ""); + print!("{}", v); + } + + println!(); + for line in arg.help.lines() { + println!(" {}", line); } - println!("{}", arg.help); } } diff --git a/src/linux.rs b/src/linux.rs index fb463c2..3e2045f 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -1658,7 +1658,7 @@ fn file_fields_to_i64<P: AsRef<Path>>(path: P) -> io::Result<Vec<i64>> { .collect() } -// Reads the contents of a file and converts them into a u64, and if there +// Reads the contents of a file and converts them into a i64, and if there // are multiple fields it only returns the first one. fn file_to_i64<P: AsRef<Path>>(path: P) -> io::Result<i64> { file_fields_to_i64(path)? diff --git a/src/main.rs b/src/main.rs index e8a6e6c..ed7bb30 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,10 +38,7 @@ use vm_control::{ }; fn executable_is_plugin(executable: &Option<Executable>) -> bool { - match executable { - Some(Executable::Plugin(_)) => true, - _ => false, - } + matches!(executable, Some(Executable::Plugin(_))) } // Wait for all children to exit. Return true if they have all exited, false @@ -1296,135 +1293,427 @@ fn validate_arguments(cfg: &mut Config) -> std::result::Result<(), argument::Err } fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> { - let arguments = - &[Argument::positional("KERNEL", "bzImage of kernel to run"), - Argument::value("android-fstab", "PATH", "Path to Android fstab"), - Argument::short_value('i', "initrd", "PATH", "Initial ramdisk to load."), - Argument::short_value('p', - "params", - "PARAMS", - "Extra kernel or plugin command line arguments. Can be given more than once."), - Argument::short_value('c', "cpus", "N", "Number of VCPUs. (default: 1)"), - Argument::value("cpu-affinity", "CPUSET", "Comma-separated list of CPUs or CPU ranges to run VCPUs on. (e.g. 0,1-3,5) (default: no mask)"), - Argument::short_value('m', - "mem", - "N", - "Amount of guest memory in MiB. (default: 256)"), - Argument::short_value('r', - "root", - "PATH[,key=value[,key=value[,...]]", - "Path to a root disk image followed by optional comma-separated options. - Like `--disk` but adds appropriate kernel command line option. - See --disk for valid options."), - Argument::value("rwroot", "PATH[,key=value[,key=value[,...]]", "Path to a writable root disk image followed by optional comma-separated options. - See --disk for valid options."), - Argument::short_value('d', "disk", "PATH[,key=value[,key=value[,...]]", "Path to a disk image followed by optional comma-separated options. - Valid keys: - sparse=BOOL - Indicates whether the disk should support the discard operation (default: true) - block_size=BYTES - Set the reported block size of the disk (default: 512)"), - Argument::value("rwdisk", "PATH[,key=value[,key=value[,...]]", "Path to a writable disk image followed by optional comma-separated options. - See --disk for valid options."), - Argument::value("rw-pmem-device", "PATH", "Path to a writable disk image."), - Argument::value("pmem-device", "PATH", "Path to a disk image."), - Argument::value("pstore", "path=PATH,size=SIZE", "Path to pstore buffer backend file follewed by size."), - Argument::value("host_ip", - "IP", - "IP address to assign to host tap interface."), - Argument::value("netmask", "NETMASK", "Netmask for VM subnet."), - Argument::value("mac", "MAC", "MAC address for VM."), - Argument::value("net-vq-pairs", "N", "virtio net virtual queue paris. (default: 1)"), - Argument::value("ac97", - "[backend=BACKEND,capture=true,capture_effect=EFFECT]", - "Comma separated key=value pairs for setting up Ac97 devices. Can be given more than once . - Possible key values: - backend=(null, cras) - Where to route the audio device. If not provided, backend will default to null. - `null` for /dev/null, and cras for CRAS server. - capture - Enable audio capture - capture_effects - | separated effects to be enabled for recording. The only supported effect value now is EchoCancellation or aec."), - Argument::value("serial", - "type=TYPE,[hardware=HW,num=NUM,path=PATH,input=PATH,console,earlycon,stdin]", - "Comma separated key=value pairs for setting up serial devices. Can be given more than once. - Possible key values: - type=(stdout,syslog,sink,file) - Where to route the serial device - hardware=(serial,virtio-console) - Which type of serial hardware to emulate. Defaults to 8250 UART (serial). - num=(1,2,3,4) - Serial Device Number. If not provided, num will default to 1. - path=PATH - The path to the file to write to when type=file - input=PATH - The path to the file to read from when not stdin - console - Use this serial device as the guest console. Can only be given once. Will default to first serial port if not provided. - earlycon - Use this serial device as the early console. Can only be given once. - stdin - Direct standard input to this serial device. Can only be given once. Will default to first serial port if not provided. - "), - Argument::value("syslog-tag", "TAG", "When logging to syslog, use the provided tag."), - Argument::value("x-display", "DISPLAY", "X11 display name to use."), - Argument::flag("display-window-keyboard", "Capture keyboard input from the display window."), - Argument::flag("display-window-mouse", "Capture keyboard input from the display window."), - Argument::value("wayland-sock", "PATH[,name=NAME]", "Path to the Wayland socket to use. The unnamed one is used for displaying virtual screens. Named ones are only for IPC."), - #[cfg(feature = "wl-dmabuf")] - Argument::flag("wayland-dmabuf", "Enable support for DMABufs in Wayland device."), - Argument::short_value('s', - "socket", - "PATH", - "Path to put the control socket. If PATH is a directory, a name will be generated."), - Argument::flag("disable-sandbox", "Run all devices in one, non-sandboxed process."), - Argument::value("cid", "CID", "Context ID for virtual sockets."), - Argument::value("shared-dir", "PATH:TAG[:type=TYPE:writeback=BOOL:timeout=SECONDS:uidmap=UIDMAP:gidmap=GIDMAP:cache=CACHE]", - "Colon-separated options for configuring a directory to be shared with the VM. -The first field is the directory to be shared and the second field is the tag that the VM can use to identify the device. -The remaining fields are key=value pairs that may appear in any order. Valid keys are: -type=(p9, fs) - Indicates whether the directory should be shared via virtio-9p or virtio-fs (default: p9). -uidmap=UIDMAP - The uid map to use for the device's jail in the format \"inner outer count[,inner outer count]\" (default: 0 <current euid> 1). -gidmap=GIDMAP - The gid map to use for the device's jail in the format \"inner outer count[,inner outer count]\" (default: 0 <current egid> 1). -cache=(never, auto, always) - Indicates whether the VM can cache the contents of the shared directory (default: auto). When set to \"auto\" and the type is \"fs\", the VM will use close-to-open consistency for file contents. -timeout=SECONDS - How long the VM should consider file attributes and directory entries to be valid (default: 5). If the VM has exclusive access to the directory, then this should be a large value. If the directory can be modified by other processes, then this should be 0. -writeback=BOOL - Indicates whether the VM can use writeback caching (default: false). This is only safe to do when the VM has exclusive access to the files in a directory. Additionally, the server should have read permission for all files as the VM may issue read requests even for files that are opened write-only. + let arguments = &[ + Argument::positional("KERNEL", "bzImage of kernel to run."), + Argument::value("android-fstab", "PATH", "Path to Android fstab."), + Argument::short_value('i', "initrd", "PATH", "Initial ramdisk to load."), + Argument::short_value( + 'p', + "params", + "PARAMS", + "\ +Extra kernel or plugin command line arguments. Can be given more than once. +", + ), + Argument::short_value('c', "cpus", "N", "Number of VCPUs. (default: 1)"), + Argument::value( + "cpu-affinity", + "CPUSET", + "\ +Comma-separated list of CPUs or CPU ranges to run VCPUs on (e.g. 0,1-3,5). +(default: no mask) +", + ), + Argument::short_value( + 'm', + "mem", + "N", + "Amount of guest memory in MiB. (default: 256)", + ), + Argument::short_value( + 'r', + "root", + "PATH[,key=value[,key=value[,...]]", + "\ +Path to a root disk image followed by optional comma-separated options. +Like --disk but adds appropriate kernel command line option. See --disk for +valid options. +", + ), + Argument::value( + "rwroot", + "PATH[,key=value[,key=value[,...]]", + "\ +Path to a writable root disk image followed by optional comma-separated +options. See --disk for valid options. +", + ), + Argument::short_value( + 'd', + "disk", + "PATH[,key=value[,key=value[,...]]", + "\ +Path to a disk image followed by optional comma-separated options. + +Valid keys: + + sparse=BOOL + Indicates whether the disk should support the discard operation. + (default: true) + + block_size=BYTES + Set the reported block size of the disk. + (default: 512) +", + ), + Argument::value( + "rwdisk", + "PATH[,key=value[,key=value[,...]]", + "\ +Path to a writable disk image followed by optional comma-separated options. +See --disk for valid options. +", + ), + Argument::value("rw-pmem-device", "PATH", "Path to a writable disk image."), + Argument::value("pmem-device", "PATH", "Path to a disk image."), + Argument::value( + "pstore", + "path=PATH,size=SIZE", + "\ +Path to pstore buffer backend file follewed by size. +", + ), + Argument::value( + "host_ip", + "IP", + "IP address to assign to host tap interface.", + ), + Argument::value("netmask", "NETMASK", "Netmask for VM subnet."), + Argument::value("mac", "MAC", "MAC address for VM."), + Argument::value( + "ac97", + "[backend=BACKEND,capture=true,capture_effect=EFFECT]", + r#"Comma separated key=value pairs for setting up Ac97 devices. Can be +given more than once. + +Possible key values: + + backend=(null,cras) + Where to route the audio device. "null" for /dev/null, and "cras" + for CRAS server. + (default: null) + + capture + Enable audio capture. + + capture_effects + Separated effects to be enabled for recording. The only supported + effect value now is EchoCancellation or aec. +"#, + ), + Argument::value( + "serial", + "type=TYPE,[hardware=HW,num=NUM,path=PATH,input=PATH,console,earlycon,stdin]", + "\ +Comma separated key=value pairs for setting up serial devices. Can be given +more than once. + +Possible key values: + + type=(stdout,syslog,sink,file) + Where to route the serial device. + + hardware=(serial,virtio-console) + Which type of serial hardware to emulate. Defaults to 8250 UART + (serial). + + num=(1,2,3,4) + Serial Device Number. If not provided, num will default to 1. + + path=PATH + The path to the file to write to when type=file. + + input=PATH + The path to the file to read from when not stdin. + + console + Use this serial device as the guest console. Can only be given once. + Will default to first serial port if not provided. + + earlycon + Use this serial device as the early console. Can only be given once. + + stdin + Direct standard input to this serial device. Can only be given once. + Will default to first serial port if not provided. +", + ), + Argument::value( + "syslog-tag", + "TAG", + "When logging to syslog, use the provided tag.", + ), + Argument::value("x-display", "DISPLAY", "X11 display name to use."), + Argument::flag( + "display-window-keyboard", + "\ +Capture keyboard input from the display window. +", + ), + Argument::flag( + "display-window-mouse", + "Capture keyboard input from the display window.", + ), + Argument::value( + "net-vq-pairs", + "N", + "\ +Number of virtio-net virtual queue pairs. +(default: 1) +", + ), + Argument::value( + "wayland-sock", + "PATH[,name=NAME]", + "\ +Path to the Wayland socket to use. The unnamed one is used for displaying +virtual screens. Named ones are only for IPC. +", + ), + #[cfg(feature = "wl-dmabuf")] + Argument::flag( + "wayland-dmabuf", + "Enable support for DMABufs in Wayland device.", + ), + Argument::short_value( + 's', + "socket", + "PATH", + "\ +Path to put the control socket. If PATH is a directory, a name will be +generated. +", + ), + Argument::flag( + "disable-sandbox", + "Run all devices in one, non-sandboxed process.", + ), + Argument::value("cid", "CID", "Context ID for virtual sockets."), + Argument::value( + "shared-dir", + "\ +PATH:TAG[:type=TYPE:writeback=BOOL:timeout=SECONDS:uidmap=UIDMAP:gidmap=GIDMAP:cache=CACHE]", + r#"Colon-separated options for configuring a directory to be shared with the +VM. + +The first field is the directory to be shared and the second field is the +tag that the VM can use to identify the device. The remaining fields are +key=value pairs that may appear in any order. Valid keys are: + + type=(p9, fs) + Indicates whether the directory should be shared via virtio-9p or + virtio-fs. + (default: p9) + + uidmap=UIDMAP + The uid map to use for the device's jail in the format + "inner outer count[,inner outer count]". + (default: 0 <current euid> 1). + + gidmap=GIDMAP + The gid map to use for the device's jail in the format + "inner outer count[,inner outer count]". + (default: 0 <current egid> 1) + + cache=(never, auto, always) + Indicates whether the VM can cache the contents of the shared directory. + When set to "auto" and the type is "fs", the VM will use + close-to-open consistency for file contents. + (default: auto) + + timeout=SECONDS + How long the VM should consider file attributes and directory entries to + be valid. If the VM has exclusive access to the directory, then this + should be a large value. If the directory can be modified by other + processes, then this should be 0. + (default: 5) + + writeback=BOOL + Indicates whether the VM can use writeback caching. This is only safe + to do when the VM has exclusive access to the files in a directory. + Additionally, the server should have read permission for all files as + the VM may issue read requests even for files that are opened + write-only. + (default: false) +"#, + ), + Argument::value( + "seccomp-policy-dir", + "PATH", + "Path to seccomp .policy files.", + ), + Argument::flag( + "seccomp-log-failures", + "\ +Instead of seccomp filter failures being fatal, they will be logged instead.", + ), + #[cfg(feature = "plugin")] + Argument::value( + "plugin", + "PATH", + "Absolute path to plugin process to run under crosvm.", + ), + #[cfg(feature = "plugin")] + Argument::value( + "plugin-root", + "PATH", + "\ +Absolute path to a directory that will become root filesystem for the plugin +process. +", + ), + #[cfg(feature = "plugin")] + Argument::value( + "plugin-mount", + "PATH:PATH:BOOL", + "\ +Path to be mounted into the plugin's root filesystem. Can be given more +than once. +", + ), + #[cfg(feature = "plugin")] + Argument::value( + "plugin-mount-file", + "PATH", + "\ +Path to the file listing paths be mounted into the plugin's root filesystem. +Can be given more than once. +", + ), + #[cfg(feature = "plugin")] + Argument::value( + "plugin-gid-map", + "GID:GID:INT", + "\ +Supplemental GIDs that should be mapped in plugin jail. Can be given more +than once. +", + ), + #[cfg(feature = "plugin")] + Argument::value( + "plugin-gid-map-file", + "PATH", + "\ +Path to the file listing supplemental GIDs that should be mapped in plugin +jail. Can be given more than once. +", + ), + Argument::flag("vhost-net", "Use vhost for networking."), + Argument::value( + "tap-fd", + "fd", + "\ +File descriptor for configured tap device. A different virtual network card +will be added each time this argument is given. +", + ), + #[cfg(feature = "gpu")] + Argument::flag_or_value( + "gpu", + "[width=INT,height=INT]", + "\ +(EXPERIMENTAL) +Comma separated key=value pairs for setting up a virtio-gpu device. + +Possible key values: + backend=(2d|3d|gfxstream) + Which backend to use for virtio-gpu (determining rendering protocol). + + width=INT + The width of the virtual display connected to the virtio-gpu. + + height=INT + The height of the virtual display connected to the virtio-gpu. + + egl[=true|=false] + If the virtio-gpu backend should use a EGL context for rendering. + + glx[=true|=false] + If the virtio-gpu backend should use a GLX context for rendering. + + surfaceless[=true|=false] + If the virtio-gpu backend should use a surfaceless context for rendering. +", + ), + #[cfg(feature = "tpm")] + Argument::flag( + "software-tpm", + "\ +Enable a software emulated trusted platform module device. +", + ), + Argument::value( + "evdev", + "PATH", + "\ +Path to an event device node. The device will be grabbed (unusable from the +host) and made available to the guest with the same configuration it shows +on the host. +", + ), + Argument::value( + "single-touch", + "PATH:WIDTH:HEIGHT", + "\ +Path to a socket from where to read single touch input events (such as those +from a touchscreen) and write status updates to, optionally followed by +width and height. +(default: 800x1280) +", + ), + Argument::value( + "trackpad", + "PATH:WIDTH:HEIGHT", + "\ +Path to a socket from where to read trackpad input events and write status +updates to, optionally followed by screen width and height. +(default: 800x1280) +", + ), + Argument::value( + "mouse", + "PATH", + "\ +Path to a socket from where to read mouse input events and write status +updates to. +", + ), + Argument::value( + "keyboard", + "PATH", + "\ +Path to a socket from where to read keyboard input events and write status +updates to. +", + ), + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + Argument::flag( + "split-irqchip", + "\ +(EXPERIMENTAL) +Enable split-irqchip support. +", + ), + Argument::value("bios", "PATH", "Path to BIOS/firmware ROM"), + Argument::value( + "vfio", + "PATH", + "Path to sysfs of pass through or mdev device", + ), + #[cfg(feature = "video-decoder")] + Argument::flag("video-decoder", "\ +(EXPERIMENTAL) +Enable virtio-video decoder device. +", + ), + #[cfg(feature = "video-encoder")] + Argument::flag("video-encoder", "\ +(EXPERIMENTAL) +Enable virtio-video encoder device. "), - Argument::value("seccomp-policy-dir", "PATH", "Path to seccomp .policy files."), - Argument::flag("seccomp-log-failures", "Instead of seccomp filter failures being fatal, they will be logged instead."), - #[cfg(feature = "plugin")] - Argument::value("plugin", "PATH", "Absolute path to plugin process to run under crosvm."), - #[cfg(feature = "plugin")] - Argument::value("plugin-root", "PATH", "Absolute path to a directory that will become root filesystem for the plugin process."), - #[cfg(feature = "plugin")] - Argument::value("plugin-mount", "PATH:PATH:BOOL", "Path to be mounted into the plugin's root filesystem. Can be given more than once."), - #[cfg(feature = "plugin")] - Argument::value("plugin-mount-file", "PATH", "Path to the file listing paths be mounted into the plugin's root filesystem. Can be given more than once."), - #[cfg(feature = "plugin")] - Argument::value("plugin-gid-map", "GID:GID:INT", "Supplemental GIDs that should be mapped in plugin jail. Can be given more than once."), - #[cfg(feature = "plugin")] - Argument::value("plugin-gid-map-file", "PATH", "Path to the file listing supplemental GIDs that should be mapped in plugin jail. Can be given more than once."), - Argument::flag("vhost-net", "Use vhost for networking."), - Argument::value("tap-fd", - "fd", - "File descriptor for configured tap device. A different virtual network card will be added each time this argument is given."), - #[cfg(feature = "gpu")] - Argument::flag_or_value("gpu", - "[width=INT,height=INT]", - "(EXPERIMENTAL) Comma separated key=value pairs for setting up a virtio-gpu device - Possible key values: - backend=(2d|3d|gfxstream) - Which backend to use for virtio-gpu (determining rendering protocol) - width=INT - The width of the virtual display connected to the virtio-gpu. - height=INT - The height of the virtual display connected to the virtio-gpu. - egl[=true|=false] - If the virtio-gpu backend should use a EGL context for rendering. - glx[=true|=false] - If the virtio-gpu backend should use a GLX context for rendering. - surfaceless[=true|=false] - If the virtio-gpu backend should use a surfaceless context for rendering. - "), - #[cfg(feature = "tpm")] - Argument::flag("software-tpm", "enable a software emulated trusted platform module device"), - Argument::value("evdev", "PATH", "Path to an event device node. The device will be grabbed (unusable from the host) and made available to the guest with the same configuration it shows on the host"), - Argument::value("single-touch", "PATH:WIDTH:HEIGHT", "Path to a socket from where to read single touch input events (such as those from a touchscreen) and write status updates to, optionally followed by width and height (defaults to 800x1280)."), - Argument::value("trackpad", "PATH:WIDTH:HEIGHT", "Path to a socket from where to read trackpad input events and write status updates to, optionally followed by screen width and height (defaults to 800x1280)."), - Argument::value("mouse", "PATH", "Path to a socket from where to read mouse input events and write status updates to."), - Argument::value("keyboard", "PATH", "Path to a socket from where to read keyboard input events and write status updates to."), - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - Argument::flag("split-irqchip", "(EXPERIMENTAL) enable split-irqchip support"), - Argument::value("bios", "PATH", "Path to BIOS/firmware ROM"), - Argument::value("vfio", "PATH", "Path to sysfs of pass through or mdev device"), - #[cfg(feature = "video-decoder")] - Argument::flag("video-decoder", "(EXPERIMENTAL) enable virtio-video decoder device"), - #[cfg(feature = "video-encoder")] - Argument::flag("video-encoder", "(EXPERIMENTAL) enable virtio-video encoder device"), - Argument::value("acpi-table", "PATH", "Path to user provided ACPI table"), - Argument::short_flag('h', "help", "Print help message.")]; + Argument::value("acpi-table", "PATH", "Path to user provided ACPI table."), + Argument::short_flag('h', "help", "Print help message."), + ]; let mut cfg = Config::default(); let match_res = set_arguments(args, &arguments[..], |name, value| { @@ -1542,7 +1831,7 @@ fn resume_vms(args: std::env::Args) -> std::result::Result<(), ()> { fn balloon_vms(mut args: std::env::Args) -> std::result::Result<(), ()> { if args.len() < 2 { print_help("crosvm balloon", "SIZE VM_SOCKET...", &[]); - println!("Set the ballon size of the crosvm instance to `SIZE` bytes."); + println!("Set the balloon size of the crosvm instance to `SIZE` bytes."); return Err(()); } let num_bytes = match args.next().unwrap().parse::<u64>() { @@ -1871,12 +2160,15 @@ fn modify_usb(mut args: std::env::Args) -> std::result::Result<(), ()> { fn print_usage() { print_help("crosvm", "[stop|run]", &[]); println!("Commands:"); - println!(" stop - Stops crosvm instances via their control sockets."); - println!(" run - Start a new crosvm instance."); - println!(" create_qcow2 - Create a new qcow2 disk image file."); - println!(" disk - Manage attached virtual disk devices."); - println!(" usb - Manage attached virtual USB devices."); - println!(" version - Show package version."); + println!(" stop Stops crosvm instances via their control sockets."); + println!(" suspend Suspends crosvm instances via their control sockets."); + println!(" resume Resumes crosvm instances via their control sockets."); + println!(" run Start a new crosvm instance."); + println!(" balloon Set balloon size of crosvm instances via their control sockets."); + println!(" create_qcow2 Create a new qcow2 disk image file."); + println!(" disk Manage attached virtual disk devices."); + println!(" usb Manage attached virtual USB devices."); + println!(" version Show package version."); } fn pkg_version() -> std::result::Result<(), ()> { diff --git a/src/plugin/vcpu.rs b/src/plugin/vcpu.rs index 06e1861..4bd3ea8 100644 --- a/src/plugin/vcpu.rs +++ b/src/plugin/vcpu.rs @@ -322,10 +322,7 @@ enum VcpuRunData<'a> { impl<'a> VcpuRunData<'a> { fn is_write(&self) -> bool { - match self { - VcpuRunData::Write(_) => true, - _ => false, - } + matches!(self, VcpuRunData::Write(_)) } fn as_slice(&self) -> &[u8] { |