@@ -7,7 +7,7 @@ use alloc::boxed::Box;
7
7
use core:: {
8
8
cell:: UnsafeCell ,
9
9
marker:: { PhantomData , PhantomPinned } ,
10
- mem:: MaybeUninit ,
10
+ mem:: { align_of , size_of , MaybeUninit } ,
11
11
ops:: { Deref , DerefMut } ,
12
12
ptr:: NonNull ,
13
13
} ;
@@ -463,3 +463,102 @@ impl<T: LittleEndian + Copy> core::convert::From<T> for LE<T> {
463
463
LE ( value. to_le ( ) )
464
464
}
465
465
}
466
+
467
+ /// Specifies that a type is safely readable from byte slices.
468
+ ///
469
+ /// Not all types can be safely read from byte slices; examples from
470
+ /// <https://doc.rust-lang.org/reference/behavior-considered-undefined.html> include [`bool`] that
471
+ /// must be either `0` or `1`, and [`char`] that cannot be a surrogate or above [`char::MAX`].
472
+ ///
473
+ /// # Safety
474
+ ///
475
+ /// Implementers must ensure that any bit pattern is valid for this type.
476
+ pub unsafe trait FromBytes : Sized {
477
+ /// Converts the given byte slice into a shared reference to [`Self`].
478
+ ///
479
+ /// It fails if the size or alignment requirements are not satisfied.
480
+ fn from_bytes ( data : & [ u8 ] , offset : usize ) -> Option < & Self > {
481
+ if offset > data. len ( ) {
482
+ return None ;
483
+ }
484
+ let data = & data[ offset..] ;
485
+ let ptr = data. as_ptr ( ) ;
486
+ if ptr as usize % align_of :: < Self > ( ) != 0 || data. len ( ) < size_of :: < Self > ( ) {
487
+ return None ;
488
+ }
489
+ // SAFETY: The memory is valid for read because we have a reference to it. We have just
490
+ // checked the minimum size and alignment as well.
491
+ Some ( unsafe { & * ptr. cast ( ) } )
492
+ }
493
+
494
+ /// Converts the given byte slice into a shared slice of [`Self`].
495
+ ///
496
+ /// It fails if the size or alignment requirements are not satisfied.
497
+ fn from_bytes_to_slice ( data : & [ u8 ] ) -> Option < & [ Self ] > {
498
+ let ptr = data. as_ptr ( ) ;
499
+ if ptr as usize % align_of :: < Self > ( ) != 0 {
500
+ return None ;
501
+ }
502
+ // SAFETY: The memory is valid for read because we have a reference to it. We have just
503
+ // checked the minimum alignment as well, and the length of the slice is calculated from
504
+ // the length of `Self`.
505
+ Some ( unsafe { core:: slice:: from_raw_parts ( ptr. cast ( ) , data. len ( ) / size_of :: < Self > ( ) ) } )
506
+ }
507
+ }
508
+
509
+ // SAFETY: All bit patterns are acceptable values of the types below.
510
+ unsafe impl FromBytes for u8 { }
511
+ unsafe impl FromBytes for u16 { }
512
+ unsafe impl FromBytes for u32 { }
513
+ unsafe impl FromBytes for u64 { }
514
+ unsafe impl FromBytes for usize { }
515
+ unsafe impl FromBytes for i8 { }
516
+ unsafe impl FromBytes for i16 { }
517
+ unsafe impl FromBytes for i32 { }
518
+ unsafe impl FromBytes for i64 { }
519
+ unsafe impl FromBytes for isize { }
520
+ unsafe impl < const N : usize , T : FromBytes > FromBytes for [ T ; N ] { }
521
+ unsafe impl < T : FromBytes + Copy + LittleEndian > FromBytes for LE < T > { }
522
+
523
+ /// Derive [`FromBytes`] for the structs defined in the block.
524
+ ///
525
+ /// # Examples
526
+ ///
527
+ /// ```
528
+ /// kernel::derive_readable_from_bytes! {
529
+ /// #[repr(C)]
530
+ /// struct SuperBlock {
531
+ /// a: u16,
532
+ /// _padding: [u8; 6],
533
+ /// b: u64,
534
+ /// }
535
+ ///
536
+ /// #[repr(C)]
537
+ /// struct Inode {
538
+ /// a: u16,
539
+ /// b: u16,
540
+ /// c: u32,
541
+ /// }
542
+ /// }
543
+ /// ```
544
+ #[ macro_export]
545
+ macro_rules! derive_readable_from_bytes {
546
+ ( $( $( #[ $outer: meta] ) * $outerv: vis struct $name: ident {
547
+ $( $( #[ $m: meta] ) * $v: vis $id: ident : $t: ty) ,* $( , ) ?
548
+ } ) * ) => {
549
+ $(
550
+ $( #[ $outer] ) *
551
+ $outerv struct $name {
552
+ $(
553
+ $( #[ $m] ) *
554
+ $v $id: $t,
555
+ ) *
556
+ }
557
+ unsafe impl $crate:: types:: FromBytes for $name { }
558
+ const _: ( ) = {
559
+ const fn is_readable_from_bytes<T : $crate:: types:: FromBytes >( ) { }
560
+ $( is_readable_from_bytes:: <$t>( ) ; ) *
561
+ } ;
562
+ ) *
563
+ } ;
564
+ }
0 commit comments