use std::fmt::Display;
use std::fs::File;
use std::str::FromStr;
use crate::error::NitfError;
use crate::headers::NitfSegmentHeader;
use crate::types::{NitfField, Security, ExtendedSubheader};
#[derive(Default, Clone, Debug, Eq, PartialEq)]
pub struct GraphicHeader {
pub sy: NitfField<String>,
pub sid: NitfField<String>,
pub sname: NitfField<String>,
pub security: Security,
pub encryp: NitfField<String>,
pub sfmt: NitfField<Format>,
pub sstruct: NitfField<u64>,
pub sdlvl: NitfField<u16>,
pub salvl: NitfField<u16>,
pub sloc: NitfField<String>, pub sbnd1: NitfField<BoundLocation>,
pub scolor: NitfField<Color>,
pub sbnd2: NitfField<BoundLocation>,
pub sres2: NitfField<u8>,
pub sxshdl: NitfField<u16>,
pub sxsofl: NitfField<u16>,
pub sxshd: ExtendedSubheader,
}
impl Display for GraphicHeader {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut out_str = String::default();
out_str += format!("SY: {}, ", self.sy).as_ref();
out_str += format!("SID: {}, ", self.sid).as_ref();
out_str += format!("SNAME: {}, ", self.sname).as_ref();
out_str += format!("SECURITY: [{}], ", self.security).as_ref();
out_str += format!("ENCRYP: {}, ", self.encryp).as_ref();
out_str += format!("SFMT: {}, ", self.sfmt).as_ref();
out_str += format!("SSTRUCT: {}, ", self.sstruct).as_ref();
out_str += format!("SDLVL: {}, ", self.sdlvl).as_ref();
out_str += format!("SALVL: {}, ", self.salvl).as_ref();
out_str += format!("SLOC: {}, ", self.sloc).as_ref();
out_str += format!("SBND1: {}, ", self.sbnd1).as_ref();
out_str += format!("SCOLOR: {}, ", self.scolor).as_ref();
out_str += format!("SBND2: {}, ", self.sbnd2).as_ref();
out_str += format!("SRES2: {}, ", self.sres2).as_ref();
out_str += format!("SXSHDL: {}, ", self.sxshdl).as_ref();
out_str += format!("SXSOFL: {}, ", self.sxsofl).as_ref();
out_str += format!("[SXSHD: {}]", self.sxshd).as_ref();
write!(f, "[Graphic Subheader: {out_str}]")
}
}
impl NitfSegmentHeader for GraphicHeader {
fn read(&mut self, reader: &mut File) {
self.sy.read(reader, 2u8);
self.sid.read(reader, 10u8);
self.sname.read(reader, 20u8);
self.security.read(reader);
self.encryp.read(reader, 1u8);
self.sfmt.read(reader, 1u8);
self.sstruct.read(reader, 13u8);
self.sdlvl.read(reader, 3u8);
self.salvl.read(reader, 3u8);
self.sloc.read(reader, 10u8);
self.sbnd1.read(reader, 10u8);
self.scolor.read(reader, 1u8);
self.sbnd2.read(reader, 10u8);
self.sres2.read(reader, 2u8);
self.sxshdl.read(reader, 5u8);
let gphx_data_length = self.sxshdl.val;
if gphx_data_length != 0 {
self.sxsofl.read(reader, 3u8);
self.sxshd.read(reader, (gphx_data_length - 3) as usize);
}
}
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub enum Format {
#[default]
C,
}
impl FromStr for Format {
type Err = NitfError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"C" => Ok(Self::C),
_ => Err(NitfError::FieldError),
}
}
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct BoundLocation {
pub row: i32,
pub col: i32,
}
impl FromStr for BoundLocation {
type Err = NitfError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let n_char_tot = s.len();
if n_char_tot % 2 == 0 {
let mut bounds = Self::default();
let n_char = n_char_tot / 2;
bounds.row = s[..n_char].parse().unwrap();
bounds.col = s[n_char..].parse().unwrap();
Ok(bounds)
} else {
Err(NitfError::FieldError)
}
}
}
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub enum Color {
#[default]
C,
M,
}
impl FromStr for Color {
type Err = NitfError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"C" => Ok(Self::C),
"M" => Ok(Self::M),
_ => Err(NitfError::FieldError),
}
}
}