1use crate::{Driver, Pinned, Value, Wrapped};
4use alloc::{boxed::Box, vec::Vec};
5
6pub(crate) struct Directive<'lt> {
8 closure: Box<dyn FnOnce(&mut Driver<'lt, Pinned>) + Send + 'lt>,
11}
12
13impl<'lt> Directive<'lt> {
14 pub(crate) fn new<
16 Tag,
17 Input: 'lt + Wrapped<Tag>,
18 NtsOutput: 'lt + Send + Sync,
19 TsOutput: 'lt + Wrapped<Tag>,
20 >(
21 input: Input,
22 op: impl FnOnce(Input::Unwrapped) -> DirectiveOutput<NtsOutput, TsOutput::Unwrapped>
23 + Send
24 + 'lt,
25 ) -> (Directive<'lt>, Value<(NtsOutput, TsOutput)>) {
26 let (ret_slot, in_slot) = Value::new();
28
29 let closure = Box::new(move |driver: &mut Driver<'lt, Pinned>| {
30 #[cfg(feature = "fallback")]
33 if driver.is_fallback() {
34 let known = driver.known_values();
35
36 unsafe {
38 input.for_each_representative(|value| {
39 if !known.contains(&value) {
40 panic!("unknown value passed to driver: {:X}", value);
41 }
42 });
43 }
44 }
45
46 let unwrapped = unsafe { input.unwrap() };
49
50 let DirectiveOutput {
52 thread_safe_value,
53 thread_unsafe_value,
54 deleted_values,
55 } = op(unwrapped);
56
57 let ts_out = unsafe { TsOutput::wrap(thread_unsafe_value) };
59
60 #[cfg(feature = "fallback")]
62 {
63 let known = driver.known_values_mut();
64
65 deleted_values.into_iter().for_each(|value| {
66 known.remove(&value);
67 });
68
69 unsafe {
71 ts_out.for_each_representative(|value| {
72 known.insert(value);
73 });
74 }
75 }
76
77 in_slot.put((thread_safe_value, ts_out));
79 });
80
81 (Self { closure }, ret_slot)
82 }
83
84 pub(crate) fn run(self, driver: &mut Driver<'lt, Pinned>) {
85 (self.closure)(driver);
86 }
87}
88
89pub struct DirectiveOutput<NtsOutput, TsOutput> {
91 pub thread_safe_value: NtsOutput,
93 pub thread_unsafe_value: TsOutput,
95 pub deleted_values: Vec<usize>,
97}