Skip to content

Commit 2b7bb6c

Browse files
author
Joanne Chen
committed
Directly implement AsBytes trait for Generic structs [experiemntal].
Attempts to completely remove the AsSliceU8 trait by directly implementing AsBytes for generic structs because of lack of support for generics using derive. Fixes hermit-os#692. Signed-off-by: Joanne Chen <[email protected]>
1 parent 5934f22 commit 2b7bb6c

File tree

7 files changed

+78
-99
lines changed

7 files changed

+78
-99
lines changed

Cargo.lock

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ lock_api = "0.4"
9090
num = { version = "0.4", default-features = false }
9191
num-traits = { version = "0.2", default-features = false }
9292
num-derive = "0.3"
93-
zerocopy = "0.6"
93+
zerocopy = "0.7.0-alpha.3"
9494

9595
[dependencies.smoltcp]
9696
version = "0.9"

src/drivers/fs/virtio_fs.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use alloc::rc::Rc;
22
use alloc::string::{String, ToString};
33
use alloc::vec::Vec;
44

5+
use zerocopy::AsBytes;
6+
57
use self::constants::{FeatureSet, Features};
68
use crate::config::VIRTIO_MAX_QUEUE_SIZE;
79
#[cfg(feature = "pci")]
@@ -12,7 +14,7 @@ use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg};
1214
#[cfg(feature = "pci")]
1315
use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg};
1416
use crate::drivers::virtio::virtqueue::{
15-
AsSliceU8, BuffSpec, BufferToken, Bytes, Virtq, VqIndex, VqSize, VqType,
17+
BuffSpec, BufferToken, Bytes, Virtq, VqIndex, VqSize, VqType,
1618
};
1719
use crate::fs::fuse::{self, FuseInterface};
1820

@@ -168,7 +170,7 @@ impl FuseInterface for VirtioFsDriver {
168170
self.ready_queue.push(tkn);
169171

170172
if let Some(response) = response {
171-
rsp.as_slice_u8_mut()[..response.len()].copy_from_slice(response.as_ref());
173+
rsp.as_bytes_mut()[..response.len()].copy_from_slice(response.as_ref());
172174
}
173175
}
174176
}

src/drivers/virtio/virtqueue/mod.rs

