use std::{mem, ops::Deref}; use mlua::{prelude::LuaUserDataMethods, UserData}; use tokio::sync::SemaphorePermit; pub type PermitRef<'lua, F> = mlua::UserDataRef<'lua, Permit>; pub struct Permit { inner: Option>, destruct: Option, } impl Deref for Permit { type Target = Option>; fn deref(&self) -> &Self::Target { &self.inner } } impl Permit { pub fn new(inner: SemaphorePermit<'static>, f: F) -> Self { Self { inner: Some(inner), destruct: Some(f) } } fn dropping(&mut self) { if let Some(f) = self.destruct.take() { f(); } if let Some(p) = self.inner.take() { mem::drop(p); } } } impl Drop for Permit { fn drop(&mut self) { self.dropping(); } } impl UserData for Permit { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { methods.add_method_mut("drop", |_, me, ()| Ok(me.dropping())); } }