1use alloc::borrow::Cow;
2
3use super::{IntoSystem, ReadOnlySystem, System};
4use crate::{
5 schedule::InternedSystemSet,
6 system::{input::SystemInput, SystemIn},
7 world::unsafe_world_cell::UnsafeWorldCell,
8};
9
10#[diagnostic::on_unimplemented(
47 message = "`{Self}` can not adapt a system of type `{S}`",
48 label = "invalid system adapter"
49)]
50pub trait Adapt<S: System>: Send + Sync + 'static {
51 type In: SystemInput;
53 type Out;
55
56 fn adapt(
59 &mut self,
60 input: <Self::In as SystemInput>::Inner<'_>,
61 run_system: impl FnOnce(SystemIn<'_, S>) -> S::Out,
62 ) -> Self::Out;
63}
64
65#[derive(Clone)]
67pub struct IntoAdapterSystem<Func, S> {
68 func: Func,
69 system: S,
70}
71
72impl<Func, S> IntoAdapterSystem<Func, S> {
73 pub const fn new(func: Func, system: S) -> Self {
75 Self { func, system }
76 }
77}
78
79#[doc(hidden)]
80pub struct IsAdapterSystemMarker;
81
82impl<Func, S, I, O, M> IntoSystem<Func::In, Func::Out, (IsAdapterSystemMarker, I, O, M)>
83 for IntoAdapterSystem<Func, S>
84where
85 Func: Adapt<S::System>,
86 I: SystemInput,
87 S: IntoSystem<I, O, M>,
88{
89 type System = AdapterSystem<Func, S::System>;
90
91 fn into_system(this: Self) -> Self::System {
93 let system = IntoSystem::into_system(this.system);
94 let name = system.name();
95 AdapterSystem::new(this.func, system, name)
96 }
97}
98
99#[derive(Clone)]
101pub struct AdapterSystem<Func, S> {
102 func: Func,
103 system: S,
104 name: Cow<'static, str>,
105}
106
107impl<Func, S> AdapterSystem<Func, S>
108where
109 Func: Adapt<S>,
110 S: System,
111{
112 pub const fn new(func: Func, system: S, name: Cow<'static, str>) -> Self {
114 Self { func, system, name }
115 }
116}
117
118impl<Func, S> System for AdapterSystem<Func, S>
119where
120 Func: Adapt<S>,
121 S: System,
122{
123 type In = Func::In;
124 type Out = Func::Out;
125
126 fn name(&self) -> Cow<'static, str> {
127 self.name.clone()
128 }
129
130 fn component_access(&self) -> &crate::query::Access<crate::component::ComponentId> {
131 self.system.component_access()
132 }
133
134 #[inline]
135 fn archetype_component_access(
136 &self,
137 ) -> &crate::query::Access<crate::archetype::ArchetypeComponentId> {
138 self.system.archetype_component_access()
139 }
140
141 fn is_send(&self) -> bool {
142 self.system.is_send()
143 }
144
145 fn is_exclusive(&self) -> bool {
146 self.system.is_exclusive()
147 }
148
149 fn has_deferred(&self) -> bool {
150 self.system.has_deferred()
151 }
152
153 #[inline]
154 unsafe fn run_unsafe(
155 &mut self,
156 input: SystemIn<'_, Self>,
157 world: UnsafeWorldCell,
158 ) -> Self::Out {
159 self.func.adapt(input, |input| unsafe {
161 self.system.run_unsafe(input, world)
162 })
163 }
164
165 #[inline]
166 fn run(&mut self, input: SystemIn<'_, Self>, world: &mut crate::prelude::World) -> Self::Out {
167 self.func
168 .adapt(input, |input| self.system.run(input, world))
169 }
170
171 #[inline]
172 fn apply_deferred(&mut self, world: &mut crate::prelude::World) {
173 self.system.apply_deferred(world);
174 }
175
176 #[inline]
177 fn queue_deferred(&mut self, world: crate::world::DeferredWorld) {
178 self.system.queue_deferred(world);
179 }
180
181 #[inline]
182 unsafe fn validate_param_unsafe(&mut self, world: UnsafeWorldCell) -> bool {
183 unsafe { self.system.validate_param_unsafe(world) }
185 }
186
187 fn initialize(&mut self, world: &mut crate::prelude::World) {
188 self.system.initialize(world);
189 }
190
191 #[inline]
192 fn update_archetype_component_access(&mut self, world: UnsafeWorldCell) {
193 self.system.update_archetype_component_access(world);
194 }
195
196 fn check_change_tick(&mut self, change_tick: crate::component::Tick) {
197 self.system.check_change_tick(change_tick);
198 }
199
200 fn default_system_sets(&self) -> Vec<InternedSystemSet> {
201 self.system.default_system_sets()
202 }
203
204 fn get_last_run(&self) -> crate::component::Tick {
205 self.system.get_last_run()
206 }
207
208 fn set_last_run(&mut self, last_run: crate::component::Tick) {
209 self.system.set_last_run(last_run);
210 }
211}
212
213unsafe impl<Func, S> ReadOnlySystem for AdapterSystem<Func, S>
215where
216 Func: Adapt<S>,
217 S: ReadOnlySystem,
218{
219}
220
221impl<F, S, Out> Adapt<S> for F
222where
223 F: Send + Sync + 'static + FnMut(S::Out) -> Out,
224 S: System,
225{
226 type In = S::In;
227 type Out = Out;
228
229 fn adapt(
230 &mut self,
231 input: <Self::In as SystemInput>::Inner<'_>,
232 run_system: impl FnOnce(SystemIn<'_, S>) -> S::Out,
233 ) -> Out {
234 self(run_system(input))
235 }
236}