1use std::fmt::Display;
3use std::io::{Read, Seek, Write};
4use std::str::FromStr;
5
6use crate::headers::NitfSegmentHeader;
7use crate::types::{ExtendedSubheader, NitfField, Security};
8use crate::{NitfError, NitfResult};
9#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
11pub struct GraphicHeader {
12 pub sy: NitfField<SY>,
14 pub sid: NitfField<String>,
16 pub sname: NitfField<String>,
18 pub security: Security,
20 pub encryp: NitfField<String>,
22 pub sfmt: NitfField<Format>,
24 pub sstruct: NitfField<u64>,
26 pub sdlvl: NitfField<u16>,
28 pub salvl: NitfField<u16>,
30 pub sloc: NitfField<BoundLocation>, pub sbnd1: NitfField<BoundLocation>,
34 pub scolor: NitfField<Color>,
36 pub sbnd2: NitfField<BoundLocation>,
38 pub sres2: NitfField<u8>,
40 pub sxshdl: NitfField<u16>,
42 pub sxsofl: NitfField<u16>,
44 pub sxshd: ExtendedSubheader,
46}
47impl Default for GraphicHeader {
48 fn default() -> Self {
49 Self {
50 sy: NitfField::init(2u8, "SY"),
51 sid: NitfField::init(10u8, "SID"),
52 sname: NitfField::init(20u8, "SNAME"),
53 security: Security::default(),
54 encryp: NitfField::init(1u8, "ENCRYP"),
55 sfmt: NitfField::init(1u8, "SFMT"),
56 sstruct: NitfField::init(13u8, "SSTRUCT"),
57 sdlvl: NitfField::init(3u8, "SDLVL"),
58 salvl: NitfField::init(3u8, "SALVL"),
59 sloc: NitfField::init(10u8, "SLOC"),
60 sbnd1: NitfField::init(10u8, "SBND1"),
61 scolor: NitfField::init(1u8, "SCOLOR"),
62 sbnd2: NitfField::init(10u8, "SBND2"),
63 sres2: NitfField::init(2u8, "SRES2"),
64 sxshdl: NitfField::init(5u8, "SXSHDL"),
65 sxsofl: NitfField::init(3u8, "SXSOFL"),
66 sxshd: ExtendedSubheader::init("SXSHD"),
67 }
68 }
69}
70#[derive(Default, Clone, Debug, Eq, PartialEq, Copy, Ord, PartialOrd)]
71pub enum SY {
72 #[default]
73 SY,
74}
75impl FromStr for SY {
76 type Err = NitfError;
77 fn from_str(s: &str) -> Result<Self, Self::Err> {
78 match s {
79 "SY" => Ok(Self::default()),
80 _ => Err(NitfError::ParseError("SY".to_string())),
81 }
82 }
83}
84impl Display for SY {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 write!(f, "SY")
87 }
88}
89
90impl Display for GraphicHeader {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 let mut out_str = String::default();
93 out_str += format!("{}, ", self.sy).as_ref();
94 out_str += format!("{}, ", self.sid).as_ref();
95 out_str += format!("{}, ", self.sname).as_ref();
96 out_str += format!("SECURITY: [{}], ", self.security).as_ref();
97 out_str += format!("{}, ", self.encryp).as_ref();
98 out_str += format!("{}, ", self.sfmt).as_ref();
99 out_str += format!("{}, ", self.sstruct).as_ref();
100 out_str += format!("{}, ", self.sdlvl).as_ref();
101 out_str += format!("{}, ", self.salvl).as_ref();
102 out_str += format!("{}, ", self.sloc).as_ref();
103 out_str += format!("{}, ", self.sbnd1).as_ref();
104 out_str += format!("{}, ", self.scolor).as_ref();
105 out_str += format!("{}, ", self.sbnd2).as_ref();
106 out_str += format!("{}, ", self.sres2).as_ref();
107 out_str += format!("{}, ", self.sxshdl).as_ref();
108 out_str += format!("{}, ", self.sxsofl).as_ref();
109 out_str += format!("{}", self.sxshd).as_ref();
110 write!(f, "Graphic Header: [{out_str}]")
111 }
112}
113impl NitfSegmentHeader for GraphicHeader {
114 fn read(&mut self, reader: &mut (impl Read + Seek)) -> NitfResult<()> {
115 self.sy.read(reader)?;
116 self.sid.read(reader)?;
117 self.sname.read(reader)?;
118 self.security.read(reader)?;
119 self.encryp.read(reader)?;
120 self.sfmt.read(reader)?;
121 self.sstruct.read(reader)?;
122 self.sdlvl.read(reader)?;
123 self.salvl.read(reader)?;
124 self.sloc.read(reader)?;
125 self.sbnd1.read(reader)?;
126 self.scolor.read(reader)?;
127 self.sbnd2.read(reader)?;
128 self.sres2.read(reader)?;
129 self.sxshdl.read(reader)?;
130 if self.sxshdl.val != 0 {
131 self.sxsofl.read(reader)?;
132 self.sxshd.read(reader, (self.sxshdl.val - 3) as usize)?;
133 }
134 Ok(())
135 }
136 fn write(&self, writer: &mut (impl Write + Seek)) -> NitfResult<usize> {
137 let mut bytes_written = 0;
138 bytes_written += self.sy.write(writer)?;
139 bytes_written += self.sid.write(writer)?;
140 bytes_written += self.sname.write(writer)?;
141 bytes_written += self.security.write(writer)?;
142 bytes_written += self.encryp.write(writer)?;
143 bytes_written += self.sfmt.write(writer)?;
144 bytes_written += self.sstruct.write(writer)?;
145 bytes_written += self.sdlvl.write(writer)?;
146 bytes_written += self.salvl.write(writer)?;
147 bytes_written += self.sloc.write(writer)?;
148 bytes_written += self.sbnd1.write(writer)?;
149 bytes_written += self.scolor.write(writer)?;
150 bytes_written += self.sbnd2.write(writer)?;
151 bytes_written += self.sres2.write(writer)?;
152 bytes_written += self.sxshdl.write(writer)?;
153 if self.sxshdl.val != 0 {
154 bytes_written += self.sxsofl.write(writer)?;
155 bytes_written += self.sxshd.write(writer)?;
156 }
157 Ok(bytes_written)
158 }
159 fn length(&self) -> usize {
160 let mut length = 0;
161 length += self.sy.length;
162 length += self.sid.length;
163 length += self.sname.length;
164 length += self.security.length();
165 length += self.encryp.length;
166 length += self.sfmt.length;
167 length += self.sstruct.length;
168 length += self.sdlvl.length;
169 length += self.salvl.length;
170 length += self.sloc.length;
171 length += self.sbnd1.length;
172 length += self.scolor.length;
173 length += self.sbnd2.length;
174 length += self.sres2.length;
175 length += self.sxshdl.length;
176 if self.sxshdl.val != 0 {
177 length += self.sxsofl.length;
178 length += self.sxshd.size();
179 }
180 length
181 }
182}
183
184#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
186pub enum Format {
187 #[default]
188 C,
190}
191
192impl FromStr for Format {
193 type Err = NitfError;
194 fn from_str(s: &str) -> Result<Self, Self::Err> {
195 match s {
196 "C" => Ok(Self::C),
197 _ => Err(NitfError::ParseError("Format".to_string())),
198 }
199 }
200}
201impl Display for Format {
202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203 match self {
204 Self::C => write!(f, "C"),
205 }
206 }
207}
208
209#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
211pub struct BoundLocation {
212 pub row: i32,
213 pub col: i32,
214}
215
216impl FromStr for BoundLocation {
217 type Err = NitfError;
218 fn from_str(s: &str) -> Result<Self, Self::Err> {
219 if s.len() == 10 {
220 let bounds = Self {
221 row: s[..5]
222 .parse()
223 .or(Err(NitfError::ParseError("BoundLocation.row".to_string())))?,
224 col: s[5..]
225 .parse()
226 .or(Err(NitfError::ParseError("BoundLocation.col".to_string())))?,
227 };
228 Ok(bounds)
229 } else {
230 Err(NitfError::ParseError("BoundLocation".to_string()))
231 }
232 }
233}
234impl Display for BoundLocation {
235 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
236 write!(f, "{:0<5}{:0<5}", self.row, self.col)
237 }
238}
239#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
241pub enum Color {
242 #[default]
243 C,
245 M,
247}
248
249impl FromStr for Color {
250 type Err = NitfError;
251 fn from_str(s: &str) -> Result<Self, Self::Err> {
252 match s {
253 "C" => Ok(Self::C),
254 "M" => Ok(Self::M),
255 _ => Err(NitfError::ParseError("Color".to_string())),
256 }
257 }
258}
259impl Display for Color {
260 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
261 match self {
262 Self::C => write!(f, "C"),
263 Self::M => write!(f, "M"),
264 }
265 }
266}