+7-49
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ impl Virtq {
142142
///
143143
/// Structures provided to the Queue must pass this test, otherwise the queue
144144
/// currently panics.
145-
pub fn check_bounds<T: AsSliceU8>(data: &T) -> bool {
146-
let slice = data.as_slice_u8();
145+
pub fn check_bounds<T: AsBytes>(data: &T) -> bool {
146+
let slice = data.as_bytes();
147147

148148
let start_virt = (&slice[0] as *const u8) as usize;
149149
let end_virt = (&slice[slice.len() - 1] as *const u8) as usize;
@@ -443,7 +443,7 @@ impl Virtq {
443443
/// ```
444444
/// Then he must split the structure after the send part and provide the respective part via the send argument and the respective other
445445
/// part via the recv argument.
446-
pub fn prep_transfer_from_raw<T: AsSliceU8 + 'static, K: AsSliceU8 + 'static>(
446+
pub fn prep_transfer_from_raw<T: AsBytes + 'static, K: AsBytes + 'static>(
447447
&self,
448448
rc_self: Rc<Virtq>,
449449
send: Option<(*mut T, BuffSpec<'_>)>,
@@ -519,48 +519,6 @@ impl Virtq {
519519
}
520520
}
521521

522-
/// The trait needs to be implemented on structures which are to be used via the `prep_transfer()` function of virtqueues and for
523-
/// structures which are to be used to write data into buffers of a [BufferToken](BufferToken) via `BufferToken.write()` or
524-
/// `BufferToken.write_seq()`.
525-
///
526-
/// **INFO:*
527-
/// The trait provides a decent default implementation. Please look at the code for details.
528-
/// The provided default implementation computes the size of the given structure via `core::mem::size_of_val(&self)`
529-
/// and then casts the given `*const Self` pointer of the structure into an `*const u8`.
530-
///
531-
/// Users must be really careful, and check, whether the memory representation of the given structure equals
532-
/// the representation the device expects. It is advised to only use `#[repr(C)]` and to check the output
533-
/// of `as_slice_u8` and `as_slice_u8_mut`.
534-
pub trait AsSliceU8 {
535-
/// Retruns the size of the structure
536-
///
537-
/// In case of an unsized structure, the function should returns
538-
/// the exact value of the structure.
539-
fn len(&self) -> usize {
540-
core::mem::size_of_val(self)
541-
}
542-
543-
/// Returns a slice of the given structure.
544-
///
545-
/// ** WARN:**
546-
/// * The slice must be little endian coded in order to be understood by the device
547-
/// * The slice must serialize the actual structure the device expects, as the queue will use
548-
/// the addresses of the slice in order to refer to the structure.
549-
fn as_slice_u8(&self) -> &[u8] {
550-
unsafe { core::slice::from_raw_parts((self as *const _) as *const u8, self.len()) }
551-
}
552-
553-
/// Returns a mutable slice of the given structure.
554-
///
555-
/// ** WARN:**
556-
/// * The slice must be little endian coded in order to be understood by the device
557-
/// * The slice must serialize the actual structure the device expects, as the queue will use
558-
/// the addresses of the slice in order to refer to the structure.
559-
fn as_slice_u8_mut(&mut self) -> &mut [u8] {
560-
unsafe { core::slice::from_raw_parts_mut((self as *const _) as *mut u8, self.len()) }
561-
}
562-
}
563-
564522
/// The [Transfer](Transfer) will be received when a [TransferToken](TransferToken) is dispatched via `TransferToken.dispatch()` or
565523
/// via `TransferToken.dispatch_blocking()`.
566524
///
@@ -1605,18 +1563,18 @@ impl BufferToken {
16051563
/// descriptors.
16061564
/// The `write()` function does NOT take into account the distinct descriptors of a buffer but treats the buffer as a single continuous
16071565
/// memory element and as a result writes `T` or `H` as a slice of bytes into this memory.
1608-
pub fn write<K: AsSliceU8 + ?Sized, H: AsSliceU8 + ?Sized>(
1566+
pub fn write<K: AsBytes + ?Sized, H: AsBytes + ?Sized>(
16091567
mut self,
16101568
send: Option<&K>,
16111569
recv: Option<&H>,
16121570
) -> Result<TransferToken, VirtqError> {
16131571
if let Some(data) = send {
16141572
match self.send_buff.as_mut() {
16151573
Some(buff) => {
1616-
if buff.len() < data.as_slice_u8().len() {
1574+
if buff.len() < data.as_bytes().len() {
16171575
return Err(VirtqError::WriteToLarge(self));
16181576
} else {
1619-
let data_slc = data.as_slice_u8();
1577+
let data_slc = data.as_bytes();
16201578
let mut from = 0usize;
16211579

16221580
for i in 0..buff.num_descr() {
@@ -1640,7 +1598,7 @@ impl BufferToken {
16401598
if let Some(data) = recv {
16411599
match self.recv_buff.as_mut() {
16421600
Some(buff) => {
1643-
let data_slc = data.as_slice_u8();
1601+
let data_slc = data.as_bytes();
16441602

16451603
if buff.len() < data_slc.len() {
16461604
return Err(VirtqError::WriteToLarge(self));

src/drivers/virtio/virtqueue/packed.rs

+20-19
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use core::ptr;
1111
use core::sync::atomic::{fence, Ordering};
1212

1313
use align_address::Align;
14+
use zerocopy::AsBytes;
1415

1516
use self::error::VqPackedError;
1617
use super::super::features::Features;
@@ -20,8 +21,8 @@ use super::super::transport::mmio::{ComCfg, NotifCfg, NotifCtrl};
2021
use super::super::transport::pci::{ComCfg, NotifCfg, NotifCtrl};
2122
use super::error::VirtqError;
2223
use super::{
23-
AsSliceU8, BuffSpec, Buffer, BufferToken, Bytes, DescrFlags, MemDescr, MemPool, Pinned,
24-
Transfer, TransferState, TransferToken, Virtq, VqIndex, VqSize,
24+
BuffSpec, Buffer, BufferToken, Bytes, DescrFlags, MemDescr, MemPool, Pinned, Transfer,
25+
TransferState, TransferToken, Virtq, VqIndex, VqSize,
2526
};
2627
use crate::arch::mm::paging::{BasePageSize, PageSize};
2728
use crate::arch::mm::{paging, VirtAddr};
@@ -1314,7 +1315,7 @@ impl PackedVq {
13141315
}
13151316

13161317
/// See `Virtq.prep_transfer_from_raw()` documentation.
1317-
pub fn prep_transfer_from_raw<T: AsSliceU8 + 'static, K: AsSliceU8 + 'static>(
1318+
pub fn prep_transfer_from_raw<T: AsBytes + 'static, K: AsBytes + 'static>(
13181319
&self,
13191320
master: Rc<Virtq>,
13201321
send: Option<(*mut T, BuffSpec<'_>)>,
@@ -1325,7 +1326,7 @@ impl PackedVq {
13251326
(Some((send_data, send_spec)), None) => {
13261327
match send_spec {
13271328
BuffSpec::Single(size) => {
1328-
let data_slice = unsafe { (*send_data).as_slice_u8() };
1329+
let data_slice = unsafe { (*send_data).as_bytes() };
13291330

13301331
// Buffer must have the right size
13311332
if data_slice.len() != size.into() {
@@ -1358,7 +1359,7 @@ impl PackedVq {
13581359
})
13591360
}
13601361
BuffSpec::Multiple(size_lst) => {
1361-
let data_slice = unsafe { (*send_data).as_slice_u8() };
1362+
let data_slice = unsafe { (*send_data).as_bytes() };
13621363
let mut desc_lst: Vec<MemDescr> = Vec::with_capacity(size_lst.len());
13631364
let mut index = 0usize;
13641365

@@ -1399,7 +1400,7 @@ impl PackedVq {
13991400
})
14001401
}
14011402
BuffSpec::Indirect(size_lst) => {
1402-
let data_slice = unsafe { (*send_data).as_slice_u8() };
1403+
let data_slice = unsafe { (*send_data).as_bytes() };
14031404
let mut desc_lst: Vec<MemDescr> = Vec::with_capacity(size_lst.len());
14041405
let mut index = 0usize;
14051406

@@ -1447,7 +1448,7 @@ impl PackedVq {
14471448
(None, Some((recv_data, recv_spec))) => {
14481449
match recv_spec {
14491450
BuffSpec::Single(size) => {
1450-
let data_slice = unsafe { (*recv_data).as_slice_u8() };
1451+
let data_slice = unsafe { (*recv_data).as_bytes() };
14511452

14521453
// Buffer must have the right size
14531454
if data_slice.len() != size.into() {
@@ -1480,7 +1481,7 @@ impl PackedVq {
14801481
})
14811482
}
14821483
BuffSpec::Multiple(size_lst) => {
1483-
let data_slice = unsafe { (*recv_data).as_slice_u8() };
1484+
let data_slice = unsafe { (*recv_data).as_bytes() };
14841485
let mut desc_lst: Vec<MemDescr> = Vec::with_capacity(size_lst.len());
14851486
let mut index = 0usize;
14861487

@@ -1521,7 +1522,7 @@ impl PackedVq {
15211522
})
15221523
}
15231524
BuffSpec::Indirect(size_lst) => {
1524-
let data_slice = unsafe { (*recv_data).as_slice_u8() };
1525+
let data_slice = unsafe { (*recv_data).as_bytes() };
15251526
let mut desc_lst: Vec<MemDescr> = Vec::with_capacity(size_lst.len());
15261527
let mut index = 0usize;
15271528

@@ -1569,7 +1570,7 @@ impl PackedVq {
15691570
(Some((send_data, send_spec)), Some((recv_data, recv_spec))) => {
15701571
match (send_spec, recv_spec) {
15711572
(BuffSpec::Single(send_size), BuffSpec::Single(recv_size)) => {
1572-
let send_data_slice = unsafe { (*send_data).as_slice_u8() };
1573+
let send_data_slice = unsafe { (*send_data).as_bytes() };
15731574

15741575
// Buffer must have the right size
15751576
if send_data_slice.len() != send_size.into() {
@@ -1584,7 +1585,7 @@ impl PackedVq {
15841585
Err(vq_err) => return Err(vq_err),
15851586
};
15861587

1587-
let recv_data_slice = unsafe { (*recv_data).as_slice_u8() };
1588+
let recv_data_slice = unsafe { (*recv_data).as_bytes() };
15881589

15891590
// Buffer must have the right size
15901591
if recv_data_slice.len() != recv_size.into() {
@@ -1621,7 +1622,7 @@ impl PackedVq {
16211622
})
16221623
}
16231624
(BuffSpec::Single(send_size), BuffSpec::Multiple(recv_size_lst)) => {
1624-
let send_data_slice = unsafe { (*send_data).as_slice_u8() };
1625+
let send_data_slice = unsafe { (*send_data).as_bytes() };
16251626

16261627
// Buffer must have the right size
16271628
if send_data_slice.len() != send_size.into() {
@@ -1636,7 +1637,7 @@ impl PackedVq {
16361637
Err(vq_err) => return Err(vq_err),
16371638
};
16381639

1639-
let recv_data_slice = unsafe { (*recv_data).as_slice_u8() };
1640+
let recv_data_slice = unsafe { (*recv_data).as_bytes() };
16401641
let mut recv_desc_lst: Vec<MemDescr> =
16411642
Vec::with_capacity(recv_size_lst.len());
16421643
let mut index = 0usize;
@@ -1684,7 +1685,7 @@ impl PackedVq {
16841685
})
16851686
}
16861687
(BuffSpec::Multiple(send_size_lst), BuffSpec::Multiple(recv_size_lst)) => {
1687-
let send_data_slice = unsafe { (*send_data).as_slice_u8() };
1688+
let send_data_slice = unsafe { (*send_data).as_bytes() };
16881689
let mut send_desc_lst: Vec<MemDescr> =
16891690
Vec::with_capacity(send_size_lst.len());
16901691
let mut index = 0usize;
@@ -1710,7 +1711,7 @@ impl PackedVq {
17101711
index += usize::from(*byte);
17111712
}
17121713

1713-
let recv_data_slice = unsafe { (*recv_data).as_slice_u8() };
1714+
let recv_data_slice = unsafe { (*recv_data).as_bytes() };
17141715
let mut recv_desc_lst: Vec<MemDescr> =
17151716
Vec::with_capacity(recv_size_lst.len());
17161717
let mut index = 0usize;
@@ -1758,7 +1759,7 @@ impl PackedVq {
17581759
})
17591760
}
17601761
(BuffSpec::Multiple(send_size_lst), BuffSpec::Single(recv_size)) => {
1761-
let send_data_slice = unsafe { (*send_data).as_slice_u8() };
1762+
let send_data_slice = unsafe { (*send_data).as_bytes() };
17621763
let mut send_desc_lst: Vec<MemDescr> =
17631764
Vec::with_capacity(send_size_lst.len());
17641765
let mut index = 0usize;
@@ -1784,7 +1785,7 @@ impl PackedVq {
17841785
index += usize::from(*byte);
17851786
}
17861787

1787-
let recv_data_slice = unsafe { (*recv_data).as_slice_u8() };
1788+
let recv_data_slice = unsafe { (*recv_data).as_bytes() };
17881789

17891790
// Buffer must have the right size
17901791
if recv_data_slice.len() != recv_size.into() {
@@ -1821,7 +1822,7 @@ impl PackedVq {
18211822
})
18221823
}
18231824
(BuffSpec::Indirect(send_size_lst), BuffSpec::Indirect(recv_size_lst)) => {
1824-
let send_data_slice = unsafe { (*send_data).as_slice_u8() };
1825+
let send_data_slice = unsafe { (*send_data).as_bytes() };
18251826
let mut send_desc_lst: Vec<MemDescr> =
18261827
Vec::with_capacity(send_size_lst.len());
18271828
let mut index = 0usize;
@@ -1844,7 +1845,7 @@ impl PackedVq {
18441845
index += usize::from(*byte);
18451846
}
18461847

1847-
let recv_data_slice = unsafe { (*recv_data).as_slice_u8() };
1848+
let recv_data_slice = unsafe { (*recv_data).as_bytes() };
18481849
let mut recv_desc_lst: Vec<MemDescr> =
18491850
Vec::with_capacity(recv_size_lst.len());
18501851
let mut index = 0usize;

0 commit comments

Comments
 (0)