use getset::{CopyGetters, Getters, MutGetters}; use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ButtplugDeviceConfigError, ServerDeviceDefinition, ServerDeviceDefinitionBuilder}; use super::feature::{ConfigBaseDeviceFeature, ConfigUserDeviceFeature}; #[derive(Debug, Clone, Getters, CopyGetters, Serialize, Deserialize)] pub struct ConfigBaseDeviceDefinition { #[getset(get = "pub")] identifier: Option>, #[getset(get = "pub")] /// Given name of the device this instance represents. name: String, #[getset(get_copy = "pub")] id: Uuid, #[getset(get = "pub")] protocol_variant: Option, #[getset(get_copy = "pub")] message_gap_ms: Option, #[getset(get = "pub")] features: Option>, } impl ConfigBaseDeviceDefinition { pub fn update_with_configuration(&self, config: ConfigBaseDeviceDefinition) -> Self { Self { identifier: config.identifier().clone(), name: config.name().clone(), id: config.id(), protocol_variant: config.protocol_variant.or(self.protocol_variant.clone()), message_gap_ms: config.message_gap_ms.or(self.message_gap_ms), features: config.features.or(self.features.clone()), } } } impl From for ServerDeviceDefinition { fn from(val: ConfigBaseDeviceDefinition) -> Self { let mut builder = ServerDeviceDefinitionBuilder::new(&val.name, &val.id); if let Some(variant) = val.protocol_variant { builder.protocol_variant(&variant); } if let Some(gap) = val.message_gap_ms { builder.message_gap_ms(gap); } if let Some(features) = val.features { for feature in features { builder.add_feature(&feature.into()); } } builder.finish() } } #[derive(Serialize, Deserialize, Debug, Getters, CopyGetters, Default, Clone, MutGetters)] pub struct ConfigUserDeviceCustomization { #[serde(default, skip_serializing_if = "Option::is_none")] #[getset(get = "pub")] display_name: Option, #[serde(default)] #[getset(get_copy = "pub")] allow: bool, #[serde(default)] #[getset(get_copy = "pub")] deny: bool, #[getset(get_copy = "pub", get_mut = "pub")] index: u32, #[getset(get_copy = "pub")] #[serde(default, skip_serializing_if = "Option::is_none")] message_gap_ms: Option, } impl From<&ServerDeviceDefinition> for ConfigUserDeviceCustomization { fn from(value: &ServerDeviceDefinition) -> Self { Self { display_name: value.display_name().clone(), allow: value.allow(), deny: value.deny(), index: value.index(), message_gap_ms: value.message_gap_ms(), } } } #[derive(Debug, Clone, Getters, MutGetters, Serialize, Deserialize, CopyGetters)] pub struct ConfigUserDeviceDefinition { #[getset(get_copy = "pub")] id: Uuid, #[getset(get_copy = "pub")] base_id: Uuid, #[getset(get = "pub")] /// Message attributes for this device instance. #[getset(get = "pub", get_mut = "pub")] features: Vec, #[getset(get = "pub", get_mut = "pub")] /// Per-user configurations specific to this device instance. user_config: ConfigUserDeviceCustomization, } impl ConfigUserDeviceDefinition { pub fn build_from_base_definition( &self, base: &ServerDeviceDefinition, ) -> Result { let mut builder = ServerDeviceDefinitionBuilder::from_base(base, self.id, false); builder.display_name(&self.user_config.display_name); if let Some(message_gap_ms) = self.user_config.message_gap_ms { builder.message_gap_ms(message_gap_ms); } self.user_config.allow.then(|| builder.allow(true)); self.user_config.deny.then(|| builder.deny(true)); builder.index(self.user_config.index); if self.features().len() != base.features().len() { return Err(ButtplugDeviceConfigError::UserFeatureMismatch); } for feature in self.features() { if let Some(base_feature) = base.features().iter().find(|x| x.id() == feature.base_id()) { builder.add_feature(&feature.with_base_feature(base_feature)?); } else { return Err(ButtplugDeviceConfigError::UserFeatureMismatch); } } Ok(builder.finish()) } } impl From<&ServerDeviceDefinition> for ConfigUserDeviceDefinition { fn from(value: &ServerDeviceDefinition) -> Self { Self { id: value.id(), base_id: value.base_id().expect("Should always have a base id"), features: value.features().iter().map(|x| x.into()).collect(), user_config: value.into(), } } }