switch from `data_model::DataInit` to `zerocopy`

No behavior change intended.

The `DataInit` trait has been deleted in favor of the `zerocopy` crate,
which doesn't require any unsafe code to use.

Bug: 269356487
Test: m
Change-Id: Ie1ee815ca1beb06b336cb060a651b75c3b02e1c0
diff --git a/apkdmverity/Android.bp b/apkdmverity/Android.bp
index cc54d2e..c4c90cd 100644
--- a/apkdmverity/Android.bp
+++ b/apkdmverity/Android.bp
@@ -14,7 +14,6 @@
         "libapkverify",
         "libbitflags",
         "libclap",
-        "libdata_model",
         "libdm_rust",
         "libitertools",
         "liblibc",
@@ -22,6 +21,7 @@
         "libnum_traits",
         "libscopeguard",
         "libuuid",
+        "libzerocopy",
     ],
     proc_macros: ["libnum_derive"],
     multilib: {
diff --git a/libs/devicemapper/Android.bp b/libs/devicemapper/Android.bp
index 8f9c25c..5332469 100644
--- a/libs/devicemapper/Android.bp
+++ b/libs/devicemapper/Android.bp
@@ -13,10 +13,10 @@
         "libanyhow",
         "libbitflags",
         "liblibc",
-        "libdata_model",
         "libhex",
         "libnix",
         "libuuid",
+        "libzerocopy",
     ],
     multilib: {
         lib32: {
diff --git a/libs/devicemapper/src/crypt.rs b/libs/devicemapper/src/crypt.rs
index 8281b34..36c45c7 100644
--- a/libs/devicemapper/src/crypt.rs
+++ b/libs/devicemapper/src/crypt.rs
@@ -20,10 +20,10 @@
 use crate::DmTargetSpec;
 
 use anyhow::{ensure, Context, Result};
-use data_model::DataInit;
 use std::io::Write;
 use std::mem::size_of;
 use std::path::Path;
+use zerocopy::AsBytes;
 
 const SECTOR_SIZE: u64 = 512;
 
@@ -174,7 +174,7 @@
         header.next = aligned_size as u32;
 
         let mut buf = Vec::with_capacity(aligned_size);
-        buf.write_all(header.as_slice())?;
+        buf.write_all(header.as_bytes())?;
         buf.write_all(body.as_bytes())?;
         buf.write_all(vec![0; padding].as_slice())?;
 
diff --git a/libs/devicemapper/src/lib.rs b/libs/devicemapper/src/lib.rs
index 868ac5a..8d004f9 100644
--- a/libs/devicemapper/src/lib.rs
+++ b/libs/devicemapper/src/lib.rs
@@ -32,12 +32,13 @@
 #![cfg_attr(test, allow(unused))]
 
 use anyhow::{Context, Result};
-use data_model::DataInit;
 use std::fs::{File, OpenOptions};
 use std::io::Write;
 use std::mem::size_of;
 use std::os::unix::io::AsRawFd;
 use std::path::{Path, PathBuf};
+use zerocopy::AsBytes;
+use zerocopy::FromZeroes;
 
 /// Exposes DmCryptTarget & related builder
 pub mod crypt;
@@ -87,7 +88,7 @@
 // `DmTargetSpec` is the header of the data structure for a device-mapper target. When doing the
 // ioctl, one of more `DmTargetSpec` (and its body) are appened to the `DmIoctl` struct.
 #[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, AsBytes, FromZeroes)]
 struct DmTargetSpec {
     sector_start: u64,
     length: u64, // number of 512 sectors
@@ -96,13 +97,9 @@
     target_type: [u8; DM_MAX_TYPE_NAME],
 }
 
-// SAFETY: C struct is safe to be initialized from raw data
-unsafe impl DataInit for DmTargetSpec {}
-
 impl DmTargetSpec {
     fn new(target_type: &str) -> Result<Self> {
-        // safe because the size of the array is the same as the size of the struct
-        let mut spec: Self = *DataInit::from_mut_slice(&mut [0; size_of::<Self>()]).unwrap();
+        let mut spec = Self::new_zeroed();
         spec.target_type.as_mut().write_all(target_type.as_bytes())?;
         Ok(spec)
     }
@@ -110,8 +107,7 @@
 
 impl DmIoctl {
     fn new(name: &str) -> Result<DmIoctl> {
-        // safe because the size of the array is the same as the size of the struct
-        let mut data: Self = *DataInit::from_mut_slice(&mut [0; size_of::<Self>()]).unwrap();
+        let mut data: Self = Self::new_zeroed();
         data.version[0] = DM_VERSION_MAJOR;
         data.version[1] = DM_VERSION_MINOR;
         data.version[2] = DM_VERSION_PATCHLEVEL;
@@ -202,7 +198,7 @@
         }
 
         let mut payload = Vec::with_capacity(payload_size);
-        payload.extend_from_slice(data.as_slice());
+        payload.extend_from_slice(data.as_bytes());
         payload.extend_from_slice(target);
         dm_table_load(self, payload.as_mut_ptr() as *mut DmIoctl)
             .context("failed to load table")?;
diff --git a/libs/devicemapper/src/loopdevice.rs b/libs/devicemapper/src/loopdevice.rs
index 16b5b65..9dc722b 100644
--- a/libs/devicemapper/src/loopdevice.rs
+++ b/libs/devicemapper/src/loopdevice.rs
@@ -25,15 +25,14 @@
 
 use crate::util::*;
 use anyhow::{Context, Result};
-use data_model::DataInit;
 use libc::O_DIRECT;
 use std::fs::{File, OpenOptions};
-use std::mem::size_of;
 use std::os::unix::fs::OpenOptionsExt;
 use std::os::unix::io::AsRawFd;
 use std::path::{Path, PathBuf};
 use std::thread;
 use std::time::{Duration, Instant};
+use zerocopy::FromZeroes;
 
 use crate::loopdevice::sys::*;
 
@@ -122,9 +121,7 @@
         .custom_flags(if direct_io { O_DIRECT } else { 0 })
         .open(&path)
         .context(format!("failed to open {:?}", path.as_ref()))?;
-    // safe because the size of the array is the same as the size of the struct
-    let mut config: loop_config =
-        *DataInit::from_mut_slice(&mut [0; size_of::<loop_config>()]).unwrap();
+    let mut config = loop_config::new_zeroed();
     config.fd = backing_file.as_raw_fd() as u32;
     config.block_size = 4096;
     config.info.lo_offset = offset;
diff --git a/libs/devicemapper/src/loopdevice/sys.rs b/libs/devicemapper/src/loopdevice/sys.rs
index a35eaa9..ce4ef61 100644
--- a/libs/devicemapper/src/loopdevice/sys.rs
+++ b/libs/devicemapper/src/loopdevice/sys.rs
@@ -15,7 +15,7 @@
  */
 
 use bitflags::bitflags;
-use data_model::DataInit;
+use zerocopy::FromZeroes;
 
 // This UAPI is copied and converted from include/uapi/linux/loop.h Note that this module doesn't
 // implement all the features introduced in loop(4). Only the features that are required to support
@@ -28,7 +28,7 @@
 pub const LOOP_CLR_FD: libc::c_ulong = 0x4C01;
 
 #[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, FromZeroes)]
 pub struct loop_config {
     pub fd: u32,
     pub block_size: u32,
@@ -36,11 +36,8 @@
     pub reserved: [u64; 8],
 }
 
-// SAFETY: C struct is safe to be initialized from raw data
-unsafe impl DataInit for loop_config {}
-
 #[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, FromZeroes)]
 pub struct loop_info64 {
     pub lo_device: u64,
     pub lo_inode: u64,
@@ -57,13 +54,12 @@
     pub lo_init: [u64; 2],
 }
 
-// SAFETY: C struct is safe to be initialized from raw data
-unsafe impl DataInit for loop_info64 {}
+#[repr(transparent)]
+#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, FromZeroes)]
+pub struct Flag(u32);
 
 bitflags! {
-    #[repr(transparent)]
-    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-    pub struct Flag: u32 {
+    impl Flag: u32 {
         const LO_FLAGS_READ_ONLY = 1 << 0;
         const LO_FLAGS_AUTOCLEAR = 1 << 2;
         const LO_FLAGS_PARTSCAN = 1 << 3;
diff --git a/libs/devicemapper/src/sys.rs b/libs/devicemapper/src/sys.rs
index 3cecde3..bd1e165 100644
--- a/libs/devicemapper/src/sys.rs
+++ b/libs/devicemapper/src/sys.rs
@@ -15,7 +15,8 @@
  */
 
 use bitflags::bitflags;
-use data_model::DataInit;
+use zerocopy::AsBytes;
+use zerocopy::FromZeroes;
 
 // UAPI for device mapper can be found at include/uapi/linux/dm-ioctl.h
 
@@ -44,7 +45,7 @@
 }
 
 #[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, AsBytes, FromZeroes)]
 pub struct DmIoctl {
     pub version: [u32; 3],
     pub data_size: u32,
@@ -60,9 +61,6 @@
     pub data: [u8; 7],
 }
 
-// SAFETY: C struct is safe to be initialized from raw data
-unsafe impl DataInit for DmIoctl {}
-
 pub const DM_VERSION_MAJOR: u32 = 4;
 pub const DM_VERSION_MINOR: u32 = 0;
 pub const DM_VERSION_PATCHLEVEL: u32 = 0;
@@ -71,10 +69,12 @@
 pub const DM_UUID_LEN: usize = 129;
 pub const DM_MAX_TYPE_NAME: usize = 16;
 
+#[repr(transparent)]
+#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, AsBytes, FromZeroes)]
+pub struct Flag(u32);
+
 bitflags! {
-    #[repr(transparent)]
-    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-    pub struct Flag: u32 {
+    impl Flag: u32 {
         const DM_READONLY_FLAG = 1 << 0;
         const DM_SUSPEND_FLAG = 1 << 1;
         const DM_PERSISTENT_DEV_FLAG = 1 << 3;
diff --git a/libs/devicemapper/src/verity.rs b/libs/devicemapper/src/verity.rs
index e0c5e52..24584f8 100644
--- a/libs/devicemapper/src/verity.rs
+++ b/libs/devicemapper/src/verity.rs
@@ -19,10 +19,10 @@
 // which is then given to `DeviceMapper` to create a mapper device.
 
 use anyhow::{bail, Context, Result};
-use data_model::DataInit;
 use std::io::Write;
 use std::mem::size_of;
 use std::path::Path;
+use zerocopy::AsBytes;
 
 use crate::util::*;
 use crate::DmTargetSpec;
@@ -195,7 +195,7 @@
         header.next = aligned_size as u32;
 
         let mut buf = Vec::with_capacity(aligned_size);
-        buf.write_all(header.as_slice())?;
+        buf.write_all(header.as_bytes())?;
         buf.write_all(body.as_bytes())?;
         buf.write_all(vec![0; padding].as_slice())?;
         Ok(DmVerityTarget(buf.into_boxed_slice()))