Hide all async features under the flag

This commit is contained in:
Alex Orlenko 2020-04-17 19:15:08 +01:00
parent 563e6a2e9a
commit 46a879a33d
6 changed files with 70 additions and 33 deletions

View file

@ -31,14 +31,14 @@ lua52 = []
lua51 = []
luajit = []
vendored = ["lua-src", "luajit-src"]
async = ["futures-task", "futures-util"]
async = ["futures-core", "futures-task", "futures-util"]
[dependencies]
bstr = { version = "0.2", features = ["std"], default_features = false }
futures-core = { version = "0.3.4" }
num-traits = { version = "0.2.11" }
futures-core = { version = "0.3.4", optional = true }
futures-task = { version = "0.3.4", optional = true }
futures-util = { version = "0.3.4", optional = true }
num-traits = { version = "0.2.11" }
[build-dependencies]
cc = { version = "1.0" }

View file

@ -67,9 +67,12 @@ pub use crate::multi::Variadic;
pub use crate::stdlib::StdLib;
pub use crate::string::String;
pub use crate::table::{Table, TablePairs, TableSequence};
pub use crate::thread::{AsyncThread, Thread, ThreadStatus};
pub use crate::thread::{Thread, ThreadStatus};
pub use crate::types::{Integer, LightUserData, Number, RegistryKey};
pub use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataMethods};
pub use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
#[cfg(feature = "async")]
pub use crate::thread::AsyncThread;
pub mod prelude;

View file

