use super::{EntryBuilderCore, data_writer};
use crate::{
CipherMode, Encryption, Metadata, NormalEntry, WriteOptions,
chunk::RawChunk,
cipher::CipherWriter,
compress::CompressionWriter,
entry::{EntryHeader, EntryName, EntryReference, WriteOption},
io::{FlattenWriter, TryIntoInner},
};
use std::io::{self, Write};
struct LinkEntryBuilder {
core: EntryBuilderCore,
data: CompressionWriter<CipherWriter<FlattenWriter>>,
}
impl LinkEntryBuilder {
fn new(
header: EntryHeader,
source: EntryReference,
option: impl WriteOption,
) -> io::Result<Self> {
let (mut writer, iv, phsf) = data_writer(option)?;
writer.write_all(source.as_bytes())?;
let mut core = EntryBuilderCore::new(header);
core.set_cipher(iv, phsf);
Ok(Self { core, data: writer })
}
fn build(self) -> io::Result<NormalEntry> {
let data = self.data.try_into_inner()?.try_into_inner()?.inner;
Ok(self.core.build(data, None))
}
}
pub struct SymlinkEntryBuilder(LinkEntryBuilder);
impl SymlinkEntryBuilder {
#[inline]
pub fn new(name: EntryName, source: EntryReference) -> io::Result<Self> {
Self::new_with_options(name, source, WriteOptions::store())
}
#[inline]
pub fn new_with_options(
name: EntryName,
source: EntryReference,
option: impl WriteOption,
) -> io::Result<Self> {
let encryption = option.encryption();
let cipher_mode = if encryption == Encryption::NO {
CipherMode::CBC
} else {
option.cipher_mode()
};
let header = EntryHeader::new_with_options(
crate::DataKind::SYMBOLIC_LINK,
option.compression(),
encryption,
cipher_mode,
name,
);
Ok(Self(LinkEntryBuilder::new(header, source, option)?))
}
#[inline]
pub fn metadata(&mut self, metadata: Metadata) -> &mut Self {
self.0.core.metadata(metadata);
self
}
#[inline]
pub fn add_extra_chunk<T: Into<RawChunk>>(&mut self, chunk: T) -> &mut Self {
self.0.core.add_extra_chunk(chunk);
self
}
#[inline]
#[must_use = "building an entry without using it is wasteful"]
pub fn build(self) -> io::Result<NormalEntry> {
self.0.build()
}
}
pub struct HardLinkEntryBuilder(LinkEntryBuilder);
impl HardLinkEntryBuilder {
#[inline]
pub fn new(name: EntryName, source: EntryReference) -> io::Result<Self> {
Self::new_with_options(name, source, WriteOptions::store())
}
#[inline]
pub fn new_with_options(
name: EntryName,
source: EntryReference,
option: impl WriteOption,
) -> io::Result<Self> {
let encryption = option.encryption();
let cipher_mode = if encryption == Encryption::NO {
CipherMode::CBC
} else {
option.cipher_mode()
};
let header = EntryHeader::new_with_options(
crate::DataKind::HARD_LINK,
option.compression(),
encryption,
cipher_mode,
name,
);
Ok(Self(LinkEntryBuilder::new(header, source, option)?))
}
#[inline]
pub fn metadata(&mut self, metadata: Metadata) -> &mut Self {
self.0.core.metadata(metadata);
self
}
#[inline]
pub fn add_extra_chunk<T: Into<RawChunk>>(&mut self, chunk: T) -> &mut Self {
self.0.core.add_extra_chunk(chunk);
self
}
#[inline]
#[must_use = "building an entry without using it is wasteful"]
pub fn build(self) -> io::Result<NormalEntry> {
self.0.build()
}
}