use serde::{Deserialize, Serialize};
use static_assertions::const_assert_eq;
#[derive(Debug, Serialize, Deserialize)]
#[repr(C)]
pub struct SparseHeader {
pub magic: u32,
pub major_version: u16,
pub minor_version: u16,
pub file_hdr_sz: u16,
pub chunk_hdr_sz: u16,
pub blk_sz: u32,
pub total_blks: u32,
pub total_chunks: u32,
pub image_checksum: u32,
}
pub const SPARSE_HEADER_SIZE: usize = std::mem::size_of::<SparseHeader>();
const_assert_eq!(SPARSE_HEADER_SIZE, 28);
impl SparseHeader {
pub fn new(blk_sz: u32, total_blks: u32, total_chunks: u32) -> SparseHeader {
SparseHeader {
magic: SPARSE_HEADER_MAGIC,
major_version: MAJOR_VERSION,
minor_version: MINOR_VERSION,
file_hdr_sz: std::mem::size_of::<SparseHeader>() as u16,
chunk_hdr_sz: std::mem::size_of::<ChunkHeader>() as u16,
blk_sz,
total_blks,
total_chunks,
image_checksum: CHECKSUM, }
}
pub fn valid(&self) -> bool {
self.magic == SPARSE_HEADER_MAGIC
&& self.major_version == MAJOR_VERSION
&& self.minor_version == MINOR_VERSION
}
}
#[derive(Debug, Serialize, Deserialize)]
#[repr(C)]
pub struct ChunkHeader {
pub chunk_type: u16,
reserved1: u16,
pub chunk_sz: u32,
pub total_sz: u32,
}
pub const CHUNK_HEADER_SIZE: usize = std::mem::size_of::<ChunkHeader>();
const_assert_eq!(CHUNK_HEADER_SIZE, 12);
pub const CHUNK_TYPE_RAW: u16 = 0xCAC1;
pub const CHUNK_TYPE_FILL: u16 = 0xCAC2;
pub const CHUNK_TYPE_DONT_CARE: u16 = 0xCAC3;
pub const CHUNK_TYPE_CRC32: u16 = 0xCAC4;
impl ChunkHeader {
pub fn new(chunk_type: u16, reserved1: u16, chunk_sz: u32, total_sz: u32) -> ChunkHeader {
ChunkHeader { chunk_type, reserved1, chunk_sz, total_sz }
}
pub fn valid(&self) -> bool {
self.chunk_type == CHUNK_TYPE_RAW
|| self.chunk_type == CHUNK_TYPE_FILL
|| self.chunk_type == CHUNK_TYPE_DONT_CARE
|| self.chunk_type == CHUNK_TYPE_CRC32
}
}
pub const SPARSE_HEADER_MAGIC: u32 = 0xED26FF3A;
const MAJOR_VERSION: u16 = 0x1;
const MINOR_VERSION: u16 = 0x0;
const CHECKSUM: u32 = 0xCAFED00D;