json_rpc/lib.rs
1//! A framework-agnostic JSON-RPC 2.0 implementation with Bring Your Own Transport.
2//!
3//! This library handles the JSON-RPC protocol layer including message parsing,
4//! method routing, and response generation. You register methods with the
5//! `JsonRpc` handler, then process JSON-RPC messages from any transport.
6//!
7//! # Bring Your Own Transport
8//!
9//! The library does not include transport implementations. You read JSON strings
10//! from your transport (stdio, HTTP, WebSocket, TCP, etc.), call `JsonRpc::call()`,
11//! and write the response back. This gives you full control over your transport
12//! layer.
13//!
14//! # Quick Start
15//!
16//! Create a handler and process a message:
17//!
18//! ```no_run
19//! use json_rpc::JsonRpc;
20//! use serde_json::Value;
21//!
22//! async fn echo(params: Value) -> Result<Value, json_rpc::Error> {
23//! Ok(params)
24//! }
25//!
26//! # tokio::runtime::Runtime::new().unwrap().block_on(async {
27//! let json_rpc = JsonRpc::new()
28//! .add("echo", echo);
29//!
30//! // Read from your transport
31//! let message = r#"{"jsonrpc":"2.0","method":"echo","params":"hello","id":1}"#;
32//!
33//! // Process the message
34//! if let Some(response) = json_rpc.call(message).await {
35//! // Write to your transport
36//! println!("{}", response);
37//! }
38//! # });
39//! ```
40//!
41//! # Stdio Example
42//!
43//! Read newline-delimited JSON from stdin and write responses to stdout:
44//!
45//! ```no_run
46//! use json_rpc::JsonRpc;
47//! use serde_json::Value;
48//! use tokio::io::AsyncBufReadExt;
49//!
50//! async fn echo(params: Value) -> Result<Value, json_rpc::Error> {
51//! Ok(params)
52//! }
53//!
54//! # tokio::runtime::Runtime::new().unwrap().block_on(async {
55//! let json_rpc = JsonRpc::new().add("echo", echo);
56//!
57//! let stdin = tokio::io::stdin();
58//! let mut reader = tokio::io::BufReader::new(stdin);
59//! let mut line = String::new();
60//!
61//! while reader.read_line(&mut line).await.unwrap() > 0 {
62//! let trimmed = line.trim();
63//! if !trimmed.is_empty() {
64//! if let Some(response) = json_rpc.call(trimmed).await {
65//! println!("{}", response);
66//! }
67//! }
68//! line.clear();
69//! }
70//! # });
71//! ```
72//!
73//! # Struct Parameters
74//!
75//! Handlers can use struct parameters for complex APIs:
76//!
77//! ```no_run
78//! use json_rpc::JsonRpc;
79//! use serde::Deserialize;
80//!
81//! # tokio::runtime::Runtime::new().unwrap().block_on(async {
82//! #[derive(Deserialize)]
83//! struct InitializeParams {
84//! name: String,
85//! version: String,
86//! }
87//!
88//! async fn initialize(params: InitializeParams) -> Result<String, json_rpc::Error> {
89//! Ok(format!("Server {} v{} initialized", params.name, params.version))
90//! }
91//!
92//! let json_rpc = JsonRpc::new()
93//! .add("initialize", initialize);
94//! # });
95//! ```
96//!
97//! # Error Handling
98//!
99//! Methods return `Result<T, Error>`. Create JSON-RPC protocol errors with
100//! specific codes:
101//!
102//! ```no_run
103//! use json_rpc::{JsonRpc, Error};
104//!
105//! async fn divide(params: (i32, i32)) -> Result<i32, Error> {
106//! if params.1 == 0 {
107//! return Err(Error::rpc(-32000, "Division by zero"));
108//! }
109//! Ok(params.0 / params.1)
110//! }
111//!
112//! let json_rpc = JsonRpc::new().add("divide", divide);
113//! ```
114//!
115//! # Axum Integration
116//!
117//! The axum feature provides a handler for HTTP integration. Enable the feature
118//! in Cargo.toml:
119//!
120//! ```toml
121//! [dependencies]
122//! json-rpc-rs = { version = "0.2", features = ["axum"] }
123//! ```
124//!
125//! ```no_run
126//! # #[cfg(feature = "axum")]
127//! # {
128//! use json_rpc::{JsonRpc, axum::handler};
129//! use axum::Router;
130//! use std::sync::Arc;
131//!
132//! async fn echo(params: serde_json::Value) -> Result<serde_json::Value, json_rpc::Error> {
133//! Ok(params)
134//! }
135//!
136//! let json_rpc = JsonRpc::new().add("echo", echo);
137//! let app = Router::new()
138//! .route("/jsonrpc", handler)
139//! .with_state(Arc::new(json_rpc));
140//! # }
141//! ```
142
143pub use error::Error;
144pub use jsonrpc::JsonRpc;
145pub use types::{Message, Notification, Request, RequestId, Response};
146
147pub mod error;
148pub mod jsonrpc;
149pub mod types;
150
151#[cfg(feature = "axum")]
152pub mod axum;