sftp_protocol/packet/
name.rs

1use camino::Utf8Path;
2use camino::Utf8PathBuf;
3
4use crate::common::FileAttributes;
5
6use super::kind::PacketType;
7use super::PayloadTrait;
8
9#[derive(Clone, Debug, Eq, PartialEq, Nom, Serialize)]
10#[nom(BigEndian)]
11#[cfg_attr(test, derive(test_strategy::Arbitrary))]
12pub struct Name {
13	pub id: u32,
14	#[nom(Parse(crate::util::parse_vec))]
15	#[serde(serialize_with = "crate::util::vec_with_u32_length")]
16	pub files: Vec<File>
17}
18
19impl Name {
20	pub fn new(id: u32) -> Self {
21		Self{
22			id,
23			files: Vec::new()
24		}
25	}
26
27	pub fn append_file(&mut self, filename: &Utf8Path, attrs: FileAttributes) {
28		self.files.push(File::new(attrs, filename.into()));
29	}
30}
31
32impl PayloadTrait for Name {
33	const Type: PacketType = PacketType::Name;
34	fn binsize(&self) -> u32 {
35		4 + 4 + self.files.iter().map(|f| f.binsize()).sum::<u32>()
36	}
37}
38
39impl From<Name> for super::Payload {
40	fn from(p: Name) -> Self {
41		Self::Name(p)
42	}
43}
44
45#[derive(Clone, Debug, Eq, PartialEq, Nom, Serialize)]
46#[nom(BigEndian)]
47#[cfg_attr(test, derive(test_strategy::Arbitrary))]
48pub struct File {
49	#[nom(Parse(crate::util::parse_path))]
50	#[serde(serialize_with = "crate::util::path_with_u32_length")]
51	pub filename: Utf8PathBuf,
52	#[nom(Parse(crate::util::parse_string))]
53	#[serde(serialize_with = "crate::util::str_with_u32_length")]
54	pub longname: String,
55	pub attrs: FileAttributes
56}
57
58impl File {
59	pub fn new(attrs: FileAttributes, filename: Utf8PathBuf) -> Self {
60		Self{
61			longname: format!("{} {}", attrs, filename),
62			filename,
63			attrs
64		}
65	}
66
67	pub fn binsize(&self) -> u32 {
68		4 + self.filename.as_str().len() as u32 + 4 + self.longname.as_str().len() as u32 + self.attrs.binsize()
69	}
70}
71
72#[cfg(test)]
73mod tests {
74	use test_strategy::proptest;
75	use crate::parser::encode;
76	use crate::parser::Parser;
77	use super::*;
78
79	#[proptest]
80	fn roundtrip_whole(input: Name) {
81		let mut stream = Parser::default();
82		let packet = input.into_packet();
83		stream.write(&encode(&packet)).unwrap();
84		assert_eq!(stream.get_packet(), Ok(Some(packet)));
85		assert_eq!(stream.get_packet(), Ok(None));
86	}
87}
88