1use super::{MemoryDescriptor, StorageError};
7
8pub trait Memset: MemoryDescriptor {
10 fn memset(&mut self, value: u8, offset: usize, size: usize) -> Result<(), StorageError>;
22}
23
24pub trait Slice: MemoryDescriptor + 'static {
26 unsafe fn as_slice(&self) -> Result<&[u8], StorageError>;
36
37 fn slice(&self, offset: usize, len: usize) -> Result<&[u8], StorageError> {
49 let slice = unsafe { self.as_slice()? };
51
52 if offset.saturating_add(len) > slice.len() {
54 return Err(StorageError::Unsupported("slice out of bounds".into()));
55 }
56
57 slice
58 .get(offset..offset.saturating_add(len))
59 .ok_or_else(|| StorageError::Unsupported("slice out of bounds".into()))
60 }
61
62 fn as_slice_typed<T: Sized>(&self) -> Result<&[T], StorageError> {
72 let bytes = unsafe { self.as_slice()? };
74 let ptr = bytes.as_ptr() as *const T;
75 let elem_size = std::mem::size_of::<T>();
76 if elem_size == 0 {
77 return Err(StorageError::Unsupported(
78 "zero-sized types are not supported".into(),
79 ));
80 }
81 let len = bytes.len() / elem_size;
82
83 if !(bytes.as_ptr() as usize).is_multiple_of(std::mem::align_of::<T>()) {
84 return Err(StorageError::Unsupported(format!(
85 "memory not aligned for type (required alignment: {})",
86 std::mem::align_of::<T>()
87 )));
88 }
89
90 if bytes.len() % elem_size != 0 {
91 return Err(StorageError::Unsupported(format!(
92 "size {} is not a multiple of type size {}",
93 bytes.len(),
94 elem_size
95 )));
96 }
97
98 Ok(unsafe { std::slice::from_raw_parts(ptr, len) })
100 }
101
102 fn slice_typed<T: Sized>(&self, offset: usize, len: usize) -> Result<&[T], StorageError> {
116 let type_size = std::mem::size_of::<T>();
117 let byte_len = len
118 .checked_mul(type_size)
119 .ok_or_else(|| StorageError::Unsupported("length overflow".into()))?;
120
121 let bytes = self.slice(offset, byte_len)?;
122 let ptr = bytes.as_ptr() as *const T;
123
124 if !(bytes.as_ptr() as usize).is_multiple_of(std::mem::align_of::<T>()) {
125 return Err(StorageError::Unsupported(format!(
126 "memory not aligned for type (required alignment: {})",
127 std::mem::align_of::<T>()
128 )));
129 }
130
131 Ok(unsafe { std::slice::from_raw_parts(ptr, len) })
133 }
134}
135
136pub trait SliceMut: MemoryDescriptor + 'static {
138 unsafe fn as_slice_mut(&mut self) -> Result<&mut [u8], StorageError>;
148
149 fn slice_mut(&mut self, offset: usize, len: usize) -> Result<&mut [u8], StorageError> {
161 let slice = unsafe { self.as_slice_mut()? };
163
164 if offset.saturating_add(len) > slice.len() {
166 return Err(StorageError::Unsupported("slice out of bounds".into()));
167 }
168
169 slice
170 .get_mut(offset..offset.saturating_add(len))
171 .ok_or_else(|| StorageError::Unsupported("slice out of bounds".into()))
172 }
173
174 fn as_slice_typed_mut<T: Sized>(&mut self) -> Result<&mut [T], StorageError> {
183 let bytes = unsafe { self.as_slice_mut()? };
185 let ptr = bytes.as_mut_ptr() as *mut T;
186 let len = bytes.len() / std::mem::size_of::<T>();
187
188 if !(bytes.as_ptr() as usize).is_multiple_of(std::mem::align_of::<T>()) {
189 return Err(StorageError::Unsupported(format!(
190 "memory not aligned for type (required alignment: {})",
191 std::mem::align_of::<T>()
192 )));
193 }
194
195 if bytes.len() % std::mem::size_of::<T>() != 0 {
196 return Err(StorageError::Unsupported(format!(
197 "size {} is not a multiple of type size {}",
198 bytes.len(),
199 std::mem::size_of::<T>()
200 )));
201 }
202
203 Ok(unsafe { std::slice::from_raw_parts_mut(ptr, len) })
205 }
206
207 fn slice_typed_mut<T: Sized>(
220 &mut self,
221 offset: usize,
222 len: usize,
223 ) -> Result<&mut [T], StorageError> {
224 let type_size = std::mem::size_of::<T>();
225 let byte_len = len
226 .checked_mul(type_size)
227 .ok_or_else(|| StorageError::Unsupported("length overflow".into()))?;
228
229 let bytes = self.slice_mut(offset, byte_len)?;
230 let ptr = bytes.as_mut_ptr() as *mut T;
231
232 if !(bytes.as_ptr() as usize).is_multiple_of(std::mem::align_of::<T>()) {
233 return Err(StorageError::Unsupported(format!(
234 "memory not aligned for type (required alignment: {})",
235 std::mem::align_of::<T>()
236 )));
237 }
238
239 Ok(unsafe { std::slice::from_raw_parts_mut(ptr, len) })
241 }
242}
243
244#[cfg(test)]
245mod tests {
246 use super::*;
247 use crate::SystemStorage;
248
249 fn create_storage(size: usize) -> SystemStorage {
251 SystemStorage::new(size).expect("allocation failed")
252 }
253
254 #[test]
257 fn test_memset_full_region() {
258 let mut storage = create_storage(1024);
259 storage
260 .memset(0xAB, 0, 1024)
261 .expect("memset should succeed");
262
263 let slice = unsafe { storage.as_slice().expect("as_slice should succeed") };
264 assert!(slice.iter().all(|&b| b == 0xAB));
265 }
266
267 #[test]
268 fn test_memset_partial_region() {
269 let mut storage = create_storage(1024);
270 storage
272 .memset(0x00, 0, 1024)
273 .expect("memset should succeed");
274 storage
276 .memset(0xFF, 100, 200)
277 .expect("memset should succeed");
278
279 let slice = unsafe { storage.as_slice().expect("as_slice should succeed") };
280 assert!(slice[..100].iter().all(|&b| b == 0x00));
282 assert!(slice[100..300].iter().all(|&b| b == 0xFF));
284 assert!(slice[300..].iter().all(|&b| b == 0x00));
286 }
287
288 #[test]
289 fn test_memset_at_end() {
290 let mut storage = create_storage(1024);
291 storage
293 .memset(0x42, 924, 100)
294 .expect("memset should succeed");
295
296 let slice = unsafe { storage.as_slice().expect("as_slice should succeed") };
297 assert!(slice[924..].iter().all(|&b| b == 0x42));
298 }
299
300 #[test]
301 fn test_memset_zero_size() {
302 let mut storage = create_storage(1024);
303 storage
305 .memset(0xFF, 500, 0)
306 .expect("zero-size memset should succeed");
307 }
308
309 #[test]
310 fn test_memset_out_of_bounds() {
311 let mut storage = create_storage(1024);
312 let result = storage.memset(0xFF, 900, 200);
314 assert!(result.is_err());
315 }
316
317 #[test]
318 fn test_memset_offset_overflow() {
319 let mut storage = create_storage(1024);
320 let result = storage.memset(0xFF, usize::MAX, 1);
322 assert!(result.is_err());
323 }
324
325 #[test]
328 fn test_as_slice_full() {
329 let mut storage = create_storage(1024);
330 storage
331 .memset(0xCD, 0, 1024)
332 .expect("memset should succeed");
333
334 let slice = unsafe { storage.as_slice().expect("as_slice should succeed") };
335 assert_eq!(slice.len(), 1024);
336 assert!(slice.iter().all(|&b| b == 0xCD));
337 }
338
339 #[test]
340 fn test_slice_partial() {
341 let mut storage = create_storage(1024);
342 storage
343 .memset(0x00, 0, 1024)
344 .expect("memset should succeed");
345 storage
346 .memset(0xAA, 100, 50)
347 .expect("memset should succeed");
348
349 let partial = storage.slice(100, 50).expect("slice should succeed");
350 assert_eq!(partial.len(), 50);
351 assert!(partial.iter().all(|&b| b == 0xAA));
352 }
353
354 #[test]
355 fn test_slice_at_start() {
356 let storage = create_storage(1024);
357 let slice = storage.slice(0, 100).expect("slice should succeed");
358 assert_eq!(slice.len(), 100);
359 }
360
361 #[test]
362 fn test_slice_at_end() {
363 let storage = create_storage(1024);
364 let slice = storage.slice(924, 100).expect("slice should succeed");
365 assert_eq!(slice.len(), 100);
366 }
367
368 #[test]
369 fn test_slice_zero_length() {
370 let storage = create_storage(1024);
371 let slice = storage
372 .slice(500, 0)
373 .expect("zero-length slice should succeed");
374 assert!(slice.is_empty());
375 }
376
377 #[test]
378 fn test_slice_out_of_bounds() {
379 let storage = create_storage(1024);
380 let result = storage.slice(900, 200);
381 assert!(result.is_err());
382 }
383
384 #[test]
385 fn test_slice_offset_overflow() {
386 let storage = create_storage(1024);
387 let result = storage.slice(usize::MAX, 1);
389 assert!(result.is_err());
390 }
391
392 #[test]
395 fn test_as_slice_typed_u32() {
396 let mut storage = create_storage(1024);
397 storage
399 .memset(0x00, 0, 1024)
400 .expect("memset should succeed");
401
402 let typed: &[u32] = storage
403 .as_slice_typed()
404 .expect("typed slice should succeed");
405 assert_eq!(typed.len(), 256); assert!(typed.iter().all(|&v| v == 0));
407 }
408
409 #[test]
410 fn test_as_slice_typed_u64() {
411 let storage = create_storage(1024);
412 let typed: &[u64] = storage
413 .as_slice_typed()
414 .expect("typed slice should succeed");
415 assert_eq!(typed.len(), 128); }
417
418 #[test]
419 fn test_slice_typed_partial() {
420 let mut storage = create_storage(1024);
421 storage
422 .memset(0x00, 0, 1024)
423 .expect("memset should succeed");
424
425 let typed: &[u32] = storage
427 .slice_typed(0, 10)
428 .expect("typed slice should succeed");
429 assert_eq!(typed.len(), 10);
430 }
431
432 #[test]
433 fn test_slice_typed_with_offset() {
434 let storage = create_storage(1024);
435 let typed: &[u64] = storage
437 .slice_typed(64, 5)
438 .expect("typed slice should succeed");
439 assert_eq!(typed.len(), 5);
440 }
441
442 #[test]
443 fn test_as_slice_typed_zst_error() {
444 let storage = create_storage(1024);
445 let result: Result<&[()], _> = storage.as_slice_typed();
447 assert!(result.is_err());
448 }
449
450 #[test]
451 fn test_as_slice_typed_size_not_multiple() {
452 let storage = create_storage(1023);
454 let result: Result<&[u32], _> = storage.as_slice_typed();
455 assert!(result.is_err());
456 }
457
458 #[test]
459 fn test_slice_typed_length_overflow() {
460 let storage = create_storage(1024);
461 let result: Result<&[u64], _> = storage.slice_typed(0, usize::MAX);
463 assert!(result.is_err());
464 }
465
466 #[test]
467 fn test_slice_typed_out_of_bounds() {
468 let storage = create_storage(1024);
469 let result: Result<&[u64], _> = storage.slice_typed(0, 200);
471 assert!(result.is_err());
472 }
473}