dfir_rs/scheduled/handoff/
handoff_list.rs1use std::any::Any;
4
5use ref_cast::RefCast;
6use sealed::sealed;
7use variadics::{Variadic, variadic_trait};
8
9use super::Handoff;
10use crate::scheduled::graph::HandoffData;
11use crate::scheduled::port::{Polarity, Port, PortCtx};
12use crate::scheduled::{HandoffId, HandoffTag, SubgraphId};
13use crate::util::slot_vec::SlotVec;
14
15#[sealed]
19pub trait PortList<S>: Variadic
20where
21 S: Polarity,
22{
23 fn set_graph_meta(
34 &self,
35 handoffs: &mut SlotVec<HandoffTag, HandoffData>,
36 out_handoff_ids: &mut Vec<HandoffId>,
37 sg_id: SubgraphId,
38 handoffs_are_preds: bool,
39 );
40
41 type Ctx<'a>: Variadic;
43 unsafe fn make_ctx<'a>(&self, handoffs: &'a SlotVec<HandoffTag, HandoffData>) -> Self::Ctx<'a>;
54
55 fn assert_is_from(&self, handoffs: &SlotVec<HandoffTag, HandoffData>);
57}
58#[sealed]
59impl<S, Rest, H> PortList<S> for (Port<S, H>, Rest)
60where
61 S: Polarity,
62 H: Handoff,
63 Rest: PortList<S>,
64{
65 fn set_graph_meta(
66 &self,
67 handoffs: &mut SlotVec<HandoffTag, HandoffData>,
68 out_handoff_ids: &mut Vec<HandoffId>,
69 sg_id: SubgraphId,
70 handoffs_are_preds: bool,
71 ) {
72 let (this, rest) = self;
73 let this_handoff = &mut handoffs[this.handoff_id];
74
75 out_handoff_ids.extend(if handoffs_are_preds {
79 this_handoff.pred_handoffs.iter().copied()
80 } else {
81 this_handoff.succ_handoffs.iter().copied()
82 });
83
84 if handoffs_are_preds {
86 for succ_hoff in this_handoff.succ_handoffs.clone() {
87 handoffs[succ_hoff].succs.push(sg_id);
88 }
89 } else {
90 for pred_hoff in this_handoff.pred_handoffs.clone() {
91 handoffs[pred_hoff].preds.push(sg_id);
92 }
93 }
94 rest.set_graph_meta(handoffs, out_handoff_ids, sg_id, handoffs_are_preds);
95 }
96
97 type Ctx<'a> = (&'a PortCtx<S, H>, Rest::Ctx<'a>);
98 unsafe fn make_ctx<'a>(&self, handoffs: &'a SlotVec<HandoffTag, HandoffData>) -> Self::Ctx<'a> {
99 let (this, rest) = self;
100 let hoff_any: &dyn Any = &*handoffs.get(this.handoff_id).unwrap().handoff;
101 debug_assert!(hoff_any.is::<H>());
102
103 let handoff = unsafe {
104 &*(hoff_any as *const dyn Any as *const H)
107 };
108
109 let ctx = RefCast::ref_cast(handoff);
110 let ctx_rest = unsafe {
111 rest.make_ctx(handoffs)
113 };
114 (ctx, ctx_rest)
115 }
116
117 fn assert_is_from(&self, handoffs: &SlotVec<HandoffTag, HandoffData>) {
118 let (this, rest) = self;
119 let Some(hoff_data) = handoffs.get(this.handoff_id) else {
120 panic!("Handoff ID {} not found in `handoffs`.", this.handoff_id);
121 };
122 let hoff_any: &dyn Any = &*hoff_data.handoff;
123 assert!(
124 hoff_any.is::<H>(),
125 "Handoff ID {} is not of type {} in `handoffs`.",
126 this.handoff_id,
127 std::any::type_name::<H>(),
128 );
129 rest.assert_is_from(handoffs);
130 }
131}
132#[sealed]
133impl<S> PortList<S> for ()
134where
135 S: Polarity,
136{
137 fn set_graph_meta(
138 &self,
139 _handoffs: &mut SlotVec<HandoffTag, HandoffData>,
140 _out_handoff_ids: &mut Vec<HandoffId>,
141 _sg_id: SubgraphId,
142 _handoffs_are_preds: bool,
143 ) {
144 }
145
146 type Ctx<'a> = ();
147 unsafe fn make_ctx<'a>(
148 &self,
149 _handoffs: &'a SlotVec<HandoffTag, HandoffData>,
150 ) -> Self::Ctx<'a> {
151 }
152
153 fn assert_is_from(&self, _handoffs: &SlotVec<HandoffTag, HandoffData>) {}
154}
155
156#[sealed]
158pub trait PortListSplit<S, A>: PortList<S>
159where
160 S: Polarity,
161 A: PortList<S>,
162{
163 type Suffix: PortList<S>;
165
166 fn split_ctx(ctx: Self::Ctx<'_>) -> (A::Ctx<'_>, <Self::Suffix as PortList<S>>::Ctx<'_>);
168}
169#[sealed]
170impl<S, H, T, U> PortListSplit<S, (Port<S, H>, U)> for (Port<S, H>, T)
171where
172 S: Polarity,
173 H: Handoff,
174 T: PortListSplit<S, U>,
175 U: PortList<S>,
176{
177 type Suffix = T::Suffix;
178
179 fn split_ctx(
180 ctx: Self::Ctx<'_>,
181 ) -> (
182 <(Port<S, H>, U) as PortList<S>>::Ctx<'_>,
183 <Self::Suffix as PortList<S>>::Ctx<'_>,
184 ) {
185 let (x, t) = ctx;
186 let (u, v) = T::split_ctx(t);
187 ((x, u), v)
188 }
189}
190#[sealed]
191impl<S, T> PortListSplit<S, ()> for T
192where
193 S: Polarity,
194 T: PortList<S>,
195{
196 type Suffix = T;
197
198 fn split_ctx(ctx: Self::Ctx<'_>) -> ((), T::Ctx<'_>) {
199 ((), ctx)
200 }
201}
202
203variadic_trait! {
204 #[sealed]
215 pub variadic<T> HandoffList where T: 'static + Handoff {}
216}