diff options
author | Bryan Newbold <bnewbold@robocracy.org> | 2022-10-28 20:00:55 -0700 |
---|---|---|
committer | Bryan Newbold <bnewbold@robocracy.org> | 2022-10-28 20:00:55 -0700 |
commit | f99cff96758176701656285712246173db76ac58 (patch) | |
tree | 10a4f8c167c055b39a96a342f9a9334ec877414e /iroh-car/src/header.rs | |
parent | 4b4eb3aa819ee16cd8d7074cfd21d94deab2276d (diff) | |
download | adenosine-f99cff96758176701656285712246173db76ac58.tar.gz adenosine-f99cff96758176701656285712246173db76ac58.zip |
copy in iroh-car from iroh repo, verbatim
Diffstat (limited to 'iroh-car/src/header.rs')
-rw-r--r-- | iroh-car/src/header.rs | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/iroh-car/src/header.rs b/iroh-car/src/header.rs new file mode 100644 index 0000000..c004e35 --- /dev/null +++ b/iroh-car/src/header.rs @@ -0,0 +1,104 @@ +use cid::Cid; +use ipld::codec::Codec; +use ipld_cbor::DagCborCodec; + +use crate::error::Error; + +/// A car header. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum CarHeader { + V1(CarHeaderV1), +} + +impl CarHeader { + pub fn new_v1(roots: Vec<Cid>) -> Self { + Self::V1(roots.into()) + } + + pub fn decode(buffer: &[u8]) -> Result<Self, Error> { + let header: CarHeaderV1 = DagCborCodec + .decode(buffer) + .map_err(|e| Error::Parsing(e.to_string()))?; + + if header.roots.is_empty() { + return Err(Error::Parsing("empty CAR file".to_owned())); + } + + if header.version != 1 { + return Err(Error::InvalidFile( + "Only CAR file version 1 is supported".to_string(), + )); + } + + Ok(CarHeader::V1(header)) + } + + pub fn encode(&self) -> Result<Vec<u8>, Error> { + match self { + CarHeader::V1(ref header) => { + let res = DagCborCodec.encode(header)?; + Ok(res) + } + } + } + + pub fn roots(&self) -> &[Cid] { + match self { + CarHeader::V1(header) => &header.roots, + } + } + + pub fn version(&self) -> u64 { + match self { + CarHeader::V1(_) => 1, + } + } +} + +/// CAR file header version 1. +#[derive(Debug, Clone, Default, ipld::DagCbor, PartialEq, Eq)] +pub struct CarHeaderV1 { + #[ipld] + pub roots: Vec<Cid>, + #[ipld] + pub version: u64, +} + +impl CarHeaderV1 { + /// Creates a new CAR file header + pub fn new(roots: Vec<Cid>, version: u64) -> Self { + Self { roots, version } + } +} + +impl From<Vec<Cid>> for CarHeaderV1 { + fn from(roots: Vec<Cid>) -> Self { + Self { roots, version: 1 } + } +} + +#[cfg(test)] +mod tests { + use ipld::codec::{Decode, Encode}; + use ipld_cbor::DagCborCodec; + use multihash::MultihashDigest; + + use super::*; + + #[test] + fn symmetric_header_v1() { + let digest = multihash::Code::Blake2b256.digest(b"test"); + let cid = Cid::new_v1(DagCborCodec.into(), digest); + + let header = CarHeaderV1::from(vec![cid]); + + let mut bytes = Vec::new(); + header.encode(DagCborCodec, &mut bytes).unwrap(); + + assert_eq!( + CarHeaderV1::decode(DagCborCodec, &mut std::io::Cursor::new(&bytes)).unwrap(), + header + ); + } +} |