jsonrpsee_core/
traits.rs

1// Copyright 2019-2021 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any
4// person obtaining a copy of this software and associated
5// documentation files (the "Software"), to deal in the
6// Software without restriction, including without
7// limitation the rights to use, copy, modify, merge,
8// publish, distribute, sublicense, and/or sell copies of
9// the Software, and to permit persons to whom the Software
10// is furnished to do so, subject to the following
11// conditions:
12//
13// The above copyright notice and this permission notice
14// shall be included in all copies or substantial portions
15// of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25// DEALINGS IN THE SOFTWARE.
26
27use jsonrpsee_types::SubscriptionId;
28use serde::Serialize;
29use serde_json::value::RawValue;
30
31/// Marker trait for types that can be serialized as JSON compatible strings.
32///
33/// This trait ensures the correctness of the RPC parameters.
34///
35/// # Note
36///
37/// Please consider using the [`crate::params::ArrayParams`] and [`crate::params::ObjectParams`] than
38/// implementing this trait.
39///
40/// # Examples
41///
42/// ## Implementation for hard-coded strings
43///
44/// ```rust
45/// use jsonrpsee_core::traits::ToRpcParams;
46/// use serde_json::value::RawValue;
47///
48/// struct ManualParam;
49///
50/// impl ToRpcParams for ManualParam {
51///     fn to_rpc_params(self) -> Result<Option<Box<RawValue>>, serde_json::Error> {
52///         // Manually define a valid JSONRPC parameter.
53///         serde_json::value::to_raw_value(&[1,2,3]).map(Some)
54///     }
55/// }
56/// ```
57///
58/// ## Implementation for JSON serializable structures
59///
60/// ```rust
61/// use jsonrpsee_core::traits::ToRpcParams;
62/// use serde_json::value::RawValue;
63/// use serde::Serialize;
64///
65/// #[derive(Serialize)]
66/// struct SerParam {
67///     param_1: u8,
68///     param_2: String,
69/// };
70///
71/// impl ToRpcParams for SerParam {
72///     fn to_rpc_params(self) -> Result<Option<Box<RawValue>>, serde_json::Error> {
73///         let s = String::from_utf8(serde_json::to_vec(&self)?).expect("Valid UTF8 format");
74///         RawValue::from_string(s).map(Some)
75///     }
76/// }
77/// ```
78pub trait ToRpcParams {
79	/// Consume and serialize the type as a JSON raw value.
80	fn to_rpc_params(self) -> Result<Option<Box<RawValue>>, serde_json::Error>;
81}
82
83// To not bound the `ToRpcParams: Serialize` define a custom implementation
84// for types which are serializable.
85macro_rules! to_rpc_params_impl {
86	() => {
87		fn to_rpc_params(self) -> Result<Option<Box<RawValue>>, serde_json::Error> {
88			let json = serde_json::value::to_raw_value(&self)?;
89			Ok(Some(json))
90		}
91	};
92}
93
94impl ToRpcParams for serde_json::Map<String, serde_json::Value> {
95	to_rpc_params_impl!();
96}
97
98impl<P: Serialize> ToRpcParams for &[P] {
99	to_rpc_params_impl!();
100}
101
102impl<P: Serialize> ToRpcParams for Vec<P> {
103	to_rpc_params_impl!();
104}
105impl<P, const N: usize> ToRpcParams for [P; N]
106where
107	[P; N]: Serialize,
108{
109	to_rpc_params_impl!();
110}
111
112macro_rules! tuple_impls {
113	($($len:expr => ($($n:tt $name:ident)+))+) => {
114		$(
115			impl<$($name: Serialize),+> ToRpcParams for ($($name,)+) {
116				to_rpc_params_impl!();
117			}
118		)+
119	}
120}
121
122tuple_impls! {
123	1 => (0 T0)
124	2 => (0 T0 1 T1)
125	3 => (0 T0 1 T1 2 T2)
126	4 => (0 T0 1 T1 2 T2 3 T3)
127	5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
128	6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
129	7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
130	8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
131	9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
132	10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
133	11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
134	12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
135	13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
136	14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
137	15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
138	16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
139}
140
141/// Trait to generate subscription IDs.
142pub trait IdProvider: Send + Sync + std::fmt::Debug {
143	/// Returns the next ID for the subscription.
144	fn next_id(&self) -> SubscriptionId<'static>;
145}
146
147// Implement `IdProvider` for `Box<T>`
148//
149// It's not implemented for `&'_ T` because
150// of the required `'static lifetime`
151// Thus, `&dyn IdProvider` won't work.
152impl<T: IdProvider + ?Sized> IdProvider for Box<T> {
153	fn next_id(&self) -> SubscriptionId<'static> {
154		(**self).next_id()
155	}
156}
157
158/// Interface for types that can be serialized into JSON.
159pub trait ToJson {
160	/// Convert the type into a JSON value.
161	fn to_json(&self) -> Result<Box<RawValue>, serde_json::Error>;
162}