mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-28 07:47:02 -05:00
* Add `current_bit_offset()` and `read_bits(...)` to `std::mem` * Replace deprecated BitfieldOrder enum values with new clearer names This adds new options named `MostToLeastSignificant` and `LeastToMostSignificant` to replace the old `LeftToRight` and `RightToLeft` names. These names should be much clearer about what they affect and how. * Throw errors when `std::core::(get|set)_bitfield_order()` are called * Update all patterns to work with the new bitfield behaviors
119 lines
3.0 KiB
Rust
119 lines
3.0 KiB
Rust
// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md
|
|
|
|
#pragma MIME application/zstd
|
|
|
|
#include <std/core.pat>
|
|
#include <std/io.pat>
|
|
#include <std/mem.pat>
|
|
#include <std/sys.pat>
|
|
|
|
using BitfieldOrder = std::core::BitfieldOrder;
|
|
|
|
#define ZSTD_MAGIC_NUMBER 0xFD2FB528
|
|
|
|
bitfield frame_header_descriptor_t {
|
|
frame_content_size_flag : 2;
|
|
single_segment_flag : 1;
|
|
unused_bit : 1;
|
|
reserved_bit : 1;
|
|
content_checksum_flag : 1;
|
|
dictionary_id_flag : 2;
|
|
} [[bitfield_order(BitfieldOrder::MostToLeastSignificant, 8)]];
|
|
|
|
bitfield window_descriptor_t {
|
|
exponent : 5;
|
|
mantissa : 3;
|
|
} [[bitfield_order(BitfieldOrder::MostToLeastSignificant, 8)]];
|
|
|
|
fn window_size(window_descriptor_t window_descriptor) {
|
|
u64 window_log = 10 + window_descriptor.exponent;
|
|
u64 window_base = 1 << window_log;
|
|
u64 window_add = (window_base / 8) * window_descriptor.mantissa;
|
|
u64 window_size = window_base + window_add;
|
|
return window_size;
|
|
};
|
|
|
|
struct frame_header_t {
|
|
frame_header_descriptor_t frame_header_descriptor;
|
|
|
|
if (!frame_header_descriptor.single_segment_flag){
|
|
window_descriptor_t window_descriptor;
|
|
}
|
|
|
|
if (frame_header_descriptor.dictionary_id_flag == 1) {
|
|
le u8 dictionary_id;
|
|
}
|
|
else if (frame_header_descriptor.dictionary_id_flag == 2) {
|
|
le u16 dictionary_id;
|
|
}
|
|
else if (frame_header_descriptor.dictionary_id_flag == 3) {
|
|
le u32 dictionary_id;
|
|
}
|
|
|
|
if (frame_header_descriptor.frame_content_size_flag == 0) { // 0
|
|
if (frame_header_descriptor.single_segment_flag) {
|
|
le u8 content_size;
|
|
}
|
|
}
|
|
else if (frame_header_descriptor.frame_content_size_flag == 1) {
|
|
le u16 content_size;
|
|
}
|
|
else if (frame_header_descriptor.frame_content_size_flag == 2) {
|
|
le u32 content_size;
|
|
}
|
|
else {
|
|
le u64 content_size;
|
|
}
|
|
};
|
|
|
|
bitfield block_header_t {
|
|
last_block : 1;
|
|
block_type : 2;
|
|
block_size : 21;
|
|
};
|
|
|
|
enum block_type : u8 {
|
|
raw_block = 0,
|
|
rle_block = 1,
|
|
compressed_block = 2,
|
|
reserved = 3
|
|
};
|
|
|
|
struct data_block_t {
|
|
block_header_t block_header;
|
|
|
|
if (block_header.last_block) {
|
|
last_block_flag = true;
|
|
}
|
|
|
|
if (block_header.block_type == block_type::raw_block) {
|
|
le u8 block_content[block_header.block_size];
|
|
}
|
|
else if (block_header.block_type == block_type::rle_block) {
|
|
le u8 block_content[1];
|
|
}
|
|
else if (block_header.block_type == block_type::compressed_block) {
|
|
le u8 block_content[block_header.block_size];
|
|
}
|
|
else {
|
|
std::error("The data block seems to be corrupted!");
|
|
}
|
|
};
|
|
|
|
struct content_checksum_t {
|
|
le u32 xxh64_hash;
|
|
};
|
|
|
|
struct zstd_frame_t {
|
|
le u32 magic_number;
|
|
std::assert(magic_number == ZSTD_MAGIC_NUMBER, "Invalid magic number!");
|
|
frame_header_t frame_header;
|
|
data_block_t data_block[while(!last_block_flag)];
|
|
if (frame_header.frame_header_descriptor.content_checksum_flag) {
|
|
content_checksum_t content_checksum;
|
|
}
|
|
};
|
|
|
|
bool last_block_flag = false;
|
|
zstd_frame_t zstd_frame @ 0x00;
|