Working
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use crate::{CDef, CDefBuilder, FromFfi, ToFfi, Type, TypeBuilder, display};
|
||||
use crate::{CDef, CDefBuilder, FfiReturnConvention, FromFfi, ToFfi, Type, TypeBuilder, display};
|
||||
use std::{ffi::c_int, fmt::Display, ptr};
|
||||
|
||||
#[repr(C)]
|
||||
@@ -29,34 +29,32 @@ unsafe impl<T: Type> CDef for lua_option<T> {
|
||||
}
|
||||
|
||||
unsafe impl<T: FromFfi> FromFfi for Option<T> {
|
||||
type From = *mut Self::FromValue; // pass by-ref
|
||||
type FromValue = lua_option<T::FromValue>;
|
||||
type From = lua_option<T::From>;
|
||||
type FromArg = *mut Self::From; // pass by-ref
|
||||
|
||||
const ARG_KEEPALIVE: bool = T::ARG_KEEPALIVE;
|
||||
fn require_keepalive() -> bool {
|
||||
T::require_keepalive()
|
||||
}
|
||||
|
||||
fn prelude(arg: &str) -> impl Display {
|
||||
let ct = Self::FromValue::name();
|
||||
let ct = Self::From::name();
|
||||
display!(
|
||||
"if {arg} == nil then {arg} = {ct}(); else {}{arg} = {ct}(1, {arg}); end; ",
|
||||
"if {arg} == nil then {arg} = __cnew(__ctypes.{ct}); else {}{arg} = __cnew(__ctypes.{ct}, 1, {arg}); end; ",
|
||||
T::prelude(arg)
|
||||
)
|
||||
}
|
||||
|
||||
fn convert(from: Self::From) -> Self {
|
||||
debug_assert!(
|
||||
!from.is_null(),
|
||||
"Option<T>::convert() called on a null lua_option<T>"
|
||||
);
|
||||
|
||||
Self::convert_value(unsafe { ptr::replace(from, lua_option::None) })
|
||||
}
|
||||
|
||||
fn convert_value(from: Self::FromValue) -> Self {
|
||||
match from {
|
||||
lua_option::Some(value) => Some(T::convert_value(value)),
|
||||
lua_option::Some(value) => Some(T::convert(value)),
|
||||
lua_option::None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_arg(from: Self::FromArg) -> Self {
|
||||
debug_assert!(!from.is_null());
|
||||
Self::convert(unsafe { ptr::replace(from, lua_option::None) })
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: ToFfi> ToFfi for Option<T> {
|
||||
@@ -69,12 +67,12 @@ unsafe impl<T: ToFfi> ToFfi for Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn postlude(ret: &str) -> impl Display {
|
||||
fn postlude(ret: &str, _conv: FfiReturnConvention) -> impl Display {
|
||||
// if we don't have a value, return nil. otherwise copy out the inner value immediately,
|
||||
// forget the option cdata, then call postlude on the inner value.
|
||||
display!(
|
||||
"if {ret}.__tag == 0 then {ret} = nil; else {ret} = {ret}.__value; {}end; ",
|
||||
T::postlude(ret)
|
||||
T::postlude(ret, FfiReturnConvention::ByValue)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user