mod codepage437;
mod larini_decoder;
pub use codepage437::*;
pub use larini_decoder::*;
use p101_is::*;
use crate::encoding::*;
pub struct Decoder<E: Encoding> {
encoding: E,
cai_mode: bool
}
impl<E> Decoder<E> where E: Encoding + Default {
pub fn new() -> Self {
Decoder {
encoding: Default::default(),
cai_mode: false
}
}
pub fn decode(&mut self, text: &str) -> Result<Vec<Instruction>, String> {
let mut program = Vec::new();
let mut line_number = 1;
for line in text.lines() {
match self.decode_line(line) {
DecodeResult::Ok(i) => {
self.set_mode(&i);
program.push(i)
},
DecodeResult::None => (),
DecodeResult::Err(e) => {
return Err(format!("{} at line {}", e, line_number))
}
}
line_number += 1
}
if !program.is_empty() {
Ok(program)
} else {
Err("No text to decode".into())
}
}
fn decode_line(&self, line: &str) -> DecodeResult {
if self.cai_mode {
self.encoding.decode_cai(line)
} else {
self.encoding.decode_instr(line)
}
}
fn set_mode(&mut self, i: &Instruction) {
match i {
Instruction::Cai(_, order, _, _) => {
self.cai_mode = *order == CaiOrder::Low;
},
Instruction::CaiStart => self.cai_mode = true,
_ => ()
}
}
}
impl<E> Default for Decoder<E> where E: Encoding + Default {
fn default() -> Self {
Self::new()
}
}