dwarfs-enc 0.1.0

A library for writing DwarFS archives (aka. DwarFS images)
Documentation
use dwarfs::{Archive, AsChunks, InodeKind, archive::IsInode};
use dwarfs_enc::{
    chunker::{BasicChunker, Chunker},
    metadata::{Builder, InodeMetadata},
    section::{CompressParam, Writer},
};

const META: InodeMetadata = InodeMetadata::new(0o777);

fn build_with(f: impl FnOnce(&mut Builder, &mut dyn Chunker) -> dwarfs_enc::Result<()>) -> Vec<u8> {
    let buf = Vec::new();
    let writer = Writer::new(buf).unwrap();
    let mut builder = Builder::new(&META);
    let mut chunker = BasicChunker::new(writer, builder.block_size(), CompressParam::Zstd(3));
    f(&mut builder, &mut chunker).unwrap();
    let mut writer = chunker.finish().unwrap();
    writer
        .write_metadata_sections(&builder.finish().unwrap(), CompressParam::Zstd(3))
        .unwrap();
    writer.finish().unwrap()
}

#[test]
fn empty() {
    let b = build_with(|_meta, _chunker| Ok(()));
    let (index, _archive) = Archive::new(b).unwrap();
    assert_eq!(index.root().entries().len(), 0);
    assert_eq!(index.inodes().len(), 1);
    assert_eq!(index.directories().len(), 1);
}

#[test]
fn smoke() {
    let b = build_with(|meta, _chunker| {
        let root = meta.root();
        meta.put_dir(root, "0dir", &META)?;
        let f = meta.put_file(root, "1file", &META, [])?;
        meta.put_symlink(root, "2symlink", &META, "target")?;
        meta.put_block_device(root, "3blkdev", &META, 0xDEAD_BEEF_DEAD_BEEF)?;
        meta.put_char_device(root, "4chardev", &META, 0xBEEF_DEAD_BEEF_DEAD)?;
        meta.put_fifo(root, "5fifo", &META)?;
        meta.put_socket(root, "6socket", &META)?;
        meta.put_hard_link(root, "7hardlink", f)?;
        Ok(())
    });

    let (index, _archive) = Archive::new(b).unwrap();
    let (children, names) = index
        .root()
        .entries()
        .map(|ent| (ent.inode().classify(), ent.name()))
        .unzip::<_, _, Vec<_>, Vec<_>>();

    assert_eq!(
        names,
        vec![
            "0dir",
            "1file",
            "2symlink",
            "3blkdev",
            "4chardev",
            "5fifo",
            "6socket",
            "7hardlink",
        ]
    );

    assert!(matches!(children[0], InodeKind::Directory(_)));
    assert!(matches!(children[1], InodeKind::File(i) if i.as_chunks().len() == 0));
    assert!(matches!(children[2], InodeKind::Symlink(i) if i.target() == "target"));
    assert!(matches!(children[3], InodeKind::Device(i) if i.device_id() == 0xDEAD_BEEF_DEAD_BEEF));
    assert!(matches!(children[4], InodeKind::Device(i) if i.device_id() == 0xBEEF_DEAD_BEEF_DEAD));
    assert!(matches!(children[5], InodeKind::Ipc(_)));
    assert!(matches!(children[6], InodeKind::Ipc(_)));
    assert_eq!(children[7].inode_num(), children[1].inode_num());
}