Lines
100 %
Functions
68.85 %
Branches
//! Error enums and flags
/// A result type which uses the [Error] enum as the error type.
pub type Result<T> = core::result::Result<T, Error>;
/// Calculate a parity bit given a u16 word value
///
/// MIL STD 1553B uses an odd parity bit (1 if the
/// bit count of the data is even, 0 if not)[^1].
/// [^1]: [MIL-STD-1553 Tutorial](http://www.horntech.cn/techDocuments/MIL-STD-1553Tutorial.pdf)
#[inline]
#[must_use = "Returned value is not used"]
pub(crate) const fn parity(v: u16) -> u8 {
match v.count_ones() % 2 {
0 => 1,
_ => 0,
}
/// An error deriving from the software itself, rather than a terminal.
/// These errors occur during parsing or other calculations when those
/// calculations fail. The [Error::SystemError] variant
/// contains any errors generated by the 1553 bus.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
#[repr(u8)]
pub enum Error {
/// An index or range was out of bounds
OutOfBounds,
/// A packet was found to be invalid
InvalidPacket,
/// A word was found to be invalid
InvalidWord,
/// The given string is the wrong size or encoding
InvalidString,
/// The message is full and cannot accept words
MessageFull,
/// A message cannot begin with a data word
DataFirst,
/// Cannot add header words after the first word
HeaderNotFirst,
/// The message is invalid
InvalidMessage,
/// An error from a terminal (see [SystemError])
SystemError(SystemError),
/// An error deriving from a remote terminal or bus controller.
/// These errors are generated during runtime by terminals and
/// provided in messages on the bus.
pub enum SystemError {
/// No error
None,
/// A terminal error (see [TerminalError] for more information)
Terminal(TerminalError),
/// A subsystem error (see [SubsystemError] for more information)
Subsystem(SubsystemError),
/// A message error (see [MessageError] for more information)
Message(MessageError),
/// This flag is to inform the bus controller of faults in a remote terminal
/// The error bit flag defined here maps to the Terminal Flag bit at bit
/// time 19 (index 15). It is used to notify the bus controller of a fault
/// or failure within the *entire* remote terminal, rather than only the
/// channel on which the error was received.
/// This flag is described on page 35 in the MIL-STD-1553 Tutorial[^1].
pub enum TerminalError {
None = 0,
/// An error has occurred
Error = 1,
impl TerminalError {
/// Check if the enum is the 'None' variant
pub const fn is_none(&self) -> bool {
matches!(self, Self::None)
/// Check if the enum is the 'Error' variant
pub const fn is_error(&self) -> bool {
matches!(self, Self::Error)
impl From<u8> for TerminalError {
fn from(value: u8) -> Self {
match value {
1 => Self::Error,
_ => Self::None,
impl From<TerminalError> for u8 {
fn from(value: TerminalError) -> Self {
TerminalError::Error => 1,
TerminalError::None => 0,
impl From<u16> for TerminalError {
fn from(value: u16) -> Self {
Self::from(value as u8)
impl From<TerminalError> for u16 {
u8::from(value) as u16
/// This flag provides health data regarding subsystems of a remote terminal.
/// The Subsystem Flag bit located at bit time 17 (index 13) is used to provide
/// “health” data regarding the subsystems to which the remote terminal is connected.
/// Multiple subsystems may logically OR their bits together to form a composite
/// health indicator. This indicator only informs the bus controller that a fault
/// or failure exists, and further information must be obtained in some other fashion.
/// This flag is described on page 34 in the MIL-STD-1553 Tutorial[^1].
pub enum SubsystemError {
impl SubsystemError {
/// Check if the enum is 'None' variant
/// Check if the enum is 'Error' variant
impl From<u8> for SubsystemError {
impl From<SubsystemError> for u8 {
fn from(value: SubsystemError) -> Self {
SubsystemError::Error => 1,
SubsystemError::None => 0,
impl From<u16> for SubsystemError {
impl From<SubsystemError> for u16 {
/// This flag is set when a receiving terminal detects an error in a message.
/// The error may have occurred in any of the data words within the message, and
/// when a terminal receives this flag in a message, it will ignore all data
/// words in the containing message. If an error is detected within a message
/// and this flag is set, the remote terminal must suppress transmission of the
/// status word. If an illegal command is detected, this flag is set and the
/// status word is transmitted.
/// This flag is described on page 32 in the MIL-STD-1553 Tutorial[^1].
pub enum MessageError {
impl MessageError {
/// Check if enum is 'Error' variant
impl From<u8> for MessageError {
impl From<MessageError> for u8 {
fn from(value: MessageError) -> Self {
MessageError::Error => 1,
MessageError::None => 0,
impl From<u16> for MessageError {
impl From<MessageError> for u16 {
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parity_0() {
let value = parity(0b1010101010101010);
assert_eq!(value, 1);
fn test_parity_1() {
let value = parity(0b1010101010101000);
assert_eq!(value, 0);
fn test_parity_2() {
let value = parity(0b1010101010100000);
fn test_parity_3() {
let value = parity(0b1010101010000000);
fn test_system_error_clone() {
let error1 = SystemError::Terminal(TerminalError::Error);
let error2 = error1.clone();
assert_eq!(error1, error2);
fn test_terminal_error_clone() {
let error1 = TerminalError::Error;
fn test_terminal_error() {
let error = TerminalError::None;
assert!(error.is_none());
let error = TerminalError::Error;
assert!(error.is_error());
fn test_terminal_error_from_u8() {
let error = TerminalError::from(0u8);
let error = TerminalError::from(1u8);
fn test_u8_from_terminal_error() {
let error = u8::from(TerminalError::None);
assert_eq!(error, 0);
let error = u8::from(TerminalError::Error);
assert_eq!(error, 1);
fn test_terminal_error_from_u16() {
let error = TerminalError::from(0u16);
let error = TerminalError::from(1u16);
fn test_u16_from_terminal_error() {
let error = u16::from(TerminalError::None);
let error = u16::from(TerminalError::Error);
fn test_subsystem_error_clone() {
let error1 = SubsystemError::Error;
fn test_subsystem_error() {
let error = SubsystemError::None;
let error = SubsystemError::Error;
fn test_subsystem_error_from_u8() {
let error = SubsystemError::from(0u8);
let error = SubsystemError::from(1u8);
fn test_u8_from_subsystem_error() {
let error = u8::from(SubsystemError::None);
let error = u8::from(SubsystemError::Error);
fn test_subsystem_error_from_u16() {
let error = SubsystemError::from(0u16);
let error = SubsystemError::from(1u16);
fn test_u16_from_subsystem_error() {
let error = u16::from(SubsystemError::None);
let error = u16::from(SubsystemError::Error);
fn test_message_error_clone() {
let error1 = MessageError::Error;
fn test_message_error() {
let error = MessageError::None;
let error = MessageError::Error;
fn test_message_error_from_u8() {
let error = MessageError::from(0u8);
let error = MessageError::from(1u8);
fn test_u8_from_message_error() {
let error = u8::from(MessageError::None);
let error = u8::from(MessageError::Error);
fn test_message_error_from_u16() {
let error = MessageError::from(0u16);
let error = MessageError::from(1u16);
fn test_u16_from_message_error() {
let error = u16::from(MessageError::None);
let error = u16::from(MessageError::Error);