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
66mod 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#[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#[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}