iscsi-client-rs 0.0.2

A pure-Rust iSCSI initiator library and CLI
Documentation
use anyhow::{Result, bail};

use crate::{
    cfg::config::Config,
    models::{
        common::{BasicHeaderSegment, Builder},
        parse::Pdu,
    },
};

/// Trait for serializing a Protocol Data Unit (PDU) into bytes.
pub trait ToBytes: Sized {
    // The fixed length of the PDU header in bytes.
    // rust now don`t support compile time array length
    type Header: AsRef<[u8]>;

    /// Consume the PDU builder or object and produce:
    /// - A fixed-size array of `HEADER_LEN` bytes representing the PDU header.
    /// - A `Vec<u8>` containing the variable-length data segment.
    /// - A `Option<Vec<u8>>` containing the data-digest data segment.
    fn to_bytes(self, cfg: &Config) -> Result<(Self::Header, Vec<u8>)>;
}

/// Trait for deserializing a full PDU from raw bytes.
pub trait FromBytes: Sized + BasicHeaderSegment {
    /// The fixed length of the PDU header in bytes.
    ///
    /// rust now don`t support compile time array length
    const HEADER_LEN: usize;

    /// Given only the header bytes, inspect them to determine
    /// the total length of the entire PDU (header + payload + optional digest).
    ///
    /// The total PDU length in bytes, or an error if the header is malformed
    /// or too short.
    fn total_len(buf: &[u8]) -> Result<usize> {
        if buf.len() < Self::HEADER_LEN {
            bail!(
                "Buffer {} too small for Pdu BHS {}",
                buf.len(),
                Self::HEADER_LEN
            );
        }
        let hdr = Pdu::from_bhs_bytes(&buf[..Self::HEADER_LEN])?;

        Ok(hdr.total_length_bytes())
    }

    /// Parse the full PDU from a contiguous byte buffer.
    ///
    /// The parsed `Response` (often a tuple of header struct, payload bytes,
    /// and digest), or an error if parsing fails.
    fn from_bytes(buf: &[u8]) -> Result<Self>;
}

impl<B> ToBytes for B
where B: Builder
{
    type Header = B::Header;

    fn to_bytes(self, cfg: &Config) -> Result<(Self::Header, Vec<u8>)> {
        self.build(cfg)
    }
}