capnweb-core 0.1.0

Core protocol implementation for Cap'n Web RPC - capability-based security with promise pipelining
Documentation
use crate::ids::{CallId, CapId};
use serde::{Deserialize, Serialize};
use serde_json::Value;

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Target {
    Cap { cap: CapIdWrapper },
    Special { special: String },
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CapIdWrapper {
    pub id: CapId,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Outcome {
    Success { value: Value },
    Error { error: crate::error::RpcError },
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Message {
    Call {
        call: CallMessage,
    },
    Result {
        result: ResultMessage,
    },
    CapRef {
        #[serde(rename = "capRef")]
        cap_ref: CapRefMessage,
    },
    Dispose {
        dispose: DisposeMessage,
    },
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CallMessage {
    pub id: CallId,
    pub target: Target,
    pub member: String,
    pub args: Vec<Value>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ResultMessage {
    pub id: CallId,
    #[serde(flatten)]
    pub outcome: Outcome,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CapRefMessage {
    pub id: CapId,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DisposeMessage {
    pub caps: Vec<CapId>,
}

impl Target {
    pub fn cap(id: CapId) -> Self {
        Target::Cap {
            cap: CapIdWrapper { id },
        }
    }

    pub fn special(name: String) -> Self {
        Target::Special { special: name }
    }
}

impl Message {
    pub fn call(id: CallId, target: Target, member: String, args: Vec<Value>) -> Self {
        Message::Call {
            call: CallMessage {
                id,
                target,
                member,
                args,
            },
        }
    }

    pub fn result(id: CallId, outcome: Outcome) -> Self {
        Message::Result {
            result: ResultMessage { id, outcome },
        }
    }

    pub fn cap_ref(id: CapId) -> Self {
        Message::CapRef {
            cap_ref: CapRefMessage { id },
        }
    }

    pub fn dispose(caps: Vec<CapId>) -> Self {
        Message::Dispose {
            dispose: DisposeMessage { caps },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_message_serialization() {
        let msg = Message::call(
            CallId::new(1),
            Target::cap(CapId::new(42)),
            "test".to_string(),
            vec![Value::String("arg".to_string())],
        );

        let json = serde_json::to_string(&msg).unwrap();
        let deserialized: Message = serde_json::from_str(&json).unwrap();
        assert_eq!(msg, deserialized);
    }
}