1use log::{trace, warn};
3use memmap2::{Mmap, MmapOptions};
4use std::fmt::{Debug, Display};
5use std::io::{Read, Seek, Write};
6use std::ops::Deref;
7use std::str::FromStr;
8
9use crate::headers::NitfSegmentHeader;
10use crate::{NitfError, NitfResult};
11
12#[derive(Default, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
14pub struct NitfField<V: FromStr + Debug + Default + Display> {
15 pub val: V,
17 pub length: usize,
19 pub name: String,
21}
22
23impl<V> NitfField<V>
25where
26 V: FromStr + Debug + Default + Display,
27 <V as FromStr>::Err: Debug,
28{
29 pub fn init(length: u8, name: &str) -> Self {
30 Self {
31 val: V::default(),
32 length: length.into(),
33 name: name.to_string(),
34 }
35 }
36 pub fn read(&mut self, reader: &mut (impl Read + Seek)) -> NitfResult<()> {
40 let mut bytes = vec![0; self.length];
41 let string;
42
43 let offset = reader
45 .stream_position()
46 .or(Err(NitfError::ReadFatal(self.name.clone())))?;
47
48 reader
50 .read_exact(&mut bytes)
51 .or(Err(NitfError::ReadFatal(self.name.clone())))?;
52
53 match String::from_utf8(bytes.to_vec()) {
55 Ok(str) => {
57 string = str.clone();
58 self.val = str.trim().parse().unwrap_or_else(|e| {
60 warn!("Non-fatal error parsing {}: {e:?}", self.name);
61 V::default()
62 });
63 }
64
65 Err(_) => {
66 string = "Error parsing to string".to_string();
67 warn!("Failed to parse {} from bytes: {bytes:?}", self.name);
68 }
69 }
70 trace!("Read {} at offset {offset}: {string}", self.name);
71 Ok(())
72 }
73
74 pub fn write(&self, writer: &mut (impl Write + Seek)) -> NitfResult<usize> {
75 let buf = format!("{:<1$}", self.val.to_string(), self.length);
76 let offset = writer.stream_position()?;
77 trace!(
78 "Wrote {} bytes for {} at offset {offset}: {buf}",
79 buf.len(),
80 self.name
81 );
82 writer.write(buf.as_bytes()).map_err(NitfError::IOError)
83 }
84}
85
86impl<V: FromStr + Debug + Default + Display> Display for NitfField<V> {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 write!(
89 f,
90 "{}: {:<2$}",
91 self.name,
92 self.val.to_string(),
93 self.length
94 )
95 }
96}
97
98#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord)]
99pub struct NitfSegment<T: NitfSegmentHeader> {
100 pub header: T,
102 pub header_offset: u64,
104 pub data_size: u64,
106 pub data_offset: u64,
108}
109impl<T: NitfSegmentHeader> NitfSegment<T> {
110 pub(crate) fn read(reader: &mut (impl Read + Seek), data_size: u64) -> NitfResult<Self> {
111 let header_offset = reader.stream_position()?;
112 let header = T::from_reader(reader)?;
113 let data_offset = reader.stream_position()?;
114
115 reader.seek(std::io::SeekFrom::Start(data_offset + data_size))?;
117 Ok(Self {
118 header,
119 header_offset,
120 data_size,
121 data_offset,
122 })
123 }
124
125 pub(crate) fn write_header(&mut self, writer: &mut (impl Write + Seek)) -> NitfResult<usize> {
127 writer.seek(std::io::SeekFrom::Start(self.header_offset))?;
128 let bytes_written = self.header.write(writer)?;
129 self.data_offset = writer.stream_position()?;
130 Ok(bytes_written)
131 }
132
133 pub fn get_data_map(&self, reader: &mut std::fs::File) -> NitfResult<Mmap> {
135 if self.data_offset == 0 {
136 Err(NitfError::Fatal(
137 "Data offset location is not set. Cannot read data".to_string(),
138 ))?
139 }
140 let mut opts = MmapOptions::new();
141 Ok(unsafe {
142 opts.len(self.data_size as usize)
143 .offset(self.data_offset)
144 .map(reader.deref())
145 }?)
146 }
147 pub fn write_data(&self, writer: &mut (impl Write + Seek), data: &[u8]) -> NitfResult<usize> {
149 writer.seek(std::io::SeekFrom::Start(self.data_offset))?;
150 writer.write(data).map_err(NitfError::IOError)
151 }
152 pub fn length(&self) -> usize {
153 self.header.length() + self.data_size as usize
154 }
155}
156impl<T: NitfSegmentHeader + Display> Display for NitfSegment<T> {
157 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158 write!(f, "{}", self.header)
159 }
160}
161#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
163pub struct Security {
164 pub clas: NitfField<Classification>,
166 pub clsy: NitfField<String>, pub code: NitfField<String>,
170 pub ctlh: NitfField<String>,
172 pub rel: NitfField<String>,
174 pub dctp: NitfField<DeclassificationType>,
176 pub dcdt: NitfField<String>,
178 pub dcxm: NitfField<DeclassificationExemption>,
180 pub dg: NitfField<Downgrade>,
182 pub dgdt: NitfField<String>,
184 pub cltx: NitfField<String>,
186 pub catp: NitfField<ClassificationAuthorityType>,
188 pub caut: NitfField<String>,
190 pub crsn: NitfField<ClassificationReason>, pub srdt: NitfField<String>,
194 pub ctln: NitfField<String>,
196}
197
198impl Default for Security {
199 fn default() -> Self {
200 Self {
201 clas: NitfField::init(1u8, "CLAS"),
202 clsy: NitfField::init(2u8, "CLSY"),
203 code: NitfField::init(11u8, "CODE"),
204 ctlh: NitfField::init(2u8, "CTLH"),
205 rel: NitfField::init(20u8, "REL"),
206 dctp: NitfField::init(2u8, "DCTP"),
207 dcdt: NitfField::init(8u8, "DCDT"),
208 dcxm: NitfField::init(4u8, "DCXM"),
209 dg: NitfField::init(1u8, "DG"),
210 dgdt: NitfField::init(8u8, "DGDT"),
211 cltx: NitfField::init(43u8, "CLTX"),
212 catp: NitfField::init(1u8, "CATP"),
213 caut: NitfField::init(40u8, "CAUT"),
214 crsn: NitfField::init(1u8, "CRSN"),
215 srdt: NitfField::init(8u8, "SRDT"),
216 ctln: NitfField::init(15u8, "CTLN"),
217 }
218 }
219}
220
221impl Security {
222 pub fn read(&mut self, reader: &mut (impl Read + Seek)) -> NitfResult<()> {
223 self.clas.read(reader)?;
224 self.clsy.read(reader)?;
225 self.code.read(reader)?;
226 self.ctlh.read(reader)?;
227 self.rel.read(reader)?;
228 self.dctp.read(reader)?;
229 self.dcdt.read(reader)?;
230 self.dcxm.read(reader)?;
231 self.dg.read(reader)?;
232 self.dgdt.read(reader)?;
233 self.cltx.read(reader)?;
234 self.catp.read(reader)?;
235 self.caut.read(reader)?;
236 self.crsn.read(reader)?;
237 self.srdt.read(reader)?;
238 self.ctln.read(reader)?;
239 Ok(())
240 }
241 pub fn write(&self, writer: &mut (impl Write + Seek)) -> NitfResult<usize> {
242 let mut bytes_written = 0;
243 bytes_written += self.clas.write(writer)?;
244 bytes_written += self.clsy.write(writer)?;
245 bytes_written += self.code.write(writer)?;
246 bytes_written += self.ctlh.write(writer)?;
247 bytes_written += self.rel.write(writer)?;
248 bytes_written += self.dctp.write(writer)?;
249 bytes_written += self.dcdt.write(writer)?;
250 bytes_written += self.dcxm.write(writer)?;
251 bytes_written += self.dg.write(writer)?;
252 bytes_written += self.dgdt.write(writer)?;
253 bytes_written += self.cltx.write(writer)?;
254 bytes_written += self.catp.write(writer)?;
255 bytes_written += self.caut.write(writer)?;
256 bytes_written += self.crsn.write(writer)?;
257 bytes_written += self.srdt.write(writer)?;
258 bytes_written += self.ctln.write(writer)?;
259 Ok(bytes_written)
260 }
261 pub fn length(&self) -> usize {
263 167
264 }
265}
266impl Display for Security {
267 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
268 let mut out_str = String::default();
269 out_str += &format!("{}, ", self.clas);
270 out_str += &format!("{}, ", self.clsy);
271 out_str += &format!("{}, ", self.code);
272 out_str += &format!("{}, ", self.ctlh);
273 out_str += &format!("{}, ", self.rel);
274 out_str += &format!("{}, ", self.dctp);
275 out_str += &format!("{}, ", self.dcdt);
276 out_str += &format!("{}, ", self.dcxm);
277 out_str += &format!("{}, ", self.dg);
278 out_str += &format!("{}, ", self.dgdt);
279 out_str += &format!("{}, ", self.cltx);
280 out_str += &format!("{}, ", self.catp);
281 out_str += &format!("{}, ", self.caut);
282 out_str += &format!("{}, ", self.crsn);
283 out_str += &format!("{}, ", self.srdt);
284 out_str += &format!("{}", self.ctln);
285 write!(f, "{out_str}")
286 }
287}
288
289#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
291pub enum Classification {
292 #[default]
293 U,
295 T,
297 S,
299 C,
301 R,
303}
304impl FromStr for Classification {
305 type Err = NitfError;
306 fn from_str(s: &str) -> Result<Self, Self::Err> {
307 match s {
308 "U" => Ok(Self::U),
309 "T" => Ok(Self::T),
310 "S" => Ok(Self::S),
311 "C" => Ok(Self::C),
312 "R" => Ok(Self::R),
313 _ => Err(NitfError::ParseError("Classification".to_string())),
314 }
315 }
316}
317impl Display for Classification {
318 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
319 match self {
320 Self::U => write!(f, "U"),
321 Self::T => write!(f, "T"),
322 Self::S => write!(f, "S"),
323 Self::C => write!(f, "C"),
324 Self::R => write!(f, "R"),
325 }
326 }
327}
328#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
330pub enum DeclassificationType {
331 #[default]
332 DEFAULT,
334 DD,
336 DE,
338 GD,
340 GE,
342 O,
344 X,
346}
347impl FromStr for DeclassificationType {
348 type Err = NitfError;
349 fn from_str(s: &str) -> Result<Self, Self::Err> {
350 match s {
351 "" => Ok(Self::DEFAULT),
352 "DD" => Ok(Self::DD),
353 "DE" => Ok(Self::DE),
354 "GD" => Ok(Self::GD),
355 "GE" => Ok(Self::GE),
356 "O" => Ok(Self::O),
357 "X" => Ok(Self::X),
358 _ => Err(NitfError::ParseError("DeclassificationType".to_string())),
359 }
360 }
361}
362impl Display for DeclassificationType {
363 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
364 match self {
365 Self::DEFAULT => write!(f, " "),
366 Self::DD => write!(f, "DD"),
367 Self::DE => write!(f, "DE"),
368 Self::GD => write!(f, "GD"),
369 Self::GE => write!(f, "GE"),
370 Self::O => write!(f, "O"),
371 Self::X => write!(f, "X"),
372 }
373 }
374}
375
376#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
378pub enum DeclassificationExemption {
379 #[default]
380 DEFAULT,
382 DExX1,
384 DExX2,
385 DExX3,
386 DExX4,
387 DExX5,
388 DExX6,
389 DExX7,
390 DExX8,
391 DEx25X1,
392 DEx25X2,
393 DEx25X3,
394 DEx25X4,
395 DEx25X5,
396 DEx25X6,
397 DEx25X7,
398 DEx25X8,
399 DEx25X9,
400 DExDN10,
401 DExDNI,
402}
403impl FromStr for DeclassificationExemption {
404 type Err = NitfError;
405 fn from_str(s: &str) -> Result<Self, Self::Err> {
406 match s {
407 "" => Ok(Self::DEFAULT),
408 "X1" => Ok(Self::DExX1), "X2" => Ok(Self::DExX2), "X3" => Ok(Self::DExX3), "X4" => Ok(Self::DExX4), "X5" => Ok(Self::DExX5), "X6" => Ok(Self::DExX6), "X7" => Ok(Self::DExX7), "X8" => Ok(Self::DExX8), "25X1" => Ok(Self::DEx25X1), "25X2" => Ok(Self::DEx25X2), "25X3" => Ok(Self::DEx25X3), "25X4" => Ok(Self::DEx25X4), "25X5" => Ok(Self::DEx25X5), "25X6" => Ok(Self::DEx25X6), "25X7" => Ok(Self::DEx25X7), "25X8" => Ok(Self::DEx25X8), "25X9" => Ok(Self::DEx25X9), "DN10" => Ok(Self::DExDN10),
426 "DNI" => Ok(Self::DExDNI),
427 _ => Err(NitfError::ParseError(
428 "DeclassificationExemption".to_string(),
429 )),
430 }
431 }
432}
433impl Display for DeclassificationExemption {
434 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
435 match self {
436 Self::DEFAULT => write!(f, ""),
437 Self::DExX1 => write!(f, "X1"),
438 Self::DExX2 => write!(f, "X2"),
439 Self::DExX3 => write!(f, "X3"),
440 Self::DExX4 => write!(f, "X4"),
441 Self::DExX5 => write!(f, "X5"),
442 Self::DExX6 => write!(f, "X6"),
443 Self::DExX7 => write!(f, "X7"),
444 Self::DExX8 => write!(f, "X8"),
445 Self::DEx25X1 => write!(f, "25X1"),
446 Self::DEx25X2 => write!(f, "25X2"),
447 Self::DEx25X3 => write!(f, "25X3"),
448 Self::DEx25X4 => write!(f, "25X4"),
449 Self::DEx25X5 => write!(f, "25X5"),
450 Self::DEx25X6 => write!(f, "25X6"),
451 Self::DEx25X7 => write!(f, "25X7"),
452 Self::DEx25X8 => write!(f, "25X8"),
453 Self::DEx25X9 => write!(f, "25X9"),
454 Self::DExDN10 => write!(f, "DN10"),
455 Self::DExDNI => write!(f, "DNI"),
456 }
457 }
458}
459
460#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
462pub enum Downgrade {
463 #[default]
464 DEFAULT,
466 S,
468 C,
470 R,
472}
473impl FromStr for Downgrade {
474 type Err = NitfError;
475 fn from_str(s: &str) -> Result<Self, Self::Err> {
476 match s {
477 "" => Ok(Self::DEFAULT),
478 "S" => Ok(Self::S),
479 "C" => Ok(Self::C),
480 "R" => Ok(Self::R),
481 _ => Err(NitfError::ParseError("Downgrade".to_string())),
482 }
483 }
484}
485impl Display for Downgrade {
486 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
487 match self {
488 Self::DEFAULT => write!(f, ""),
489 Self::S => write!(f, "S"),
490 Self::C => write!(f, "C"),
491 Self::R => write!(f, "R"),
492 }
493 }
494}
495
496#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
498pub enum ClassificationAuthorityType {
499 #[default]
500 DEFAULT,
502 O,
504 D,
506 M,
508}
509impl FromStr for ClassificationAuthorityType {
510 type Err = NitfError;
511 fn from_str(s: &str) -> Result<Self, Self::Err> {
512 match s {
513 "" => Ok(Self::DEFAULT),
514 "O" => Ok(Self::O),
515 "D" => Ok(Self::D),
516 "M" => Ok(Self::M),
517 _ => Err(NitfError::ParseError(
518 "ClassificationAuthorityType".to_string(),
519 )),
520 }
521 }
522}
523impl Display for ClassificationAuthorityType {
524 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
525 match self {
526 Self::DEFAULT => write!(f, ""),
527 Self::O => write!(f, "O"),
528 Self::D => write!(f, "D"),
529 Self::M => write!(f, "M"),
530 }
531 }
532}
533
534#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
536pub enum ClassificationReason {
537 #[default]
538 DEFAULT,
540 A,
542 B,
543 C,
544 D,
545 E,
546 F,
547 G,
548 H,
549}
550impl FromStr for ClassificationReason {
551 type Err = NitfError;
552 fn from_str(s: &str) -> Result<Self, Self::Err> {
553 match s {
554 "" => Ok(Self::DEFAULT),
555 "A" => Ok(Self::A),
556 "B" => Ok(Self::B),
557 "C" => Ok(Self::C),
558 "D" => Ok(Self::D),
559 "E" => Ok(Self::E),
560 "F" => Ok(Self::F),
561 "G" => Ok(Self::G),
562 "H" => Ok(Self::H),
563 _ => Err(NitfError::ParseError("ClassificationReason".to_string())),
564 }
565 }
566}
567impl Display for ClassificationReason {
568 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
569 match self {
570 Self::DEFAULT => write!(f, ""),
571 Self::A => write!(f, "A"),
572 Self::B => write!(f, "B"),
573 Self::C => write!(f, "C"),
574 Self::D => write!(f, "D"),
575 Self::E => write!(f, "E"),
576 Self::F => write!(f, "F"),
577 Self::G => write!(f, "G"),
578 Self::H => write!(f, "H"),
579 }
580 }
581}
582
583#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd)]
585pub struct ExtendedSubheader {
586 tre: Vec<u8>,
588 size: usize,
590 pub name: String,
592}
593impl ExtendedSubheader {
594 pub fn tre(&self) -> &Vec<u8> {
596 &self.tre
597 }
598 pub fn size(&self) -> &usize {
600 &self.size
601 }
602 pub fn init(name: &str) -> Self {
603 Self {
604 tre: vec![],
605 size: 0,
606 name: name.to_string(),
607 }
608 }
609 pub fn set_tre(&mut self, new_tre: Vec<u8>) {
611 self.size = new_tre.len();
612 self.tre = new_tre;
613 }
614 pub fn read(&mut self, reader: &mut (impl Read + Seek), n_bytes: usize) -> NitfResult<()> {
615 self.size = n_bytes;
616 self.tre = vec![0; n_bytes];
617 trace!("Reading: {}", self.name);
618 reader
619 .read_exact(self.tre.as_mut_slice())
620 .map_err(NitfError::IOError)
621 }
622 pub fn write(&self, writer: &mut (impl Write + Seek)) -> NitfResult<usize> {
623 trace!("Writing: {}", self.name);
624 writer
625 .write(self.tre.as_slice())
626 .map_err(NitfError::IOError)
627 }
628}
629impl Display for ExtendedSubheader {
630 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
631 let out_str = String::from_utf8(self.tre.to_vec()).or(Err(std::fmt::Error))?;
633 write!(f, "{}: [{out_str}], ", self.name)
634 }
635}