@@ -322,6 +322,8 @@ impl BootInformation {
322322 /// Public getter to find any Multiboot tag by its type, including
323323 /// specified and custom ones.
324324 ///
325+ /// The parameter can be of type `u32`, [`TagType`], or [`TagTypeId`].
326+ ///
325327 /// # Specified or Custom Tags
326328 /// The Multiboot2 specification specifies a list of tags, see [`TagType`].
327329 /// However, it doesn't forbid to use custom tags. Because of this, there
@@ -331,10 +333,13 @@ impl BootInformation {
331333 ///
332334 /// ## Use Custom Tags
333335 /// The following example shows how you may use this interface to parse custom tags from
334- /// the MBI.
336+ /// the MBI. Custom tags must be `Sized`. Hence, they are not allowed to contain a field such
337+ /// as `name: [u8]`.
335338 ///
336- /// ```ignore
339+ /// ```rust
340+ /// use std::ffi::{c_char, CStr};
337341 /// use multiboot2::TagTypeId;
342+ ///
338343 /// #[repr(C, align(8))]
339344 /// struct CustomTag {
340345 /// // new type from the lib: has repr(u32)
@@ -345,16 +350,16 @@ impl BootInformation {
345350 /// }
346351 ///
347352 /// let tag = bi
348- /// // this function is now public!
349- /// .get_tag(0x1337.into())
353+ /// .get_tag(0x1337)
350354 /// .unwrap()
351355 /// // type definition from end user; must be `Sized`!
352356 /// .cast_tag::<CustomTag>();
353357 /// let name = &tag.name as *const u8 as *const c_char;
354358 /// let str = unsafe { CStr::from_ptr(name).to_str().unwrap() };
355359 /// assert_eq!(str, "name");
356360 /// ```
357- pub fn get_tag ( & self , typ : TagType ) -> Option < & Tag > {
361+ pub fn get_tag ( & self , typ : impl Into < TagTypeId > ) -> Option < & Tag > {
362+ let typ = typ. into ( ) ;
358363 self . tags ( ) . find ( |tag| tag. typ == typ)
359364 }
360365
@@ -1548,15 +1553,63 @@ mod tests {
15481553 name : u8 ,
15491554 }
15501555
1551- let tag = bi
1552- . get_tag ( CUSTOM_TAG_ID . into ( ) )
1553- . unwrap ( )
1554- . cast_tag :: < CustomTag > ( ) ;
1556+ let tag = bi. get_tag ( CUSTOM_TAG_ID ) . unwrap ( ) . cast_tag :: < CustomTag > ( ) ;
15551557
15561558 // strlen without null byte
15571559 let strlen = tag. size as usize - mem:: size_of :: < CommandLineTag > ( ) ;
15581560 let bytes = unsafe { slice:: from_raw_parts ( ( & tag. name ) as * const u8 , strlen) } ;
15591561 let name = core:: str:: from_utf8 ( bytes) . unwrap ( ) ;
15601562 assert_eq ! ( name, "name" ) ;
15611563 }
1564+
1565+ /// Tests that `get_tag` can consume multiple types that implement `Into<TagTypeId>`
1566+ #[ test]
1567+ fn get_tag_into_variants ( ) {
1568+ #[ repr( C , align( 8 ) ) ]
1569+ struct Bytes ( [ u8 ; 32 ] ) ;
1570+ let bytes: Bytes = Bytes ( [
1571+ 32 ,
1572+ 0 ,
1573+ 0 ,
1574+ 0 , // total_size
1575+ 0 ,
1576+ 0 ,
1577+ 0 ,
1578+ 0 , // reserved
1579+ TagType :: Cmdline . val ( ) . to_ne_bytes ( ) [ 0 ] ,
1580+ TagType :: Cmdline . val ( ) . to_ne_bytes ( ) [ 1 ] ,
1581+ TagType :: Cmdline . val ( ) . to_ne_bytes ( ) [ 2 ] ,
1582+ TagType :: Cmdline . val ( ) . to_ne_bytes ( ) [ 3 ] ,
1583+ 13 ,
1584+ 0 ,
1585+ 0 ,
1586+ 0 , // tag size
1587+ 110 ,
1588+ 97 ,
1589+ 109 ,
1590+ 101 , // ASCII string 'name'
1591+ 0 ,
1592+ 0 ,
1593+ 0 ,
1594+ 0 , // null byte + padding
1595+ 0 ,
1596+ 0 ,
1597+ 0 ,
1598+ 0 , // end tag type
1599+ 8 ,
1600+ 0 ,
1601+ 0 ,
1602+ 0 , // end tag size
1603+ ] ) ;
1604+
1605+ let addr = bytes. 0 . as_ptr ( ) as usize ;
1606+ let bi = unsafe { load ( addr) } ;
1607+ let bi = bi. unwrap ( ) ;
1608+
1609+ let _tag = bi. get_tag ( TagType :: Cmdline ) . unwrap ( ) ;
1610+
1611+ let _tag = bi. get_tag ( 1 ) . unwrap ( ) ;
1612+
1613+ let _tag = bi. get_tag ( TagTypeId :: new ( 1 ) ) . unwrap ( ) ;
1614+ }
15621615}
0 commit comments