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
use crate::{RDW_HEADER_LEN, RdwHeader};
use copybook_error::Result;
/// An RDW record with header and payload bytes.
#[derive(Debug, Clone)]
pub struct RDWRecord {
/// 4-byte RDW header (length + reserved).
pub header: [u8; RDW_HEADER_LEN],
/// Record payload bytes.
pub payload: Vec<u8>,
}
impl RDWRecord {
/// Create a new RDW record from payload (fallible constructor).
///
/// Constructs an [`RDWRecord`] with a computed header (payload length + zero reserved bytes).
///
/// # Examples
///
/// ```
/// use copybook_rdw::RDWRecord;
///
/// let record = RDWRecord::try_new(vec![0xC8; 80]).unwrap();
/// assert_eq!(record.length(), 80);
/// assert_eq!(record.payload.len(), 80);
/// ```
///
/// # Errors
/// Returns an error when payload length exceeds `u16::MAX`.
#[inline]
#[must_use = "Handle the Result or propagate the error"]
pub fn try_new(payload: Vec<u8>) -> Result<Self> {
let header = RdwHeader::from_payload_len(payload.len(), 0)?.bytes();
Ok(Self { header, payload })
}
/// Create an RDW record preserving reserved bytes (fallible constructor).
///
/// # Errors
/// Returns an error when payload length exceeds `u16::MAX`.
#[inline]
#[must_use = "Handle the Result or propagate the error"]
pub fn try_with_reserved(payload: Vec<u8>, reserved: u16) -> Result<Self> {
let header = RdwHeader::from_payload_len(payload.len(), reserved)?.bytes();
Ok(Self { header, payload })
}
/// Get payload length from header.
#[inline]
#[must_use]
pub fn length(&self) -> u16 {
RdwHeader::from_bytes(self.header).length()
}
/// Get reserved bytes from header.
#[inline]
#[must_use]
pub fn reserved(&self) -> u16 {
RdwHeader::from_bytes(self.header).reserved()
}
/// Recompute the header length field from payload length.
///
/// # Errors
/// Returns an error when payload length exceeds `u16::MAX`.
#[inline]
#[must_use = "Handle the Result or propagate the error"]
pub fn try_recompute_length(&mut self) -> Result<()> {
self.header = RdwHeader::from_payload_len(self.payload.len(), self.reserved())?.bytes();
Ok(())
}
/// Serialize record as `header + payload`.
#[inline]
#[must_use]
pub fn as_bytes(&self) -> Vec<u8> {
let mut result = Vec::with_capacity(RDW_HEADER_LEN + self.payload.len());
result.extend_from_slice(&self.header);
result.extend_from_slice(&self.payload);
result
}
}