Skip to content

Commit

Permalink
Drop Default requirement on ByteValued
Browse files Browse the repository at this point in the history
Since zeros are a valid value for any ByteValued type, we can use
that instead of relying on a Default implementation (which may not be
auto-derivable for some array types).

Further optimizations would be possible if we would have access
to a pointer value into the source data. Then we could also use
ptr::copy_nonoverlapping and avoid pre-initialization altogether. But
changing the API just for that seems a bit excessive.

Signed-off-by: Erik Schilling <[email protected]>
  • Loading branch information
Ablu authored and bonzini committed Dec 14, 2023
1 parent ca6f1b1 commit f765629
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- [[#266](https://github.com/rust-vmm/vm-memory/pull/266)] Derive `Debug` for several
types that were missing it.
- [[#274]] Drop `Default` as requirement for `ByteValued`.

## [v0.13.1]

Expand Down
9 changes: 6 additions & 3 deletions src/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
//! data.

use std::io::{Read, Write};
use std::mem::size_of;
use std::mem::{size_of, MaybeUninit};
use std::result::Result;
use std::slice::{from_raw_parts, from_raw_parts_mut};
use std::sync::atomic::Ordering;
Expand All @@ -31,7 +31,7 @@ use crate::volatile_memory::VolatileSlice;
/// cause undefined behavior.
///
/// Implementing this trait guarantees that it is safe to instantiate the struct with random data.
pub unsafe trait ByteValued: Copy + Default + Send + Sync {
pub unsafe trait ByteValued: Copy + Send + Sync {
/// Converts a slice of raw data into a reference of `Self`.
///
/// The value of `data` is not copied. Instead a reference is made from the given slice. The
Expand Down Expand Up @@ -268,7 +268,10 @@ pub trait Bytes<A> {
///
/// Returns an error if there's not enough data inside the container.
fn read_obj<T: ByteValued>(&self, addr: A) -> Result<T, Self::E> {
let mut result: T = Default::default();
// SAFETY: ByteValued objects must be assignable from a arbitrary byte
// sequence and are mandated to be packed.
// Hence, zeroed memory is a fine initialization.
let mut result: T = unsafe { MaybeUninit::<T>::zeroed().assume_init() };
self.read_slice(result.as_mut_slice(), addr).map(|_| result)
}

Expand Down

0 comments on commit f765629

Please sign in to comment.