1#![allow(clippy::unnecessary_fallible_conversions)] use std::io::Cursor;
7
8use binrw::BinRead;
9use binrw::binrw;
10
11use crate::ByteSpan;
12use crate::common::Language;
13
14#[binrw]
15#[brw(magic = b"EXHF")]
16#[brw(big)]
17#[allow(dead_code)]
18#[derive(Debug)]
19pub struct EXHHeader {
20 pub(crate) version: u16,
21
22 pub data_offset: u16,
23 pub(crate) column_count: u16,
24 pub(crate) page_count: u16,
25 pub(crate) language_count: u16,
26
27 #[br(pad_before = 6)]
28 #[br(pad_after = 8)]
29 pub row_count: u32,
30}
31
32#[binrw]
33#[brw(repr(u16))]
34#[repr(u16)]
35#[derive(PartialEq, Eq, Clone, Copy, Debug)]
36pub enum ColumnDataType {
37 String = 0x0,
38 Bool = 0x1,
39 Int8 = 0x2,
40 UInt8 = 0x3,
41 Int16 = 0x4,
42 UInt16 = 0x5,
43 Int32 = 0x6,
44 UInt32 = 0x7,
45 Float32 = 0x9,
46 Int64 = 0xA,
47 UInt64 = 0xB,
48
49 PackedBool0 = 0x19,
50 PackedBool1 = 0x1A,
51 PackedBool2 = 0x1B,
52 PackedBool3 = 0x1C,
53 PackedBool4 = 0x1D,
54 PackedBool5 = 0x1E,
55 PackedBool6 = 0x1F,
56 PackedBool7 = 0x20,
57}
58
59#[binrw]
60#[brw(big)]
61#[derive(Debug, Copy, Clone)]
62pub struct ExcelColumnDefinition {
63 pub data_type: ColumnDataType,
64 pub offset: u16,
65}
66
67#[binrw]
68#[brw(big)]
69#[allow(dead_code)]
70#[derive(Debug)]
71pub struct ExcelDataPagination {
72 pub start_id: u32,
73 pub row_count: u32,
74}
75
76#[binrw]
77#[brw(big)]
78#[allow(dead_code)]
79#[derive(Debug)]
80pub struct EXH {
81 pub header: EXHHeader,
82
83 #[br(count = header.column_count)]
84 pub column_definitions: Vec<ExcelColumnDefinition>,
85
86 #[br(count = header.page_count)]
87 pub pages: Vec<ExcelDataPagination>,
88
89 #[br(count = header.language_count)]
90 pub languages: Vec<Language>,
91}
92
93impl EXH {
94 pub fn from_existing(buffer: ByteSpan) -> Option<EXH> {
95 EXH::read(&mut Cursor::new(&buffer)).ok()
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use std::fs::read;
102 use std::path::PathBuf;
103
104 use super::*;
105
106 #[test]
107 fn test_invalid() {
108 let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
109 d.push("resources/tests");
110 d.push("random");
111
112 EXH::from_existing(&read(d).unwrap());
114 }
115}