summary refs log tree commit diff
path: root/data_model
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2019-08-05 15:51:46 -0700
committerCommit Bot <commit-bot@chromium.org>2019-08-14 03:44:28 +0000
commit301583c01a64cecdf2e96b66c14442f7b0122f49 (patch)
tree37665008d6b695fae0589f41afcf87ed0cdc49b4 /data_model
parent3d690c6f5324030fc2b041e44f17abfed312fa38 (diff)
downloadcrosvm-301583c01a64cecdf2e96b66c14442f7b0122f49.tar
crosvm-301583c01a64cecdf2e96b66c14442f7b0122f49.tar.gz
crosvm-301583c01a64cecdf2e96b66c14442f7b0122f49.tar.bz2
crosvm-301583c01a64cecdf2e96b66c14442f7b0122f49.tar.lz
crosvm-301583c01a64cecdf2e96b66c14442f7b0122f49.tar.xz
crosvm-301583c01a64cecdf2e96b66c14442f7b0122f49.tar.zst
crosvm-301583c01a64cecdf2e96b66c14442f7b0122f49.zip
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 <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1737723
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'data_model')
-rw-r--r--data_model/src/lib.rs22
1 files changed, 21 insertions, 1 deletions
diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs
index 8288c84..dcca108 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<R: io::Read>(mut read: R) -> io::Result<Self> {
+        // Allocate a Vec<u8> with enough extra space for the worst-case alignment offset.
+        let mut data = vec![0u8; size_of::<Self>() + align_of::<Self>()];
+
+        // Get a u8 slice within data with sufficient alignment for Self.
+        let align_offset = data.as_ptr().align_offset(align_of::<Self>());
+        let mut aligned_data = &mut data[align_offset..align_offset + size_of::<Self>()];
+
+        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`.