1use serde::de::DeserializeOwned;
2
3use crate::callable::{CallableParam, SupportsAsync};
4
5use super::{RpcError, RpcRequestContext, RpcRequestData, RpcRequestInit};
6
7#[derive(Debug)]
33pub struct Params<T: DeserializeOwned>(pub T);
34
35#[derive(Debug, thiserror::Error)]
36pub enum ParamsError {
37 #[error("failed to deserialize params: {0}")]
38 Deserialize(#[from] serde_json::Error),
39 #[error("request body data already consumed")]
40 DataAlreadyConsumed,
41}
42
43impl<T: DeserializeOwned + Send + Sync> CallableParam<RpcRequestContext, RpcRequestInit>
44 for Params<T>
45{
46 type Error = RpcError;
47
48 async fn extract(
49 ctx: &mut RpcRequestContext,
50 init: &RpcRequestInit,
51 ) -> Result<Self, Self::Error> {
52 let data = match ctx.request.data.take().ok_or_else(|| {
53 RpcError::ParamsError(init.method.clone(), ParamsError::DataAlreadyConsumed)
54 })? {
55 RpcRequestData::Typed(data) => serde_json::from_value(data)?,
56 };
57
58 Ok(Self(data))
59 }
60}
61
62impl<T: DeserializeOwned> SupportsAsync for Params<T> {}