pub mod v0;
pub mod v4;
mod device_feature;
pub mod serializer;
pub use device_feature::*;
pub use v0::*;
pub use v4::*;
use crate::errors::ButtplugMessageError;
use enum_dispatch::enum_dispatch;
use serde_repr::{Deserialize_repr, Serialize_repr};
use std::convert::TryFrom;
use super::errors::ButtplugError;
#[derive(
Debug, Clone, Copy, Display, PartialEq, Eq, PartialOrd, Ord, Serialize_repr, Deserialize_repr,
)]
#[repr(u32)]
pub enum ButtplugMessageSpecVersion {
Version0 = 0,
Version1 = 1,
Version2 = 2,
Version3 = 3,
Version4 = 4,
}
impl TryFrom<i32> for ButtplugMessageSpecVersion {
type Error = ButtplugError;
fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(ButtplugMessageSpecVersion::Version0),
1 => Ok(ButtplugMessageSpecVersion::Version1),
2 => Ok(ButtplugMessageSpecVersion::Version2),
3 => Ok(ButtplugMessageSpecVersion::Version3),
4 => Ok(ButtplugMessageSpecVersion::Version4),
_ => Err(
ButtplugMessageError::InvalidMessageContents(format!(
"Message spec version {value} is not valid"
))
.into(),
),
}
}
}
pub const BUTTPLUG_SERVER_EVENT_ID: u32 = 0;
pub const BUTTPLUG_CURRENT_API_MAJOR_VERSION: ButtplugMessageSpecVersion =
ButtplugMessageSpecVersion::Version4;
pub const BUTTPLUG_CURRENT_API_MINOR_VERSION: u32 = 0;
pub trait ButtplugMessageFinalizer {
fn finalize(&mut self) {
}
}
#[enum_dispatch]
pub trait ButtplugMessage: ButtplugMessageValidator + Send + Sync + Clone {
fn id(&self) -> u32;
fn set_id(&mut self, id: u32);
fn is_server_event(&self) -> bool {
self.id() == BUTTPLUG_SERVER_EVENT_ID
}
}
#[enum_dispatch]
pub trait ButtplugMessageValidator {
fn is_valid(&self) -> Result<(), ButtplugMessageError> {
Ok(())
}
fn is_system_id(&self, id: u32) -> Result<(), ButtplugMessageError> {
if id == 0 {
Ok(())
} else {
Err(ButtplugMessageError::InvalidMessageContents(
"Message should have id of 0, as it is a system message.".to_string(),
))
}
}
fn is_not_system_id(&self, id: u32) -> Result<(), ButtplugMessageError> {
if id == 0 {
Err(ButtplugMessageError::InvalidMessageContents(
"Message should not have 0 for an Id. Id of 0 is reserved for system messages.".to_string(),
))
} else {
Ok(())
}
}
fn is_in_command_range(&self, value: f64, error_msg: String) -> Result<(), ButtplugMessageError> {
if !(0.0..=1.0).contains(&value) {
Err(ButtplugMessageError::InvalidMessageContents(error_msg))
} else {
Ok(())
}
}
}
#[enum_dispatch]
pub trait ButtplugDeviceMessage: ButtplugMessage {
fn device_index(&self) -> u32;
fn set_device_index(&mut self, id: u32);
}
pub type ButtplugClientMessageCurrent = ButtplugClientMessageV4;
pub type ButtplugServerMessageCurrent = ButtplugServerMessageV4;
macro_rules! simple_client_message {
($name:ident) => {
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct $name {
#[serde(rename = "Id")]
id: u32,
}
impl Default for $name {
fn default() -> Self {
Self { id: 1 }
}
}
impl crate::message::ButtplugMessage for $name {
fn id(&self) -> u32 {
self.id
}
fn set_id(&mut self, id: u32) {
self.id = id;
}
}
impl crate::message::ButtplugMessageValidator for $name {
fn is_valid(&self) -> Result<(), crate::errors::ButtplugMessageError> {
self.is_not_system_id(self.id)
}
}
};
}
pub(crate) use simple_client_message;