1pub mod raw;
2
3use crate::{
4 BasicTarError,
5 header::raw::{ StringExt, U64Ext, Checksum }
6};
7
8
9#[derive(Default, Debug, Clone, Eq, PartialEq)]
11pub struct Header {
12 pub path: String,
14 pub mode: Option<u64>,
16 pub uid: Option<u64>,
18 pub gid: Option<u64>,
20 pub size: u64,
22 pub mtime: Option<u64>,
24 pub typeflag: u8,
26 pub linkname: Option<String>
28}
29impl Header {
30 pub fn parse(data: raw::header::Raw) -> Result<Self, BasicTarError> {
32 if data.as_ref() == raw::header::raw().as_ref() {
34 Err(BasicTarError::EmptyHeader)?
35 }
36
37 let tar = raw::header::Header::from(data);
39 Checksum::verify(&tar)?;
40
41 let path = String::from_field(&tar.name)?;
43
44 let mode = Option::from_octal_field(&tar.mode)?;
46 let uid = Option::from_octal_field(&tar.uid)?;
47 let gid = Option::from_octal_field(&tar.gid)?;
48
49 let size = u64::from_octal_field(&tar.size)?;
51 let mtime = Option::from_octal_field(&tar.mtime)?;
52
53 let linkname = Option::from_field(&tar.linkname)?;
55 Ok(Self{ path, mode, uid, gid, size, typeflag: tar.typeflag[0], mtime, linkname })
56 }
57
58 pub fn serialize(self) -> Result<raw::header::Raw, BasicTarError> {
63 let mut tar = raw::header::header();
65 self.path.into_field(&mut tar.name)?;
66
67 self.mode.into_octal_field(&mut tar.mode)?;
68 self.uid.into_octal_field(&mut tar.uid)?;
69 self.gid.into_octal_field(&mut tar.gid)?;
70
71 self.size.into_octal_field(&mut tar.size)?;
72 self.mtime.into_octal_field(&mut tar.mtime)?;
73
74 tar.typeflag[0] = self.typeflag;
75 self.linkname.into_field(&mut tar.linkname)?;
76
77 Checksum::write(&mut tar);
79 Ok(tar.into())
80 }
81}