DoxigAlpha

findFile

Function parameters

Parameters

#
fr:*File.Reader

Type definitions in this namespace

Types

#

Extract the zipped files to the given `dest` directory.

Functions

#
extract
Extract the zipped files to the given `dest` directory.

= [4]u8{ 'P', 'K', 1, 2 }

Values

#
central_file_header_sig
= [4]u8{ 'P', 'K', 1, 2 }
local_file_header_sig
= [4]u8{ 'P', 'K', 3, 4 }
end_record_sig
= [4]u8{ 'P', 'K', 5, 6 }
end_record64_sig
= [4]u8{ 'P', 'K', 6, 6 }
end_locator64_sig
= [4]u8{ 'P', 'K', 6, 7 }

Source

Implementation

#
pub fn findFile(fr: *File.Reader) FindFileError!EndRecord {
    const end_pos = try fr.getSize();

    var buf: [@sizeOf(EndRecord) + std.math.maxInt(u16)]u8 = undefined;
    const record_len_max = @min(end_pos, buf.len);
    var loaded_len: u32 = 0;
    var comment_len: u16 = 0;
    while (true) {
        const record_len: u32 = @as(u32, comment_len) + @sizeOf(EndRecord);
        if (record_len > record_len_max)
            return error.ZipNoEndRecord;

        if (record_len > loaded_len) {
            const new_loaded_len = @min(loaded_len + 300, record_len_max);
            const read_len = new_loaded_len - loaded_len;

            try fr.seekTo(end_pos - @as(u64, new_loaded_len));
            const read_buf: []u8 = buf[buf.len - new_loaded_len ..][0..read_len];
            fr.interface.readSliceAll(read_buf) catch |err| switch (err) {
                error.ReadFailed => return fr.err.?,
                error.EndOfStream => return error.EndOfStream,
            };
            loaded_len = new_loaded_len;
        }

        const record_bytes = buf[buf.len - record_len ..][0..@sizeOf(EndRecord)];
        if (std.mem.eql(u8, record_bytes[0..4], &end_record_sig) and
            std.mem.readInt(u16, record_bytes[20..22], .little) == comment_len)
        {
            const record: *align(1) EndRecord = @ptrCast(record_bytes.ptr);
            if (!is_le) std.mem.byteSwapAllFields(EndRecord, record);
            return record.*;
        }

        if (comment_len == std.math.maxInt(u16))
            return error.ZipNoEndRecord;
        comment_len += 1;
    }
}