Эх сурвалжийг харах

multiboot2: get_tag consumes Into<TagTypeId>

Philipp Schuster 2 жил өмнө
parent
commit
ff60f052ca

+ 62 - 9
multiboot2/src/lib.rs

@@ -322,6 +322,8 @@ impl BootInformation {
     /// Public getter to find any Multiboot tag by its type, including
     /// specified and custom ones.
     ///
+    /// The parameter can be of type `u32`, [`TagType`], or [`TagTypeId`].
+    ///
     /// # Specified or Custom Tags
     /// The Multiboot2 specification specifies a list of tags, see [`TagType`].
     /// However, it doesn't forbid to use custom tags. Because of this, there
@@ -331,10 +333,13 @@ impl BootInformation {
     ///
     /// ## Use Custom Tags
     /// The following example shows how you may use this interface to parse custom tags from
-    /// the MBI.
+    /// the MBI. Custom tags must be `Sized`. Hence, they are not allowed to contain a field such
+    /// as `name: [u8]`.
     ///
-    /// ```ignore
+    /// ```rust
+    /// use std::ffi::{c_char, CStr};
     /// use multiboot2::TagTypeId;
+    ///
     /// #[repr(C, align(8))]
     ///     struct CustomTag {
     ///     // new type from the lib: has repr(u32)
@@ -345,8 +350,7 @@ impl BootInformation {
     /// }
     ///
     /// let tag = bi
-    ///     // this function is now public!
-    ///     .get_tag(0x1337.into())
+    ///     .get_tag(0x1337)
     ///     .unwrap()
     ///     // type definition from end user; must be `Sized`!
     ///     .cast_tag::<CustomTag>();
@@ -354,7 +358,8 @@ impl BootInformation {
     /// let str = unsafe { CStr::from_ptr(name).to_str().unwrap() };
     /// assert_eq!(str, "name");
     /// ```
-    pub fn get_tag(&self, typ: TagType) -> Option<&Tag> {
+    pub fn get_tag(&self, typ: impl Into<TagTypeId>) -> Option<&Tag> {
+        let typ = typ.into();
         self.tags().find(|tag| tag.typ == typ)
     }
 
@@ -1548,10 +1553,7 @@ mod tests {
             name: u8,
         }
 
-        let tag = bi
-            .get_tag(CUSTOM_TAG_ID.into())
-            .unwrap()
-            .cast_tag::<CustomTag>();
+        let tag = bi.get_tag(CUSTOM_TAG_ID).unwrap().cast_tag::<CustomTag>();
 
         // strlen without null byte
         let strlen = tag.size as usize - mem::size_of::<CommandLineTag>();
@@ -1559,4 +1561,55 @@ mod tests {
         let name = core::str::from_utf8(bytes).unwrap();
         assert_eq!(name, "name");
     }
+
+    /// Tests that `get_tag` can consume multiple types that implement `Into<TagTypeId>`
+    #[test]
+    fn get_tag_into_variants() {
+        #[repr(C, align(8))]
+        struct Bytes([u8; 32]);
+        let bytes: Bytes = Bytes([
+            32,
+            0,
+            0,
+            0, // total_size
+            0,
+            0,
+            0,
+            0, // reserved
+            TagType::Cmdline.val().to_ne_bytes()[0],
+            TagType::Cmdline.val().to_ne_bytes()[1],
+            TagType::Cmdline.val().to_ne_bytes()[2],
+            TagType::Cmdline.val().to_ne_bytes()[3],
+            13,
+            0,
+            0,
+            0, // tag size
+            110,
+            97,
+            109,
+            101, // ASCII string 'name'
+            0,
+            0,
+            0,
+            0, // null byte + padding
+            0,
+            0,
+            0,
+            0, // end tag type
+            8,
+            0,
+            0,
+            0, // end tag size
+        ]);
+
+        let addr = bytes.0.as_ptr() as usize;
+        let bi = unsafe { load(addr) };
+        let bi = bi.unwrap();
+
+        let _tag = bi.get_tag(TagType::Cmdline).unwrap();
+
+        let _tag = bi.get_tag(1).unwrap();
+
+        let _tag = bi.get_tag(TagTypeId::new(1)).unwrap();
+    }
 }

+ 1 - 1
multiboot2/src/tag_type.rs

@@ -35,7 +35,7 @@ pub enum TagType {
     /// Tag `1`: Additional command line string.
     /// For example `''` or `'--my-custom-option foo --provided by_grub`, if
     /// your GRUB config contains `multiboot2 /boot/multiboot2-binary.elf --my-custom-option foo --provided by_grub`
-    Cmdline, /* 1 */
+    Cmdline,
     /// Tag `2`: Name of the bootloader, e.g. 'GRUB 2.04-1ubuntu44.2'
     BootLoaderName,
     /// Tag `3`: Additional Multiboot modules, which are BLOBs provided in