vlfd-rs 2.0.1

Modern Rust driver for the VLFD board
Documentation
use std::{error::Error as StdError, fmt};
pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    DeviceNotOpen,
    DeviceNotFound {
        vid: u16,
        pid: u16,
    },
    BufferTooLarge {
        context: &'static str,
        max_words: usize,
        actual_words: usize,
    },
    FeatureUnavailable(&'static str),
    InvalidBitfile(&'static str),
    InvalidBitfileLine {
        line: usize,
        reason: &'static str,
    },
    InvalidBufferLength {
        context: &'static str,
        expected: usize,
        actual: usize,
    },
    InvalidMode {
        expected: &'static str,
        actual: &'static str,
    },
    NotProgrammed,
    Timeout(&'static str),
    UnexpectedResponse(&'static str),
    VersionMismatch {
        expected: u16,
        actual: u16,
    },
    Usb {
        source: Box<dyn StdError + Send + Sync>,
        context: &'static str,
    },
    Io(std::io::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::DeviceNotOpen => write!(f, "device is not open"),
            Error::DeviceNotFound { vid, pid } => {
                write!(f, "device {vid:#06x}:{pid:#06x} not found")
            }
            Error::BufferTooLarge {
                context,
                max_words,
                actual_words,
            } => write!(
                f,
                "{context} exceeds FIFO capacity ({actual_words} words > {max_words} words)"
            ),
            Error::FeatureUnavailable(feature) => write!(f, "feature `{feature}` is unavailable"),
            Error::InvalidBitfile(reason) => write!(f, "invalid bitfile: {reason}"),
            Error::InvalidBitfileLine { line, reason } => {
                write!(f, "invalid bitfile line {line}: {reason}")
            }
            Error::InvalidBufferLength {
                context,
                expected,
                actual,
            } => write!(
                f,
                "invalid buffer length for `{context}` (expected {expected}, got {actual})"
            ),
            Error::InvalidMode { expected, actual } => {
                write!(
                    f,
                    "invalid device mode (expected `{expected}`, got `{actual}`)"
                )
            }
            Error::NotProgrammed => write!(f, "FPGA is not programmed"),
            Error::Timeout(context) => write!(f, "operation `{context}` timed out"),
            Error::UnexpectedResponse(context) => {
                write!(f, "unexpected response during `{context}`")
            }
            Error::VersionMismatch { expected, actual } => write!(
                f,
                "SMIMS version mismatch (expected {expected:#06x}, found {actual:#06x})"
            ),
            Error::Usb { source, context } => {
                write!(f, "usb error {source} in `{context}`")
            }
            Error::Io(err) => err.fmt(f),
        }
    }
}

impl std::error::Error for Error {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Error::Usb { source, .. } => Some(source.as_ref()),
            Error::Io(err) => Some(err),
            _ => None,
        }
    }
}

impl From<std::io::Error> for Error {
    fn from(value: std::io::Error) -> Self {
        Self::Io(value)
    }
}