Buttplug sex toy control library
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
8use crate::message::{
9 v1::{LinearCmdV1, RequestServerInfoV1, RotateCmdV1, VibrateCmdV1},
10 v2::{ButtplugClientMessageV2, ButtplugServerMessageV2, ServerInfoV2},
11};
12use buttplug_core::{
13 errors::{ButtplugError, ButtplugMessageError},
14 message::{
15 ButtplugMessage,
16 ButtplugMessageFinalizer,
17 ButtplugMessageValidator,
18 ButtplugServerMessageV4,
19 DeviceRemovedV0,
20 ErrorV0,
21 OkV0,
22 PingV0,
23 RequestDeviceListV0,
24 ScanningFinishedV0,
25 StartScanningV0,
26 StopAllDevicesV0,
27 StopDeviceCmdV0,
28 StopScanningV0,
29 },
30};
31use serde::{Deserialize, Serialize};
32
33use super::{
34 DeviceAddedV3,
35 DeviceListV3,
36 ScalarCmdV3,
37 SensorReadCmdV3,
38 SensorReadingV3,
39 SensorSubscribeCmdV3,
40 SensorUnsubscribeCmdV3,
41};
42
43/// Represents all client-to-server messages in v3 of the Buttplug Spec
44#[derive(
45 Debug,
46 Clone,
47 PartialEq,
48 ButtplugMessage,
49 ButtplugMessageValidator,
50 ButtplugMessageFinalizer,
51 FromSpecificButtplugMessage,
52 Serialize,
53 Deserialize,
54)]
55pub enum ButtplugClientMessageV3 {
56 // Handshake messages
57 RequestServerInfo(RequestServerInfoV1),
58 Ping(PingV0),
59 // Device enumeration messages
60 StartScanning(StartScanningV0),
61 StopScanning(StopScanningV0),
62 RequestDeviceList(RequestDeviceListV0),
63 // Generic commands
64 StopAllDevices(StopAllDevicesV0),
65 VibrateCmd(VibrateCmdV1),
66 LinearCmd(LinearCmdV1),
67 RotateCmd(RotateCmdV1),
68 StopDeviceCmd(StopDeviceCmdV0),
69 ScalarCmd(ScalarCmdV3),
70 // Sensor commands
71 SensorReadCmd(SensorReadCmdV3),
72 SensorSubscribeCmd(SensorSubscribeCmdV3),
73 SensorUnsubscribeCmd(SensorUnsubscribeCmdV3),
74}
75
76// For v2 to v3, all deprecations should be treated as conversions, but will require current
77// connected device state, meaning they'll need to be implemented where they can also access the
78// device manager.
79impl TryFrom<ButtplugClientMessageV2> for ButtplugClientMessageV3 {
80 type Error = ButtplugMessageError;
81
82 fn try_from(value: ButtplugClientMessageV2) -> Result<Self, Self::Error> {
83 match value {
84 ButtplugClientMessageV2::Ping(m) => Ok(ButtplugClientMessageV3::Ping(m.clone())),
85 ButtplugClientMessageV2::RequestServerInfo(m) => {
86 Ok(ButtplugClientMessageV3::RequestServerInfo(m.clone()))
87 }
88 ButtplugClientMessageV2::StartScanning(m) => {
89 Ok(ButtplugClientMessageV3::StartScanning(m.clone()))
90 }
91 ButtplugClientMessageV2::StopScanning(m) => {
92 Ok(ButtplugClientMessageV3::StopScanning(m.clone()))
93 }
94 ButtplugClientMessageV2::RequestDeviceList(m) => {
95 Ok(ButtplugClientMessageV3::RequestDeviceList(m.clone()))
96 }
97 ButtplugClientMessageV2::StopAllDevices(m) => {
98 Ok(ButtplugClientMessageV3::StopAllDevices(m.clone()))
99 }
100 ButtplugClientMessageV2::StopDeviceCmd(m) => {
101 Ok(ButtplugClientMessageV3::StopDeviceCmd(m.clone()))
102 }
103 // Vibrate was supposed to be phased out in v3 but was left in the allowable message set.
104 // Oops.
105 ButtplugClientMessageV2::VibrateCmd(m) => Ok(ButtplugClientMessageV3::VibrateCmd(m)),
106 ButtplugClientMessageV2::LinearCmd(m) => Ok(ButtplugClientMessageV3::LinearCmd(m)),
107 ButtplugClientMessageV2::RotateCmd(m) => Ok(ButtplugClientMessageV3::RotateCmd(m)),
108 _ => Err(ButtplugMessageError::MessageConversionError(format!(
109 "Cannot convert message {value:?} to V3 message spec while lacking state."
110 ))),
111 }
112 }
113}
114
115/// Represents all server-to-client messages in v3 of the Buttplug Spec
116#[derive(
117 Debug,
118 Clone,
119 ButtplugMessage,
120 ButtplugMessageValidator,
121 FromSpecificButtplugMessage,
122 Serialize,
123 Deserialize,
124)]
125pub enum ButtplugServerMessageV3 {
126 // Status messages
127 Ok(OkV0),
128 Error(ErrorV0),
129 // Handshake messages
130 ServerInfo(ServerInfoV2),
131 // Device enumeration messages
132 DeviceList(DeviceListV3),
133 DeviceAdded(DeviceAddedV3),
134 DeviceRemoved(DeviceRemovedV0),
135 ScanningFinished(ScanningFinishedV0),
136 // Sensor commands
137 SensorReading(SensorReadingV3),
138}
139
140impl ButtplugMessageFinalizer for ButtplugServerMessageV3 {
141 fn finalize(&mut self) {
142 match self {
143 ButtplugServerMessageV3::DeviceAdded(da) => da.finalize(),
144 ButtplugServerMessageV3::DeviceList(dl) => dl.finalize(),
145 _ => (),
146 }
147 }
148}
149
150impl From<ButtplugServerMessageV3> for ButtplugServerMessageV2 {
151 fn from(value: ButtplugServerMessageV3) -> Self {
152 match value {
153 ButtplugServerMessageV3::Ok(m) => ButtplugServerMessageV2::Ok(m),
154 ButtplugServerMessageV3::Error(m) => ButtplugServerMessageV2::Error(m),
155 ButtplugServerMessageV3::ServerInfo(m) => ButtplugServerMessageV2::ServerInfo(m),
156 ButtplugServerMessageV3::DeviceRemoved(m) => ButtplugServerMessageV2::DeviceRemoved(m),
157 ButtplugServerMessageV3::ScanningFinished(m) => ButtplugServerMessageV2::ScanningFinished(m),
158 ButtplugServerMessageV3::DeviceAdded(m) => ButtplugServerMessageV2::DeviceAdded(m.into()),
159 ButtplugServerMessageV3::DeviceList(m) => ButtplugServerMessageV2::DeviceList(m.into()),
160 ButtplugServerMessageV3::SensorReading(_) => ButtplugServerMessageV2::Error(ErrorV0::from(
161 ButtplugError::from(ButtplugMessageError::MessageConversionError(
162 "SensorReading cannot be converted to Buttplug Message Spec V2".to_owned(),
163 )),
164 )),
165 }
166 }
167}
168
169impl TryFrom<ButtplugServerMessageV4> for ButtplugServerMessageV3 {
170 type Error = ButtplugMessageError;
171
172 fn try_from(
173 value: ButtplugServerMessageV4,
174 ) -> Result<Self, <ButtplugServerMessageV3 as TryFrom<ButtplugServerMessageV4>>::Error> {
175 match value {
176 // Direct conversions
177 ButtplugServerMessageV4::Ok(m) => Ok(ButtplugServerMessageV3::Ok(m)),
178 ButtplugServerMessageV4::Error(m) => Ok(ButtplugServerMessageV3::Error(m)),
179 ButtplugServerMessageV4::ServerInfo(m) => Ok(ButtplugServerMessageV3::ServerInfo(m.into())),
180 ButtplugServerMessageV4::ScanningFinished(m) => {
181 Ok(ButtplugServerMessageV3::ScanningFinished(m))
182 }
183 ButtplugServerMessageV4::DeviceList(m) => Ok(ButtplugServerMessageV3::DeviceList(m.into())),
184 // All other messages (SensorReading) requires device manager context.
185 _ => Err(ButtplugMessageError::MessageConversionError(format!(
186 "Cannot convert message {value:?} to current message spec while lacking state."
187 ))),
188 }
189 }
190}
191
192#[derive(Copy, Debug, Clone, PartialEq, Eq, Hash, Display, Serialize, Deserialize)]
193pub enum ButtplugDeviceMessageNameV3 {
194 LinearCmd,
195 RotateCmd,
196 StopDeviceCmd,
197 ScalarCmd,
198 SensorReadCmd,
199 SensorSubscribeCmd,
200 SensorUnsubscribeCmd,
201}