zerolaunch-plugin-protocol 0.1.0

ZeroLaunch plugin JSON-RPC protocol definitions.
Documentation
use serde::{Deserialize, Serialize};

use crate::error::JsonRpcError;

/// JSON-RPC 2.0 envelope. Untagged so serde can distinguish Request / Response / Notification.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Message {
    Request(Request),
    Response(Response),
    Notification(Notification),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Request {
    pub jsonrpc: String,
    pub id: u64,
    pub method: String,
    #[serde(default)]
    pub params: serde_json::Value,
}

impl Request {
    pub fn new(id: u64, method: impl Into<String>, params: serde_json::Value) -> Self {
        Self {
            jsonrpc: "2.0".into(),
            id,
            method: method.into(),
            params,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Response {
    pub jsonrpc: String,
    pub id: u64,
    #[serde(default)]
    pub result: Option<serde_json::Value>,
    #[serde(default)]
    pub error: Option<JsonRpcError>,
}

impl Response {
    pub fn ok(id: u64, result: serde_json::Value) -> Self {
        Self {
            jsonrpc: "2.0".into(),
            id,
            result: Some(result),
            error: None,
        }
    }

    pub fn err(id: u64, error: JsonRpcError) -> Self {
        Self {
            jsonrpc: "2.0".into(),
            id,
            result: None,
            error: Some(error),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Notification {
    pub jsonrpc: String,
    pub method: String,
    #[serde(default)]
    pub params: serde_json::Value,
}

impl Notification {
    pub fn new(method: impl Into<String>, params: serde_json::Value) -> Self {
        Self {
            jsonrpc: "2.0".into(),
            method: method.into(),
            params,
        }
    }
}

/// Returns true if a message is a JSON-RPC request (not a notification — has an id).
pub fn is_request(msg: &Message) -> bool {
    matches!(msg, Message::Request(_))
}

/// Returns true if a message is a JSON-RPC notification (no id).
pub fn is_notification(msg: &Message) -> bool {
    matches!(msg, Message::Notification(_))
}

/// Returns true if a message is a JSON-RPC response.
pub fn is_response(msg: &Message) -> bool {
    matches!(msg, Message::Response(_))
}