xio_instructionset 0.5.0

XIO instructionset data structures
Documentation
#![deny(missing_docs)]

//! The data structures representing a XIO instruction set.

#[macro_use]
extern crate serde_derive;

extern crate indexmap;
extern crate ommui_file_loading;
extern crate ommui_string_patterns;
extern crate serde;
extern crate xio_base_datatypes;

use indexmap::IndexMap;
use ommui_string_patterns::{
    freetextstring, idstring, idstring_maybe_empty,
};
use xio_base_datatypes as base;

mod hexnumber;

/// Functionality for loading a XIO instruction set from files.
pub mod filesystem;

/// A map containing instructions indexed by their identifier.
pub type InstructionMap = IndexMap<String, Instruction>;

/// Description of an instruction type.
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct Instruction {
    /// The instruction code.
    #[serde(with = "hexnumber")]
    pub code: u16,

    /// The description of the instruction.
    #[serde(with = "freetextstring")]
    pub description: String,

    /// The format string in Qt format syntax.
    ///
    /// The Qt string formatting replaces %1, %2, …, %99 in the provided
    /// order. See http://doc.qt.io/qt-5/qstring.html#arg
    #[serde(
        with = "freetextstring",
        default,
        skip_serializing_if = "String::is_empty"
    )]
    pub formatstring: String,

    /// The parameters which are required for the instruction.
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub parameters: Vec<InstructionParameter>,
}

/// Instruction categories.
pub enum InstructionCategory {
    /// Commands without a time extent (e.g. setValue).
    CommandWithoutTimeExtent,

    /// Commands with time extent (e.g. wait);
    CommandWithTimeExtent,

    /// Conditions for commands with time extent.
    Condition,

    /// Invalid category.
    Invalid,
}

impl Instruction {
    /// Get the category of an instruction.
    pub fn category(&self) -> InstructionCategory {
        use std::ops::Shr;
        use InstructionCategory::*;
        match self.code.shr(8) & 0b1111u16 {
            0b0000u16 => CommandWithoutTimeExtent,
            0b0100u16 => CommandWithTimeExtent,
            0b1000u16 => Condition,
            _ => Invalid,
        }
    }
}

/// Description of an instruction parameter type.
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct InstructionParameter {
    /// The id string of the parameter.
    #[serde(with = "idstring")]
    pub id: String,

    /// The group to which the parameter belongs.
    ///
    /// If empty, the parameter implicitly has it's own group where
    /// it is the only member.
    #[serde(
        with = "idstring_maybe_empty",
        default,
        skip_serializing_if = "String::is_empty"
    )]
    pub group: String,

    /// The allowed types of parameters.
    ///
    /// Each parameter in a group must have the same type.
    #[serde(rename = "type")]
    pub parameter_type: Vec<base::DataType>,

    /// The permitted storage type for the parameter.
    pub storage: base::StorageTypeWithMixed,

    /// A human-readable description of the parameter.
    #[serde(with = "freetextstring")]
    pub description: String,
}