use std::collections::HashMap;
use serde_json::Value;
use crate::engine::DarklyEngine;
pub mod handlers;
mod transport;
pub use transport::{DrainOutcome, QueuedRequest, RequestOutcome, Transport};
pub use crate::gpu::params::param_values_from_json as params_from_json;
#[derive(Debug)]
pub struct Response {
pub value: Value,
pub bytes: Option<Vec<u8>>,
}
impl Response {
pub fn json(value: Value) -> Self {
Response { value, bytes: None }
}
pub fn binary(value: Value, bytes: Vec<u8>) -> Self {
Response {
value,
bytes: Some(bytes),
}
}
pub fn empty() -> Self {
Response {
value: Value::Null,
bytes: None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ProtocolError {
UnknownRequest(String),
BadPayload(String),
Engine(String),
}
impl ProtocolError {
pub fn unknown(kind: &str) -> Self {
ProtocolError::UnknownRequest(kind.to_string())
}
pub fn engine(msg: impl Into<String>) -> Self {
ProtocolError::Engine(msg.into())
}
pub fn to_json(&self) -> Value {
let (kind, message) = match self {
ProtocolError::UnknownRequest(k) => ("unknown_request", k.clone()),
ProtocolError::BadPayload(m) => ("bad_payload", m.clone()),
ProtocolError::Engine(m) => ("engine_error", m.clone()),
};
serde_json::json!({ "kind": kind, "message": message })
}
}
pub fn bad_payload(e: impl std::fmt::Display) -> ProtocolError {
ProtocolError::BadPayload(e.to_string())
}
pub fn decode<T: serde::de::DeserializeOwned>(payload: Value) -> Result<T, ProtocolError> {
serde_json::from_value(payload).map_err(bad_payload)
}
pub fn layer_id(payload: Value) -> Result<crate::layer::LayerId, ProtocolError> {
#[derive(serde::Deserialize)]
struct Id {
id: u64,
}
let r: Id = decode(payload)?;
Ok(crate::layer::LayerId::from_ffi(r.id))
}
pub fn graph_result(r: Result<String, String>) -> Result<Response, ProtocolError> {
match r {
Ok(json) => {
let graph: Value = serde_json::from_str(&json).map_err(bad_payload)?;
Ok(Response::json(serde_json::json!({ "graph": graph })))
}
Err(e) => Ok(Response::json(serde_json::json!({ "error": e }))),
}
}
pub fn ok_or_error(r: Result<(), String>) -> Response {
match r {
Ok(()) => Response::json(Value::Null),
Err(e) => Response::json(serde_json::json!({ "error": e })),
}
}
pub struct RequestRegistration {
pub kind: &'static str,
pub handle: fn(&mut DarklyEngine, Value, &[u8]) -> Result<Response, ProtocolError>,
}
pub struct RequestRegistry {
handlers: HashMap<&'static str, RequestRegistration>,
}
impl Default for RequestRegistry {
fn default() -> Self {
Self::new()
}
}
impl RequestRegistry {
pub fn new() -> Self {
let mut map: HashMap<&'static str, RequestRegistration> = HashMap::new();
for reg in handlers::registrations() {
let kind = reg.kind;
let prev = map.insert(kind, reg);
assert!(prev.is_none(), "duplicate request kind: {kind}");
}
RequestRegistry { handlers: map }
}
pub fn all_kinds(&self) -> Vec<&'static str> {
let mut kinds: Vec<&'static str> = self.handlers.keys().copied().collect();
kinds.sort_unstable();
kinds
}
pub fn dispatch(
&self,
engine: &mut DarklyEngine,
kind: &str,
payload: Value,
bytes: &[u8],
) -> Result<Response, ProtocolError> {
match self.handlers.get(kind) {
Some(reg) => (reg.handle)(engine, payload, bytes),
None => Err(ProtocolError::unknown(kind)),
}
}
}