Skip to main content

osdp/command/
file_transfer.rs

1//! `osdp_FILETRANSFER` (`0x7C`) — chunked file upload to the PD.
2//!
3//! # Spec: §6.21
4
5use crate::error::Error;
6use alloc::vec::Vec;
7
8/// `osdp_FILETRANSFER` body.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct FileTransfer {
11    /// Vendor-specific file type.
12    pub file_type: u8,
13    /// Total file size, in bytes.
14    pub total_size: u32,
15    /// Byte offset of this fragment.
16    pub offset: u32,
17    /// File fragment.
18    pub fragment: Vec<u8>,
19}
20
21impl FileTransfer {
22    /// Encode.
23    pub fn encode(&self) -> Result<Vec<u8>, Error> {
24        if self.fragment.len() > u16::MAX as usize {
25            return Err(Error::MalformedPayload {
26                code: 0x7C,
27                reason: "FILETRANSFER fragment > 65535 bytes",
28            });
29        }
30        let mut out = Vec::with_capacity(11 + self.fragment.len());
31        out.push(self.file_type);
32        out.extend_from_slice(&self.total_size.to_le_bytes());
33        out.extend_from_slice(&self.offset.to_le_bytes());
34        out.extend_from_slice(&(self.fragment.len() as u16).to_le_bytes());
35        out.extend_from_slice(&self.fragment);
36        Ok(out)
37    }
38
39    /// Decode.
40    pub fn decode(data: &[u8]) -> Result<Self, Error> {
41        if data.len() < 11 {
42            return Err(Error::MalformedPayload {
43                code: 0x7C,
44                reason: "FILETRANSFER requires at least 11 bytes",
45            });
46        }
47        let total_size = u32::from_le_bytes([data[1], data[2], data[3], data[4]]);
48        let offset = u32::from_le_bytes([data[5], data[6], data[7], data[8]]);
49        let frag_len = u16::from_le_bytes([data[9], data[10]]) as usize;
50        if data.len() != 11 + frag_len {
51            return Err(Error::MalformedPayload {
52                code: 0x7C,
53                reason: "FILETRANSFER fragment length disagrees with payload",
54            });
55        }
56        Ok(Self {
57            file_type: data[0],
58            total_size,
59            offset,
60            fragment: data[11..11 + frag_len].to_vec(),
61        })
62    }
63}