orml_traits/
parameters.rs

1#[doc(hidden)]
2pub use frame_support;
3use frame_support::Parameter;
4#[doc(hidden)]
5pub use parity_scale_codec;
6#[doc(hidden)]
7pub use paste;
8#[doc(hidden)]
9pub use scale_info;
10#[doc(hidden)]
11pub use sp_runtime;
12
13pub trait RuntimeParameterStore {
14	type AggregratedKeyValue: AggregratedKeyValue;
15
16	fn get<KV, K>(key: K) -> Option<K::Value>
17	where
18		KV: AggregratedKeyValue,
19		K: Key + Into<<KV as AggregratedKeyValue>::AggregratedKey>,
20		<KV as AggregratedKeyValue>::AggregratedKey:
21			Into2<<<Self as RuntimeParameterStore>::AggregratedKeyValue as AggregratedKeyValue>::AggregratedKey>,
22		<<Self as RuntimeParameterStore>::AggregratedKeyValue as AggregratedKeyValue>::AggregratedValue:
23			TryInto2<<KV as AggregratedKeyValue>::AggregratedValue>,
24		<KV as AggregratedKeyValue>::AggregratedValue: TryInto<K::WrappedValue>;
25}
26
27pub trait Key {
28	type Value;
29	type WrappedValue: Into<Self::Value>;
30}
31
32pub trait AggregratedKeyValue: Parameter {
33	type AggregratedKey: Parameter + parity_scale_codec::MaxEncodedLen;
34	type AggregratedValue: Parameter + parity_scale_codec::MaxEncodedLen;
35
36	fn into_parts(self) -> (Self::AggregratedKey, Option<Self::AggregratedValue>);
37}
38
39pub trait ParameterStore<KV: AggregratedKeyValue> {
40	fn get<K>(key: K) -> Option<K::Value>
41	where
42		K: Key + Into<<KV as AggregratedKeyValue>::AggregratedKey>,
43		<KV as AggregratedKeyValue>::AggregratedValue: TryInto<K::WrappedValue>;
44}
45
46pub struct ParameterStoreAdapter<PS, KV>(sp_std::marker::PhantomData<(PS, KV)>);
47
48impl<PS, KV> ParameterStore<KV> for ParameterStoreAdapter<PS, KV>
49where
50	PS: RuntimeParameterStore,
51	KV: AggregratedKeyValue,
52	<KV as AggregratedKeyValue>::AggregratedKey:
53		Into2<<<PS as RuntimeParameterStore>::AggregratedKeyValue as AggregratedKeyValue>::AggregratedKey>,
54	<KV as AggregratedKeyValue>::AggregratedValue:
55		TryFrom2<<<PS as RuntimeParameterStore>::AggregratedKeyValue as AggregratedKeyValue>::AggregratedValue>,
56{
57	fn get<K>(key: K) -> Option<K::Value>
58	where
59		K: Key + Into<<KV as AggregratedKeyValue>::AggregratedKey>,
60		<KV as AggregratedKeyValue>::AggregratedValue: TryInto<K::WrappedValue>,
61	{
62		PS::get::<KV, K>(key)
63	}
64}
65
66// workaround for rust bug https://github.com/rust-lang/rust/issues/51445
67mod workaround {
68	pub trait From2<T>: Sized {
69		#[must_use]
70		fn from2(value: T) -> Self;
71	}
72
73	pub trait Into2<T>: Sized {
74		#[must_use]
75		fn into2(self) -> T;
76	}
77
78	impl<T, U> Into2<U> for T
79	where
80		U: From2<T>,
81	{
82		#[inline]
83		fn into2(self) -> U {
84			U::from2(self)
85		}
86	}
87
88	pub trait TryInto2<T>: Sized {
89		type Error;
90
91		fn try_into2(self) -> Result<T, Self::Error>;
92	}
93
94	pub trait TryFrom2<T>: Sized {
95		type Error;
96
97		fn try_from2(value: T) -> Result<Self, Self::Error>;
98	}
99
100	impl<T, U> TryInto2<U> for T
101	where
102		U: TryFrom2<T>,
103	{
104		type Error = U::Error;
105
106		#[inline]
107		fn try_into2(self) -> Result<U, U::Error> {
108			U::try_from2(self)
109		}
110	}
111}
112pub use workaround::*;
113
114/// Define parameters key value types.
115/// Example:
116///
117/// ```
118/// # #[macro_use]
119/// # extern crate orml_traits;
120/// # fn main() {}
121/// define_parameters! {
122///     pub Pallet = {
123///         Key1: u64 = 0,
124///         Key2(u32): u32 = 1,
125///         Key3((u8, u8)): u128 = 2,
126///     }
127/// }
128/// ```
129#[macro_export]
130macro_rules! define_parameters {
131	(
132		$vis:vis $name:ident = {
133			$(
134				$key_name:ident $( ($key_para: ty) )? : $value_type:ty = $index:expr
135			),+ $(,)?
136		}
137	) => {
138		$crate::parameters::paste::item! {
139			#[derive(
140				Clone,
141				PartialEq,
142				Eq,
143				$crate::parameters::parity_scale_codec::Encode,
144				$crate::parameters::parity_scale_codec::Decode,
145				$crate::parameters::parity_scale_codec::MaxEncodedLen,
146				$crate::parameters::sp_runtime::RuntimeDebug,
147				$crate::parameters::scale_info::TypeInfo,
148				$crate::parameters::parity_scale_codec::DecodeWithMemTracking
149			)]
150			$vis enum $name {
151				$(
152					#[codec(index = $index)]
153					$key_name($key_name, Option<$value_type>),
154				)*
155			}
156
157			#[derive(
158				Clone,
159				PartialEq,
160				Eq,
161				$crate::parameters::parity_scale_codec::Encode,
162				$crate::parameters::parity_scale_codec::Decode,
163				$crate::parameters::parity_scale_codec::MaxEncodedLen,
164				$crate::parameters::sp_runtime::RuntimeDebug,
165				$crate::parameters::scale_info::TypeInfo,
166				$crate::parameters::parity_scale_codec::DecodeWithMemTracking
167			)]
168			$vis enum [<$name Key>] {
169				$(
170					#[codec(index = $index)]
171					$key_name($key_name),
172				)*
173			}
174
175			#[derive(
176				Clone,
177				PartialEq,
178				Eq,
179				$crate::parameters::parity_scale_codec::Encode,
180				$crate::parameters::parity_scale_codec::Decode,
181				$crate::parameters::parity_scale_codec::MaxEncodedLen,
182				$crate::parameters::sp_runtime::RuntimeDebug,
183				$crate::parameters::scale_info::TypeInfo,
184				$crate::parameters::parity_scale_codec::DecodeWithMemTracking
185			)]
186			$vis enum [<$name Value>] {
187				$(
188					#[codec(index = $index)]
189					$key_name($value_type),
190				)*
191			}
192
193			impl $crate::parameters::AggregratedKeyValue for $name {
194				type AggregratedKey = [<$name Key>];
195				type AggregratedValue = [<$name Value>];
196
197				fn into_parts(self) -> (Self::AggregratedKey, Option<Self::AggregratedValue>) {
198					match self {
199						$(
200							$name::$key_name(key, value) => ([<$name Key>]::$key_name(key), value.map([<$name Value>]::$key_name)),
201						)*
202					}
203				}
204			}
205
206			$(
207				#[derive(
208					Clone,
209					PartialEq,
210					Eq,
211					$crate::parameters::parity_scale_codec::Encode,
212					$crate::parameters::parity_scale_codec::Decode,
213					$crate::parameters::parity_scale_codec::MaxEncodedLen,
214					$crate::parameters::sp_runtime::RuntimeDebug,
215					$crate::parameters::scale_info::TypeInfo,
216					$crate::parameters::parity_scale_codec::DecodeWithMemTracking
217				)]
218				$vis struct $key_name $( (pub $key_para) )?;
219
220				impl $crate::parameters::Key for $key_name {
221					type Value = $value_type;
222					type WrappedValue = [<$key_name Value>];
223				}
224
225				impl From<$key_name> for [<$name Key>] {
226					fn from(key: $key_name) -> Self {
227						[<$name Key>]::$key_name(key)
228					}
229				}
230
231				impl TryFrom<[<$name Key>]> for $key_name {
232					type Error = ();
233
234					fn try_from(key: [<$name Key>]) -> Result<Self, Self::Error> {
235						match key {
236							[<$name Key>]::$key_name(key) => Ok(key),
237							_ => Err(()),
238						}
239					}
240				}
241
242				#[derive(
243					Clone,
244					PartialEq,
245					Eq,
246					$crate::parameters::sp_runtime::RuntimeDebug
247				)]
248				$vis struct [<$key_name Value>](pub $value_type);
249
250				impl From<[<$key_name Value>]> for [<$name Value>] {
251					fn from(value: [<$key_name Value>]) -> Self {
252						[<$name Value>]::$key_name(value.0)
253					}
254				}
255
256				impl From<($key_name, $value_type)> for $name {
257					fn from((key, value): ($key_name, $value_type)) -> Self {
258						$name::$key_name(key, Some(value))
259					}
260				}
261
262				impl From<$key_name> for $name {
263					fn from(key: $key_name) -> Self {
264						$name::$key_name(key, None)
265					}
266				}
267
268				impl TryFrom<[<$name Value>]> for [<$key_name Value>] {
269					type Error = ();
270
271					fn try_from(value: [<$name Value>]) -> Result<Self, Self::Error> {
272						match value {
273							[<$name Value>]::$key_name(value) => Ok([<$key_name Value>](value)),
274							_ => Err(()),
275						}
276					}
277				}
278
279				impl From<[<$key_name Value>]> for $value_type {
280					fn from(value: [<$key_name Value>]) -> Self {
281						value.0
282					}
283				}
284			)*
285		}
286	};
287}
288
289/// Define aggregated parameters types.
290///
291/// Example:
292/// ```
293/// # #[macro_use]
294/// # extern crate orml_traits;
295/// # fn main() {}
296/// mod pallet1 {
297///     define_parameters! {
298///         pub Pallet = {
299///             Key1: u64 = 0,
300///             Key2(u32): u32 = 1,
301///             Key3((u8, u8)): u128 = 2,
302///         }
303///     }
304/// }
305///
306/// mod pallet2 {
307///     define_parameters! {
308///         pub Pallet = {
309///             Key1: u64 = 0,
310///             Key2(u32): u32 = 1,
311///             Key3((u8, u8)): u128 = 2,
312///         }
313///     }
314/// }
315///
316/// define_aggregrated_parameters! {
317///     pub AggregratedPallet = {
318///         Pallet1: pallet1::Pallet = 0,
319///         Pallet2: pallet2::Pallet = 1,
320///     }
321/// }
322/// ```
323#[macro_export]
324macro_rules! define_aggregrated_parameters {
325	(
326		$vis:vis $name:ident = {
327			$(
328				$parameter_name:ident: $parameter_type:ty = $index:expr
329			),+ $(,)?
330		}
331	) => {
332		$crate::parameters::paste::item! {
333			#[derive(
334				Clone,
335				PartialEq,
336				Eq,
337				$crate::parameters::parity_scale_codec::Encode,
338				$crate::parameters::parity_scale_codec::Decode,
339				$crate::parameters::parity_scale_codec::MaxEncodedLen,
340				$crate::parameters::sp_runtime::RuntimeDebug,
341				$crate::parameters::scale_info::TypeInfo,
342				$crate::parameters::parity_scale_codec::DecodeWithMemTracking
343			)]
344			$vis enum $name {
345				$(
346					#[codec(index = $index)]
347					$parameter_name($parameter_type),
348				)*
349			}
350
351			#[derive(
352				Clone,
353				PartialEq,
354				Eq,
355				$crate::parameters::parity_scale_codec::Encode,
356				$crate::parameters::parity_scale_codec::Decode,
357				$crate::parameters::parity_scale_codec::MaxEncodedLen,
358				$crate::parameters::sp_runtime::RuntimeDebug,
359				$crate::parameters::scale_info::TypeInfo,
360				$crate::parameters::parity_scale_codec::DecodeWithMemTracking
361			)]
362			$vis enum [<$name Key>] {
363				$(
364					#[codec(index = $index)]
365					$parameter_name(<$parameter_type as $crate::parameters::AggregratedKeyValue>::AggregratedKey),
366				)*
367			}
368
369			#[derive(
370				Clone,
371				PartialEq,
372				Eq,
373				$crate::parameters::parity_scale_codec::Encode,
374				$crate::parameters::parity_scale_codec::Decode,
375				$crate::parameters::parity_scale_codec::MaxEncodedLen,
376				$crate::parameters::sp_runtime::RuntimeDebug,
377				$crate::parameters::scale_info::TypeInfo,
378				$crate::parameters::parity_scale_codec::DecodeWithMemTracking
379			)]
380			$vis enum [<$name Value>] {
381				$(
382					#[codec(index = $index)]
383					$parameter_name(<$parameter_type as $crate::parameters::AggregratedKeyValue>::AggregratedValue),
384				)*
385			}
386
387			impl $crate::parameters::AggregratedKeyValue for $name {
388				type AggregratedKey = [<$name Key>];
389				type AggregratedValue = [<$name Value>];
390
391				fn into_parts(self) -> (Self::AggregratedKey, Option<Self::AggregratedValue>) {
392					match self {
393						$(
394							$name::$parameter_name(parameter) => {
395								let (key, value) = parameter.into_parts();
396								([<$name Key>]::$parameter_name(key), value.map([<$name Value>]::$parameter_name))
397							},
398						)*
399					}
400				}
401			}
402
403			$(
404				impl $crate::parameters::From2<<$parameter_type as $crate::parameters::AggregratedKeyValue>::AggregratedKey> for [<$name Key>] {
405					fn from2(key: <$parameter_type as $crate::parameters::AggregratedKeyValue>::AggregratedKey) -> Self {
406						[<$name Key>]::$parameter_name(key)
407					}
408				}
409
410				impl $crate::parameters::TryFrom2<[<$name Value>]> for <$parameter_type as $crate::parameters::AggregratedKeyValue>::AggregratedValue {
411					type Error = ();
412
413					fn try_from2(value: [<$name Value>]) -> Result<Self, Self::Error> {
414						match value {
415							[<$name Value>]::$parameter_name(value) => Ok(value),
416							_ => Err(()),
417						}
418					}
419				}
420			)*
421		}
422	};
423}
424
425#[cfg(test)]
426mod tests {
427	pub mod pallet1 {
428		define_parameters! {
429			pub Parameters = {
430				Key1: u64 = 0,
431				Key2(u32): u32 = 1,
432				Key3((u8, u8)): u128 = 2,
433			}
434		}
435	}
436	pub mod pallet2 {
437		define_parameters! {
438			pub Parameters = {
439				Key1: u64 = 0,
440				Key2(u32): u32 = 2,
441				Key3((u8, u8)): u128 = 4,
442			}
443		}
444	}
445	define_aggregrated_parameters! {
446		pub RuntimeParameters = {
447			Pallet1: pallet1::Parameters = 0,
448			Pallet2: pallet2::Parameters = 3,
449		}
450	}
451
452	#[test]
453	fn test_define_parameters_key_convert() {
454		let key1 = pallet1::Key1;
455		let parameter_key: pallet1::ParametersKey = key1.clone().into();
456		let key1_2: pallet1::Key1 = parameter_key.clone().try_into().unwrap();
457
458		assert_eq!(key1, key1_2);
459		assert_eq!(parameter_key, pallet1::ParametersKey::Key1(key1));
460
461		let key2 = pallet1::Key2(1);
462		let parameter_key: pallet1::ParametersKey = key2.clone().into();
463		let key2_2: pallet1::Key2 = parameter_key.clone().try_into().unwrap();
464
465		assert_eq!(key2, key2_2);
466		assert_eq!(parameter_key, pallet1::ParametersKey::Key2(key2));
467	}
468
469	#[test]
470	fn test_define_parameters_value_convert() {
471		let value1 = pallet1::Key1Value(1);
472		let parameter_value: pallet1::ParametersValue = value1.clone().into();
473		let value1_2: pallet1::Key1Value = parameter_value.clone().try_into().unwrap();
474
475		assert_eq!(value1, value1_2);
476		assert_eq!(parameter_value, pallet1::ParametersValue::Key1(1));
477
478		let value2 = pallet1::Key2Value(2);
479		let parameter_value: pallet1::ParametersValue = value2.clone().into();
480		let value2_2: pallet1::Key2Value = parameter_value.clone().try_into().unwrap();
481
482		assert_eq!(value2, value2_2);
483		assert_eq!(parameter_value, pallet1::ParametersValue::Key2(2));
484	}
485
486	#[test]
487	fn test_define_parameters_aggregrated_key_value() {
488		use crate::parameters::AggregratedKeyValue;
489
490		let kv1 = pallet1::Parameters::Key1(pallet1::Key1, None);
491		let (key1, value1) = kv1.clone().into_parts();
492
493		assert_eq!(key1, pallet1::ParametersKey::Key1(pallet1::Key1));
494		assert_eq!(value1, None);
495
496		let kv2 = pallet1::Parameters::Key2(pallet1::Key2(1), Some(2));
497		let (key2, value2) = kv2.clone().into_parts();
498
499		assert_eq!(key2, pallet1::ParametersKey::Key2(pallet1::Key2(1)));
500		assert_eq!(value2, Some(pallet1::ParametersValue::Key2(2)));
501	}
502
503	#[test]
504	fn test_define_aggregrated_parameters_key_convert() {
505		use crate::parameters::workaround::Into2;
506		use parity_scale_codec::Encode;
507
508		let key1 = pallet1::Key1;
509		let parameter_key: pallet1::ParametersKey = key1.clone().into();
510		let runtime_key: RuntimeParametersKey = parameter_key.clone().into2();
511
512		assert_eq!(
513			runtime_key,
514			RuntimeParametersKey::Pallet1(pallet1::ParametersKey::Key1(key1))
515		);
516		assert_eq!(runtime_key.encode(), vec![0, 0]);
517
518		let key2 = pallet2::Key2(1);
519		let parameter_key: pallet2::ParametersKey = key2.clone().into();
520		let runtime_key: RuntimeParametersKey = parameter_key.clone().into2();
521
522		assert_eq!(
523			runtime_key,
524			RuntimeParametersKey::Pallet2(pallet2::ParametersKey::Key2(key2))
525		);
526		assert_eq!(runtime_key.encode(), vec![3, 2, 1, 0, 0, 0]);
527	}
528
529	#[test]
530	fn test_define_aggregrated_parameters_aggregrated_key_value() {
531		use crate::parameters::AggregratedKeyValue;
532
533		let kv1 = RuntimeParameters::Pallet1(pallet1::Parameters::Key1(pallet1::Key1, None));
534		let (key1, value1) = kv1.clone().into_parts();
535
536		assert_eq!(
537			key1,
538			RuntimeParametersKey::Pallet1(pallet1::ParametersKey::Key1(pallet1::Key1))
539		);
540		assert_eq!(value1, None);
541
542		let kv2 = RuntimeParameters::Pallet2(pallet2::Parameters::Key2(pallet2::Key2(1), Some(2)));
543		let (key2, value2) = kv2.clone().into_parts();
544
545		assert_eq!(
546			key2,
547			RuntimeParametersKey::Pallet2(pallet2::ParametersKey::Key2(pallet2::Key2(1)))
548		);
549		assert_eq!(
550			value2,
551			Some(RuntimeParametersValue::Pallet2(pallet2::ParametersValue::Key2(2)))
552		);
553	}
554}