vyre_libs/parsing/c/preprocess/gpu_pipeline/
dispatch.rs1use vyre_foundation::ir::Program;
2
3pub trait ProgramOracle {
9 fn dispatch(&self, program: &Program, inputs: &[Vec<u8>]) -> Result<Vec<Vec<u8>>, String>;
11
12 fn dispatch_borrowed(
17 &self,
18 program: &Program,
19 inputs: &[&[u8]],
20 ) -> Result<Vec<Vec<u8>>, String> {
21 let owned: Vec<Vec<u8>> = inputs.iter().map(|slice| slice.to_vec()).collect();
22 ProgramOracle::dispatch(self, program, &owned)
23 }
24
25 fn dispatch_borrowed_into(
30 &self,
31 program: &Program,
32 inputs: &[&[u8]],
33 outputs: &mut Vec<Vec<u8>>,
34 ) -> Result<(), String> {
35 let result = self.dispatch_borrowed(program, inputs)?;
36 replace_outputs_preserving_slots(outputs, result);
37 Ok(())
38 }
39
40 fn requires_output_inputs(&self) -> bool {
46 false
47 }
48}
49
50fn replace_outputs_preserving_slots(outputs: &mut Vec<Vec<u8>>, result: Vec<Vec<u8>>) {
51 let mut incoming = result.into_iter();
52 let mut reused = 0usize;
53 for (slot, mut next) in outputs.iter_mut().zip(incoming.by_ref()) {
54 if next.len() <= slot.capacity() {
55 slot.clear();
56 slot.extend_from_slice(&next);
57 } else {
58 std::mem::swap(slot, &mut next);
59 }
60 reused += 1;
61 }
62 outputs.truncate(reused);
63 outputs.extend(incoming);
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn replace_outputs_preserving_slots_reuses_retained_buffers() {
72 let mut outputs = vec![Vec::with_capacity(16), Vec::with_capacity(8)];
73 outputs[0].extend_from_slice(&[9, 9]);
74 outputs[1].extend_from_slice(&[8]);
75 let outer_ptr = outputs.as_ptr() as usize;
76 let first_ptr = outputs[0].as_ptr() as usize;
77 let second_ptr = outputs[1].as_ptr() as usize;
78
79 replace_outputs_preserving_slots(&mut outputs, vec![vec![1, 2, 3], vec![4]]);
80
81 assert_eq!(outputs, vec![vec![1, 2, 3], vec![4]]);
82 assert_eq!(outputs.as_ptr() as usize, outer_ptr);
83 assert_eq!(outputs[0].as_ptr() as usize, first_ptr);
84 assert_eq!(outputs[1].as_ptr() as usize, second_ptr);
85 }
86
87 #[test]
88 fn replace_outputs_preserving_slots_moves_oversized_buffers() {
89 let mut outputs = vec![Vec::with_capacity(1)];
90 outputs[0].push(9);
91 let incoming = vec![vec![1, 2, 3, 4]];
92 let incoming_ptr = incoming[0].as_ptr() as usize;
93
94 replace_outputs_preserving_slots(&mut outputs, incoming);
95
96 assert_eq!(outputs, vec![vec![1, 2, 3, 4]]);
97 assert_eq!(
98 outputs[0].as_ptr() as usize,
99 incoming_ptr,
100 "Fix: oversized C-preprocessor GPU outputs must be moved into retained slots instead of copied through too-small buffers."
101 );
102 }
103}