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