1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::services::lfo::CompressionFormats;
use crate::services::{DEFAULT_AID_HEX, DEFAULT_CID_HEX};
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct LfoRequest {
pub(crate) cid: [u8; 16],
pub(crate) aid: [u8; 16],
pub(crate) compression: u16,
pub(crate) remote_path: String,
pub(crate) offset: u32,
}
impl LfoRequest {
pub fn new_simple(remote_path: String) -> Self {
Self {
cid: hex::decode(DEFAULT_CID_HEX).unwrap().try_into().unwrap(),
aid: hex::decode(DEFAULT_AID_HEX).unwrap().try_into().unwrap(),
compression: 0,
remote_path,
offset: 0,
}
}
pub fn new_custom(
cid: [u8; 16],
aid: [u8; 16],
compression: CompressionFormats,
remote_path: String,
) -> Self {
Self {
cid,
aid,
compression: compression as u16,
remote_path,
offset: 0,
}
}
pub(crate) fn to_payload(&self) -> Vec<u8> {
let mut payload = vec![];
payload.extend_from_slice(&self.cid); payload.extend_from_slice(&self.aid); payload.extend_from_slice(8u32.to_be_bytes().as_slice());
payload.extend_from_slice(&self.offset.to_be_bytes());
payload.extend_from_slice(&self.compression.to_be_bytes());
payload.extend_from_slice(self.remote_path.as_bytes());
payload
}
#[cfg(test)]
pub(crate) fn try_from_payload(payload: &[u8]) -> Result<Self, super::LfoError> {
use super::LfoError;
use byteorder::{ReadBytesExt, BE};
use std::io::Read;
let mut cursor = std::io::Cursor::new(payload);
let mut cid = [0u8; 16];
cursor.read_exact(&mut cid)?;
let mut aid = [0u8; 16];
cursor.read_exact(&mut aid)?;
_ = cursor.read_u32::<BE>()?;
let offset = cursor.read_u32::<BE>()?;
let compression = cursor.read_u16::<BE>()?;
let remote_path = String::from_utf8(payload[cursor.position() as usize..].into())
.map_err(|_| LfoError::InvalidRequest)?;
Ok(Self {
cid,
aid,
compression,
remote_path,
offset,
})
}
}