dis-rust 0.2.10

A rust implementation of the DIS simulation protocol.
Documentation
//     dis-rust - A rust implementation of the DIS simulation protocol.
//     Copyright (C) 2022 Thomas Mann
// 
//     This software is dual-licensed. It is available under the conditions of
//     the GNU Affero General Public License (see the LICENSE file included) 
//     or under a commercial license (email contact@coffeebreakdevs.com for
//     details).

use bytes::{BytesMut, BufMut, Buf};
use num_derive::FromPrimitive;
use serde::{Serialize, Deserialize}; 

#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
/// General Appearance Record as defined in IEEE 1278.1 standard. Used to communicate the general appearance of an entity during the simulation.
pub struct GeneralAppearanceRecord {
    pub entity_paint_scheme_field: EntityPaintScheme,
    pub entity_mobility_kill_field: EntityMobilityKill,
    pub entity_fire_power_field: EntityFirePower,
    pub entity_damage_field: EntityDamage,
    pub entity_smoke_field: EntitySmoke,
    pub entity_trailing_effect_field: EntityTrailingEffect,
    pub entity_hatch_state_field: EntityHatchState,
    pub entity_lights_field: EntityLights,
    pub entity_flaming_effect_field: EntityFlamingEffect,
}

impl GeneralAppearanceRecord {
    /// Provides a function to create a new GeneralAppearanceRecord.
    pub fn new(entity_paint_scheme_field: EntityPaintScheme,
        entity_mobility_kill_field: EntityMobilityKill,
        entity_fire_power_field: EntityFirePower,
        entity_damage_field: EntityDamage,
        entity_smoke_field: EntitySmoke,
        entity_trailing_effect_field: EntityTrailingEffect,
        entity_hatch_state_field: EntityHatchState,
        entity_lights_field: EntityLights,
        entity_flaming_effect_field: EntityFlamingEffect,) -> Self {
        GeneralAppearanceRecord {
            entity_paint_scheme_field,
            entity_mobility_kill_field,
            entity_fire_power_field,
            entity_damage_field,
            entity_smoke_field,
            entity_trailing_effect_field,
            entity_hatch_state_field,
            entity_lights_field,
            entity_flaming_effect_field,
        }
    }

    /// Provides a function to default a new GeneralAppearanceRecord.
    /// The default record shows an entity in uniform with no damage or effects.
    pub fn default() -> Self {
        GeneralAppearanceRecord {
            entity_paint_scheme_field: EntityPaintScheme::UniformColor,
            entity_mobility_kill_field: EntityMobilityKill::NoMobilityKill,
            entity_fire_power_field: EntityFirePower::NoFirePowerKill,
            entity_damage_field: EntityDamage::NoDamage,
            entity_smoke_field: EntitySmoke::NotSmoking,
            entity_trailing_effect_field: EntityTrailingEffect::None,
            entity_hatch_state_field: EntityHatchState::NotApplicable,
            entity_lights_field: EntityLights::None,
            entity_flaming_effect_field: EntityFlamingEffect::None,
        }
    }

    /// Fills a BytesMut struct with a GeneralAppearanceRecord serialised into binary. This buffer is then ready to be sent via
    /// UDP to the simluation network.
    pub fn serialize(&self, buf: &mut BytesMut) {
        let entity_paint_scheme : u16 = self.entity_paint_scheme_field as u16;
        let entity_paint_scheme = entity_paint_scheme << 15;
        let entity_mobility_kill : u16 = self.entity_mobility_kill_field as u16;
        let entity_mobility_kill = entity_mobility_kill << 14;
        let entity_fire_power : u16 = self.entity_fire_power_field as u16;
        let entity_fire_power = entity_fire_power << 13;
        let entity_damage : u16 = self.entity_damage_field as u16;
        let entity_damage = entity_damage << 11;
        let entity_smoke : u16 = self.entity_smoke_field as u16;
        let entity_smoke = entity_smoke << 9;
        let entity_trailing_effect : u16 = self.entity_trailing_effect_field as u16;
        let entity_trailing_effect = entity_trailing_effect << 7;
        let entity_hatch_state : u16 = self.entity_hatch_state_field as u16;
        let entity_hatch_state = entity_hatch_state << 4;
        let entity_lights : u16 = self.entity_lights_field as u16;
        let entity_lights = entity_lights << 1;
        let entity_flaming_effect : u16 = self.entity_flaming_effect_field as u16;

        let general_appearance : u16 = 0u16 | entity_paint_scheme | entity_mobility_kill
            | entity_fire_power | entity_damage | entity_smoke | entity_trailing_effect
            | entity_hatch_state | entity_lights | entity_flaming_effect;
        buf.put_u16(general_appearance);
    }

    pub fn decode(buf: &mut BytesMut) -> GeneralAppearanceRecord {
        let bytes = buf.get_u16();
        GeneralAppearanceRecord { 
            entity_paint_scheme_field: EntityPaintScheme::from_u8((bytes >> 1) as u8), 
            entity_mobility_kill_field: EntityMobilityKill::from_u8((bytes >> 1) as u8), 
            entity_fire_power_field: EntityFirePower::from_u8((bytes >> 1) as u8), 
            entity_damage_field: EntityDamage::from_u8((bytes >> 2) as u8), 
            entity_smoke_field: EntitySmoke::from_u8((bytes >> 2) as u8), 
            entity_trailing_effect_field: EntityTrailingEffect::from_u8((bytes >> 2) as u8), 
            entity_hatch_state_field: EntityHatchState::from_u8((bytes >> 3) as u8), 
            entity_lights_field: EntityLights::from_u8((bytes >> 3) as u8), 
            entity_flaming_effect_field: EntityFlamingEffect::from_u8((bytes >> 1) as u8) 
        }
    }
}

