Something went wrong. Try again.
Personal fork of prime agent. Mirror of: https://mnemosyne.sigilzero.dev/sigilzero/prime-agent
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348use std::os::raw::c_int;use std::string::String as StdString;use std::sync::Arc;
use crate::error::{Error, Result};use crate::multi::MultiValue;use crate::private::Sealed;use crate::state::{Lua, RawLua, WeakLua};use crate::types::MaybeSend;use crate::util::{check_stack, parse_lookup_path, short_type_name};use crate::value::Value;
#[cfg(feature = "async")]use {crate::function::AsyncCallFuture, std::future::Future};
/// Trait for types convertible to [`Value`].pub trait IntoLua: Sized { /// Performs the conversion. fn into_lua(self, lua: &Lua) -> Result<Value>;
/// Pushes the value into the Lua stack. /// /// # Safety /// This method does not check Lua stack space. #[doc(hidden)] #[inline] unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> { lua.push_value(&self.into_lua(lua.lua())?) }}
/// Trait for types convertible from [`Value`].pub trait FromLua: Sized { /// Performs the conversion. fn from_lua(value: Value, lua: &Lua) -> Result<Self>;
/// Performs the conversion for an argument (eg. function argument). /// /// `i` is the argument index (position), /// `to` is a function name that received the argument. #[doc(hidden)] #[inline] fn from_lua_arg(arg: Value, i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> { Self::from_lua(arg, lua).map_err(|err| Error::BadArgument { to: to.map(|s| s.to_string()), pos: i, name: None, cause: Arc::new(err), }) }
/// Performs the conversion for a value in the Lua stack at index `idx`. #[doc(hidden)] #[inline] unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> { Self::from_lua(lua.stack_value(idx, None), lua.lua()) }
/// Same as `from_lua_arg` but for a value in the Lua stack at index `idx`. #[doc(hidden)] #[inline] unsafe fn from_stack_arg(idx: c_int, i: usize, to: Option<&str>, lua: &RawLua) -> Result<Self> { Self::from_stack(idx, lua).map_err(|err| Error::BadArgument { to: to.map(|s| s.to_string()), pos: i, name: None, cause: Arc::new(err), }) }}
/// Trait for types convertible to any number of Lua values.////// This is a generalization of [`IntoLua`], allowing any number of resulting Lua values instead of/// just one. Any type that implements [`IntoLua`] will automatically implement this trait.pub trait IntoLuaMulti: Sized { /// Performs the conversion. fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue>;
/// Pushes the values into the Lua stack. /// /// Returns number of pushed values. #[doc(hidden)] #[inline] unsafe fn push_into_stack_multi(self, lua: &RawLua) -> Result<c_int> { let values = self.into_lua_multi(lua.lua())?; let len: c_int = values.len().try_into().unwrap(); unsafe { check_stack(lua.state(), len + 1)?; for val in &values { lua.push_value(val)?; } } Ok(len) }}
/// Trait for types that can be created from an arbitrary number of Lua values.////// This is a generalization of [`FromLua`], allowing an arbitrary number of Lua values to/// participate in the conversion. Any type that implements [`FromLua`] will automatically/// implement this trait.pub trait FromLuaMulti: Sized { /// Performs the conversion. /// /// In case `values` contains more values than needed to perform the conversion, the excess /// values should be ignored. This reflects the semantics of Lua when calling a function or /// assigning values. Similarly, if not enough values are given, conversions should assume that /// any missing values are nil. fn from_lua_multi(values: MultiValue, lua: &Lua) -> Result<Self>;
/// Performs the conversion for a list of arguments. /// /// `i` is an index (position) of the first argument, /// `to` is a function name that received the arguments. #[doc(hidden)] #[inline] fn from_lua_args(args: MultiValue, i: usize, to: Option<&str>, lua: &Lua) -> Result<Self> { let _ = (i, to); Self::from_lua_multi(args, lua) }
/// Performs the conversion for a number of values in the Lua stack. #[doc(hidden)] #[inline] unsafe fn from_stack_multi(nvals: c_int, lua: &RawLua) -> Result<Self> { let mut values = MultiValue::with_capacity(nvals as usize); for idx in 0..nvals { values.push_back(lua.stack_value(-nvals + idx, None)); } Self::from_lua_multi(values, lua.lua()) }
/// Same as `from_lua_args` but for a number of values in the Lua stack. #[doc(hidden)] #[inline] unsafe fn from_stack_args(nargs: c_int, i: usize, to: Option<&str>, lua: &RawLua) -> Result<Self> { let _ = (i, to); Self::from_stack_multi(nargs, lua) }}
/// A trait for types that can be used as Lua objects (usually table and userdata).pub trait ObjectLike: Sealed { /// Gets the value associated to `key` from the object, assuming it has `__index` metamethod. fn get<V: FromLua>(&self, key: impl IntoLua) -> Result<V>;
/// Sets the value associated to `key` in the object, assuming it has `__newindex` metamethod. fn set(&self, key: impl IntoLua, value: impl IntoLua) -> Result<()>;
/// Calls the object as a function assuming it has `__call` metamethod. /// /// The metamethod is called with the object as its first argument, followed by the passed /// arguments. fn call<R>(&self, args: impl IntoLuaMulti) -> Result<R> where R: FromLuaMulti;
/// Asynchronously calls the object as a function assuming it has `__call` metamethod. /// /// The metamethod is called with the object as its first argument, followed by the passed /// arguments. #[cfg(feature = "async")] #[cfg_attr(docsrs, doc(cfg(feature = "async")))] fn call_async<R>(&self, args: impl IntoLuaMulti) -> AsyncCallFuture<R> where R: FromLuaMulti;
/// Gets the function associated to key `name` from the object and calls it, /// passing the object itself along with `args` as function arguments. fn call_method<R>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R> where R: FromLuaMulti;
/// Gets the function associated to key `name` from the object and asynchronously calls it, /// passing the object itself along with `args` as function arguments. /// /// This might invoke the `__index` metamethod. #[cfg(feature = "async")] #[cfg_attr(docsrs, doc(cfg(feature = "async")))] fn call_async_method<R>(&self, name: &str, args: impl IntoLuaMulti) -> AsyncCallFuture<R> where R: FromLuaMulti;
/// Gets the function associated to key `name` from the object and calls it, /// passing `args` as function arguments. /// /// This might invoke the `__index` metamethod. fn call_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R> where R: FromLuaMulti;
/// Gets the function associated to key `name` from the object and asynchronously calls it, /// passing `args` as function arguments. /// /// This might invoke the `__index` metamethod. #[cfg(feature = "async")] #[cfg_attr(docsrs, doc(cfg(feature = "async")))] fn call_async_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> AsyncCallFuture<R> where R: FromLuaMulti;
/// Look up a value by a path of keys. /// /// The syntax is similar to accessing nested tables in Lua, with additional support for /// `?` operator to perform safe navigation. /// /// For example, the path `a[1].c` is equivalent to `table.a[1].c` in Lua. /// With `?` operator, `a[1]?.c` is equivalent to `table.a[1] and table.a[1].c or nil` in Lua. /// /// Bracket notation rules: /// - `[123]` - integer keys /// - `["string key"]` or `['string key']` - string keys (must be quoted) /// - String keys support escape sequences: `\"`, `\'`, `\\` fn get_path<V: FromLua>(&self, path: &str) -> Result<V> { let mut current = self.to_value(); for (key, safe_nil) in parse_lookup_path(path)? { current = match current { Value::Table(table) => table.get::<Value>(key), Value::UserData(ud) => ud.get::<Value>(key), _ => { let type_name = current.type_name(); let err = format!("attempt to index a {type_name} value with key '{key}'"); Err(Error::runtime(err)) } }?; if safe_nil && (current == Value::Nil || current == Value::NULL) { break; } }
let lua = self.weak_lua().lock(); V::from_lua(current, lua.lua()) }
/// Converts the object to a string in a human-readable format. /// /// This might invoke the `__tostring` metamethod. fn to_string(&self) -> Result<StdString>;
/// Converts the object to a Lua value. fn to_value(&self) -> Value;
/// Gets a reference to the associated Lua state. #[doc(hidden)] fn weak_lua(&self) -> &WeakLua;}
/// A trait for types that can be used as Lua functions.pub trait LuaNativeFn<A: FromLuaMulti> { type Output: IntoLuaMulti;
fn call(&self, args: A) -> Self::Output;}
/// A trait for types with mutable state that can be used as Lua functions.pub trait LuaNativeFnMut<A: FromLuaMulti> { type Output: IntoLuaMulti;
fn call(&mut self, args: A) -> Self::Output;}
/// A trait for types that returns a future and can be used as Lua functions.#[cfg(feature = "async")]pub trait LuaNativeAsyncFn<A: FromLuaMulti> { type Output: IntoLuaMulti;
fn call(&self, args: A) -> impl Future<Output = Self::Output> + MaybeSend + 'static;}
macro_rules! impl_lua_native_fn { ($($A:ident),*) => { impl<FN, $($A,)* R> LuaNativeFn<($($A,)*)> for FN where FN: Fn($($A,)*) -> R + MaybeSend + 'static, ($($A,)*): FromLuaMulti, R: IntoLuaMulti, { type Output = R;
#[allow(non_snake_case)] fn call(&self, args: ($($A,)*)) -> Self::Output { let ($($A,)*) = args; self($($A,)*) } }
impl<FN, $($A,)* R> LuaNativeFnMut<($($A,)*)> for FN where FN: FnMut($($A,)*) -> R + MaybeSend + 'static, ($($A,)*): FromLuaMulti, R: IntoLuaMulti, { type Output = R;
#[allow(non_snake_case)] fn call(&mut self, args: ($($A,)*)) -> Self::Output { let ($($A,)*) = args; self($($A,)*) } }
#[cfg(feature = "async")] impl<FN, $($A,)* Fut, R> LuaNativeAsyncFn<($($A,)*)> for FN where FN: Fn($($A,)*) -> Fut + MaybeSend + 'static, ($($A,)*): FromLuaMulti, Fut: Future<Output = R> + MaybeSend + 'static, R: IntoLuaMulti, { type Output = R;
#[allow(non_snake_case)] fn call(&self, args: ($($A,)*)) -> impl Future<Output = Self::Output> + MaybeSend + 'static { let ($($A,)*) = args; self($($A,)*) } } };}
impl_lua_native_fn!();impl_lua_native_fn!(A);impl_lua_native_fn!(A, B);impl_lua_native_fn!(A, B, C);impl_lua_native_fn!(A, B, C, D);impl_lua_native_fn!(A, B, C, D, E);impl_lua_native_fn!(A, B, C, D, E, F);impl_lua_native_fn!(A, B, C, D, E, F, G);impl_lua_native_fn!(A, B, C, D, E, F, G, H);impl_lua_native_fn!(A, B, C, D, E, F, G, H, I);impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J);impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K);impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L);impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M);impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);impl_lua_native_fn!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
pub(crate) trait ShortTypeName { #[inline(always)] fn type_name() -> StdString { short_type_name::<Self>() }}
impl<T> ShortTypeName for T {}