use std::io;
use camino::Utf8PathBuf;
pub fn start_archive(buf: &mut [u8]) -> Result<usize, io::Error> {
write_str(buf, "nix-archive-1")
}
pub fn start_entry(buf: &mut [u8]) -> Result<usize, io::Error> {
write_str(buf, "(")
}
pub fn close_entry(buf: &mut [u8]) -> Result<usize, io::Error> {
write_str(buf, ")")
}
pub fn close_dir_entry(buf: &mut [u8]) -> Result<usize, io::Error> {
let len = write_str(buf, ")")?;
let len = len + write_str(&mut buf[len..], ")")?;
Ok(len)
}
pub fn start_dir(buf: &mut [u8]) -> Result<usize, io::Error> {
let len = write_str(buf, "type")?;
let len = len + write_str(&mut buf[len..], "directory")?;
Ok(len)
}
pub fn start_dir_entry(buf: &mut [u8], name: &str) -> Result<usize, io::Error> {
let len = write_str(buf, "entry")?;
let len = len + write_str(&mut buf[len..], "(")?;
let len = len + write_str(&mut buf[len..], "name")?;
let len = len + write_bytes(&mut buf[len..], name.as_bytes())?;
let len = len + write_str(&mut buf[len..], "node")?;
let len = len + write_str(&mut buf[len..], "(")?;
Ok(len)
}
pub fn write_symlink(buf: &mut [u8], target: &Utf8PathBuf) -> Result<usize, io::Error> {
let len = write_str(buf, "type")?;
let len = len + write_str(&mut buf[len..], "symlink")?;
let len = len + write_str(&mut buf[len..], "target")?;
let len = len + write_str(&mut buf[len..], target.as_ref())?;
Ok(len)
}
pub fn write_file_regular(buf: &mut [u8], executable: bool) -> Result<usize, io::Error> {
let mut len = write_str(buf, "type")?;
len += write_str(&mut buf[len..], "regular")?;
if executable {
len += write_str(&mut buf[len..], "executable")?;
len += write_str(&mut buf[len..], "")?;
}
len += write_str(&mut buf[len..], "contents")?;
Ok(len)
}
pub fn write_str(buf: &mut [u8], str: &str) -> Result<usize, io::Error> {
write_bytes(buf, str.as_bytes())
}
pub fn write_bytes(buf: &mut [u8], bytes: &[u8]) -> Result<usize, io::Error> {
let len = bytes.len();
let len_rounded_up = (len + 7) & !7;
if len_rounded_up + 8 > buf.len() {
return Err(io::Error::other(format!(
"not enough space to serialize {bytes:#?}, need {}, have {}",
len_rounded_up + 8,
buf.len()
)));
}
buf[..8].copy_from_slice(&u64::to_le_bytes(len as u64));
buf[8..8 + len].copy_from_slice(bytes);
buf[8 + len..8 + len_rounded_up].fill(0);
Ok(8 + len_rounded_up)
}
pub fn write_u64_le(buf: &mut [u8], len: u64) -> Result<usize, io::Error> {
if buf.len() < 8 {
return Err(io::Error::other(format!(
"not enough space to serialize len, need 8, have {}",
buf.len()
)));
}
buf[..8].copy_from_slice(&u64::to_le_bytes(len));
Ok(8)
}