use crate::message;
use libffi::low;
use std::sync::Arc;
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum MessageMagic {
End = 0x0,
TypeUint = 0x10,
TypeInt = 0x11,
TypeF32 = 0x12,
TypeSeq = 0x13,
TypeObjectId = 0x14,
TypeVarchar = 0x20,
TypeArray = 0x21,
TypeObject = 0x22,
TypeFd = 0x40,
}
impl MessageMagic {
pub(crate) fn to_ffi_type(self) -> *mut low::ffi_type {
match self {
Self::TypeUint | Self::TypeObject | Self::TypeSeq | Self::TypeObjectId => {
&raw mut low::types::uint32
}
Self::TypeInt | Self::TypeFd => &raw mut low::types::sint32,
Self::TypeVarchar | Self::TypeArray => &raw mut low::types::pointer,
Self::TypeF32 => &raw mut low::types::float,
Self::End => &raw mut low::types::void,
}
}
}
impl TryFrom<u8> for MessageMagic {
type Error = message::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0x00 => Ok(Self::End),
0x10 => Ok(Self::TypeUint),
0x11 => Ok(Self::TypeInt),
0x12 => Ok(Self::TypeF32),
0x13 => Ok(Self::TypeSeq),
0x14 => Ok(Self::TypeObjectId),
0x20 => Ok(Self::TypeVarchar),
0x21 => Ok(Self::TypeArray),
0x22 => Ok(Self::TypeObject),
0x40 => Ok(Self::TypeFd),
_ => Err(message::Error::MalformedMessage),
}
}
}
pub enum CallArg<'a> {
Uint(u32),
Int(i32),
F32(f32),
Object(u32),
Varchar(&'a [u8]),
Fd(i32),
UintArray(&'a [u32]),
IntArray(&'a [i32]),
F32Array(&'a [f32]),
ObjectArray(&'a [u32]),
FdArray(&'a [i32]),
VarcharArray(&'a [&'a [u8]]),
}
pub struct Method {
pub idx: u32,
pub params: &'static [u8],
pub returns_type: &'static str,
pub since: u32,
pub destructor: bool,
}
pub trait ProtocolObjectSpec: Send + Sync {
fn object_name(&self) -> &str;
fn c2s(&self) -> &[Method];
fn s2c(&self) -> &[Method];
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn message_magic_known_values_try_from() {
let known: &[u8] = &[0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x20, 0x21, 0x22, 0x40];
for &byte in known {
assert!(
MessageMagic::try_from(byte).is_ok(),
"expected Ok for byte={byte:#04x}"
);
}
}
#[test]
fn message_magic_unknown_value_fails() {
assert!(MessageMagic::try_from(0xFF_u8).is_err());
}
}
pub trait ProtocolSpec {
fn spec_name(&self) -> &str;
fn spec_ver(&self) -> u32;
fn objects(&self) -> &[Arc<dyn ProtocolObjectSpec>];
}