1- use alloc:: vec:: Vec ;
2- use core:: ops:: Range ;
1+ use alloc:: { boxed :: Box , vec:: Vec } ;
2+ use core:: ops:: { Deref , Range } ;
33
44use crate :: filename:: { Filename , truncate} ;
55
66/// A parser for an already decompressed image
77#[ derive( Clone , Copy ) ]
88pub struct ImageParser < ' a > {
9- input : & ' a [ u8 ] ,
9+ input : & ' a TarBytesSlice ,
1010 offset : usize ,
1111}
1212
1313impl < ' a > ImageParser < ' a > {
14- pub fn new ( input : & ' a [ u8 ] ) -> Self {
14+ pub fn new ( input : & ' a TarBytesSlice ) -> Self {
1515 Self { input, offset : 0 }
1616 }
1717}
@@ -56,6 +56,35 @@ impl<'a> From<core::str::Utf8Error> for ImageParserError<'a> {
5656 }
5757}
5858
59+ /// Owned bytes belonging to a decompressed tar file
60+ #[ derive( Clone , Default , PartialEq , Eq ) ]
61+ pub struct TarBytes ( pub Box < [ u8 ] > ) ;
62+
63+ #[ derive( PartialEq , Eq ) ]
64+ #[ repr( transparent) ]
65+ pub struct TarBytesSlice ( pub [ u8 ] ) ;
66+
67+ impl Deref for TarBytes {
68+ type Target = TarBytesSlice ;
69+
70+ #[ inline( always) ]
71+ fn deref ( & self ) -> & TarBytesSlice {
72+ TarBytesSlice :: new ( & self . 0 [ ..] )
73+ }
74+ }
75+
76+ impl TarBytesSlice {
77+ #[ inline( always) ]
78+ pub const fn new ( data : & [ u8 ] ) -> & Self {
79+ unsafe { & * ( data as * const [ u8 ] as * const Self ) }
80+ }
81+
82+ pub const fn split_at ( & self , mid : usize ) -> ( & Self , & Self ) {
83+ let ( a, b) = self . 0 . split_at ( mid) ;
84+ ( Self :: new ( a) , Self :: new ( b) )
85+ }
86+ }
87+
5988fn try_parse_octal < ' a , T : num_traits:: Num > ( s : & [ u8 ] ) -> Result < T , ImageParserError < ' a > >
6089where
6190 T :: FromStrRadixErr : Into < ImageParserError < ' a > > ,
@@ -68,38 +97,38 @@ const BLOCK_SIZE_2POW: u32 = 9;
6897
6998impl < ' a > ImageParser < ' a > {
7099 fn next_intern ( & mut self ) -> Result < Option < ImageFile < ' a > > , ImageParserError < ' a > > {
71- while self . input . len ( ) >= BLOCK_SIZE {
100+ while self . input . 0 . len ( ) >= BLOCK_SIZE {
72101 // `input` starts with a tar header, padded to 512 bytes (block size)
73102 let offset = self . offset ;
74103 let ( header, rest) = self . input . split_at ( BLOCK_SIZE ) ;
75104
76105 // note that integers are usually encoded as octal numbers
77- let name = truncate ( & header[ 0 ..100 ] ) ;
78- if header. iter ( ) . take_while ( |i| * * i == 0 ) . count ( ) == BLOCK_SIZE {
106+ let name = truncate ( & header. 0 [ 0 ..100 ] ) ;
107+ if header. 0 . iter ( ) . take_while ( |i| * * i == 0 ) . count ( ) == BLOCK_SIZE {
79108 // EOF marker
80109 return Ok ( None ) ;
81110 }
82- let is_exec = if let Ok ( mode) = try_parse_octal :: < u16 > ( & header[ 100 ..108 ] ) {
111+ let is_exec = if let Ok ( mode) = try_parse_octal :: < u16 > ( & header. 0 [ 100 ..108 ] ) {
83112 mode & 0o111 != 0
84113 } else {
85114 false
86115 } ;
87- let size: usize = try_parse_octal :: < u64 > ( & header[ 124 ..136 ] ) ?. try_into ( ) ?;
88- let _linkname = & header[ 157 ..257 ] ;
89- let magic = & header[ 257 ..263 ] ;
90- let _version = & header[ 263 ..265 ] ;
91- let prefix = & header[ 345 ..500 ] ;
116+ let size: usize = try_parse_octal :: < u64 > ( & header. 0 [ 124 ..136 ] ) ?. try_into ( ) ?;
117+ let _linkname = & header. 0 [ 157 ..257 ] ;
118+ let magic = & header. 0 [ 257 ..263 ] ;
119+ let _version = & header. 0 [ 263 ..265 ] ;
120+ let prefix = & header. 0 [ 345 ..500 ] ;
92121
93122 // check if this is a supported file type
94- let ret = match header[ 156 ] {
123+ let ret = match header. 0 [ 156 ] {
95124 0 | b'0' => {
96125 // regular file
97126 let value_offset = offset + BLOCK_SIZE ;
98127 Some ( ImageFile {
99128 name : Filename :: One ( name) ,
100129 is_exec,
101130 value_range : value_offset..( value_offset + size) ,
102- value : rest. get ( ..size) . ok_or ( ImageParserError :: UnexpectedEof ) ?,
131+ value : rest. 0 . get ( ..size) . ok_or ( ImageParserError :: UnexpectedEof ) ?,
103132 } )
104133 }
105134 _ => None ,
@@ -117,9 +146,11 @@ impl<'a> ImageParser<'a> {
117146 tmp << BLOCK_SIZE_2POW
118147 } ;
119148 self . offset += actual_rest_size;
120- self . input = rest
121- . get ( actual_rest_size..)
122- . ok_or ( ImageParserError :: UnexpectedEof ) ?;
149+ self . input = TarBytesSlice :: new (
150+ rest. 0
151+ . get ( actual_rest_size..)
152+ . ok_or ( ImageParserError :: UnexpectedEof ) ?,
153+ ) ;
123154
124155 if let Some ( mut x) = ret {
125156 // gather full file name (we might have to honor the ustar prefix)
@@ -133,7 +164,7 @@ impl<'a> ImageParser<'a> {
133164 }
134165 }
135166
136- if self . input . is_empty ( ) {
167+ if self . input . 0 . is_empty ( ) {
137168 return Ok ( None ) ;
138169 }
139170 Err ( ImageParserError :: UnexpectedEof )
@@ -149,7 +180,7 @@ impl<'a> Iterator for ImageParser<'a> {
149180 Ok ( Some ( x) ) => Some ( Ok ( x) ) ,
150181 Err ( e) => {
151182 // make sure we don't get stuck
152- self . input = & [ ] ;
183+ self . input = TarBytesSlice :: new ( & [ ] ) ;
153184 Some ( Err ( e) )
154185 }
155186 }
@@ -165,7 +196,7 @@ mod tests {
165196 proptest ! {
166197 #[ test]
167198 fn doesnt_crash( data: Vec <u8 >) {
168- ImageParser :: new( & * data) . count( ) ;
199+ ImageParser :: new( TarBytesSlice :: new ( & * data) ) . count( ) ;
169200 }
170201 }
171202}
0 commit comments