Skip to content

Commit 8c37cf7

Browse files
roypatbonzini
authored andcommitted
Add ByteValued::{write_all_to,read_exact_from}
Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
1 parent 9687cad commit 8c37cf7

File tree

1 file changed

+37
-1
lines changed

1 file changed

+37
-1
lines changed

src/bytes.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! Define the `ByteValued` trait to mark that it is safe to instantiate the struct with random
1212
//! data.
1313
14+
use std::io::{Read, Write};
1415
use std::mem::{size_of, MaybeUninit};
1516
use std::result::Result;
1617
use std::slice::{from_raw_parts, from_raw_parts_mut};
@@ -116,6 +117,20 @@ pub unsafe trait ByteValued: Copy + Send + Sync {
116117
fn as_bytes(&mut self) -> VolatileSlice {
117118
VolatileSlice::from(self.as_mut_slice())
118119
}
120+
121+
/// Writes this [`ByteValued`]'s byte representation to the given [`Write`] impl.
122+
fn write_all_to<W: Write>(&self, mut writer: W) -> Result<(), std::io::Error> {
123+
writer.write_all(self.as_slice())
124+
}
125+
126+
/// Constructs an instance of this [`ByteValued`] by reading from the given [`Read`] impl.
127+
fn read_exact_from<R: Read>(mut reader: R) -> Result<Self, std::io::Error> {
128+
// SAFETY: ByteValued objects must be assignable from arbitrary byte
129+
// sequences and are mandated to be packed.
130+
// Hence, zeroed memory is a fine initialization.
131+
let mut result: Self = unsafe { MaybeUninit::<Self>::zeroed().assume_init() };
132+
reader.read_exact(result.as_mut_slice()).map(|_| result)
133+
}
119134
}
120135

121136
macro_rules! byte_valued_array {
@@ -407,6 +422,7 @@ pub(crate) mod tests {
407422

408423
use std::cell::RefCell;
409424
use std::fmt::Debug;
425+
use std::io::ErrorKind;
410426
use std::mem::align_of;
411427

412428
// Helper method to test atomic accesses for a given `b: Bytes` that's supposed to be
@@ -607,7 +623,7 @@ pub(crate) mod tests {
607623
}
608624

609625
#[repr(C)]
610-
#[derive(Copy, Clone, Default)]
626+
#[derive(Copy, Clone, Default, Debug)]
611627
struct S {
612628
a: u32,
613629
b: u32,
@@ -623,4 +639,24 @@ pub(crate) mod tests {
623639
assert_eq!(s.a, 0);
624640
assert_eq!(s.b, 0x0101_0101);
625641
}
642+
643+
#[test]
644+
fn test_byte_valued_io() {
645+
let a: [u8; 8] = [0, 0, 0, 0, 1, 1, 1, 1];
646+
647+
let result = S::read_exact_from(&a[1..]);
648+
assert_eq!(result.unwrap_err().kind(), ErrorKind::UnexpectedEof);
649+
650+
let s = S::read_exact_from(&a[..]).unwrap();
651+
assert_eq!(s.a, 0);
652+
assert_eq!(s.b, 0x0101_0101);
653+
654+
let mut b = Vec::new();
655+
s.write_all_to(&mut b).unwrap();
656+
assert_eq!(a.as_ref(), b.as_slice());
657+
658+
let mut b = [0; 7];
659+
let result = s.write_all_to(b.as_mut_slice());
660+
assert_eq!(result.unwrap_err().kind(), ErrorKind::WriteZero);
661+
}
626662
}

0 commit comments

Comments
 (0)