Skip to content

Commit 5be4bf3

Browse files
committed
Support Context<T> in async code.
1 parent be5eb2b commit 5be4bf3

File tree

5 files changed

+144
-98
lines changed

5 files changed

+144
-98
lines changed

examples/async.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
use json_rpc2::{Request, Response, Result, futures::*};
2-
use serde_json::Value;
31
use async_trait::async_trait;
2+
use json_rpc2::{futures::*, Context, Request, Response, Result};
3+
use serde_json::Value;
44

55
struct ServiceHandler;
66

77
#[async_trait]
8-
impl Service for ServiceHandler {
9-
async fn handle(&self, req: &mut Request) -> Result<Option<Response>> {
8+
impl<T: Send + Sync> Service<T> for ServiceHandler {
9+
async fn handle(
10+
&self,
11+
req: &mut Request,
12+
_ctx: &Context<T>,
13+
) -> Result<Option<Response>> {
1014
let mut response = None;
1115
if req.matches("hello") {
1216
let params: String = req.deserialize()?;
@@ -19,10 +23,11 @@ impl Service for ServiceHandler {
1923

2024
#[tokio::main]
2125
async fn main() -> Result<()> {
22-
let service: Box<dyn Service> = Box::new(ServiceHandler {});
23-
let mut request = Request::new("hello", Some(Value::String("world".to_string())));
24-
let services = vec![&service];
25-
let response = serve(&services, &mut request).await;
26+
let service: Box<dyn Service<()>> = Box::new(ServiceHandler {});
27+
let mut request =
28+
Request::new("hello", Some(Value::String("world".to_string())));
29+
let server = Server::new(vec![&service]);
30+
let response = server.serve(&mut request, &Default::default()).await;
2631
println!("{:?}", response.result());
2732
assert_eq!(
2833
Some(Value::String("Hello, world!".to_string())),

examples/hello-world.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ use serde_json::Value;
33

44
struct ServiceHandler;
55
impl<T> Service<T> for ServiceHandler {
6-
fn handle(&self, request: &mut Request, _context: &Context<T>) -> Result<Option<Response>> {
6+
fn handle(
7+
&self,
8+
request: &mut Request,
9+
_ctx: &Context<T>,
10+
) -> Result<Option<Response>> {
711
let mut response = None;
812
if request.matches("hello") {
913
let params: String = request.deserialize()?;
@@ -16,9 +20,10 @@ impl<T> Service<T> for ServiceHandler {
1620

1721
fn main() -> Result<()> {
1822
let service: Box<dyn Service<()>> = Box::new(ServiceHandler {});
19-
let mut request = Request::new("hello", Some(Value::String("world".to_string())));
20-
let services = vec![&service];
21-
let response = serve(&services, &mut request);
23+
let mut request =
24+
Request::new("hello", Some(Value::String("world".to_string())));
25+
let server = Server::new(vec![&service]);
26+
let response = server.serve(&mut request, &Default::default());
2227
println!("{:?}", response.result());
2328
assert_eq!(
2429
Some(Value::String("Hello, world!".to_string())),

rustfmt.toml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
edition = "2018"
2+
max_width = 80

src/futures.rs

+48-28
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,63 @@
11
//! Non-blocking implementation, requires the `async` feature.
22
3-
use crate::{Request, Response, Error, Result};
3+
use crate::{Context, Error, Request, Response, Result};
44
use async_trait::async_trait;
55

66
#[async_trait]
77
/// Trait for async services that maybe handle a request.
8-
pub trait Service {
8+
pub trait Service<T: Send + Send> {
99
/// See [Service](crate::Service) for more information.
10-
async fn handle(&self, req: &mut Request) -> Result<Option<Response>>;
10+
async fn handle(
11+
&self,
12+
request: &mut Request,
13+
ctx: &Context<T>,
14+
) -> Result<Option<Response>>;
1115
}
1216

13-
/// Call async services in order and return the first response message.
14-
///
15-
/// See [handle](crate::handle) for more information.
16-
pub async fn handle<'a>(
17-
services: &'a Vec<&'a Box<dyn Service>>,
18-
request: &mut Request,
19-
) -> Result<Response> {
20-
for service in services {
21-
if let Some(result) = service.handle(request).await? {
22-
return Ok(result);
23-
}
17+
/// Serve requests.
18+
pub struct Server<'a, T: Send + Sync> {
19+
/// Services that the server should invoke for every request.
20+
services: Vec<&'a Box<dyn Service<T>>>,
21+
}
22+
23+
impl<'a, T: Send + Sync> Server<'a, T> {
24+
/// Create a new server.
25+
pub fn new(services: Vec<&'a Box<dyn Service<T>>>) -> Self {
26+
Self {services}
2427
}
2528

26-
let err = Error::MethodNotFound {
27-
name: request.method().to_string(),
28-
id: request.id.clone(),
29-
};
29+
/// Call services in order and return the first response message.
30+
///
31+
/// If no services match the incoming request this will
32+
/// return a `Error::MethodNotFound`.
33+
pub(crate) async fn handle(
34+
&self,
35+
request: &mut Request,
36+
ctx: &Context<T>,
37+
) -> Result<Response> {
38+
for service in self.services.iter() {
39+
if let Some(result) = service.handle(request, ctx).await? {
40+
return Ok(result);
41+
}
42+
}
43+
44+
let err = Error::MethodNotFound {
45+
name: request.method().to_string(),
46+
id: request.id.clone(),
47+
};
3048

31-
Ok((request, err).into())
32-
}
49+
Ok((request, err).into())
50+
}
3351

34-
/// Infallible async service handler, errors are automatically converted to responses.
35-
pub async fn serve<'a>(
36-
services: &'a Vec<&'a Box<dyn Service>>,
37-
request: &mut Request,
38-
) -> Response {
39-
match handle(services, request).await {
40-
Ok(response) => response,
41-
Err(e) => e.into(),
52+
/// Infallible service handler, errors are automatically converted to responses.
53+
pub async fn serve(
54+
&self,
55+
request: &mut Request,
56+
ctx: &Context<T>,
57+
) -> Response {
58+
match self.handle(request, ctx).await {
59+
Ok(response) => response,
60+
Err(e) => e.into(),
61+
}
4262
}
4363
}

0 commit comments

Comments
 (0)