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 v0::DeviceMessageInfoV0,
10 v1::DeviceMessageInfoV1,
11 v2::{DeviceAddedV2, DeviceMessageInfoV2},
12};
13use buttplug_core::{
14 errors::ButtplugMessageError,
15 message::{
16 ButtplugMessage,
17 ButtplugMessageFinalizer,
18 ButtplugMessageValidator,
19 DeviceFeature,
20 DeviceMessageInfoV4,
21 },
22};
23
24use getset::{CopyGetters, Getters};
25
26use serde::{Deserialize, Serialize};
27
28use super::{ClientDeviceMessageAttributesV3, DeviceMessageInfoV3};
29
30/// Notification that a device has been found and connected to the server.
31#[derive(ButtplugMessage, Clone, Debug, Getters, CopyGetters, Serialize, Deserialize)]
32pub struct DeviceAddedV3 {
33 #[serde(rename = "Id")]
34 id: u32,
35 // DeviceAdded is not considered a device message because it only notifies of existence and is not
36 // a command (and goes from server to client), therefore we have to define the getter ourselves.
37 #[serde(rename = "DeviceIndex")]
38 #[getset(get_copy = "pub")]
39 device_index: u32,
40 #[serde(rename = "DeviceName")]
41 #[getset(get = "pub")]
42 device_name: String,
43 #[serde(rename = "DeviceDisplayName", skip_serializing_if = "Option::is_none")]
44 #[getset(get = "pub")]
45 device_display_name: Option<String>,
46 #[serde(rename = "DeviceMessageTimingGap")]
47 #[getset(get_copy = "pub")]
48 device_message_timing_gap: u32,
49 #[serde(rename = "DeviceMessages")]
50 #[getset(get = "pub")]
51 device_messages: ClientDeviceMessageAttributesV3,
52}
53
54impl DeviceAddedV3 {
55 pub fn new(
56 device_index: u32,
57 device_name: &str,
58 device_display_name: &Option<String>,
59 device_message_timing_gap: u32,
60 device_messages: &ClientDeviceMessageAttributesV3,
61 ) -> Self {
62 let mut obj = Self {
63 id: 0,
64 device_index,
65 device_name: device_name.to_string(),
66 device_display_name: device_display_name.clone(),
67 device_message_timing_gap,
68 device_messages: device_messages.clone(),
69 };
70 obj.finalize();
71 obj
72 }
73}
74
75impl ButtplugMessageValidator for DeviceAddedV3 {
76 fn is_valid(&self) -> Result<(), ButtplugMessageError> {
77 self.is_system_id(self.id)
78 }
79}
80
81impl ButtplugMessageFinalizer for DeviceAddedV3 {
82 fn finalize(&mut self) {
83 self.device_messages.finalize();
84 }
85}
86
87impl From<DeviceAddedV3> for DeviceMessageInfoV0 {
88 fn from(device_added: DeviceAddedV3) -> Self {
89 let dmi = DeviceMessageInfoV3::from(device_added);
90 let dmi_v2: DeviceMessageInfoV2 = dmi.into();
91 let dmi_v1: DeviceMessageInfoV1 = dmi_v2.into();
92 dmi_v1.into()
93 }
94}
95
96impl From<DeviceAddedV3> for DeviceAddedV2 {
97 fn from(msg: DeviceAddedV3) -> Self {
98 let id = msg.id();
99 let dmi = DeviceMessageInfoV3::from(msg);
100 let dmiv1 = DeviceMessageInfoV2::from(dmi);
101
102 Self {
103 id,
104 device_index: dmiv1.device_index(),
105 device_name: dmiv1.device_name().clone(),
106 device_messages: dmiv1.device_messages().clone(),
107 }
108 }
109}
110
111impl From<DeviceAddedV3> for DeviceMessageInfoV2 {
112 fn from(device_added: DeviceAddedV3) -> Self {
113 let dmi = DeviceMessageInfoV3::from(device_added);
114 DeviceMessageInfoV2::from(dmi)
115 }
116}
117
118impl From<DeviceMessageInfoV4> for DeviceAddedV3 {
119 fn from(value: DeviceMessageInfoV4) -> Self {
120 let feature_vec: Vec<DeviceFeature> = value.device_features().values().cloned().collect();
121 let mut da3 = DeviceAddedV3::new(
122 value.device_index(),
123 value.device_name(),
124 value.device_display_name(),
125 value.device_message_timing_gap(),
126 &feature_vec.into(),
127 );
128 da3.set_id(0);
129 da3
130 }
131}