Skip to content

Commit 3073fa5

Browse files
committed
feat: (breaking change) require explicit implementation of MemoryView and do not implicitly implement it for all Copy types
1 parent d8a4fda commit 3073fa5

File tree

11 files changed

+146
-66
lines changed

11 files changed

+146
-66
lines changed

examples/dyn_memory/src/main.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,22 @@ use std::{
99
use raw_struct::{
1010
raw_struct,
1111
Copy,
12+
CopyMemoryView,
13+
Copyable,
1214
FromMemoryView,
13-
Viewable,
1415
};
1516

1617
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
1718
/*
1819
* Note:
1920
* Accessing all the container entries evaluates in release mode to just a mov instruction.
2021
*/
21-
let buffer = [0x1122u64, 0x8877, 0x9988];
22+
let buffer = CopyMemoryView::new([0x1122u64, 0x8877, 0x9988]);
2223
let object = Copy::<dyn Container<u64>>::read_object(&buffer, 0x00)?;
2324

2425
println!(
2526
"Memory size: 0x{:X}",
26-
<dyn Container::<u64> as Viewable>::MEMORY_SIZE
27+
<dyn Container::<u64> as Copyable>::MEMORY_SIZE
2728
);
2829
println!("Vat a = 0x{:X}", object.var_a()?);
2930
println!("Inner = 0x{:X}", object.inner()?);

examples/minimal/src/main.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,20 @@ use raw_struct::{
1212
},
1313
raw_struct,
1414
Copy,
15+
CopyMemoryView,
16+
Copyable,
1517
FromMemoryView,
1618
Reference,
17-
Viewable,
1819
};
1920

2021
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
2122
let mut memory = [0u8; 0x40];
2223
memory[0..4].copy_from_slice(&0x6Fu32.to_le_bytes());
2324
memory[4..8].copy_from_slice(&0x99u32.to_le_bytes());
2425

25-
println!("{}", <dyn MyStruct as Viewable>::MEMORY_SIZE);
26+
println!("{}", <dyn MyStruct as Copyable>::MEMORY_SIZE);
2627

27-
let memory = Arc::new(memory);
28+
let memory = Arc::new(CopyMemoryView::new(memory));
2829
{
2930
let object = Reference::<dyn MyStruct, _>::new(memory.clone(), 0x00);
3031
println!("field_a = {}", object.field_a()?);

raw_struct/src/builtins/array.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,21 @@ use alloc::{
44
vec::Vec,
55
};
66
use core::{
7-
marker::{
8-
self,
9-
},
7+
self,
8+
marker,
109
mem,
1110
ops::Range,
1211
slice,
1312
};
1413

1514
use crate::{
15+
view::Copyable,
1616
AccessError,
1717
AccessMode,
1818
Copy,
1919
FromMemoryView,
2020
MemoryView,
2121
Reference,
22-
Viewable,
2322
};
2423

2524
#[allow(clippy::len_without_is_empty)]
@@ -79,7 +78,8 @@ impl<T: FromMemoryView> dyn Array<T> {
7978
}
8079
}
8180

