1use core::{
2 self,
3 convert::Infallible,
4 mem::{
5 self,
6 MaybeUninit,
7 },
8 slice,
9};
10
11use crate::{
12 error::OutOfBoundsViolation,
13 MemoryDecodeError,
14};
15
16pub trait MemoryView {
17 type AccessError;
18
19 fn read_memory(&self, offset: u64, buffer: &mut [u8]) -> Result<(), Self::AccessError>;
20}
21
22impl<M: MemoryView> MemoryView for &M {
23 type AccessError = M::AccessError;
24
25 fn read_memory(&self, offset: u64, buffer: &mut [u8]) -> Result<(), Self::AccessError> {
26 M::read_memory(self, offset, buffer)
27 }
28}
29
30#[cfg(feature = "alloc")]
31impl<M: ?Sized + MemoryView> MemoryView for alloc::sync::Arc<M> {
32 type AccessError = M::AccessError;
33
34 fn read_memory(&self, offset: u64, buffer: &mut [u8]) -> Result<(), Self::AccessError> {
35 M::read_memory(self, offset, buffer)
36 }
37}
38
39impl MemoryView for &[u8] {
40 type AccessError = OutOfBoundsViolation;
41
42 fn read_memory(&self, offset: u64, buffer: &mut [u8]) -> Result<(), Self::AccessError> {
43 let offset = offset as usize;
44 if offset + buffer.len() > self.len() {
45 return Err(OutOfBoundsViolation {
46 access_offset: offset,
47 access_len: buffer.len(),
48
49 src_len: self.len(),
50 });
51 }
52
53 buffer.copy_from_slice(&self[offset..offset + buffer.len()]);
54 Ok(())
55 }
56}
57
58pub trait MemoryViewDereferenceable: MemoryView {
59 fn dereference(&self, address: u64) -> Result<u64, Self::AccessError>;
60}
61
62impl<M: MemoryViewDereferenceable> MemoryViewDereferenceable for &M {
63 fn dereference(&self, address: u64) -> Result<u64, Self::AccessError> {
64 M::dereference(&self, address)
65 }
66}
67
68#[cfg(feature = "alloc")]
69impl<M: ?Sized + MemoryViewDereferenceable> MemoryViewDereferenceable for alloc::sync::Arc<M> {
70 fn dereference(&self, address: u64) -> Result<u64, Self::AccessError> {
71 M::dereference(&self, address)
72 }
73}
74
75pub trait FromMemoryView: Sized {
80 type DecodeError;
81
82 fn read_object<M: MemoryView>(
83 view: &M,
84 offset: u64,
85 ) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>>;
86
87 }
89
90pub trait CopyConstructable: Copy {}
98
99impl<T: CopyConstructable> FromMemoryView for T {
100 type DecodeError = Infallible;
101
102 fn read_object<M: MemoryView>(
103 view: &M,
104 offset: u64,
105 ) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
106 let mut result = MaybeUninit::uninit();
107
108 let result_memory = unsafe {
109 slice::from_raw_parts_mut(result.as_mut_ptr() as *mut u8, mem::size_of::<T>())
110 };
111
112 view.read_memory(offset, result_memory)
113 .map_err(MemoryDecodeError::MemoryAccess)?;
114
115 Ok(unsafe { result.assume_init() })
116 }
117}
118
119impl<T1: CopyConstructable, T2: CopyConstructable> CopyConstructable for (T1, T2) {}
120impl<T: CopyConstructable, const N: usize> CopyConstructable for [T; N] {}
121
122impl CopyConstructable for u8 {}
123impl CopyConstructable for i8 {}
124
125impl CopyConstructable for u16 {}
126impl CopyConstructable for i16 {}
127
128impl CopyConstructable for u32 {}
129impl CopyConstructable for i32 {}
130
131impl CopyConstructable for u64 {}
132impl CopyConstructable for i64 {}
133
134impl CopyConstructable for f32 {}
135impl CopyConstructable for f64 {}
136
137impl FromMemoryView for bool {
138 type DecodeError = Infallible;
139
140 fn read_object<M: MemoryView>(
141 view: &M,
142 offset: u64,
143 ) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
144 let value = u8::read_object(view, offset)?;
145 Ok(value > 0)
146 }
147}
148
149#[cfg(test)]
150mod test {
151 use crate::memory::FromMemoryView;
152
153 #[test]
154 fn test_typing() {
155 let memory = &[0x01u8, 0x00, 0x00, 0x00];
156
157 let x = u32::read_object(&memory.as_slice(), 0x00);
158 assert_eq!(x, Ok(0x01));
159 }
160}