1pub mod bindings;
2pub mod internal;
3pub mod marshal;
4
5use std::marker::PhantomData;
6
7pub struct Program<T> {
8 prog: internal::Program,
9 _marker: PhantomData<T>,
10}
11
12pub struct Input;
14pub struct Output;
15pub struct InputOutput;
16
17pub trait Fact<Prog> {
18 type DIRECTION: Direction;
19 const COLUMN_COUNT: u32;
20 const FACT_NAME: &'static str;
21}
22
23impl<P> Program<P> {
24 pub fn new(_handle: P) -> Self {
25 Self {
26 prog: internal::Program::new(),
27 _marker: PhantomData,
28 }
29 }
30
31 pub fn run(&mut self) {
32 self.prog.run()
33 }
34
35 pub fn get_facts<FactType>(&mut self) -> ReadBufferIterator<FactType>
39 where
40 PhantomData<FactType>: Fact<P>,
41 <PhantomData<FactType> as Fact<P>>::DIRECTION: IsOutput,
42 {
43 let name = <PhantomData<FactType> as Fact<P>>::FACT_NAME;
44 let fact_type_idx = self.prog.encode_string(name).0;
45 ReadBufferIterator::new(&self.prog, fact_type_idx)
46 }
47
48 pub fn add_fact<FactType>(&mut self, fact: FactType)
49 where
50 PhantomData<FactType>: Fact<P>,
51 <PhantomData<FactType> as Fact<P>>::DIRECTION: IsInput,
52 FactType: marshal::Marshal,
53 {
54 let name = <PhantomData<FactType> as Fact<P>>::FACT_NAME;
55 let column_count = <PhantomData<FactType> as Fact<P>>::COLUMN_COUNT;
56 let fact_type_idx = self.prog.encode_string(name).0;
57
58 let mut vec: Vec<u32> = Vec::with_capacity(column_count as usize);
60 let buf_ptr = vec.as_mut_ptr();
61 let mut cursor = marshal::WriteCursor::new(&mut self.prog, buf_ptr);
62 fact.serialize(&mut cursor);
63 self.prog.add_fact(fact_type_idx, buf_ptr);
64 }
65
66 pub fn add_facts<FactType, Iter>(&mut self, facts: Iter)
67 where
68 Iter: ExactSizeIterator<Item = FactType>,
69 FactType: marshal::Marshal,
70 PhantomData<FactType>: Fact<P>,
71 <PhantomData<FactType> as Fact<P>>::DIRECTION: IsInput,
72 {
73 let name = <PhantomData<FactType> as Fact<P>>::FACT_NAME;
74 let fact_type_idx = self.prog.encode_string(name).0;
75 let fact_count = facts.len();
76 let column_count = <PhantomData<FactType> as Fact<P>>::COLUMN_COUNT as usize;
77 let vec_size = fact_count * column_count;
78
79 let mut vec: Vec<u32> = Vec::with_capacity(vec_size);
80 let buf_ptr = vec.as_mut_ptr();
81 let mut cursor = marshal::WriteCursor::new(&mut self.prog, buf_ptr);
82 for fact in facts {
83 fact.serialize(&mut cursor);
84 }
85
86 self.prog.add_facts(fact_type_idx, buf_ptr, fact_count);
87 }
88}
89
90pub struct ReadBufferIterator<'a, T> {
91 cursor: marshal::ReadCursor<'a>,
92 count: usize,
93 current: usize,
94 _buf: internal::Buffer, _marker: PhantomData<T>,
96}
97
98impl<'a, T> ReadBufferIterator<'a, T> {
99 fn new(prog: &'a internal::Program, fact_type_idx: u32) -> Self {
100 let count = prog.fact_count(fact_type_idx);
101 let buf = prog.get_facts(fact_type_idx);
102 let buf_ptr = buf.ptr;
103 Self {
104 cursor: marshal::ReadCursor::new(prog, buf_ptr),
105 count,
106 current: 0,
107 _buf: buf,
108 _marker: PhantomData,
109 }
110 }
111}
112
113impl<'a, T: marshal::Marshal> Iterator for ReadBufferIterator<'a, T> {
114 type Item = T;
115
116 fn next(&mut self) -> Option<T> {
117 if self.count == self.current {
118 None
119 } else {
120 let unmarshalled = marshal::Marshal::deserialize(&mut self.cursor);
121 self.current += 1;
122 Some(unmarshalled)
123 }
124 }
125
126 fn size_hint(&self) -> (usize, Option<usize>) {
127 let count = self.len();
128 (count, Some(count))
129 }
130}
131
132impl<'a, T: marshal::Marshal> ExactSizeIterator for ReadBufferIterator<'a, T> {
133 fn len(&self) -> usize {
134 self.count
135 }
136}
137
138pub trait Direction: sealed::Direction {}
140impl Direction for Input {}
141impl Direction for Output {}
142impl Direction for InputOutput {}
143
144pub trait IsInput: sealed::IsInput {}
145impl IsInput for Input {}
146impl IsInput for InputOutput {}
147
148pub trait IsOutput: sealed::IsOutput {}
149impl IsOutput for Output {}
150impl IsOutput for InputOutput {}
151
152mod sealed {
153 pub trait Direction {}
155 impl Direction for super::Input {}
156 impl Direction for super::Output {}
157 impl Direction for super::InputOutput {}
158
159 pub trait IsInput {}
160 impl IsInput for super::Input {}
161 impl IsInput for super::InputOutput {}
162
163 pub trait IsOutput {}
164 impl IsOutput for super::Output {}
165 impl IsOutput for super::InputOutput {}
166}