Skip to content

Commit 879e309

Browse files
authored
Merge pull request #788 from TheBlueMatt/2020-02-concrete-bindings
Concretize bindings templates
2 parents c35002f + c2fd683 commit 879e309

File tree

26 files changed

+7560
-3541
lines changed

26 files changed

+7560
-3541
lines changed

c-bindings-gen/src/blocks.rs

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,261 @@ pub fn write_cpp_wrapper(cpp_header_file: &mut File, ty: &str, has_destructor: b
3232
writeln!(cpp_header_file, "}};").unwrap();
3333
}
3434

35+
/// Writes out a C-callable concrete Result<A, B> struct and utility methods
36+
pub fn write_result_block<W: std::io::Write>(w: &mut W, mangled_container: &str, ok_type: &str, err_type: &str, clonable: bool) {
37+
writeln!(w, "#[repr(C)]").unwrap();
38+
writeln!(w, "pub union {}Ptr {{", mangled_container).unwrap();
39+
if ok_type != "()" {
40+
writeln!(w, "\tpub result: *mut {},", ok_type).unwrap();
41+
} else {
42+
writeln!(w, "\t/// Note that this value is always NULL, as there are no contents in the OK variant").unwrap();
43+
writeln!(w, "\tpub result: *mut std::ffi::c_void,").unwrap();
44+
}
45+
if err_type != "()" {
46+
writeln!(w, "\tpub err: *mut {},", err_type).unwrap();
47+
} else {
48+
writeln!(w, "\t/// Note that this value is always NULL, as there are no contents in the Err variant").unwrap();
49+
writeln!(w, "\tpub err: *mut std::ffi::c_void,").unwrap();
50+
}
51+
writeln!(w, "}}").unwrap();
52+
writeln!(w, "#[repr(C)]").unwrap();
53+
writeln!(w, "pub struct {} {{", mangled_container).unwrap();
54+
writeln!(w, "\tpub contents: {}Ptr,", mangled_container).unwrap();
55+
writeln!(w, "\tpub result_ok: bool,").unwrap();
56+
writeln!(w, "}}").unwrap();
57+
58+
writeln!(w, "#[no_mangle]").unwrap();
59+
if ok_type != "()" {
60+
writeln!(w, "pub extern \"C\" fn {}_ok(o: {}) -> {} {{", mangled_container, ok_type, mangled_container).unwrap();
61+
} else {
62+
writeln!(w, "pub extern \"C\" fn {}_ok() -> {} {{", mangled_container, mangled_container).unwrap();
63+
}
64+
writeln!(w, "\t{} {{", mangled_container).unwrap();
65+
writeln!(w, "\t\tcontents: {}Ptr {{", mangled_container).unwrap();
66+
if ok_type != "()" {
67+
writeln!(w, "\t\t\tresult: Box::into_raw(Box::new(o)),").unwrap();
68+
} else {
69+
writeln!(w, "\t\t\tresult: std::ptr::null_mut(),").unwrap();
70+
}
71+
writeln!(w, "\t\t}},").unwrap();
72+
writeln!(w, "\t\tresult_ok: true,").unwrap();
73+
writeln!(w, "\t}}").unwrap();
74+
writeln!(w, "}}").unwrap();
75+
76+
writeln!(w, "#[no_mangle]").unwrap();
77+
if err_type != "()" {
78+
writeln!(w, "pub extern \"C\" fn {}_err(e: {}) -> {} {{", mangled_container, err_type, mangled_container).unwrap();
79+
} else {
80+
writeln!(w, "pub extern \"C\" fn {}_err() -> {} {{", mangled_container, mangled_container).unwrap();
81+
}
82+
writeln!(w, "\t{} {{", mangled_container).unwrap();
83+
writeln!(w, "\t\tcontents: {}Ptr {{", mangled_container).unwrap();
84+
if err_type != "()" {
85+
writeln!(w, "\t\t\terr: Box::into_raw(Box::new(e)),").unwrap();
86+
} else {
87+
writeln!(w, "\t\t\terr: std::ptr::null_mut(),").unwrap();
88+
}
89+
writeln!(w, "\t\t}},").unwrap();
90+
writeln!(w, "\t\tresult_ok: false,").unwrap();
91+
writeln!(w, "\t}}").unwrap();
92+
writeln!(w, "}}").unwrap();
93+
94+
writeln!(w, "#[no_mangle]").unwrap();
95+
writeln!(w, "pub extern \"C\" fn {}_free(_res: {}) {{ }}", mangled_container, mangled_container).unwrap();
96+
writeln!(w, "impl Drop for {} {{", mangled_container).unwrap();
97+
writeln!(w, "\tfn drop(&mut self) {{").unwrap();
98+
writeln!(w, "\t\tif self.result_ok {{").unwrap();
99+
if ok_type != "()" {
100+
writeln!(w, "\t\t\tif unsafe {{ !(self.contents.result as *mut ()).is_null() }} {{").unwrap();
101+
writeln!(w, "\t\t\t\tlet _ = unsafe {{ Box::from_raw(self.contents.result) }};").unwrap();
102+
writeln!(w, "\t\t\t}}").unwrap();
103+
}
104+
writeln!(w, "\t\t}} else {{").unwrap();
105+
if err_type != "()" {
106+
writeln!(w, "\t\t\tif unsafe {{ !(self.contents.err as *mut ()).is_null() }} {{").unwrap();
107+
writeln!(w, "\t\t\t\tlet _ = unsafe {{ Box::from_raw(self.contents.err) }};").unwrap();
108+
writeln!(w, "\t\t\t}}").unwrap();
109+
}
110+
writeln!(w, "\t\t}}").unwrap();
111+
writeln!(w, "\t}}").unwrap();
112+
writeln!(w, "}}").unwrap();
113+
114+
// TODO: Templates should use () now that they can, too
115+
let templ_ok_type = if ok_type != "()" { ok_type } else { "u8" };
116+
let templ_err_type = if err_type != "()" { err_type } else { "u8" };
117+
118+
writeln!(w, "impl From<crate::c_types::CResultTempl<{}, {}>> for {} {{", templ_ok_type, templ_err_type, mangled_container).unwrap();
119+
writeln!(w, "\tfn from(mut o: crate::c_types::CResultTempl<{}, {}>) -> Self {{", templ_ok_type, templ_err_type).unwrap();
120+
writeln!(w, "\t\tlet contents = if o.result_ok {{").unwrap();
121+
if ok_type != "()" {
122+
writeln!(w, "\t\t\tlet result = unsafe {{ o.contents.result }};").unwrap();
123+
writeln!(w, "\t\t\tunsafe {{ o.contents.result = std::ptr::null_mut() }};").unwrap();
124+
writeln!(w, "\t\t\t{}Ptr {{ result }}", mangled_container).unwrap();
125+
} else {
126+
writeln!(w, "\t\t\tlet _ = unsafe {{ Box::from_raw(o.contents.result) }};").unwrap();
127+
writeln!(w, "\t\t\to.contents.result = std::ptr::null_mut();").unwrap();
128+
writeln!(w, "\t\t\t{}Ptr {{ result: std::ptr::null_mut() }}", mangled_container).unwrap();
129+
}
130+
writeln!(w, "\t\t}} else {{").unwrap();
131+
if err_type != "()" {
132+
writeln!(w, "\t\t\tlet err = unsafe {{ o.contents.err }};").unwrap();
133+
writeln!(w, "\t\t\tunsafe {{ o.contents.err = std::ptr::null_mut(); }}").unwrap();
134+
writeln!(w, "\t\t\t{}Ptr {{ err }}", mangled_container).unwrap();
135+
} else {
136+
writeln!(w, "\t\t\tlet _ = unsafe {{ Box::from_raw(o.contents.err) }};").unwrap();
137+
writeln!(w, "\t\t\to.contents.err = std::ptr::null_mut();").unwrap();
138+
writeln!(w, "\t\t\t{}Ptr {{ err: std::ptr::null_mut() }}", mangled_container).unwrap();
139+
}
140+
writeln!(w, "\t\t}};").unwrap();
141+
writeln!(w, "\t\tSelf {{").unwrap();
142+
writeln!(w, "\t\t\tcontents,").unwrap();
143+
writeln!(w, "\t\t\tresult_ok: o.result_ok,").unwrap();
144+
writeln!(w, "\t\t}}").unwrap();
145+
writeln!(w, "\t}}").unwrap();
146+
writeln!(w, "}}").unwrap();
147+
148+
if clonable {
149+
writeln!(w, "impl Clone for {} {{", mangled_container).unwrap();
150+
writeln!(w, "\tfn clone(&self) -> Self {{").unwrap();
151+
writeln!(w, "\t\tif self.result_ok {{").unwrap();
152+
writeln!(w, "\t\t\tSelf {{ result_ok: true, contents: {}Ptr {{", mangled_container).unwrap();
153+
if ok_type != "()" {
154+
writeln!(w, "\t\t\t\tresult: Box::into_raw(Box::new(<{}>::clone(unsafe {{ &*self.contents.result }})))", ok_type).unwrap();
155+
} else {
156+
writeln!(w, "\t\t\t\tresult: std::ptr::null_mut()").unwrap();
157+
}
158+
writeln!(w, "\t\t\t}} }}").unwrap();
159+
writeln!(w, "\t\t}} else {{").unwrap();
160+
writeln!(w, "\t\t\tSelf {{ result_ok: false, contents: {}Ptr {{", mangled_container).unwrap();
161+
if err_type != "()" {
162+
writeln!(w, "\t\t\t\terr: Box::into_raw(Box::new(<{}>::clone(unsafe {{ &*self.contents.err }})))", err_type).unwrap();
163+
} else {
164+
writeln!(w, "\t\t\t\terr: std::ptr::null_mut()").unwrap();
165+
}
166+
writeln!(w, "\t\t\t}} }}").unwrap();
167+
writeln!(w, "\t\t}}").unwrap();
168+
writeln!(w, "\t}}").unwrap();
169+
writeln!(w, "}}").unwrap();
170+
writeln!(w, "#[no_mangle]").unwrap();
171+
writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{ orig.clone() }}", mangled_container, mangled_container, mangled_container).unwrap();
172+
}
173+
}
174+
175+
/// Writes out a C-callable concrete Vec<A> struct and utility methods
176+
pub fn write_vec_block<W: std::io::Write>(w: &mut W, mangled_container: &str, inner_type: &str, clonable: bool) {
177+
writeln!(w, "#[repr(C)]").unwrap();
178+
writeln!(w, "pub struct {} {{", mangled_container).unwrap();
179+
writeln!(w, "\tpub data: *mut {},", inner_type).unwrap();
180+
writeln!(w, "\tpub datalen: usize").unwrap();
181+
writeln!(w, "}}").unwrap();
182+
183+
writeln!(w, "impl {} {{", mangled_container).unwrap();
184+
writeln!(w, "\t#[allow(unused)] pub(crate) fn into_rust(&mut self) -> Vec<{}> {{", inner_type).unwrap();
185+
writeln!(w, "\t\tif self.datalen == 0 {{ return Vec::new(); }}").unwrap();
186+
writeln!(w, "\t\tlet ret = unsafe {{ Box::from_raw(std::slice::from_raw_parts_mut(self.data, self.datalen)) }}.into();").unwrap();
187+
writeln!(w, "\t\tself.data = std::ptr::null_mut();").unwrap();
188+
writeln!(w, "\t\tself.datalen = 0;").unwrap();
189+
writeln!(w, "\t\tret").unwrap();
190+
writeln!(w, "\t}}").unwrap();
191+
writeln!(w, "\t#[allow(unused)] pub(crate) fn as_slice(&self) -> &[{}] {{", inner_type).unwrap();
192+
writeln!(w, "\t\tunsafe {{ std::slice::from_raw_parts_mut(self.data, self.datalen) }}").unwrap();
193+
writeln!(w, "\t}}").unwrap();
194+
writeln!(w, "}}").unwrap();
195+
196+
writeln!(w, "impl From<Vec<{}>> for {} {{", inner_type, mangled_container).unwrap();
197+
writeln!(w, "\tfn from(v: Vec<{}>) -> Self {{", inner_type).unwrap();
198+
writeln!(w, "\t\tlet datalen = v.len();").unwrap();
199+
writeln!(w, "\t\tlet data = Box::into_raw(v.into_boxed_slice());").unwrap();
200+
writeln!(w, "\t\tSelf {{ datalen, data: unsafe {{ (*data).as_mut_ptr() }} }}").unwrap();
201+
writeln!(w, "\t}}").unwrap();
202+
writeln!(w, "}}").unwrap();
203+
204+
writeln!(w, "#[no_mangle]").unwrap();
205+
writeln!(w, "pub extern \"C\" fn {}_free(_res: {}) {{ }}", mangled_container, mangled_container).unwrap();
206+
writeln!(w, "impl Drop for {} {{", mangled_container).unwrap();
207+
writeln!(w, "\tfn drop(&mut self) {{").unwrap();
208+
writeln!(w, "\t\tif self.datalen == 0 {{ return; }}").unwrap();
209+
writeln!(w, "\t\tunsafe {{ Box::from_raw(std::slice::from_raw_parts_mut(self.data, self.datalen)) }};").unwrap();
210+
writeln!(w, "\t}}").unwrap();
211+
writeln!(w, "}}").unwrap();
212+
if clonable {
213+
writeln!(w, "impl Clone for {} {{", mangled_container).unwrap();
214+
writeln!(w, "\tfn clone(&self) -> Self {{").unwrap();
215+
writeln!(w, "\t\tlet mut res = Vec::new();").unwrap();
216+
writeln!(w, "\t\tif self.datalen == 0 {{ return Self::from(res); }}").unwrap();
217+
writeln!(w, "\t\tres.extend_from_slice(unsafe {{ std::slice::from_raw_parts_mut(self.data, self.datalen) }});").unwrap();
218+
writeln!(w, "\t\tSelf::from(res)").unwrap();
219+
writeln!(w, "\t}}").unwrap();
220+
writeln!(w, "}}").unwrap();
221+
}
222+
}
223+
224+
/// Writes out a C-callable concrete (A, B, ...) struct and utility methods
225+
pub fn write_tuple_block<W: std::io::Write>(w: &mut W, mangled_container: &str, types: &[String], clonable: bool) {
226+
writeln!(w, "#[repr(C)]").unwrap();
227+
writeln!(w, "pub struct {} {{", mangled_container).unwrap();
228+
for (idx, ty) in types.iter().enumerate() {
229+
writeln!(w, "\tpub {}: {},", ('a' as u8 + idx as u8) as char, ty).unwrap();
230+
}
231+
writeln!(w, "}}").unwrap();
232+
233+
let mut tuple_str = "(".to_owned();
234+
for (idx, ty) in types.iter().enumerate() {
235+
if idx != 0 { tuple_str += ", "; }
236+
tuple_str += ty;
237+
}
238+
tuple_str += ")";
239+
240+
writeln!(w, "impl From<{}> for {} {{", tuple_str, mangled_container).unwrap();
241+
writeln!(w, "\tfn from (tup: {}) -> Self {{", tuple_str).unwrap();
242+
writeln!(w, "\t\tSelf {{").unwrap();
243+
for idx in 0..types.len() {
244+
writeln!(w, "\t\t\t{}: tup.{},", ('a' as u8 + idx as u8) as char, idx).unwrap();
245+
}
246+
writeln!(w, "\t\t}}").unwrap();
247+
writeln!(w, "\t}}").unwrap();
248+
writeln!(w, "}}").unwrap();
249+
writeln!(w, "impl {} {{", mangled_container).unwrap();
250+
writeln!(w, "\t#[allow(unused)] pub(crate) fn to_rust(mut self) -> {} {{", tuple_str).unwrap();
251+
write!(w, "\t\t(").unwrap();
252+
for idx in 0..types.len() {
253+
write!(w, "{}self.{}", if idx != 0 {", "} else {""}, ('a' as u8 + idx as u8) as char).unwrap();
254+
}
255+
writeln!(w, ")").unwrap();
256+
writeln!(w, "\t}}").unwrap();
257+
writeln!(w, "}}").unwrap();
258+
259+
if clonable {
260+
writeln!(w, "impl Clone for {} {{", mangled_container).unwrap();
261+
writeln!(w, "\tfn clone(&self) -> Self {{").unwrap();
262+
writeln!(w, "\t\tSelf {{").unwrap();
263+
for idx in 0..types.len() {
264+
writeln!(w, "\t\t\t{}: self.{}.clone(),", ('a' as u8 + idx as u8) as char, ('a' as u8 + idx as u8) as char).unwrap();
265+
}
266+
writeln!(w, "\t\t}}").unwrap();
267+
writeln!(w, "\t}}").unwrap();
268+
writeln!(w, "}}").unwrap();
269+
writeln!(w, "#[no_mangle]").unwrap();
270+
writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{ orig.clone() }}", mangled_container, mangled_container, mangled_container).unwrap();
271+
}
272+
273+
write!(w, "#[no_mangle]\npub extern \"C\" fn {}_new(", mangled_container).unwrap();
274+
for (idx, gen) in types.iter().enumerate() {
275+
write!(w, "{}{}: ", if idx != 0 { ", " } else { "" }, ('a' as u8 + idx as u8) as char).unwrap();
276+
//if !self.write_c_type_intern(&mut created_container, gen, generics, false, false, false) { return false; }
277+
write!(w, "{}", gen).unwrap();
278+
}
279+
writeln!(w, ") -> {} {{", mangled_container).unwrap();
280+
write!(w, "\t{} {{ ", mangled_container).unwrap();
281+
for idx in 0..types.len() {
282+
write!(w, "{}, ", ('a' as u8 + idx as u8) as char).unwrap();
283+
}
284+
writeln!(w, "}}\n}}\n").unwrap();
285+
286+
writeln!(w, "#[no_mangle]").unwrap();
287+
writeln!(w, "pub extern \"C\" fn {}_free(_res: {}) {{ }}", mangled_container, mangled_container).unwrap();
288+
}
289+
35290
/// Prints the docs from a given attribute list unless its tagged no export
36291
pub fn writeln_docs<W: std::io::Write>(w: &mut W, attrs: &[syn::Attribute], prefix: &str) {
37292
for attr in attrs.iter() {

0 commit comments

Comments
 (0)