frame_support_procedural/construct_runtime/expand/
task.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License
17
18use crate::construct_runtime::Pallet;
19use proc_macro2::{Ident, TokenStream as TokenStream2};
20use quote::quote;
21
22/// Expands aggregate `RuntimeTask` enum.
23pub fn expand_outer_task(
24	runtime_name: &Ident,
25	pallet_decls: &[Pallet],
26	scrate: &TokenStream2,
27) -> TokenStream2 {
28	let mut from_impls = Vec::new();
29	let mut task_variants = Vec::new();
30	let mut variant_names = Vec::new();
31	let mut task_paths = Vec::new();
32	for decl in pallet_decls {
33		if decl.find_part("Task").is_none() {
34			continue
35		}
36
37		let variant_name = &decl.name;
38		let path = &decl.path;
39		let index = decl.index;
40
41		from_impls.push(quote! {
42			impl From<#path::Task<#runtime_name>> for RuntimeTask {
43				fn from(hr: #path::Task<#runtime_name>) -> Self {
44					RuntimeTask::#variant_name(hr)
45				}
46			}
47
48			impl TryInto<#path::Task<#runtime_name>> for RuntimeTask {
49				type Error = ();
50
51				fn try_into(self) -> Result<#path::Task<#runtime_name>, Self::Error> {
52					match self {
53						RuntimeTask::#variant_name(hr) => Ok(hr),
54						_ => Err(()),
55					}
56				}
57			}
58		});
59
60		task_variants.push(quote! {
61			#[codec(index = #index)]
62			#variant_name(#path::Task<#runtime_name>),
63		});
64
65		variant_names.push(quote!(#variant_name));
66
67		task_paths.push(quote!(#path::Task));
68	}
69
70	let prelude = quote!(#scrate::traits::tasks::__private);
71
72	const INCOMPLETE_MATCH_QED: &'static str =
73		"cannot have an instantiated RuntimeTask without some Task variant in the runtime. QED";
74
75	let output = quote! {
76		/// An aggregation of all `Task` enums across all pallets included in the current runtime.
77		#[derive(
78			Clone, Eq, PartialEq,
79			#scrate::__private::codec::Encode,
80			#scrate::__private::codec::Decode,
81			#scrate::__private::scale_info::TypeInfo,
82			#scrate::__private::RuntimeDebug,
83		)]
84		pub enum RuntimeTask {
85			#( #task_variants )*
86		}
87
88		#[automatically_derived]
89		impl #scrate::traits::Task for RuntimeTask {
90			type Enumeration = #prelude::IntoIter<RuntimeTask>;
91
92			fn is_valid(&self) -> bool {
93				match self {
94					#(RuntimeTask::#variant_names(val) => val.is_valid(),)*
95					_ => unreachable!(#INCOMPLETE_MATCH_QED),
96				}
97			}
98
99			fn run(&self) -> Result<(), #scrate::traits::tasks::__private::DispatchError> {
100				match self {
101					#(RuntimeTask::#variant_names(val) => val.run(),)*
102					_ => unreachable!(#INCOMPLETE_MATCH_QED),
103				}
104			}
105
106			fn weight(&self) -> #scrate::pallet_prelude::Weight {
107				match self {
108					#(RuntimeTask::#variant_names(val) => val.weight(),)*
109					_ => unreachable!(#INCOMPLETE_MATCH_QED),
110				}
111			}
112
113			fn task_index(&self) -> u32 {
114				match self {
115					#(RuntimeTask::#variant_names(val) => val.task_index(),)*
116					_ => unreachable!(#INCOMPLETE_MATCH_QED),
117				}
118			}
119
120			fn iter() -> Self::Enumeration {
121				let mut all_tasks = Vec::new();
122				#(all_tasks.extend(#task_paths::iter().map(RuntimeTask::from).collect::<Vec<_>>());)*
123				all_tasks.into_iter()
124			}
125		}
126
127		#( #from_impls )*
128	};
129
130	output
131}