Implement IntoFfi for Result
This commit is contained in:
parent
9d5bcc5ef2
commit
1aa9b4aa02
@ -1,4 +1,72 @@
|
|||||||
// pub enum lua_result<T> {
|
use crate::{
|
||||||
// Err(lua_error),
|
__internal::{disp, display},
|
||||||
// Ok(T),
|
Cdef, CdefBuilder, IntoFfi, Type, TypeBuilder, TypeType,
|
||||||
// }
|
string::{DROP_BUFFER_FN, lua_buffer},
|
||||||
|
};
|
||||||
|
use std::{ffi::c_int, fmt::Display};
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub enum lua_result<T> {
|
||||||
|
Err(lua_buffer), // __tag = 0
|
||||||
|
Ok(T), // __tag = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: Type> Type for lua_result<T> {
|
||||||
|
fn name() -> impl Display {
|
||||||
|
display!("result__{}", T::name())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ty() -> TypeType {
|
||||||
|
TypeType::Aggregate
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cdecl(name: impl Display) -> impl Display {
|
||||||
|
display!("struct {} {name}", Self::name())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build(b: &mut TypeBuilder) {
|
||||||
|
b.cdef::<Self>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: Type> Cdef for lua_result<T> {
|
||||||
|
fn build(b: &mut CdefBuilder) {
|
||||||
|
b.field::<c_int>("__tag").inner_union(|b| {
|
||||||
|
(T::ty() != TypeType::Void).then(|| b.field::<T>("__value"));
|
||||||
|
b.field::<lua_buffer>("__err");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: IntoFfi, E: Display> IntoFfi for Result<T, E> {
|
||||||
|
type Into = lua_result<T::Into>;
|
||||||
|
|
||||||
|
fn convert(self) -> Self::Into {
|
||||||
|
match self {
|
||||||
|
Ok(value) => lua_result::Ok(T::convert(value)),
|
||||||
|
Err(err) => lua_result::Err(lua_buffer::new(err.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn postlude(ret: &str) -> impl Display {
|
||||||
|
disp(move |f| {
|
||||||
|
let ct = T::Into::name();
|
||||||
|
write!(f, "if {ret}.__tag ~= 0 then ")?;
|
||||||
|
match T::Into::ty() {
|
||||||
|
TypeType::Void => write!(f, "{ret} = nil; "), // for void results, we don't have a __value
|
||||||
|
TypeType::Primitive => write!(f, "{ret} = {ret}.__value; "),
|
||||||
|
TypeType::Aggregate => write!(f, "{ret} = __new(__ct.{ct}, {ret}.__value); "),
|
||||||
|
}?;
|
||||||
|
write!(f, "{}", T::postlude(ret))?;
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"else \
|
||||||
|
local __{ret}_msg = __intern({ret}.__err.__ptr, {ret}.__err.__len); \
|
||||||
|
__C.{DROP_BUFFER_FN}({ret}.__err); \
|
||||||
|
return error(__{ret}_msg); \
|
||||||
|
end; "
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user