use crate::durandal::{bin::*, chunk::*, err::*, text::*}; use std::fmt; fn read_group(b: &[u8], text: &[u8]) -> ResultS { // flags = b.c_u16b( 0)?; let ttype = b.c_u16b(2)?; let pdata = b.c_i16b(4)?; let start = b.c_u16b(6)? as usize; let size = b.c_u16b(8)? as usize; let lines = b.c_u16b(10)?; let text = mac_roman_conv(&text[start..start + size]); let ttype = GroupType::from_repr(ttype)?; Ok(Group{ttype, pdata, lines, text}) } fn read_face(b: &[u8]) -> ResultS { let start = b.c_u16b(0)? as usize; let face = b.c_u16b(2)?; let color = b.c_u16b(4)?; Ok(Face { start, face, color }) } fn read_terminal(b: &[u8]) -> ResultS<(usize, Terminal)> { const SIZE_GROUP: usize = 12; const SIZE_FACE: usize = 6; let end = b.c_u16b(0)? as usize; let encoded = b.c_u16b(2)? & 1 != 0; let lines = b.c_u16b(4)?; let group_n = b.c_u16b(6)? as usize; let face_n = b.c_u16b(8)? as usize; let mut groups = Vec::with_capacity(group_n); let mut faces = Vec::with_capacity(face_n); let mut p = 10; // size of header 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((end, Terminal{lines, groups, faces})) } impl Chunker> for Terminal { fn chunk(b: &[u8]) -> ResultS> { let mut v = Vec::new(); let mut p = 0; while p < b.len() { let (size, trm) = read_terminal(&b[p..])?; v.push(trm); p += size; } Ok(v) } } #[derive(Debug)] pub struct Terminal { lines: u16, groups: Vec, faces: Vec, } #[derive(Debug)] pub struct Face { start: usize, face: u16, color: u16, } pub struct Group { ttype: GroupType, pdata: i16, lines: u16, text: String, } c_enum! { #[derive(Debug)] 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.len() != 0 { write!(f, ";\n{}", self.text)?; } write!(f, "}}") } } // EOF