gc_abi 0.5.0

Gridcore Plugin Safe ABI Bindings
Documentation
//! Device configuration types for serial and ethernet interfaces.
//!
//! These types define the configuration for device interfaces that can be queried by plugins.

use crate::error::GCPluginABIError;
use crate::{GCAbiConversion, copy_str_to_c};
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::ffi::CStr;

/// Serial port stop bits configuration
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum StopBits {
    /// 1 stop bit
    One,
    /// 2 stop bits
    Two,
}

impl StopBits {
    /// Converts from C ABI enum to Rust enum
    pub fn from_c(c_stop_bits: gc_abi_sys::GCStopBits) -> Result<Self, GCPluginABIError> {
        match c_stop_bits {
            gc_abi_sys::GCStopBits_GC_STOP_BITS_ONE => Ok(StopBits::One),
            gc_abi_sys::GCStopBits_GC_STOP_BITS_TWO => Ok(StopBits::Two),
            _ => Err(GCPluginABIError::ErrorInvalidCEnum(format!(
                "Invalid stop bits value from C ABI: {}",
                c_stop_bits
            ))),
        }
    }

    /// Converts from Rust enum to C ABI enum
    pub fn to_c(&self) -> gc_abi_sys::GCStopBits {
        match self {
            StopBits::One => gc_abi_sys::GCStopBits_GC_STOP_BITS_ONE,
            StopBits::Two => gc_abi_sys::GCStopBits_GC_STOP_BITS_TWO,
        }
    }
}

/// Serial port parity configuration
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Parity {
    /// No parity
    None,
    /// Odd parity
    Odd,
    /// Even parity
    Even,
}

impl Parity {
    /// Converts from C ABI enum to Rust enum
    pub fn from_c(c_parity: gc_abi_sys::GCParity) -> Result<Self, GCPluginABIError> {
        match c_parity {
            gc_abi_sys::GCParity_GC_PARITY_NONE => Ok(Parity::None),
            gc_abi_sys::GCParity_GC_PARITY_ODD => Ok(Parity::Odd),
            gc_abi_sys::GCParity_GC_PARITY_EVEN => Ok(Parity::Even),
            _ => Err(GCPluginABIError::ErrorInvalidCEnum(format!(
                "Invalid parity value from C ABI: {}",
                c_parity
            ))),
        }
    }

    /// Converts from Rust enum to C ABI enum
    pub fn to_c(&self) -> gc_abi_sys::GCParity {
        match self {
            Parity::None => gc_abi_sys::GCParity_GC_PARITY_NONE,
            Parity::Odd => gc_abi_sys::GCParity_GC_PARITY_ODD,
            Parity::Even => gc_abi_sys::GCParity_GC_PARITY_EVEN,
        }
    }
}

/// Serial port data bits configuration
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum DataBits {
    /// 5 data bits
    Five,
    /// 6 data bits
    Six,
    /// 7 data bits
    Seven,
    /// 8 data bits
    Eight,
}

impl DataBits {
    /// Converts from C ABI enum to Rust enum
    pub fn from_c(c_data_bits: gc_abi_sys::GCDataBits) -> Result<Self, GCPluginABIError> {
        match c_data_bits {
            gc_abi_sys::GCDataBits_GC_DATA_BITS_FIVE => Ok(DataBits::Five),
            gc_abi_sys::GCDataBits_GC_DATA_BITS_SIX => Ok(DataBits::Six),
            gc_abi_sys::GCDataBits_GC_DATA_BITS_SEVEN => Ok(DataBits::Seven),
            gc_abi_sys::GCDataBits_GC_DATA_BITS_EIGHT => Ok(DataBits::Eight),
            _ => Err(GCPluginABIError::ErrorInvalidCEnum(format!(
                "Invalid data bits value from C ABI: {}",
                c_data_bits
            ))),
        }
    }

