traits.rs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. //! Module for the helper trait [`StructAsBytes`].
  2. use crate::{
  3. AddressHeaderTag, ConsoleHeaderTag, EfiBootServiceHeaderTag, EndHeaderTag,
  4. EntryAddressHeaderTag, EntryEfi32HeaderTag, EntryEfi64HeaderTag, FramebufferHeaderTag,
  5. InformationRequestHeaderTag, ModuleAlignHeaderTag, Multiboot2BasicHeader, RelocatableHeaderTag,
  6. };
  7. use alloc::vec::Vec;
  8. use core::mem::size_of;
  9. /// Trait for all tags that helps to create a byte array from the tag.
  10. /// Useful in builders to construct a byte vector that
  11. /// represents the Multiboot2 header with all its tags.
  12. pub(crate) trait StructAsBytes: Sized {
  13. /// Returns the size in bytes of the struct, as known during compile
  14. /// time. This doesn't use read the "size" field of tags.
  15. fn byte_size(&self) -> usize {
  16. size_of::<Self>()
  17. }
  18. /// Returns a byte pointer to the begin of the struct.
  19. fn as_ptr(&self) -> *const u8 {
  20. self as *const Self as *const u8
  21. }
  22. /// Returns the structure as a vector of its bytes.
  23. /// The length is determined by [`Self::byte_size`].
  24. fn struct_as_bytes(&self) -> Vec<u8> {
  25. let ptr = self.as_ptr();
  26. let bytes = unsafe { core::slice::from_raw_parts(ptr, self.byte_size()) };
  27. Vec::from(bytes)
  28. }
  29. }
  30. impl StructAsBytes for AddressHeaderTag {}
  31. impl StructAsBytes for ConsoleHeaderTag {}
  32. impl StructAsBytes for EndHeaderTag {}
  33. impl StructAsBytes for EntryEfi32HeaderTag {}
  34. impl StructAsBytes for EntryEfi64HeaderTag {}
  35. impl StructAsBytes for EntryAddressHeaderTag {}
  36. impl StructAsBytes for FramebufferHeaderTag {}
  37. impl StructAsBytes for InformationRequestHeaderTag<0> {}
  38. impl StructAsBytes for ModuleAlignHeaderTag {}
  39. impl StructAsBytes for RelocatableHeaderTag {}
  40. impl StructAsBytes for EfiBootServiceHeaderTag {}
  41. impl StructAsBytes for Multiboot2BasicHeader {}
  42. #[cfg(test)]
  43. mod tests {
  44. use super::*;
  45. #[test]
  46. #[cfg_attr(miri, ignore)]
  47. fn test_as_bytes() {
  48. struct Foobar {
  49. a: u32,
  50. b: u8,
  51. c: u128,
  52. }
  53. impl StructAsBytes for Foobar {}
  54. #[allow(clippy::disallowed_names)]
  55. let foo = Foobar {
  56. a: 11,
  57. b: 22,
  58. c: 33,
  59. };
  60. let bytes = foo.struct_as_bytes();
  61. let foo_from_bytes = unsafe { (bytes.as_ptr() as *const Foobar).as_ref().unwrap() };
  62. assert_eq!(bytes.len(), size_of::<Foobar>());
  63. assert_eq!(foo.a, foo_from_bytes.a);
  64. assert_eq!(foo.b, foo_from_bytes.b);
  65. assert_eq!(foo.c, foo_from_bytes.c);
  66. }
  67. }