buttplug/core/message/
mod.rs

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//! sometimes with multiple versions of the same message relating to different spec versions. There
13//! are also enum types that are used to classify messages into categories, for instance, messages
14//! that only should be sent by a client or server.
15
16mod battery_level_cmd;
17mod battery_level_reading;
18mod client_device_message_attributes;
19mod device_added;
20mod device_feature;
21mod device_list;
22mod device_message_info;
23mod device_removed;
24mod endpoint;
25mod error;
26mod fleshlight_launch_fw12_cmd;
27mod kiiroo_cmd;
28mod linear_cmd;
29mod log;
30mod log_level;
31mod lovense_cmd;
32mod ok;
33mod ping;
34mod raw_read_cmd;
35mod raw_reading;
36mod raw_subscribe_cmd;
37mod raw_unsubscribe_cmd;
38mod raw_write_cmd;
39mod request_device_list;
40mod request_log;
41mod request_server_info;
42mod rotate_cmd;
43mod rssi_level_cmd;
44mod rssi_level_reading;
45mod scalar_cmd;
46mod scanning_finished;
47mod sensor_read_cmd;
48mod sensor_reading;
49mod sensor_subscribe_cmd;
50mod sensor_unsubscribe_cmd;
51pub mod serializer;
52mod server_info;
53mod single_motor_vibrate_cmd;
54mod start_scanning;
55mod stop_all_devices;
56mod stop_device_cmd;
57mod stop_scanning;
58mod test;
59mod vibrate_cmd;
60mod vorze_a10_cyclone_cmd;
61
62pub use self::log::LogV0;
63pub use battery_level_cmd::BatteryLevelCmdV2;
64pub use battery_level_reading::BatteryLevelReadingV2;
65pub use client_device_message_attributes::{
66  ActuatorType,
67  ClientDeviceMessageAttributesV1,
68  ClientDeviceMessageAttributesV2,
69  ClientDeviceMessageAttributesV3,
70  ClientDeviceMessageAttributesV3Builder,
71  ClientGenericDeviceMessageAttributesV3,
72  NullDeviceMessageAttributesV1,
73  RawDeviceMessageAttributesV2,
74  SensorDeviceMessageAttributesV3,
75  SensorType,
76};
77pub use device_added::{DeviceAddedV0, DeviceAddedV1, DeviceAddedV2, DeviceAddedV3, DeviceAddedV4};
78pub use device_feature::{
79  DeviceFeature,
80  DeviceFeatureActuator,
81  DeviceFeatureRaw,
82  DeviceFeatureSensor,
83  FeatureType,
84};
85pub use device_list::{DeviceListV0, DeviceListV1, DeviceListV2, DeviceListV3, DeviceListV4};
86pub use device_message_info::{
87  DeviceMessageInfoV0,
88  DeviceMessageInfoV1,
89  DeviceMessageInfoV2,
90  DeviceMessageInfoV3,
91  DeviceMessageInfoV4,
92};
93pub use device_removed::DeviceRemovedV0;
94pub use endpoint::Endpoint;
95pub use error::{ErrorCode, ErrorV0};
96pub use fleshlight_launch_fw12_cmd::FleshlightLaunchFW12CmdV0;
97pub use kiiroo_cmd::KiirooCmdV0;
98pub use linear_cmd::{LinearCmdV1, LinearCmdV4, VectorSubcommandV1, VectorSubcommandV4};
99pub use log_level::LogLevel;
100pub use lovense_cmd::LovenseCmdV0;
101pub use ok::OkV0;
102pub use ping::PingV0;
103pub use raw_read_cmd::RawReadCmdV2;
104pub use raw_reading::RawReadingV2;
105pub use raw_subscribe_cmd::RawSubscribeCmdV2;
106pub use raw_unsubscribe_cmd::RawUnsubscribeCmdV2;
107pub use raw_write_cmd::RawWriteCmdV2;
108pub use request_device_list::RequestDeviceListV0;
109pub use request_log::RequestLogV0;
110pub use request_server_info::RequestServerInfoV1;
111pub use rotate_cmd::{RotateCmdV1, RotateCmdV4, RotationSubcommandV1, RotationSubcommandV4};
112pub use rssi_level_cmd::RSSILevelCmdV2;
113pub use rssi_level_reading::RSSILevelReadingV2;
114pub use scalar_cmd::{ScalarCmdV3, ScalarCmdV4, ScalarSubcommandV3, ScalarSubcommandV4};
115pub use scanning_finished::ScanningFinishedV0;
116pub use sensor_read_cmd::{SensorReadCmdV3, SensorReadCmdV4};
117pub use sensor_reading::{SensorReadingV3, SensorReadingV4};
118pub use sensor_subscribe_cmd::{SensorSubscribeCmdV3, SensorSubscribeCmdV4};
119pub use sensor_unsubscribe_cmd::{SensorUnsubscribeCmdV3, SensorUnsubscribeCmdV4};
120pub use server_info::{ServerInfoV0, ServerInfoV2};
121pub use single_motor_vibrate_cmd::SingleMotorVibrateCmdV0;
122pub use start_scanning::StartScanningV0;
123pub use stop_all_devices::StopAllDevicesV0;
124pub use stop_device_cmd::StopDeviceCmdV0;
125pub use stop_scanning::StopScanningV0;
126pub use test::TestV0;
127pub use vibrate_cmd::{VibrateCmdV1, VibrateSubcommandV1};
128pub use vorze_a10_cyclone_cmd::VorzeA10CycloneCmdV0;
129
130use crate::core::errors::ButtplugMessageError;
131use serde::{Deserialize, Serialize};
132#[cfg(feature = "serialize-json")]
133use serde_repr::{Deserialize_repr, Serialize_repr};
134use std::cmp::Ordering;
135use std::convert::TryFrom;
136
137use super::errors::ButtplugError;
138
139/// Enum of possible [Buttplug Message
140/// Spec](https://buttplug-spec.docs.buttplug.io) versions.
141#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Display)]
142#[repr(u32)]
143#[cfg_attr(feature = "serialize-json", derive(Serialize_repr, Deserialize_repr))]
144pub enum ButtplugMessageSpecVersion {
145  Version0 = 0,
146  Version1 = 1,
147  Version2 = 2,
148  Version3 = 3,
149  Version4 = 4,
150}
151
152impl TryFrom<i32> for ButtplugMessageSpecVersion {
153  type Error = ButtplugError;
154
155  // There's probably another crate to make this easier but eh.
156  fn try_from(value: i32) -> Result<Self, Self::Error> {
157    match value {
158      0 => Ok(ButtplugMessageSpecVersion::Version0),
159      1 => Ok(ButtplugMessageSpecVersion::Version1),
160      2 => Ok(ButtplugMessageSpecVersion::Version2),
161      3 => Ok(ButtplugMessageSpecVersion::Version3),
162      4 => Ok(ButtplugMessageSpecVersion::Version4),
163      _ => Err(
164        ButtplugMessageError::InvalidMessageContents(format!(
165          "Message spec version {} is not valid",
166          value
167        ))
168        .into(),
169      ),
170    }
171  }
172}
173
174/// Message Id for events sent from the server, which are not in response to a
175/// client request.
176pub const BUTTPLUG_SERVER_EVENT_ID: u32 = 0;
177
178/// The current latest version of the spec implemented by the library.
179pub const BUTTPLUG_CURRENT_MESSAGE_SPEC_VERSION: ButtplugMessageSpecVersion =
180  ButtplugMessageSpecVersion::Version3;
181
182pub trait ButtplugMessageFinalizer {
183  fn finalize(&mut self) {
184  }
185}
186
187/// Base trait for all Buttplug Protocol Message Structs. Handles management of
188/// message ids, as well as implementing conveinence functions for converting
189/// between message structs and various message enums, serialization, etc...
190pub trait ButtplugMessage:
191  ButtplugMessageValidator + ButtplugMessageFinalizer + Send + Sync + Clone
192{
193  /// Returns the id number of the message
194  fn id(&self) -> u32;
195  /// Sets the id number of the message.
196  fn set_id(&mut self, id: u32);
197  /// True if the message is an event (message id of 0) from the server.
198  fn is_server_event(&self) -> bool {
199    self.id() == BUTTPLUG_SERVER_EVENT_ID
200  }
201}
202
203/// Validation function for message contents. Can be run before message is
204/// transmitted, as message may be formed and mutated at multiple points in the
205/// library, or may need to be checked after deserialization. Message enums will
206/// run this on whatever their variant is.
207pub trait ButtplugMessageValidator {
208  /// Returns () if the message is valid, otherwise returns a message error.
209  fn is_valid(&self) -> Result<(), ButtplugMessageError> {
210    // By default, return Ok, as many messages won't have any checks.
211    Ok(())
212  }
213
214  fn is_system_id(&self, id: u32) -> Result<(), ButtplugMessageError> {
215    if id == 0 {
216      Ok(())
217    } else {
218      Err(ButtplugMessageError::InvalidMessageContents(
219        "Message should have id of 0, as it is a system message.".to_string(),
220      ))
221    }
222  }
223
224  fn is_not_system_id(&self, id: u32) -> Result<(), ButtplugMessageError> {
225    if id == 0 {
226      Err(ButtplugMessageError::InvalidMessageContents(
227        "Message should not have 0 for an Id. Id of 0 is reserved for system messages.".to_string(),
228      ))
229    } else {
230      Ok(())
231    }
232  }
233
234  fn is_in_command_range(&self, value: f64, error_msg: String) -> Result<(), ButtplugMessageError> {
235    if !(0.0..=1.0).contains(&value) {
236      Err(ButtplugMessageError::InvalidMessageContents(error_msg))
237    } else {
238      Ok(())
239    }
240  }
241}
242
243/// Adds device index handling to the [ButtplugMessage] trait.
244pub trait ButtplugDeviceMessage: ButtplugMessage {
245  fn device_index(&self) -> u32;
246  fn set_device_index(&mut self, id: u32);
247}
248
249/// Used in [MessageAttributes][crate::core::messages::DeviceMessageAttributes] for denoting message
250/// capabilties.
251#[derive(Copy, Debug, Clone, PartialEq, Eq, Hash, Display, Serialize, Deserialize)]
252pub enum ButtplugDeviceMessageType {
253  VibrateCmd,
254  LinearCmd,
255  RotateCmd,
256  StopDeviceCmd,
257  RawWriteCmd,
258  RawReadCmd,
259  RawSubscribeCmd,
260  RawUnsubscribeCmd,
261  BatteryLevelCmd,
262  RSSILevelCmd,
263  ScalarCmd,
264  SensorReadCmd,
265  SensorSubscribeCmd,
266  SensorUnsubscribeCmd,
267  // Deprecated generic commands
268  SingleMotorVibrateCmd,
269  // Deprecated device specific commands
270  FleshlightLaunchFW12Cmd,
271  LovenseCmd,
272  KiirooCmd,
273  VorzeA10CycloneCmd,
274}
275
276// Ordering for ButtplugDeviceMessageType should be lexicographic, for
277// serialization reasons.
278impl PartialOrd for ButtplugDeviceMessageType {
279  fn partial_cmp(&self, other: &ButtplugDeviceMessageType) -> Option<Ordering> {
280    Some(self.cmp(other))
281  }
282}
283
284impl Ord for ButtplugDeviceMessageType {
285  fn cmp(&self, other: &ButtplugDeviceMessageType) -> Ordering {
286    self.to_string().cmp(&other.to_string())
287  }
288}
289
290#[derive(Copy, Debug, Clone, Hash, Display, PartialEq, Eq, Serialize, Deserialize)]
291pub enum ButtplugActuatorFeatureMessageType {
292  ScalarCmd,
293  RotateCmd,
294  LinearCmd,
295}
296
297impl From<ButtplugActuatorFeatureMessageType> for ButtplugDeviceMessageType {
298  fn from(value: ButtplugActuatorFeatureMessageType) -> Self {
299    match value {
300      ButtplugActuatorFeatureMessageType::LinearCmd => ButtplugDeviceMessageType::LinearCmd,
301      ButtplugActuatorFeatureMessageType::RotateCmd => ButtplugDeviceMessageType::RotateCmd,
302      ButtplugActuatorFeatureMessageType::ScalarCmd => ButtplugDeviceMessageType::ScalarCmd,
303    }
304  }
305}
306
307impl TryFrom<ButtplugDeviceMessageType> for ButtplugActuatorFeatureMessageType {
308  type Error = ();
309
310  fn try_from(value: ButtplugDeviceMessageType) -> Result<Self, Self::Error> {
311    match value {
312      ButtplugDeviceMessageType::LinearCmd => Ok(ButtplugActuatorFeatureMessageType::LinearCmd),
313      ButtplugDeviceMessageType::RotateCmd => Ok(ButtplugActuatorFeatureMessageType::RotateCmd),
314      ButtplugDeviceMessageType::ScalarCmd => Ok(ButtplugActuatorFeatureMessageType::ScalarCmd),
315      _ => Err(()),
316    }
317  }
318}
319
320#[derive(Copy, Debug, Clone, Hash, Display, PartialEq, Eq, Serialize, Deserialize)]
321pub enum ButtplugSensorFeatureMessageType {
322  SensorReadCmd,
323  SensorSubscribeCmd,
324}
325
326impl From<ButtplugSensorFeatureMessageType> for ButtplugDeviceMessageType {
327  fn from(value: ButtplugSensorFeatureMessageType) -> Self {
328    match value {
329      ButtplugSensorFeatureMessageType::SensorReadCmd => ButtplugDeviceMessageType::SensorReadCmd,
330      ButtplugSensorFeatureMessageType::SensorSubscribeCmd => {
331        ButtplugDeviceMessageType::SensorSubscribeCmd
332      }
333    }
334  }
335}
336
337impl TryFrom<ButtplugDeviceMessageType> for ButtplugSensorFeatureMessageType {
338  type Error = ();
339
340  fn try_from(value: ButtplugDeviceMessageType) -> Result<Self, Self::Error> {
341    match value {
342      ButtplugDeviceMessageType::SensorReadCmd => {
343        Ok(ButtplugSensorFeatureMessageType::SensorReadCmd)
344      }
345      ButtplugDeviceMessageType::SensorSubscribeCmd => {
346        Ok(ButtplugSensorFeatureMessageType::SensorSubscribeCmd)
347      }
348      _ => Err(()),
349    }
350  }
351}
352
353#[derive(Copy, Debug, Clone, Hash, Display, PartialEq, Eq, Serialize, Deserialize)]
354pub enum ButtplugRawFeatureMessageType {
355  RawReadCmd,
356  RawWriteCmd,
357  RawSubscribeCmd,
358}
359
360impl From<ButtplugRawFeatureMessageType> for ButtplugDeviceMessageType {
361  fn from(value: ButtplugRawFeatureMessageType) -> Self {
362    match value {
363      ButtplugRawFeatureMessageType::RawReadCmd => ButtplugDeviceMessageType::RawReadCmd,
364      ButtplugRawFeatureMessageType::RawWriteCmd => ButtplugDeviceMessageType::RawWriteCmd,
365      ButtplugRawFeatureMessageType::RawSubscribeCmd => ButtplugDeviceMessageType::RawSubscribeCmd,
366    }
367  }
368}
369
370impl TryFrom<ButtplugDeviceMessageType> for ButtplugRawFeatureMessageType {
371  type Error = ();
372
373  fn try_from(value: ButtplugDeviceMessageType) -> Result<Self, Self::Error> {
374    match value {
375      ButtplugDeviceMessageType::RawReadCmd => Ok(ButtplugRawFeatureMessageType::RawReadCmd),
376      ButtplugDeviceMessageType::RawWriteCmd => Ok(ButtplugRawFeatureMessageType::RawWriteCmd),
377      ButtplugDeviceMessageType::RawSubscribeCmd => {
378        Ok(ButtplugRawFeatureMessageType::RawSubscribeCmd)
379      }
380      _ => Err(()),
381    }
382  }
383}
384
385#[derive(
386  Debug, Clone, PartialEq, ButtplugMessage, ButtplugMessageFinalizer, ButtplugMessageValidator,
387)]
388pub enum ButtplugClientMessageVariant {
389  V0(ButtplugClientMessageV0),
390  V1(ButtplugClientMessageV1),
391  V2(ButtplugClientMessageV2),
392  V3(ButtplugClientMessageV3),
393  V4(ButtplugClientMessageV4),
394}
395
396impl ButtplugClientMessageVariant {
397  pub fn version(&self) -> ButtplugMessageSpecVersion {
398    match self {
399      Self::V0(_) => ButtplugMessageSpecVersion::Version0,
400      Self::V1(_) => ButtplugMessageSpecVersion::Version1,
401      Self::V2(_) => ButtplugMessageSpecVersion::Version2,
402      Self::V3(_) => ButtplugMessageSpecVersion::Version3,
403      Self::V4(_) => ButtplugMessageSpecVersion::Version4,
404    }
405  }
406}
407
408impl From<ButtplugClientMessageV0> for ButtplugClientMessageVariant {
409  fn from(value: ButtplugClientMessageV0) -> Self {
410    ButtplugClientMessageVariant::V0(value)
411  }
412}
413
414impl From<ButtplugClientMessageV1> for ButtplugClientMessageVariant {
415  fn from(value: ButtplugClientMessageV1) -> Self {
416    ButtplugClientMessageVariant::V1(value)
417  }
418}
419
420impl From<ButtplugClientMessageV2> for ButtplugClientMessageVariant {
421  fn from(value: ButtplugClientMessageV2) -> Self {
422    ButtplugClientMessageVariant::V2(value)
423  }
424}
425
426impl From<ButtplugClientMessageV3> for ButtplugClientMessageVariant {
427  fn from(value: ButtplugClientMessageV3) -> Self {
428    ButtplugClientMessageVariant::V3(value)
429  }
430}
431
432impl From<ButtplugClientMessageV4> for ButtplugClientMessageVariant {
433  fn from(value: ButtplugClientMessageV4) -> Self {
434    ButtplugClientMessageVariant::V4(value)
435  }
436}
437
438#[derive(
439  Debug, Clone, PartialEq, ButtplugMessage, ButtplugMessageFinalizer, ButtplugMessageValidator,
440)]
441pub enum ButtplugServerMessageVariant {
442  V0(ButtplugServerMessageV0),
443  V1(ButtplugServerMessageV1),
444  V2(ButtplugServerMessageV2),
445  V3(ButtplugServerMessageV3),
446  V4(ButtplugServerMessageV4),
447}
448
449impl ButtplugServerMessageVariant {
450  pub fn version(&self) -> ButtplugMessageSpecVersion {
451    match self {
452      Self::V0(_) => ButtplugMessageSpecVersion::Version0,
453      Self::V1(_) => ButtplugMessageSpecVersion::Version1,
454      Self::V2(_) => ButtplugMessageSpecVersion::Version2,
455      Self::V3(_) => ButtplugMessageSpecVersion::Version3,
456      Self::V4(_) => ButtplugMessageSpecVersion::Version4,
457    }
458  }
459}
460
461impl From<ButtplugServerMessageV0> for ButtplugServerMessageVariant {
462  fn from(value: ButtplugServerMessageV0) -> Self {
463    ButtplugServerMessageVariant::V0(value)
464  }
465}
466
467impl From<ButtplugServerMessageV1> for ButtplugServerMessageVariant {
468  fn from(value: ButtplugServerMessageV1) -> Self {
469    ButtplugServerMessageVariant::V1(value)
470  }
471}
472
473impl From<ButtplugServerMessageV2> for ButtplugServerMessageVariant {
474  fn from(value: ButtplugServerMessageV2) -> Self {
475    ButtplugServerMessageVariant::V2(value)
476  }
477}
478
479impl From<ButtplugServerMessageV3> for ButtplugServerMessageVariant {
480  fn from(value: ButtplugServerMessageV3) -> Self {
481    ButtplugServerMessageVariant::V3(value)
482  }
483}
484
485impl From<ButtplugServerMessageV4> for ButtplugServerMessageVariant {
486  fn from(value: ButtplugServerMessageV4) -> Self {
487    ButtplugServerMessageVariant::V4(value)
488  }
489}
490
491/// Represents all possible messages a [ButtplugServer][crate::server::ButtplugServer] can send to a
492/// [ButtplugClient][crate::client::ButtplugClient] that denote an EVENT from a device. These are
493/// only used in notifications, so read requests will not need to be added here, only messages that
494/// will require Id of 0.
495#[derive(
496  Debug,
497  Clone,
498  PartialEq,
499  Eq,
500  ButtplugMessage,
501  ButtplugMessageValidator,
502  ButtplugMessageFinalizer,
503  FromSpecificButtplugMessage,
504)]
505pub enum ButtplugServerDeviceMessage {
506  // Generic commands
507  RawReading(RawReadingV2),
508  // Generic Sensor Reading Messages
509  SensorReading(SensorReadingV4),
510}
511
512impl From<ButtplugServerDeviceMessage> for ButtplugServerMessageV4 {
513  fn from(other: ButtplugServerDeviceMessage) -> Self {
514    match other {
515      ButtplugServerDeviceMessage::RawReading(msg) => ButtplugServerMessageV4::RawReading(msg),
516      ButtplugServerDeviceMessage::SensorReading(msg) => {
517        ButtplugServerMessageV4::SensorReading(msg)
518      }
519    }
520  }
521}
522
523/// Type alias for the latest version of client-to-server messages.
524pub type ButtplugClientMessageCurrent = ButtplugClientMessageV3;
525/// Type alias for the latest version of server-to-client messages.
526pub type ButtplugServerMessageCurrent = ButtplugServerMessageV3;
527
528/// Represents all client-to-server messages in v3 of the Buttplug Spec
529#[derive(
530  Debug,
531  Clone,
532  PartialEq,
533  ButtplugMessage,
534  ButtplugMessageValidator,
535  ButtplugMessageFinalizer,
536  FromSpecificButtplugMessage,
537)]
538#[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))]
539pub enum ButtplugClientMessageV4 {
540  // Handshake messages
541  RequestServerInfo(RequestServerInfoV1),
542  Ping(PingV0),
543  // Device enumeration messages
544  StartScanning(StartScanningV0),
545  StopScanning(StopScanningV0),
546  RequestDeviceList(RequestDeviceListV0),
547  // Generic commands
548  StopDeviceCmd(StopDeviceCmdV0),
549  StopAllDevices(StopAllDevicesV0),
550  ScalarCmd(ScalarCmdV4),
551  LinearCmd(LinearCmdV4),
552  RotateCmd(RotateCmdV4),
553  RawWriteCmd(RawWriteCmdV2),
554  RawReadCmd(RawReadCmdV2),
555  RawSubscribeCmd(RawSubscribeCmdV2),
556  RawUnsubscribeCmd(RawUnsubscribeCmdV2),
557  // Sensor commands
558  SensorReadCmd(SensorReadCmdV4),
559  SensorSubscribeCmd(SensorSubscribeCmdV4),
560  SensorUnsubscribeCmd(SensorUnsubscribeCmdV4),
561}
562
563/// Represents all server-to-client messages in v3 of the Buttplug Spec
564#[derive(
565  Debug, Clone, PartialEq, ButtplugMessage, ButtplugMessageValidator, FromSpecificButtplugMessage,
566)]
567#[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))]
568pub enum ButtplugServerMessageV4 {
569  // Status messages
570  Ok(OkV0),
571  Error(ErrorV0),
572  // Handshake messages
573  ServerInfo(ServerInfoV2),
574  // Device enumeration messages
575  DeviceList(DeviceListV4),
576  DeviceAdded(DeviceAddedV4),
577  DeviceRemoved(DeviceRemovedV0),
578  ScanningFinished(ScanningFinishedV0),
579  // Generic commands
580  RawReading(RawReadingV2),
581  // Sensor commands
582  SensorReading(SensorReadingV4),
583}
584
585impl ButtplugMessageFinalizer for ButtplugServerMessageV4 {
586  fn finalize(&mut self) {
587    match self {
588      ButtplugServerMessageV4::DeviceAdded(da) => da.finalize(),
589      ButtplugServerMessageV4::DeviceList(dl) => dl.finalize(),
590      _ => return,
591    }
592  }
593}
594
595/// Represents all client-to-server messages in v3 of the Buttplug Spec
596#[derive(
597  Debug,
598  Clone,
599  PartialEq,
600  ButtplugMessage,
601  ButtplugMessageValidator,
602  ButtplugMessageFinalizer,
603  FromSpecificButtplugMessage,
604)]
605#[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))]
606pub enum ButtplugClientMessageV3 {
607  // Handshake messages
608  RequestServerInfo(RequestServerInfoV1),
609  Ping(PingV0),
610  // Device enumeration messages
611  StartScanning(StartScanningV0),
612  StopScanning(StopScanningV0),
613  RequestDeviceList(RequestDeviceListV0),
614  // Generic commands
615  StopAllDevices(StopAllDevicesV0),
616  VibrateCmd(VibrateCmdV1),
617  LinearCmd(LinearCmdV1),
618  RotateCmd(RotateCmdV1),
619  RawWriteCmd(RawWriteCmdV2),
620  RawReadCmd(RawReadCmdV2),
621  StopDeviceCmd(StopDeviceCmdV0),
622  RawSubscribeCmd(RawSubscribeCmdV2),
623  RawUnsubscribeCmd(RawUnsubscribeCmdV2),
624  ScalarCmd(ScalarCmdV3),
625  // Sensor commands
626  SensorReadCmd(SensorReadCmdV3),
627  SensorSubscribeCmd(SensorSubscribeCmdV3),
628  SensorUnsubscribeCmd(SensorUnsubscribeCmdV3),
629}
630
631/// Represents all server-to-client messages in v3 of the Buttplug Spec
632#[derive(
633  Debug, Clone, PartialEq, ButtplugMessage, ButtplugMessageValidator, FromSpecificButtplugMessage,
634)]
635#[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))]
636pub enum ButtplugServerMessageV3 {
637  // Status messages
638  Ok(OkV0),
639  Error(ErrorV0),
640  // Handshake messages
641  ServerInfo(ServerInfoV2),
642  // Device enumeration messages
643  DeviceList(DeviceListV3),
644  DeviceAdded(DeviceAddedV3),
645  DeviceRemoved(DeviceRemovedV0),
646  ScanningFinished(ScanningFinishedV0),
647  // Generic commands
648  RawReading(RawReadingV2),
649  // Sensor commands
650  SensorReading(SensorReadingV3),
651}
652
653impl ButtplugMessageFinalizer for ButtplugServerMessageV3 {
654  fn finalize(&mut self) {
655    match self {
656      ButtplugServerMessageV3::DeviceAdded(da) => da.finalize(),
657      ButtplugServerMessageV3::DeviceList(dl) => dl.finalize(),
658      _ => return,
659    }
660  }
661}
662
663/// Represents all client-to-server messages in v2 of the Buttplug Spec
664#[derive(
665  Debug,
666  Clone,
667  PartialEq,
668  ButtplugMessage,
669  ButtplugMessageValidator,
670  ButtplugMessageFinalizer,
671  FromSpecificButtplugMessage,
672)]
673#[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))]
674pub enum ButtplugClientMessageV2 {
675  // Handshake messages
676  RequestServerInfo(RequestServerInfoV1),
677  Ping(PingV0),
678  // Device enumeration messages
679  StartScanning(StartScanningV0),
680  StopScanning(StopScanningV0),
681  RequestDeviceList(RequestDeviceListV0),
682  // Generic commands
683  StopAllDevices(StopAllDevicesV0),
684  VibrateCmd(VibrateCmdV1),
685  LinearCmd(LinearCmdV1),
686  RotateCmd(RotateCmdV1),
687  RawWriteCmd(RawWriteCmdV2),
688  RawReadCmd(RawReadCmdV2),
689  StopDeviceCmd(StopDeviceCmdV0),
690  RawSubscribeCmd(RawSubscribeCmdV2),
691  RawUnsubscribeCmd(RawUnsubscribeCmdV2),
692  // Sensor commands
693  BatteryLevelCmd(BatteryLevelCmdV2),
694  RSSILevelCmd(RSSILevelCmdV2),
695}
696
697/// Represents all server-to-client messages in v2 of the Buttplug Spec
698#[derive(
699  Debug,
700  Clone,
701  PartialEq,
702  ButtplugMessage,
703  ButtplugMessageValidator,
704  ButtplugMessageFinalizer,
705  FromSpecificButtplugMessage,
706)]
707#[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))]
708pub enum ButtplugServerMessageV2 {
709  // Status messages
710  Ok(OkV0),
711  Error(ErrorV0),
712  // Handshake messages
713  ServerInfo(ServerInfoV2),
714  // Device enumeration messages
715  DeviceList(DeviceListV2),
716  DeviceAdded(DeviceAddedV2),
717  DeviceRemoved(DeviceRemovedV0),
718  ScanningFinished(ScanningFinishedV0),
719  // Generic commands
720  RawReading(RawReadingV2),
721  // Sensor commands
722  BatteryLevelReading(BatteryLevelReadingV2),
723  RSSILevelReading(RSSILevelReadingV2),
724}
725
726/// Represents all client-to-server messages in v1 of the Buttplug Spec
727#[derive(
728  Debug,
729  Clone,
730  PartialEq,
731  ButtplugMessage,
732  ButtplugMessageValidator,
733  ButtplugMessageFinalizer,
734  FromSpecificButtplugMessage,
735)]
736#[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))]
737pub enum ButtplugClientMessageV1 {
738  // Handshake and server messages
739  RequestServerInfo(RequestServerInfoV1),
740  Ping(PingV0),
741  RequestLog(RequestLogV0),
742  // Device enumeration messages
743  StartScanning(StartScanningV0),
744  StopScanning(StopScanningV0),
745  RequestDeviceList(RequestDeviceListV0),
746  // Generic commands
747  StopAllDevices(StopAllDevicesV0),
748  VibrateCmd(VibrateCmdV1),
749  LinearCmd(LinearCmdV1),
750  RotateCmd(RotateCmdV1),
751  StopDeviceCmd(StopDeviceCmdV0),
752  // Deprecated generic commands (not removed until v2)
753  SingleMotorVibrateCmd(SingleMotorVibrateCmdV0),
754  // Deprecated device specific commands (not removed until v2)
755  FleshlightLaunchFW12Cmd(FleshlightLaunchFW12CmdV0),
756  LovenseCmd(LovenseCmdV0),
757  KiirooCmd(KiirooCmdV0),
758  VorzeA10CycloneCmd(VorzeA10CycloneCmdV0),
759}
760
761/// Represents all server-to-client messages in v2 of the Buttplug Spec
762#[derive(
763  Debug,
764  Clone,
765  PartialEq,
766  ButtplugMessage,
767  ButtplugMessageValidator,
768  ButtplugMessageFinalizer,
769  FromSpecificButtplugMessage,
770)]
771#[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))]
772pub enum ButtplugServerMessageV1 {
773  // Status messages
774  Ok(OkV0),
775  Error(ErrorV0),
776  Log(LogV0),
777  // Handshake messages
778  ServerInfo(ServerInfoV0),
779  // Device enumeration messages
780  DeviceList(DeviceListV1),
781  DeviceAdded(DeviceAddedV1),
782  DeviceRemoved(DeviceRemovedV0),
783  ScanningFinished(ScanningFinishedV0),
784}
785
786/// Represents all client-to-server messages in v0 of the Buttplug Spec
787#[derive(
788  Debug,
789  Clone,
790  PartialEq,
791  ButtplugMessage,
792  ButtplugMessageValidator,
793  ButtplugMessageFinalizer,
794  FromSpecificButtplugMessage,
795)]
796#[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))]
797pub enum ButtplugClientMessageV0 {
798  RequestLog(RequestLogV0),
799  Ping(PingV0),
800  // Handshake messages
801  //
802  // We use RequestServerInfoV1 here, as the only difference between v0 and v1 was passing the spec
803  // version. If the spec version doesn't exist, we automatically set the spec version to 0.
804  RequestServerInfo(RequestServerInfoV1),
805  // Device enumeration messages
806  StartScanning(StartScanningV0),
807  StopScanning(StopScanningV0),
808  RequestDeviceList(RequestDeviceListV0),
809  // Generic commands
810  StopAllDevices(StopAllDevicesV0),
811  StopDeviceCmd(StopDeviceCmdV0),
812  // Deprecated generic commands
813  SingleMotorVibrateCmd(SingleMotorVibrateCmdV0),
814  // Deprecated device specific commands
815  FleshlightLaunchFW12Cmd(FleshlightLaunchFW12CmdV0),
816  LovenseCmd(LovenseCmdV0),
817  KiirooCmd(KiirooCmdV0),
818  VorzeA10CycloneCmd(VorzeA10CycloneCmdV0),
819}
820
821/// Represents all server-to-client messages in v0 of the Buttplug Spec
822#[derive(
823  Debug, Clone, PartialEq, ButtplugMessage, ButtplugMessageValidator, ButtplugMessageFinalizer,
824)]
825#[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))]
826pub enum ButtplugServerMessageV0 {
827  // Status messages
828  Ok(OkV0),
829  Error(ErrorV0),
830  Log(LogV0),
831  // Handshake messages
832  ServerInfo(ServerInfoV0),
833  // Device enumeration messages
834  DeviceList(DeviceListV0),
835  DeviceAdded(DeviceAddedV0),
836  DeviceRemoved(DeviceRemovedV0),
837  ScanningFinished(ScanningFinishedV0),
838}
839
840/// Represents messages that should go to the
841/// [DeviceManager][crate::server::device_manager::DeviceManager] of a
842/// [ButtplugServer](crate::server::ButtplugServer)
843#[derive(
844  Debug,
845  Clone,
846  PartialEq,
847  Eq,
848  ButtplugMessage,
849  ButtplugMessageValidator,
850  ButtplugMessageFinalizer,
851  FromSpecificButtplugMessage,
852)]
853pub enum ButtplugDeviceManagerMessageUnion {
854  RequestDeviceList(RequestDeviceListV0),
855  StopAllDevices(StopAllDevicesV0),
856  StartScanning(StartScanningV0),
857  StopScanning(StopScanningV0),
858}
859
860impl TryFrom<ButtplugClientMessageV4> for ButtplugDeviceManagerMessageUnion {
861  type Error = ();
862
863  fn try_from(value: ButtplugClientMessageV4) -> Result<Self, Self::Error> {
864    match value {
865      ButtplugClientMessageV4::RequestDeviceList(m) => {
866        Ok(ButtplugDeviceManagerMessageUnion::RequestDeviceList(m))
867      }
868      ButtplugClientMessageV4::StopAllDevices(m) => {
869        Ok(ButtplugDeviceManagerMessageUnion::StopAllDevices(m))
870      }
871      ButtplugClientMessageV4::StartScanning(m) => {
872        Ok(ButtplugDeviceManagerMessageUnion::StartScanning(m))
873      }
874      ButtplugClientMessageV4::StopScanning(m) => {
875        Ok(ButtplugDeviceManagerMessageUnion::StopScanning(m))
876      }
877      _ => Err(()),
878    }
879  }
880}
881
882/// Represents all possible device command message types.
883#[derive(
884  Debug,
885  Clone,
886  PartialEq,
887  ButtplugDeviceMessage,
888  ButtplugMessageValidator,
889  ButtplugMessageFinalizer,
890  FromSpecificButtplugMessage,
891)]
892#[cfg_attr(feature = "serialize-json", derive(Serialize, Deserialize))]
893pub enum ButtplugDeviceCommandMessageUnion {
894  StopDeviceCmd(StopDeviceCmdV0),
895  LinearCmd(LinearCmdV4),
896  RotateCmd(RotateCmdV4),
897  ScalarCmd(ScalarCmdV4),
898  SensorReadCmd(SensorReadCmdV4),
899  SensorSubscribeCmd(SensorSubscribeCmdV4),
900  SensorUnsubscribeCmd(SensorUnsubscribeCmdV4),
901  RawWriteCmd(RawWriteCmdV2),
902  RawReadCmd(RawReadCmdV2),
903  RawSubscribeCmd(RawSubscribeCmdV2),
904  RawUnsubscribeCmd(RawUnsubscribeCmdV2),
905}
906
907impl TryFrom<ButtplugClientMessageV4> for ButtplugDeviceCommandMessageUnion {
908  type Error = ();
909
910  fn try_from(value: ButtplugClientMessageV4) -> Result<Self, Self::Error> {
911    match value {
912      ButtplugClientMessageV4::StopDeviceCmd(m) => {
913        Ok(ButtplugDeviceCommandMessageUnion::StopDeviceCmd(m))
914      }
915      ButtplugClientMessageV4::LinearCmd(m) => Ok(ButtplugDeviceCommandMessageUnion::LinearCmd(m)),
916      ButtplugClientMessageV4::RotateCmd(m) => Ok(ButtplugDeviceCommandMessageUnion::RotateCmd(m)),
917      ButtplugClientMessageV4::ScalarCmd(m) => Ok(ButtplugDeviceCommandMessageUnion::ScalarCmd(m)),
918      ButtplugClientMessageV4::SensorReadCmd(m) => {
919        Ok(ButtplugDeviceCommandMessageUnion::SensorReadCmd(m))
920      }
921      ButtplugClientMessageV4::SensorSubscribeCmd(m) => {
922        Ok(ButtplugDeviceCommandMessageUnion::SensorSubscribeCmd(m))
923      }
924      ButtplugClientMessageV4::SensorUnsubscribeCmd(m) => {
925        Ok(ButtplugDeviceCommandMessageUnion::SensorUnsubscribeCmd(m))
926      }
927      ButtplugClientMessageV4::RawWriteCmd(m) => {
928        Ok(ButtplugDeviceCommandMessageUnion::RawWriteCmd(m))
929      }
930      ButtplugClientMessageV4::RawReadCmd(m) => {
931        Ok(ButtplugDeviceCommandMessageUnion::RawReadCmd(m))
932      }
933      ButtplugClientMessageV4::RawSubscribeCmd(m) => {
934        Ok(ButtplugDeviceCommandMessageUnion::RawSubscribeCmd(m))
935      }
936      ButtplugClientMessageV4::RawUnsubscribeCmd(m) => {
937        Ok(ButtplugDeviceCommandMessageUnion::RawUnsubscribeCmd(m))
938      }
939      _ => Err(()),
940    }
941  }
942}