mod incoming;
mod outgoing;
mod props;
mod types;
pub const PROTOCOL_VERSION: u32 = 1;
pub fn json_protocol_version(value: &serde_json::Value) -> Option<u32> {
value.as_u64().and_then(|v| u32::try_from(v).ok())
}
pub use incoming::{ImageOpPayload, IncomingMessage, LoadFontPayload};
pub use outgoing::{
CoalesceHint, DiagnosticLevel, DiagnosticMessage, EffectResponse, EffectStubAck,
InteractResponse, KeyModifiers, OutgoingEvent, QueryResponse, ResetResponse,
ScreenshotResponse, TreeHashResponse,
};
pub use props::{PropMap, PropValue, Props};
pub use types::{PatchOp, TreeNode, canonical_tree_hash};
#[derive(Debug)]
pub struct SessionMessage {
pub session: String,
pub message: IncomingMessage,
}
impl SessionMessage {
pub fn from_value(mut value: serde_json::Value) -> Result<Self, serde_json::Error> {
let session = match value.as_object_mut() {
Some(obj) => match obj.remove("session") {
None => String::new(),
Some(serde_json::Value::String(s)) => s,
Some(other) => {
return Err(serde::de::Error::custom(format!(
"session must be a string, got {}",
other
)));
}
},
None => {
return Err(serde::de::Error::custom("expected JSON object"));
}
};
let message = serde_json::from_value(value)?;
Ok(Self { session, message })
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn json_protocol_version_accepts_u32_max() {
assert_eq!(json_protocol_version(&json!(u32::MAX)), Some(u32::MAX));
}
#[test]
fn json_protocol_version_rejects_out_of_range_values() {
assert_eq!(json_protocol_version(&json!(u64::from(u32::MAX) + 1)), None);
}
#[test]
fn json_protocol_version_rejects_non_integer_values() {
assert_eq!(json_protocol_version(&json!(1.5)), None);
assert_eq!(json_protocol_version(&json!(-1)), None);
assert_eq!(json_protocol_version(&json!("1")), None);
}
}