import os
from datetime import datetime
from itertools import repeat
import parse
################################################################################
def arg_in(a, use_self):
if a.type == 'libfive_tree':
if use_self and a.index == 0:
return 'self'
else:
return '{}: Tree'.format(a.name)
elif a.type == 'tfloat':
return '{}: TreeF32'.format(a.name)
elif a.type == 'tvec2':
return '{}: TreeVec2'.format(a.name)
elif a.type == 'tvec3':
return '{}: TreeVec3'.format(a.name)
elif a.type == 'int':
return '{}: u32'.format(a.name)
elif a.type == 'const char*':
return '{}: &CStr'.format(a.name)
else:
raise RuntimeError("Unknown type %s" % a.type)
def arg_out(a, use_self):
if a.type == 'libfive_tree':
if use_self and a.index == 0:
return 'self.0'
else:
return '{}.0'.format(a.name)
elif a.type == 'tfloat':
return '{}.0'.format(a.name)
elif a.type == 'tvec2':
return 'sys::tvec2 {{ x: {0}.x.0, y: {0}.y.0 }}'.format(a.name)
elif a.type == 'tvec3':
return 'sys::tvec3 {{ x: {0}.x.0, y: {0}.y.0, z: {0}.z.0 }}'.format(a.name)
elif a.type == 'int':
return '{}.try_into().unwrap()'.format(a.name)
elif a.type == 'const char*':
return '{}.as_ptr()'.format(a.name)
else:
raise RuntimeError("Unknown type %s" % a.type)
def format_module_modifier(lib, m):
out = '''
/// # {}
impl Tree {{
'''.format(m.title(), m)
for f in lib[m].shapes:
args_in = ", ".join(map(arg_in, f.args, repeat(True)))
args_out = ", ".join(map(arg_out, f.args, repeat(True)))
out += '''
pub fn {name}({args_in}) -> Self {{
Self(unsafe {{ sys::{raw_name}{u}({args_out}) }})
}}
'''.format(name='moveit' if f.name.endswith('move') else f.name,
raw_name=f.raw_name,
u='',
args_in=args_in,
args_out=args_out)
out += '}'
return out
def format_module_generator(lib, m):
out = '''
/// # {}
impl Tree {{
'''.format(m.title(), m)
for f in lib[m].shapes:
args_in = ", ".join(map(arg_in, f.args, repeat(False)))
args_out = ", ".join(map(arg_out, f.args, repeat(False)))
out += '''
pub fn {name}({args_in}) -> Self {{
Self(unsafe {{ sys::{raw_name}{u}({args_out}) }})
}}
'''.format(name=f.name,
raw_name=f.raw_name,
u='',
args_in=args_in,
args_out=args_out)
out += '}'
return out
################################################################################
def arg_call(a):
if a.type == 'libfive_tree':
return 'libfive::Tree'
elif a.type == 'tfloat':
return 'TreeF32' # same as float
elif a.type == 'tvec2':
return 'TreeVec2'
elif a.type == 'tvec3':
return 'TreeVec3'
elif a.type in ['float', 'int', 'const char*']:
return a.type
else:
raise RuntimeError("Unknown arg type {}".format(a.type))
################################################################################
stdlib = parse.parse_stdlib()
def write_header(f, m):
f.write(
'''//
// Rust API for the libfive standard library’s ‘{}’ module.
//
// DO NOT EDIT BY HAND!
// This file is automatically generated from libfive/stdlib/stdlib.h.
//
// It was last generated on {} by user {}.
//
'''.format(m, datetime.now().strftime("%Y-%m-%d %H:%M:%S"), os.getlogin()))
stdlib = parse.parse_stdlib()
for m in ['csg', 'transforms']:
with open('../bind/rust/libfive/stdlib/%s.rs' % m, 'w') as f:
write_header(f, m)
f.write(format_module_modifier(stdlib, m))
for m in ['shapes', 'generators']:
with open('../bind/rust/libfive/stdlib/%s.rs' % m, 'w') as f:
write_header(f, m)
f.write(format_module_generator(stdlib, m))
f = open('../bind/rust/libfive/stdlib/text.rs', 'w')
f.write(
'''
/// # Text
impl Tree {
pub fn text(txt: impl Into>, pos: TreeVec2) -> Self {
let txt = std::ffi::CString::new(txt).unwrap();
Self(unsafe { sys::text(txt.as_ptr(), sys::tvec2 { x: pos.x.0, y: pos.y.0 }) })
}
}
'''
)