diff --git a/src/main.zig b/src/main.zig index 1b8a024..5d4b427 100644 --- a/src/main.zig +++ b/src/main.zig @@ -20,6 +20,74 @@ fn usage() void { exit("", .{}, 1); } +const BitWalker = struct { + const Self = @This(); + + data: *[]u8, + position: usize = 0, + in_byte_position: u3 = 0, + direction: bool = false, + + fn init(data: *[]u8, direction: bool) Self { + return Self{ + .data = data, + .direction = direction, + }; + } + + // TODO direction + fn walk(self: *Self, bits: u3) !u8 { + if (bits > 8 or bits == 0) return error.invalid_bit_number; + var byte = self.data.ptr[self.position]; + + // jumps over bytes + if (self.in_byte_position + @as(u4, bits) > 8) { + // Generate a mast that covers the last part of the old byte + var old_mask: u8 = 0; + var i: usize = 0; + while (i < bits - self.in_byte_position) : (i += 1) { + old_mask = @shlExact(old_mask, 1) + 1; + } + old_mask = @shlExact(old_mask, self.in_byte_position); + + var next_byte = self.data.ptr[self.position + 1]; + var new_byte_pos: u3 = self.in_byte_position + bits % 8; + + var new_mask: u8 = 0; + var j: usize = 0; + while (j < new_byte_pos) : (j += 1) { + new_mask = @shlExact(new_mask, 1) + 1; + } + print("{} mask: {b}, new_mask", .{ bits, old_mask, new_mask }); + print("here {b} {b}", .{ byte, old_mask }); + print("here_new {b} {b}", .{ next_byte, new_mask }); + + self.position += 1; + self.in_byte_position = new_byte_pos; + return byte & old_mask + next_byte & new_mask; + } + + // Generate a mast that covers the last part of the old byte + var old_mask: u8 = 0; + var i: usize = 0; + while (i < bits) : (i += 1) { + old_mask = @shlExact(old_mask, 1) + 1; + } + old_mask = @shlExact(old_mask, self.in_byte_position); + + if (self.in_byte_position + bits == 8) { + self.position += 1; + self.in_byte_position = 0; + } + + const result = @shrExact(byte & old_mask, self.in_byte_position); + + self.in_byte_position += bits; + + return result; + } +}; + const LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50; const ZipFileHeader = struct { version: u16, @@ -92,11 +160,26 @@ const ZipFileHeader = struct { } self.uncompressed_content = try self.allocator.alloc(u8, self.uncompressed_size); - errdefer self.allocator.free(self.uncompressed_size); + errdefer self.allocator.free(self.uncompressed_content); + + var bitw = BitWalker.init(&self.compressed_content, false); + + var lastBlock1 = try bitw.walk(1); + var blockType1 = try bitw.walk(2); + var number_of_literal_codes1 = try bitw.walk(5); + var number_of_dist_codes1 = try bitw.walk(5); + + print("{} {} {} {}", .{ lastBlock1, blockType1, number_of_literal_codes1, number_of_dist_codes1 }); var byte = self.compressed_content[0]; - var lastBlock = byte & 0b1000_0000 == 0b1000_0000; - var blockType = @shrExact(byte & 0b0110_0000, 5); + var lastBlock = byte & 0b0000_0001 == 0b0000_0001; + var blockType = @shrExact(byte & 0b0000_0110, 1); + var number_of_literal_codes = @shrExact(byte & 0b1111_1000, 3); // 256 + byte = self.compressed_content[1]; + var number_of_dist_codes = byte & 0b0001_1111; + var next_byte = self.compressed_content[2]; + var number_of_length_codes = @shrExact(byte & 0b1110_0000, 5) + @shlExact(next_byte & 0b0000_0001, 3); + byte = next_byte; if (lastBlock) { print("last block", .{}); @@ -104,12 +187,16 @@ const ZipFileHeader = struct { print("not last block", .{}); } - print("blockType: {}", .{blockType}); + print("block_type: {}", .{blockType}); if (blockType != 2) { return error.unsuported_block_type; } + print("number of literal codes: {}", .{number_of_literal_codes}); + print("number of dist codes: {}", .{number_of_dist_codes}); + print("number_of_length_coes: {}", .{number_of_length_codes}); + self.decompressed = true; }