Buttplug sex toy control library
1use buttplug_core::message::{
2 ButtplugClientMessageV4,
3 ButtplugMessage,
4 ButtplugMessageFinalizer,
5 ButtplugServerMessageV4,
6 serializer::{
7 ButtplugMessageSerializer,
8 ButtplugSerializedMessage,
9 ButtplugSerializerError,
10 json_serializer::{create_message_validator, deserialize_to_message, vec_to_protocol_json},
11 },
12};
13use jsonschema::Validator;
14use serde::{Deserialize, Serialize};
15use std::fmt::Debug;
16
17pub struct ButtplugClientJSONSerializerImpl {
18 validator: Validator,
19}
20
21impl Default for ButtplugClientJSONSerializerImpl {
22 fn default() -> Self {
23 Self {
24 validator: create_message_validator(),
25 }
26 }
27}
28
29impl ButtplugClientJSONSerializerImpl {
30 pub fn deserialize<T>(
31 &self,
32 msg: &ButtplugSerializedMessage,
33 ) -> Result<Vec<T>, ButtplugSerializerError>
34 where
35 T: serde::de::DeserializeOwned + ButtplugMessageFinalizer + Clone + Debug,
36 {
37 if let ButtplugSerializedMessage::Text(text_msg) = msg {
38 deserialize_to_message::<T>(Some(&self.validator), text_msg)
39 } else {
40 Err(ButtplugSerializerError::BinaryDeserializationError)
41 }
42 }
43
44 pub fn serialize<T>(&self, msg: &[T]) -> ButtplugSerializedMessage
45 where
46 T: ButtplugMessage + Serialize + Deserialize<'static>,
47 {
48 ButtplugSerializedMessage::Text(vec_to_protocol_json(msg))
49 }
50}
51
52#[derive(Default)]
53pub struct ButtplugClientJSONSerializer {
54 serializer_impl: ButtplugClientJSONSerializerImpl,
55}
56
57impl ButtplugMessageSerializer for ButtplugClientJSONSerializer {
58 type Inbound = ButtplugServerMessageV4;
59 type Outbound = ButtplugClientMessageV4;
60
61 fn deserialize(
62 &self,
63 msg: &ButtplugSerializedMessage,
64 ) -> Result<Vec<Self::Inbound>, ButtplugSerializerError> {
65 self.serializer_impl.deserialize(msg)
66 }
67
68 fn serialize(&self, msg: &[Self::Outbound]) -> ButtplugSerializedMessage {
69 self.serializer_impl.serialize(msg)
70 }
71}
72
73#[cfg(test)]
74mod test {
75 use super::*;
76 use buttplug_core::message::{
77 BUTTPLUG_CURRENT_API_MAJOR_VERSION,
78 BUTTPLUG_CURRENT_API_MINOR_VERSION,
79 RequestServerInfoV4,
80 };
81
82 #[test]
83 fn test_client_incorrect_messages() {
84 let incorrect_incoming_messages = vec![
85 // Not valid JSON
86 "not a json message",
87 // Valid json object but no contents
88 "{}",
89 // Valid json but not an object
90 "[]",
91 // Not a message type
92 "[{\"NotAMessage\":{}}]",
93 // Valid json and message type but not in correct format
94 "[{\"Ok\":[]}]",
95 // Valid json and message type but not in correct format
96 "[{\"Ok\":{}}]",
97 // Valid json and message type but not an array.
98 "{\"Ok\":{\"Id\":0}}",
99 // Valid json and message type but not an array.
100 "[{\"Ok\":{\"Id\":0}}]",
101 // Valid json and message type but with extra content
102 "[{\"Ok\":{\"NotAField\":\"NotAValue\",\"Id\":1}}]",
103 ];
104 let serializer = ButtplugClientJSONSerializer::default();
105 let _ = serializer.serialize(&vec![
106 RequestServerInfoV4::new(
107 "test client",
108 BUTTPLUG_CURRENT_API_MAJOR_VERSION,
109 BUTTPLUG_CURRENT_API_MINOR_VERSION,
110 )
111 .into(),
112 ]);
113 for msg in incorrect_incoming_messages {
114 let res = serializer.deserialize(&ButtplugSerializedMessage::Text(msg.to_owned()));
115 assert!(res.is_err(), "{} should be an error", msg);
116 if let Err(ButtplugSerializerError::MessageSpecVersionNotReceived) = res {
117 assert!(false, "Wrong error!");
118 }
119 }
120 }
121}