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