Maraiah/src/marathon/term.rs

144 lines
2.9 KiB
Rust

use crate::durandal::{bin::*, chunk::*, err::*, text::*};
use serde::Serialize;
use std::fmt;
fn read_group(b: &[u8], text: &[u8]) -> ResultS<Group>
{
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)?;
let text = c_data(text, start..start + size)?;
let text = mac_roman_conv(text);
let ttype = GroupType::from_repr(ttype)?;
Ok(Group{ttype, pdata, lines, text})
}
fn read_face(b: &[u8]) -> ResultS<Face>
{
let start = c_u16b(b, 0)? as usize;
let face = c_u16b(b, 2)?;
let color = c_u16b(b, 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 = 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;
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 = c_data(b, text_st..end)?;
let text = if encoded {
fuck_string(text)
} else {
text.to_vec()
};
for _ in 0..group_n {
groups.push(read_group(c_data(b, p..)?, &text)?);
p += SIZE_GROUP;
}
for _ in 0..face_n {
faces.push(read_face(c_data(b, p..)?)?);
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() {
let (size, trm) = read_terminal(c_data(b, p..)?)?;
v.push(trm);
p += size;
}
Ok(v)
}
}
#[derive(Debug, Serialize)]
pub struct Terminal
{
lines: u16,
groups: Vec<Group>,
faces: Vec<Face>,
}
#[derive(Debug, Serialize)]
pub struct Face
{
start: usize,
face: u16,
color: u16,
}
#[derive(Serialize)]
pub struct Group
{
ttype: GroupType,
pdata: i16,
lines: u16,
text: String,
}
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