use std::{borrow::Cow, collections::HashSet, io::Cursor};
use binrw::{binread, BinRead};
use getset::{CopyGetters, Getters};
use num_enum::IntoPrimitive;
use crate::error::Result;
use super::File;
#[binread]
#[derive(Debug, Getters, CopyGetters)]
#[br(big, magic = b"EXHF")]
pub struct ExcelHeader {
_version: u16,
#[get_copy = "pub"]
row_size: u16,
#[br(temp)]
column_count: u16,
#[br(temp)]
page_count: u16,
#[br(temp)]
language_count: u16,
#[br(pad_before = 3)]
#[get_copy = "pub"]
kind: SheetKind,
#[br(pad_before = 2)]
_row_count: u32,
#[br(
pad_before = 8,
count = column_count,
)]
#[get = "pub"]
columns: Vec<ColumnDefinition>,
#[br(count = page_count)]
#[get = "pub"]
pages: Vec<PageDefinition>,
#[br(
count = language_count,
map = LanguageDefinition::to_set,
)]
#[get = "pub"]
languages: HashSet<u8>,
}
impl File for ExcelHeader {
fn read<'a>(data: impl Into<Cow<'a, [u8]>>) -> Result<Self> {
Ok(<Self as BinRead>::read(&mut Cursor::new(data.into()))?)
}
}
#[binread]
#[derive(Clone, Copy, Debug, PartialEq)]
#[br(repr = u8)]
pub enum SheetKind {
Unknown = 0,
Default = 1,
Subrows = 2,
}
#[binread]
#[derive(Clone, Debug, CopyGetters)]
#[br(big)]
pub struct ColumnDefinition {
#[get_copy = "pub"]
kind: ColumnKind,
#[get_copy = "pub"]
offset: u16,
}
#[allow(missing_docs)]
#[binread]
#[derive(Clone, Copy, Debug, IntoPrimitive)]
#[br(big, repr = u16)]
#[repr(u16)]
pub enum ColumnKind {
String = 0x0,
Bool = 0x1,
Int8 = 0x2,
UInt8 = 0x3,
Int16 = 0x4,
UInt16 = 0x5,
Int32 = 0x6,
UInt32 = 0x7,
Float32 = 0x9,
Int64 = 0xA,
UInt64 = 0xB,
PackedBool0 = 0x19,
PackedBool1 = 0x1A,
PackedBool2 = 0x1B,
PackedBool3 = 0x1C,
PackedBool4 = 0x1D,
PackedBool5 = 0x1E,
PackedBool6 = 0x1F,
PackedBool7 = 0x20,
}
#[binread]
#[derive(Debug, CopyGetters)]
#[br(big)]
pub struct PageDefinition {
#[get_copy = "pub"]
start_id: u32,
#[get_copy = "pub"]
row_count: u32,
}
#[binread]
#[derive(Debug)]
#[br(big)]
struct LanguageDefinition {
#[br(pad_after = 1)]
language: u8,
}
impl LanguageDefinition {
fn to_set(languages: Vec<Self>) -> HashSet<u8> {
languages.iter().map(|language| language.language).collect()
}
}