dis-rs 0.13.0

An implementation of the Distributed Interactive Simulation protocol (IEEE-1278.1) in Rust. This main crate contains PDU implementations and facilities to read/write PDUs from Rust data structures to the wire format and vice versa. It supports versions 6 and 7 of the protocol.
Documentation
use crate::common::attribute::model::{
    Attribute, AttributeRecord, AttributeRecordSet, BASE_ATTRIBUTE_RECORD_LENGTH_OCTETS,
};
use crate::common::model::PduBody;
use crate::common::parser::{entity_id, pdu_type, protocol_version, simulation_address};
use crate::enumerations::{AttributeActionCode, VariableRecordType};
use crate::BodyRaw;
use nom::bytes::complete::take;
use nom::multi::count;
use nom::number::complete::{be_u16, be_u32, be_u8};
use nom::{IResult, Parser};

pub(crate) fn attribute_body(input: &[u8]) -> IResult<&[u8], PduBody> {
    let (input, origination_simulation_address) = simulation_address(input)?;
    let (input, _padding) = be_u32(input)?;
    let (input, _padding) = be_u16(input)?;
    let (input, record_pdu_type) = pdu_type(input)?;
    let (input, record_protocol_version) = protocol_version(input)?;
    let (input, master_attribute_record_type) = be_u32(input)?;
    let master_attribute_record_type = VariableRecordType::from(master_attribute_record_type);
    let (input, action_code) = be_u8(input)?;
    let action_code = AttributeActionCode::from(action_code);
    let (input, _padding) = be_u8(input)?;
    let (input, number_of_record_sets) = be_u16(input)?;
    let (input, attribute_record_sets) =
        count(attribute_record_set, number_of_record_sets.into()).parse(input)?;

    let body = Attribute::builder()
        .with_originating_simulation_address(origination_simulation_address)
        .with_record_pdu_type(record_pdu_type)
        .with_record_protocol_version(record_protocol_version)
        .with_master_attribute_record_type(master_attribute_record_type)
        .with_action_code(action_code)
        .with_attribute_record_sets(attribute_record_sets)
        .build();

    Ok((input, body.into_pdu_body()))
}

pub(crate) fn attribute_record_set(input: &[u8]) -> IResult<&[u8], AttributeRecordSet> {
    let (input, entity_id) = entity_id(input)?;
    let (input, number_of_records) = be_u16(input)?;
    let (input, attribute_records) =
        count(attribute_record, number_of_records.into()).parse(input)?;

    Ok((
        input,
        AttributeRecordSet::new()
            .with_entity_id(entity_id)
            .with_attribute_records(attribute_records),
    ))
}

pub(crate) fn attribute_record(input: &[u8]) -> IResult<&[u8], AttributeRecord> {
    let (input, record_type) = be_u32(input)?;
    let record_type = VariableRecordType::from(record_type);
    let (input, record_length_octets) = be_u16(input)?;
    let (input, fields) =
        take(record_length_octets.saturating_sub(BASE_ATTRIBUTE_RECORD_LENGTH_OCTETS))(input)?;

    Ok((
        input,
        AttributeRecord::new()
            .with_record_type(record_type)
            .with_specific_fields(fields.to_vec()),
    ))
}