referrerpolicy=no-referrer-when-downgrade

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_types = Vec::new();
32	let mut cfg_attrs = Vec::new();
33	for decl in pallet_decls {
34		if decl.find_part("Task").is_none() {
35			continue
36		}
37
38		let variant_name = &decl.name;
39		let path = &decl.path;
40		let index = decl.index;
41		let instance = decl.instance.as_ref().map(|instance| quote!(, #path::#instance));
42		let task_type = quote!(#path::Task<#runtime_name #instance>);
43
44		let attr = decl.get_attributes();
45
46		from_impls.push(quote! {
47			#attr
48			impl From<#task_type> for RuntimeTask {
49				fn from(hr: #task_type) -> Self {
50					RuntimeTask::#variant_name(hr)
51				}
52			}
53
54			#attr
55			impl TryInto<#task_type> for RuntimeTask {
56				type Error = ();
57
58				fn try_into(self) -> Result<#task_type, Self::Error> {
59					match self {
60						RuntimeTask::#variant_name(hr) => Ok(hr),
61						_ => Err(()),
62					}
63				}
64			}
65		});
66
67		task_variants.push(quote! {
68			#attr
69			#[codec(index = #index)]
70			#variant_name(#task_type),
71		});
72
73		variant_names.push(quote!(#variant_name));
74
75		task_types.push(task_type);
76
77		cfg_attrs.push(attr);
78	}
79
80	let prelude = quote!(#scrate::traits::tasks::__private);
81
82	const INCOMPLETE_MATCH_QED: &'static str =
83		"cannot have an instantiated RuntimeTask without some Task variant in the runtime. QED";
84
85	let output = quote! {
86		/// An aggregation of all `Task` enums across all pallets included in the current runtime.
87		#[derive(
88			Clone, Eq, PartialEq,
89			#scrate::__private::codec::Encode,
90			#scrate::__private::codec::Decode,
91			#scrate::__private::codec::DecodeWithMemTracking,
92			#scrate::__private::scale_info::TypeInfo,
93			#scrate::__private::RuntimeDebug,
94		)]
95		pub enum RuntimeTask {
96			#( #task_variants )*
97		}
98
99		#[automatically_derived]
100		impl #scrate::traits::Task for RuntimeTask {
101			type Enumeration = #prelude::IntoIter<RuntimeTask>;
102
103			fn is_valid(&self) -> bool {
104				match self {
105					#(
106						#cfg_attrs
107						RuntimeTask::#variant_names(val) => val.is_valid(),
108					)*
109					_ => unreachable!(#INCOMPLETE_MATCH_QED),
110				}
111			}
112
113			fn run(&self) -> Result<(), #scrate::traits::tasks::__private::DispatchError> {
114				match self {
115					#(
116						#cfg_attrs
117						RuntimeTask::#variant_names(val) => val.run(),
118					)*
119					_ => unreachable!(#INCOMPLETE_MATCH_QED),
120				}
121			}
122
123			fn weight(&self) -> #scrate::pallet_prelude::Weight {
124				match self {
125					#(
126						#cfg_attrs
127						RuntimeTask::#variant_names(val) => val.weight(),
128					)*
129					_ => unreachable!(#INCOMPLETE_MATCH_QED),
130				}
131			}
132
133			fn task_index(&self) -> u32 {
134				match self {
135					#(
136						#cfg_attrs
137						RuntimeTask::#variant_names(val) => val.task_index(),
138					)*
139					_ => unreachable!(#INCOMPLETE_MATCH_QED),
140				}
141			}
142
143			fn iter() -> Self::Enumeration {
144				let mut all_tasks = Vec::new();
145				#(
146					#cfg_attrs
147					all_tasks.extend(<#task_types>::iter().map(RuntimeTask::from).collect::<Vec<_>>());
148				)*
149				all_tasks.into_iter()
150			}
151		}
152
153		#( #from_impls )*
154	};
155
156	output
157}