Skip to main content

copybook_codec/file/
dispatch.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2//! Operation-level fixed/RDW dispatch for codec callers.
3//!
4//! The framing crates own byte-level parsing and writing. This module owns the
5//! format choice used by codec operations and keeps the legacy single-record
6//! helpers available through [`crate::record`].
7
8use crate::options::RecordFormat;
9use copybook_error::{Error, ErrorCode, Result};
10use std::io::{Read, Write};
11
12pub use copybook_fixed::{FixedRecordReader, FixedRecordWriter};
13pub use copybook_rdw::{RDWRecord, RDWRecordReader, RDWRecordWriter};
14
15/// Read one record using the selected framing format.
16///
17/// # Errors
18/// Returns an error when the delegated framing read fails or when fixed
19/// framing is missing its LRECL.
20#[inline]
21#[must_use = "Handle the Result or propagate the error"]
22pub fn read_record(
23    input: &mut impl Read,
24    format: RecordFormat,
25    lrecl: Option<u32>,
26) -> Result<Option<Vec<u8>>> {
27    match format {
28        RecordFormat::Fixed => read_fixed_record(input, lrecl),
29        RecordFormat::RDW => {
30            read_rdw_record(input, false).map(|record| record.map(|record| record.payload))
31        }
32    }
33}
34
35#[inline]
36fn read_fixed_record(input: &mut impl Read, lrecl: Option<u32>) -> Result<Option<Vec<u8>>> {
37    let mut reader = FixedRecordReader::new(input, lrecl)?;
38    reader.read_record()
39}
40
41/// Read one complete RDW record, preserving its header and reserved bytes.
42///
43/// Use [`read_record`] when the operation only needs the payload. This helper
44/// is the lossless dispatch path for callers that need to inspect or preserve
45/// the original RDW framing metadata.
46///
47/// # Errors
48/// Returns an error when the delegated RDW framing read fails.
49#[inline]
50#[must_use = "Handle the Result or propagate the error"]
51pub fn read_rdw_record(input: &mut impl Read, strict_mode: bool) -> Result<Option<RDWRecord>> {
52    let mut reader = RDWRecordReader::new(input, strict_mode);
53    reader.read_record()
54}
55
56/// Write one record using the selected framing format.
57///
58/// # Errors
59/// Returns an error when the delegated framing write fails.
60#[inline]
61#[must_use = "Handle the Result or propagate the error"]
62pub fn write_record(output: &mut impl Write, data: &[u8], format: RecordFormat) -> Result<()> {
63    match format {
64        RecordFormat::Fixed => {
65            output.write_all(data).map_err(|e| {
66                Error::new(
67                    ErrorCode::CBKR101_FIXED_RECORD_ERROR,
68                    format!("Write error: {e}"),
69                )
70            })?;
71            Ok(())
72        }
73        RecordFormat::RDW => {
74            let mut writer = RDWRecordWriter::new(output);
75            writer.write_record_from_payload(data, None)
76        }
77    }
78}