diff --git a/src/conversion.rs b/src/conversion.rs index 949ab36..2925535 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -9,7 +9,8 @@ use table::Table; use userdata::{AnyUserData, UserData}; use function::Function; use thread::Thread; -use lua::{FromLua, Lua, Nil, ToLua, Value}; +use value::{FromLua, Nil, ToLua, Value}; +use lua::Lua; impl<'lua> ToLua<'lua> for Value<'lua> { fn to_lua(self, _: &'lua Lua) -> Result> { diff --git a/src/function.rs b/src/function.rs index f087f20..9f4f617 100644 --- a/src/function.rs +++ b/src/function.rs @@ -4,7 +4,7 @@ use ffi; use error::*; use util::*; use types::LuaRef; -use lua::{FromLuaMulti, MultiValue, ToLuaMulti}; +use value::{FromLuaMulti, MultiValue, ToLuaMulti}; /// Handle to an internal Lua function. #[derive(Clone, Debug)] diff --git a/src/lib.rs b/src/lib.rs index cc54e27..4f69581 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,7 @@ mod error; #[macro_use] mod macros; mod util; +mod value; mod types; mod lua; mod conversion; @@ -68,6 +69,7 @@ pub use table::{Table, TablePairs, TableSequence}; pub use function::Function; pub use thread::{Thread, ThreadStatus}; pub use userdata::{AnyUserData, MetaMethod, UserData, UserDataMethods}; -pub use lua::{FromLua, FromLuaMulti, Lua, MultiValue, Nil, ToLua, ToLuaMulti, Value}; +pub use value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value}; +pub use lua::Lua; pub mod prelude; diff --git a/src/lua.rs b/src/lua.rs index 35e4af7..e14e113 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -1,11 +1,10 @@ use std::{ptr, str}; -use std::ops::{Deref, DerefMut}; -use std::iter::FromIterator; +use std::ops::DerefMut; use std::cell::RefCell; use std::ffi::CString; use std::any::TypeId; use std::marker::PhantomData; -use std::collections::{HashMap, VecDeque}; +use std::collections::HashMap; use std::os::raw::{c_char, c_int, c_void}; use std::process; @@ -14,6 +13,7 @@ use libc; use ffi; use error::*; use util::*; +use value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value}; use types::{Callback, Integer, LightUserData, LuaRef, Number}; use string::String; use table::Table; @@ -21,131 +21,6 @@ use function::Function; use thread::Thread; use userdata::{AnyUserData, MetaMethod, UserData, UserDataMethods}; -/// A dynamically typed Lua value. -#[derive(Debug, Clone)] -pub enum Value<'lua> { - /// The Lua value `nil`. - Nil, - /// The Lua value `true` or `false`. - Boolean(bool), - /// A "light userdata" object, equivalent to a raw pointer. - LightUserData(LightUserData), - /// An integer number. - /// - /// Any Lua number convertible to a `Integer` will be represented as this variant. - Integer(Integer), - /// A floating point number. - Number(Number), - /// An interned string, managed by Lua. - /// - /// Unlike Rust strings, Lua strings may not be valid UTF-8. - String(String<'lua>), - /// Reference to a Lua table. - Table(Table<'lua>), - /// Reference to a Lua function (or closure). - Function(Function<'lua>), - /// Reference to a Lua thread (or coroutine). - Thread(Thread<'lua>), - /// Reference to a userdata object that holds a custom type which implements `UserData`. - /// Special builtin userdata types will be represented as other `Value` variants. - UserData(AnyUserData<'lua>), - /// `Error` is a special builtin userdata type. When received from Lua it is implicitly cloned. - Error(Error), -} -pub use self::Value::Nil; - -impl<'lua> Value<'lua> { - pub(crate) fn type_name(&self) -> &'static str { - match *self { - Value::Nil => "nil", - Value::Boolean(_) => "boolean", - Value::LightUserData(_) => "light userdata", - Value::Integer(_) => "integer", - Value::Number(_) => "number", - Value::String(_) => "string", - Value::Table(_) => "table", - Value::Function(_) => "function", - Value::Thread(_) => "thread", - Value::UserData(_) | Value::Error(_) => "userdata", - } - } -} - -/// Trait for types convertible to `Value`. -pub trait ToLua<'lua> { - /// Performs the conversion. - fn to_lua(self, lua: &'lua Lua) -> Result>; -} - -/// Trait for types convertible from `Value`. -pub trait FromLua<'lua>: Sized { - /// Performs the conversion. - fn from_lua(lua_value: Value<'lua>, lua: &'lua Lua) -> Result; -} - -/// Multiple Lua values used for both argument passing and also for multiple return values. -#[derive(Debug, Clone)] -pub struct MultiValue<'lua>(VecDeque>); - -impl<'lua> MultiValue<'lua> { - /// Creates an empty `MultiValue` containing no values. - pub fn new() -> MultiValue<'lua> { - MultiValue(VecDeque::new()) - } -} - -impl<'lua> FromIterator> for MultiValue<'lua> { - fn from_iter>>(iter: I) -> Self { - MultiValue(VecDeque::from_iter(iter)) - } -} - -impl<'lua> IntoIterator for MultiValue<'lua> { - type Item = Value<'lua>; - type IntoIter = > as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl<'lua> Deref for MultiValue<'lua> { - type Target = VecDeque>; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl<'lua> DerefMut for MultiValue<'lua> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -/// Trait for types convertible to any number of Lua values. -/// -/// This is a generalization of `ToLua`, allowing any number of resulting Lua values instead of just -/// one. Any type that implements `ToLua` will automatically implement this trait. -pub trait ToLuaMulti<'lua> { - /// Performs the conversion. - fn to_lua_multi(self, lua: &'lua Lua) -> Result>; -} - -/// 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<'lua>: 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: &'lua Lua) -> Result; -} - /// Top level Lua struct which holds the Lua state itself. pub struct Lua { pub(crate) state: *mut ffi::lua_State, diff --git a/src/multi.rs b/src/multi.rs index 63e3682..e0c10e0 100644 --- a/src/multi.rs +++ b/src/multi.rs @@ -3,6 +3,7 @@ use std::iter::FromIterator; use std::result::Result as StdResult; use error::*; +use value::*; use lua::*; /// Result is convertible to `MultiValue` following the common Lua idiom of returning the result diff --git a/src/table.rs b/src/table.rs index f022f9f..679849a 100644 --- a/src/table.rs +++ b/src/table.rs @@ -4,7 +4,7 @@ use ffi; use error::Result; use util::*; use types::{Integer, LuaRef}; -use lua::{FromLua, ToLua}; +use value::{FromLua, ToLua}; /// Handle to an internal Lua table. #[derive(Clone, Debug)] @@ -436,7 +436,8 @@ where mod tests { use super::Table; use error::Result; - use lua::{Lua, Nil, Value}; + use value::{Nil, Value}; + use lua::Lua; #[test] fn test_set_get() { diff --git a/src/thread.rs b/src/thread.rs index d784865..4f31019 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -4,7 +4,7 @@ use ffi; use error::*; use util::*; use types::LuaRef; -use lua::{FromLuaMulti, MultiValue, ToLuaMulti}; +use value::{FromLuaMulti, MultiValue, ToLuaMulti}; /// Status of a Lua thread (or coroutine). #[derive(Debug, Copy, Clone, Eq, PartialEq)] diff --git a/src/types.rs b/src/types.rs index 6d406ad..2a13265 100644 --- a/src/types.rs +++ b/src/types.rs @@ -3,7 +3,8 @@ use std::os::raw::{c_int, c_void}; use ffi; use error::Result; -use lua::{Lua, MultiValue}; +use value::MultiValue; +use lua::Lua; /// Type of Lua integer numbers. pub type Integer = ffi::lua_Integer; diff --git a/src/userdata.rs b/src/userdata.rs index 48955bb..f3bbf12 100644 --- a/src/userdata.rs +++ b/src/userdata.rs @@ -7,7 +7,8 @@ use ffi; use error::*; use util::*; use types::{Callback, LuaRef}; -use lua::{FromLua, FromLuaMulti, Lua, ToLuaMulti}; +use value::{FromLua, FromLuaMulti, ToLuaMulti}; +use lua::Lua; /// Kinds of metamethods that can be overridden. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] diff --git a/src/value.rs b/src/value.rs new file mode 100644 index 0000000..b3b4f2f --- /dev/null +++ b/src/value.rs @@ -0,0 +1,138 @@ +use std::str; +use std::ops::{Deref, DerefMut}; +use std::iter::FromIterator; +use std::collections::VecDeque; + +use error::*; +use types::{Integer, LightUserData, Number}; +use string::String; +use table::Table; +use function::Function; +use thread::Thread; +use userdata::AnyUserData; +use lua::Lua; + +/// A dynamically typed Lua value. +#[derive(Debug, Clone)] +pub enum Value<'lua> { + /// The Lua value `nil`. + Nil, + /// The Lua value `true` or `false`. + Boolean(bool), + /// A "light userdata" object, equivalent to a raw pointer. + LightUserData(LightUserData), + /// An integer number. + /// + /// Any Lua number convertible to a `Integer` will be represented as this variant. + Integer(Integer), + /// A floating point number. + Number(Number), + /// An interned string, managed by Lua. + /// + /// Unlike Rust strings, Lua strings may not be valid UTF-8. + String(String<'lua>), + /// Reference to a Lua table. + Table(Table<'lua>), + /// Reference to a Lua function (or closure). + Function(Function<'lua>), + /// Reference to a Lua thread (or coroutine). + Thread(Thread<'lua>), + /// Reference to a userdata object that holds a custom type which implements `UserData`. + /// Special builtin userdata types will be represented as other `Value` variants. + UserData(AnyUserData<'lua>), + /// `Error` is a special builtin userdata type. When received from Lua it is implicitly cloned. + Error(Error), +} +pub use self::Value::Nil; + +impl<'lua> Value<'lua> { + pub(crate) fn type_name(&self) -> &'static str { + match *self { + Value::Nil => "nil", + Value::Boolean(_) => "boolean", + Value::LightUserData(_) => "light userdata", + Value::Integer(_) => "integer", + Value::Number(_) => "number", + Value::String(_) => "string", + Value::Table(_) => "table", + Value::Function(_) => "function", + Value::Thread(_) => "thread", + Value::UserData(_) | Value::Error(_) => "userdata", + } + } +} + +/// Trait for types convertible to `Value`. +pub trait ToLua<'lua> { + /// Performs the conversion. + fn to_lua(self, lua: &'lua Lua) -> Result>; +} + +/// Trait for types convertible from `Value`. +pub trait FromLua<'lua>: Sized { + /// Performs the conversion. + fn from_lua(lua_value: Value<'lua>, lua: &'lua Lua) -> Result; +} + +/// Multiple Lua values used for both argument passing and also for multiple return values. +#[derive(Debug, Clone)] +pub struct MultiValue<'lua>(VecDeque>); + +impl<'lua> MultiValue<'lua> { + /// Creates an empty `MultiValue` containing no values. + pub fn new() -> MultiValue<'lua> { + MultiValue(VecDeque::new()) + } +} + +impl<'lua> FromIterator> for MultiValue<'lua> { + fn from_iter>>(iter: I) -> Self { + MultiValue(VecDeque::from_iter(iter)) + } +} + +impl<'lua> IntoIterator for MultiValue<'lua> { + type Item = Value<'lua>; + type IntoIter = > as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl<'lua> Deref for MultiValue<'lua> { + type Target = VecDeque>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'lua> DerefMut for MultiValue<'lua> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +/// Trait for types convertible to any number of Lua values. +/// +/// This is a generalization of `ToLua`, allowing any number of resulting Lua values instead of just +/// one. Any type that implements `ToLua` will automatically implement this trait. +pub trait ToLuaMulti<'lua> { + /// Performs the conversion. + fn to_lua_multi(self, lua: &'lua Lua) -> Result>; +} + +/// 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<'lua>: 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: &'lua Lua) -> Result; +}