No description
Find a file
damfle 41b722eb3f
All checks were successful
CI / Build (push) Successful in 21s
CI / Test (push) Successful in 22s
CI / Create Tag (push) Successful in 6s
CI / Lint (push) Successful in 22s
min: move to estd
2026-02-11 11:33:45 +01:00
.forgejo/workflows init: initial commit 2026-02-11 11:23:14 +01:00
examples init: initial commit 2026-02-11 11:23:14 +01:00
src init: initial commit 2026-02-11 11:23:14 +01:00
.gitignore init: initial commit 2026-02-11 11:23:14 +01:00
Cargo.toml min: move to estd 2026-02-11 11:33:45 +01:00
LICENSE init: initial commit 2026-02-11 11:23:14 +01:00
README.md init: initial commit 2026-02-11 11:23:14 +01:00

estd-jsonrpc

A JSON-RPC 2.0 implementation built on top of estd.

Overview

This library provides JSON-RPC 2.0 protocol support without any network implementation. You bring your own transport layer (TCP, Unix sockets, stdin/stdout, WebSockets, etc.).

Features

  • Full JSON-RPC 2.0 specification - Requests, responses, notifications, errors, and batch operations
  • Stream-based API - Reader and Writer for working with std::io::Read and std::io::Write
  • Non-stream API - Encoder and Decoder for direct message encoding/decoding
  • Zero network dependencies - Pure protocol implementation
  • Built on estd - No external dependencies except estd
  • Type-safe - Strongly typed requests, responses, and errors

Installation

Add to your Cargo.toml:

[dependencies]
estd-jsonrpc = { git = "https://git.flety.net/damien/estd-jsonrpc.git" }

Usage

Non-Stream API

For direct encoding/decoding of JSON-RPC messages:

use estd_jsonrpc::{Request, Response, MethodCall, SuccessResponse, Id, Encoder, Decoder};
use estd::encoding::Value;

// Encode a request
let request = Request::Single(MethodCall::new("subtract", None, 1));
let json = Encoder::encode(&request).unwrap();

// Decode a request
let decoded = Decoder::decode(&json).unwrap();

// Encode a response
let response = Response::Success(SuccessResponse::new(
    Value::Number(42.0),
    Id::Number(1)
));
let json = Encoder::encode_response(&response).unwrap();

Stream API

For reading/writing JSON-RPC messages from/to streams:

use estd_jsonrpc::{Reader, Writer, Request, Response, MethodCall, SuccessResponse, Id};
use estd::encoding::Value;
use std::net::TcpStream;

// Example with TCP stream
let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
let read_stream = stream.try_clone().unwrap();

// Create reader and writer
let mut reader = Reader::new(read_stream);
let mut writer = Writer::new(stream);

// Write a request
let request = Request::Single(MethodCall::new("add", None, 1));
writer.write_request(&request).unwrap();

// Read a response
let response = reader.read_response().unwrap();

Working with Parameters

Parameters can be either positional (array) or named (object):

use estd_jsonrpc::{Request, MethodCall};
use estd::encoding::Value;
use std::collections::BTreeMap;

// Positional parameters
let params = Value::Array(vec![
    Value::Number(42.0),
    Value::Number(23.0),
]);
let request = Request::Single(MethodCall::new("subtract", Some(params), 1));

// Named parameters
let mut params_obj = BTreeMap::new();
params_obj.insert("subtrahend".to_string(), Value::Number(23.0));
params_obj.insert("minuend".to_string(), Value::Number(42.0));
let params = Value::Object(params_obj);
let request = Request::Single(MethodCall::new("subtract", Some(params), 2));

Notifications

Notifications are requests without an ID (no response expected):

use estd_jsonrpc::{Request, Notification};

let notification = Request::Notification(Notification::new("update", None));

Error Handling

Use the standard JSON-RPC error codes:

use estd_jsonrpc::{Response, ErrorResponse, RpcError, Id};

// Standard errors
let error = RpcError::method_not_found();
let error = RpcError::invalid_params();
let error = RpcError::internal_error();

// Custom error
let error = RpcError::new(-32000, "Custom error message");

let response = Response::Error(ErrorResponse::new(error, Some(Id::Number(1))));

Batch Requests

Send multiple requests in a single batch:

use estd_jsonrpc::{Request, MethodCall, Notification};

let batch = Request::Batch(vec![
    Request::Single(MethodCall::new("sum", None, 1)),
    Request::Single(MethodCall::new("notify_hello", None, 2)),
    Request::Notification(Notification::new("update", None)),
]);

Architecture

This library is designed to be transport-agnostic. It only deals with the JSON-RPC protocol layer:

┌─────────────────────────────────────┐
│     Your Application Layer          │
├─────────────────────────────────────┤
│     estd-jsonrpc (This Library)     │
│  - Request/Response types           │
│  - Encoder/Decoder (non-stream)     │
│  - Reader/Writer (stream)           │
├─────────────────────────────────────┤
│     Your Transport Layer            │
│  - TCP, Unix sockets, stdio, etc.   │
└─────────────────────────────────────┘

You provide the transport (anything implementing Read/Write), and this library handles the protocol.

JSON-RPC 2.0 Compliance

This library implements the full JSON-RPC 2.0 specification:

  • Request objects with method, params, and id
  • Notification objects (no id field)
  • Response objects with result or error
  • Error objects with code, message, and optional data
  • Batch requests/responses
  • Standard error codes (-32700 to -32603)
  • Null id support for error responses

Examples

See the examples directory for complete working examples:

  • simple.rs - Basic request/response with non-stream API
  • stream.rs - Stream-based communication
  • stdio.rs - JSON-RPC over stdin/stdout

License

ISC License - See LICENSE file for details.

Author

Damien FLETY