82-
impl<T: ?Sized + Viewable> dyn Array<T> {
81+
/* We need T to be a Copyable as we need to know the element size */
82+
impl<T: ?Sized + Copyable> dyn Array<T> {
8383
pub fn element_reference<E: 'static>(
8484
&self,
8585
memory: Arc<dyn MemoryView<Error = E>>,
@@ -103,15 +103,15 @@ impl<T: ?Sized + Viewable> dyn Array<T> {
103103
}
104104
}
105105

106-
impl<T: ?Sized + Viewable> dyn Array<T>
107-
where
108-
T::Instance<T::Memory>: marker::Copy,
109-
{
106+
impl<T: ?Sized + Copyable> dyn Array<T> {
110107
pub fn element_copy<E>(
111108
&self,
112109
memory: &dyn MemoryView<Error = E>,
113110
index: usize,
114-
) -> Result<Copy<T>, AccessError<E>> {
111+
) -> Result<Copy<T>, AccessError<E>>
112+
where
113+
Copy<T>: marker::Copy,
114+
{
115115
let offset = (index * T::MEMORY_SIZE) as u64;
116116
Copy::read_object(memory, self.start_address() + offset).map_err(|err| AccessError {
117117
source: err,

raw_struct/src/builtins/ptr.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use super::{
1313
Array,
1414
};
1515
use crate::{
16+
view::Copyable,
1617
AccessError,
1718
AccessMode,
1819
Copy,
@@ -89,7 +90,9 @@ impl<T: ?Sized + Viewable> Ptr64<T> {
8990
None
9091
}
9192
}
93+
}
9294

95+
impl<T: ?Sized + Copyable> Ptr64<T> {
9396
/// Create a copy of the value the pointer points to
9497
#[must_use = "copied result must be used"]
9598
pub fn value_copy<E>(

raw_struct/src/copy.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,22 @@ use core::{
44
ops::Deref,
55
};
66

7-
use crate::view::Viewable;
7+
use crate::{
8+
memory::CopyMemoryView,
9+
view::Copyable,
10+
ViewableBase,
11+
};
812

913
/// A Copy represents an owned copy of the struct binary contents
1014
#[repr(transparent)]
11-
pub struct Copy<T: ?Sized + Viewable> {
12-
inner: T::Instance<T::Memory>,
15+
pub struct Copy<T: ?Sized + Copyable> {
16+
inner: T::Instance<CopyMemoryView<T::Memory>>,
1317
}
1418

15-
impl<T: ?Sized + Viewable> Copy<T> {
19+
impl<T: ?Sized + Copyable> Copy<T> {
1620
pub fn new(inner: T::Memory) -> Self {
1721
Self {
18-
inner: T::create_view(inner),
22+
inner: T::create_view(CopyMemoryView::new(inner)),
1923
}
2024
}
2125

@@ -25,10 +29,16 @@ impl<T: ?Sized + Viewable> Copy<T> {
2529
pub unsafe fn new_zerod() -> Self {
2630
Self::new(MaybeUninit::zeroed().assume_init())
2731
}
32+
33+
// pub fn read_object<E>(view: &dyn MemoryView<Error = E>, offset: u64) -> Result<Self, E> {
34+
// Ok(Self {
35+
// inner: T::create_view(CopyMemoryView::<T::Memory>::read_object(view, offset)?),
36+
// })
37+
// }
2838
}
2939

30-
impl<T: ?Sized + Viewable> Deref for Copy<T> {
31-
type Target = T::Instance<T::Memory>;
40+
impl<T: ?Sized + Copyable> Deref for Copy<T> {
41+
type Target = T::Instance<CopyMemoryView<T::Memory>>;
3242

3343
fn deref(&self) -> &Self::Target {
3444
&self.inner
@@ -37,19 +47,18 @@ impl<T: ?Sized + Viewable> Deref for Copy<T> {
3747

3848
impl<T> Clone for Copy<T>
3949
where
40-
T: ?Sized + Viewable,
41-
T::Instance<T::Memory>: Clone,
50+
T: ?Sized + Copyable,
4251
{
4352
fn clone(&self) -> Self {
4453
Self {
45-
inner: self.inner.clone(),
54+
inner: T::create_view(self.inner.object_memory().clone()),
4655
}
4756
}
4857
}
4958

5059
impl<T> marker::Copy for Copy<T>
5160
where
52-
T: ?Sized + Viewable,
53-
T::Instance<T::Memory>: marker::Copy,
61+
T: ?Sized + Copyable,
62+
T::Instance<CopyMemoryView<T::Memory>>: marker::Copy,
5463
{
5564
}

raw_struct/src/error.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ use alloc::{
22
borrow::Cow,
33
format,
44
};
5-
#[cfg(feature = "no_std")]
6-
pub use core::error::Error as ErrorType;
75
use core::{
86
convert::Infallible,
9-
fmt,
7+
fmt::{
8+
self,
9+
Debug,
10+
},
1011
};
11-
#[cfg(not(feature = "no_std"))]
12-
pub use std::error::Error as ErrorType;
1312

1413
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
1514
pub enum AccessMode {
@@ -35,7 +34,11 @@ impl fmt::Display for AccessViolation {
3534
}
3635
}
3736

38-
impl ErrorType for AccessViolation {}
37+
#[cfg(feature = "no_std")]
38+
impl core::error::Error for AccessViolation {}
39+
40+
#[cfg(not(feature = "no_std"))]
41+
impl std::error::Error for AccessViolation {}
3942

4043
#[derive(Debug)]
4144
pub struct AccessError<S = Infallible> {
@@ -67,8 +70,16 @@ impl<S: fmt::Display> fmt::Display for AccessError<S> {
6770
}
6871
}
6972

70-
impl<S: ErrorType + 'static> ErrorType for AccessError<S> {
71-
fn source(&self) -> Option<&(dyn ErrorType + 'static)> {
73+
#[cfg(feature = "no_std")]
74+
impl<S: core::error::Error + 'static> core::error::Error for AccessError<S> {
75+
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
76+
Some(&self.source)
77+
}
78+
}
79+
80+
#[cfg(not(feature = "no_std"))]
81+
impl<S: std::error::Error + 'static> std::error::Error for AccessError<S> {
82+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
7283
Some(&self.source)
7384
}
7485
}

raw_struct/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ pub use error::{
1414
AccessViolation,
1515
};
1616
pub use memory::{
17+
CopyMemoryView,
1718
FromMemoryView,
1819
MemoryView,
1920
};
2021
pub use raw_struct_derive::raw_struct;
2122
pub use reference::Reference;
2223
pub use view::{
24+
Copyable,
2325
Viewable,
2426
ViewableBase,
2527
ViewableInstance,

raw_struct/src/memory.rs

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::{
2+
marker,
23
mem::{
34
self,
45
MaybeUninit,
@@ -14,42 +15,88 @@ pub trait MemoryView: Send + Sync {
1415
fn read_memory(&self, offset: u64, buffer: &mut [u8]) -> Result<(), Self::Error>;
1516
}
1617

17-
/*
18-
* Attention:
19-
* This is dangarous MemoryView should only explicitly be implemented because
20-
* this implementation allows to read from &0 (aka references) as 8 byte values.
21-
*/
22-
impl<T: Copy + Send + Sync> MemoryView for T {
18+
impl MemoryView for &[u8] {
2319
type Error = AccessViolation;
2420

2521
fn read_memory(&self, offset: u64, buffer: &mut [u8]) -> Result<(), Self::Error> {
26-
let src_buffer = unsafe {
27-
core::slice::from_raw_parts(self as *const _ as *const u8, core::mem::size_of_val(self))
28-
};
29-
3022
let offset = offset as usize;
31-
if offset + buffer.len() > src_buffer.len() {
23+
if offset + buffer.len() > self.len() {
3224
return Err(AccessViolation);
3325
}
3426

35-
buffer.copy_from_slice(&src_buffer[offset..offset + buffer.len()]);
27+
buffer.copy_from_slice(&self[offset..offset + buffer.len()]);
3628
Ok(())
3729
}
3830
}
3931

32+
#[derive(Clone)]
33+
pub struct CopyMemoryView<T: marker::Copy> {
34+
inner: T,
35+
}
36+
37+
impl<T: marker::Copy> CopyMemoryView<T> {
38+
pub fn new(value: T) -> Self {
39+
Self { inner: value }
40+
}
41+
}
42+
43+
impl<T: marker::Copy + Send + Sync> MemoryView for CopyMemoryView<T> {
44+
type Error = AccessViolation;
45+
46+
fn read_memory(&self, offset: u64, buffer: &mut [u8]) -> Result<(), Self::Error> {
47+
let src_buffer = unsafe {
48+
core::slice::from_raw_parts(
49+
&self.inner as *const _ as *const u8,
50+
core::mem::size_of_val(self),
51+
)
52+
};
53+
54+
src_buffer.read_memory(offset, buffer)
55+
}
56+
}
57+
58+
impl<T: marker::Copy + Send + Sync> From<T> for CopyMemoryView<T> {
59+
fn from(value: T) -> Self {
60+
Self::new(value)
61+
}
62+
}
63+
64+
impl<T: marker::Copy> marker::Copy for CopyMemoryView<T> {}
65+
4066
pub trait FromMemoryView: Sized {
67+
/// Read an instance of this byte by byte and interpret it as this.
4168
fn read_object<E>(view: &dyn MemoryView<Error = E>, offset: u64) -> Result<Self, E>;
42-
// fn read_boxed(view: &dyn MemoryView, offset: u64) -> Result<Box<Self>, Box<dyn error::ErrorType>>;
69+
70+
/// Read an instance of this byte by byte into heap memory
71+
fn read_boxed<E>(view: &dyn MemoryView<Error = E>, offset: u64) -> Result<Box<Self>, E>;
4372
}
4473

4574
impl<T: Copy> FromMemoryView for T {
4675
fn read_object<E>(view: &dyn MemoryView<Error = E>, offset: u64) -> Result<Self, E> {
4776
let mut result = MaybeUninit::uninit();
4877
let size = mem::size_of_val(&result);
4978

50-
let buffer = unsafe { slice::from_raw_parts_mut(&mut result as *mut _ as *mut u8, size) };
51-
view.read_memory(offset, buffer)?;
79+
// Safety:
80+
// As T is marker::Copy it is safe to access it's memory byte by byte
81+
let result = unsafe {
82+
let buffer = slice::from_raw_parts_mut(&mut result as *mut _ as *mut u8, size);
83+
view.read_memory(offset, buffer)?;
84+
result.assume_init()
85+
};
86+
Ok(result)
87+
}
88+
89+
fn read_boxed<E>(view: &dyn MemoryView<Error = E>, offset: u64) -> Result<Box<Self>, E> {
90+
let mut result = Box::new_uninit();
91+
let size = mem::size_of_val(&result);
5292

53-
Ok(unsafe { result.assume_init() })
93+
// Safety:
94+
// As T is marker::Copy it is safe to access it's memory byte by byte
95+
let result = unsafe {
96+
let buffer = slice::from_raw_parts_mut(result.as_mut_ptr() as *mut _ as *mut u8, size);
97+
view.read_memory(offset, buffer)?;
98+
result.assume_init()
99+
};
100+
Ok(result)
54101
}
55102
}

0 commit comments

Comments
 (0)