nitf_rs/headers/
file_hdr.rs

1//! File header definition
2use 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/// Metadata for Nitf File Header
10#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
11pub struct NitfHeader {
12    /// File Profile Name
13    pub fhdr: NitfField<FHDR>,
14    /// File Version
15    pub fver: NitfField<FVER>,
16    /// Complexity Level
17    pub clevel: NitfField<u8>,
18    /// Standard Type
19    pub stype: NitfField<String>,
20    /// Originating Station ID
21    pub ostaid: NitfField<String>,
22    /// File Date and Time
23    pub fdt: NitfField<String>,
24    /// File Title
25    pub ftitle: NitfField<String>,
26    /// Security information
27    pub security: Security,
28    /// File Copy Number
29    pub fscop: NitfField<u32>,
30    /// File Number of Copies
31    pub fscpys: NitfField<u32>,
32    /// Encryption
33    pub encryp: NitfField<String>,
34    /// File Background Color
35    pub fbkgc: Vec<NitfField<String>>, // TODO: Fix the parsing of this
36    /// Originator's Name
37    pub oname: NitfField<String>,
38    /// Originator's Phone Number
39    pub ophone: NitfField<String>,
40    /// File Length
41    pub fl: NitfField<u64>,
42    /// NITF File Header Length
43    pub hl: NitfField<u32>,
44    /// Number of Image Segments
45    pub numi: NitfField<u16>,
46    /// Image Segments
47    pub imheaders: Vec<SubHeader>,
48    /// Number of Graphics Segments
49    pub nums: NitfField<u16>,
50    /// Graphic Segments
51    pub graphheaders: Vec<SubHeader>,
52    /// Reserved for future use
53    pub numx: NitfField<u16>,
54    /// Number of Text Segments
55    pub numt: NitfField<u16>,
56    /// Text Segments
57    pub textheaders: Vec<SubHeader>,
58    /// Number of Data Extension Segments
59    pub numdes: NitfField<u16>,
60    /// Data Extenstion Segments
61    pub dextheaders: Vec<SubHeader>,
62    /// Number of Reserved Extension Segments
63    pub numres: NitfField<u16>,
64    /// Reserved Extension Segments
65    pub resheaders: Vec<SubHeader>,
66    /// User Defined Header Data Length
67    pub udhdl: NitfField<u32>,
68    /// User Defined Header Overflow
69    pub udhofl: NitfField<u16>,
70    /// User Defined Header Data
71    pub udhd: ExtendedSubheader, // TODO: Figure out what to do with this
72    /// Extended Header Data Length
73    pub xhdl: NitfField<u32>,
74    /// Extended Header Data Overflow
75    pub xhdlofl: NitfField<u16>,
76    /// Extended Header Data
77    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/// Subheader element type
442///
443/// Used within the NITF header to denote the subheader segments contained in the file
444#[derive(Default, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
445pub struct SubHeader {
446    /// Bytes of header description
447    pub subheader_size: NitfField<u32>,
448    /// Bytes of the data
449    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}