use camino::Utf8Path;
use camino::Utf8PathBuf;
use crate::common::FileAttributes;
use super::kind::PacketType;
use super::PayloadTrait;
#[derive(Clone, Debug, Eq, PartialEq, Nom, Serialize)]
#[nom(BigEndian)]
#[cfg_attr(test, derive(test_strategy::Arbitrary))]
pub struct Name {
pub id: u32,
#[nom(Parse(crate::util::parse_vec))]
#[serde(serialize_with = "crate::util::vec_with_u32_length")]
pub files: Vec<File>
}
impl Name {
pub fn new(id: u32) -> Self {
Self{
id,
files: Vec::new()
}
}
pub fn append_file(&mut self, filename: &Utf8Path, attrs: FileAttributes) {
self.files.push(File::new(attrs, filename.into()));
}
}
impl PayloadTrait for Name {
const Type: PacketType = PacketType::Name;
fn binsize(&self) -> u32 {
4 + 4 + self.files.iter().map(|f| f.binsize()).sum::<u32>()
}
}
impl From<Name> for super::Payload {
fn from(p: Name) -> Self {
Self::Name(p)
}
}
#[derive(Clone, Debug, Eq, PartialEq, Nom, Serialize)]
#[nom(BigEndian)]
#[cfg_attr(test, derive(test_strategy::Arbitrary))]
pub struct File {
#[nom(Parse(crate::util::parse_path))]
#[serde(serialize_with = "crate::util::path_with_u32_length")]
pub filename: Utf8PathBuf,
#[nom(Parse(crate::util::parse_string))]
#[serde(serialize_with = "crate::util::str_with_u32_length")]
pub longname: String,
pub attrs: FileAttributes
}
impl File {
pub fn new(attrs: FileAttributes, filename: Utf8PathBuf) -> Self {
Self{
longname: format!("{} {}", attrs, filename),
filename,
attrs
}
}
pub fn binsize(&self) -> u32 {
4 + self.filename.as_str().len() as u32 + 4 + self.longname.as_str().len() as u32 + self.attrs.binsize()
}
}
#[cfg(test)]
mod tests {
use test_strategy::proptest;
use crate::parser::encode;
use crate::parser::Parser;
use super::*;
#[proptest]
fn roundtrip_whole(input: Name) {
let mut stream = Parser::default();
let packet = input.into_packet();
stream.write(&encode(&packet)).unwrap();
assert_eq!(stream.get_packet(), Ok(Some(packet)));
assert_eq!(stream.get_packet(), Ok(None));
}
}