@@ -322,6 +322,8 @@ impl BootInformation {
322
322
/// Public getter to find any Multiboot tag by its type, including
323
323
/// specified and custom ones.
324
324
///
325
+ /// The parameter can be of type `u32`, [`TagType`], or [`TagTypeId`].
326
+ ///
325
327
/// # Specified or Custom Tags
326
328
/// The Multiboot2 specification specifies a list of tags, see [`TagType`].
327
329
/// However, it doesn't forbid to use custom tags. Because of this, there
@@ -331,10 +333,13 @@ impl BootInformation {
331
333
///
332
334
/// ## Use Custom Tags
333
335
/// 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]`.
335
338
///
336
- /// ```ignore
339
+ /// ```rust
340
+ /// use std::ffi::{c_char, CStr};
337
341
/// use multiboot2::TagTypeId;
342
+ ///
338
343
/// #[repr(C, align(8))]
339
344
/// struct CustomTag {
340
345
/// // new type from the lib: has repr(u32)
@@ -345,16 +350,16 @@ impl BootInformation {
345
350
/// }
346
351
///
347
352
/// let tag = bi
348
- /// // this function is now public!
349
- /// .get_tag(0x1337.into())
353
+ /// .get_tag(0x1337)
350
354
/// .unwrap()
351
355
/// // type definition from end user; must be `Sized`!
352
356
/// .cast_tag::<CustomTag>();
353
357
/// let name = &tag.name as *const u8 as *const c_char;
354
358
/// let str = unsafe { CStr::from_ptr(name).to_str().unwrap() };
355
359
/// assert_eq!(str, "name");
356
360
/// ```
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 ( ) ;
358
363
self . tags ( ) . find ( |tag| tag. typ == typ)
359
364
}
360
365
@@ -1548,15 +1553,63 @@ mod tests {
1548
1553
name : u8 ,
1549
1554
}
1550
1555
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 > ( ) ;
1555
1557
1556
1558
// strlen without null byte
1557
1559
let strlen = tag. size as usize - mem:: size_of :: < CommandLineTag > ( ) ;
1558
1560
let bytes = unsafe { slice:: from_raw_parts ( ( & tag. name ) as * const u8 , strlen) } ;
1559
1561
let name = core:: str:: from_utf8 ( bytes) . unwrap ( ) ;
1560
1562
assert_eq ! ( name, "name" ) ;
1561
1563
}
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
+ }
1562
1615
}
0 commit comments