use buttplug_core::message::{
ButtplugClientMessageV4,
ButtplugMessage,
ButtplugMessageFinalizer,
ButtplugServerMessageV4,
serializer::{
ButtplugMessageSerializer,
ButtplugSerializedMessage,
ButtplugSerializerError,
json_serializer::{create_message_validator, deserialize_to_message, vec_to_protocol_json},
},
};
use jsonschema::Validator;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
pub struct ButtplugClientJSONSerializerImpl {
validator: Validator,
}
impl Default for ButtplugClientJSONSerializerImpl {
fn default() -> Self {
Self {
validator: create_message_validator(),
}
}
}
impl ButtplugClientJSONSerializerImpl {
pub fn deserialize<T>(
&self,
msg: &ButtplugSerializedMessage,
) -> Result<Vec<T>, ButtplugSerializerError>
where
T: serde::de::DeserializeOwned + ButtplugMessageFinalizer + Clone + Debug,
{
if let ButtplugSerializedMessage::Text(text_msg) = msg {
deserialize_to_message::<T>(Some(&self.validator), text_msg)
} else {
Err(ButtplugSerializerError::BinaryDeserializationError)
}
}
pub fn serialize<T>(&self, msg: &[T]) -> ButtplugSerializedMessage
where
T: ButtplugMessage + Serialize + Deserialize<'static> + Debug,
{
ButtplugSerializedMessage::Text(match vec_to_protocol_json(&self.validator, msg) {
Ok(m) => m,
Err(e) => match vec_to_protocol_json(&self.validator, &vec![e]) {
Ok(e) => {
error!("Error serializing message: {:?}", e);
e
}
Err(e) => {
error!(
"SERIALIZER AND/OR MESSAGE SCHEMA SEEMS COMPLETELY BROKEN, SENDING BACK NULL. ERROR: {:?}",
e
);
String::new()
}
},
})
}
}
#[derive(Default)]
pub struct ButtplugClientJSONSerializer {
serializer_impl: ButtplugClientJSONSerializerImpl,
}
impl ButtplugMessageSerializer for ButtplugClientJSONSerializer {
type Inbound = ButtplugServerMessageV4;
type Outbound = ButtplugClientMessageV4;
fn deserialize(
&self,
msg: &ButtplugSerializedMessage,
) -> Result<Vec<Self::Inbound>, ButtplugSerializerError> {
self.serializer_impl.deserialize(msg)
}
fn serialize(&self, msg: &[Self::Outbound]) -> ButtplugSerializedMessage {
self.serializer_impl.serialize(msg)
}
}
#[cfg(test)]
mod test {
use super::*;
use buttplug_core::message::{
BUTTPLUG_CURRENT_API_MAJOR_VERSION,
BUTTPLUG_CURRENT_API_MINOR_VERSION,
RequestServerInfoV4,
};
#[test]
fn test_client_incorrect_messages() {
let incorrect_incoming_messages = vec![
"not a json message",
"{}",
"[]",
"[{\"NotAMessage\":{}}]",
"[{\"Ok\":[]}]",
"[{\"Ok\":{}}]",
"{\"Ok\":{\"Id\":0}}",
"[{\"Ok\":{\"Id\":0}}]",
"[{\"Ok\":{\"NotAField\":\"NotAValue\",\"Id\":1}}]",
];
let serializer = ButtplugClientJSONSerializer::default();
let _ = serializer.serialize(&vec![
RequestServerInfoV4::new(
"test client",
BUTTPLUG_CURRENT_API_MAJOR_VERSION,
BUTTPLUG_CURRENT_API_MINOR_VERSION,
)
.into(),
]);
for msg in incorrect_incoming_messages {
let res = serializer.deserialize(&ButtplugSerializedMessage::Text(msg.to_owned()));
assert!(res.is_err(), "{} should be an error", msg);
if let Err(ButtplugSerializerError::MessageSpecVersionNotReceived) = res {
assert!(false, "Wrong error!");
}
}
}
}