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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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 a new RDW record from payload.
///
/// # Panics
/// Panics when payload length exceeds `u16::MAX`.
#[deprecated(
since = "0.4.3",
note = "use try_new() instead for fallible construction"
)]
#[allow(clippy::expect_used)] // Intentional panic for deprecated API
#[inline]
#[must_use]
pub fn new(payload: Vec<u8>) -> Self {
Self::try_new(payload).expect("RDW payload exceeds maximum size (65535 bytes)")
}
/// 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 })
}
/// Create an RDW record preserving reserved bytes.
///
/// # Panics
/// Panics when payload length exceeds `u16::MAX`.
#[deprecated(
since = "0.4.3",
note = "use try_with_reserved() instead for fallible construction"
)]
#[allow(clippy::expect_used)] // Intentional panic for deprecated API
#[inline]
#[must_use]
pub fn with_reserved(payload: Vec<u8>, reserved: u16) -> Self {
Self::try_with_reserved(payload, reserved)
.expect("RDW payload exceeds maximum size (65535 bytes)")
}
/// 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(())
}
/// Recompute the header length field from payload length.
///
/// # Panics
/// Panics when payload length exceeds `u16::MAX`.
#[deprecated(
since = "0.4.3",
note = "use try_recompute_length() instead for fallible operation"
)]
#[allow(clippy::expect_used)] // Intentional panic for deprecated API
#[inline]
pub fn recompute_length(&mut self) {
self.try_recompute_length()
.expect("RDW payload exceeds maximum size (65535 bytes)");
}
/// 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
}
}