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 NitfHeader {
12 pub fhdr: NitfField<FHDR>,
14 pub fver: NitfField<FVER>,
16 pub clevel: NitfField<u8>,
18 pub stype: NitfField<String>,
20 pub ostaid: NitfField<String>,
22 pub fdt: NitfField<String>,
24 pub ftitle: NitfField<String>,
26 pub security: Security,
28 pub fscop: NitfField<u32>,
30 pub fscpys: NitfField<u32>,
32 pub encryp: NitfField<String>,
34 pub fbkgc: Vec<NitfField<String>>, pub oname: NitfField<String>,
38 pub ophone: NitfField<String>,
40 pub fl: NitfField<u64>,
42 pub hl: NitfField<u32>,
44 pub numi: NitfField<u16>,
46 pub imheaders: Vec<SubHeader>,
48 pub nums: NitfField<u16>,
50 pub graphheaders: Vec<SubHeader>,
52 pub numx: NitfField<u16>,
54 pub numt: NitfField<u16>,
56 pub textheaders: Vec<SubHeader>,
58 pub numdes: NitfField<u16>,
60 pub dextheaders: Vec<SubHeader>,
62 pub numres: NitfField<u16>,
64 pub resheaders: Vec<SubHeader>,
66 pub udhdl: NitfField<u32>,
68 pub udhofl: NitfField<u16>,
70 pub udhd: ExtendedSubheader, pub xhdl: NitfField<u32>,
74 pub xhdlofl: NitfField<u16>,
76 pub xhd: ExtendedSubheader,
78}
79
80#[derive(Default, Clone, Debug, Eq, PartialEq, Copy, Ord, PartialOrd)]
81pub enum FHDR {
82 #[default]
83 NITF,
84}
85impl FromStr for FHDR {
86 type Err = NitfError;
87 fn from_str(s: &str) -> Result<Self, Self::Err> {
88 match s {
89 "NITF" => Ok(Self::default()),
90 _ => Err(NitfError::ParseError("FHDR".to_string())),
91 }
92 }
93}
94impl Display for FHDR {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 write!(f, "NITF")
97 }
98}
99
100#[derive(Default, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
101pub enum FVER {
102 #[default]
103 V02_10,
104}
105impl FromStr for FVER {
106 type Err = NitfError;
107 fn from_str(s: &str) -> Result<Self, Self::Err> {
108 match s {
109 "02.10" => Ok(Self::default()),
110 _ => Err(NitfError::ParseError("FVER".to_string())),
111 }
112 }
113}
114impl Display for FVER {
115 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116 write!(f, "02.10")
117 }
118}
119pub(crate) enum Segment {
120 Image,
121 Graphic,
122 Text,
123 DataExtension,
124 ReservedExtension,
125}
126impl Segment {
127 pub fn size(&self) -> (u8, u8) {
128 match self {
129 Self::Image => (6u8, 10u8),
130 Self::Graphic => (4u8, 6u8),
131 Self::Text => (4u8, 5u8),
132 Self::DataExtension => (4u8, 9u8),
133 Self::ReservedExtension => (4u8, 7u8),
134 }
135 }
136}
137
138impl NitfHeader {
139 pub(crate) fn write_header(
140 &mut self,
141 writer: &mut (impl Write + Seek),
142 file_length: u64,
143 ) -> NitfResult<usize> {
144 self.hl.val = self.length() as u32;
145 self.fl.val = file_length;
146 self.write(writer)
147 }
148 pub(crate) fn add_subheader(
149 &mut self,
150 segment_type: Segment,
151 subheader_size: u32,
152 item_size: u64,
153 ) {
154 use Segment::*;
155 let mut subheader = SubHeader::new(&segment_type);
156 subheader.subheader_size.val = subheader_size;
157 subheader.item_size.val = item_size;
158
159 match segment_type {
160 Image => {
161 self.numi.val += 1;
162 self.imheaders.push(subheader);
163 }
164 Graphic => {
165 self.nums.val += 1;
166 self.graphheaders.push(subheader);
167 }
168 Text => {
169 self.numt.val += 1;
170 self.textheaders.push(subheader);
171 }
172 DataExtension => {
173 self.numdes.val += 1;
174 self.dextheaders.push(subheader);
175 }
176 ReservedExtension => {
177 self.numres.val += 1;
178 self.resheaders.push(subheader);
179 }
180 }
181 }
182}
183impl Default for NitfHeader {
184 fn default() -> Self {
185 Self {
186 fhdr: NitfField::init(4u8, "FHDR"),
187 fver: NitfField::init(5u8, "FVER"),
188 clevel: NitfField::init(2u8, "CLEVEL"),
189 stype: NitfField::init(4u8, "STYPE"),
190 ostaid: NitfField::init(10u8, "OSTAID"),
191 fdt: NitfField::init(14u8, "FDT"),
192 ftitle: NitfField::init(80u8, "FTITLE"),
193 security: Security::default(),
194 fscop: NitfField::init(5u8, "FSCOP"),
195 fscpys: NitfField::init(5u8, "FSCPYS"),
196 encryp: NitfField::init(1u8, "ENCRYP"),
197 fbkgc: vec![NitfField::init(1u8, "FBKGC"); 3],
198 oname: NitfField::init(24u8, "ONAME"),
199 ophone: NitfField::init(18u8, "OPHONE"),
200 fl: NitfField::init(12u8, "FL"),
201 hl: NitfField::init(6u8, "HL"),
202 numi: NitfField::init(3u8, "NUMI"),
203 imheaders: vec![],
204 nums: NitfField::init(3u8, "NUMS"),
205 graphheaders: vec![],
206 numx: NitfField::init(3u8, "NUMX"),
207 numt: NitfField::init(3u8, "NUMT"),
208 textheaders: vec![],
209 numdes: NitfField::init(3u8, "NUMDES"),
210 dextheaders: vec![],
211 numres: NitfField::init(3u8, "NUMRES"),
212 resheaders: vec![],
213 udhdl: NitfField::init(5u8, "UDHDL"),
214 udhofl: NitfField::init(3u8, "UDHOFL"),
215 udhd: ExtendedSubheader::init("UDHD"),
216 xhdl: NitfField::init(5u8, "XHDL"),
217 xhdlofl: NitfField::init(3u8, "XHDLOFL"),
218 xhd: ExtendedSubheader::init("XHD"),
219 }
220 }
221}
222impl Display for NitfHeader {
223 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
224 let mut out_str = String::default();
225 out_str += format!("{}, ", self.fhdr).as_ref();
226 out_str += format!("{}, ", self.clevel).as_ref();
227 out_str += format!("{}, ", self.stype).as_ref();
228 out_str += format!("{}, ", self.ostaid).as_ref();
229 out_str += format!("{}, ", self.fdt).as_ref();
230 out_str += format!("{}, ", self.ftitle).as_ref();
231 out_str += format!("SECURITY: [{}], ", self.security).as_ref();
232 out_str += format!("{}, ", self.fscop).as_ref();
233 out_str += format!("{}, ", self.fscpys).as_ref();
234 out_str += format!("{}, ", self.encryp).as_ref();
235 out_str += format!(
236 "FBKGC: [R: {}, G: {}, B: {}], ",
237 self.fbkgc[0], self.fbkgc[1], self.fbkgc[2],
238 )
239 .as_ref();
240 out_str += format!("{}, ", self.oname).as_ref();
241 out_str += format!("{}, ", self.ophone).as_ref();
242 out_str += format!("{}, ", self.fl).as_ref();
243 out_str += format!("{}, ", self.hl).as_ref();
244 out_str += format!("{}, ", self.numi).as_ref();
245 for (i_seg, seg) in self.imheaders.iter().enumerate() {
246 out_str += format!("Image Segment {i_seg}: [{seg}], ").as_ref();
247 }
248 out_str += format!("{}, ", self.nums).as_ref();
249 for (i_seg, seg) in self.graphheaders.iter().enumerate() {
250 out_str += format!("Graphic Segment {i_seg}: [{seg}], ").as_ref();
251 }
252 out_str += format!("{}, ", self.numx).as_ref();
253 out_str += format!("{}, ", self.numt).as_ref();
254 for (i_seg, seg) in self.textheaders.iter().enumerate() {
255 out_str += format!("Text Segment {i_seg}: [{seg}], ").as_ref();
256 }
257 out_str += format!("{}, ", self.numdes).as_ref();
258 for (i_seg, seg) in self.dextheaders.iter().enumerate() {
259 out_str += format!("Data Extension Segment {i_seg}: [{seg}], ").as_ref();
260 }
261 out_str += format!("{}, ", self.numres).as_ref();
262 for (i_seg, seg) in self.resheaders.iter().enumerate() {
263 out_str += format!("Reserved Extension Segment {i_seg}: [{seg}], ").as_ref();
264 }
265 out_str += format!("{}, ", self.udhdl).as_ref();
266 out_str += format!("{}, ", self.udhofl).as_ref();
267 out_str += format!("{}, ", self.udhd).as_ref();
268 out_str += format!("{}, ", self.xhdl).as_ref();
269 out_str += format!("{}, ", self.xhdlofl).as_ref();
270 out_str += format!("{}", self.xhd).as_ref();
271 write!(f, "Nitf Header: [{out_str}]")
272 }
273}
274
275impl NitfSegmentHeader for NitfHeader {
276 fn read(&mut self, reader: &mut (impl Read + Seek)) -> NitfResult<()> {
277 self.fhdr.read(reader)?;
278 self.fver.read(reader)?;
279 self.clevel.read(reader)?;
280 self.stype.read(reader)?;
281 self.ostaid.read(reader)?;
282 self.fdt.read(reader)?;
283 self.ftitle.read(reader)?;
284 self.security.read(reader)?;
285 self.fscop.read(reader)?;
286 self.fscpys.read(reader)?;
287 self.encryp.read(reader)?;
288 self.fbkgc = vec![NitfField::init(1u8, "FBKGC"); 3];
289 self.fbkgc
290 .iter_mut()
291 .try_for_each(|color| color.read(reader))?;
292
293 self.oname.read(reader)?;
294 self.ophone.read(reader)?;
295 self.fl.read(reader)?;
296 self.hl.read(reader)?;
297 self.numi.read(reader)?;
298 self.imheaders = vec![SubHeader::new(&Segment::Image); self.numi.val.into()];
299 self.imheaders
300 .iter_mut()
301 .try_for_each(|hdr| hdr.read(reader))?;
302
303 self.nums.read(reader)?;
304 self.graphheaders = vec![SubHeader::new(&Segment::Graphic); self.nums.val.into()];
305 self.graphheaders
306 .iter_mut()
307 .try_for_each(|hdr| hdr.read(reader))?;
308
309 self.numx.read(reader)?;
310 self.numt.read(reader)?;
311 self.textheaders = vec![SubHeader::new(&Segment::Text); self.numt.val.into()];
312 self.textheaders
313 .iter_mut()
314 .try_for_each(|hdr| hdr.read(reader))?;
315
316 self.numdes.read(reader)?;
317 self.dextheaders = vec![SubHeader::new(&Segment::DataExtension); self.numdes.val.into()];
318 self.dextheaders
319 .iter_mut()
320 .try_for_each(|hdr| hdr.read(reader))?;
321
322 self.numres.read(reader)?;
323 self.resheaders = vec![SubHeader::new(&Segment::ReservedExtension); self.numres.val.into()];
324 self.resheaders
325 .iter_mut()
326 .try_for_each(|hdr| hdr.read(reader))?;
327
328 self.udhdl.read(reader)?;
329 if self.udhdl.val != 0 {
330 self.udhofl.read(reader)?;
331 self.udhd.read(reader, (self.udhdl.val - 3) as usize)?;
332 }
333
334 self.xhdl.read(reader)?;
335 if self.xhdl.val != 0 {
336 self.xhdlofl.read(reader)?;
337 self.xhd.read(reader, (self.xhdl.val - 3) as usize)?;
338 }
339 Ok(())
340 }
341 fn write(&self, writer: &mut (impl Write + Seek)) -> NitfResult<usize> {
342 let mut bytes_written = self.fhdr.write(writer)?;
343 bytes_written += self.fver.write(writer)?;
344 bytes_written += self.clevel.write(writer)?;
345 bytes_written += self.stype.write(writer)?;
346 bytes_written += self.ostaid.write(writer)?;
347 bytes_written += self.fdt.write(writer)?;
348 bytes_written += self.ftitle.write(writer)?;
349 bytes_written += self.security.write(writer)?;
350 bytes_written += self.fscop.write(writer)?;
351 bytes_written += self.fscpys.write(writer)?;
352 bytes_written += self.encryp.write(writer)?;
353 for color in &self.fbkgc {
354 bytes_written += color.write(writer)?;
355 }
356 bytes_written += self.oname.write(writer)?;
357 bytes_written += self.ophone.write(writer)?;
358 bytes_written += self.fl.write(writer)?;
359 bytes_written += self.hl.write(writer)?;
360 bytes_written += self.numi.write(writer)?;
361 for subheader in &self.imheaders {
362 bytes_written += subheader.write(writer)?;
363 }
364
365 bytes_written += self.nums.write(writer)?;
366 for subheader in &self.graphheaders {
367 bytes_written += subheader.write(writer)?;
368 }
369
370 bytes_written += self.numx.write(writer)?;
371 bytes_written += self.numt.write(writer)?;
372 for subheader in &self.textheaders {
373 bytes_written += subheader.write(writer)?;
374 }
375
376 bytes_written += self.numdes.write(writer)?;
377 for subheader in &self.dextheaders {
378 bytes_written += subheader.write(writer)?;
379 }
380
381 bytes_written += self.numres.write(writer)?;
382 for subheader in &self.resheaders {
383 bytes_written += subheader.write(writer)?;
384 }
385
386 bytes_written += self.udhdl.write(writer)?;
387 if self.udhdl.val != 0 {
388 bytes_written += self.udhofl.write(writer)?;
389 bytes_written += self.udhd.write(writer)?;
390 }
391
392 bytes_written += self.xhdl.write(writer)?;
393 if self.xhdl.val != 0 {
394 bytes_written += self.xhdlofl.write(writer)?;
395 bytes_written += self.xhd.write(writer)?;
396 }
397 Ok(bytes_written)
398 }
399 fn length(&self) -> usize {
400 let mut length = self.fhdr.length;
401 length += self.fver.length;
402 length += self.clevel.length;
403 length += self.stype.length;
404 length += self.ostaid.length;
405 length += self.fdt.length;
406 length += self.ftitle.length;
407 length += self.security.length();
408 length += self.fscop.length;
409 length += self.fscpys.length;
410 length += self.encryp.length;
411 length += self.fbkgc.iter().map(|c| c.length).sum::<usize>();
412 length += self.oname.length;
413 length += self.ophone.length;
414 length += self.fl.length;
415 length += self.hl.length;
416 length += self.numi.length;
417 length += self.imheaders.iter().map(|s| s.length()).sum::<usize>();
418 length += self.nums.length;
419 length += self.graphheaders.iter().map(|s| s.length()).sum::<usize>();
420 length += self.numx.length;
421 length += self.numt.length;
422 length += self.textheaders.iter().map(|s| s.length()).sum::<usize>();
423 length += self.numdes.length;
424 length += self.dextheaders.iter().map(|s| s.length()).sum::<usize>();
425 length += self.numres.length;
426 length += self.resheaders.iter().map(|s| s.length()).sum::<usize>();
427 length += self.udhdl.length;
428 if self.udhdl.val != 0 {
429 length += self.udhofl.length;
430 length += self.udhd.size();
431 }
432 length += self.xhdl.length;
433 if self.xhdl.val != 0 {
434 length += self.xhdlofl.length;
435 length += self.xhd.size();
436 }
437 length
438 }
439}
440
441#[derive(Default, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
445pub struct SubHeader {
446 pub subheader_size: NitfField<u32>,
448 pub item_size: NitfField<u64>,
450}
451impl SubHeader {
452 pub fn init(subheader_len: u8, item_len: u8) -> Self {
453 Self {
454 subheader_size: NitfField::init(subheader_len, "SUBHEADER_SIZE"),
455 item_size: NitfField::init(item_len, "ITEM_SIZE"),
456 }
457 }
458
459 pub fn read(&mut self, reader: &mut (impl Read + Seek)) -> NitfResult<()> {
460 self.subheader_size.read(reader)?;
461 self.item_size.read(reader)?;
462 Ok(())
463 }
464
465 pub fn write(&self, writer: &mut (impl Write + Seek)) -> NitfResult<usize> {
466 let mut bytes_written = self.subheader_size.write(writer)?;
467 bytes_written += self.item_size.write(writer)?;
468 Ok(bytes_written)
469 }
470
471 pub fn length(&self) -> usize {
472 self.subheader_size.length + self.item_size.length
473 }
474
475 pub(crate) fn new(segment_type: &Segment) -> Self {
476 let (sh_size, item_size) = Segment::size(segment_type);
477 SubHeader::init(sh_size, item_size)
478 }
479}
480impl Display for SubHeader {
481 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
482 write!(f, "{}, {}", self.subheader_size, self.item_size)
483 }
484}