Buttplug sex toy control library
at dev 5.0 kB view raw
1// Buttplug Rust Source Code File - See https://buttplug.io for more info. 2// 3// Copyright 2016-2024 Nonpolynomial Labs LLC. All rights reserved. 4// 5// Licensed under the BSD 3-Clause license. See LICENSE file in the project root 6// for full license information. 7 8//! Representations of low level [Buttplug Protocol](https://buttplug-spec.docs.buttplug.io) 9//! messages 10//! 11//! The core communication types for the Buttplug protocol. There are structs for each message type, 12//! with only the current message spec being included here (older message specs are only used for 13//! backward compatibilty and are in the server::message module). There are also enum types that are 14//! used to classify messages into categories, for instance, messages that only should be sent by a 15//! client or server. 16 17pub mod v0; 18pub mod v4; 19 20mod device_feature; 21pub mod serializer; 22 23pub use device_feature::*; 24pub use v0::*; 25pub use v4::*; 26 27use crate::errors::ButtplugMessageError; 28use serde_repr::{Deserialize_repr, Serialize_repr}; 29use std::convert::TryFrom; 30 31use super::errors::ButtplugError; 32 33/// Enum of possible [Buttplug Message 34/// Spec](https://buttplug-spec.docs.buttplug.io) versions. 35#[derive( 36 Debug, Clone, Copy, Display, PartialEq, Eq, PartialOrd, Ord, Serialize_repr, Deserialize_repr, 37)] 38#[repr(u32)] 39pub enum ButtplugMessageSpecVersion { 40 Version0 = 0, 41 Version1 = 1, 42 Version2 = 2, 43 Version3 = 3, 44 Version4 = 4, 45} 46 47impl TryFrom<i32> for ButtplugMessageSpecVersion { 48 type Error = ButtplugError; 49 50 // There's probably another crate to make this easier but eh. 51 fn try_from(value: i32) -> Result<Self, Self::Error> { 52 match value { 53 0 => Ok(ButtplugMessageSpecVersion::Version0), 54 1 => Ok(ButtplugMessageSpecVersion::Version1), 55 2 => Ok(ButtplugMessageSpecVersion::Version2), 56 3 => Ok(ButtplugMessageSpecVersion::Version3), 57 4 => Ok(ButtplugMessageSpecVersion::Version4), 58 _ => Err( 59 ButtplugMessageError::InvalidMessageContents(format!( 60 "Message spec version {value} is not valid" 61 )) 62 .into(), 63 ), 64 } 65 } 66} 67 68/// Message Id for events sent from the server, which are not in response to a 69/// client request. 70pub const BUTTPLUG_SERVER_EVENT_ID: u32 = 0; 71 72/// The current latest version of the spec implemented by the library. 73pub const BUTTPLUG_CURRENT_API_MAJOR_VERSION: ButtplugMessageSpecVersion = 74 ButtplugMessageSpecVersion::Version4; 75 76pub const BUTTPLUG_CURRENT_API_MINOR_VERSION: u32 = 0; 77 78pub trait ButtplugMessageFinalizer { 79 fn finalize(&mut self) { 80 } 81} 82 83/// Base trait for all Buttplug Protocol Message Structs. Handles management of 84/// message ids, as well as implementing conveinence functions for converting 85/// between message structs and various message enums, serialization, etc... 86pub trait ButtplugMessage: 87 ButtplugMessageValidator + ButtplugMessageFinalizer + Send + Sync + Clone 88{ 89 /// Returns the id number of the message 90 fn id(&self) -> u32; 91 /// Sets the id number of the message. 92 fn set_id(&mut self, id: u32); 93 /// True if the message is an event (message id of 0) from the server. 94 fn is_server_event(&self) -> bool { 95 self.id() == BUTTPLUG_SERVER_EVENT_ID 96 } 97} 98 99/// Validation function for message contents. Can be run before message is 100/// transmitted, as message may be formed and mutated at multiple points in the 101/// library, or may need to be checked after deserialization. Message enums will 102/// run this on whatever their variant is. 103pub trait ButtplugMessageValidator { 104 /// Returns () if the message is valid, otherwise returns a message error. 105 fn is_valid(&self) -> Result<(), ButtplugMessageError> { 106 // By default, return Ok, as many messages won't have any checks. 107 Ok(()) 108 } 109 110 fn is_system_id(&self, id: u32) -> Result<(), ButtplugMessageError> { 111 if id == 0 { 112 Ok(()) 113 } else { 114 Err(ButtplugMessageError::InvalidMessageContents( 115 "Message should have id of 0, as it is a system message.".to_string(), 116 )) 117 } 118 } 119 120 fn is_not_system_id(&self, id: u32) -> Result<(), ButtplugMessageError> { 121 if id == 0 { 122 Err(ButtplugMessageError::InvalidMessageContents( 123 "Message should not have 0 for an Id. Id of 0 is reserved for system messages.".to_string(), 124 )) 125 } else { 126 Ok(()) 127 } 128 } 129 130 fn is_in_command_range(&self, value: f64, error_msg: String) -> Result<(), ButtplugMessageError> { 131 if !(0.0..=1.0).contains(&value) { 132 Err(ButtplugMessageError::InvalidMessageContents(error_msg)) 133 } else { 134 Ok(()) 135 } 136 } 137} 138 139/// Adds device index handling to the [ButtplugMessage] trait. 140pub trait ButtplugDeviceMessage: ButtplugMessage { 141 fn device_index(&self) -> u32; 142 fn set_device_index(&mut self, id: u32); 143} 144 145/// Type alias for the latest version of client-to-server messages. 146pub type ButtplugClientMessageCurrent = ButtplugClientMessageV4; 147/// Type alias for the latest version of server-to-client messages. 148pub type ButtplugServerMessageCurrent = ButtplugServerMessageV4;