@@ -3,25 +3,6 @@ const block = @import("xz/block.zig");
3
3
const Allocator = std .mem .Allocator ;
4
4
const Crc32 = std .hash .Crc32 ;
5
5
6
- pub const Flags = packed struct (u16 ) {
7
- reserved1 : u8 ,
8
- check_kind : Check ,
9
- reserved2 : u4 ,
10
- };
11
-
12
- pub const Header = extern struct {
13
- magic : [6 ]u8 ,
14
- flags : Flags ,
15
- crc32 : u32 ,
16
- };
17
-
18
- pub const Footer = extern struct {
19
- crc32 : u32 ,
20
- backward_size : u32 ,
21
- flags : Flags ,
22
- magic : [2 ]u8 ,
23
- };
24
-
25
6
pub const Check = enum (u4 ) {
26
7
none = 0x00 ,
27
8
crc32 = 0x01 ,
@@ -30,6 +11,20 @@ pub const Check = enum(u4) {
30
11
_ ,
31
12
};
32
13
14
+ fn readStreamFlags (reader : anytype , check : * Check ) ! void {
15
+ var bit_reader = std .io .bitReader (.Little , reader );
16
+
17
+ const reserved1 = try bit_reader .readBitsNoEof (u8 , 8 );
18
+ if (reserved1 != 0 )
19
+ return error .CorruptInput ;
20
+
21
+ check .* = @intToEnum (Check , try bit_reader .readBitsNoEof (u4 , 4 ));
22
+
23
+ const reserved2 = try bit_reader .readBitsNoEof (u4 , 4 );
24
+ if (reserved2 != 0 )
25
+ return error .CorruptInput ;
26
+ }
27
+
33
28
pub fn decompress (allocator : Allocator , reader : anytype ) ! Decompress (@TypeOf (reader )) {
34
29
return Decompress (@TypeOf (reader )).init (allocator , reader );
35
30
}
@@ -46,21 +41,24 @@ pub fn Decompress(comptime ReaderType: type) type {
46
41
in_reader : ReaderType ,
47
42
48
43
fn init (allocator : Allocator , source : ReaderType ) ! Self {
49
- const header = try source .readStruct (Header );
50
-
51
- if (! std .mem .eql (u8 , & header .magic , &.{ 0xFD , '7' , 'z' , 'X' , 'Z' , 0x00 }))
44
+ const magic = try source .readBytesNoEof (6 );
45
+ if (! std .mem .eql (u8 , & magic , &.{ 0xFD , '7' , 'z' , 'X' , 'Z' , 0x00 }))
52
46
return error .BadHeader ;
53
47
54
- if (header .flags .reserved1 != 0 or header .flags .reserved2 != 0 )
55
- return error .BadHeader ;
48
+ var check : Check = undefined ;
49
+ const hash_a = blk : {
50
+ var hasher = std .compress .hashedReader (source , Crc32 .init ());
51
+ try readStreamFlags (hasher .reader (), & check );
52
+ break :blk hasher .hasher .final ();
53
+ };
56
54
57
- const hash = Crc32 . hash ( std . mem . asBytes ( & header . flags ) );
58
- if (hash != header . crc32 )
55
+ const hash_b = try source . readIntLittle ( u32 );
56
+ if (hash_a != hash_b )
59
57
return error .WrongChecksum ;
60
58
61
59
return Self {
62
60
.allocator = allocator ,
63
- .block_decoder = try block .decoder (allocator , source , header . flags . check_kind ),
61
+ .block_decoder = try block .decoder (allocator , source , check ),
64
62
.in_reader = source ,
65
63
};
66
64
}
@@ -114,22 +112,27 @@ pub fn Decompress(comptime ReaderType: type) type {
114
112
break :blk counter .bytes_read ;
115
113
};
116
114
117
- const footer = try self .in_reader .readStruct (Footer );
118
- const backward_size = (footer .backward_size + 1 ) * 4 ;
119
- if (backward_size != index_size )
120
- return error .CorruptInput ;
115
+ const hash_a = try self .in_reader .readIntLittle (u32 );
121
116
122
- if (footer .flags .reserved1 != 0 or footer .flags .reserved2 != 0 )
123
- return error .CorruptInput ;
117
+ const hash_b = blk : {
118
+ var hasher = std .compress .hashedReader (self .in_reader , Crc32 .init ());
119
+ const hashed_reader = hasher .reader ();
120
+
121
+ const backward_size = (try hashed_reader .readIntLittle (u32 ) + 1 ) * 4 ;
122
+ if (backward_size != index_size )
123
+ return error .CorruptInput ;
124
+
125
+ var check : Check = undefined ;
126
+ try readStreamFlags (hashed_reader , & check );
127
+
128
+ break :blk hasher .hasher .final ();
129
+ };
124
130
125
- var hasher = Crc32 .init ();
126
- hasher .update (std .mem .asBytes (& footer .backward_size ));
127
- hasher .update (std .mem .asBytes (& footer .flags ));
128
- const hash = hasher .final ();
129
- if (hash != footer .crc32 )
131
+ if (hash_a != hash_b )
130
132
return error .WrongChecksum ;
131
133
132
- if (! std .mem .eql (u8 , & footer .magic , &.{ 'Y' , 'Z' }))
134
+ const magic = try self .in_reader .readBytesNoEof (2 );
135
+ if (! std .mem .eql (u8 , & magic , &.{ 'Y' , 'Z' }))
133
136
return error .CorruptInput ;
134
137
135
138
return 0 ;
0 commit comments