#[derive(Debug, FromPrimitive, PartialEq, Clone, Copy, Serialize, Deserialize)]
/// Enum to represent an entity's paint scheme.
pub enum EntityPaintScheme {
    UniformColor = 0,
    Camouflage = 1,
}

impl EntityPaintScheme {
    pub fn from_u8(bit: u8) -> EntityPaintScheme {
        match bit {
            0 => EntityPaintScheme::UniformColor,
            1 => EntityPaintScheme::Camouflage,
            2_u8..=u8::MAX => EntityPaintScheme::UniformColor
        }
    }
}

#[derive(Debug, FromPrimitive, PartialEq, Clone, Copy, Serialize, Deserialize)]
/// Enum to represent an entity's mobility kill status.
pub enum EntityMobilityKill {
    NoMobilityKill = 0,
    MobilityKill = 1,
}

impl EntityMobilityKill {
    pub fn from_u8(bit: u8) -> EntityMobilityKill {
        match bit {
            0 => EntityMobilityKill::NoMobilityKill,
            1 => EntityMobilityKill::MobilityKill,
            2_u8..=u8::MAX => EntityMobilityKill::NoMobilityKill
        }
    }
}

#[derive(Debug, FromPrimitive, PartialEq, Clone, Copy, Serialize, Deserialize)]
/// Enum to represent an entity's firepower kill status.
pub enum EntityFirePower {
    NoFirePowerKill = 0,
    FirePowerKill = 1,
}

impl EntityFirePower {
    pub fn from_u8(bit: u8) -> EntityFirePower {
        match bit {
            0 => EntityFirePower::NoFirePowerKill,
            1 => EntityFirePower::FirePowerKill,
            2_u8..=u8::MAX => EntityFirePower::NoFirePowerKill
        }
    }
}

#[derive(Debug, FromPrimitive, PartialEq, Clone, Copy, Serialize, Deserialize)]
/// Enum to represent an entity's damage.
pub enum EntityDamage {
    NoDamage = 0,
    SlightDamage = 1,
    ModerateDamage = 2,
    Destroyed = 3,
}

impl EntityDamage {
    pub fn from_u8(bit: u8) -> EntityDamage {
        match bit {
            0 => EntityDamage::NoDamage,
            1 => EntityDamage::SlightDamage,
            2 => EntityDamage::ModerateDamage,
            3 => EntityDamage::Destroyed,
            3_u8..=u8::MAX => EntityDamage::Destroyed
        }
    }
}

#[derive(Debug, FromPrimitive, PartialEq, Clone, Copy, Serialize, Deserialize)]
/// Enum to represent an entity's smoke effect.
pub enum EntitySmoke {
    NotSmoking = 0,
    SmokePlumeRising = 1,
    EngineSmoke = 2,
    EngineSmokeAndSmokePlumeRising = 3,
}

impl EntitySmoke {
    pub fn from_u8(bit: u8) -> EntitySmoke {
        match bit {
            0 => EntitySmoke::NotSmoking,
            1 => EntitySmoke::SmokePlumeRising,
            2 => EntitySmoke::EngineSmoke,
            3_u8..=u8::MAX => EntitySmoke::EngineSmokeAndSmokePlumeRising
        }
    }
}

#[derive(Debug, FromPrimitive, PartialEq, Clone, Copy, Serialize, Deserialize)]
/// Enum to represent an entity's trailing effect.
pub enum EntityTrailingEffect {
    None = 0,
    Small = 1,
    Medium = 2,
    Large = 3,
}

impl EntityTrailingEffect {
    pub fn from_u8(bit: u8) -> EntityTrailingEffect {
        match bit {
            0 => EntityTrailingEffect::None,
            1 => EntityTrailingEffect::Small,
            2 => EntityTrailingEffect::Medium,
            3_u8..=u8::MAX => EntityTrailingEffect::Large
        }
    }
}

#[derive(Debug, FromPrimitive, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub enum EntityHatchState {
    NotApplicable = 0,
    PrimaryHatchClosed = 1,
    PrimaryHatchPopped = 2,
    PrimaryHatchPoppedAndPersonVisibleUnderHatch = 3,
    PrimaryHatchOpen = 4,
    PrimaryHatchOpenAndPersonVisible = 5,
}

impl EntityHatchState {
    pub fn from_u8(bit: u8) -> EntityHatchState {
        match bit {
            0 => EntityHatchState::NotApplicable,
            1 => EntityHatchState::PrimaryHatchClosed,
            2 => EntityHatchState::PrimaryHatchPopped,
            3 => EntityHatchState::PrimaryHatchPoppedAndPersonVisibleUnderHatch,
            4 => EntityHatchState::PrimaryHatchOpen,
            5_u8..=u8::MAX => EntityHatchState::PrimaryHatchOpenAndPersonVisible
        }
    }
}

#[derive(Debug, FromPrimitive, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub enum EntityLights {
    None = 0,
    RunningLightsOn = 1,
    NavigationLightsOn = 2,
    FormationLightsOn = 3,
}

impl EntityLights {
    pub fn from_u8(bit: u8) -> EntityLights {
        match bit {
            0 => EntityLights::None,
            1 => EntityLights::RunningLightsOn,
            2 => EntityLights::NavigationLightsOn,
            3_u8..=u8::MAX => EntityLights::None
        }
    }
}

#[derive(Debug, FromPrimitive, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub enum EntityFlamingEffect {
    None = 0,
    FlamesPresent = 1,
}

impl EntityFlamingEffect {
    pub fn from_u8(bit: u8) -> EntityFlamingEffect {
        match bit {
            0 => EntityFlamingEffect::None,
            1 => EntityFlamingEffect::FlamesPresent,
            2_u8..=u8::MAX => EntityFlamingEffect::None
        }
    }
}