    /// Converts from Rust enum to C ABI enum
    pub fn to_c(&self) -> gc_abi_sys::GCDataBits {
        match self {
            DataBits::Five => gc_abi_sys::GCDataBits_GC_DATA_BITS_FIVE,
            DataBits::Six => gc_abi_sys::GCDataBits_GC_DATA_BITS_SIX,
            DataBits::Seven => gc_abi_sys::GCDataBits_GC_DATA_BITS_SEVEN,
            DataBits::Eight => gc_abi_sys::GCDataBits_GC_DATA_BITS_EIGHT,
        }
    }
}

/// Zero-cost abstraction over Ethernet interface configuration from C ABI.
///
/// This struct wraps the C ABI struct and provides safe Rust accessors.
#[repr(transparent)]
#[derive(Debug)]
pub struct GCEthernetInterface(gc_abi_sys::sGCEthernetInterface);

impl GCEthernetInterface {
    #[doc(hidden)]
    /// Intended for internal use only - creates an EthernetInterface from raw parameters
    pub fn new(interface: &str) -> Result<Self, GCPluginABIError> {
        let interface_buf = copy_str_to_c(interface)?;
        Ok(GCEthernetInterface(gc_abi_sys::sGCEthernetInterface { interface: interface_buf }))
    }

    /// Get the OS interface name (e.g., "eth0", "enp0s3")
    ///
    /// Returns the interface name as a string slice, or None if the C string is invalid.
    pub fn interface(&self) -> Cow<'_, str> {
        // Safety: The C array is guaranteed to be null-terminated by the core
        unsafe { CStr::from_ptr(self.0.interface.as_ptr()).to_string_lossy() }
    }
}

unsafe impl GCAbiConversion for GCEthernetInterface {
    type CType = gc_abi_sys::sGCEthernetInterface;

    fn from_c(c_type: Self::CType) -> Self {
        GCEthernetInterface(c_type)
    }

    fn into_c(self) -> Self::CType {
        self.0
    }
}

/// Zero-cost abstraction over Serial interface configuration from C ABI.
///
/// This struct wraps the C ABI struct and provides safe Rust accessors.
#[repr(transparent)]
#[derive(Debug)]
pub struct GCSerialInterface(gc_abi_sys::sGCSerialInterface);

impl GCSerialInterface {
    #[doc(hidden)]
    /// Intended for internal use only - creates a SerialInterface from raw parameters
    pub fn new(interface: &str, baud_rate: u32, parity: Parity, stop_bits: StopBits, data_bits: DataBits) -> Result<Self, GCPluginABIError> {
        let interface_buf = copy_str_to_c(interface)?;
        Ok(GCSerialInterface(gc_abi_sys::sGCSerialInterface {
            interface: interface_buf,
            baud_rate,
            parity: parity.to_c(),
            stop_bits: stop_bits.to_c(),
            data_bits: data_bits.to_c(),
        }))
    }

    /// Get the OS interface path (e.g., "/dev/ttyS0", "/dev/ttyM0")
    ///
    /// Returns the interface path as a string slice, or None if the C string is invalid.
    pub fn interface<'a>(&'a self) -> Cow<'a, str> {
        // Safety: The C array is guaranteed to be null-terminated by the core
        unsafe { CStr::from_ptr(self.0.interface.as_ptr()).to_string_lossy() }
    }

    /// Get the baud rate (e.g., 9600, 115200)
    pub fn baud_rate(&self) -> u32 {
        self.0.baud_rate
    }

    /// Get the parity setting
    pub fn parity(&self) -> Result<Parity, GCPluginABIError> {
        Parity::from_c(self.0.parity)
    }

    /// Get the number of stop bits
    pub fn stop_bits(&self) -> Result<StopBits, GCPluginABIError> {
        StopBits::from_c(self.0.stop_bits)
    }

    /// Get the number of data bits
    pub fn data_bits(&self) -> Result<DataBits, GCPluginABIError> {
        DataBits::from_c(self.0.data_bits)
    }
}

unsafe impl GCAbiConversion for GCSerialInterface {
    type CType = gc_abi_sys::sGCSerialInterface;

    fn from_c(c_type: Self::CType) -> Self {
        GCSerialInterface(c_type)
    }

    fn into_c(self) -> Self::CType {
        self.0
    }
}