This repository has been archived on 2026-08-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
el-retired/ui/vessels/el-services/src/binding/mod.rs
T

115 lines
3.0 KiB
Rust

//! Service binding implementations.
//!
//! Each binding protocol implements the `Binding` trait.
//! The proxy uses whatever binding is configured in `el.toml`.
pub mod direct;
pub mod grpc;
pub mod rest;
pub mod websocket;
use crate::ServiceResult;
use std::collections::HashMap;
/// Which protocol this service binding uses.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BindingKind {
/// HTTP REST — maps service methods to HTTP endpoints.
Rest,
/// WebSocket — persistent connection, message-based RPC.
WebSocket,
/// gRPC — protobuf over HTTP/2 (stub; codegen is a future TODO).
Grpc,
/// Direct — server-side only; calls Rust functions directly, zero network.
Direct,
}
impl BindingKind {
pub fn from_str(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"rest" => Some(Self::Rest),
"websocket" | "ws" => Some(Self::WebSocket),
"grpc" => Some(Self::Grpc),
"direct" => Some(Self::Direct),
_ => None,
}
}
pub fn as_str(&self) -> &'static str {
match self {
Self::Rest => "rest",
Self::WebSocket => "websocket",
Self::Grpc => "grpc",
Self::Direct => "direct",
}
}
}
/// A service call request — method name and parameters.
#[derive(Debug, Clone)]
pub struct ServiceRequest {
pub service: String,
pub method: String,
/// Parameters as key-value pairs. Complex types are JSON-serialized strings.
pub params: HashMap<String, String>,
}
impl ServiceRequest {
pub fn new(service: impl Into<String>, method: impl Into<String>) -> Self {
Self {
service: service.into(),
method: method.into(),
params: HashMap::new(),
}
}
pub fn with_param(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.params.insert(key.into(), value.into());
self
}
}
/// A service call response — raw body string (JSON, protobuf bytes as hex, etc.)
#[derive(Debug, Clone)]
pub struct ServiceResponse {
pub status: u16,
pub body: String,
pub headers: HashMap<String, String>,
}
impl ServiceResponse {
pub fn ok(body: impl Into<String>) -> Self {
Self {
status: 200,
body: body.into(),
headers: HashMap::new(),
}
}
pub fn error(status: u16, body: impl Into<String>) -> Self {
Self {
status,
body: body.into(),
headers: HashMap::new(),
}
}
pub fn is_success(&self) -> bool {
(200..300).contains(&self.status)
}
}
/// The core binding trait — implemented by each protocol.
pub trait Binding: Send + Sync {
/// The kind of binding this is.
fn kind(&self) -> BindingKind;
/// Execute a service method call and return the response.
fn call(&self, request: ServiceRequest) -> ServiceResult<ServiceResponse>;
/// Whether this binding supports streaming responses.
fn supports_streaming(&self) -> bool {
false
}
}