@@ -7,7 +7,7 @@ use alloc::boxed::Box;
77use core:: {
88 cell:: UnsafeCell ,
99 marker:: { PhantomData , PhantomPinned } ,
10- mem:: MaybeUninit ,
10+ mem:: { align_of , size_of , MaybeUninit } ,
1111 ops:: { Deref , DerefMut } ,
1212 ptr:: NonNull ,
1313} ;
@@ -463,3 +463,102 @@ impl<T: LittleEndian + Copy> core::convert::From<T> for LE<T> {
463463 LE ( value. to_le ( ) )
464464 }
465465}
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