use super::ButtplugSerializerError;
use crate::{
errors::{ButtplugError, ButtplugMessageError},
message::{ButtplugMessage, ButtplugMessageFinalizer, ErrorV0},
};
use jsonschema::Validator;
use serde::{Deserialize, Serialize};
use serde_json::{Deserializer, Value};
use std::fmt::{Debug, Display};
static MESSAGE_JSON_SCHEMA: &str = include_str!("../../../schema/buttplug-schema.json");
pub fn create_message_validator() -> Validator {
let schema: serde_json::Value = serde_json::from_str(MESSAGE_JSON_SCHEMA)
.expect("schema must be valid JSON (validated by build.rs)");
Validator::new(&schema).expect("schema must be valid JSON Schema (validated by build.rs)")
}
pub fn msg_to_protocol_json<T>(msg: T) -> String
where
T: ButtplugMessage + Serialize + Deserialize<'static>,
{
serde_json::to_string(&[&msg]).expect("ButtplugMessage types are always serializable")
}
pub fn vec_to_protocol_json<T>(validator: &Validator, msg: &[T]) -> Result<String, ErrorV0>
where
T: ButtplugMessage + Serialize + Deserialize<'static> + Debug,
{
let return_error_msg = |e: &dyn Display| {
let err = ButtplugMessageError::MessageSerializationError(
ButtplugSerializerError::JsonSerializerError(e.to_string()),
);
ErrorV0::from(ButtplugError::from(err))
};
let val = serde_json::to_value(msg).map_err(|e| return_error_msg(&e))?;
validator.validate(&val).map_err(|e| return_error_msg(&e))?;
serde_json::to_string(&val).map_err(|e| return_error_msg(&e))
}
pub fn deserialize_to_message<T>(
validator: Option<&Validator>,
msg_str: &str,
) -> Result<Vec<T>, ButtplugSerializerError>
where
T: serde::de::DeserializeOwned + ButtplugMessageFinalizer + Clone + Debug,
{
let stream = Deserializer::from_str(msg_str).into_iter::<Value>();
let mut result = vec![];
for msg in stream {
match msg {
Ok(json_msg) => {
if let Some(validator) = validator
&& !validator.is_valid(&json_msg)
{
let e = validator
.validate(&json_msg)
.expect_err("We can't get here without validity checks failing.");
return Err(ButtplugSerializerError::JsonSerializerError(format!(
"Error during JSON Schema Validation - Message: {json_msg} - Error: {e:?}"
)));
}
match serde_json::from_value::<Vec<T>>(json_msg) {
Ok(mut msg_vec) => {
for msg in msg_vec.iter_mut() {
msg.finalize();
}
result.append(&mut msg_vec);
}
Err(e) => {
return Err(ButtplugSerializerError::JsonSerializerError(format!(
"Message: {msg_str} - Error: {e:?}"
)));
}
}
}
Err(e) => {
return Err(ButtplugSerializerError::JsonSerializerError(format!(
"Message: {msg_str} - Error: {e:?}"
)));
}
}
}
Ok(result)
}