From 301583c01a64cecdf2e96b66c14442f7b0122f49 Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Mon, 5 Aug 2019 15:51:46 -0700 Subject: [PATCH] data_model: allow reading structs from io::Read Add a from_reader() function that allows reading a DataInit type from a std::io::Read stream. BUG=None TEST=./build_test Change-Id: Iaacae489db2c265d6b1a9af6e18c11c9e6efe354 Signed-off-by: Daniel Verkamp Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1737723 Tested-by: kokoro Reviewed-by: Zach Reizner --- data_model/src/lib.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index 8288c84eaf..dcca108f7f 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -use std::mem::size_of; +use std::io; +use std::mem::{align_of, size_of}; use std::slice::{from_raw_parts, from_raw_parts_mut}; /// Types for which it is safe to initialize from raw data. @@ -64,6 +65,25 @@ pub unsafe trait DataInit: Copy + Send + Sync { } } + /// Creates an instance of `Self` by copying raw data from an io::Read stream. + fn from_reader(mut read: R) -> io::Result { + // Allocate a Vec with enough extra space for the worst-case alignment offset. + let mut data = vec![0u8; size_of::() + align_of::()]; + + // Get a u8 slice within data with sufficient alignment for Self. + let align_offset = data.as_ptr().align_offset(align_of::()); + let mut aligned_data = &mut data[align_offset..align_offset + size_of::()]; + + read.read_exact(&mut aligned_data)?; + match Self::from_slice(&aligned_data) { + Some(obj) => Ok(*obj), + None => Err(io::Error::new( + io::ErrorKind::InvalidData, + "from_slice failed", + )), + } + } + /// Converts a reference to `self` into a slice of bytes. /// /// The value of `self` is not copied. Instead, the slice is made from a reference to `self`.