mirror of
https://github.com/lune-org/lune.git
synced 2025-04-10 21:40:54 +01:00
Implement luavalue conversion (#243)
This commit is contained in:
parent
6d0db930f6
commit
48d2db4950
14 changed files with 293 additions and 99 deletions
|
@ -39,7 +39,7 @@ impl CArr {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_lua_userdata<'lua>(
|
pub fn new_from_lua_userdata<'lua>(
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
luatype: &LuaAnyUserData<'lua>,
|
luatype: &LuaAnyUserData<'lua>,
|
||||||
length: usize,
|
length: usize,
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl CFn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_lua_table(lua: &Lua, args: LuaTable, ret: LuaAnyUserData) -> LuaResult<Self> {
|
pub fn new_from_lua_table(lua: &Lua, args: LuaTable, ret: LuaAnyUserData) -> LuaResult<Self> {
|
||||||
let args = type_list_from_table(lua, &args)?;
|
let args = type_list_from_table(lua, &args)?;
|
||||||
let ret = type_from_userdata(lua, &ret)?;
|
let ret = type_from_userdata(lua, &ret)?;
|
||||||
Ok(Self::new(args, ret))
|
Ok(Self::new(args, ret))
|
||||||
|
|
|
@ -60,7 +60,7 @@ impl LuaUserData for CPtr {
|
||||||
Ok(pointer)
|
Ok(pointer)
|
||||||
});
|
});
|
||||||
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {
|
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {
|
||||||
let carr = CArr::from_lua_userdata(lua, &this, length)?;
|
let carr = CArr::new_from_lua_userdata(lua, &this, length)?;
|
||||||
Ok(carr)
|
Ok(carr)
|
||||||
});
|
});
|
||||||
methods.add_meta_function(LuaMetaMethod::ToString, |lua, this: LuaAnyUserData| {
|
methods.add_meta_function(LuaMetaMethod::ToString, |lua, this: LuaAnyUserData| {
|
||||||
|
|
|
@ -57,7 +57,7 @@ impl CStruct {
|
||||||
|
|
||||||
// Create new CStruct UserData with LuaTable.
|
// Create new CStruct UserData with LuaTable.
|
||||||
// Lock and hold table for .inner ref
|
// Lock and hold table for .inner ref
|
||||||
pub fn from_lua_table<'lua>(
|
pub fn new_from_lua_table<'lua>(
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
table: LuaTable<'lua>,
|
table: LuaTable<'lua>,
|
||||||
) -> LuaResult<LuaAnyUserData<'lua>> {
|
) -> LuaResult<LuaAnyUserData<'lua>> {
|
||||||
|
@ -135,7 +135,7 @@ impl LuaUserData for CStruct {
|
||||||
Ok(pointer)
|
Ok(pointer)
|
||||||
});
|
});
|
||||||
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {
|
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {
|
||||||
let carr = CArr::from_lua_userdata(lua, &this, length)?;
|
let carr = CArr::new_from_lua_userdata(lua, &this, length)?;
|
||||||
Ok(carr)
|
Ok(carr)
|
||||||
});
|
});
|
||||||
methods.add_meta_function(LuaMetaMethod::ToString, |lua, this: LuaAnyUserData| {
|
methods.add_meta_function(LuaMetaMethod::ToString, |lua, this: LuaAnyUserData| {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![allow(clippy::cargo_common_metadata)]
|
#![allow(clippy::cargo_common_metadata)]
|
||||||
|
|
||||||
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
|
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
|
||||||
use num::cast::{AsPrimitive, NumCast};
|
use num::cast::AsPrimitive;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use libffi::middle::Type;
|
use libffi::middle::Type;
|
||||||
|
@ -24,13 +24,18 @@ pub struct CType<T: ?Sized> {
|
||||||
_phantom: PhantomData<T>,
|
_phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static CType, for borrow, is operation
|
// We can't get a CType<T> through mlua, something like
|
||||||
|
// .is::<CType<dyn Any>> will fail.
|
||||||
|
// So we need data that has a static type.
|
||||||
|
// each CType<T> userdata instance stores an instance of CTypeStatic.
|
||||||
|
#[allow(unused)]
|
||||||
pub struct CTypeStatic {
|
pub struct CTypeStatic {
|
||||||
pub libffi_type: Type,
|
pub libffi_type: Type,
|
||||||
pub size: usize,
|
pub size: usize,
|
||||||
pub name: Option<&'static str>,
|
pub name: Option<&'static str>,
|
||||||
pub signedness: bool,
|
pub signedness: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CTypeStatic {
|
impl CTypeStatic {
|
||||||
fn new<T>(ctype: &CType<T>) -> Self {
|
fn new<T>(ctype: &CType<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -45,8 +50,8 @@ impl LuaUserData for CTypeStatic {}
|
||||||
|
|
||||||
impl<T> CType<T>
|
impl<T> CType<T>
|
||||||
where
|
where
|
||||||
Self: CTypeConvert,
|
|
||||||
T: 'static,
|
T: 'static,
|
||||||
|
Self: CTypeConvert + CTypeCast,
|
||||||
{
|
{
|
||||||
pub fn new_with_libffi_type<'lua>(
|
pub fn new_with_libffi_type<'lua>(
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
|
@ -73,25 +78,12 @@ where
|
||||||
Ok(userdata)
|
Ok(userdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_type(&self) -> &Type {
|
|
||||||
&self.libffi_type
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stringify(&self) -> &str {
|
pub fn stringify(&self) -> &str {
|
||||||
match self.name {
|
match self.name {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => "unnamed",
|
None => "unnamed",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cast_failed_with(&self, into_ctype: &LuaAnyUserData) -> LuaError {
|
|
||||||
let config = ValueFormatConfig::new();
|
|
||||||
LuaError::external(format!(
|
|
||||||
"Cannot cast <CType({})> to {}",
|
|
||||||
self.stringify(),
|
|
||||||
pretty_format_value(&LuaValue::UserData(into_ctype.to_owned()), &config)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle C data, provide type conversion between luavalue and c-type
|
// Handle C data, provide type conversion between luavalue and c-type
|
||||||
|
@ -127,12 +119,9 @@ pub trait CTypeConvert {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CTypeNumCast<T>
|
pub trait CTypeCast {
|
||||||
where
|
|
||||||
T: NumCast,
|
|
||||||
{
|
|
||||||
// Cast T as U
|
// Cast T as U
|
||||||
fn cast_userdata<U>(from: &LuaAnyUserData, into: &LuaAnyUserData) -> LuaResult<()>
|
fn cast_num<T, U>(&self, from: &LuaAnyUserData, into: &LuaAnyUserData) -> LuaResult<()>
|
||||||
where
|
where
|
||||||
T: AsPrimitive<U>,
|
T: AsPrimitive<U>,
|
||||||
U: 'static + Copy,
|
U: 'static + Copy,
|
||||||
|
@ -147,7 +136,8 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cast_userdata_if_type_match<U>(
|
fn try_cast_num<T, U>(
|
||||||
|
&self,
|
||||||
ctype: &LuaAnyUserData,
|
ctype: &LuaAnyUserData,
|
||||||
from: &LuaAnyUserData,
|
from: &LuaAnyUserData,
|
||||||
into: &LuaAnyUserData,
|
into: &LuaAnyUserData,
|
||||||
|
@ -157,18 +147,42 @@ where
|
||||||
U: 'static + Copy,
|
U: 'static + Copy,
|
||||||
{
|
{
|
||||||
if ctype.is::<CType<U>>() {
|
if ctype.is::<CType<U>>() {
|
||||||
Self::cast_userdata(from, into)?;
|
Self::cast_num::<T, U>(self, from, into)?;
|
||||||
Ok(Some(()))
|
Ok(Some(()))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn cast(
|
||||||
|
&self,
|
||||||
|
from_ctype: &LuaAnyUserData,
|
||||||
|
into_ctype: &LuaAnyUserData,
|
||||||
|
from: &LuaAnyUserData,
|
||||||
|
into: &LuaAnyUserData,
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
Err(Self::cast_failed_with(self, from_ctype, into_ctype))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cast_failed_with(
|
||||||
|
&self,
|
||||||
|
from_ctype: &LuaAnyUserData,
|
||||||
|
into_ctype: &LuaAnyUserData,
|
||||||
|
) -> LuaError {
|
||||||
|
let config = ValueFormatConfig::new();
|
||||||
|
LuaError::external(format!(
|
||||||
|
"Cannot cast {} to {}",
|
||||||
|
pretty_format_value(&LuaValue::UserData(from_ctype.to_owned()), &config),
|
||||||
|
pretty_format_value(&LuaValue::UserData(into_ctype.to_owned()), &config),
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> LuaUserData for CType<T>
|
impl<T> LuaUserData for CType<T>
|
||||||
where
|
where
|
||||||
Self: CTypeConvert,
|
|
||||||
T: 'static,
|
T: 'static,
|
||||||
|
Self: CTypeConvert + CTypeCast,
|
||||||
{
|
{
|
||||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("size", |_, this| Ok(this.size));
|
fields.add_field_method_get("size", |_, this| Ok(this.size));
|
||||||
|
@ -193,8 +207,22 @@ where
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {
|
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {
|
||||||
CArr::from_lua_userdata(lua, &this, length)
|
CArr::new_from_lua_userdata(lua, &this, length)
|
||||||
});
|
});
|
||||||
|
methods.add_function(
|
||||||
|
"cast",
|
||||||
|
|_,
|
||||||
|
(from_type, into_type, from, into): (
|
||||||
|
LuaAnyUserData,
|
||||||
|
LuaAnyUserData,
|
||||||
|
LuaAnyUserData,
|
||||||
|
LuaAnyUserData,
|
||||||
|
)| {
|
||||||
|
from_type
|
||||||
|
.borrow::<Self>()?
|
||||||
|
.cast(&from_type, &into_type, &from, &into)
|
||||||
|
},
|
||||||
|
);
|
||||||
methods.add_meta_method(LuaMetaMethod::ToString, |lua, this, ()| {
|
methods.add_meta_method(LuaMetaMethod::ToString, |lua, this, ()| {
|
||||||
lua.create_string(this.stringify())
|
lua.create_string(this.stringify())
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,21 +2,23 @@ use core::ffi::*;
|
||||||
|
|
||||||
use libffi::middle::Type;
|
use libffi::middle::Type;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
use super::super::c_type::{CType, CTypeConvert, CTypeNumCast};
|
use super::super::c_type::{CType, CTypeCast, CTypeConvert};
|
||||||
use crate::ffi::ffi_platform::CHAR_IS_SIGNED;
|
use crate::ffi::ffi_platform::CHAR_IS_SIGNED;
|
||||||
|
|
||||||
impl CTypeConvert for CType<c_char> {
|
impl CTypeConvert for CType<c_char> {
|
||||||
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
||||||
let value = match value {
|
let value: c_char = match value {
|
||||||
LuaValue::Integer(t) => t,
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t.as_bytes().first().map_or(0, u8::to_owned).as_(),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(LuaError::external(format!(
|
return Err(LuaError::external(format!(
|
||||||
"Integer expected, got {}",
|
"Argument LuaValue expected a Integer or String, got {}",
|
||||||
value.type_name()
|
value.type_name()
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
} as c_char;
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
*(ptr.cast::<c_char>()) = value;
|
*(ptr.cast::<c_char>()) = value;
|
||||||
}
|
}
|
||||||
|
@ -28,29 +30,24 @@ impl CTypeConvert for CType<c_char> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CType<c_char> {
|
impl CTypeCast for CType<c_char> {
|
||||||
fn cast(
|
fn cast(
|
||||||
&self,
|
&self,
|
||||||
|
from_ctype: &LuaAnyUserData,
|
||||||
into_ctype: &LuaAnyUserData,
|
into_ctype: &LuaAnyUserData,
|
||||||
from: &LuaAnyUserData,
|
from: &LuaAnyUserData,
|
||||||
into: &LuaAnyUserData,
|
into: &LuaAnyUserData,
|
||||||
) -> LuaResult<()> {
|
) -> LuaResult<()> {
|
||||||
Self::cast_userdata_if_type_match::<c_float>(into_ctype, from, into)?
|
self.try_cast_num::<c_char, c_float>(into_ctype, from, into)?
|
||||||
.or(Self::cast_userdata_if_type_match::<c_double>(
|
.or(self.try_cast_num::<c_char, c_double>(into_ctype, from, into)?)
|
||||||
into_ctype, from, into,
|
.or(self.try_cast_num::<c_char, c_char>(into_ctype, from, into)?)
|
||||||
)?)
|
.or(self.try_cast_num::<c_char, c_long>(into_ctype, from, into)?)
|
||||||
.or(Self::cast_userdata_if_type_match::<c_char>(
|
.or(self.try_cast_num::<c_char, c_int>(into_ctype, from, into)?)
|
||||||
into_ctype, from, into,
|
.or(self.try_cast_num::<c_char, c_longlong>(into_ctype, from, into)?)
|
||||||
)?)
|
.ok_or_else(|| self.cast_failed_with(from_ctype, into_ctype))
|
||||||
.or(Self::cast_userdata_if_type_match::<c_long>(
|
|
||||||
into_ctype, from, into,
|
|
||||||
)?)
|
|
||||||
.ok_or_else(|| self.cast_failed_with(into_ctype))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CTypeNumCast<c_char> for CType<c_char> {}
|
|
||||||
|
|
||||||
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
Ok((
|
Ok((
|
||||||
"char",
|
"char",
|
||||||
|
|
59
crates/lune-std-ffi/src/c/types/c_double.rs
Normal file
59
crates/lune-std-ffi/src/c/types/c_double.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use core::ffi::*;
|
||||||
|
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeCast, CTypeConvert};
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
impl CTypeConvert for CType<c_double> {
|
||||||
|
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
||||||
|
let value: c_double = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<c_double>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<c_double>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue> {
|
||||||
|
let value = unsafe { (*ptr.cast::<c_double>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CTypeCast for CType<c_double> {
|
||||||
|
fn cast(
|
||||||
|
&self,
|
||||||
|
from_ctype: &LuaAnyUserData,
|
||||||
|
into_ctype: &LuaAnyUserData,
|
||||||
|
from: &LuaAnyUserData,
|
||||||
|
into: &LuaAnyUserData,
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
self.try_cast_num::<c_double, c_float>(into_ctype, from, into)?
|
||||||
|
.or(self.try_cast_num::<c_double, c_double>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_double, c_char>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_double, c_long>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_double, c_int>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_double, c_longlong>(into_ctype, from, into)?)
|
||||||
|
.ok_or_else(|| self.cast_failed_with(from_ctype, into_ctype))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"double",
|
||||||
|
CType::<c_double>::new_with_libffi_type(lua, Type::f64(), true, Some("double"))?,
|
||||||
|
))
|
||||||
|
}
|
59
crates/lune-std-ffi/src/c/types/c_float.rs
Normal file
59
crates/lune-std-ffi/src/c/types/c_float.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use core::ffi::*;
|
||||||
|
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeCast, CTypeConvert};
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
impl CTypeConvert for CType<c_float> {
|
||||||
|
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
||||||
|
let value: c_float = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<c_float>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<c_float>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue> {
|
||||||
|
let value = unsafe { (*ptr.cast::<c_float>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CTypeCast for CType<c_float> {
|
||||||
|
fn cast(
|
||||||
|
&self,
|
||||||
|
from_ctype: &LuaAnyUserData,
|
||||||
|
into_ctype: &LuaAnyUserData,
|
||||||
|
from: &LuaAnyUserData,
|
||||||
|
into: &LuaAnyUserData,
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
self.try_cast_num::<c_float, c_float>(into_ctype, from, into)?
|
||||||
|
.or(self.try_cast_num::<c_float, c_double>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_float, c_char>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_float, c_long>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_float, c_int>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_float, c_longlong>(into_ctype, from, into)?)
|
||||||
|
.ok_or_else(|| self.cast_failed_with(from_ctype, into_ctype))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"float",
|
||||||
|
CType::<c_float>::new_with_libffi_type(lua, Type::f32(), true, Some("float"))?,
|
||||||
|
))
|
||||||
|
}
|
|
@ -2,20 +2,26 @@ use core::ffi::*;
|
||||||
|
|
||||||
use libffi::middle::Type;
|
use libffi::middle::Type;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
use super::super::c_type::{CType, CTypeConvert, CTypeNumCast};
|
use super::super::c_type::{CType, CTypeCast, CTypeConvert};
|
||||||
|
|
||||||
impl CTypeConvert for CType<c_int> {
|
impl CTypeConvert for CType<c_int> {
|
||||||
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
||||||
let value = match value {
|
let value: c_int = match value {
|
||||||
LuaValue::Integer(t) => t,
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<i32>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(LuaError::external(format!(
|
return Err(LuaError::external(format!(
|
||||||
"Integer expected, got {}",
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
value.type_name()
|
value.type_name()
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
} as c_int;
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
*(ptr.cast::<c_int>()) = value;
|
*(ptr.cast::<c_int>()) = value;
|
||||||
}
|
}
|
||||||
|
@ -27,29 +33,26 @@ impl CTypeConvert for CType<c_int> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CType<c_int> {
|
impl CType<c_int> {}
|
||||||
|
|
||||||
|
impl CTypeCast for CType<c_int> {
|
||||||
fn cast(
|
fn cast(
|
||||||
&self,
|
&self,
|
||||||
|
from_ctype: &LuaAnyUserData,
|
||||||
into_ctype: &LuaAnyUserData,
|
into_ctype: &LuaAnyUserData,
|
||||||
from: &LuaAnyUserData,
|
from: &LuaAnyUserData,
|
||||||
into: &LuaAnyUserData,
|
into: &LuaAnyUserData,
|
||||||
) -> LuaResult<()> {
|
) -> LuaResult<()> {
|
||||||
Self::cast_userdata_if_type_match::<c_float>(into_ctype, from, into)?
|
self.try_cast_num::<c_int, c_float>(into_ctype, from, into)?
|
||||||
.or(Self::cast_userdata_if_type_match::<c_double>(
|
.or(self.try_cast_num::<c_int, c_double>(into_ctype, from, into)?)
|
||||||
into_ctype, from, into,
|
.or(self.try_cast_num::<c_int, c_char>(into_ctype, from, into)?)
|
||||||
)?)
|
.or(self.try_cast_num::<c_int, c_long>(into_ctype, from, into)?)
|
||||||
.or(Self::cast_userdata_if_type_match::<c_char>(
|
.or(self.try_cast_num::<c_int, c_int>(into_ctype, from, into)?)
|
||||||
into_ctype, from, into,
|
.or(self.try_cast_num::<c_int, c_longlong>(into_ctype, from, into)?)
|
||||||
)?)
|
.ok_or_else(|| self.cast_failed_with(from_ctype, into_ctype))
|
||||||
.or(Self::cast_userdata_if_type_match::<c_long>(
|
|
||||||
into_ctype, from, into,
|
|
||||||
)?)
|
|
||||||
.ok_or_else(|| self.cast_failed_with(into_ctype))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CTypeNumCast<c_int> for CType<c_int> {}
|
|
||||||
|
|
||||||
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
Ok((
|
Ok((
|
||||||
"int",
|
"int",
|
||||||
|
|
59
crates/lune-std-ffi/src/c/types/c_long.rs
Normal file
59
crates/lune-std-ffi/src/c/types/c_long.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use core::ffi::*;
|
||||||
|
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeCast, CTypeConvert};
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
impl CTypeConvert for CType<c_long> {
|
||||||
|
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
||||||
|
let value: c_long = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<c_long>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<c_long>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue> {
|
||||||
|
let value = unsafe { (*ptr.cast::<c_long>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CTypeCast for CType<c_long> {
|
||||||
|
fn cast(
|
||||||
|
&self,
|
||||||
|
from_ctype: &LuaAnyUserData,
|
||||||
|
into_ctype: &LuaAnyUserData,
|
||||||
|
from: &LuaAnyUserData,
|
||||||
|
into: &LuaAnyUserData,
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
self.try_cast_num::<c_long, c_float>(into_ctype, from, into)?
|
||||||
|
.or(self.try_cast_num::<c_long, c_double>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_long, c_char>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_long, c_long>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_long, c_int>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<c_long, c_longlong>(into_ctype, from, into)?)
|
||||||
|
.ok_or_else(|| self.cast_failed_with(from_ctype, into_ctype))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"long",
|
||||||
|
CType::<c_long>::new_with_libffi_type(lua, Type::c_long(), true, Some("long"))?,
|
||||||
|
))
|
||||||
|
}
|
|
@ -1,9 +1,18 @@
|
||||||
mod c_char;
|
mod c_char;
|
||||||
|
mod c_double;
|
||||||
|
mod c_float;
|
||||||
mod c_int;
|
mod c_int;
|
||||||
|
mod c_long;
|
||||||
|
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
// export all default c-types
|
// export all default c-types
|
||||||
pub fn create_all_types(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>> {
|
pub fn create_all_types(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>> {
|
||||||
Ok(vec![c_int::get_export(lua)?, c_char::get_export(lua)?])
|
Ok(vec![
|
||||||
|
c_char::get_export(lua)?,
|
||||||
|
c_double::get_export(lua)?,
|
||||||
|
c_float::get_export(lua)?,
|
||||||
|
c_int::get_export(lua)?,
|
||||||
|
c_long::get_export(lua)?,
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,18 +39,9 @@ impl FfiBox {
|
||||||
|
|
||||||
// Todo: if too big, print as another format
|
// Todo: if too big, print as another format
|
||||||
pub fn stringify(&self) -> String {
|
pub fn stringify(&self) -> String {
|
||||||
let mut buff: String = String::with_capacity(self.size() * 10 - 2);
|
let mut buff: String = String::with_capacity(self.size() * 2);
|
||||||
for (pos, value) in self.0.iter().enumerate() {
|
for value in &self.0 {
|
||||||
for i in 0..8 {
|
buff.push_str(format!("{:x}", value.to_be()).as_str());
|
||||||
if (value & (1 << i)) == 0 {
|
|
||||||
buff.push('0');
|
|
||||||
} else {
|
|
||||||
buff.push('1');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if pos < self.size() - 1 {
|
|
||||||
buff.push_str(", ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
buff
|
buff
|
||||||
}
|
}
|
||||||
|
@ -78,7 +69,7 @@ impl FfiBox {
|
||||||
bounds = bounds.offset(t);
|
bounds = bounds.offset(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lua should not be able to deref a box that refers to a box managed by Lua.
|
// Lua should not be able to deref a box.
|
||||||
// To deref a box space is to allow lua to read any space,
|
// To deref a box space is to allow lua to read any space,
|
||||||
// which has security issues and is ultimately dangerous.
|
// which has security issues and is ultimately dangerous.
|
||||||
// Therefore, box:ref():deref() is not allowed.
|
// Therefore, box:ref():deref() is not allowed.
|
||||||
|
|
|
@ -1,22 +1,11 @@
|
||||||
use core::ffi::c_char;
|
use core::ffi::c_char;
|
||||||
use std::env::consts;
|
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
pub const CHAR_IS_SIGNED: bool = c_char::MIN as u8 != u8::MIN;
|
pub const CHAR_IS_SIGNED: bool = c_char::MIN as u8 != u8::MIN;
|
||||||
pub const IS_LITTLE_ENDIAN: bool = cfg!(target_endian = "little");
|
|
||||||
|
|
||||||
pub fn get_platform_value() -> Vec<(&'static str, &'static str)> {
|
pub fn get_platform_value() -> Vec<(&'static str, &'static str)> {
|
||||||
vec![
|
vec![(
|
||||||
// https://doc.rust-lang.org/std/env/consts/constant.ARCH.html
|
"char_variant",
|
||||||
("arch", consts::ARCH),
|
if CHAR_IS_SIGNED { "schar" } else { "uchar" },
|
||||||
// https://doc.rust-lang.org/std/env/consts/constant.OS.html
|
)]
|
||||||
("os", consts::OS),
|
|
||||||
// https://doc.rust-lang.org/std/env/consts/constant.FAMILY.html
|
|
||||||
("family", consts::FAMILY),
|
|
||||||
("endian", if IS_LITTLE_ENDIAN { "little" } else { "big" }),
|
|
||||||
(
|
|
||||||
"char_variant",
|
|
||||||
if CHAR_IS_SIGNED { "schar" } else { "uchar" },
|
|
||||||
),
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,11 +30,11 @@ pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||||
Ok(lib)
|
Ok(lib)
|
||||||
})?
|
})?
|
||||||
.with_function("struct", |lua, types: LuaTable| {
|
.with_function("struct", |lua, types: LuaTable| {
|
||||||
let cstruct = CStruct::from_lua_table(lua, types)?;
|
let cstruct = CStruct::new_from_lua_table(lua, types)?;
|
||||||
Ok(cstruct)
|
Ok(cstruct)
|
||||||
})?
|
})?
|
||||||
.with_function("fn", |lua, (args, ret): (LuaTable, LuaAnyUserData)| {
|
.with_function("fn", |lua, (args, ret): (LuaTable, LuaAnyUserData)| {
|
||||||
let cfn = CFn::from_lua_table(lua, args, ret)?;
|
let cfn = CFn::new_from_lua_table(lua, args, ret)?;
|
||||||
Ok(cfn)
|
Ok(cfn)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue