Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions res/translators/rust/implementation/functions.rs.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<%#
Creates the SplashKit functions that wrap the sklib FFI calls
%>
<%
@functions.each do |function|
%>
<%= sk_signature_for(function) %> {
<%
# Convert parameters to C types for FFI using existing mappers
function[:parameters].each do |param_name, param_data|
param_var = param_name.to_s.to_snake_case
# Escape 'fn' keyword if needed
param_var = "r##{param_var}" if param_var == 'fn'
if param_data[:is_reference] && !param_data[:is_const]
%>
let mut __skparam__<%= param_name.to_s.to_snake_case %> = <%= lib_mapper_fn_for param_data %>((*<%= param_var %>).clone());
<%
else
%>
let __skparam__<%= param_name.to_s.to_snake_case %> = <%= lib_mapper_fn_for param_data %>(<%= param_var %>);
<%
end
%>
<%
end
%>
unsafe {
<%
if is_func?(function)
return_type = function[:return][:type]
rust_return_type = sk_type_for(function[:return])
%>
let __skreturn = <%= lib_function_name_for function %>(<%=
lib_argument_list_for(function)
%>);
<%
else
%>
<%= lib_function_name_for function %>(<%=
lib_argument_list_for(function)
%>);
<%
end
%>
<%
function[:parameters].each do |param_name, param_data|
if param_data[:is_reference] && !param_data[:is_const]
%>
*<%= param_name.variable_case %> = <%= sk_mapper_fn_for param_data %>(__skparam__<%= param_name %>);
<%
end
end
%>
<%
if is_func?(function)
%>
<%= sk_mapper_fn_for function[:return] %>(__skreturn)
<%
end
%>
}
}
<%
end # functions.each
%>
8 changes: 7 additions & 1 deletion res/translators/rust/implementation/mappers.rs.erb
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
<%= read_template 'implementation/mappers/bool' %>
<%= read_template 'implementation/mappers/char' %>
<%= read_template 'implementation/mappers/direct' %>
<%= read_template 'implementation/mappers/direct' %>
<%= read_template 'implementation/mappers/enum' %>
<%= read_template 'implementation/mappers/struct' %>
<%= read_template 'implementation/mappers/vector' %>
<%= read_template 'implementation/mappers/string' %>
<%= read_template 'implementation/mappers/function_pointer' %>
<%= read_template 'implementation/mappers/typealias_pointer' %>
19 changes: 7 additions & 12 deletions res/translators/rust/implementation/mappers/bool.rs.erb
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
<%#
Mappers from `bool` <-> `i32`
%>
fn __skadapter__to_sklib_bool(v: bool) -> i32
{
if v {
return -1;
} else {
return 0;
}
}

fn __skadapter__to_bool(v: i32) -> bool
{
return v != 0;
#[inline]
pub(crate) fn __skadapter__to_sklib_bool(v: bool) -> i32 {
if v { 1 } else { 0 }
}
#[inline]
pub(crate) fn __skadapter__to_bool(v: i32) -> bool {
v != 0
}
20 changes: 6 additions & 14 deletions res/translators/rust/implementation/mappers/char.rs.erb
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
fn __skadapter__to_sklib_char(v: char) -> u8 {
return v as u8;
#[inline]
pub(crate) fn __skadapter__to_sklib_char(v: char) -> i8 {
return v as i8;
}

fn __skadapter__to_char(v: u8) -> char
#[inline]
pub(crate) fn __skadapter__to_char(v: i8) -> char
{
return v as char;
}
fn __skadapter__to_sklib_unsigned_char(v: char) -> u8
{
return v as u8;
}

fn __skadapter__to_unsigned_char(v: u8) -> char
{
return v as char;
return v as u8 as char;
}
19 changes: 9 additions & 10 deletions res/translators/rust/implementation/mappers/direct.rs.erb
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
<%#
Direct type mappers have no change between the C- and rust-types and
Direct type mappers have no change between the C and Rust types and
can therefore directly translate one to the other by just returning the
value
%>
<%
direct_types.each do |c_type, rs_type|
direct_types.each do |c_type, rust_type|
c_type = c_type.tr("\s", "_")
%>
fn __skadapter__to_sklib_<%= c_type %>(v: <%= rs_type %>) -> <%= rs_type %>
{
return v;
#[inline]
pub(crate) fn __skadapter__to_sklib_<%= c_type %>(v: <%= rust_type %>) -> <%= rust_type %> {
v
}

fn __skadapter__to_<%= c_type %>(v: <%= rs_type %>) -> <%= rs_type %>
{
return v;
#[inline]
pub(crate) fn __skadapter__to_<%= c_type %>(v: <%= rust_type %>) -> <%= rust_type %> {
v
}
<%
end
%>
%>
32 changes: 32 additions & 0 deletions res/translators/rust/implementation/mappers/enum.rs.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<%#
Enum mapper from Rust enum <-> C int
%>
<% @enums.each do |enum| %>
<%
# Track seen numbers to only use first instance
seen_numbers = {}
# Counter for non-numbered enums
counter = 0
%>
pub(crate) fn __skadapter__to_<%= enum[:name] %>(v: i32) -> <%= enum[:name].to_pascal_case %> {
match v {
<% enum[:constants].each do |name, data| %>
<% if data[:number] %>
<% if !seen_numbers[data[:number]] %>
<% seen_numbers[data[:number]] = true %>
<%= data[:number] %> => <%= enum[:name].to_pascal_case %>::<%= name.to_s.to_pascal_case %>,
<% end %>
<% else %>
<%= counter %> => <%= enum[:name].to_pascal_case %>::<%= name.to_s.to_pascal_case %>,
<% counter += 1 %>
<% end %>
<% end %>
_ => panic!("Invalid <%= enum[:name].to_pascal_case %> value: {}", v)
}
}
#[inline]
pub(crate) fn __skadapter__to_sklib_<%= enum[:name] %>(v: <%= enum[:name].to_pascal_case %>) -> i32 {
v as i32
}

<% end # enums.each %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<%#
Function pointer translations
%>
<%
@function_pointers.each do |fp|
sk_fp_type = fp[:name].type_case
return_type = if is_func?(fp)
lib_type_for(fp[:return])
else
"()"
end
%>
#[inline]
pub(crate) fn __skadapter__to_sklib_<%= fp[:name] %>(callback: <%= sk_fp_type %>) -> __sklib_<%= fp[:name].to_snake_case %> {
thread_local! {
static CALLBACK: RefCell<Option<<%= sk_fp_type %>>> = RefCell::new(None);
}

CALLBACK.with(|cell| {
*cell.borrow_mut() = Some(callback);
});

extern "C" fn wrapper(
<%
fp[:parameters].each do |param_name, param_data|
%>
<%= param_name.to_s.to_snake_case %>: <%= lib_type_for(param_data) %>,
<%
end
%>
) -> <%= return_type %> {
CALLBACK.with(|cell| {
if let Some(cb) = &*cell.borrow() {
cb(
<%
fp[:parameters].each_with_index do |(param_name, param_data), index|
comma = index < fp[:parameters].length - 1 ? "," : ""
if void_pointer?(param_data)
%>
<%= param_name.to_s.to_snake_case %><%= comma %>
<%
else
%>
__skadapter__to_<%= param_data[:type] %>(<%= param_name.to_s.to_snake_case %>)<%= comma %>
<%
end
%>
<%
end
%>
)
}
})
}
wrapper
}
<%
end
%>
50 changes: 50 additions & 0 deletions res/translators/rust/implementation/mappers/string.rs.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#[repr(C)]
#[derive(Copy, Clone)]
pub struct __sklib_string {
pub str: *mut c_char,
pub size: c_int,
pub ptr: __sklib_ptr,
}
impl __sklib_string {
pub fn new() -> Self {
Self {
str: null_mut(),
size: 0,
ptr: null_mut(),
}
}
}
pub(crate) fn __skadapter__to_sklib_string<S: AsRef<str>>(s: S) -> __sklib_string {
let s = s.as_ref();
let c_string = CString::new(s).expect("Failed to create CString");
let ptr = c_string.into_raw();
let size = s.len() as c_int;

__sklib_string {
str: ptr,
size,
ptr: null_mut(),
}
}

pub(crate) fn __skadapter__to_string(v: __sklib_string) -> String {
unsafe {
let result = if v.str.is_null() {
String::new()
} else {
CStr::from_ptr(v.str)
.to_string_lossy()
.into_owned()
};

if !v.str.is_null() {
let _ = CString::from_raw(v.str);
}

result
}
}

pub(crate) fn __skadapter__free__sklib_string(_s: __sklib_string) {
// The actual freeing is handled by the C library
}
30 changes: 30 additions & 0 deletions res/translators/rust/implementation/mappers/struct.rs.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<% @structs.each do |struct| %>
pub(crate) fn __skadapter__to_sklib_<%= struct[:name] %>(v: <%= struct[:name].type_case %>) -> __sklib_<%= struct[:name] %> {
let mut result = __sklib_<%= struct[:name] %>::new();
<% struct[:fields].each do |field_name, field_data|
field_name = field_name
if field_data[:is_array]
array_size_as_one_dimensional(field_data).times do |i| %>
result.<%= field_name %>[<%= i %>] = <%= lib_mapper_fn_for field_data %>(v.<%= field_name %><%= array_mapper_index_for(field_data, i) %>);
<% end
else %>
result.<%= field_name %> = <%= lib_mapper_fn_for field_data %>(v.<%= field_name %>);
<% end
end %>
result
}
pub(crate) fn __skadapter__to_<%= struct[:name] %>(v: __sklib_<%= struct[:name] %>) -> <%= struct[:name].type_case %> {
let mut result = <%= struct[:name].type_case %>::new();
<% struct[:fields].each do |field_name, field_data|
field_name = field_name.to_s.to_snake_case
if field_data[:is_array]
array_size_as_one_dimensional(field_data).times do |i| %>
result.<%= field_name %><%= array_mapper_index_for(field_data, i) %> = <%= sk_mapper_fn_for field_data %>(v.<%= field_name %>[<%= i %>]);
<% end
else %>
result.<%= field_name %> = <%= sk_mapper_fn_for field_data %>(v.<%= field_name %>);
<% end
end %>
result
}
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<%#
Typealias pointer mappers map:
__sklib_ptr to RustType
RustType to __sklib_ptr
%>
#[inline]
pub(crate) fn __skadapter__to_sklib_ptr(v: __sklib_ptr) -> __sklib_ptr {
v
}

#[inline]
pub(crate) fn __skadapter__to_ptr(v: __sklib_ptr) -> __sklib_ptr {
v
}
<%
@typealiases.pluck(:name).each do |typealias|
%>
#[inline]
pub(crate) fn __skadapter__to_<%= typealias %>(v: __sklib_ptr) -> <%= typealias.type_case %> {
<%= typealias.type_case %> { ptr: v }
}
#[inline]
pub(crate) fn __skadapter__to_sklib_<%= typealias %>(v: <%= typealias.type_case %>) -> __sklib_ptr {
v.ptr
}
<%
end # typealiases.each
%>
Loading