@ -5,19 +5,8 @@ use std::ffi::CString;
use std::marker::PhantomData;
use std::os::raw::{c_char, c_int};
use std::rc::Rc;
use std::task::Waker;
use std::{mem, ptr, str};
use futures_core::future::LocalBoxFuture;
#[cfg(feature = "async")]
use {
futures_task::noop_waker,
futures_util::future::{self, FutureExt, TryFutureExt},
std::future::Future,
std::task::{Context, Poll},
};
use crate::error::{Error, Result};
use crate::ffi;
use crate::function::Function;
@ -25,7 +14,7 @@ use crate::stdlib::StdLib;
use crate::string::String;
use crate::table::Table;
use crate::thread::Thread;
use crate::types::{AsyncCallback, Callback, Integer, LightUserData, LuaRef, Number, RegistryKey};
use crate::types::{Callback, Integer, LightUserData, LuaRef, Number, RegistryKey};
use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataMethods};
use crate::util::{
assert_stack, callback_error, check_stack, get_gc_userdata, get_main_state,
@ -35,6 +24,18 @@ use crate::util::{
};
use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
#[cfg(feature = "async")]
use {
crate::types::AsyncCallback,
futures_core::future::LocalBoxFuture,
futures_task::noop_waker,
futures_util::future::{self, FutureExt, TryFutureExt},
std::{
future::Future,
task::{Context, Poll, Waker},
},
};
/// Top level Lua struct which holds the Lua state itself.
pub struct Lua {
pub(crate) state: *mut ffi::lua_State,
@ -56,7 +57,9 @@ struct ExtraData {
ref_free: Vec<c_int>,
}
#[cfg(feature = "async")]
pub(crate) struct AsyncPollPending;
#[cfg(feature = "async")]
pub(crate) static WAKER_REGISTRY_KEY: u8 = 0;
impl Drop for Lua {
@ -137,11 +140,14 @@ impl Lua {
// to prevent them from being garbage collected.
init_gc_metatable_for::<Callback>(state, None);
init_gc_metatable_for::<AsyncCallback>(state, None);
init_gc_metatable_for::<LocalBoxFuture<Result<MultiValue>>>(state, None);
init_gc_metatable_for::<AsyncPollPending>(state, None);
init_gc_metatable_for::<Waker>(state, None);
init_gc_metatable_for::<Lua>(state, None);
#[cfg(feature = "async")]
{
init_gc_metatable_for::<AsyncCallback>(state, None);
init_gc_metatable_for::<LocalBoxFuture<Result<MultiValue>>>(state, None);
init_gc_metatable_for::<AsyncPollPending>(state, None);
init_gc_metatable_for::<Waker>(state, None);
}
// Create ref stack thread and place it in the registry to prevent it from being garbage
// collected.
@ -1024,7 +1030,12 @@ impl Lua {
})?;
}
if methods.methods.is_empty() && methods.async_methods.is_empty() {
#[cfg(feature = "async")]
let no_methods = methods.methods.is_empty() && methods.async_methods.is_empty();
#[cfg(not(feature = "async"))]
let no_methods = methods.methods.is_empty();
if no_methods {
init_userdata_metatable::<RefCell<T>>(self.state, -1, None)?;
} else {
protect_lua_closure(self.state, 0, 1, |state| {
@ -1488,6 +1499,7 @@ unsafe fn ref_stack_pop(extra: &mut ExtraData) -> c_int {
struct StaticUserDataMethods<'lua, T: 'static + UserData> {
methods: Vec<(Vec<u8>, Callback<'lua, 'static>)>,
#[cfg(feature = "async")]
async_methods: Vec<(Vec<u8>, AsyncCallback<'lua, 'static>)>,
meta_methods: Vec<(MetaMethod, Callback<'lua, 'static>)>,
_type: PhantomData<T>,
@ -1497,6 +1509,7 @@ impl<'lua, T: 'static + UserData> Default for StaticUserDataMethods<'lua, T> {
fn default() -> StaticUserDataMethods<'lua, T> {
StaticUserDataMethods {
methods: Vec::new(),
#[cfg(feature = "async")]
async_methods: Vec::new(),
meta_methods: Vec::new(),
_type: PhantomData,

View file

@ -1,20 +1,30 @@
use std::cell::RefCell;
use std::marker::PhantomData;
use std::os::raw::{c_int, c_void};
use std::pin::Pin;
use std::task::{Context, Poll, Waker};
use std::os::raw::c_int;
use futures_core::{future::Future, stream::Stream};
use crate::error::{Error, ExternalError, Result};
use crate::error::{Error, Result};
use crate::ffi;
use crate::lua::{AsyncPollPending, Lua, WAKER_REGISTRY_KEY};
use crate::types::LuaRef;
use crate::util::{
assert_stack, check_stack, error_traceback, get_gc_userdata, pop_error, protect_lua_closure,
push_gc_userdata, StackGuard,
assert_stack, check_stack, error_traceback, pop_error, protect_lua_closure, StackGuard,
};
use crate::value::{FromLuaMulti, MultiValue, ToLuaMulti};
#[cfg(feature = "async")]
use {
crate::{
error::ExternalError,
lua::{AsyncPollPending, Lua, WAKER_REGISTRY_KEY},
util::{get_gc_userdata, push_gc_userdata},
value::Value,
},
futures_core::{future::Future, stream::Stream},
std::{
cell::RefCell,
marker::PhantomData,
os::raw::c_void,
pin::Pin,
task::{Context, Poll, Waker},
},
};
use crate::value::{FromLuaMulti, MultiValue, ToLuaMulti, Value};
/// Status of a Lua thread (or coroutine).
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
@ -36,6 +46,7 @@ pub enum ThreadStatus {
pub struct Thread<'lua>(pub(crate) LuaRef<'lua>);
/// Thread (coroutine) representation as an async Future or Stream.
#[cfg(feature = "async")]
#[derive(Debug)]
pub struct AsyncThread<'lua, R> {
thread: Thread<'lua>,
@ -201,6 +212,7 @@ impl<'lua> Thread<'lua> {
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "async")]
pub fn into_async<A, R>(self, args: A) -> AsyncThread<'lua, R>
where
A: ToLuaMulti<'lua>,
@ -221,6 +233,7 @@ impl<'lua> PartialEq for Thread<'lua> {
}
}
#[cfg(feature = "async")]
impl<'lua, R> Stream for AsyncThread<'lua, R>
where
R: FromLuaMulti<'lua>,
@ -251,6 +264,7 @@ where
}
}
#[cfg(feature = "async")]
impl<'lua, R> Future for AsyncThread<'lua, R>
where
R: FromLuaMulti<'lua>,
@ -286,6 +300,7 @@ where
}
}
#[cfg(feature = "async")]
fn is_poll_pending(lua: &Lua, val: &MultiValue) -> bool {
if val.len() != 1 {
return false;
@ -309,8 +324,10 @@ fn is_poll_pending(lua: &Lua, val: &MultiValue) -> bool {
false
}
#[cfg(feature = "async")]
struct WakerGuard(*mut ffi::lua_State);
#[cfg(feature = "async")]
impl WakerGuard {
pub fn new(state: *mut ffi::lua_State, waker: Waker) -> Result<WakerGuard> {
unsafe {
@ -326,6 +343,7 @@ impl WakerGuard {
}
}
#[cfg(feature = "async")]
impl Drop for WakerGuard {
fn drop(&mut self) {
unsafe {

View file

@ -3,6 +3,7 @@ use std::os::raw::{c_int, c_void};
use std::rc::Rc;
use std::{fmt, mem, ptr};
#[cfg(feature = "async")]
use futures_core::future::LocalBoxFuture;
use crate::error::Result;
@ -23,6 +24,7 @@ pub struct LightUserData(pub *mut c_void);
pub(crate) type Callback<'lua, 'a> =
Box<dyn Fn(&'lua Lua, MultiValue<'lua>) -> Result<MultiValue<'lua>> + 'a>;
#[cfg(feature = "async")]
pub(crate) type AsyncCallback<'lua, 'a> =
Box<dyn Fn(&'lua Lua, MultiValue<'lua>) -> LocalBoxFuture<'lua, Result<MultiValue<'lua>>> + 'a>;

View file

@ -100,6 +100,7 @@ fn test_thread() -> Result<()> {
Ok(())
}
#[cfg(feature = "async")]
#[tokio::test]
async fn test_thread_stream() -> Result<()> {
let lua = Lua::new();