traits.rs 2.5 KB

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