source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+[[package]]
+name = "array-init"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
+
[[package]]
name = "async-trait"
version = "0.1.81"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
"rustc-demangle",
]
+[[package]]
+name = "binrw"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d4bca59c20d6f40c2cc0802afbe1e788b89096f61bdf7aeea6bf00f10c2909b"
+dependencies = [
+ "array-init",
+ "binrw_derive",
+ "bytemuck",
+]
+
+[[package]]
+name = "binrw_derive"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8ba42866ce5bced2645bfa15e97eef2c62d2bdb530510538de8dd3d04efff3c"
+dependencies = [
+ "either",
+ "owo-colors",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+[[package]]
+name = "bytemuck"
+version = "1.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
+
[[package]]
name = "bytes"
version = "1.7.1"
"heck",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
"num-traits",
]
+[[package]]
+name = "owo-colors"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
+
[[package]]
name = "parking_lot"
version = "0.12.3"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
version = "1.0.0"
dependencies = [
"anyhow",
+ "binrw",
"bitflags 2.6.0",
"chardetng",
"chrono",
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
[[package]]
name = "syn"
version = "2.0.87"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
]
[[package]]
"once_cell",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
"wasm-bindgen-shared",
]
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.87",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
--- /dev/null
+use std::fmt::Debug;
+
+use binrw::{binread, BinRead, BinResult, Error as BinError};
+
+#[binread]
+#[br(little)]
+#[derive(Debug)]
+struct TableLook {
+ pt_table_look: PtTableLook,
+ pv_separator_style: PvSeparatorStyle,
+ pv_cell_style: PvCellStyle,
+ pv_text_style: PvTextStyle,
+}
+
+#[binread]
+#[br(little)]
+#[derive(Debug)]
+struct PtTableLook {
+ #[br(temp)]
+ #[br(assert(&tag.string == b"PTTableLook"))]
+ tag: Tag,
+
+ #[br(assert(version == 0 || version == 2, "PTTableLook version {version} not supported (expected 0 or 2)."))]
+ #[br(temp)]
+ version: u8,
+
+ flags: u16,
+
+ #[br(magic = b"\0\0")]
+ #[br(parse_with = parse_bool)]
+ nested_row_labels: bool,
+
+ #[br(magic = b"\0")]
+ #[br(parse_with = parse_bool)]
+ footnote_marker_subscripts: bool,
+
+ #[br(temp, magic = b"\0\x36\0\0\0\x12\0\0\0")]
+ _empty: (),
+}
+
+#[binread]
+#[br(little)]
+#[derive(Debug)]
+struct PvSeparatorStyle {
+ #[br(assert(&tag.string == b"PVSeparatorStyle"))]
+ tag: Tag,
+
+ #[br(magic = b"\0")]
+ horizontal_dimension_rows: Separator,
+ vertical_dimension_rows: Separator,
+ horizontal_category_rows: Separator,
+ vertical_category_rows: Separator,
+
+ #[br(magic = b"\x03\x80\0")]
+ horizontal_dimension_columns: Separator,
+ vertical_dimension_columns: Separator,
+ horizontal_category_columns: Separator,
+ vertical_category_columns: Separator,
+}
+
+#[binread]
+#[br(little)]
+#[derive(Debug)]
+enum Separator {
+ #[br(magic = 0u16)]
+ None,
+ #[br(magic = 1u16)]
+ Some { color: u32, style: u16, width: u16 },
+}
+
+#[binread]
+#[br(little)]
+#[derive(Debug)]
+struct PvCellStyle {
+ #[br(assert(&tag.string == b"PVCellStyle"))]
+ tag: Tag,
+
+ title_color: AreaColor,
+}
+
+#[binread]
+#[br(little)]
+#[derive(Debug)]
+struct AreaColor {
+ #[br(magic = b"\0\x01\0")]
+ color10: u32,
+ color0: u32,
+ shading: u8,
+ #[br(temp, magic = 0u8)]
+ _empty: (),
+}
+
+#[binread]
+#[br(little)]
+#[derive(Debug)]
+struct PvTextStyle {
+ #[br(assert(&tag.string == b"PVTextStyle"))]
+ tag: Tag,
+
+ #[br(magic = 0u8)]
+ title_style: AreaStyle,
+ layers: MostAreas,
+ corner: MostAreas,
+ row_labels: MostAreas,
+ column_labels: MostAreas,
+ data: MostAreas,
+ caption: MostAreas,
+ footer: MostAreas,
+}
+
+#[binread]
+#[br(little)]
+#[derive(Debug)]
+struct MostAreas {
+ #[br(magic = b"\x06\x80")]
+ color: AreaColor,
+
+ #[br(magic = b"\x08\x80\0")]
+ style: AreaStyle,
+}
+
+#[binread]
+#[br(little)]
+#[derive(Debug)]
+struct AreaStyle {
+ valign: u16,
+ halign: u16,
+ decimal_offset: u16,
+ left_margin: u16,
+ right_margin: u16,
+ top_margin: u16,
+ bottom_margin: u16,
+ #[br(magic = b"\0\0\x01\0")]
+ font_size: i32,
+ stretch: u16,
+ #[br(magic = 0u16)]
+ rotation_angle: u32,
+ #[br(magic = 0u32)]
+ weight: u16,
+ #[br(magic = 0u16)]
+ #[br(parse_with = parse_bool)]
+ italic: bool,
+ #[br(parse_with = parse_bool)]
+ underline: bool,
+ #[br(parse_with = parse_bool)]
+ strike_through: bool,
+ rtf_charset_number: u32,
+ x: u8,
+ font_name: U8String,
+ text_color: u32,
+ #[br(magic = 0u16)]
+ _empty: (),
+}
+
+#[binrw::parser(reader, endian)]
+fn parse_bool() -> BinResult<bool> {
+ let byte = <u8>::read_options(reader, endian, ())?;
+ match byte {
+ 0 => Ok(false),
+ 1 => Ok(true),
+ _ => Err(BinError::NoVariantMatch {
+ pos: reader.stream_position()? - 1,
+ }),
+ }
+}
+
+#[binread]
+#[br(little)]
+struct Tag {
+ #[br(magic = b"\xff\xff\0\0")]
+ #[br(temp)]
+ length: u16,
+
+ #[br(count = length)]
+ string: Vec<u8>,
+}
+
+impl Debug for Tag {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{:?}", String::from_utf8_lossy(&self.string))
+ }
+}
+
+#[binread]
+#[br(little)]
+struct U8String {
+ #[br(temp)]
+ length: u8,
+
+ #[br(count = length)]
+ string: Vec<u8>,
+}
+
+impl Debug for U8String {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{:?}", String::from_utf8_lossy(&self.string))
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use std::io::Cursor;
+
+ use binrw::BinRead;
+
+ use crate::output::pivot::tlo::TableLook;
+
+ #[test]
+ fn parse() {
+ let bytes = include_bytes!("test1.tlo");
+ let tlo = TableLook::read(&mut Cursor::new(bytes)).unwrap();
+ println!("{tlo:#?}");
+ }
+}