This commit is contained in:
2025-06-22 15:11:37 +10:00
parent 5be3f2970c
commit 0667f79ff5
14 changed files with 508 additions and 319 deletions

View File

@@ -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)
)
}
}