1
1
//! Various utilities.
2
2
3
- use crate :: ALIGNMENT ;
3
+ use crate :: tag:: GenericTag ;
4
+ use crate :: { TagHeader , TagTrait , TagType , ALIGNMENT } ;
4
5
use core:: fmt;
5
6
use core:: fmt:: { Display , Formatter } ;
6
7
use core:: str:: Utf8Error ;
8
+ use core:: { ptr, slice} ;
9
+ #[ cfg( feature = "builder" ) ]
10
+ use { alloc:: alloc:: Layout , alloc:: boxed:: Box } ;
7
11
8
12
/// Error type describing failures when parsing the string from a tag.
9
13
#[ derive( Debug , PartialEq , Eq , Clone ) ]
@@ -31,6 +35,38 @@ impl core::error::Error for StringError {
31
35
}
32
36
}
33
37
38
+ /// Creates a new tag implementing [`TagTrait`] on the heap. This works for
39
+ /// sized and unsized tags. However, it only makes sense to use this for tags
40
+ /// that are DSTs (unsized), as for the sized ones, you can call a regular
41
+ /// constructor and box the result.
42
+ ///
43
+ /// # Parameters
44
+ /// - `additional_bytes`: All bytes apart from the default [`TagHeader`] that
45
+ /// are included into the tag.
46
+ #[ cfg( feature = "alloc" ) ]
47
+ pub fn new_boxed < T : TagTrait + ?Sized > ( additional_bytes : & [ u8 ] ) -> Box < T > {
48
+ let size = size_of :: < TagHeader > ( ) + additional_bytes. iter ( ) . len ( ) ;
49
+ let alloc_size = increase_to_alignment ( size) ;
50
+ let layout = Layout :: from_size_align ( alloc_size, ALIGNMENT ) . unwrap ( ) ;
51
+ let heap_ptr = unsafe { alloc:: alloc:: alloc ( layout) } ;
52
+ assert ! ( !heap_ptr. is_null( ) ) ;
53
+
54
+ unsafe {
55
+ heap_ptr. cast :: < u32 > ( ) . write ( T :: ID . val ( ) ) ;
56
+ heap_ptr. cast :: < u32 > ( ) . add ( 1 ) . write ( size as u32 ) ;
57
+ }
58
+ unsafe {
59
+ let ptr = heap_ptr. add ( size_of :: < TagHeader > ( ) ) ;
60
+ ptr:: copy_nonoverlapping ( additional_bytes. as_ptr ( ) , ptr, additional_bytes. len ( ) ) ;
61
+ }
62
+
63
+ let header = unsafe { heap_ptr. cast :: < TagHeader > ( ) . as_ref ( ) } . unwrap ( ) ;
64
+
65
+ let ptr = ptr_meta:: from_raw_parts_mut ( heap_ptr. cast ( ) , T :: dst_len ( header) ) ;
66
+
67
+ unsafe { Box :: from_raw ( ptr) }
68
+ }
69
+
34
70
/// Parses the provided byte sequence as Multiboot string, which maps to a
35
71
/// [`str`].
36
72
pub fn parse_slice_as_string ( bytes : & [ u8 ] ) -> Result < & str , StringError > {
@@ -52,6 +88,8 @@ pub const fn increase_to_alignment(size: usize) -> usize {
52
88
#[ cfg( test) ]
53
89
mod tests {
54
90
use super :: * ;
91
+ use crate :: tag:: GenericTag ;
92
+ use crate :: CommandLineTag ;
55
93
56
94
#[ test]
57
95
fn test_parse_slice_as_string ( ) {
@@ -87,4 +125,13 @@ mod tests {
87
125
assert_eq ! ( increase_to_alignment( 8 ) , 8 ) ;
88
126
assert_eq ! ( increase_to_alignment( 9 ) , 16 ) ;
89
127
}
128
+
129
+ #[ test]
130
+ fn test_new_boxed ( ) {
131
+ let tag = new_boxed :: < GenericTag > ( & [ 0 , 1 , 2 , 3 ] ) ;
132
+ assert_eq ! ( tag. header( ) . typ, GenericTag :: ID ) ;
133
+ { }
134
+ let tag = new_boxed :: < CommandLineTag > ( "hello\0 " . as_bytes ( ) ) ;
135
+ assert_eq ! ( tag. cmdline( ) , Ok ( "hello" ) ) ;
136
+ }
90
137
}
0 commit comments