use std::borrow::Cow;
use nom::{
bytes::{
complete::{tag, take_until},
streaming::take,
},
multi::count,
number::complete::{be_u16, be_u32},
IResult,
};
use crate::{
images::imc::{decode_imc, MonochromeScreen},
util::{Buf, Bytes16, Bytes32},
};
use super::{bytes16, bytes32};
#[derive(Debug)]
pub struct HCIMHeader {
pub header_length: u32,
pub img_count: u16,
pub site_count: u16,
pub c: Bytes32,
pub d: Bytes32,
}
#[derive(Debug)]
#[allow(non_snake_case)]
pub struct ImageSite {
pub page: u16,
pub site: ImageArea,
pub _5: u16,
pub sel: ImageArea,
pub _A: u16,
pub _B: u16,
pub _C: u16,
pub img: u16,
pub _E: u16,
pub _F: Bytes16,
}
#[derive(Debug, Copy, Clone)]
pub struct ImageArea {
pub x: u16,
pub y: u16,
pub w: u16,
pub h: u16,
}
#[derive(Debug)]
pub struct HCIM<'a> {
pub header: HCIMHeader,
pub sites: Vec<ImageSite>,
pub images: Vec<Buf<'a>>,
}
pub fn parse_image_buf(input: &[u8]) -> IResult<&[u8], Buf> {
let (input, length2) = be_u32(input)?;
let (input, buf2) = take((length2 - 4) as usize)(input)?;
Ok((input, Buf(buf2)))
}
#[derive(Debug)]
pub struct Image<'a> {
pub key: Cow<'a, str>,
pub bytes: Buf<'a>,
pub image: MonochromeScreen,
}
const ZERO: &[u8] = &[0];
pub fn parse_image(input: &[u8]) -> IResult<&[u8], Image> {
let (input, key_bytes) = take_until(ZERO)(input)?;
let key = String::from_utf8_lossy(key_bytes);
let (input, _) = tag(ZERO)(input)?;
let (input, bytes) = take(27usize - key_bytes.len())(input)?;
let (input, image) = decode_imc(input)?;
let bytes = Buf(bytes);
Ok((input, Image { key, bytes, image }))
}
pub fn parse_hcim_header(input: &[u8]) -> IResult<&[u8], HCIMHeader> {
let (input, header_length) = be_u32(input)?;
let (input, img_count) = be_u16(input)?;
let (input, site_count) = be_u16(input)?;
let (input, c) = bytes32(input)?;
let (input, d) = bytes32(input)?;
Ok((
input,
HCIMHeader {
header_length,
img_count,
site_count,
c,
d,
},
))
}
#[allow(non_snake_case, clippy::just_underscores_and_digits)]
pub fn parse_hcim_img_ref(input: &[u8]) -> IResult<&[u8], ImageSite> {
let (input, page) = be_u16(input)?;
let (input, site_x) = be_u16(input)?;
let (input, site_y) = be_u16(input)?;
let (input, site_w) = be_u16(input)?;
let (input, site_h) = be_u16(input)?;
let (input, _5) = be_u16(input)?;
let (input, sel_x) = be_u16(input)?;
let (input, sel_y) = be_u16(input)?;
let (input, sel_w) = be_u16(input)?;
let (input, sel_h) = be_u16(input)?;
let (input, _A) = be_u16(input)?;
let (input, _B) = be_u16(input)?;
let (input, _C) = be_u16(input)?;
let (input, img) = be_u16(input)?;
let (input, _E) = be_u16(input)?;
let (input, _F) = bytes16(input)?;
Ok((
input,
ImageSite {
page,
site: ImageArea {
x: site_x,
y: site_y,
w: site_w,
h: site_h,
},
_5,
sel: ImageArea {
x: sel_x,
y: sel_y,
w: sel_w,
h: sel_h,
},
_A,
_B,
_C,
img,
_E,
_F,
},
))
}
pub fn parse_hcim(input: &[u8]) -> IResult<&[u8], HCIM> {
let (input, header) = parse_hcim_header(input)?;
let (input, buf) = take(header.header_length as usize)(input)?;
let (_, sites) = count(parse_hcim_img_ref, header.site_count as usize)(buf)?;
let (input, images) = count(parse_image_buf, header.img_count as usize)(input)?;
Ok((
input,
HCIM {
header,
sites,
images,
},
))
}