@@ -317,6 +317,8 @@ impl BootInformation {
317317 /// Public getter to find any Multiboot tag by its type, including
318318 /// specified and custom ones.
319319 ///
320+ /// The parameter can be of type `u32`, [`TagType`], or [`TagTypeId`].
321+ ///
320322 /// # Specified or Custom Tags
321323 /// The Multiboot2 specification specifies a list of tags, see [`TagType`].
322324 /// However, it doesn't forbid to use custom tags. Because of this, there
@@ -326,10 +328,13 @@ impl BootInformation {
326328 ///
327329 /// ## Use Custom Tags
328330 /// The following example shows how you may use this interface to parse custom tags from
329- /// the MBI.
331+ /// the MBI. Custom tags must be `Sized`. Hence, they are not allowed to contain a field such
332+ /// as `name: [u8]`.
330333 ///
331- /// ```ignore
334+ /// ```rust
335+ /// use std::ffi::{c_char, CStr};
332336 /// use multiboot2::TagTypeId;
337+ ///
333338 /// #[repr(C, align(8))]
334339 /// struct CustomTag {
335340 /// // new type from the lib: has repr(u32)
@@ -340,16 +345,16 @@ impl BootInformation {
340345 /// }
341346 ///
342347 /// let tag = bi
343- /// // this function is now public!
344- /// .get_tag(0x1337.into())
348+ /// .get_tag(0x1337)
345349 /// .unwrap()
346350 /// // type definition from end user; must be `Sized`!
347351 /// .cast_tag::<CustomTag>();
348352 /// let name = &tag.name as *const u8 as *const c_char;
349353 /// let str = unsafe { CStr::from_ptr(name).to_str().unwrap() };
350354 /// assert_eq!(str, "name");
351355 /// ```
352- pub fn get_tag ( & self , typ : TagType ) -> Option < & Tag > {
356+ pub fn get_tag ( & self , typ : impl Into < TagTypeId > ) -> Option < & Tag > {
357+ let typ = typ. into ( ) ;
353358 self . tags ( ) . find ( |tag| tag. typ == typ)
354359 }
355360
@@ -1537,15 +1542,63 @@ mod tests {
15371542 name : u8 ,
15381543 }
15391544
1540- let tag = bi
1541- . get_tag ( CUSTOM_TAG_ID . into ( ) )
1542- . unwrap ( )
1543- . cast_tag :: < CustomTag > ( ) ;
1545+ let tag = bi. get_tag ( CUSTOM_TAG_ID ) . unwrap ( ) . cast_tag :: < CustomTag > ( ) ;
15441546
15451547 // strlen without null byte
15461548 let strlen = tag. size as usize - mem:: size_of :: < CommandLineTag > ( ) ;
15471549 let bytes = unsafe { slice:: from_raw_parts ( ( & tag. name ) as * const u8 , strlen) } ;
15481550 let name = core:: str:: from_utf8 ( bytes) . unwrap ( ) ;
15491551 assert_eq ! ( name, "name" ) ;
15501552 }
1553+
1554+ /// Tests that `get_tag` can consume multiple types that implement `Into<TagTypeId>`
1555+ #[ test]
1556+ fn get_tag_into_variants ( ) {
1557+ #[ repr( C , align( 8 ) ) ]
1558+ struct Bytes ( [ u8 ; 32 ] ) ;
1559+ let bytes: Bytes = Bytes ( [
1560+ 32 ,
1561+ 0 ,
1562+ 0 ,
1563+ 0 , // total_size
1564+ 0 ,
1565+ 0 ,
1566+ 0 ,
1567+ 0 , // reserved
1568+ TagType :: Cmdline . val ( ) . to_ne_bytes ( ) [ 0 ] ,
1569+ TagType :: Cmdline . val ( ) . to_ne_bytes ( ) [ 1 ] ,
1570+ TagType :: Cmdline . val ( ) . to_ne_bytes ( ) [ 2 ] ,
1571+ TagType :: Cmdline . val ( ) . to_ne_bytes ( ) [ 3 ] ,
1572+ 13 ,
1573+ 0 ,
1574+ 0 ,
1575+ 0 , // tag size
1576+ 110 ,
1577+ 97 ,
1578+ 109 ,
1579+ 101 , // ASCII string 'name'
1580+ 0 ,
1581+ 0 ,
1582+ 0 ,
1583+ 0 , // null byte + padding
1584+ 0 ,
1585+ 0 ,
1586+ 0 ,
1587+ 0 , // end tag type
1588+ 8 ,
1589+ 0 ,
1590+ 0 ,
1591+ 0 , // end tag size
1592+ ] ) ;
1593+
1594+ let addr = bytes. 0 . as_ptr ( ) as usize ;
1595+ let bi = unsafe { load ( addr) } ;
1596+ let bi = bi. unwrap ( ) ;
1597+
1598+ let _tag = bi. get_tag ( TagType :: Cmdline ) . unwrap ( ) ;
1599+
1600+ let _tag = bi. get_tag ( 1 ) . unwrap ( ) ;
1601+
1602+ let _tag = bi. get_tag ( TagTypeId :: new ( 1 ) ) . unwrap ( ) ;
1603+ }
15511604}
0 commit comments