use std::fmt; use crate::durandal::text::*; use crate::durandal::bin::*; impl Terminal { pub fn read(b: &[u8]) -> ResultS<(usize, Terminal)> { const SIZE_HEAD : usize = 10; const SIZE_GROUP: usize = 12; const SIZE_FACE : usize = 6; let len = b.c_u16b(0)? as usize; let enc = b.c_u16b(2)? & 1 != 0; let lns = b.c_u16b(4)?; let gnu = b.c_u16b(6)? as usize; let fnu = b.c_u16b(8)? as usize; let mut grp = Vec::with_capacity(gnu); let mut fcs = Vec::with_capacity(fnu); let end = SIZE_GROUP * gnu + SIZE_FACE * fnu + SIZE_HEAD; let mut p = SIZE_HEAD; for _ in 0..gnu { // flg = b.c_u16b(p )?; let typ = b.c_u16b(p+ 2)?.into(); let per = b.c_i16b(p+ 4)?; let beg = b.c_u16b(p+ 6)? as usize; let len = b.c_u16b(p+ 8)? as usize; let lns = b.c_u16b(p+10)?; let sta = end + beg; let txt = &b[sta..sta+len]; let txt = if enc {mac_roman_conv(&fuck_string(txt))} else {mac_roman_conv(&txt)}; grp.push(Group{typ, per, lns, txt}); p += SIZE_GROUP; } for _ in 0..fnu { let ind = b.c_u16b(p )?; let fce = b.c_u16b(p+2)?; let col = b.c_u16b(p+4)?; fcs.push(Face{ind, fce, col}); p += SIZE_FACE; } Ok((len, Terminal{enc, lns, grp, fcs})) } pub fn chunk(b: &[u8]) -> ResultS> { let mut v = Vec::new(); let mut p = 0; while p < b.len() { let sta = p; let (len, trm) = Terminal::read(&b[p..])?; v.push(trm); p = sta + len; } Ok(v) } } #[derive(Debug)] pub struct Terminal { enc: bool, lns: u16, grp: Vec, fcs: Vec, } pub struct Face { ind: u16, fce: u16, col: u16, } pub struct Group { typ: Type, per: i16, lns: u16, txt: String, } #[derive(Debug)] pub enum Type { Logon, Unfinished, Success, Failure, Information, End, InterlevelTeleport, IntralevelTeleport, Checkpoint, Sound, Movie, Track, Pict, Logoff, Camera, Static, TagActivate, } impl From for Type { fn from(n: u16) -> Self { match n { 0 => Type::Logon, 1 => Type::Unfinished, 2 => Type::Success, 3 => Type::Failure, 4 => Type::Information, 5 => Type::End, 6 => Type::InterlevelTeleport, 7 => Type::IntralevelTeleport, 8 => Type::Checkpoint, 9 => Type::Sound, 10 => Type::Movie, 11 => Type::Track, 12 => Type::Pict, 13 => Type::Logoff, 14 => Type::Camera, 15 => Type::Static, 16 => Type::TagActivate, _ => panic!("invalid terminal group type {}", n), } } } impl fmt::Debug for Face { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {write!(f, "Face{{{} {} {}}}", self.ind, self.fce, self.col)} } impl fmt::Debug for Group { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Group{{{:?} {} {}", self.typ, self.per, self.lns)?; if self.txt.len() != 0 {write!(f, ";\n{}\n", self.txt)?} write!(f, "}}") } } // EOF