implement (De)Serialize for LuaFn, LuaFnMut and LuaFnOnce

This commit is contained in:
noib3 2022-06-03 13:19:16 +02:00
parent 13bd0552f7
commit 9f7a95aa6c
No known key found for this signature in database
GPG key ID: 7AF92216C504A017
11 changed files with 105 additions and 26 deletions

View file

@ -0,0 +1 @@

View file

@ -22,12 +22,18 @@ use crate::lua::{LuaFnOnce, LUA_INTERNAL_CALL};
use crate::object::{FromObject, ToObject};
use crate::Result;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct Buffer(BufHandle);
impl fmt::Debug for Buffer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("Buffer").field(&self.0).finish()
}
}
impl fmt::Display for Buffer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Buffer({})", self.0)
write!(f, "{self:?}")
}
}

View file

@ -0,0 +1 @@

View file

@ -0,0 +1 @@

View file

@ -0,0 +1 @@

View file

@ -0,0 +1 @@

View file

@ -0,0 +1 @@

View file

@ -0,0 +1 @@

View file

@ -1,17 +1,17 @@
use std::marker::PhantomData;
use std::result::Result as StdResult;
use std::{fmt, mem, ptr};
use libc::c_int;
use nvim_types::{object, LuaRef};
use serde::{Deserialize, Serialize};
use serde::{de, ser};
use super::ffi::*;
use crate::Result;
macro_rules! define {
($name:ident) => {
// TODO: custom impls for serialize & deserialize
#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct $name<A, R>(
pub(crate) LuaRef,
PhantomData<A>,
@ -66,6 +66,78 @@ from_fn_for_object!(LuaFn);
from_fn_for_object!(LuaFnMut);
from_fn_for_object!(LuaFnOnce);
macro_rules! deserialize {
($name:ident, $visitor:ident) => {
impl<'de, A, R> de::Deserialize<'de> for $name<A, R>
where
A: super::LuaPoppable,
R: super::LuaPushable,
{
fn deserialize<D>(
deserializer: D,
) -> StdResult<$name<A, R>, D::Error>
where
D: de::Deserializer<'de>,
{
struct $visitor<A, R>(PhantomData<A>, PhantomData<R>);
impl<'de, A, R> de::Visitor<'de> for $visitor<A, R>
where
A: super::LuaPoppable,
R: super::LuaPushable,
{
type Value = $name<A, R>;
fn expecting(
&self,
f: &mut fmt::Formatter,
) -> fmt::Result {
f.write_str("an f32 representing a Lua reference")
}
fn visit_f32<E>(
self,
value: f32,
) -> StdResult<Self::Value, E>
where
E: de::Error,
{
Ok($name(value as i32, PhantomData, PhantomData))
}
}
deserializer
.deserialize_f32($visitor(PhantomData, PhantomData))
}
}
};
}
deserialize!(LuaFn, LuaFnVisitor);
deserialize!(LuaFnMut, LuaFnMutVisitor);
deserialize!(LuaFnOnce, LuaFnOnceVisitor);
macro_rules! serialize {
($name:ident) => {
impl<A, R> ser::Serialize for $name<A, R>
where
A: super::LuaPoppable,
R: super::LuaPushable,
{
fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_f32(self.0 as f32)
}
}
};
}
serialize!(LuaFn);
serialize!(LuaFnMut);
serialize!(LuaFnOnce);
macro_rules! create_ref {
($lstate:ident, $fun:ident, $cb:ident) => {
super::with_state(move |$lstate| unsafe {
@ -154,18 +226,6 @@ where
}
}
macro_rules! unref {
() => {
/// Removes the stored reference from the Lua registry.
#[allow(dead_code)]
pub(crate) fn unref(self) {
super::with_state(move |lstate| unsafe {
luaL_unref(lstate, LUA_REGISTRYINDEX, self.0);
})
}
};
}
macro_rules! call_body {
($self:ident, $args:ident) => {
todo!()
@ -177,8 +237,6 @@ where
A: super::LuaPoppable,
R: super::LuaPushable,
{
unref!();
pub fn _call(&self, _args: A) -> crate::Result<R> {
call_body!(self, _args)
}
@ -189,8 +247,6 @@ where
A: super::LuaPoppable,
R: super::LuaPushable,
{
unref!();
pub fn _call(&mut self, _args: A) -> crate::Result<R> {
call_body!(self, _args)
}
@ -201,9 +257,14 @@ where
A: super::LuaPoppable,
R: super::LuaPushable,
{
unref!();
pub fn _call(self, _args: A) -> crate::Result<R> {
call_body!(self, _args)
}
/// Removes the stored reference from the Lua registry.
pub(crate) fn unref(self) {
super::with_state(move |lstate| unsafe {
luaL_unref(lstate, LUA_REGISTRYINDEX, self.0);
})
}
}

View file

@ -42,8 +42,14 @@ impl<'de> de::Deserializer<'de> for Deserializer {
},
kObjectTypeArray => self.deserialize_seq(visitor),
kObjectTypeDictionary => self.deserialize_map(visitor),
// TODO: map Lua functions to i32 for now.
kObjectTypeLuaRef => visitor.visit_i32(unsafe { data.luaref }),
// We map the ref representing the index of the lua function in the
// Lua registry to `f32`. It's definitely a hack, but Neovim rarely
// returns a float so it should a good place to store it to avoid
// collisions.
kObjectTypeLuaRef => {
visitor.visit_f32(unsafe { data.luaref } as f32)
},
}
}

View file

@ -4,7 +4,6 @@ group_imports = "StdExternalCrate"
imports_layout = "HorizontalVertical"
match_block_trailing_comma = true
max_width = 79
reorder_impl_items = true
unstable_features = true
use_field_init_shorthand = true
use_small_heuristics = "Max"