use crate::durandal::{err::*, text::*}; use bitflags::bitflags; use serde::Serialize; use std::fmt; fn read_group(b: &[u8], text: &[u8]) -> ResultS { read_data! { 12, BE in b => flags = u16[0]; ttype = u16[2]; pdata = i16[4]; start = u16[6] as usize; size = u16[8] as usize; lines = u16[10]; } let text = mac_roman_conv(&text[start..start + size]); let flags = flag_ok!(GroupFlags, flags)?; let ttype = GroupType::from_repr(ttype)?; Ok(Group{flags, ttype, pdata, lines, text}) } fn read_face(b: &[u8]) -> ResultS { read_data! { 6, BE in b => start = u16[0] as usize; face = u16[2]; color = u16[4]; } Ok(Face{start, face, color}) } pub fn read_term(b: &[u8]) -> ResultS<(Terminal, usize)> { const SIZE_GROUP: usize = 12; const SIZE_FACE: usize = 6; read_data! { 10, BE in b => end = u16[0] as usize; encoded = u16[2]; lines = u16[4]; group_n = u16[6] as usize; face_n = u16[8] as usize; } let encoded = encoded != 0; let mut groups = Vec::with_capacity(group_n); let mut faces = Vec::with_capacity(face_n); let mut p = 10; let text_st = p + SIZE_GROUP * group_n + SIZE_FACE * face_n; let text = &b[text_st..end]; let text = if encoded { fuck_string(text) } else { text.to_vec() }; for _ in 0..group_n { groups.push(read_group(&b[p..], &text)?); p += SIZE_GROUP; } for _ in 0..face_n { faces.push(read_face(&b[p..])?); p += SIZE_FACE; } Ok((Terminal{lines, groups, faces}, end)) } #[derive(Debug, Serialize)] pub struct Terminal { lines: u16, groups: Vec, faces: Vec, } #[derive(Debug, Serialize)] pub struct Face { start: usize, face: u16, color: u16, } #[derive(Serialize)] pub struct Group { flags: GroupFlags, ttype: GroupType, pdata: i16, lines: u16, text: String, } bitflags! { #[derive(Serialize)] pub struct GroupFlags: u16 { const DrawOnRight = 1; const DrawCenter = 1 << 1; } } c_enum! { #[derive(Debug, Serialize)] pub enum GroupType: u16 { 0 => Logon, 1 => Unfinished, 2 => Success, 3 => Failure, 4 => Info, 5 => End, 6 => TeleInter, 7 => TeleIntra, 8 => Checkpoint, 9 => Sound, 10 => Movie, 11 => Track, 12 => Pict, 13 => Logoff, 14 => Camera, 15 => Static, 16 => Tag, } } impl fmt::Debug for Group { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Group{{{:?} {} {}", self.ttype, self.pdata, self.lines)?; if !self.text.is_empty() { write!(f, ";\n{}", self.text)?; } write!(f, "}}") } } // EOF