Skip to content

Commit 1c0de98

Browse files
committed
feat: introducing CopyConstructable to indicate that a struct is constructable from memory just by copying the underlying data
1 parent df4d6be commit 1c0de98

File tree

5 files changed

+66
-92
lines changed

5 files changed

+66
-92
lines changed

raw_struct/src/builtins/array.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use core::{
88

99
use crate::{
1010
Copy,
11+
CopyConstructable,
1112
FromMemoryView,
1213
MemoryDecodeError,
1314
MemoryView,
@@ -31,17 +32,26 @@ impl<T: FromMemoryView> dyn Array<T> {
3132
let offset = (index * mem::size_of::<T>()) as u64;
3233
T::read_object(memory, self.start_address() + offset)
3334
}
35+
}
3436

37+
impl<T: CopyConstructable> dyn Array<T> {
3538
pub fn elements<M: MemoryView>(
3639
&self,
3740
memory: &M,
3841
range: Range<usize>,
39-
) -> Result<Vec<T>, MemoryDecodeError<M::AccessError, T::DecodeError>> {
42+
) -> Result<Vec<T>, M::AccessError> {
4043
let element_count = range.end - range.start;
4144
let mut result = Vec::with_capacity(element_count);
4245

43-
for index in range {
44-
result.push(self.element_at(memory, index)?);
46+
let result_buffer = unsafe {
47+
slice::from_raw_parts_mut(
48+
result.as_mut_ptr() as *mut u8,
49+
element_count * mem::size_of::<T>(),
50+
)
51+
};
52+
memory.read_memory((range.start * mem::size_of::<T>()) as u64, result_buffer)?;
53+
unsafe {
54+
result.set_len(element_count);
4555
}
4656

4757
Ok(result)

raw_struct/src/builtins/ptr.rs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use core::{
99
use crate::{
1010
builtins::Array,
1111
Copy,
12+
CopyConstructable,
1213
FromMemoryView,
1314
MemoryDecodeError,
1415
MemoryView,
@@ -30,19 +31,7 @@ impl<T: ?Sized> Clone for Ptr64<T> {
3031
}
3132
impl<T: ?Sized> marker::Copy for Ptr64<T> {}
3233

33-
impl<T: ?Sized> FromMemoryView for Ptr64<T> {
34-
type DecodeError = <u64 as FromMemoryView>::DecodeError;
35-
36-
fn read_object<M: MemoryView>(
37-
view: &M,
38-
offset: u64,
39-
) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
40-
Ok(Self {
41-
address: u64::read_object(view, offset)?,
42-
_type: Default::default(),
43-
})
44-
}
45-
}
34+
impl<T: ?Sized> CopyConstructable for Ptr64<T> {}
4635

4736
impl<T: ?Sized> Ptr64<T> {
4837
pub fn is_null(&self) -> bool {

raw_struct/src/copy.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use core::{
2-
convert::Infallible,
32
marker,
43
mem::{
54
self,
@@ -10,8 +9,7 @@ use core::{
109
};
1110

1211
use crate::{
13-
FromMemoryView,
14-
MemoryDecodeError,
12+
CopyConstructable,
1513
MemoryView,
1614
OutOfBoundsViolation,
1715
Reference,
@@ -73,17 +71,6 @@ impl<T: SizedViewable> Copy<T> {
7371
}
7472
}
7573

76-
impl<T: SizedViewable> FromMemoryView for Copy<T> {
77-
type DecodeError = Infallible;
78-
79-
fn read_object<M: MemoryView>(
80-
view: &M,
81-
offset: u64,
82-
) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
83-
Self::read_from_memory(view, offset).map_err(MemoryDecodeError::MemoryAccess)
84-
}
85-
}
86-
8774
impl<T> Clone for Copy<T>
8875
where
8976
T: SizedViewable,
@@ -103,6 +90,13 @@ where
10390
{
10491
}
10592

93+
impl<T> CopyConstructable for Copy<T>
94+
where
95+
T: SizedViewable,
96+
T::Implementation<CopyMemory<T::Memory>>: marker::Copy,
97+
{
98+
}
99+
106100
impl<T: SizedViewable> Deref for Copy<T> {
107101
type Target = T::Implementation<CopyMemory<T::Memory>>;
108102

raw_struct/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub use error::{
1010

1111
mod memory;
1212
pub use memory::{
13+
CopyConstructable,
1314
FromMemoryView,
1415
MemoryView,
1516
};

raw_struct/src/memory.rs

Lines changed: 42 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -58,71 +58,51 @@ pub trait FromMemoryView: Sized {
5858
// fn read_boxed(view: &dyn MemoryView, offset: u64) -> Result<Box<Self>, Box<dyn error::ErrorType>>;
5959
}
6060

61-
macro_rules! impl_from_memory_copy {
62-
($type:ty) => {
63-
impl FromMemoryView for $type {
64-
type DecodeError = Infallible;
65-
66-
fn read_object<M: MemoryView>(
67-
view: &M,
68-
offset: u64,
69-
) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
70-
let mut result = MaybeUninit::uninit();
71-
72-
{
73-
let result_memory = unsafe {
74-
slice::from_raw_parts_mut(
75-
result.as_mut_ptr() as *mut u8,
76-
mem::size_of::<$type>(),
77-
)
78-
};
79-
80-
view.read_memory(offset, result_memory)
81-
.map_err(MemoryDecodeError::MemoryAccess)?;
82-
}
83-
84-
Ok(unsafe { result.assume_init() })
85-
}
86-
}
61+
/// Marker trait for types that can be trivially constructed by copying their
62+
/// underlying data.
63+
///
64+
/// For types implementing this trait:
65+
/// - [`FromMemoryView`] is automatically implemented.
66+
/// - The associated [`DecodeError`] is fixed to [`Infallible`], since decoding
67+
/// cannot fail.
68+
pub trait CopyConstructable: Copy {}
69+
70+
impl<T: CopyConstructable> FromMemoryView for T {
71+
type DecodeError = Infallible;
8772

88-
impl<const N: usize> FromMemoryView for [$type; N] {
89-
type DecodeError = Infallible;
90-
91-
fn read_object<M: MemoryView>(
92-
view: &M,
93-
offset: u64,
94-
) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
95-
let mut result = MaybeUninit::uninit();
96-
97-
{
98-
let result_memory = unsafe {
99-
slice::from_raw_parts_mut(
100-
result.as_mut_ptr() as *mut u8,
101-
mem::size_of::<$type>() * N,
102-
)
103-
};
104-
105-
view.read_memory(offset, result_memory)
106-
.map_err(MemoryDecodeError::MemoryAccess)?;
107-
}
108-
109-
Ok(unsafe { result.assume_init() })
110-
}
111-
}
112-
};
73+
fn read_object<M: MemoryView>(
74+
view: &M,
75+
offset: u64,
76+
) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
77+
let mut result = MaybeUninit::uninit();
78+
79+
let result_memory = unsafe {
80+
slice::from_raw_parts_mut(result.as_mut_ptr() as *mut u8, mem::size_of::<T>())
81+
};
82+
83+
view.read_memory(offset, result_memory)
84+
.map_err(MemoryDecodeError::MemoryAccess)?;
85+
86+
Ok(unsafe { result.assume_init() })
87+
}
11388
}
11489

115-
impl_from_memory_copy!(i8);
116-
impl_from_memory_copy!(u8);
117-
impl_from_memory_copy!(i16);
118-
impl_from_memory_copy!(u16);
119-
impl_from_memory_copy!(i32);
120-
impl_from_memory_copy!(u32);
121-
impl_from_memory_copy!(i64);
122-
impl_from_memory_copy!(u64);
123-
124-
impl_from_memory_copy!(f32);
125-
impl_from_memory_copy!(f64);
90+
impl<T: CopyConstructable, const N: usize> CopyConstructable for [T; N] {}
91+
92+
impl CopyConstructable for u8 {}
93+
impl CopyConstructable for i8 {}
94+
95+
impl CopyConstructable for u16 {}
96+
impl CopyConstructable for i16 {}
97+
98+
impl CopyConstructable for u32 {}
99+
impl CopyConstructable for i32 {}
100+
101+
impl CopyConstructable for u64 {}
102+
impl CopyConstructable for i64 {}
103+
104+
impl CopyConstructable for f32 {}
105+
impl CopyConstructable for f64 {}
126106

127107
impl FromMemoryView for bool {
128108
type DecodeError = Infallible;

0 commit comments

Comments
 (0)