Setup to replace separate header/node idiom with unified Node. Enum

`Filetype` with now have `Normal(File)` (todo) which will include the
size, checksum and data, removing the `size` field from `Header`. The
`Header` struct will become the new `Node`.
This commit is contained in:
Nathan Fisher 2023-07-02 22:52:26 -04:00
parent 85e55dc456
commit bdbcd41617
3 changed files with 237 additions and 8 deletions

108
Cargo.lock generated
View File

@ -2,6 +2,114 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cpufeatures"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "libc"
version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "md-5"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca"
dependencies = [
"digest",
]
[[package]]
name = "sha1"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha2"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "tar-ng"
version = "0.1.0"
dependencies = [
"md-5",
"sha1",
"sha2",
]
[[package]]
name = "typenum"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"

View File

@ -6,3 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
md-5 = "0.10"
sha1 = "0.10"
sha2 = "0.10"

View File

@ -1,9 +1,14 @@
use std::{
array::TryFromSliceError,
fmt,
io::{self, Read, Write},
num::TryFromIntError,
string::FromUtf8Error,
use {
md5::{Digest, Md5},
sha1::Sha1,
sha2::Sha256,
std::{
array::TryFromSliceError,
fmt,
io::{self, Read, Write},
num::TryFromIntError,
string::FromUtf8Error,
},
};
#[derive(Debug)]
@ -12,6 +17,7 @@ pub enum Error {
Io(io::Error),
Utf8(FromUtf8Error),
Slice(TryFromSliceError),
InvalidChecksum,
MissingData,
UnexpectedData,
UnknownFileType,
@ -24,6 +30,7 @@ impl fmt::Display for Error {
Self::Utf8(e) => write!(f, "{e}"),
Self::Slice(e) => write!(f, "{e}"),
Self::Io(e) => write!(f, "{e}"),
Self::InvalidChecksum => write!(f, "invalid checksum"),
Self::MissingData => write!(f, "missing data"),
Self::UnexpectedData => write!(f, "unexpected data"),
Self::UnknownFileType => write!(f, "unknown file type"),
@ -91,6 +98,117 @@ impl Special {
}
}
#[derive(Debug)]
pub enum Checksum {
Md5([u8; 16]),
Sha1([u8; 20]),
Sha256([u8; 32]),
Skip,
}
impl Checksum {
pub fn read<T: Read>(reader: &mut T) -> Result<Self, Error> {
let mut buf = [0; 1];
reader.read_exact(&mut buf)?;
match buf[0] {
0 => {
let mut sum = [0; 16];
reader.read_exact(&mut sum)?;
Ok(Self::Md5(sum))
},
1 => {
let mut sum = [0; 20];
reader.read_exact(&mut sum)?;
Ok(Self::Sha1(sum))
},
2 => {
let mut sum = [0; 32];
reader.read_exact(&mut sum)?;
Ok(Self::Sha256(sum))
},
_ => Ok(Self::Skip),
}
}
pub fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
match self {
Self::Md5(sum) => {
writer.write_all(&[b'0'])?;
writer.write_all(&sum[..])?;
},
Self::Sha1(sum) => {
writer.write_all(&[b'1'])?;
writer.write_all(&sum[..])?;
},
Self::Sha256(sum) => {
writer.write_all(&[b'2'])?;
writer.write_all(&sum[..])?;
},
Self::Skip => writer.write_all(&[b'3'])?,
}
Ok(())
}
}
#[derive(Debug)]
pub struct File {
pub len: u64,
pub checksum: Checksum,
pub data: Vec<u8>,
}
impl File {
pub fn read<T: Read>(reader: &mut T) -> Result<Self, Error> {
let mut len = [0; 8];
reader.read_exact(&mut len)?;
let len = u64::from_le_bytes(len);
let checksum = Checksum::read(reader)?;
let mut data = Vec::with_capacity(len.try_into()?);
let mut handle = reader.take(len);
handle.read_exact(&mut data)?;
match checksum {
Checksum::Md5(sum) => {
let mut hasher = Md5::new();
hasher.update(&data);
let res = hasher.finalize();
if res == sum.into() {
Ok(Self { len, checksum, data })
} else {
Err(Error::InvalidChecksum)
}
},
Checksum::Sha1(sum) => {
let mut hasher = Sha1::new();
hasher.update(&data);
let res = hasher.finalize();
if res == sum.into() {
Ok(Self { len, checksum, data })
} else {
Err(Error::InvalidChecksum)
}
},
Checksum::Sha256(sum) => {
let mut hasher = Sha256::new();
hasher.update(&data);
let res = hasher.finalize();
if res == sum.into() {
Ok(Self { len, checksum, data })
} else {
Err(Error::InvalidChecksum)
}
},
_ => Ok(Self { len, checksum, data }),
}
}
pub fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
writer.write_all(&self.len.to_be_bytes())?;
Checksum::write(&self.checksum, writer)?;
writer.write_all(&self.data)?;
Ok(())
}
}
#[repr(u8)]
#[derive(Debug)]
pub enum FileType {
@ -256,12 +374,12 @@ impl Node {
} else {
return Err(Error::MissingData);
}
},
}
_ => {
if self.data.is_some() {
return Err(Error::UnexpectedData);
}
},
}
}
Ok(())
}