1use crate::{ByteOrder, Configuration, error::Error, DataFormatIdentifier, ModeOfOperation, RequestData, utils};
4
5pub enum RequestFileTransfer {
6 AddFile {
7 filepath: String,
8 dfi: DataFormatIdentifier,
9 filesize_len: u8,
10 uncompressed_size: u128,
11 compressed_size: u128,
12 },
13 DeleteFile { filepath: String,
15 },
16 ReplaceFile { filepath: String,
18 dfi: DataFormatIdentifier,
19 filesize_len: u8,
20 uncompressed_size: u128,
21 compressed_size: u128,
22 },
23 ReadFile { filepath: String,
25 dfi: DataFormatIdentifier,
26 },
27 ReadDir { filepath: String,
29 },
30 ResumeFile { filepath: String,
32 dfi: DataFormatIdentifier,
33 filesize_len: u8,
34 uncompressed_size: u128,
35 compressed_size: u128,
36 },
37}
38
39impl RequestData for RequestFileTransfer {
40 type SubFunc = ModeOfOperation;
41 fn try_parse(data: &[u8], sub_func: Option<Self::SubFunc>, _: &Configuration) -> Result<Self, Error> {
42 match sub_func {
43 Some(v) => {
44 let data_len = data.len();
45 utils::data_length_check(data_len, 3, false)?;
46 let mut offset = 0;
47
48 let len = u16::from_be_bytes([data[offset], data[offset + 1]]) as usize;
49 offset += 2;
50 utils::data_length_check(data_len, offset + len + 1, false)?;
51
52 let filepath = String::from_utf8(
53 data[offset..offset + len].to_vec()
54 ).map_err(|_| Error::InvalidData(hex::encode(data)))?;
55 offset += len;
56
57 match v {
58 ModeOfOperation::AddFile => {
59 let dfi = DataFormatIdentifier::from(data[offset]);
60 offset += 1;
61 let filesize_len = data[offset];
62 offset += 1;
63 let uncompressed_size = utils::slice_to_u128(&data[offset..offset + filesize_len as usize], ByteOrder::Big);
64 offset += filesize_len as usize;
65 let compressed_size = utils::slice_to_u128(&data[offset..offset + filesize_len as usize], ByteOrder::Big);
66 Ok(Self::AddFile { filepath, dfi, filesize_len, uncompressed_size, compressed_size })
67 },
68 ModeOfOperation::ReplaceFile => {
69 let dfi = DataFormatIdentifier::from(data[offset]);
70 offset += 1;
71 let filesize_len = data[offset];
72 offset += 1;
73 let uncompressed_size = utils::slice_to_u128(&data[offset..offset + filesize_len as usize], ByteOrder::Big);
74 offset += filesize_len as usize;
75 let compressed_size = utils::slice_to_u128(&data[offset..offset + filesize_len as usize], ByteOrder::Big);
76 Ok(Self::ReplaceFile { filepath, dfi, filesize_len, uncompressed_size, compressed_size })
77 },
78 ModeOfOperation::ResumeFile => {
79 let dfi = DataFormatIdentifier::from(data[offset]);
80 offset += 1;
81 let filesize_len = data[offset];
82 offset += 1;
83 let uncompressed_size = utils::slice_to_u128(&data[offset..offset + filesize_len as usize], ByteOrder::Big);
84 offset += filesize_len as usize;
85 let compressed_size = utils::slice_to_u128(&data[offset..offset + filesize_len as usize], ByteOrder::Big);
86 Ok(Self::ResumeFile { filepath, dfi, filesize_len, uncompressed_size, compressed_size })
87 },
88 ModeOfOperation::DeleteFile => Ok(Self::DeleteFile { filepath }),
89 ModeOfOperation::ReadDir => Ok(Self::ReadDir { filepath }),
90 ModeOfOperation::ReadFile => {
91 let dfi = DataFormatIdentifier::from(data[offset]);
92
93 Ok(Self::ReadFile {
94 filepath,
95 dfi
96 })
97 },
98 }
99 },
100 None => panic!("Sub-function required"),
101 }
102 }
103 #[inline]
104 fn to_vec(self, _: &Configuration) -> Vec<u8> {
105 self.into()
106 }
107}
108
109impl Into<Vec<u8>> for RequestFileTransfer {
110 fn into(self) -> Vec<u8> {
111 let mut result = Vec::new();
112 match &self {
113 Self::AddFile { .. } => result.push(ModeOfOperation::AddFile.into()),
114 Self::DeleteFile { .. } => result.push(ModeOfOperation::DeleteFile.into()),
115 Self::ReplaceFile { .. } => result.push(ModeOfOperation::ReplaceFile.into()),
116 Self::ReadFile { .. } => result.push(ModeOfOperation::ReadFile.into()),
117 Self::ReadDir { .. } => result.push(ModeOfOperation::ReadDir.into()),
118 Self::ResumeFile { .. } => result.push(ModeOfOperation::ResumeFile.into()),
119 }
120 match self {
121 Self::AddFile {
122 filepath,
123 dfi,
124 filesize_len,
125 uncompressed_size,
126 compressed_size,
127 } |
128 Self::ReplaceFile {
129 filepath,
130 dfi,
131 filesize_len,
132 uncompressed_size,
133 compressed_size,
134 } |
135 Self::ResumeFile {
136 filepath,
137 dfi,
138 filesize_len,
139 uncompressed_size,
140 compressed_size,
141 } => {
142 let mut bytes: Vec<_> = filepath.bytes().collect();
143 result.extend((bytes.len() as u16).to_be_bytes());
144 result.append(&mut bytes);
145 result.push(dfi.into());
146 result.push(filesize_len);
147
148 result.append(&mut utils::u128_to_vec(uncompressed_size, filesize_len as usize, ByteOrder::Big));
149 result.append(&mut utils::u128_to_vec(compressed_size, filesize_len as usize, ByteOrder::Big));
150 },
151 Self::DeleteFile { filepath, } |
152 Self::ReadDir { filepath, } => {
153 let mut bytes: Vec<_> = filepath.bytes().collect();
154 result.extend((bytes.len() as u16).to_be_bytes());
155 result.append(&mut bytes);
156 },
157 Self::ReadFile { filepath, dfi, } => {
158 let mut bytes: Vec<_> = filepath.bytes().collect();
159 result.extend((bytes.len() as u16).to_be_bytes());
160 result.append(&mut bytes);
161 result.push(dfi.into());
162 },
163 }
164
165 result
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use crate::{Configuration, DataFormatIdentifier, ModeOfOperation, RequestData};
172 use super::RequestFileTransfer;
173
174 #[test]
175 fn add_file() -> anyhow::Result<()> {
176 let source = hex::decode("3801001E443A5C6D6170646174615C6575726F70655C6765726D616E79312E79787A1102C3507530")?;
178
179 let cfg = Configuration::default();
180 let request = RequestFileTransfer::try_parse(&source[2..], Some(ModeOfOperation::AddFile), &cfg)?;
181 match request {
182 RequestFileTransfer::AddFile {
183 filepath,
184 dfi,
185 filesize_len,
186 uncompressed_size,
187 compressed_size,
188 } => {
189 assert_eq!(filepath, r"D:\mapdata\europe\germany1.yxz".to_string());
190 assert_eq!(dfi, DataFormatIdentifier(0x11));
191 assert_eq!(filesize_len, 0x02);
192 assert_eq!(uncompressed_size, 0xC350);
193 assert_eq!(compressed_size, 0x7530);
194 },
195 _ => panic!(),
196 }
197
198 Ok(())
199 }
200}